sql-athame 0.4.0a1__py3-none-any.whl → 0.4.0a3__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.
sql_athame/dataclasses.py CHANGED
@@ -100,12 +100,24 @@ class ModelBase(Mapping[str, Any]):
100
100
  _cache: Dict[tuple, Any]
101
101
  table_name: str
102
102
  primary_key_names: Tuple[str, ...]
103
+ array_safe_insert: bool
103
104
 
104
105
  def __init_subclass__(
105
- cls, *, table_name: str, primary_key: Union[FieldNames, str] = (), **kwargs: Any
106
+ cls,
107
+ *,
108
+ table_name: str,
109
+ primary_key: Union[FieldNames, str] = (),
110
+ insert_multiple_mode: str = "unnest",
111
+ **kwargs: Any,
106
112
  ):
107
113
  cls._cache = {}
108
114
  cls.table_name = table_name
115
+ if insert_multiple_mode == "array_safe":
116
+ cls.array_safe_insert = True
117
+ elif insert_multiple_mode == "unnest":
118
+ cls.array_safe_insert = False
119
+ else:
120
+ raise ValueError("Unknown `insert_multiple_mode`")
109
121
  if isinstance(primary_key, str):
110
122
  cls.primary_key_names = (primary_key,)
111
123
  else:
@@ -407,19 +419,69 @@ class ModelBase(Mapping[str, Any]):
407
419
  )
408
420
 
409
421
  @classmethod
410
- async def insert_multiple(
422
+ def insert_multiple_array_safe_sql(cls: Type[T], rows: Iterable[T]) -> Fragment:
423
+ return sql(
424
+ "INSERT INTO {table} ({fields}) VALUES {values}",
425
+ table=cls.table_name_sql(),
426
+ fields=sql.list(cls.field_names_sql()),
427
+ values=sql.list(
428
+ sql("({})", sql.list(row.field_values_sql(default_none=True)))
429
+ for row in rows
430
+ ),
431
+ )
432
+
433
+ @classmethod
434
+ async def insert_multiple_unnest(
411
435
  cls: Type[T], connection_or_pool: Union[Connection, Pool], rows: Iterable[T]
412
436
  ) -> str:
413
437
  return await connection_or_pool.execute(*cls.insert_multiple_sql(rows))
414
438
 
415
439
  @classmethod
416
- async def upsert_multiple(
440
+ async def insert_multiple_array_safe(
441
+ cls: Type[T], connection_or_pool: Union[Connection, Pool], rows: Iterable[T]
442
+ ) -> str:
443
+ for chunk in chunked(rows, 100):
444
+ last = await connection_or_pool.execute(
445
+ *cls.insert_multiple_array_safe_sql(chunk)
446
+ )
447
+ return last
448
+
449
+ @classmethod
450
+ async def insert_multiple(
451
+ cls: Type[T], connection_or_pool: Union[Connection, Pool], rows: Iterable[T]
452
+ ) -> str:
453
+ if cls.array_safe_insert:
454
+ return await cls.insert_multiple_array_safe(connection_or_pool, rows)
455
+ else:
456
+ return await cls.insert_multiple_unnest(connection_or_pool, rows)
457
+
458
+ @classmethod
459
+ async def upsert_multiple_unnest(
417
460
  cls: Type[T], connection_or_pool: Union[Connection, Pool], rows: Iterable[T]
418
461
  ) -> str:
419
462
  return await connection_or_pool.execute(
420
463
  *cls.upsert_sql(cls.insert_multiple_sql(rows))
421
464
  )
422
465
 
466
+ @classmethod
467
+ async def upsert_multiple_array_safe(
468
+ cls: Type[T], connection_or_pool: Union[Connection, Pool], rows: Iterable[T]
469
+ ) -> str:
470
+ for chunk in chunked(rows, 100):
471
+ last = await connection_or_pool.execute(
472
+ *cls.upsert_sql(cls.insert_multiple_array_safe_sql(chunk))
473
+ )
474
+ return last
475
+
476
+ @classmethod
477
+ async def upsert_multiple(
478
+ cls: Type[T], connection_or_pool: Union[Connection, Pool], rows: Iterable[T]
479
+ ) -> str:
480
+ if cls.array_safe_insert:
481
+ return await cls.upsert_multiple_array_safe(connection_or_pool, rows)
482
+ else:
483
+ return await cls.upsert_multiple_unnest(connection_or_pool, rows)
484
+
423
485
  @classmethod
424
486
  def _get_equal_ignoring_fn(
425
487
  cls: Type[T], ignore: FieldNamesSet = ()
@@ -530,3 +592,10 @@ class ModelBase(Mapping[str, Any]):
530
592
  await cls.delete_multiple(connection, deleted)
531
593
 
532
594
  return created, updated_triples, deleted
595
+
596
+
597
+ def chunked(lst, n):
598
+ if type(lst) is not list:
599
+ lst = list(lst)
600
+ for i in range(0, len(lst), n):
601
+ yield lst[i : i + n]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sql-athame
3
- Version: 0.4.0a1
3
+ Version: 0.4.0a3
4
4
  Summary: Python tool for slicing and dicing SQL
5
5
  Home-page: https://github.com/bdowning/sql-athame
6
6
  License: MIT
@@ -1,11 +1,11 @@
1
1
  sql_athame/__init__.py,sha256=rzUQcbzmj3qkPZpL9jI_ALTRv-e1pAV4jSCryWkutlk,130
2
2
  sql_athame/base.py,sha256=fSnHQhh5ULeJ5q32RVUAvpWtF0qoY61B2gEEP59Nrpo,10350
3
- sql_athame/dataclasses.py,sha256=U-fxF8fMgEIINofmHZ8ujhPob9vMgUmECSZCdx35SRU,17370
3
+ sql_athame/dataclasses.py,sha256=qMs5xCuYwBjPYOD3EdRR9p4Bc3ZqoRsOmD1urDYVvH0,19751
4
4
  sql_athame/escape.py,sha256=LXExbiYtc407yDU4vPieyY2Pq5nypsJFfBc_2-gsbUg,743
5
5
  sql_athame/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  sql_athame/sqlalchemy.py,sha256=c-pCLE11hTh5I19rY1Vp5E7P7lAaj9i-i7ko2L8rlF4,1305
7
7
  sql_athame/types.py,sha256=7P4OyY0ezRlb2UDD9lpdXiLChnhQcBvHWaG_PKy3jmE,412
8
- sql_athame-0.4.0a1.dist-info/LICENSE,sha256=xqV29vPFqITcKifYrGPgVIBjq4fdmLSwY3gRUtDKafg,1076
9
- sql_athame-0.4.0a1.dist-info/METADATA,sha256=wH5Opq8gLMTBd7NHC1RjdW6TZDaPOWX-E27pOs6iiu0,12845
10
- sql_athame-0.4.0a1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
11
- sql_athame-0.4.0a1.dist-info/RECORD,,
8
+ sql_athame-0.4.0a3.dist-info/LICENSE,sha256=xqV29vPFqITcKifYrGPgVIBjq4fdmLSwY3gRUtDKafg,1076
9
+ sql_athame-0.4.0a3.dist-info/METADATA,sha256=ww5zr5Vvsn2SDrKZU6Er-xahTj091zKXpGTVv4EarV8,12845
10
+ sql_athame-0.4.0a3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
11
+ sql_athame-0.4.0a3.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.8.1
2
+ Generator: poetry-core 1.9.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any