sqlspec 0.14.1__py3-none-any.whl → 0.15.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.
Potentially problematic release.
This version of sqlspec might be problematic. Click here for more details.
- sqlspec/__init__.py +50 -25
- sqlspec/__main__.py +1 -1
- sqlspec/__metadata__.py +1 -3
- sqlspec/_serialization.py +1 -2
- sqlspec/_sql.py +256 -120
- sqlspec/_typing.py +278 -142
- sqlspec/adapters/adbc/__init__.py +4 -3
- sqlspec/adapters/adbc/_types.py +12 -0
- sqlspec/adapters/adbc/config.py +115 -260
- sqlspec/adapters/adbc/driver.py +462 -367
- sqlspec/adapters/aiosqlite/__init__.py +18 -3
- sqlspec/adapters/aiosqlite/_types.py +13 -0
- sqlspec/adapters/aiosqlite/config.py +199 -129
- sqlspec/adapters/aiosqlite/driver.py +230 -269
- sqlspec/adapters/asyncmy/__init__.py +18 -3
- sqlspec/adapters/asyncmy/_types.py +12 -0
- sqlspec/adapters/asyncmy/config.py +80 -168
- sqlspec/adapters/asyncmy/driver.py +260 -225
- sqlspec/adapters/asyncpg/__init__.py +19 -4
- sqlspec/adapters/asyncpg/_types.py +17 -0
- sqlspec/adapters/asyncpg/config.py +82 -181
- sqlspec/adapters/asyncpg/driver.py +285 -383
- sqlspec/adapters/bigquery/__init__.py +17 -3
- sqlspec/adapters/bigquery/_types.py +12 -0
- sqlspec/adapters/bigquery/config.py +191 -258
- sqlspec/adapters/bigquery/driver.py +474 -646
- sqlspec/adapters/duckdb/__init__.py +14 -3
- sqlspec/adapters/duckdb/_types.py +12 -0
- sqlspec/adapters/duckdb/config.py +415 -351
- sqlspec/adapters/duckdb/driver.py +343 -413
- sqlspec/adapters/oracledb/__init__.py +19 -5
- sqlspec/adapters/oracledb/_types.py +14 -0
- sqlspec/adapters/oracledb/config.py +123 -379
- sqlspec/adapters/oracledb/driver.py +507 -560
- sqlspec/adapters/psqlpy/__init__.py +13 -3
- sqlspec/adapters/psqlpy/_types.py +11 -0
- sqlspec/adapters/psqlpy/config.py +93 -254
- sqlspec/adapters/psqlpy/driver.py +505 -234
- sqlspec/adapters/psycopg/__init__.py +19 -5
- sqlspec/adapters/psycopg/_types.py +17 -0
- sqlspec/adapters/psycopg/config.py +143 -403
- sqlspec/adapters/psycopg/driver.py +706 -872
- sqlspec/adapters/sqlite/__init__.py +14 -3
- sqlspec/adapters/sqlite/_types.py +11 -0
- sqlspec/adapters/sqlite/config.py +202 -118
- sqlspec/adapters/sqlite/driver.py +264 -303
- sqlspec/base.py +105 -9
- sqlspec/{statement/builder → builder}/__init__.py +12 -14
- sqlspec/{statement/builder → builder}/_base.py +120 -55
- sqlspec/{statement/builder → builder}/_column.py +17 -6
- sqlspec/{statement/builder → builder}/_ddl.py +46 -79
- sqlspec/{statement/builder → builder}/_ddl_utils.py +5 -10
- sqlspec/{statement/builder → builder}/_delete.py +6 -25
- sqlspec/{statement/builder → builder}/_insert.py +6 -64
- sqlspec/builder/_merge.py +56 -0
- sqlspec/{statement/builder → builder}/_parsing_utils.py +3 -10
- sqlspec/{statement/builder → builder}/_select.py +11 -56
- sqlspec/{statement/builder → builder}/_update.py +12 -18
- sqlspec/{statement/builder → builder}/mixins/__init__.py +10 -14
- sqlspec/{statement/builder → builder}/mixins/_cte_and_set_ops.py +48 -59
- sqlspec/{statement/builder → builder}/mixins/_insert_operations.py +22 -16
- sqlspec/{statement/builder → builder}/mixins/_join_operations.py +1 -3
- sqlspec/{statement/builder → builder}/mixins/_merge_operations.py +3 -5
- sqlspec/{statement/builder → builder}/mixins/_order_limit_operations.py +3 -3
- sqlspec/{statement/builder → builder}/mixins/_pivot_operations.py +4 -8
- sqlspec/{statement/builder → builder}/mixins/_select_operations.py +21 -36
- sqlspec/{statement/builder → builder}/mixins/_update_operations.py +3 -14
- sqlspec/{statement/builder → builder}/mixins/_where_clause.py +52 -79
- sqlspec/cli.py +4 -5
- sqlspec/config.py +180 -133
- sqlspec/core/__init__.py +63 -0
- sqlspec/core/cache.py +873 -0
- sqlspec/core/compiler.py +396 -0
- sqlspec/core/filters.py +828 -0
- sqlspec/core/hashing.py +310 -0
- sqlspec/core/parameters.py +1209 -0
- sqlspec/core/result.py +664 -0
- sqlspec/{statement → core}/splitter.py +321 -191
- sqlspec/core/statement.py +651 -0
- sqlspec/driver/__init__.py +7 -10
- sqlspec/driver/_async.py +387 -176
- sqlspec/driver/_common.py +527 -289
- sqlspec/driver/_sync.py +390 -172
- sqlspec/driver/mixins/__init__.py +2 -19
- sqlspec/driver/mixins/_result_tools.py +168 -0
- sqlspec/driver/mixins/_sql_translator.py +6 -3
- sqlspec/exceptions.py +5 -252
- sqlspec/extensions/aiosql/adapter.py +93 -96
- sqlspec/extensions/litestar/config.py +0 -1
- sqlspec/extensions/litestar/handlers.py +15 -26
- sqlspec/extensions/litestar/plugin.py +16 -14
- sqlspec/extensions/litestar/providers.py +17 -52
- sqlspec/loader.py +424 -105
- sqlspec/migrations/__init__.py +12 -0
- sqlspec/migrations/base.py +92 -68
- sqlspec/migrations/commands.py +24 -106
- sqlspec/migrations/loaders.py +402 -0
- sqlspec/migrations/runner.py +49 -51
- sqlspec/migrations/tracker.py +31 -44
- sqlspec/migrations/utils.py +64 -24
- sqlspec/protocols.py +7 -183
- sqlspec/storage/__init__.py +1 -1
- sqlspec/storage/backends/base.py +37 -40
- sqlspec/storage/backends/fsspec.py +136 -112
- sqlspec/storage/backends/obstore.py +138 -160
- sqlspec/storage/capabilities.py +5 -4
- sqlspec/storage/registry.py +57 -106
- sqlspec/typing.py +136 -115
- sqlspec/utils/__init__.py +2 -3
- sqlspec/utils/correlation.py +0 -3
- sqlspec/utils/deprecation.py +6 -6
- sqlspec/utils/fixtures.py +6 -6
- sqlspec/utils/logging.py +0 -2
- sqlspec/utils/module_loader.py +7 -12
- sqlspec/utils/singleton.py +0 -1
- sqlspec/utils/sync_tools.py +16 -37
- sqlspec/utils/text.py +12 -51
- sqlspec/utils/type_guards.py +443 -232
- {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/METADATA +7 -2
- sqlspec-0.15.0.dist-info/RECORD +134 -0
- sqlspec/adapters/adbc/transformers.py +0 -108
- sqlspec/driver/connection.py +0 -207
- sqlspec/driver/mixins/_cache.py +0 -114
- sqlspec/driver/mixins/_csv_writer.py +0 -91
- sqlspec/driver/mixins/_pipeline.py +0 -508
- sqlspec/driver/mixins/_query_tools.py +0 -796
- sqlspec/driver/mixins/_result_utils.py +0 -138
- sqlspec/driver/mixins/_storage.py +0 -912
- sqlspec/driver/mixins/_type_coercion.py +0 -128
- sqlspec/driver/parameters.py +0 -138
- sqlspec/statement/__init__.py +0 -21
- sqlspec/statement/builder/_merge.py +0 -95
- sqlspec/statement/cache.py +0 -50
- sqlspec/statement/filters.py +0 -625
- sqlspec/statement/parameters.py +0 -956
- sqlspec/statement/pipelines/__init__.py +0 -210
- sqlspec/statement/pipelines/analyzers/__init__.py +0 -9
- sqlspec/statement/pipelines/analyzers/_analyzer.py +0 -646
- sqlspec/statement/pipelines/context.py +0 -109
- sqlspec/statement/pipelines/transformers/__init__.py +0 -7
- sqlspec/statement/pipelines/transformers/_expression_simplifier.py +0 -88
- sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +0 -1247
- sqlspec/statement/pipelines/transformers/_remove_comments_and_hints.py +0 -76
- sqlspec/statement/pipelines/validators/__init__.py +0 -23
- sqlspec/statement/pipelines/validators/_dml_safety.py +0 -290
- sqlspec/statement/pipelines/validators/_parameter_style.py +0 -370
- sqlspec/statement/pipelines/validators/_performance.py +0 -714
- sqlspec/statement/pipelines/validators/_security.py +0 -967
- sqlspec/statement/result.py +0 -435
- sqlspec/statement/sql.py +0 -1774
- sqlspec/utils/cached_property.py +0 -25
- sqlspec/utils/statement_hashing.py +0 -203
- sqlspec-0.14.1.dist-info/RECORD +0 -145
- /sqlspec/{statement/builder → builder}/mixins/_delete_operations.py +0 -0
- {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/entry_points.txt +0 -0
- {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/licenses/LICENSE +0 -0
- {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlspec
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.0
|
|
4
4
|
Summary: SQL Experiments in Python
|
|
5
5
|
Project-URL: Discord, https://discord.gg/litestar
|
|
6
6
|
Project-URL: Issue, https://github.com/litestar-org/sqlspec/issues/
|
|
@@ -11,8 +11,9 @@ License-Expression: MIT
|
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
License-File: NOTICE
|
|
13
13
|
Requires-Python: <4.0,>=3.9
|
|
14
|
-
Requires-Dist: click
|
|
15
14
|
Requires-Dist: eval-type-backport; python_version < '3.10'
|
|
15
|
+
Requires-Dist: mypy-extensions
|
|
16
|
+
Requires-Dist: rich-click
|
|
16
17
|
Requires-Dist: sqlglot>=19.9.0
|
|
17
18
|
Requires-Dist: typing-extensions
|
|
18
19
|
Provides-Extra: adbc
|
|
@@ -28,6 +29,9 @@ Provides-Extra: asyncmy
|
|
|
28
29
|
Requires-Dist: asyncmy; extra == 'asyncmy'
|
|
29
30
|
Provides-Extra: asyncpg
|
|
30
31
|
Requires-Dist: asyncpg; extra == 'asyncpg'
|
|
32
|
+
Provides-Extra: attrs
|
|
33
|
+
Requires-Dist: attrs; extra == 'attrs'
|
|
34
|
+
Requires-Dist: cattrs; extra == 'attrs'
|
|
31
35
|
Provides-Extra: bigquery
|
|
32
36
|
Requires-Dist: google-cloud-bigquery; extra == 'bigquery'
|
|
33
37
|
Provides-Extra: cli
|
|
@@ -44,6 +48,7 @@ Provides-Extra: litestar
|
|
|
44
48
|
Requires-Dist: litestar; extra == 'litestar'
|
|
45
49
|
Provides-Extra: msgspec
|
|
46
50
|
Requires-Dist: msgspec; extra == 'msgspec'
|
|
51
|
+
Provides-Extra: mypyc
|
|
47
52
|
Provides-Extra: nanoid
|
|
48
53
|
Requires-Dist: fastnanoid>=0.4.1; extra == 'nanoid'
|
|
49
54
|
Provides-Extra: obstore
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
sqlspec/__init__.py,sha256=8_TR9bXd7bkA4qBGCzTHNawH7KXaJ4YlnCJzJwvgud8,2066
|
|
2
|
+
sqlspec/__main__.py,sha256=lXBKZMOXA1uY735Rnsb-GS7aXy0nt22tYmd2X9FcxrY,253
|
|
3
|
+
sqlspec/__metadata__.py,sha256=IUw6MCTy1oeUJ1jAVYbuJLkOWbiAWorZ5W-E-SAD9N4,395
|
|
4
|
+
sqlspec/_serialization.py,sha256=6U5-smk2h2yl0i6am2prtOLJTdu4NJQdcLlSfSUMaUQ,2590
|
|
5
|
+
sqlspec/_sql.py,sha256=GggpMLOqVQxuirCcpSj-wBQX2N89jOqNibP7r88-dMY,39567
|
|
6
|
+
sqlspec/_typing.py,sha256=jv-7QHGLrJLfnP86bR-Xcmj3PDoddNZEKDz_vYRBiAU,22684
|
|
7
|
+
sqlspec/base.py,sha256=lVLzFD-nzEU6QnwnU0kRWh3XWjbvXWX0XnnUViYBoQk,21767
|
|
8
|
+
sqlspec/cli.py,sha256=3ZxPwl4neNWyrAkM9J9ccC_gaFigDJbhuZfx15JVE7E,9903
|
|
9
|
+
sqlspec/config.py,sha256=s7csxGK0SlTvB9jOvHlKKm4Y272RInQrUd6hGXwy31Q,14974
|
|
10
|
+
sqlspec/exceptions.py,sha256=mCqNJ0JSPA-TUPpAfdctwwqJWbiNsWap5ATNNRdczwU,6159
|
|
11
|
+
sqlspec/loader.py,sha256=sIK4I8L1Qe6hyoi6OHuaaAUUTdj4UrsRca16fuMs8HM,27259
|
|
12
|
+
sqlspec/protocols.py,sha256=nWj5DwWGBkY3i5KV5MsXSSALBbbR8vV_i17YoWNpW4U,12632
|
|
13
|
+
sqlspec/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
sqlspec/typing.py,sha256=JEq2VsTaLdNZ1HAqj3n_HgQgdwlQQOCcZx3VBiPs0UA,7393
|
|
15
|
+
sqlspec/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
+
sqlspec/adapters/adbc/__init__.py,sha256=CqBaEahvHbQ5NxmBJuuCtZ8v5wuaPgbqSSe9WUhglWY,336
|
|
17
|
+
sqlspec/adapters/adbc/_types.py,sha256=htTZ20qVo6Iod_ooUTLGd0xAL8AUYA4qeOexTaLQG3Q,351
|
|
18
|
+
sqlspec/adapters/adbc/config.py,sha256=UdS_4q5tsXKPEilD2dLtk9H1BI02CTSvhIWEDChrPEs,13871
|
|
19
|
+
sqlspec/adapters/adbc/driver.py,sha256=nYS6e6DXxZ8lHzUFvXvC8qtcGSBTvK8IF_NlBbw56pg,20217
|
|
20
|
+
sqlspec/adapters/aiosqlite/__init__.py,sha256=q2YXU9WCL2RSYFvd0DiXz5PeCaezCRmrqmQVd86V2so,577
|
|
21
|
+
sqlspec/adapters/aiosqlite/_types.py,sha256=M8VqaW6iCigfExhdJM2yPAN09Ue2yBoBL59-QXGBObo,355
|
|
22
|
+
sqlspec/adapters/aiosqlite/config.py,sha256=F_trn-H2KcB1sH1fXdGKYNLcDFwu28WszTBoESK8D0c,9036
|
|
23
|
+
sqlspec/adapters/aiosqlite/driver.py,sha256=pU6uyvZSDrUsgkLkBW1guq6wno5FOyqt9Tg8dg6L7HM,9644
|
|
24
|
+
sqlspec/adapters/asyncmy/__init__.py,sha256=wBgak4MA3ySaGQHUxrnv3HdSVQKKRWf1_DmENL0LkWs,531
|
|
25
|
+
sqlspec/adapters/asyncmy/_types.py,sha256=WbwREzJkLYmqd4c7A7cu04WaD5g7-n35ZETHZvbP1Z8,250
|
|
26
|
+
sqlspec/adapters/asyncmy/config.py,sha256=8fGiiFjIaT_y6OcVj_7dTK9sSuLqucMRsGcRPoYigy8,6557
|
|
27
|
+
sqlspec/adapters/asyncmy/driver.py,sha256=W_RLuGrGlqLl5aZBfMu4ZxBcgKZDPOmoJuAD-wpZeKM,11215
|
|
28
|
+
sqlspec/adapters/asyncpg/__init__.py,sha256=h3lg3pLBLrS9ABBt5yKFKhGL69RpOlASYSqVCuAuURY,567
|
|
29
|
+
sqlspec/adapters/asyncpg/_types.py,sha256=p65WrqfUl2cx5Md759_aV8m_gHP-PyCzNk48bLhDQkc,425
|
|
30
|
+
sqlspec/adapters/asyncpg/config.py,sha256=KdJ2BEtkIA3X3BY4C86zCOUH1-U3AT8ZPNYOpbN0e3A,8752
|
|
31
|
+
sqlspec/adapters/asyncpg/driver.py,sha256=jKDnh5Cz-LTCQvSGaYPgDysl7aocVZ9Wfxy_ERz0RUw,14286
|
|
32
|
+
sqlspec/adapters/bigquery/__init__.py,sha256=1nzkWubO4ZObuK27QoeGfS05ed5v02NU4GaXrvqjlw0,504
|
|
33
|
+
sqlspec/adapters/bigquery/_types.py,sha256=gECmbiSmZmnR-xJpmznhnva4SbhhdcYQ09jBdqMAmOs,255
|
|
34
|
+
sqlspec/adapters/bigquery/config.py,sha256=KYVvhcd4MyU2ak0t1mX3bd3EXlVMEciO7YPaDtZsPc8,11975
|
|
35
|
+
sqlspec/adapters/bigquery/driver.py,sha256=3y8gwrYTt6ktPKE0ihGk5Dj7yvL52Gc8uT1b1ynaCuA,24016
|
|
36
|
+
sqlspec/adapters/duckdb/__init__.py,sha256=iovQlYGfizYpIZpbc1YymK2xt6pZ4ApQj6I0Q0lHc3I,603
|
|
37
|
+
sqlspec/adapters/duckdb/_types.py,sha256=4p5nuD1yNs0fmQ5sGxKFx2ru6jUCPrpsYgqfh-uZHM8,270
|
|
38
|
+
sqlspec/adapters/duckdb/config.py,sha256=krVy5BsS7f2Uv4vmZrwpxlXzbe-MweS6JbHm809NJqE,18610
|
|
39
|
+
sqlspec/adapters/duckdb/driver.py,sha256=HDRPYh1k0JnnnaPpyv8oONn7UAYDCQyTK4fsgFDv6uk,15003
|
|
40
|
+
sqlspec/adapters/oracledb/__init__.py,sha256=AUsZ8m9tDgNwxv9m4LtkIs9Ib6hOtBrGNm-Ee4HWNq0,843
|
|
41
|
+
sqlspec/adapters/oracledb/_types.py,sha256=yPJTQE37HYVgvxI3USonWvFJ2VcfaNnXqfgKNVphmcQ,400
|
|
42
|
+
sqlspec/adapters/oracledb/config.py,sha256=yZITXSWuHKwrjVcuaTLyR9RtVb3WtzmWlBQTjvyUtPo,11383
|
|
43
|
+
sqlspec/adapters/oracledb/driver.py,sha256=mckrpid-XI-3juWbTXfy0JuYuZl3NS-ZB9P2VcJMSTI,22534
|
|
44
|
+
sqlspec/adapters/psqlpy/__init__.py,sha256=ABve2Oj-G-fxMO8WRJ0XzxEw2cs5H3INDnmUI99l8gc,526
|
|
45
|
+
sqlspec/adapters/psqlpy/_types.py,sha256=tG4jwQtBB6mCX5KU5x3hAhxsQUQlQEzbCsYhU3IouVc,269
|
|
46
|
+
sqlspec/adapters/psqlpy/config.py,sha256=h9IZr0vv6-rS7RLHSVsaIdCGgLsTdXQJSSgw4HI99d4,7866
|
|
47
|
+
sqlspec/adapters/psqlpy/driver.py,sha256=e9gHrmjXj7QGE_DxCTA3DhjvckSuFGO7pcdm3kqNv1c,20346
|
|
48
|
+
sqlspec/adapters/psycopg/__init__.py,sha256=swmTz8xlj6LvB-i78tBSE_T-sez2e6lFJW2cMzNJEVE,862
|
|
49
|
+
sqlspec/adapters/psycopg/_types.py,sha256=UJBKDWgARoSR6UxSy8zcIP7HSHTpXU5moJTsjDj0M4M,563
|
|
50
|
+
sqlspec/adapters/psycopg/config.py,sha256=tyxP1WbLQlwvdWdykG_iluIaQg0O6GLUwMLtfaRQ3sE,16268
|
|
51
|
+
sqlspec/adapters/psycopg/driver.py,sha256=qMRaoUI1RF0JLGEEIWzZJTyPd5jEaRFq6ZY0dkukrCQ,33434
|
|
52
|
+
sqlspec/adapters/sqlite/__init__.py,sha256=wDN0StuJxCy0VX1fVYDngTFUP5Cx8d0-foeJeJaEVOw,484
|
|
53
|
+
sqlspec/adapters/sqlite/_types.py,sha256=4Nqolhk8s4mwLw13BwUjuyhAbM9BsKwJCvcmjMWkhaY,246
|
|
54
|
+
sqlspec/adapters/sqlite/config.py,sha256=jTomeuHahwMN9huOnQclAuJyiFL1m8hoexQxWCn0Ckg,9166
|
|
55
|
+
sqlspec/adapters/sqlite/driver.py,sha256=uAhasoCNOV30gTvl1EUpofRcm8YiEW5RnVy07XyypzI,12103
|
|
56
|
+
sqlspec/builder/__init__.py,sha256=E3UGimdSOUK_ZGxFEOsCduwWWwTxcqoLe3Rvh4KbGNY,1429
|
|
57
|
+
sqlspec/builder/_base.py,sha256=vApAFc9-Vw4DsiQP7iQhtfIEjGy10mvi-6DjJnulZiM,17234
|
|
58
|
+
sqlspec/builder/_column.py,sha256=sGDoRhgeqNv69M2jIcNDWxTsMV3TKRNtktpDwl_ssSI,13224
|
|
59
|
+
sqlspec/builder/_ddl.py,sha256=6TvCMiJAuPBtwXbAupGKnrJ9Wb9-VK5P6cfEFbE9CT8,50284
|
|
60
|
+
sqlspec/builder/_ddl_utils.py,sha256=qlKT9TqlaymwZLiZjHXIVvFofiWekCLNu-AvPFzUiac,4115
|
|
61
|
+
sqlspec/builder/_delete.py,sha256=YCAV7GUutY-j1Z6tQ9Q0CE4K4Z5LbZXldMOpS2uxAi4,2301
|
|
62
|
+
sqlspec/builder/_insert.py,sha256=nsAaJpAWU0g8LnAJynScn5Iqiw8f-bxvKlT-g5yToxw,8489
|
|
63
|
+
sqlspec/builder/_merge.py,sha256=pabh0G7DsMZoOG8cGep0qLLdgnyoxQFRUUglhE5yScE,1570
|
|
64
|
+
sqlspec/builder/_parsing_utils.py,sha256=0Bu2G5VAWOym-tIpdFau3_sa71CMmM-BwZzgDoD89xE,5384
|
|
65
|
+
sqlspec/builder/_select.py,sha256=oxi-5ezjsAt7n6OQm1FNCSO_wFo8djWBPL9f-kiUo9g,5992
|
|
66
|
+
sqlspec/builder/_update.py,sha256=l9tHwC96VSmk8zGMhzB_S4YuD2_6q4cBXMboqoqvLJ0,5969
|
|
67
|
+
sqlspec/builder/mixins/__init__.py,sha256=YXhAzKmQbQtne5j26SKWY8PUxwosl0RhlhLoahAdkj0,1885
|
|
68
|
+
sqlspec/builder/mixins/_cte_and_set_ops.py,sha256=BPPkDTFo2Feja7Vers0BrC_JIYcpfOYSTZ9GIV_UOZ4,8317
|
|
69
|
+
sqlspec/builder/mixins/_delete_operations.py,sha256=0f8ZZMFx5b53EUx1oF264owLb6aWP45naeB6g-BZQys,1068
|
|
70
|
+
sqlspec/builder/mixins/_insert_operations.py,sha256=0Pz0QSa4bgGIiKT2Y8zPs6C2uxEQPyQqXdhKADttSJ0,5528
|
|
71
|
+
sqlspec/builder/mixins/_join_operations.py,sha256=5qloj7JmRWBi7pFBpAY1acwg_O_1CpcHeYMbzkBKfBE,5507
|
|
72
|
+
sqlspec/builder/mixins/_merge_operations.py,sha256=JpP33NevlhfCHnKMpLQOU8THN2ImFKMUwdWiI6UydPI,16745
|
|
73
|
+
sqlspec/builder/mixins/_order_limit_operations.py,sha256=NuNUb_DJKTdnbjasjOh27zLtbr1JZ4ygS0NH76G4foI,4514
|
|
74
|
+
sqlspec/builder/mixins/_pivot_operations.py,sha256=nkV9kG15rSoX0IWRAmaZjxyY8J7_5sScgxrRtYjddqE,5886
|
|
75
|
+
sqlspec/builder/mixins/_select_operations.py,sha256=-zo75-lp9T3j7D7zRpsa1D3oCd0Jt2xZ_OslhZeumt0,24692
|
|
76
|
+
sqlspec/builder/mixins/_update_operations.py,sha256=N6Lm-BrMhEPfFQz9V3-4ZgvSEsGfWtuQwlWbzdgLVWc,6904
|
|
77
|
+
sqlspec/builder/mixins/_where_clause.py,sha256=lb6iGqbKPX7rInY1YwYpVMQxUlRftRZthZdwDbnYs20,25729
|
|
78
|
+
sqlspec/core/__init__.py,sha256=rU_xGsXhqIOnBbyB2InhJknYePm5NQ2DSWdBigror4g,1775
|
|
79
|
+
sqlspec/core/cache.py,sha256=CQ_xTBQVJaBxB5-ipiw4Oj6JObrcMFtXYRLMSvbXGnE,27130
|
|
80
|
+
sqlspec/core/compiler.py,sha256=we_ifDr7JOAu3EycmWDxynOYq8ufjwcZl9MDXFTf5cQ,13959
|
|
81
|
+
sqlspec/core/filters.py,sha256=J2tpDo8Ton98Gwc9Tx0Ki3X0JgO6xrnbE0_stfBeP3E,31126
|
|
82
|
+
sqlspec/core/hashing.py,sha256=4KyAFWtFDMYreoBGGPQppEuMWO6_NrRYlw9Lm-qeJqo,10429
|
|
83
|
+
sqlspec/core/parameters.py,sha256=X5e9SKGS1gkn7Sv6qAkzZtllIQDmhuUxAnLFlxBkAns,52833
|
|
84
|
+
sqlspec/core/result.py,sha256=vdPXLApkS0F2Jz-Bq7-A-bKf7g4JIs5_57nAI4O4tC0,21100
|
|
85
|
+
sqlspec/core/splitter.py,sha256=cb2P1B0q5vvALHi3SEJ7VdbRHH2GWsftrmJi9PYMbeE,28089
|
|
86
|
+
sqlspec/core/statement.py,sha256=S_fkqYkG9v2KCsznCBAJIDkR2ASKwub5Y3dNlRYkLec,24231
|
|
87
|
+
sqlspec/driver/__init__.py,sha256=QVpDRQGd1GreIP199en6qDbq-cZJcEF5go68DINagUk,569
|
|
88
|
+
sqlspec/driver/_async.py,sha256=0P3VlBYXfythkh9c1wCE3oZMwQa0NtbW_6SljPxpcAw,18858
|
|
89
|
+
sqlspec/driver/_common.py,sha256=go-SZRYlx_qEh8A9BGFl_BVByEdnLvtSXi6bqA6wOmU,25553
|
|
90
|
+
sqlspec/driver/_sync.py,sha256=UZKCTrKh48lzRONk-eX5q6qKBLZOawODaPN_28ObACE,18586
|
|
91
|
+
sqlspec/driver/mixins/__init__.py,sha256=gN4pQyJXxNy0xi91dcMJGA7DQ7TbjGjQI24SSpZc6Go,248
|
|
92
|
+
sqlspec/driver/mixins/_result_tools.py,sha256=wI8bGfDrGrG8nexPWiJdvgy1yi1_z643yKPsgMzBqiY,6915
|
|
93
|
+
sqlspec/driver/mixins/_sql_translator.py,sha256=zpaJsS0_-zVvm3u2yCQ8VkILrZ7j28925SyZe1ChvlM,1491
|
|
94
|
+
sqlspec/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
95
|
+
sqlspec/extensions/aiosql/__init__.py,sha256=-9cefc9pYPf9vCgALoB-y1DtmcgRjKe2azfl6RIarAA,414
|
|
96
|
+
sqlspec/extensions/aiosql/adapter.py,sha256=CXkNZaZq86ZhfYFGx4IFbkHmbIFQKMd9CS6Q2jkMCok,16009
|
|
97
|
+
sqlspec/extensions/litestar/__init__.py,sha256=tOmQ7RHSWOot7p30gk0efxxuP0OCq1opyyZqNmQY7FE,320
|
|
98
|
+
sqlspec/extensions/litestar/_utils.py,sha256=o-FuUj1_WkDrLxQxiP6hXDak66XfyRP3QLyEVKrIRjI,1954
|
|
99
|
+
sqlspec/extensions/litestar/cli.py,sha256=NYjPIWe0jESBgS0AG-3bdpcC5YM4RmZeeeTeFQK5Yqo,1362
|
|
100
|
+
sqlspec/extensions/litestar/config.py,sha256=3UI_vhtbupCLsf1nhUgUpRlCoUS5c0GsAjWvegT0c3c,4462
|
|
101
|
+
sqlspec/extensions/litestar/handlers.py,sha256=3LreU8rZvuHaJnKlN09ttu4wSorWJedsuKgeLT-cOEc,9993
|
|
102
|
+
sqlspec/extensions/litestar/plugin.py,sha256=lojdLit4Uop6fpJWGXgpWrbGUBgCWR_khOK4CdRYpKM,5615
|
|
103
|
+
sqlspec/extensions/litestar/providers.py,sha256=5LRb5JvRV_XZdNOKkdaIy3j5x-dFCcAi1ea1pgwuapI,18882
|
|
104
|
+
sqlspec/migrations/__init__.py,sha256=n9y2yLQb02zMz36bPXnrInsSIMLunwHvO7e8UvCYBJc,1061
|
|
105
|
+
sqlspec/migrations/base.py,sha256=D5-k0m4SnmVU0QRRPcMCvMAyEoAaceYYmD8JprSozDA,13251
|
|
106
|
+
sqlspec/migrations/commands.py,sha256=LUAOOJcfolv75ZRV33zjdZ9kocyJSJet5hEZhUVIemU,18490
|
|
107
|
+
sqlspec/migrations/loaders.py,sha256=wz-VUd1fEtOg-b1yWnLTTNtHkZkrjw-4o5hEqwUxbS0,12952
|
|
108
|
+
sqlspec/migrations/runner.py,sha256=OxzindA2EzjCAVqI59LxfWC02Ful-aPsOYY9yUV7ypA,7330
|
|
109
|
+
sqlspec/migrations/tracker.py,sha256=-gfHgvcYo1uBdr9FKrIxaU_0v734K5gpdLMuoaX29nQ,5013
|
|
110
|
+
sqlspec/migrations/utils.py,sha256=gWnCOdr8pwfkgG-FSUJgRz4q9TlCgOXY_B7n59NrgVA,3746
|
|
111
|
+
sqlspec/storage/__init__.py,sha256=bLrUfW_E41HH-Pi5kqFTPVYZiSsxlG7OZO1xP23nDSI,691
|
|
112
|
+
sqlspec/storage/capabilities.py,sha256=vyousxls9jISsykgoybpNHlGWN6Hq_pKcsZ5DmKGWvU,3045
|
|
113
|
+
sqlspec/storage/registry.py,sha256=NV-NdAcMdGqU5bHbXbkMuU_HRYuEgii7B4ldXnVSIo4,9529
|
|
114
|
+
sqlspec/storage/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
115
|
+
sqlspec/storage/backends/base.py,sha256=KS2JRZILoH_R_xsfKtYkqQ5a1r5OOBDSE5KbibTmhGY,5730
|
|
116
|
+
sqlspec/storage/backends/fsspec.py,sha256=YVr8X_q5F4Xrr9SyfUDve1dZ9E6KppuM8w6tvLwPKpc,16050
|
|
117
|
+
sqlspec/storage/backends/obstore.py,sha256=8DEpiF3SCfbWx-NxoQXZ8piJOr-9f1WURYK69hCDhnQ,19864
|
|
118
|
+
sqlspec/utils/__init__.py,sha256=DJiG2RGFaL9C0lLZStByzgR_GiPHfdkypAkTEGjTakw,211
|
|
119
|
+
sqlspec/utils/correlation.py,sha256=2jvkAY3nkU3UxNU_9pbBR6cz3A1Q1cGG9IaWSSOIb1Q,4195
|
|
120
|
+
sqlspec/utils/deprecation.py,sha256=L5ylPlkrWahXZ3q2Yta2ReFh4pA8rZapLNw9u_mOOEE,3794
|
|
121
|
+
sqlspec/utils/fixtures.py,sha256=Qm2uNMaL_6l6tlij-Pm3tLwD906iFK_OXhwZqOx3WgY,1807
|
|
122
|
+
sqlspec/utils/logging.py,sha256=ZEaj7J8oALrs_-p535vSUFo2tfrHkOEcL5pK2JGGFgM,3708
|
|
123
|
+
sqlspec/utils/module_loader.py,sha256=m5PSN9NwOLd0ZJBuqMVYVi-vaIQMBCVd25vnM3-rv3k,2823
|
|
124
|
+
sqlspec/utils/serializers.py,sha256=TKsRryRcYMnb8Z8MGkYGClIxcYvC8CW7MsrPQTJqEcY,154
|
|
125
|
+
sqlspec/utils/singleton.py,sha256=SKnszJi1NPeERgX7IjVIGYAYx4XqR1E_rph3bU6olAU,1047
|
|
126
|
+
sqlspec/utils/sync_tools.py,sha256=Iv1Msj1tb24iJhhulL_wcNsyjRComzAkyUNlefVci3w,7348
|
|
127
|
+
sqlspec/utils/text.py,sha256=n5K0gvXvyCc8jNteNKsBOymwf_JnQ65f3lu0YaYq4Ys,2898
|
|
128
|
+
sqlspec/utils/type_guards.py,sha256=AJKSQ323mNfhRbytI2e4N2cy2P6MMG7fp75foVnz328,30339
|
|
129
|
+
sqlspec-0.15.0.dist-info/METADATA,sha256=GFcTBVzGgY-1_Wc-fL_9l_lt2JN1i__L4uN9uT6rOhw,16822
|
|
130
|
+
sqlspec-0.15.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
131
|
+
sqlspec-0.15.0.dist-info/entry_points.txt,sha256=G-ZqY1Nuuw3Iys7nXw23f6ILenk_Lt47VdK2mhJCWHg,53
|
|
132
|
+
sqlspec-0.15.0.dist-info/licenses/LICENSE,sha256=MdujfZ6l5HuLz4mElxlu049itenOR3gnhN1_Nd3nVcM,1078
|
|
133
|
+
sqlspec-0.15.0.dist-info/licenses/NOTICE,sha256=Lyir8ozXWov7CyYS4huVaOCNrtgL17P-bNV-5daLntQ,1634
|
|
134
|
+
sqlspec-0.15.0.dist-info/RECORD,,
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
"""ADBC-specific AST transformers for handling driver limitations."""
|
|
2
|
-
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
|
-
from sqlglot import exp
|
|
6
|
-
|
|
7
|
-
from sqlspec.protocols import ProcessorProtocol
|
|
8
|
-
from sqlspec.statement.pipelines.context import SQLProcessingContext
|
|
9
|
-
|
|
10
|
-
__all__ = ("AdbcPostgresTransformer",)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class AdbcPostgresTransformer(ProcessorProtocol):
|
|
14
|
-
"""Transformer to handle ADBC PostgreSQL driver limitations.
|
|
15
|
-
|
|
16
|
-
This transformer addresses specific issues with the ADBC PostgreSQL driver:
|
|
17
|
-
1. Empty parameter lists in executemany() causing "no parameter $1" errors
|
|
18
|
-
2. NULL parameters causing "Can't map Arrow type 'na' to Postgres type" errors
|
|
19
|
-
|
|
20
|
-
The transformer works at the AST level to properly handle these edge cases.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def __init__(self) -> None:
|
|
24
|
-
self.has_placeholders = False
|
|
25
|
-
self.all_params_null = False
|
|
26
|
-
self.is_empty_params = False
|
|
27
|
-
self.has_null_params = False
|
|
28
|
-
self.null_param_indices: list[int] = []
|
|
29
|
-
|
|
30
|
-
def process(self, expression: Optional[exp.Expression], context: SQLProcessingContext) -> Optional[exp.Expression]:
|
|
31
|
-
"""Process the SQL expression to handle ADBC limitations."""
|
|
32
|
-
if not expression:
|
|
33
|
-
return expression
|
|
34
|
-
|
|
35
|
-
# Check if we have an empty parameter list for executemany
|
|
36
|
-
# Look at the merged_parameters in the context
|
|
37
|
-
params = context.merged_parameters
|
|
38
|
-
|
|
39
|
-
# For execute_many, check if we have an empty list
|
|
40
|
-
if isinstance(params, list) and len(params) == 0:
|
|
41
|
-
self.is_empty_params = True
|
|
42
|
-
|
|
43
|
-
# Check for NULL parameters
|
|
44
|
-
if params:
|
|
45
|
-
if isinstance(params, (list, tuple)):
|
|
46
|
-
# Track which parameters are NULL
|
|
47
|
-
self.null_param_indices = [i for i, p in enumerate(params) if p is None]
|
|
48
|
-
self.has_null_params = len(self.null_param_indices) > 0
|
|
49
|
-
self.all_params_null = len(self.null_param_indices) == len(params)
|
|
50
|
-
|
|
51
|
-
# For ADBC PostgreSQL, we need to replace NULL parameters with literals
|
|
52
|
-
# and remove them from the parameter list
|
|
53
|
-
if self.has_null_params:
|
|
54
|
-
# Create new parameter list without NULLs
|
|
55
|
-
new_params = [p for p in params if p is not None]
|
|
56
|
-
context.merged_parameters = new_params
|
|
57
|
-
|
|
58
|
-
elif isinstance(params, dict):
|
|
59
|
-
# For dict parameters, track which ones are NULL
|
|
60
|
-
null_keys = [k for k, v in params.items() if v is None]
|
|
61
|
-
self.has_null_params = len(null_keys) > 0
|
|
62
|
-
self.all_params_null = len(null_keys) == len(params)
|
|
63
|
-
|
|
64
|
-
if self.has_null_params:
|
|
65
|
-
# Remove NULL parameters from dict
|
|
66
|
-
context.merged_parameters = {k: v for k, v in params.items() if v is not None}
|
|
67
|
-
|
|
68
|
-
# Transform the AST if needed
|
|
69
|
-
if self.is_empty_params:
|
|
70
|
-
# For empty parameters, we should skip transformation and let the driver handle it
|
|
71
|
-
# The driver already has logic to return empty result for empty params
|
|
72
|
-
return expression
|
|
73
|
-
|
|
74
|
-
if self.has_null_params:
|
|
75
|
-
# Transform placeholders to NULL literals where needed
|
|
76
|
-
self._parameter_index = 0 # Track current parameter position
|
|
77
|
-
return expression.transform(self._transform_node)
|
|
78
|
-
|
|
79
|
-
return expression
|
|
80
|
-
|
|
81
|
-
def _transform_node(self, node: exp.Expression) -> exp.Expression:
|
|
82
|
-
"""Transform individual AST nodes."""
|
|
83
|
-
# Handle parameter nodes (e.g., $1, $2, etc. in PostgreSQL)
|
|
84
|
-
if isinstance(node, exp.Parameter):
|
|
85
|
-
# Access the parameter value directly from the AST node
|
|
86
|
-
# The 'this' attribute contains a Literal node, whose 'this' contains the actual value
|
|
87
|
-
if node.this and isinstance(node.this, exp.Literal):
|
|
88
|
-
try:
|
|
89
|
-
param_index = int(node.this.this) - 1 # Convert to 0-based index
|
|
90
|
-
# Check if this parameter should be NULL
|
|
91
|
-
if param_index in self.null_param_indices:
|
|
92
|
-
return exp.Null()
|
|
93
|
-
# Renumber the parameter based on how many NULLs came before it
|
|
94
|
-
nulls_before = sum(1 for idx in self.null_param_indices if idx < param_index)
|
|
95
|
-
new_index = param_index - nulls_before + 1 # Convert back to 1-based
|
|
96
|
-
return exp.Parameter(this=exp.Literal.number(new_index))
|
|
97
|
-
except (ValueError, IndexError):
|
|
98
|
-
pass
|
|
99
|
-
|
|
100
|
-
# Handle placeholder nodes for other dialects
|
|
101
|
-
elif isinstance(node, exp.Placeholder):
|
|
102
|
-
# For placeholders, we need to track position
|
|
103
|
-
if self._parameter_index in self.null_param_indices:
|
|
104
|
-
self._parameter_index += 1
|
|
105
|
-
return exp.Null()
|
|
106
|
-
self._parameter_index += 1
|
|
107
|
-
|
|
108
|
-
return node
|
sqlspec/driver/connection.py
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
"""Consolidated connection management utilities for database drivers.
|
|
2
|
-
|
|
3
|
-
This module provides centralized connection handling to avoid duplication
|
|
4
|
-
across database adapter implementations.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from contextlib import asynccontextmanager, contextmanager
|
|
8
|
-
from typing import TYPE_CHECKING, Any, Optional, TypeVar, cast
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from collections.abc import AsyncIterator, Iterator
|
|
12
|
-
|
|
13
|
-
from sqlspec.utils.type_guards import is_async_transaction_capable, is_sync_transaction_capable
|
|
14
|
-
|
|
15
|
-
__all__ = (
|
|
16
|
-
"get_connection_info",
|
|
17
|
-
"managed_connection_async",
|
|
18
|
-
"managed_connection_sync",
|
|
19
|
-
"managed_transaction_async",
|
|
20
|
-
"managed_transaction_sync",
|
|
21
|
-
"validate_pool_config",
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
ConnectionT = TypeVar("ConnectionT")
|
|
26
|
-
PoolT = TypeVar("PoolT")
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@contextmanager
|
|
30
|
-
def managed_connection_sync(config: Any, provided_connection: Optional[ConnectionT] = None) -> "Iterator[ConnectionT]":
|
|
31
|
-
"""Context manager for database connections.
|
|
32
|
-
|
|
33
|
-
Args:
|
|
34
|
-
config: Database configuration with provide_connection method
|
|
35
|
-
provided_connection: Optional existing connection to use
|
|
36
|
-
|
|
37
|
-
Yields:
|
|
38
|
-
Database connection
|
|
39
|
-
"""
|
|
40
|
-
if provided_connection is not None:
|
|
41
|
-
yield provided_connection
|
|
42
|
-
return
|
|
43
|
-
|
|
44
|
-
# Get connection from config
|
|
45
|
-
with config.provide_connection() as connection:
|
|
46
|
-
yield connection
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
@contextmanager
|
|
50
|
-
def managed_transaction_sync(connection: ConnectionT, auto_commit: bool = True) -> "Iterator[ConnectionT]":
|
|
51
|
-
"""Context manager for database transactions.
|
|
52
|
-
|
|
53
|
-
Args:
|
|
54
|
-
connection: Database connection
|
|
55
|
-
auto_commit: Whether to auto-commit on success
|
|
56
|
-
|
|
57
|
-
Yields:
|
|
58
|
-
Database connection
|
|
59
|
-
"""
|
|
60
|
-
# Check if connection already has autocommit enabled
|
|
61
|
-
has_autocommit = getattr(connection, "autocommit", False)
|
|
62
|
-
|
|
63
|
-
if not auto_commit or not is_sync_transaction_capable(connection) or has_autocommit:
|
|
64
|
-
yield connection
|
|
65
|
-
return
|
|
66
|
-
|
|
67
|
-
try:
|
|
68
|
-
yield cast("ConnectionT", connection)
|
|
69
|
-
cast("Any", connection).commit()
|
|
70
|
-
except Exception:
|
|
71
|
-
# Some databases (like DuckDB) throw an error if rollback is called
|
|
72
|
-
# when no transaction is active. Catch and ignore these specific errors.
|
|
73
|
-
try:
|
|
74
|
-
cast("Any", connection).rollback()
|
|
75
|
-
except Exception as rollback_error:
|
|
76
|
-
# Check if this is a "no transaction active" type error
|
|
77
|
-
error_msg = str(rollback_error).lower()
|
|
78
|
-
if "no transaction" in error_msg or "transaction context error" in error_msg:
|
|
79
|
-
# Ignore rollback errors when no transaction is active
|
|
80
|
-
pass
|
|
81
|
-
else:
|
|
82
|
-
# Re-raise other rollback errors
|
|
83
|
-
raise
|
|
84
|
-
raise
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
@asynccontextmanager
|
|
88
|
-
async def managed_connection_async(
|
|
89
|
-
config: Any, provided_connection: Optional[ConnectionT] = None
|
|
90
|
-
) -> "AsyncIterator[ConnectionT]":
|
|
91
|
-
"""Async context manager for database connections.
|
|
92
|
-
|
|
93
|
-
Args:
|
|
94
|
-
config: Database configuration with provide_connection method
|
|
95
|
-
provided_connection: Optional existing connection to use
|
|
96
|
-
|
|
97
|
-
Yields:
|
|
98
|
-
Database connection
|
|
99
|
-
"""
|
|
100
|
-
if provided_connection is not None:
|
|
101
|
-
yield provided_connection
|
|
102
|
-
return
|
|
103
|
-
|
|
104
|
-
# Get connection from config
|
|
105
|
-
async with config.provide_connection() as connection:
|
|
106
|
-
yield connection
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
@asynccontextmanager
|
|
110
|
-
async def managed_transaction_async(connection: ConnectionT, auto_commit: bool = True) -> "AsyncIterator[ConnectionT]":
|
|
111
|
-
"""Async context manager for database transactions.
|
|
112
|
-
|
|
113
|
-
Args:
|
|
114
|
-
connection: Database connection
|
|
115
|
-
auto_commit: Whether to auto-commit on success
|
|
116
|
-
|
|
117
|
-
Yields:
|
|
118
|
-
Database connection
|
|
119
|
-
"""
|
|
120
|
-
# Check if connection already has autocommit enabled
|
|
121
|
-
has_autocommit = getattr(connection, "autocommit", False)
|
|
122
|
-
|
|
123
|
-
if not auto_commit or not is_async_transaction_capable(connection) or has_autocommit:
|
|
124
|
-
yield connection
|
|
125
|
-
return
|
|
126
|
-
|
|
127
|
-
try:
|
|
128
|
-
yield cast("ConnectionT", connection)
|
|
129
|
-
await cast("Any", connection).commit()
|
|
130
|
-
except Exception:
|
|
131
|
-
# Some databases (like DuckDB) throw an error if rollback is called
|
|
132
|
-
# when no transaction is active. Catch and ignore these specific errors.
|
|
133
|
-
try:
|
|
134
|
-
await cast("Any", connection).rollback()
|
|
135
|
-
except Exception as rollback_error:
|
|
136
|
-
# Check if this is a "no transaction active" type error
|
|
137
|
-
error_msg = str(rollback_error).lower()
|
|
138
|
-
if "no transaction" in error_msg or "transaction context error" in error_msg:
|
|
139
|
-
# Ignore rollback errors when no transaction is active
|
|
140
|
-
pass
|
|
141
|
-
else:
|
|
142
|
-
# Re-raise other rollback errors
|
|
143
|
-
raise
|
|
144
|
-
raise
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def get_connection_info(connection: Any) -> dict[str, Any]:
|
|
148
|
-
"""Extract connection information for logging/debugging.
|
|
149
|
-
|
|
150
|
-
Args:
|
|
151
|
-
connection: Database connection object
|
|
152
|
-
|
|
153
|
-
Returns:
|
|
154
|
-
Dictionary of connection information
|
|
155
|
-
"""
|
|
156
|
-
info = {"type": type(connection).__name__, "module": type(connection).__module__}
|
|
157
|
-
|
|
158
|
-
# Try to get database name
|
|
159
|
-
for attr in ("database", "dbname", "db", "catalog"):
|
|
160
|
-
value = getattr(connection, attr, None)
|
|
161
|
-
if value is not None:
|
|
162
|
-
info["database"] = value
|
|
163
|
-
break
|
|
164
|
-
|
|
165
|
-
# Try to get host information
|
|
166
|
-
for attr in ("host", "hostname", "server"):
|
|
167
|
-
value = getattr(connection, attr, None)
|
|
168
|
-
if value is not None:
|
|
169
|
-
info["host"] = value
|
|
170
|
-
break
|
|
171
|
-
|
|
172
|
-
return info
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def validate_pool_config(
|
|
176
|
-
min_size: int, max_size: int, max_idle_time: Optional[int] = None, max_lifetime: Optional[int] = None
|
|
177
|
-
) -> None:
|
|
178
|
-
"""Validate connection pool configuration.
|
|
179
|
-
|
|
180
|
-
Args:
|
|
181
|
-
min_size: Minimum pool size
|
|
182
|
-
max_size: Maximum pool size
|
|
183
|
-
max_idle_time: Maximum idle time in seconds
|
|
184
|
-
max_lifetime: Maximum connection lifetime in seconds
|
|
185
|
-
|
|
186
|
-
Raises:
|
|
187
|
-
ValueError: If configuration is invalid
|
|
188
|
-
"""
|
|
189
|
-
if min_size < 0:
|
|
190
|
-
msg = f"min_size must be >= 0, got {min_size}"
|
|
191
|
-
raise ValueError(msg)
|
|
192
|
-
|
|
193
|
-
if max_size < 1:
|
|
194
|
-
msg = f"max_size must be >= 1, got {max_size}"
|
|
195
|
-
raise ValueError(msg)
|
|
196
|
-
|
|
197
|
-
if min_size > max_size:
|
|
198
|
-
msg = f"min_size ({min_size}) cannot be greater than max_size ({max_size})"
|
|
199
|
-
raise ValueError(msg)
|
|
200
|
-
|
|
201
|
-
if max_idle_time is not None and max_idle_time < 0:
|
|
202
|
-
msg = f"max_idle_time must be >= 0, got {max_idle_time}"
|
|
203
|
-
raise ValueError(msg)
|
|
204
|
-
|
|
205
|
-
if max_lifetime is not None and max_lifetime < 0:
|
|
206
|
-
msg = f"max_lifetime must be >= 0, got {max_lifetime}"
|
|
207
|
-
raise ValueError(msg)
|
sqlspec/driver/mixins/_cache.py
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
"""Adapter-level caching mixin for compiled SQL and prepared statements."""
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Any, Optional
|
|
4
|
-
|
|
5
|
-
from sqlspec.statement.cache import SQLCache
|
|
6
|
-
from sqlspec.statement.parameters import ParameterStyle
|
|
7
|
-
|
|
8
|
-
if TYPE_CHECKING:
|
|
9
|
-
from sqlspec.statement.sql import SQL
|
|
10
|
-
|
|
11
|
-
__all__ = ("AsyncAdapterCacheMixin", "SyncAdapterCacheMixin")
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class SyncAdapterCacheMixin:
|
|
15
|
-
"""Mixin for adapter-level SQL compilation caching.
|
|
16
|
-
|
|
17
|
-
This mixin provides:
|
|
18
|
-
- Compiled SQL caching to avoid repeated compilation
|
|
19
|
-
- Parameter style conversion caching
|
|
20
|
-
- Prepared statement name management (for supported databases)
|
|
21
|
-
|
|
22
|
-
Integrates transparently with existing adapter execution flow.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
26
|
-
"""Initialize adapter with caching support."""
|
|
27
|
-
super().__init__(*args, **kwargs)
|
|
28
|
-
|
|
29
|
-
# Get cache configuration from config or use defaults
|
|
30
|
-
config = getattr(self, "config", None)
|
|
31
|
-
cache_size = getattr(config, "adapter_cache_size", 500) if config else 500
|
|
32
|
-
enable_cache = getattr(config, "enable_adapter_cache", True) if config else True
|
|
33
|
-
|
|
34
|
-
# Initialize caches
|
|
35
|
-
self._compiled_cache: Optional[SQLCache] = SQLCache(max_size=cache_size) if enable_cache else None
|
|
36
|
-
self._prepared_statements: dict[str, str] = {}
|
|
37
|
-
self._prepared_counter = 0
|
|
38
|
-
|
|
39
|
-
def _get_compiled_sql(self, statement: "SQL", target_style: ParameterStyle) -> tuple[str, Any]:
|
|
40
|
-
"""Get compiled SQL with caching.
|
|
41
|
-
|
|
42
|
-
Args:
|
|
43
|
-
statement: SQL statement to compile
|
|
44
|
-
target_style: Target parameter style for compilation
|
|
45
|
-
|
|
46
|
-
Returns:
|
|
47
|
-
Tuple of (compiled_sql, parameters)
|
|
48
|
-
"""
|
|
49
|
-
if self._compiled_cache is None:
|
|
50
|
-
# Caching disabled
|
|
51
|
-
return statement.compile(placeholder_style=target_style)
|
|
52
|
-
|
|
53
|
-
# Generate cache key
|
|
54
|
-
cache_key = self._adapter_cache_key(statement, target_style)
|
|
55
|
-
|
|
56
|
-
# Check cache
|
|
57
|
-
cached = self._compiled_cache.get(cache_key)
|
|
58
|
-
if cached is not None:
|
|
59
|
-
return cached # type: ignore[no-any-return]
|
|
60
|
-
|
|
61
|
-
# Compile and cache
|
|
62
|
-
result = statement.compile(placeholder_style=target_style)
|
|
63
|
-
self._compiled_cache.set(cache_key, result)
|
|
64
|
-
return result
|
|
65
|
-
|
|
66
|
-
def _adapter_cache_key(self, statement: "SQL", style: ParameterStyle) -> str:
|
|
67
|
-
"""Generate adapter-specific cache key.
|
|
68
|
-
|
|
69
|
-
Args:
|
|
70
|
-
statement: SQL statement
|
|
71
|
-
style: Parameter style
|
|
72
|
-
|
|
73
|
-
Returns:
|
|
74
|
-
Cache key string
|
|
75
|
-
"""
|
|
76
|
-
# Use statement's internal cache key which includes SQL hash, params, and dialect
|
|
77
|
-
base_key = statement._cache_key()
|
|
78
|
-
# Add adapter-specific context
|
|
79
|
-
return f"{self.__class__.__name__}:{style.value}:{base_key}"
|
|
80
|
-
|
|
81
|
-
def _get_or_create_prepared_statement_name(self, sql_hash: str) -> str:
|
|
82
|
-
"""Get or create a prepared statement name for the given SQL.
|
|
83
|
-
|
|
84
|
-
Used by PostgreSQL and other databases that support prepared statements.
|
|
85
|
-
|
|
86
|
-
Args:
|
|
87
|
-
sql_hash: Hash of the SQL statement
|
|
88
|
-
|
|
89
|
-
Returns:
|
|
90
|
-
Prepared statement name
|
|
91
|
-
"""
|
|
92
|
-
if sql_hash in self._prepared_statements:
|
|
93
|
-
return self._prepared_statements[sql_hash]
|
|
94
|
-
|
|
95
|
-
# Create new prepared statement name
|
|
96
|
-
self._prepared_counter += 1
|
|
97
|
-
stmt_name = f"sqlspec_ps_{self._prepared_counter}"
|
|
98
|
-
self._prepared_statements[sql_hash] = stmt_name
|
|
99
|
-
return stmt_name
|
|
100
|
-
|
|
101
|
-
def _clear_adapter_cache(self) -> None:
|
|
102
|
-
"""Clear all adapter-level caches."""
|
|
103
|
-
if self._compiled_cache is not None:
|
|
104
|
-
self._compiled_cache.clear()
|
|
105
|
-
self._prepared_statements.clear()
|
|
106
|
-
self._prepared_counter = 0
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
class AsyncAdapterCacheMixin(SyncAdapterCacheMixin):
|
|
110
|
-
"""Async version of AdapterCacheMixin.
|
|
111
|
-
|
|
112
|
-
Identical to AdapterCacheMixin since caching operations are synchronous.
|
|
113
|
-
Provided for naming consistency with async adapters.
|
|
114
|
-
"""
|