@@ -8,11 +8,13 @@ import (
88 "github.com/cloudquery/plugin-sdk/schema"
99 "github.com/google/go-cmp/cmp"
1010 "github.com/google/go-cmp/cmp/cmpopts"
11+ "golang.org/x/exp/slices"
1112)
1213
1314type (
1415 embeddedStruct struct {
1516 EmbeddedString string
17+ IntCol int `json:"int_col,omitempty"`
1618 }
1719
1820 testStruct struct {
@@ -45,10 +47,12 @@ type (
4547 * embeddedStruct
4648 }
4749 testStructWithEmbeddedStruct struct {
50+ IntCol int `json:"int_col,omitempty"`
4851 * testStruct
4952 * embeddedStruct
5053 }
5154 testStructWithNonEmbeddedStruct struct {
55+ IntCol int `json:"int_col,omitempty"`
5256 TestStruct * testStruct
5357 NonEmbedded * embeddedStruct
5458 }
@@ -140,23 +144,74 @@ var (
140144 Columns : expectedColumns ,
141145 }
142146 expectedTestTableEmbeddedStruct = schema.Table {
147+ Name : "test_struct" ,
148+ Columns : append (expectedColumns , schema.Column {Name : "embedded_string" , Type : schema .TypeString }),
149+ }
150+ expectedTestTableEmbeddedStructWithTopLevelPK = schema.Table {
151+ Name : "test_struct" ,
152+ Columns : func (base schema.ColumnList ) schema.ColumnList {
153+ cols := slices .Clone (base )
154+ cols = append (cols , schema.Column {Name : "embedded_string" , Type : schema .TypeString })
155+ cols [cols .Index ("int_col" )].CreationOptions .PrimaryKey = true
156+ return cols
157+ }(expectedColumns ),
158+ }
159+ expectedTestTableEmbeddedStructWithUnwrappedPK = schema.Table {
143160 Name : "test_struct" ,
144161 Columns : append (
145162 expectedColumns , schema.Column {
146- Name : "embedded_string" ,
147- Type : schema .TypeString ,
163+ Name : "embedded_string" ,
164+ Type : schema .TypeString ,
165+ CreationOptions : schema.ColumnCreationOptions {PrimaryKey : true },
148166 }),
149167 }
150168 expectedTestTableNonEmbeddedStruct = schema.Table {
151169 Name : "test_struct" ,
152170 Columns : schema.ColumnList {
171+ schema.Column {Name : "int_col" , Type : schema .TypeInt },
172+ // Should not be unwrapped
173+ schema.Column {Name : "test_struct" , Type : schema .TypeJSON },
174+ // Should be unwrapped
175+ schema.Column {Name : "non_embedded_embedded_string" , Type : schema .TypeString },
176+ schema.Column {Name : "non_embedded_int_col" , Type : schema .TypeInt },
177+ },
178+ }
179+ expectedTestTableNonEmbeddedStructWithTopLevelPK = schema.Table {
180+ Name : "test_struct" ,
181+ Columns : schema.ColumnList {
182+ schema.Column {
183+ Name : "int_col" ,
184+ Type : schema .TypeInt ,
185+ CreationOptions : schema.ColumnCreationOptions {PrimaryKey : true },
186+ },
187+ // Should not be unwrapped
188+ schema.Column {Name : "test_struct" , Type : schema .TypeJSON },
189+ // Should be unwrapped
190+ schema.Column {
191+ Name : "non_embedded_embedded_string" ,
192+ Type : schema .TypeString ,
193+ },
194+ schema.Column {Name : "non_embedded_int_col" , Type : schema .TypeInt },
195+ },
196+ }
197+ expectedTestTableNonEmbeddedStructWithUnwrappedPK = schema.Table {
198+ Name : "test_struct" ,
199+ Columns : schema.ColumnList {
200+ // shouldn't be PK
201+ schema.Column {Name : "int_col" , Type : schema .TypeInt },
153202 // Should not be unwrapped
154203 schema.Column {Name : "test_struct" , Type : schema .TypeJSON },
155204 // Should be unwrapped
156205 schema.Column {
157206 Name : "non_embedded_embedded_string" ,
158207 Type : schema .TypeString ,
159208 },
209+ // should be PK
210+ schema.Column {
211+ Name : "non_embedded_int_col" ,
212+ Type : schema .TypeInt ,
213+ CreationOptions : schema.ColumnCreationOptions {PrimaryKey : true },
214+ },
160215 },
161216 }
162217 expectedTestSliceStruct = schema.Table {
@@ -219,6 +274,28 @@ func TestTableFromGoStruct(t *testing.T) {
219274 },
220275 want : expectedTestTableEmbeddedStruct ,
221276 },
277+ {
278+ name : "should unwrap all embedded structs when option is set and use top-level field as PK" ,
279+ args : args {
280+ testStruct : testStructWithEmbeddedStruct {},
281+ options : []StructTransformerOption {
282+ WithUnwrapAllEmbeddedStructs (),
283+ WithPrimaryKeys ("IntCol" ),
284+ },
285+ },
286+ want : expectedTestTableEmbeddedStructWithTopLevelPK ,
287+ },
288+ {
289+ name : "should unwrap all embedded structs when option is set and use its field as PK" ,
290+ args : args {
291+ testStruct : testStructWithEmbeddedStruct {},
292+ options : []StructTransformerOption {
293+ WithUnwrapAllEmbeddedStructs (),
294+ WithPrimaryKeys ("EmbeddedString" ),
295+ },
296+ },
297+ want : expectedTestTableEmbeddedStructWithUnwrappedPK ,
298+ },
222299 {
223300 name : "should unwrap specific structs when option is set" ,
224301 args : args {
@@ -229,6 +306,28 @@ func TestTableFromGoStruct(t *testing.T) {
229306 },
230307 want : expectedTestTableNonEmbeddedStruct ,
231308 },
309+ {
310+ name : "should unwrap specific structs when option is set and use top level field as PK" ,
311+ args : args {
312+ testStruct : testStructWithNonEmbeddedStruct {},
313+ options : []StructTransformerOption {
314+ WithUnwrapStructFields ("NonEmbedded" ),
315+ WithPrimaryKeys ("IntCol" ),
316+ },
317+ },
318+ want : expectedTestTableNonEmbeddedStructWithTopLevelPK ,
319+ },
320+ {
321+ name : "should unwrap specific structs when option is set and use its field as PK" ,
322+ args : args {
323+ testStruct : testStructWithNonEmbeddedStruct {},
324+ options : []StructTransformerOption {
325+ WithUnwrapStructFields ("NonEmbedded" ),
326+ WithPrimaryKeys ("NonEmbedded.IntCol" ),
327+ },
328+ },
329+ want : expectedTestTableNonEmbeddedStructWithUnwrappedPK ,
330+ },
232331 {
233332 name : "should generate table from slice struct" ,
234333 args : args {
0 commit comments