Skip to content

Commit c989c28

Browse files
authored
fix(transformers): Ability to transform any with TypeTransformer (#956)
plus testing fixes. Without this there was no way to transform `any` (unless it's defined as `[]any`) because bare interfaces were ignored in `isTypeIgnored()` along with channels/funcs/unsafeptrs.
1 parent 8c7acdd commit c989c28

File tree

2 files changed

+72
-3
lines changed

2 files changed

+72
-3
lines changed

transformers/struct.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ func (t *structTransformer) addColumnFromField(field reflect.StructField, parent
239239
return fmt.Errorf("failed to transform type for field %s: %w", field.Name, err)
240240
}
241241
}
242+
if columnType == nil {
243+
return nil // ignored
244+
}
242245

243246
path := field.Name
244247
name, err := t.nameTransformer(field)
@@ -290,8 +293,7 @@ func (t *structTransformer) addColumnFromField(field reflect.StructField, parent
290293

291294
func isTypeIgnored(t reflect.Type) bool {
292295
switch t.Kind() {
293-
case reflect.Interface,
294-
reflect.Func,
296+
case reflect.Func,
295297
reflect.Chan,
296298
reflect.UnsafePointer:
297299
return true
@@ -348,6 +350,9 @@ func defaultGoTypeToSchemaType(v reflect.Type) (arrow.DataType, error) {
348350
}
349351
return arrow.ListOf(elemValueType), nil
350352

353+
case reflect.Interface:
354+
return nil, nil // silently ignore
355+
351356
default:
352357
return nil, fmt.Errorf("unsupported type: %s", k)
353358
}

transformers/struct_test.go

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package transformers
22

33
import (
44
"net"
5+
"reflect"
56
"testing"
67
"time"
78

@@ -74,6 +75,11 @@ type (
7475
AFunnyLookingField string `json:"OS-EXT:a-funny-looking-field"`
7576
AFieldWithCamelCaseName string `json:"camelCaseName"`
7677
}
78+
79+
testStructWithAny struct {
80+
IntCol int `json:"int_col"`
81+
Properties any
82+
}
7783
)
7884

7985
var (
@@ -269,6 +275,30 @@ var (
269275
},
270276
},
271277
}
278+
279+
expectedTestTableStructWithAny = schema.Table{
280+
Name: "test_embedded_struct_with_any",
281+
Columns: schema.ColumnList{
282+
{
283+
Name: "int_col",
284+
Type: arrow.PrimitiveTypes.Int64,
285+
},
286+
},
287+
}
288+
289+
expectedTestTableStructWithCustomAny = schema.Table{
290+
Name: "test_embedded_struct_with_custom_any",
291+
Columns: schema.ColumnList{
292+
{
293+
Name: "int_col",
294+
Type: arrow.PrimitiveTypes.Int64,
295+
},
296+
{
297+
Name: "properties",
298+
Type: types.ExtensionTypes.JSON,
299+
},
300+
},
301+
}
272302
)
273303

274304
func TestTableFromGoStruct(t *testing.T) {
@@ -389,10 +419,34 @@ func TestTableFromGoStruct(t *testing.T) {
389419
},
390420
want: expectedFunnyTable,
391421
},
422+
{
423+
name: "Ignore any-type fields by default",
424+
args: args{
425+
testStruct: testStructWithAny{},
426+
},
427+
want: expectedTestTableStructWithAny,
428+
},
429+
{
430+
name: "Should be able to override any-type fields with a type",
431+
args: args{
432+
testStruct: testStructWithAny{},
433+
options: []StructTransformerOption{
434+
WithTypeTransformer(func(f reflect.StructField) (arrow.DataType, error) {
435+
if f.Type.Kind() == reflect.Interface {
436+
return types.ExtensionTypes.JSON, nil
437+
}
438+
return nil, nil
439+
}),
440+
},
441+
},
442+
want: expectedTestTableStructWithCustomAny,
443+
},
392444
}
393445

394446
for _, tt := range tests {
447+
tt := tt
395448
t.Run(tt.name, func(t *testing.T) {
449+
t.Parallel()
396450
table := schema.Table{
397451
Name: "test",
398452
Columns: schema.ColumnList{},
@@ -405,11 +459,21 @@ func TestTableFromGoStruct(t *testing.T) {
405459
}
406460
t.Fatal(err)
407461
}
462+
if tt.wantErr {
463+
t.Fatal("expected error, got none")
464+
}
465+
408466
for i, col := range table.Columns {
409467
if !arrow.TypeEqual(col.Type, tt.want.Columns[i].Type) {
410-
t.Fatalf("column %s does not match expected type. got %v, want %v", col.Name, col.Type, tt.want.Columns[i].Type)
468+
t.Fatalf("column %q does not match expected type. got %v, want %v", col.Name, col.Type, tt.want.Columns[i].Type)
469+
}
470+
}
471+
for _, exc := range tt.want.Columns {
472+
if c := table.Column(exc.Name); c == nil {
473+
t.Fatalf("column %q not found. want: %v", exc.Name, exc.Type)
411474
}
412475
}
476+
413477
if diff := cmp.Diff(table.PrimaryKeys(), tt.want.PrimaryKeys()); diff != "" {
414478
t.Fatalf("table does not match expected. diff (-got, +want): %v", diff)
415479
}

0 commit comments

Comments
 (0)