Skip to content

Commit d43e7cc

Browse files
authored
feat: Expose transformer option for Skipping PK Validation (#2312)
This adds an option `WithSkipPrimaryKeyValidation()` that will allow users to skip validation by specifying the name of the field
1 parent c3d2ce0 commit d43e7cc

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

transformers/options.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ func WithPrimaryKeyComponents(fields ...string) StructTransformerOption {
8585
}
8686
}
8787

88+
func WithSkipPrimaryKeyValidation(fields ...string) StructTransformerOption {
89+
return func(t *structTransformer) {
90+
t.skipPKValidationFields = fields
91+
}
92+
}
93+
8894
// WithMaxJSONTypeSchemaDepth allows to specify the maximum depth of JSON type schema
8995
func WithMaxJSONTypeSchemaDepth(maxDepth int) StructTransformerOption {
9096
return func(t *structTransformer) {

transformers/struct.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ type structTransformer struct {
3030
pkFieldsFound []string
3131
pkComponentFields []string
3232
pkComponentFieldsFound []string
33+
skipPKValidationFields []string
34+
skipPKValidationFieldsFound []string
3335
jsonSchemaNameTransformer NameTransformer
3436

3537
maxJSONTypeSchemaDepth int
@@ -190,6 +192,13 @@ func (t *structTransformer) addColumnFromField(field reflect.StructField, parent
190192
}
191193
}
192194

195+
for _, skipPK := range t.skipPKValidationFields {
196+
if skipPK == path {
197+
column.SkipPKValidation = true
198+
t.skipPKValidationFieldsFound = append(t.skipPKValidationFieldsFound, skipPK)
199+
}
200+
}
201+
193202
t.table.Columns = append(t.table.Columns, column)
194203

195204
return nil
@@ -244,6 +253,10 @@ func TransformWithStruct(st any, opts ...StructTransformerOption) schema.Transfo
244253
if diff := funk.SubtractString(t.pkComponentFields, t.pkComponentFieldsFound); len(diff) > 0 {
245254
return fmt.Errorf("failed to find all of the desired primary key components: %v", diff)
246255
}
256+
257+
if diff := funk.SubtractString(t.skipPKValidationFields, t.skipPKValidationFieldsFound); len(diff) > 0 {
258+
return fmt.Errorf("failed to find all of the desired skip primary key validation fields: %v", diff)
259+
}
247260
return nil
248261
}
249262
}

transformers/struct_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,39 @@ var (
322322
},
323323
},
324324
}
325+
326+
expectedTableWithSkipPKValidation = schema.Table{
327+
Name: "test_pk_struct",
328+
Columns: schema.ColumnList{
329+
{
330+
Name: "parent",
331+
Type: arrow.BinaryTypes.String,
332+
SkipPKValidation: true,
333+
},
334+
{
335+
Name: "name",
336+
Type: arrow.BinaryTypes.String,
337+
},
338+
{
339+
Name: "version",
340+
Type: arrow.PrimitiveTypes.Int64,
341+
},
342+
},
343+
}
344+
345+
expectedTestTableNonEmbeddedStructWithSkipPKValidation = schema.Table{
346+
Name: "test_struct",
347+
Columns: schema.ColumnList{
348+
schema.Column{Name: "int_col", Type: arrow.PrimitiveTypes.Int64},
349+
schema.Column{Name: "test_struct", Type: types.ExtensionTypes.JSON},
350+
schema.Column{
351+
Name: "non_embedded_embedded_string",
352+
Type: arrow.BinaryTypes.String,
353+
SkipPKValidation: true,
354+
},
355+
schema.Column{Name: "non_embedded_int_col", Type: arrow.PrimitiveTypes.Int64},
356+
},
357+
}
325358
)
326359

327360
func TestTableFromGoStruct(t *testing.T) {
@@ -476,6 +509,38 @@ func TestTableFromGoStruct(t *testing.T) {
476509
},
477510
want: expectedTestTableStructNonNullableFields,
478511
},
512+
{
513+
name: "Should configure skip PK validation when option is set",
514+
args: args{
515+
testStruct: testPKStruct{},
516+
options: []StructTransformerOption{
517+
WithSkipPrimaryKeyValidation("Parent"),
518+
},
519+
},
520+
want: expectedTableWithSkipPKValidation,
521+
},
522+
{
523+
name: "Should return an error when a skip PK validation field is not found",
524+
args: args{
525+
testStruct: testPKStruct{},
526+
options: []StructTransformerOption{
527+
WithSkipPrimaryKeyValidation("Parent", "InvalidColumn"),
528+
},
529+
},
530+
want: expectedTableWithSkipPKValidation,
531+
wantErr: true,
532+
},
533+
{
534+
name: "Should configure skip PK validation for unwrapped struct fields",
535+
args: args{
536+
testStruct: testStructWithNonEmbeddedStruct{},
537+
options: []StructTransformerOption{
538+
WithUnwrapStructFields("NonEmbedded"),
539+
WithSkipPrimaryKeyValidation("NonEmbedded.EmbeddedString"),
540+
},
541+
},
542+
want: expectedTestTableNonEmbeddedStructWithSkipPKValidation,
543+
},
479544
}
480545

481546
for _, tt := range tests {
@@ -512,6 +577,19 @@ func TestTableFromGoStruct(t *testing.T) {
512577
if diff := cmp.Diff(table.PrimaryKeys(), tt.want.PrimaryKeys()); diff != "" {
513578
t.Fatalf("table does not match expected. diff (-got, +want): %v", diff)
514579
}
580+
581+
// Check SkipPKValidation field for columns that have it set in expected
582+
for _, wantCol := range tt.want.Columns {
583+
if wantCol.SkipPKValidation {
584+
gotCol := table.Column(wantCol.Name)
585+
if gotCol == nil {
586+
t.Fatalf("column %q not found", wantCol.Name)
587+
}
588+
if !gotCol.SkipPKValidation {
589+
t.Fatalf("column %q expected SkipPKValidation=true, got false", wantCol.Name)
590+
}
591+
}
592+
}
515593
})
516594
}
517595
}

0 commit comments

Comments
 (0)