sqlspec 0.26.0__py3-none-any.whl → 0.28.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 +7 -15
- sqlspec/_serialization.py +55 -25
- sqlspec/_typing.py +155 -52
- sqlspec/adapters/adbc/_types.py +1 -1
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +880 -0
- sqlspec/adapters/adbc/config.py +62 -12
- sqlspec/adapters/adbc/data_dictionary.py +74 -2
- sqlspec/adapters/adbc/driver.py +226 -58
- sqlspec/adapters/adbc/litestar/__init__.py +5 -0
- sqlspec/adapters/adbc/litestar/store.py +504 -0
- sqlspec/adapters/adbc/type_converter.py +44 -50
- sqlspec/adapters/aiosqlite/_types.py +1 -1
- sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/adk/store.py +536 -0
- sqlspec/adapters/aiosqlite/config.py +86 -16
- sqlspec/adapters/aiosqlite/data_dictionary.py +34 -2
- sqlspec/adapters/aiosqlite/driver.py +127 -38
- sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/litestar/store.py +281 -0
- sqlspec/adapters/aiosqlite/pool.py +7 -7
- sqlspec/adapters/asyncmy/__init__.py +7 -1
- sqlspec/adapters/asyncmy/_types.py +1 -1
- sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
- sqlspec/adapters/asyncmy/adk/store.py +503 -0
- sqlspec/adapters/asyncmy/config.py +59 -17
- sqlspec/adapters/asyncmy/data_dictionary.py +41 -2
- sqlspec/adapters/asyncmy/driver.py +293 -62
- sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncmy/litestar/store.py +296 -0
- sqlspec/adapters/asyncpg/__init__.py +2 -1
- sqlspec/adapters/asyncpg/_type_handlers.py +71 -0
- sqlspec/adapters/asyncpg/_types.py +11 -7
- sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
- sqlspec/adapters/asyncpg/adk/store.py +460 -0
- sqlspec/adapters/asyncpg/config.py +57 -36
- sqlspec/adapters/asyncpg/data_dictionary.py +48 -2
- sqlspec/adapters/asyncpg/driver.py +153 -23
- sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncpg/litestar/store.py +253 -0
- sqlspec/adapters/bigquery/_types.py +1 -1
- sqlspec/adapters/bigquery/adk/__init__.py +5 -0
- sqlspec/adapters/bigquery/adk/store.py +585 -0
- sqlspec/adapters/bigquery/config.py +36 -11
- sqlspec/adapters/bigquery/data_dictionary.py +42 -2
- sqlspec/adapters/bigquery/driver.py +489 -144
- sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
- sqlspec/adapters/bigquery/litestar/store.py +327 -0
- sqlspec/adapters/bigquery/type_converter.py +55 -23
- sqlspec/adapters/duckdb/_types.py +2 -2
- sqlspec/adapters/duckdb/adk/__init__.py +14 -0
- sqlspec/adapters/duckdb/adk/store.py +563 -0
- sqlspec/adapters/duckdb/config.py +79 -21
- sqlspec/adapters/duckdb/data_dictionary.py +41 -2
- sqlspec/adapters/duckdb/driver.py +225 -44
- sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
- sqlspec/adapters/duckdb/litestar/store.py +332 -0
- sqlspec/adapters/duckdb/pool.py +5 -5
- sqlspec/adapters/duckdb/type_converter.py +51 -21
- sqlspec/adapters/oracledb/_numpy_handlers.py +133 -0
- sqlspec/adapters/oracledb/_types.py +20 -2
- sqlspec/adapters/oracledb/adk/__init__.py +5 -0
- sqlspec/adapters/oracledb/adk/store.py +1628 -0
- sqlspec/adapters/oracledb/config.py +120 -36
- sqlspec/adapters/oracledb/data_dictionary.py +87 -20
- sqlspec/adapters/oracledb/driver.py +475 -86
- sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
- sqlspec/adapters/oracledb/litestar/store.py +765 -0
- sqlspec/adapters/oracledb/migrations.py +316 -25
- sqlspec/adapters/oracledb/type_converter.py +91 -16
- sqlspec/adapters/psqlpy/_type_handlers.py +44 -0
- sqlspec/adapters/psqlpy/_types.py +2 -1
- sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
- sqlspec/adapters/psqlpy/adk/store.py +483 -0
- sqlspec/adapters/psqlpy/config.py +45 -19
- sqlspec/adapters/psqlpy/data_dictionary.py +48 -2
- sqlspec/adapters/psqlpy/driver.py +108 -41
- sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
- sqlspec/adapters/psqlpy/litestar/store.py +272 -0
- sqlspec/adapters/psqlpy/type_converter.py +40 -11
- sqlspec/adapters/psycopg/_type_handlers.py +80 -0
- sqlspec/adapters/psycopg/_types.py +2 -1
- sqlspec/adapters/psycopg/adk/__init__.py +5 -0
- sqlspec/adapters/psycopg/adk/store.py +962 -0
- sqlspec/adapters/psycopg/config.py +65 -37
- sqlspec/adapters/psycopg/data_dictionary.py +91 -3
- sqlspec/adapters/psycopg/driver.py +200 -78
- sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
- sqlspec/adapters/psycopg/litestar/store.py +554 -0
- sqlspec/adapters/sqlite/__init__.py +2 -1
- sqlspec/adapters/sqlite/_type_handlers.py +86 -0
- sqlspec/adapters/sqlite/_types.py +1 -1
- sqlspec/adapters/sqlite/adk/__init__.py +5 -0
- sqlspec/adapters/sqlite/adk/store.py +582 -0
- sqlspec/adapters/sqlite/config.py +85 -16
- sqlspec/adapters/sqlite/data_dictionary.py +34 -2
- sqlspec/adapters/sqlite/driver.py +120 -52
- sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/sqlite/litestar/store.py +318 -0
- sqlspec/adapters/sqlite/pool.py +5 -5
- sqlspec/base.py +45 -26
- sqlspec/builder/__init__.py +73 -4
- sqlspec/builder/_base.py +91 -58
- sqlspec/builder/_column.py +5 -5
- sqlspec/builder/_ddl.py +98 -89
- sqlspec/builder/_delete.py +5 -4
- sqlspec/builder/_dml.py +388 -0
- sqlspec/{_sql.py → builder/_factory.py} +41 -44
- sqlspec/builder/_insert.py +5 -82
- sqlspec/builder/{mixins/_join_operations.py → _join.py} +145 -143
- sqlspec/builder/_merge.py +446 -11
- sqlspec/builder/_parsing_utils.py +9 -11
- sqlspec/builder/_select.py +1313 -25
- sqlspec/builder/_update.py +11 -42
- sqlspec/cli.py +76 -69
- sqlspec/config.py +331 -62
- sqlspec/core/__init__.py +5 -4
- sqlspec/core/cache.py +18 -18
- sqlspec/core/compiler.py +6 -8
- sqlspec/core/filters.py +55 -47
- sqlspec/core/hashing.py +9 -9
- sqlspec/core/parameters.py +76 -45
- sqlspec/core/result.py +234 -47
- sqlspec/core/splitter.py +16 -17
- sqlspec/core/statement.py +32 -31
- sqlspec/core/type_conversion.py +3 -2
- sqlspec/driver/__init__.py +1 -3
- sqlspec/driver/_async.py +183 -160
- sqlspec/driver/_common.py +197 -109
- sqlspec/driver/_sync.py +189 -161
- sqlspec/driver/mixins/_result_tools.py +20 -236
- sqlspec/driver/mixins/_sql_translator.py +4 -4
- sqlspec/exceptions.py +70 -7
- sqlspec/extensions/adk/__init__.py +53 -0
- sqlspec/extensions/adk/_types.py +51 -0
- sqlspec/extensions/adk/converters.py +172 -0
- sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +144 -0
- sqlspec/extensions/adk/migrations/__init__.py +0 -0
- sqlspec/extensions/adk/service.py +181 -0
- sqlspec/extensions/adk/store.py +536 -0
- sqlspec/extensions/aiosql/adapter.py +69 -61
- sqlspec/extensions/fastapi/__init__.py +21 -0
- sqlspec/extensions/fastapi/extension.py +331 -0
- sqlspec/extensions/fastapi/providers.py +543 -0
- sqlspec/extensions/flask/__init__.py +36 -0
- sqlspec/extensions/flask/_state.py +71 -0
- sqlspec/extensions/flask/_utils.py +40 -0
- sqlspec/extensions/flask/extension.py +389 -0
- sqlspec/extensions/litestar/__init__.py +21 -4
- sqlspec/extensions/litestar/cli.py +54 -10
- sqlspec/extensions/litestar/config.py +56 -266
- sqlspec/extensions/litestar/handlers.py +46 -17
- sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
- sqlspec/extensions/litestar/migrations/__init__.py +3 -0
- sqlspec/extensions/litestar/plugin.py +349 -224
- sqlspec/extensions/litestar/providers.py +25 -25
- sqlspec/extensions/litestar/store.py +265 -0
- sqlspec/extensions/starlette/__init__.py +10 -0
- sqlspec/extensions/starlette/_state.py +25 -0
- sqlspec/extensions/starlette/_utils.py +52 -0
- sqlspec/extensions/starlette/extension.py +254 -0
- sqlspec/extensions/starlette/middleware.py +154 -0
- sqlspec/loader.py +30 -49
- sqlspec/migrations/base.py +200 -76
- sqlspec/migrations/commands.py +591 -62
- sqlspec/migrations/context.py +6 -9
- sqlspec/migrations/fix.py +199 -0
- sqlspec/migrations/loaders.py +47 -19
- sqlspec/migrations/runner.py +241 -75
- sqlspec/migrations/tracker.py +237 -21
- sqlspec/migrations/utils.py +51 -3
- sqlspec/migrations/validation.py +177 -0
- sqlspec/protocols.py +106 -36
- sqlspec/storage/_utils.py +85 -0
- sqlspec/storage/backends/fsspec.py +133 -107
- sqlspec/storage/backends/local.py +78 -51
- sqlspec/storage/backends/obstore.py +276 -168
- sqlspec/storage/registry.py +75 -39
- sqlspec/typing.py +30 -84
- sqlspec/utils/__init__.py +25 -4
- sqlspec/utils/arrow_helpers.py +81 -0
- sqlspec/utils/config_resolver.py +6 -6
- sqlspec/utils/correlation.py +4 -5
- sqlspec/utils/data_transformation.py +3 -2
- sqlspec/utils/deprecation.py +9 -8
- sqlspec/utils/fixtures.py +4 -4
- sqlspec/utils/logging.py +46 -6
- sqlspec/utils/module_loader.py +205 -5
- sqlspec/utils/portal.py +311 -0
- sqlspec/utils/schema.py +288 -0
- sqlspec/utils/serializers.py +113 -4
- sqlspec/utils/sync_tools.py +36 -22
- sqlspec/utils/text.py +1 -2
- sqlspec/utils/type_guards.py +136 -20
- sqlspec/utils/version.py +433 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.28.0.dist-info}/METADATA +41 -22
- sqlspec-0.28.0.dist-info/RECORD +221 -0
- sqlspec/builder/mixins/__init__.py +0 -55
- sqlspec/builder/mixins/_cte_and_set_ops.py +0 -253
- sqlspec/builder/mixins/_delete_operations.py +0 -50
- sqlspec/builder/mixins/_insert_operations.py +0 -282
- sqlspec/builder/mixins/_merge_operations.py +0 -698
- sqlspec/builder/mixins/_order_limit_operations.py +0 -145
- sqlspec/builder/mixins/_pivot_operations.py +0 -157
- sqlspec/builder/mixins/_select_operations.py +0 -930
- sqlspec/builder/mixins/_update_operations.py +0 -199
- sqlspec/builder/mixins/_where_clause.py +0 -1298
- sqlspec-0.26.0.dist-info/RECORD +0 -157
- sqlspec-0.26.0.dist-info/licenses/NOTICE +0 -29
- {sqlspec-0.26.0.dist-info → sqlspec-0.28.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.28.0.dist-info}/entry_points.txt +0 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.28.0.dist-info}/licenses/LICENSE +0 -0
sqlspec/core/parameters.py
CHANGED
|
@@ -20,12 +20,13 @@ Processing:
|
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
import re
|
|
23
|
-
from collections
|
|
23
|
+
from collections import OrderedDict
|
|
24
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
24
25
|
from datetime import date, datetime
|
|
25
26
|
from decimal import Decimal
|
|
26
27
|
from enum import Enum
|
|
27
28
|
from functools import singledispatch
|
|
28
|
-
from typing import Any
|
|
29
|
+
from typing import Any
|
|
29
30
|
|
|
30
31
|
from mypy_extensions import mypyc_attr
|
|
31
32
|
|
|
@@ -107,7 +108,7 @@ class TypedParameter:
|
|
|
107
108
|
|
|
108
109
|
__slots__ = ("_hash", "original_type", "semantic_name", "value")
|
|
109
110
|
|
|
110
|
-
def __init__(self, value: Any, original_type:
|
|
111
|
+
def __init__(self, value: Any, original_type: type | None = None, semantic_name: str | None = None) -> None:
|
|
111
112
|
"""Initialize typed parameter wrapper.
|
|
112
113
|
|
|
113
114
|
Args:
|
|
@@ -118,7 +119,7 @@ class TypedParameter:
|
|
|
118
119
|
self.value = value
|
|
119
120
|
self.original_type = original_type or type(value)
|
|
120
121
|
self.semantic_name = semantic_name
|
|
121
|
-
self._hash:
|
|
122
|
+
self._hash: int | None = None
|
|
122
123
|
|
|
123
124
|
def __hash__(self) -> int:
|
|
124
125
|
"""Cached hash value."""
|
|
@@ -144,7 +145,7 @@ class TypedParameter:
|
|
|
144
145
|
|
|
145
146
|
|
|
146
147
|
@singledispatch
|
|
147
|
-
def _wrap_parameter_by_type(value: Any, semantic_name:
|
|
148
|
+
def _wrap_parameter_by_type(value: Any, semantic_name: str | None = None) -> Any:
|
|
148
149
|
"""Type-specific parameter wrapping using singledispatch.
|
|
149
150
|
|
|
150
151
|
Args:
|
|
@@ -158,31 +159,31 @@ def _wrap_parameter_by_type(value: Any, semantic_name: Optional[str] = None) ->
|
|
|
158
159
|
|
|
159
160
|
|
|
160
161
|
@_wrap_parameter_by_type.register
|
|
161
|
-
def _(value: bool, semantic_name:
|
|
162
|
+
def _(value: bool, semantic_name: str | None = None) -> TypedParameter:
|
|
162
163
|
"""Wrap boolean values to prevent SQLGlot parsing issues."""
|
|
163
164
|
return TypedParameter(value, bool, semantic_name)
|
|
164
165
|
|
|
165
166
|
|
|
166
167
|
@_wrap_parameter_by_type.register
|
|
167
|
-
def _(value: Decimal, semantic_name:
|
|
168
|
+
def _(value: Decimal, semantic_name: str | None = None) -> TypedParameter:
|
|
168
169
|
"""Wrap Decimal values to preserve precision."""
|
|
169
170
|
return TypedParameter(value, Decimal, semantic_name)
|
|
170
171
|
|
|
171
172
|
|
|
172
173
|
@_wrap_parameter_by_type.register
|
|
173
|
-
def _(value: datetime, semantic_name:
|
|
174
|
+
def _(value: datetime, semantic_name: str | None = None) -> TypedParameter:
|
|
174
175
|
"""Wrap datetime values for database-specific formatting."""
|
|
175
176
|
return TypedParameter(value, datetime, semantic_name)
|
|
176
177
|
|
|
177
178
|
|
|
178
179
|
@_wrap_parameter_by_type.register
|
|
179
|
-
def _(value: date, semantic_name:
|
|
180
|
+
def _(value: date, semantic_name: str | None = None) -> TypedParameter:
|
|
180
181
|
"""Wrap date values for database-specific formatting."""
|
|
181
182
|
return TypedParameter(value, date, semantic_name)
|
|
182
183
|
|
|
183
184
|
|
|
184
185
|
@_wrap_parameter_by_type.register
|
|
185
|
-
def _(value: bytes, semantic_name:
|
|
186
|
+
def _(value: bytes, semantic_name: str | None = None) -> TypedParameter:
|
|
186
187
|
"""Wrap bytes values to prevent string conversion issues in ADBC/Arrow."""
|
|
187
188
|
return TypedParameter(value, bytes, semantic_name)
|
|
188
189
|
|
|
@@ -204,7 +205,7 @@ class ParameterInfo:
|
|
|
204
205
|
__slots__ = ("name", "ordinal", "placeholder_text", "position", "style")
|
|
205
206
|
|
|
206
207
|
def __init__(
|
|
207
|
-
self, name:
|
|
208
|
+
self, name: str | None, style: ParameterStyle, position: int, ordinal: int, placeholder_text: str
|
|
208
209
|
) -> None:
|
|
209
210
|
"""Initialize parameter information.
|
|
210
211
|
|
|
@@ -234,17 +235,8 @@ class ParameterInfo:
|
|
|
234
235
|
class ParameterStyleConfig:
|
|
235
236
|
"""Configuration for parameter style processing.
|
|
236
237
|
|
|
237
|
-
Provides configuration for parameter processing operations
|
|
238
|
-
|
|
239
|
-
Attributes:
|
|
240
|
-
default_parameter_style: Primary parsing style
|
|
241
|
-
supported_parameter_styles: All input styles supported
|
|
242
|
-
supported_execution_parameter_styles: Styles driver can execute
|
|
243
|
-
default_execution_parameter_style: Target execution format
|
|
244
|
-
type_coercion_map: Type conversions
|
|
245
|
-
output_transformer: Final SQL/parameter transformation hook
|
|
246
|
-
preserve_parameter_format: Maintain original parameter structure
|
|
247
|
-
needs_static_script_compilation: Embed parameters in SQL
|
|
238
|
+
Provides configuration for parameter processing operations including
|
|
239
|
+
style conversion, type coercion, and parameter format preservation.
|
|
248
240
|
"""
|
|
249
241
|
|
|
250
242
|
__slots__ = (
|
|
@@ -265,17 +257,17 @@ class ParameterStyleConfig:
|
|
|
265
257
|
def __init__(
|
|
266
258
|
self,
|
|
267
259
|
default_parameter_style: ParameterStyle,
|
|
268
|
-
supported_parameter_styles:
|
|
269
|
-
supported_execution_parameter_styles:
|
|
270
|
-
default_execution_parameter_style:
|
|
271
|
-
type_coercion_map:
|
|
260
|
+
supported_parameter_styles: set[ParameterStyle] | None = None,
|
|
261
|
+
supported_execution_parameter_styles: set[ParameterStyle] | None = None,
|
|
262
|
+
default_execution_parameter_style: ParameterStyle | None = None,
|
|
263
|
+
type_coercion_map: dict[type, Callable[[Any], Any]] | None = None,
|
|
272
264
|
has_native_list_expansion: bool = False,
|
|
273
265
|
needs_static_script_compilation: bool = False,
|
|
274
266
|
allow_mixed_parameter_styles: bool = False,
|
|
275
267
|
preserve_parameter_format: bool = True,
|
|
276
268
|
preserve_original_params_for_many: bool = False,
|
|
277
|
-
output_transformer:
|
|
278
|
-
ast_transformer:
|
|
269
|
+
output_transformer: Callable[[str, Any], tuple[str, Any]] | None = None,
|
|
270
|
+
ast_transformer: Callable[[Any, Any], tuple[Any, Any]] | None = None,
|
|
279
271
|
) -> None:
|
|
280
272
|
"""Initialize parameter style configuration.
|
|
281
273
|
|
|
@@ -343,13 +335,18 @@ class ParameterValidator:
|
|
|
343
335
|
compatibility with target dialects.
|
|
344
336
|
"""
|
|
345
337
|
|
|
346
|
-
__slots__ = ("_parameter_cache"
|
|
338
|
+
__slots__ = ("_cache_max_size", "_parameter_cache")
|
|
347
339
|
|
|
348
|
-
def __init__(self) -> None:
|
|
349
|
-
"""Initialize validator with
|
|
350
|
-
|
|
340
|
+
def __init__(self, cache_max_size: int = 5000) -> None:
|
|
341
|
+
"""Initialize validator with bounded LRU cache.
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
cache_max_size: Maximum number of SQL strings to cache (default: 5000)
|
|
345
|
+
"""
|
|
346
|
+
self._parameter_cache: OrderedDict[str, list[ParameterInfo]] = OrderedDict()
|
|
347
|
+
self._cache_max_size = cache_max_size
|
|
351
348
|
|
|
352
|
-
def _extract_parameter_style(self, match: "re.Match[str]") -> "tuple[
|
|
349
|
+
def _extract_parameter_style(self, match: "re.Match[str]") -> "tuple[ParameterStyle | None, str | None]":
|
|
353
350
|
"""Extract parameter style and name from regex match.
|
|
354
351
|
|
|
355
352
|
Args:
|
|
@@ -396,8 +393,15 @@ class ParameterValidator:
|
|
|
396
393
|
"""
|
|
397
394
|
cached_result = self._parameter_cache.get(sql)
|
|
398
395
|
if cached_result is not None:
|
|
396
|
+
self._parameter_cache.move_to_end(sql)
|
|
399
397
|
return cached_result
|
|
400
398
|
|
|
399
|
+
if not any(c in sql for c in ("?", "%", ":", "@", "$")):
|
|
400
|
+
if len(self._parameter_cache) >= self._cache_max_size:
|
|
401
|
+
self._parameter_cache.popitem(last=False)
|
|
402
|
+
self._parameter_cache[sql] = []
|
|
403
|
+
return []
|
|
404
|
+
|
|
401
405
|
parameters: list[ParameterInfo] = []
|
|
402
406
|
ordinal = 0
|
|
403
407
|
|
|
@@ -425,10 +429,13 @@ class ParameterValidator:
|
|
|
425
429
|
)
|
|
426
430
|
ordinal += 1
|
|
427
431
|
|
|
432
|
+
if len(self._parameter_cache) >= self._cache_max_size:
|
|
433
|
+
self._parameter_cache.popitem(last=False)
|
|
434
|
+
|
|
428
435
|
self._parameter_cache[sql] = parameters
|
|
429
436
|
return parameters
|
|
430
437
|
|
|
431
|
-
def get_sqlglot_incompatible_styles(self, dialect:
|
|
438
|
+
def get_sqlglot_incompatible_styles(self, dialect: str | None = None) -> "set[ParameterStyle]":
|
|
432
439
|
"""Get parameter styles incompatible with SQLGlot for dialect.
|
|
433
440
|
|
|
434
441
|
Args:
|
|
@@ -491,7 +498,7 @@ class ParameterConverter:
|
|
|
491
498
|
ParameterStyle.POSITIONAL_PYFORMAT: lambda _: "%s",
|
|
492
499
|
}
|
|
493
500
|
|
|
494
|
-
def normalize_sql_for_parsing(self, sql: str, dialect:
|
|
501
|
+
def normalize_sql_for_parsing(self, sql: str, dialect: str | None = None) -> "tuple[str, list[ParameterInfo]]":
|
|
495
502
|
"""Convert SQL to parsable format.
|
|
496
503
|
|
|
497
504
|
Takes raw SQL with potentially incompatible parameter styles and converts
|
|
@@ -1002,13 +1009,37 @@ class ParameterProcessor:
|
|
|
1002
1009
|
target_style = self._determine_target_execution_style(original_styles, config)
|
|
1003
1010
|
return self._converter.convert_placeholder_style(sql, parameters, target_style, is_many)
|
|
1004
1011
|
|
|
1012
|
+
def _generate_processor_cache_key(
|
|
1013
|
+
self, sql: str, parameters: Any, config: ParameterStyleConfig, is_many: bool, dialect: "str | None"
|
|
1014
|
+
) -> str:
|
|
1015
|
+
"""Generate optimized cache key for parameter processing.
|
|
1016
|
+
|
|
1017
|
+
Uses parameter fingerprint (type + structure) instead of repr()
|
|
1018
|
+
for better performance on large parameter sets.
|
|
1019
|
+
|
|
1020
|
+
Args:
|
|
1021
|
+
sql: SQL string
|
|
1022
|
+
parameters: Parameter values
|
|
1023
|
+
config: Parameter style configuration
|
|
1024
|
+
is_many: Whether this is execute_many
|
|
1025
|
+
dialect: SQL dialect
|
|
1026
|
+
|
|
1027
|
+
Returns:
|
|
1028
|
+
Cache key string
|
|
1029
|
+
"""
|
|
1030
|
+
param_fingerprint = (
|
|
1031
|
+
"none"
|
|
1032
|
+
if parameters is None
|
|
1033
|
+
else f"seq_{len(parameters)}_{type(parameters).__name__}"
|
|
1034
|
+
if isinstance(parameters, (list, tuple))
|
|
1035
|
+
else f"map_{len(parameters)}"
|
|
1036
|
+
if isinstance(parameters, dict)
|
|
1037
|
+
else f"scalar_{type(parameters).__name__}"
|
|
1038
|
+
)
|
|
1039
|
+
return f"{sql}:{param_fingerprint}:{config.default_parameter_style}:{is_many}:{dialect}"
|
|
1040
|
+
|
|
1005
1041
|
def process(
|
|
1006
|
-
self,
|
|
1007
|
-
sql: str,
|
|
1008
|
-
parameters: Any,
|
|
1009
|
-
config: ParameterStyleConfig,
|
|
1010
|
-
dialect: Optional[str] = None,
|
|
1011
|
-
is_many: bool = False,
|
|
1042
|
+
self, sql: str, parameters: Any, config: ParameterStyleConfig, dialect: str | None = None, is_many: bool = False
|
|
1012
1043
|
) -> "tuple[str, Any]":
|
|
1013
1044
|
"""Process parameters through the complete pipeline.
|
|
1014
1045
|
|
|
@@ -1029,7 +1060,7 @@ class ParameterProcessor:
|
|
|
1029
1060
|
Returns:
|
|
1030
1061
|
Tuple of (final_sql, execution_parameters)
|
|
1031
1062
|
"""
|
|
1032
|
-
cache_key =
|
|
1063
|
+
cache_key = self._generate_processor_cache_key(sql, parameters, config, is_many, dialect)
|
|
1033
1064
|
if cache_key in self._cache:
|
|
1034
1065
|
return self._cache[cache_key]
|
|
1035
1066
|
|
|
@@ -1082,7 +1113,7 @@ class ParameterProcessor:
|
|
|
1082
1113
|
return processed_sql, processed_parameters
|
|
1083
1114
|
|
|
1084
1115
|
def get_sqlglot_compatible_sql(
|
|
1085
|
-
self, sql: str, parameters: Any, config: ParameterStyleConfig, dialect:
|
|
1116
|
+
self, sql: str, parameters: Any, config: ParameterStyleConfig, dialect: str | None = None
|
|
1086
1117
|
) -> "tuple[str, Any]":
|
|
1087
1118
|
"""Get SQL normalized for parsing only (Phase 1 only).
|
|
1088
1119
|
|
|
@@ -1139,7 +1170,7 @@ class ParameterProcessor:
|
|
|
1139
1170
|
|
|
1140
1171
|
return True
|
|
1141
1172
|
|
|
1142
|
-
def _needs_sqlglot_normalization(self, param_info: "list[ParameterInfo]", dialect:
|
|
1173
|
+
def _needs_sqlglot_normalization(self, param_info: "list[ParameterInfo]", dialect: str | None = None) -> bool:
|
|
1143
1174
|
"""Check if SQLGlot normalization is needed for this SQL."""
|
|
1144
1175
|
incompatible_styles = self._validator.get_sqlglot_incompatible_styles(dialect)
|
|
1145
1176
|
return any(p.style in incompatible_styles for p in param_info)
|
|
@@ -1252,7 +1283,7 @@ def is_iterable_parameters(obj: Any) -> bool:
|
|
|
1252
1283
|
)
|
|
1253
1284
|
|
|
1254
1285
|
|
|
1255
|
-
def wrap_with_type(value: Any, semantic_name:
|
|
1286
|
+
def wrap_with_type(value: Any, semantic_name: str | None = None) -> Any:
|
|
1256
1287
|
"""Public API for type wrapping.
|
|
1257
1288
|
|
|
1258
1289
|
Args:
|