@@ -93,15 +93,22 @@ def _convert_objects(self, objects: list[dict], table_name: str) -> str:
9393 # When flattening, compute the full column set first so rows align
9494 if self .flatten :
9595 columns , flat_map = self ._infer_columns_flattened (objects , table_name )
96- # Process nested arrays into child tables
96+ # Process nested arrays into child tables, grouped by key so that
97+ # each nested array produces exactly ONE child table whose INSERT
98+ # covers every parent row's children.
99+ nested_groups : dict [str , tuple [list [dict ], list [dict ]]] = {}
97100 for obj in objects :
98101 for key , value in obj .items ():
99102 if (
100103 isinstance (value , list )
101104 and value
102105 and all (isinstance (v , dict ) for v in value )
103106 ):
104- self ._flatten_nested (table_name , key , value , obj )
107+ children , parents = nested_groups .setdefault (key , ([], []))
108+ children .extend (value )
109+ parents .extend ([obj ] * len (value ))
110+ for key , (children , parents ) in nested_groups .items ():
111+ self ._flatten_nested (table_name , key , children , parents )
105112 else :
106113 columns = self ._infer_columns (objects )
107114 flat_map = {}
@@ -240,27 +247,34 @@ def _flatten_nested(
240247 parent_table : str ,
241248 key : str ,
242249 nested_objects : list [dict ],
243- parent_obj : dict ,
250+ parent_objs : list [ dict ] ,
244251 ) -> None :
245- """Flatten a nested array of objects into a separate table."""
252+ """Flatten nested arrays of objects into a single child table.
253+
254+ ``nested_objects`` and ``parent_objs`` are aligned lists: each child
255+ row links back to its own parent via the foreign key. Grouping all
256+ parents' children into one table avoids emitting duplicate
257+ ``CREATE TABLE`` statements when multiple rows carry nested arrays.
258+ """
246259 child_table = f"{ parent_table } _{ key } "
247260 columns = self ._infer_columns (nested_objects )
248261 # Add parent reference — only if no existing column has the FK name
249262 parent_ref = None
250263 for pk in ("id" , "name" , parent_table + "_id" ):
251- if pk in parent_obj :
264+ if any ( pk in parent_obj for parent_obj in parent_objs ) :
252265 parent_ref = pk
253266 break
254267 fk_col = f"{ parent_table } _{ parent_ref } " if parent_ref else None
255268 fk_already_exists = fk_col and fk_col in columns
256269 if fk_col and not fk_already_exists :
270+ fk_parent = next (p for p in parent_objs if parent_ref in p )
257271 columns = {
258- fk_col : sql_type_for (parent_obj [parent_ref ], self .dialect ),
272+ fk_col : sql_type_for (fk_parent [parent_ref ], self .dialect ),
259273 ** columns ,
260274 }
261275
262276 rows : list [list [str ]] = []
263- for nested in nested_objects :
277+ for nested , parent_obj in zip ( nested_objects , parent_objs , strict = True ) :
264278 row : list [str ] = []
265279 for col_name in columns :
266280 if col_name == fk_col and not fk_already_exists :
@@ -277,11 +291,16 @@ def _process_flatten(self, objects: list, table_name: str) -> None:
277291 return
278292 if not objects or not isinstance (objects [0 ], dict ):
279293 return
294+ nested_groups : dict [str , tuple [list [dict ], list [dict ]]] = {}
280295 for obj in objects :
281296 for key , value in obj .items ():
282297 if (
283298 isinstance (value , list )
284299 and value
285300 and all (isinstance (v , dict ) for v in value )
286301 ):
287- self ._flatten_nested (table_name , key , value , obj )
302+ children , parents = nested_groups .setdefault (key , ([], []))
303+ children .extend (value )
304+ parents .extend ([obj ] * len (value ))
305+ for key , (children , parents ) in nested_groups .items ():
306+ self ._flatten_nested (table_name , key , children , parents )
0 commit comments