sqlspec 0.25.0__py3-none-any.whl → 0.27.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 +256 -24
- sqlspec/_typing.py +71 -52
- sqlspec/adapters/adbc/_types.py +1 -1
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +870 -0
- sqlspec/adapters/adbc/config.py +69 -12
- sqlspec/adapters/adbc/data_dictionary.py +340 -0
- sqlspec/adapters/adbc/driver.py +266 -58
- sqlspec/adapters/adbc/litestar/__init__.py +5 -0
- sqlspec/adapters/adbc/litestar/store.py +504 -0
- sqlspec/adapters/adbc/type_converter.py +153 -0
- sqlspec/adapters/aiosqlite/_types.py +1 -1
- sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/adk/store.py +527 -0
- sqlspec/adapters/aiosqlite/config.py +88 -15
- sqlspec/adapters/aiosqlite/data_dictionary.py +149 -0
- sqlspec/adapters/aiosqlite/driver.py +143 -40
- 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 +2 -2
- sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
- sqlspec/adapters/asyncmy/adk/store.py +493 -0
- sqlspec/adapters/asyncmy/config.py +68 -23
- sqlspec/adapters/asyncmy/data_dictionary.py +161 -0
- sqlspec/adapters/asyncmy/driver.py +313 -58
- 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 +450 -0
- sqlspec/adapters/asyncpg/config.py +59 -35
- sqlspec/adapters/asyncpg/data_dictionary.py +173 -0
- sqlspec/adapters/asyncpg/driver.py +170 -25
- 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 +576 -0
- sqlspec/adapters/bigquery/config.py +27 -10
- sqlspec/adapters/bigquery/data_dictionary.py +149 -0
- sqlspec/adapters/bigquery/driver.py +368 -142
- sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
- sqlspec/adapters/bigquery/litestar/store.py +327 -0
- sqlspec/adapters/bigquery/type_converter.py +125 -0
- sqlspec/adapters/duckdb/_types.py +1 -1
- sqlspec/adapters/duckdb/adk/__init__.py +14 -0
- sqlspec/adapters/duckdb/adk/store.py +553 -0
- sqlspec/adapters/duckdb/config.py +80 -20
- sqlspec/adapters/duckdb/data_dictionary.py +163 -0
- sqlspec/adapters/duckdb/driver.py +167 -45
- sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
- sqlspec/adapters/duckdb/litestar/store.py +332 -0
- sqlspec/adapters/duckdb/pool.py +4 -4
- sqlspec/adapters/duckdb/type_converter.py +133 -0
- 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 +1745 -0
- sqlspec/adapters/oracledb/config.py +122 -32
- sqlspec/adapters/oracledb/data_dictionary.py +509 -0
- sqlspec/adapters/oracledb/driver.py +353 -91
- sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
- sqlspec/adapters/oracledb/litestar/store.py +767 -0
- sqlspec/adapters/oracledb/migrations.py +348 -73
- sqlspec/adapters/oracledb/type_converter.py +207 -0
- 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 +482 -0
- sqlspec/adapters/psqlpy/config.py +46 -17
- sqlspec/adapters/psqlpy/data_dictionary.py +172 -0
- sqlspec/adapters/psqlpy/driver.py +123 -209
- sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
- sqlspec/adapters/psqlpy/litestar/store.py +272 -0
- sqlspec/adapters/psqlpy/type_converter.py +102 -0
- 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 +944 -0
- sqlspec/adapters/psycopg/config.py +69 -35
- sqlspec/adapters/psycopg/data_dictionary.py +331 -0
- sqlspec/adapters/psycopg/driver.py +238 -81
- 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 +572 -0
- sqlspec/adapters/sqlite/config.py +87 -15
- sqlspec/adapters/sqlite/data_dictionary.py +149 -0
- sqlspec/adapters/sqlite/driver.py +137 -54
- sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/sqlite/litestar/store.py +318 -0
- sqlspec/adapters/sqlite/pool.py +18 -9
- sqlspec/base.py +45 -26
- sqlspec/builder/__init__.py +73 -4
- sqlspec/builder/_base.py +162 -89
- sqlspec/builder/_column.py +62 -29
- sqlspec/builder/_ddl.py +180 -121
- sqlspec/builder/_delete.py +5 -4
- sqlspec/builder/_dml.py +388 -0
- sqlspec/{_sql.py → builder/_factory.py} +53 -94
- sqlspec/builder/_insert.py +32 -131
- sqlspec/builder/_join.py +375 -0
- sqlspec/builder/_merge.py +446 -11
- sqlspec/builder/_parsing_utils.py +111 -17
- sqlspec/builder/_select.py +1457 -24
- sqlspec/builder/_update.py +11 -42
- sqlspec/cli.py +307 -194
- sqlspec/config.py +252 -67
- sqlspec/core/__init__.py +5 -4
- sqlspec/core/cache.py +17 -17
- sqlspec/core/compiler.py +62 -9
- sqlspec/core/filters.py +37 -37
- sqlspec/core/hashing.py +9 -9
- sqlspec/core/parameters.py +83 -48
- sqlspec/core/result.py +102 -46
- sqlspec/core/splitter.py +16 -17
- sqlspec/core/statement.py +36 -30
- sqlspec/core/type_conversion.py +235 -0
- sqlspec/driver/__init__.py +7 -6
- sqlspec/driver/_async.py +188 -151
- sqlspec/driver/_common.py +285 -80
- sqlspec/driver/_sync.py +188 -152
- sqlspec/driver/mixins/_result_tools.py +20 -236
- sqlspec/driver/mixins/_sql_translator.py +4 -4
- sqlspec/exceptions.py +75 -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 +73 -53
- sqlspec/extensions/litestar/__init__.py +21 -4
- sqlspec/extensions/litestar/cli.py +54 -10
- sqlspec/extensions/litestar/config.py +59 -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 +324 -223
- sqlspec/extensions/litestar/providers.py +25 -25
- sqlspec/extensions/litestar/store.py +265 -0
- sqlspec/loader.py +30 -49
- sqlspec/migrations/__init__.py +4 -3
- sqlspec/migrations/base.py +302 -39
- sqlspec/migrations/commands.py +611 -144
- sqlspec/migrations/context.py +142 -0
- sqlspec/migrations/fix.py +199 -0
- sqlspec/migrations/loaders.py +68 -23
- sqlspec/migrations/runner.py +543 -107
- sqlspec/migrations/tracker.py +237 -21
- sqlspec/migrations/utils.py +51 -3
- sqlspec/migrations/validation.py +177 -0
- sqlspec/protocols.py +66 -36
- sqlspec/storage/_utils.py +98 -0
- sqlspec/storage/backends/fsspec.py +134 -106
- sqlspec/storage/backends/local.py +78 -51
- sqlspec/storage/backends/obstore.py +278 -162
- sqlspec/storage/registry.py +75 -39
- sqlspec/typing.py +16 -84
- sqlspec/utils/config_resolver.py +153 -0
- 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 +2 -2
- sqlspec/utils/schema.py +288 -0
- sqlspec/utils/serializers.py +50 -2
- sqlspec/utils/sync_tools.py +21 -17
- sqlspec/utils/text.py +1 -2
- sqlspec/utils/type_guards.py +111 -20
- sqlspec/utils/version.py +433 -0
- {sqlspec-0.25.0.dist-info → sqlspec-0.27.0.dist-info}/METADATA +40 -21
- sqlspec-0.27.0.dist-info/RECORD +207 -0
- sqlspec/builder/mixins/__init__.py +0 -55
- sqlspec/builder/mixins/_cte_and_set_ops.py +0 -254
- sqlspec/builder/mixins/_delete_operations.py +0 -50
- sqlspec/builder/mixins/_insert_operations.py +0 -282
- sqlspec/builder/mixins/_join_operations.py +0 -389
- sqlspec/builder/mixins/_merge_operations.py +0 -592
- sqlspec/builder/mixins/_order_limit_operations.py +0 -152
- sqlspec/builder/mixins/_pivot_operations.py +0 -157
- sqlspec/builder/mixins/_select_operations.py +0 -936
- sqlspec/builder/mixins/_update_operations.py +0 -218
- sqlspec/builder/mixins/_where_clause.py +0 -1304
- sqlspec-0.25.0.dist-info/RECORD +0 -139
- sqlspec-0.25.0.dist-info/licenses/NOTICE +0 -29
- {sqlspec-0.25.0.dist-info → sqlspec-0.27.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.25.0.dist-info → sqlspec-0.27.0.dist-info}/entry_points.txt +0 -0
- {sqlspec-0.25.0.dist-info → sqlspec-0.27.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
|
-
self._parameter_cache: dict[str, list[ParameterInfo]] = {}
|
|
340
|
+
def __init__(self, cache_max_size: int = 5000) -> None:
|
|
341
|
+
"""Initialize validator with bounded LRU cache.
|
|
351
342
|
|
|
352
|
-
|
|
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
|
|
348
|
+
|
|
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
|
|
@@ -619,7 +626,9 @@ class ParameterConverter:
|
|
|
619
626
|
|
|
620
627
|
return converted_sql
|
|
621
628
|
|
|
622
|
-
def _convert_sequence_to_dict(
|
|
629
|
+
def _convert_sequence_to_dict(
|
|
630
|
+
self, parameters: "Sequence[Any]", param_info: "list[ParameterInfo]"
|
|
631
|
+
) -> "dict[str, Any]":
|
|
623
632
|
"""Convert sequence parameters to dictionary for named styles.
|
|
624
633
|
|
|
625
634
|
Args:
|
|
@@ -637,7 +646,7 @@ class ParameterConverter:
|
|
|
637
646
|
return param_dict
|
|
638
647
|
|
|
639
648
|
def _extract_param_value_mixed_styles(
|
|
640
|
-
self, param: ParameterInfo, parameters: Mapping, param_keys: "list[str]"
|
|
649
|
+
self, param: ParameterInfo, parameters: "Mapping[str, Any]", param_keys: "list[str]"
|
|
641
650
|
) -> "tuple[Any, bool]":
|
|
642
651
|
"""Extract parameter value for mixed style parameters.
|
|
643
652
|
|
|
@@ -670,7 +679,9 @@ class ParameterConverter:
|
|
|
670
679
|
|
|
671
680
|
return None, False
|
|
672
681
|
|
|
673
|
-
def _extract_param_value_single_style(
|
|
682
|
+
def _extract_param_value_single_style(
|
|
683
|
+
self, param: ParameterInfo, parameters: "Mapping[str, Any]"
|
|
684
|
+
) -> "tuple[Any, bool]":
|
|
674
685
|
"""Extract parameter value for single style parameters.
|
|
675
686
|
|
|
676
687
|
Args:
|
|
@@ -998,13 +1009,37 @@ class ParameterProcessor:
|
|
|
998
1009
|
target_style = self._determine_target_execution_style(original_styles, config)
|
|
999
1010
|
return self._converter.convert_placeholder_style(sql, parameters, target_style, is_many)
|
|
1000
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
|
+
|
|
1001
1041
|
def process(
|
|
1002
|
-
self,
|
|
1003
|
-
sql: str,
|
|
1004
|
-
parameters: Any,
|
|
1005
|
-
config: ParameterStyleConfig,
|
|
1006
|
-
dialect: Optional[str] = None,
|
|
1007
|
-
is_many: bool = False,
|
|
1042
|
+
self, sql: str, parameters: Any, config: ParameterStyleConfig, dialect: str | None = None, is_many: bool = False
|
|
1008
1043
|
) -> "tuple[str, Any]":
|
|
1009
1044
|
"""Process parameters through the complete pipeline.
|
|
1010
1045
|
|
|
@@ -1025,7 +1060,7 @@ class ParameterProcessor:
|
|
|
1025
1060
|
Returns:
|
|
1026
1061
|
Tuple of (final_sql, execution_parameters)
|
|
1027
1062
|
"""
|
|
1028
|
-
cache_key =
|
|
1063
|
+
cache_key = self._generate_processor_cache_key(sql, parameters, config, is_many, dialect)
|
|
1029
1064
|
if cache_key in self._cache:
|
|
1030
1065
|
return self._cache[cache_key]
|
|
1031
1066
|
|
|
@@ -1078,7 +1113,7 @@ class ParameterProcessor:
|
|
|
1078
1113
|
return processed_sql, processed_parameters
|
|
1079
1114
|
|
|
1080
1115
|
def get_sqlglot_compatible_sql(
|
|
1081
|
-
self, sql: str, parameters: Any, config: ParameterStyleConfig, dialect:
|
|
1116
|
+
self, sql: str, parameters: Any, config: ParameterStyleConfig, dialect: str | None = None
|
|
1082
1117
|
) -> "tuple[str, Any]":
|
|
1083
1118
|
"""Get SQL normalized for parsing only (Phase 1 only).
|
|
1084
1119
|
|
|
@@ -1135,7 +1170,7 @@ class ParameterProcessor:
|
|
|
1135
1170
|
|
|
1136
1171
|
return True
|
|
1137
1172
|
|
|
1138
|
-
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:
|
|
1139
1174
|
"""Check if SQLGlot normalization is needed for this SQL."""
|
|
1140
1175
|
incompatible_styles = self._validator.get_sqlglot_incompatible_styles(dialect)
|
|
1141
1176
|
return any(p.style in incompatible_styles for p in param_info)
|
|
@@ -1248,7 +1283,7 @@ def is_iterable_parameters(obj: Any) -> bool:
|
|
|
1248
1283
|
)
|
|
1249
1284
|
|
|
1250
1285
|
|
|
1251
|
-
def wrap_with_type(value: Any, semantic_name:
|
|
1286
|
+
def wrap_with_type(value: Any, semantic_name: str | None = None) -> Any:
|
|
1252
1287
|
"""Public API for type wrapping.
|
|
1253
1288
|
|
|
1254
1289
|
Args:
|
sqlspec/core/result.py
CHANGED
|
@@ -10,17 +10,19 @@ Classes:
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
from abc import ABC, abstractmethod
|
|
13
|
-
from typing import TYPE_CHECKING, Any, Optional,
|
|
13
|
+
from typing import TYPE_CHECKING, Any, Optional, cast, overload
|
|
14
14
|
|
|
15
15
|
from mypy_extensions import mypyc_attr
|
|
16
16
|
from typing_extensions import TypeVar
|
|
17
17
|
|
|
18
18
|
from sqlspec.core.compiler import OperationType
|
|
19
|
+
from sqlspec.utils.schema import to_schema
|
|
19
20
|
|
|
20
21
|
if TYPE_CHECKING:
|
|
21
22
|
from collections.abc import Iterator
|
|
22
23
|
|
|
23
24
|
from sqlspec.core.statement import SQL
|
|
25
|
+
from sqlspec.typing import SchemaT
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
__all__ = ("ArrowResult", "SQLResult", "StatementResult")
|
|
@@ -52,8 +54,8 @@ class StatementResult(ABC):
|
|
|
52
54
|
statement: "SQL",
|
|
53
55
|
data: Any = None,
|
|
54
56
|
rows_affected: int = 0,
|
|
55
|
-
last_inserted_id:
|
|
56
|
-
execution_time:
|
|
57
|
+
last_inserted_id: int | str | None = None,
|
|
58
|
+
execution_time: float | None = None,
|
|
57
59
|
metadata: Optional["dict[str, Any]"] = None,
|
|
58
60
|
) -> None:
|
|
59
61
|
"""Initialize statement result.
|
|
@@ -129,19 +131,6 @@ class SQLResult(StatementResult):
|
|
|
129
131
|
The operation_type attribute indicates the nature of the operation.
|
|
130
132
|
|
|
131
133
|
For script execution, tracks multiple statement results and errors.
|
|
132
|
-
|
|
133
|
-
Attributes:
|
|
134
|
-
column_names: Names of columns in the result set.
|
|
135
|
-
error: Exception that occurred during execution.
|
|
136
|
-
errors: List of error messages for script execution.
|
|
137
|
-
has_more: Whether there are additional result pages available.
|
|
138
|
-
inserted_ids: List of IDs from INSERT operations.
|
|
139
|
-
operation_index: Index of operation in a script.
|
|
140
|
-
parameters: Parameters used for the query.
|
|
141
|
-
statement_results: Results from individual statements in a script.
|
|
142
|
-
successful_statements: Count of successful statements in a script.
|
|
143
|
-
total_count: Total number of rows in the complete result set.
|
|
144
|
-
total_statements: Total number of statements in a script.
|
|
145
134
|
"""
|
|
146
135
|
|
|
147
136
|
__slots__ = (
|
|
@@ -164,19 +153,19 @@ class SQLResult(StatementResult):
|
|
|
164
153
|
def __init__(
|
|
165
154
|
self,
|
|
166
155
|
statement: "SQL",
|
|
167
|
-
data:
|
|
156
|
+
data: list[dict[str, Any]] | None = None,
|
|
168
157
|
rows_affected: int = 0,
|
|
169
|
-
last_inserted_id:
|
|
170
|
-
execution_time:
|
|
158
|
+
last_inserted_id: int | str | None = None,
|
|
159
|
+
execution_time: float | None = None,
|
|
171
160
|
metadata: Optional["dict[str, Any]"] = None,
|
|
172
|
-
error:
|
|
161
|
+
error: Exception | None = None,
|
|
173
162
|
operation_type: OperationType = "SELECT",
|
|
174
|
-
operation_index:
|
|
175
|
-
parameters:
|
|
163
|
+
operation_index: int | None = None,
|
|
164
|
+
parameters: Any | None = None,
|
|
176
165
|
column_names: Optional["list[str]"] = None,
|
|
177
|
-
total_count:
|
|
166
|
+
total_count: int | None = None,
|
|
178
167
|
has_more: bool = False,
|
|
179
|
-
inserted_ids: Optional["list[
|
|
168
|
+
inserted_ids: Optional["list[int | str]"] = None,
|
|
180
169
|
statement_results: Optional["list[SQLResult]"] = None,
|
|
181
170
|
errors: Optional["list[str]"] = None,
|
|
182
171
|
total_statements: int = 0,
|
|
@@ -280,15 +269,25 @@ class SQLResult(StatementResult):
|
|
|
280
269
|
|
|
281
270
|
return False
|
|
282
271
|
|
|
283
|
-
|
|
272
|
+
@overload
|
|
273
|
+
def get_data(self, *, schema_type: "type[SchemaT]") -> "list[SchemaT]": ...
|
|
274
|
+
|
|
275
|
+
@overload
|
|
276
|
+
def get_data(self, *, schema_type: None = None) -> "list[dict[str, Any]]": ...
|
|
277
|
+
|
|
278
|
+
def get_data(self, *, schema_type: "type[SchemaT] | None" = None) -> "list[SchemaT] | list[dict[str, Any]]":
|
|
284
279
|
"""Get the data from the result.
|
|
285
280
|
|
|
286
281
|
For regular operations, returns the list of rows.
|
|
287
282
|
For script operations, returns a summary dictionary containing
|
|
288
283
|
execution statistics and results.
|
|
289
284
|
|
|
285
|
+
Args:
|
|
286
|
+
schema_type: Optional schema type to transform the data into.
|
|
287
|
+
Supports Pydantic models, dataclasses, msgspec structs, attrs classes, and TypedDict.
|
|
288
|
+
|
|
290
289
|
Returns:
|
|
291
|
-
List of result rows or script summary.
|
|
290
|
+
List of result rows (optionally transformed to schema_type) or script summary.
|
|
292
291
|
"""
|
|
293
292
|
op_type_upper = self.operation_type.upper()
|
|
294
293
|
if op_type_upper == "SCRIPT":
|
|
@@ -303,7 +302,10 @@ class SQLResult(StatementResult):
|
|
|
303
302
|
"total_rows_affected": self.get_total_rows_affected(),
|
|
304
303
|
}
|
|
305
304
|
]
|
|
306
|
-
|
|
305
|
+
data = cast("list[dict[str, Any]]", self.data or [])
|
|
306
|
+
if schema_type:
|
|
307
|
+
return cast("list[SchemaT]", to_schema(data, schema_type=schema_type))
|
|
308
|
+
return data
|
|
307
309
|
|
|
308
310
|
def add_statement_result(self, result: "SQLResult") -> None:
|
|
309
311
|
"""Add a statement result to the script execution results.
|
|
@@ -348,13 +350,28 @@ class SQLResult(StatementResult):
|
|
|
348
350
|
"""
|
|
349
351
|
return len(self.column_names) if self.column_names else 0
|
|
350
352
|
|
|
351
|
-
|
|
353
|
+
@overload
|
|
354
|
+
def get_first(self, *, schema_type: "type[SchemaT]") -> "SchemaT | None": ...
|
|
355
|
+
|
|
356
|
+
@overload
|
|
357
|
+
def get_first(self, *, schema_type: None = None) -> "dict[str, Any] | None": ...
|
|
358
|
+
|
|
359
|
+
def get_first(self, *, schema_type: "type[SchemaT] | None" = None) -> "SchemaT | dict[str, Any] | None":
|
|
352
360
|
"""Get the first row from the result, if any.
|
|
353
361
|
|
|
362
|
+
Args:
|
|
363
|
+
schema_type: Optional schema type to transform the data into.
|
|
364
|
+
Supports Pydantic models, dataclasses, msgspec structs, attrs classes, and TypedDict.
|
|
365
|
+
|
|
354
366
|
Returns:
|
|
355
|
-
First row or None if no data.
|
|
367
|
+
First row (optionally transformed to schema_type) or None if no data.
|
|
356
368
|
"""
|
|
357
|
-
|
|
369
|
+
if not self.data:
|
|
370
|
+
return None
|
|
371
|
+
row = cast("dict[str, Any]", self.data[0])
|
|
372
|
+
if schema_type:
|
|
373
|
+
return to_schema(row, schema_type=schema_type)
|
|
374
|
+
return row
|
|
358
375
|
|
|
359
376
|
def get_count(self) -> int:
|
|
360
377
|
"""Get the number of rows in the current result set (e.g., a page of data).
|
|
@@ -434,19 +451,42 @@ class SQLResult(StatementResult):
|
|
|
434
451
|
"""
|
|
435
452
|
return iter(self.data or [])
|
|
436
453
|
|
|
437
|
-
|
|
454
|
+
@overload
|
|
455
|
+
def all(self, *, schema_type: "type[SchemaT]") -> "list[SchemaT]": ...
|
|
456
|
+
|
|
457
|
+
@overload
|
|
458
|
+
def all(self, *, schema_type: None = None) -> list[dict[str, Any]]: ...
|
|
459
|
+
|
|
460
|
+
def all(self, *, schema_type: "type[SchemaT] | None" = None) -> "list[SchemaT] | list[dict[str, Any]]":
|
|
438
461
|
"""Return all rows as a list.
|
|
439
462
|
|
|
463
|
+
Args:
|
|
464
|
+
schema_type: Optional schema type to transform the data into.
|
|
465
|
+
Supports Pydantic models, dataclasses, msgspec structs, attrs classes, and TypedDict.
|
|
466
|
+
|
|
440
467
|
Returns:
|
|
441
|
-
List of all rows
|
|
468
|
+
List of all rows (optionally transformed to schema_type)
|
|
442
469
|
"""
|
|
443
|
-
|
|
470
|
+
data = cast("list[dict[str, Any]]", self.data or [])
|
|
471
|
+
if schema_type:
|
|
472
|
+
return cast("list[SchemaT]", to_schema(data, schema_type=schema_type))
|
|
473
|
+
return data
|
|
474
|
+
|
|
475
|
+
@overload
|
|
476
|
+
def one(self, *, schema_type: "type[SchemaT]") -> "SchemaT": ...
|
|
477
|
+
|
|
478
|
+
@overload
|
|
479
|
+
def one(self, *, schema_type: None = None) -> "dict[str, Any]": ...
|
|
444
480
|
|
|
445
|
-
def one(self) -> "dict[str, Any]":
|
|
481
|
+
def one(self, *, schema_type: "type[SchemaT] | None" = None) -> "SchemaT | dict[str, Any]":
|
|
446
482
|
"""Return exactly one row.
|
|
447
483
|
|
|
484
|
+
Args:
|
|
485
|
+
schema_type: Optional schema type to transform the data into.
|
|
486
|
+
Supports Pydantic models, dataclasses, msgspec structs, attrs classes, and TypedDict.
|
|
487
|
+
|
|
448
488
|
Returns:
|
|
449
|
-
The single row
|
|
489
|
+
The single row (optionally transformed to schema_type)
|
|
450
490
|
|
|
451
491
|
Raises:
|
|
452
492
|
ValueError: If no results or more than one result
|
|
@@ -463,13 +503,26 @@ class SQLResult(StatementResult):
|
|
|
463
503
|
msg = f"Multiple results found ({data_len}), exactly one row expected"
|
|
464
504
|
raise ValueError(msg)
|
|
465
505
|
|
|
466
|
-
|
|
506
|
+
row = cast("dict[str, Any]", self.data[0])
|
|
507
|
+
if schema_type:
|
|
508
|
+
return to_schema(row, schema_type=schema_type)
|
|
509
|
+
return row
|
|
510
|
+
|
|
511
|
+
@overload
|
|
512
|
+
def one_or_none(self, *, schema_type: "type[SchemaT]") -> "SchemaT | None": ...
|
|
467
513
|
|
|
468
|
-
|
|
514
|
+
@overload
|
|
515
|
+
def one_or_none(self, *, schema_type: None = None) -> "dict[str, Any] | None": ...
|
|
516
|
+
|
|
517
|
+
def one_or_none(self, *, schema_type: "type[SchemaT] | None" = None) -> "SchemaT | dict[str, Any] | None":
|
|
469
518
|
"""Return at most one row.
|
|
470
519
|
|
|
520
|
+
Args:
|
|
521
|
+
schema_type: Optional schema type to transform the data into.
|
|
522
|
+
Supports Pydantic models, dataclasses, msgspec structs, attrs classes, and TypedDict.
|
|
523
|
+
|
|
471
524
|
Returns:
|
|
472
|
-
The single row or None if no results
|
|
525
|
+
The single row (optionally transformed to schema_type) or None if no results
|
|
473
526
|
|
|
474
527
|
Raises:
|
|
475
528
|
ValueError: If more than one result
|
|
@@ -484,7 +537,10 @@ class SQLResult(StatementResult):
|
|
|
484
537
|
msg = f"Multiple results found ({data_len}), at most one row expected"
|
|
485
538
|
raise ValueError(msg)
|
|
486
539
|
|
|
487
|
-
|
|
540
|
+
row = cast("dict[str, Any]", self.data[0])
|
|
541
|
+
if schema_type:
|
|
542
|
+
return to_schema(row, schema_type=schema_type)
|
|
543
|
+
return row
|
|
488
544
|
|
|
489
545
|
def scalar(self) -> Any:
|
|
490
546
|
"""Return the first column of the first row.
|
|
@@ -527,8 +583,8 @@ class ArrowResult(StatementResult):
|
|
|
527
583
|
statement: "SQL",
|
|
528
584
|
data: Any,
|
|
529
585
|
rows_affected: int = 0,
|
|
530
|
-
last_inserted_id:
|
|
531
|
-
execution_time:
|
|
586
|
+
last_inserted_id: int | str | None = None,
|
|
587
|
+
execution_time: float | None = None,
|
|
532
588
|
metadata: Optional["dict[str, Any]"] = None,
|
|
533
589
|
schema: Optional["dict[str, Any]"] = None,
|
|
534
590
|
) -> None:
|
|
@@ -627,10 +683,10 @@ class ArrowResult(StatementResult):
|
|
|
627
683
|
|
|
628
684
|
def create_sql_result(
|
|
629
685
|
statement: "SQL",
|
|
630
|
-
data:
|
|
686
|
+
data: list[dict[str, Any]] | None = None,
|
|
631
687
|
rows_affected: int = 0,
|
|
632
|
-
last_inserted_id:
|
|
633
|
-
execution_time:
|
|
688
|
+
last_inserted_id: int | str | None = None,
|
|
689
|
+
execution_time: float | None = None,
|
|
634
690
|
metadata: Optional["dict[str, Any]"] = None,
|
|
635
691
|
**kwargs: Any,
|
|
636
692
|
) -> SQLResult:
|
|
@@ -663,8 +719,8 @@ def create_arrow_result(
|
|
|
663
719
|
statement: "SQL",
|
|
664
720
|
data: Any,
|
|
665
721
|
rows_affected: int = 0,
|
|
666
|
-
last_inserted_id:
|
|
667
|
-
execution_time:
|
|
722
|
+
last_inserted_id: int | str | None = None,
|
|
723
|
+
execution_time: float | None = None,
|
|
668
724
|
metadata: Optional["dict[str, Any]"] = None,
|
|
669
725
|
schema: Optional["dict[str, Any]"] = None,
|
|
670
726
|
) -> ArrowResult:
|
sqlspec/core/splitter.py
CHANGED
|
@@ -16,13 +16,12 @@ MySQL, SQLite, DuckDB, and BigQuery.
|
|
|
16
16
|
import re
|
|
17
17
|
import threading
|
|
18
18
|
from abc import ABC, abstractmethod
|
|
19
|
-
from collections.abc import Generator
|
|
19
|
+
from collections.abc import Callable, Generator
|
|
20
20
|
from enum import Enum
|
|
21
21
|
from re import Pattern
|
|
22
|
-
from typing import Any,
|
|
22
|
+
from typing import Any, Final, TypeAlias, cast
|
|
23
23
|
|
|
24
24
|
from mypy_extensions import mypyc_attr
|
|
25
|
-
from typing_extensions import TypeAlias
|
|
26
25
|
|
|
27
26
|
from sqlspec.core.cache import CacheKey, UnifiedCache
|
|
28
27
|
from sqlspec.utils.logging import get_logger
|
|
@@ -98,9 +97,9 @@ class Token:
|
|
|
98
97
|
return f"Token({self.type.value}, {self.value!r}, {self.line}:{self.column})"
|
|
99
98
|
|
|
100
99
|
|
|
101
|
-
TokenHandler: TypeAlias = Callable[[str, int, int, int],
|
|
102
|
-
TokenPattern: TypeAlias =
|
|
103
|
-
CompiledTokenPattern: TypeAlias =
|
|
100
|
+
TokenHandler: TypeAlias = Callable[[str, int, int, int], Token | None]
|
|
101
|
+
TokenPattern: TypeAlias = str | TokenHandler
|
|
102
|
+
CompiledTokenPattern: TypeAlias = Pattern[str] | TokenHandler
|
|
104
103
|
|
|
105
104
|
|
|
106
105
|
@mypyc_attr(allow_interpreted_subclasses=False)
|
|
@@ -111,13 +110,13 @@ class DialectConfig(ABC):
|
|
|
111
110
|
|
|
112
111
|
def __init__(self) -> None:
|
|
113
112
|
"""Initialize dialect configuration."""
|
|
114
|
-
self._name:
|
|
115
|
-
self._block_starters:
|
|
116
|
-
self._block_enders:
|
|
117
|
-
self._statement_terminators:
|
|
118
|
-
self._batch_separators:
|
|
119
|
-
self._special_terminators:
|
|
120
|
-
self._max_nesting_depth:
|
|
113
|
+
self._name: str | None = None
|
|
114
|
+
self._block_starters: set[str] | None = None
|
|
115
|
+
self._block_enders: set[str] | None = None
|
|
116
|
+
self._statement_terminators: set[str] | None = None
|
|
117
|
+
self._batch_separators: set[str] | None = None
|
|
118
|
+
self._special_terminators: dict[str, Callable[[list[Token], int], bool]] | None = None
|
|
119
|
+
self._max_nesting_depth: int | None = None
|
|
121
120
|
|
|
122
121
|
@property
|
|
123
122
|
@abstractmethod
|
|
@@ -436,7 +435,7 @@ class PostgreSQLDialectConfig(DialectConfig):
|
|
|
436
435
|
return [(TokenType.STRING_LITERAL, self._handle_dollar_quoted_string)]
|
|
437
436
|
|
|
438
437
|
@staticmethod
|
|
439
|
-
def _handle_dollar_quoted_string(text: str, position: int, line: int, column: int) ->
|
|
438
|
+
def _handle_dollar_quoted_string(text: str, position: int, line: int, column: int) -> Token | None:
|
|
440
439
|
"""Handle PostgreSQL dollar-quoted string literals.
|
|
441
440
|
|
|
442
441
|
Parses dollar-quoted strings in the format $tag$content$tag$
|
|
@@ -613,8 +612,8 @@ class BigQueryDialectConfig(DialectConfig):
|
|
|
613
612
|
return self._statement_terminators
|
|
614
613
|
|
|
615
614
|
|
|
616
|
-
_pattern_cache:
|
|
617
|
-
_result_cache:
|
|
615
|
+
_pattern_cache: UnifiedCache | None = None
|
|
616
|
+
_result_cache: UnifiedCache | None = None
|
|
618
617
|
_cache_lock = threading.Lock()
|
|
619
618
|
|
|
620
619
|
|
|
@@ -878,7 +877,7 @@ class StatementSplitter:
|
|
|
878
877
|
return False
|
|
879
878
|
|
|
880
879
|
|
|
881
|
-
def split_sql_script(script: str, dialect:
|
|
880
|
+
def split_sql_script(script: str, dialect: str | None = None, strip_trailing_terminator: bool = False) -> list[str]:
|
|
882
881
|
"""Split SQL script into individual statements.
|
|
883
882
|
|
|
884
883
|
Args:
|