sqlspec 0.13.0__py3-none-any.whl → 0.14.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 +39 -1
- sqlspec/adapters/adbc/config.py +4 -40
- sqlspec/adapters/adbc/driver.py +29 -16
- sqlspec/adapters/aiosqlite/config.py +15 -20
- sqlspec/adapters/aiosqlite/driver.py +36 -18
- sqlspec/adapters/asyncmy/config.py +16 -33
- sqlspec/adapters/asyncmy/driver.py +23 -16
- sqlspec/adapters/asyncpg/config.py +19 -61
- sqlspec/adapters/asyncpg/driver.py +41 -18
- sqlspec/adapters/bigquery/config.py +2 -43
- sqlspec/adapters/bigquery/driver.py +26 -14
- sqlspec/adapters/duckdb/config.py +2 -49
- sqlspec/adapters/duckdb/driver.py +35 -16
- sqlspec/adapters/oracledb/config.py +30 -83
- sqlspec/adapters/oracledb/driver.py +54 -27
- sqlspec/adapters/psqlpy/config.py +17 -57
- sqlspec/adapters/psqlpy/driver.py +28 -8
- sqlspec/adapters/psycopg/config.py +30 -73
- sqlspec/adapters/psycopg/driver.py +69 -24
- sqlspec/adapters/sqlite/config.py +3 -21
- sqlspec/adapters/sqlite/driver.py +50 -26
- sqlspec/cli.py +248 -0
- sqlspec/config.py +18 -20
- sqlspec/driver/_async.py +28 -10
- sqlspec/driver/_common.py +5 -4
- sqlspec/driver/_sync.py +28 -10
- sqlspec/driver/mixins/__init__.py +6 -0
- sqlspec/driver/mixins/_cache.py +114 -0
- sqlspec/driver/mixins/_pipeline.py +0 -4
- sqlspec/{service/base.py → driver/mixins/_query_tools.py} +86 -421
- sqlspec/driver/mixins/_result_utils.py +0 -2
- sqlspec/driver/mixins/_sql_translator.py +0 -2
- sqlspec/driver/mixins/_storage.py +4 -18
- sqlspec/driver/mixins/_type_coercion.py +0 -2
- sqlspec/driver/parameters.py +4 -4
- sqlspec/extensions/aiosql/adapter.py +4 -4
- sqlspec/extensions/litestar/__init__.py +2 -1
- sqlspec/extensions/litestar/cli.py +48 -0
- sqlspec/extensions/litestar/plugin.py +3 -0
- sqlspec/loader.py +1 -1
- sqlspec/migrations/__init__.py +23 -0
- sqlspec/migrations/base.py +390 -0
- sqlspec/migrations/commands.py +525 -0
- sqlspec/migrations/runner.py +215 -0
- sqlspec/migrations/tracker.py +153 -0
- sqlspec/migrations/utils.py +89 -0
- sqlspec/protocols.py +37 -3
- sqlspec/statement/builder/__init__.py +8 -8
- sqlspec/statement/builder/{column.py → _column.py} +82 -52
- sqlspec/statement/builder/{ddl.py → _ddl.py} +5 -5
- sqlspec/statement/builder/_ddl_utils.py +1 -1
- sqlspec/statement/builder/{delete.py → _delete.py} +1 -1
- sqlspec/statement/builder/{insert.py → _insert.py} +1 -1
- sqlspec/statement/builder/{merge.py → _merge.py} +1 -1
- sqlspec/statement/builder/_parsing_utils.py +5 -3
- sqlspec/statement/builder/{select.py → _select.py} +59 -61
- sqlspec/statement/builder/{update.py → _update.py} +2 -2
- sqlspec/statement/builder/mixins/__init__.py +24 -30
- sqlspec/statement/builder/mixins/{_set_ops.py → _cte_and_set_ops.py} +86 -2
- sqlspec/statement/builder/mixins/{_delete_from.py → _delete_operations.py} +2 -0
- sqlspec/statement/builder/mixins/{_insert_values.py → _insert_operations.py} +70 -1
- sqlspec/statement/builder/mixins/{_merge_clauses.py → _merge_operations.py} +2 -0
- sqlspec/statement/builder/mixins/_order_limit_operations.py +123 -0
- sqlspec/statement/builder/mixins/{_pivot.py → _pivot_operations.py} +71 -2
- sqlspec/statement/builder/mixins/_select_operations.py +612 -0
- sqlspec/statement/builder/mixins/{_update_set.py → _update_operations.py} +73 -2
- sqlspec/statement/builder/mixins/_where_clause.py +536 -0
- sqlspec/statement/cache.py +50 -0
- sqlspec/statement/filters.py +37 -8
- sqlspec/statement/parameters.py +154 -25
- sqlspec/statement/pipelines/__init__.py +1 -1
- sqlspec/statement/pipelines/context.py +4 -4
- sqlspec/statement/pipelines/transformers/_expression_simplifier.py +3 -3
- sqlspec/statement/pipelines/validators/_parameter_style.py +22 -22
- sqlspec/statement/pipelines/validators/_performance.py +1 -5
- sqlspec/statement/sql.py +246 -176
- sqlspec/utils/__init__.py +2 -1
- sqlspec/utils/statement_hashing.py +203 -0
- sqlspec/utils/type_guards.py +32 -0
- {sqlspec-0.13.0.dist-info → sqlspec-0.14.0.dist-info}/METADATA +1 -1
- sqlspec-0.14.0.dist-info/RECORD +143 -0
- sqlspec-0.14.0.dist-info/entry_points.txt +2 -0
- sqlspec/service/__init__.py +0 -4
- sqlspec/service/_util.py +0 -147
- sqlspec/service/pagination.py +0 -26
- sqlspec/statement/builder/mixins/_aggregate_functions.py +0 -250
- sqlspec/statement/builder/mixins/_case_builder.py +0 -91
- sqlspec/statement/builder/mixins/_common_table_expr.py +0 -90
- sqlspec/statement/builder/mixins/_from.py +0 -63
- sqlspec/statement/builder/mixins/_group_by.py +0 -118
- sqlspec/statement/builder/mixins/_having.py +0 -35
- sqlspec/statement/builder/mixins/_insert_from_select.py +0 -47
- sqlspec/statement/builder/mixins/_insert_into.py +0 -36
- sqlspec/statement/builder/mixins/_limit_offset.py +0 -53
- sqlspec/statement/builder/mixins/_order_by.py +0 -46
- sqlspec/statement/builder/mixins/_returning.py +0 -37
- sqlspec/statement/builder/mixins/_select_columns.py +0 -61
- sqlspec/statement/builder/mixins/_unpivot.py +0 -77
- sqlspec/statement/builder/mixins/_update_from.py +0 -55
- sqlspec/statement/builder/mixins/_update_table.py +0 -29
- sqlspec/statement/builder/mixins/_where.py +0 -401
- sqlspec/statement/builder/mixins/_window_functions.py +0 -86
- sqlspec/statement/parameter_manager.py +0 -220
- sqlspec/statement/sql_compiler.py +0 -140
- sqlspec-0.13.0.dist-info/RECORD +0 -150
- /sqlspec/statement/builder/{base.py → _base.py} +0 -0
- /sqlspec/statement/builder/mixins/{_join.py → _join_operations.py} +0 -0
- {sqlspec-0.13.0.dist-info → sqlspec-0.14.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.13.0.dist-info → sqlspec-0.14.0.dist-info}/licenses/LICENSE +0 -0
- {sqlspec-0.13.0.dist-info → sqlspec-0.14.0.dist-info}/licenses/NOTICE +0 -0
sqlspec/driver/_sync.py
CHANGED
|
@@ -205,17 +205,23 @@ class SyncDriverAdapterProtocol(CommonDriverAttributesMixin[ConnectionT, RowT],
|
|
|
205
205
|
_config: "Optional[SQLConfig]" = None,
|
|
206
206
|
**kwargs: Any,
|
|
207
207
|
) -> "SQLResult[RowT]":
|
|
208
|
-
|
|
208
|
+
"""Execute statement multiple times with different parameters.
|
|
209
209
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
210
|
+
Now passes first parameter set through pipeline to enable
|
|
211
|
+
literal extraction and consistent parameter processing.
|
|
212
|
+
"""
|
|
213
|
+
filters, param_sequence = process_execute_many_parameters(parameters)
|
|
214
|
+
|
|
215
|
+
# Process first parameter set through pipeline for literal extraction
|
|
216
|
+
first_params = param_sequence[0] if param_sequence else None
|
|
215
217
|
|
|
216
|
-
|
|
218
|
+
# Build statement with first params to trigger pipeline processing
|
|
219
|
+
sql_statement = self._build_statement(
|
|
220
|
+
statement, first_params, *filters, _config=_config or self.config, **kwargs
|
|
221
|
+
)
|
|
217
222
|
|
|
218
|
-
|
|
223
|
+
# Mark as many with full sequence
|
|
224
|
+
sql_statement = sql_statement.as_many(param_sequence)
|
|
219
225
|
|
|
220
226
|
return self._execute_statement(statement=sql_statement, connection=self._connection(_connection), **kwargs)
|
|
221
227
|
|
|
@@ -226,12 +232,24 @@ class SyncDriverAdapterProtocol(CommonDriverAttributesMixin[ConnectionT, RowT],
|
|
|
226
232
|
*parameters: "Union[StatementParameters, StatementFilter]",
|
|
227
233
|
_connection: "Optional[ConnectionT]" = None,
|
|
228
234
|
_config: "Optional[SQLConfig]" = None,
|
|
235
|
+
_suppress_warnings: bool = False, # New parameter for migrations
|
|
229
236
|
**kwargs: Any,
|
|
230
237
|
) -> "SQLResult[RowT]":
|
|
238
|
+
"""Execute a multi-statement script.
|
|
239
|
+
|
|
240
|
+
By default, validates each statement and logs warnings for dangerous
|
|
241
|
+
operations. Use _suppress_warnings=True for migrations and admin scripts.
|
|
242
|
+
"""
|
|
231
243
|
script_config = _config or self.config
|
|
232
|
-
|
|
233
|
-
|
|
244
|
+
|
|
245
|
+
# Keep validation enabled by default
|
|
246
|
+
# Validators will log warnings for dangerous operations
|
|
234
247
|
|
|
235
248
|
sql_statement = self._build_statement(statement, *parameters, _config=script_config, **kwargs)
|
|
236
249
|
sql_statement = sql_statement.as_script()
|
|
250
|
+
|
|
251
|
+
# Pass suppress warnings flag to execution
|
|
252
|
+
if _suppress_warnings:
|
|
253
|
+
kwargs["_suppress_warnings"] = True
|
|
254
|
+
|
|
237
255
|
return self._execute_statement(statement=sql_statement, connection=self._connection(_connection), **kwargs)
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
"""Driver mixins for instrumentation, storage, and utilities."""
|
|
2
2
|
|
|
3
|
+
from sqlspec.driver.mixins._cache import AsyncAdapterCacheMixin, SyncAdapterCacheMixin
|
|
3
4
|
from sqlspec.driver.mixins._pipeline import AsyncPipelinedExecutionMixin, SyncPipelinedExecutionMixin
|
|
5
|
+
from sqlspec.driver.mixins._query_tools import AsyncQueryMixin, SyncQueryMixin
|
|
4
6
|
from sqlspec.driver.mixins._result_utils import ToSchemaMixin
|
|
5
7
|
from sqlspec.driver.mixins._sql_translator import SQLTranslatorMixin
|
|
6
8
|
from sqlspec.driver.mixins._storage import AsyncStorageMixin, SyncStorageMixin
|
|
7
9
|
from sqlspec.driver.mixins._type_coercion import TypeCoercionMixin
|
|
8
10
|
|
|
9
11
|
__all__ = (
|
|
12
|
+
"AsyncAdapterCacheMixin",
|
|
10
13
|
"AsyncPipelinedExecutionMixin",
|
|
14
|
+
"AsyncQueryMixin",
|
|
11
15
|
"AsyncStorageMixin",
|
|
12
16
|
"SQLTranslatorMixin",
|
|
17
|
+
"SyncAdapterCacheMixin",
|
|
13
18
|
"SyncPipelinedExecutionMixin",
|
|
19
|
+
"SyncQueryMixin",
|
|
14
20
|
"SyncStorageMixin",
|
|
15
21
|
"ToSchemaMixin",
|
|
16
22
|
"TypeCoercionMixin",
|
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
"""
|
|
@@ -54,8 +54,6 @@ class PipelineOperation:
|
|
|
54
54
|
class SyncPipelinedExecutionMixin:
|
|
55
55
|
"""Mixin providing pipeline execution for sync drivers."""
|
|
56
56
|
|
|
57
|
-
__slots__ = ()
|
|
58
|
-
|
|
59
57
|
def pipeline(
|
|
60
58
|
self,
|
|
61
59
|
*,
|
|
@@ -87,8 +85,6 @@ class SyncPipelinedExecutionMixin:
|
|
|
87
85
|
class AsyncPipelinedExecutionMixin:
|
|
88
86
|
"""Async version of pipeline execution mixin."""
|
|
89
87
|
|
|
90
|
-
__slots__ = ()
|
|
91
|
-
|
|
92
88
|
def pipeline(
|
|
93
89
|
self,
|
|
94
90
|
*,
|