tracktolib 0.63.0__py3-none-any.whl → 0.64.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
tracktolib/pg/query.py CHANGED
@@ -160,12 +160,34 @@ class PGInsertQuery(PGQuery):
160
160
  def is_returning(self):
161
161
  return self.returning is not None
162
162
 
163
+ def _get_values_query(self) -> str:
164
+ """Generate the VALUES clause for the query."""
165
+ _columns = self.columns
166
+ num_cols = len(_columns)
167
+
168
+ if len(self.items) == 1 or not self.is_returning:
169
+ # Single row or no returning: simple placeholders
170
+ return ", ".join(f"${i + 1}" for i in range(num_cols))
171
+ else:
172
+ # Multiple rows with returning: generate all value groups
173
+ value_groups = []
174
+ for row_idx in range(len(self.items)):
175
+ offset = row_idx * num_cols
176
+ group = ", ".join(f"${offset + i + 1}" for i in range(num_cols))
177
+ value_groups.append(f"({group})")
178
+ return ", ".join(value_groups)
179
+
163
180
  @property
164
181
  def query(self) -> str:
165
182
  _columns = self.columns
166
- _values = ", ".join(f"${i + 1}" for i, _ in enumerate(_columns))
183
+ _values = self._get_values_query()
167
184
 
168
- query = _get_insert_query(self.table, _columns, _values)
185
+ if len(self.items) > 1 and self.is_returning:
186
+ # For multi-row insert with returning, build full VALUES clause
187
+ _columns_str = ", ".join(_columns)
188
+ query = f"INSERT INTO {self.table} AS t ({_columns_str}) VALUES {_values}"
189
+ else:
190
+ query = _get_insert_query(self.table, _columns, _values)
169
191
 
170
192
  # Conflict
171
193
  if self.on_conflict:
@@ -184,13 +206,14 @@ class PGInsertQuery(PGQuery):
184
206
  if self.returning is not None:
185
207
  if self.returning.returning_ids is None:
186
208
  raise ValueError("No returning ids found")
187
- if len(self.items) == 1:
188
- query = _get_returning_query(query, self.returning.returning_ids)
189
- else:
190
- raise NotImplementedError("Cannot return value when inserting many.")
209
+ query = _get_returning_query(query, self.returning.returning_ids)
191
210
 
192
211
  return query
193
212
 
213
+ def _get_flat_values(self) -> list:
214
+ """Get all values as a flat list for multi-row insert with returning."""
215
+ return [val for item_values in self.iter_values() for val in item_values]
216
+
194
217
 
195
218
  def get_update_fields(
196
219
  item: dict,
@@ -341,6 +364,7 @@ async def insert_one(
341
364
  await query.run(conn)
342
365
 
343
366
 
367
+ @overload
344
368
  async def insert_many(
345
369
  conn: _Connection,
346
370
  table: str,
@@ -349,12 +373,53 @@ async def insert_many(
349
373
  on_conflict: OnConflict | None = None,
350
374
  fill: bool = False,
351
375
  quote_columns: bool = False,
376
+ returning: None = None,
352
377
  query_callback: QueryCallback[PGInsertQuery] | None = None,
353
- ):
354
- query = insert_pg(table=table, items=items, on_conflict=on_conflict, fill=fill, quote_columns=quote_columns)
378
+ ) -> None: ...
379
+
380
+
381
+ @overload
382
+ async def insert_many(
383
+ conn: _Connection,
384
+ table: str,
385
+ items: list[dict],
386
+ *,
387
+ on_conflict: OnConflict | None = None,
388
+ fill: bool = False,
389
+ quote_columns: bool = False,
390
+ returning: str | list[str],
391
+ query_callback: QueryCallback[PGInsertQuery] | None = None,
392
+ ) -> list[asyncpg.Record]: ...
393
+
394
+
395
+ async def insert_many(
396
+ conn: _Connection,
397
+ table: str,
398
+ items: list[dict],
399
+ *,
400
+ on_conflict: OnConflict | None = None,
401
+ fill: bool = False,
402
+ quote_columns: bool = False,
403
+ returning: str | list[str] | None = None,
404
+ query_callback: QueryCallback[PGInsertQuery] | None = None,
405
+ ) -> list[asyncpg.Record] | None:
406
+ returning_values = [returning] if isinstance(returning, str) else returning
407
+ query = insert_pg(
408
+ table=table,
409
+ items=items,
410
+ on_conflict=on_conflict,
411
+ fill=fill,
412
+ quote_columns=quote_columns,
413
+ returning=returning_values,
414
+ )
355
415
  if query_callback is not None:
356
416
  query_callback(query)
357
- await query.run(conn)
417
+
418
+ if returning is not None:
419
+ return await conn.fetch(query.query, *query._get_flat_values())
420
+ else:
421
+ await query.run(conn)
422
+ return None
358
423
 
359
424
 
360
425
  @overload
@@ -381,22 +446,41 @@ async def insert_returning(
381
446
  ) -> asyncpg.Record | None: ...
382
447
 
383
448
 
449
+ @overload
384
450
  async def insert_returning(
385
451
  conn: _Connection,
386
452
  table: str,
387
- item: dict,
453
+ item: list[dict],
454
+ returning: str | list[str],
455
+ on_conflict: OnConflict | None = None,
456
+ fill: bool = False,
457
+ query_callback: QueryCallback[PGInsertQuery] | None = None,
458
+ ) -> list[asyncpg.Record]: ...
459
+
460
+
461
+ async def insert_returning(
462
+ conn: _Connection,
463
+ table: str,
464
+ item: dict | list[dict],
388
465
  returning: list[str] | str,
389
466
  on_conflict: OnConflict | None = None,
390
467
  fill: bool = False,
391
468
  query_callback: QueryCallback[PGInsertQuery] | None = None,
392
- ) -> asyncpg.Record | Any | None:
469
+ ) -> asyncpg.Record | Any | list[asyncpg.Record] | None:
393
470
  returning_values = [returning] if isinstance(returning, str) else returning
394
- query = insert_pg(table=table, items=[item], on_conflict=on_conflict, fill=fill, returning=returning_values)
471
+ items = item if isinstance(item, list) else [item]
472
+
473
+ query = insert_pg(table=table, items=items, on_conflict=on_conflict, fill=fill, returning=returning_values)
395
474
  if query_callback is not None:
396
475
  query_callback(query)
397
- fn = conn.fetchval if len(returning_values) == 1 and returning != "*" else conn.fetchrow
398
476
 
399
- return await fn(query.query, *query.values)
477
+ if len(items) > 1:
478
+ # Multi-row insert: use fetch() with flat values
479
+ return await conn.fetch(query.query, *query._get_flat_values())
480
+ else:
481
+ # Single row insert: use fetchval or fetchrow
482
+ fn = conn.fetchval if len(returning_values) == 1 and returning != "*" else conn.fetchrow
483
+ return await fn(query.query, *query.values)
400
484
 
401
485
 
402
486
  async def fetch_count(conn: _Connection, query: str, *args) -> int:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tracktolib
3
- Version: 0.63.0
3
+ Version: 0.64.0
4
4
  Summary: Utility library for python
5
5
  Keywords: utility
6
6
  Author-email: julien.brayere@tracktor.fr
@@ -6,7 +6,7 @@ tracktolib/notion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
6
6
  tracktolib/notion/fetch.py,sha256=zIhFo9T18eS75l0wZN_WaXD51OUxTsgvFuvqk3R87o4,9974
7
7
  tracktolib/notion/models.py,sha256=D-px7Ht2xoXKKZICuEkZhRwVBvVCaKCvhpzPtVVYawI,5390
8
8
  tracktolib/pg/__init__.py,sha256=Ul_hgwvTXZvQBt7sHKi4ZI-0DDpnXmoFtmVkGRy-1J0,366
9
- tracktolib/pg/query.py,sha256=_wL9MQU_z8Sk0ZOYGVE0TjUbwBZ1OJJuEq2jlmWoeeM,16693
9
+ tracktolib/pg/query.py,sha256=zstc-QkBby7e6LybS8ed0d_6QLQNujY2H0lLNXFLNQ8,19366
10
10
  tracktolib/pg/utils.py,sha256=ygQn63EBDaEGB0p7P2ibellO2mv-StafanpXKcCUiZU,6324
11
11
  tracktolib/pg_sync.py,sha256=MKDaV7dYsRy59Y0EE5RGZL0DlZ-RUdBeaN9eSBwiQJg,6718
12
12
  tracktolib/pg_utils.py,sha256=ArYNdf9qsdYdzGEWmev8tZpyx8_1jaGGdkfYkauM7UM,2582
@@ -15,6 +15,6 @@ tracktolib/s3/minio.py,sha256=wMEjkSes9Fp39fD17IctALpD6zB2xwDRQEmO7Vzan3g,1387
15
15
  tracktolib/s3/s3.py,sha256=0HbSAPoaup5-W4LK54zRCjrQ5mr8OWR-N9WjW99Q4aw,5937
16
16
  tracktolib/tests.py,sha256=gKE--epQjgMZGXc5ydbl4zjOdmwztJS42UMV0p4hXEA,399
17
17
  tracktolib/utils.py,sha256=ysTBF9V35fVXQVBPk0kfE_84SGRxzrayqmg9RbtoJq4,5761
18
- tracktolib-0.63.0.dist-info/WHEEL,sha256=z-mOpxbJHqy3cq6SvUThBZdaLGFZzdZPtgWLcP2NKjQ,79
19
- tracktolib-0.63.0.dist-info/METADATA,sha256=q3HcfLHVoybHIDc4Bgayt3kYd5v1spd62OCGyxjCfZw,3128
20
- tracktolib-0.63.0.dist-info/RECORD,,
18
+ tracktolib-0.64.0.dist-info/WHEEL,sha256=z-mOpxbJHqy3cq6SvUThBZdaLGFZzdZPtgWLcP2NKjQ,79
19
+ tracktolib-0.64.0.dist-info/METADATA,sha256=ypN7PUQQ45bxXO0jJDuvQjZE0_T2aHiLfFV_ekUY_4U,3128
20
+ tracktolib-0.64.0.dist-info/RECORD,,