sqlspec 0.16.1__cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.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.
- 51ff5a9eadfdefd49f98__mypyc.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/__init__.py +92 -0
- sqlspec/__main__.py +12 -0
- sqlspec/__metadata__.py +14 -0
- sqlspec/_serialization.py +77 -0
- sqlspec/_sql.py +1780 -0
- sqlspec/_typing.py +680 -0
- sqlspec/adapters/__init__.py +0 -0
- sqlspec/adapters/adbc/__init__.py +5 -0
- sqlspec/adapters/adbc/_types.py +12 -0
- sqlspec/adapters/adbc/config.py +361 -0
- sqlspec/adapters/adbc/driver.py +512 -0
- sqlspec/adapters/aiosqlite/__init__.py +19 -0
- sqlspec/adapters/aiosqlite/_types.py +13 -0
- sqlspec/adapters/aiosqlite/config.py +253 -0
- sqlspec/adapters/aiosqlite/driver.py +248 -0
- sqlspec/adapters/asyncmy/__init__.py +19 -0
- sqlspec/adapters/asyncmy/_types.py +12 -0
- sqlspec/adapters/asyncmy/config.py +180 -0
- sqlspec/adapters/asyncmy/driver.py +274 -0
- sqlspec/adapters/asyncpg/__init__.py +21 -0
- sqlspec/adapters/asyncpg/_types.py +17 -0
- sqlspec/adapters/asyncpg/config.py +229 -0
- sqlspec/adapters/asyncpg/driver.py +344 -0
- sqlspec/adapters/bigquery/__init__.py +18 -0
- sqlspec/adapters/bigquery/_types.py +12 -0
- sqlspec/adapters/bigquery/config.py +298 -0
- sqlspec/adapters/bigquery/driver.py +558 -0
- sqlspec/adapters/duckdb/__init__.py +22 -0
- sqlspec/adapters/duckdb/_types.py +12 -0
- sqlspec/adapters/duckdb/config.py +504 -0
- sqlspec/adapters/duckdb/driver.py +368 -0
- sqlspec/adapters/oracledb/__init__.py +32 -0
- sqlspec/adapters/oracledb/_types.py +14 -0
- sqlspec/adapters/oracledb/config.py +317 -0
- sqlspec/adapters/oracledb/driver.py +538 -0
- sqlspec/adapters/psqlpy/__init__.py +16 -0
- sqlspec/adapters/psqlpy/_types.py +11 -0
- sqlspec/adapters/psqlpy/config.py +214 -0
- sqlspec/adapters/psqlpy/driver.py +530 -0
- sqlspec/adapters/psycopg/__init__.py +32 -0
- sqlspec/adapters/psycopg/_types.py +17 -0
- sqlspec/adapters/psycopg/config.py +426 -0
- sqlspec/adapters/psycopg/driver.py +796 -0
- sqlspec/adapters/sqlite/__init__.py +15 -0
- sqlspec/adapters/sqlite/_types.py +11 -0
- sqlspec/adapters/sqlite/config.py +240 -0
- sqlspec/adapters/sqlite/driver.py +294 -0
- sqlspec/base.py +571 -0
- sqlspec/builder/__init__.py +62 -0
- sqlspec/builder/_base.py +473 -0
- sqlspec/builder/_column.py +320 -0
- sqlspec/builder/_ddl.py +1346 -0
- sqlspec/builder/_ddl_utils.py +103 -0
- sqlspec/builder/_delete.py +76 -0
- sqlspec/builder/_insert.py +256 -0
- sqlspec/builder/_merge.py +71 -0
- sqlspec/builder/_parsing_utils.py +140 -0
- sqlspec/builder/_select.py +170 -0
- sqlspec/builder/_update.py +188 -0
- sqlspec/builder/mixins/__init__.py +55 -0
- sqlspec/builder/mixins/_cte_and_set_ops.py +222 -0
- sqlspec/builder/mixins/_delete_operations.py +41 -0
- sqlspec/builder/mixins/_insert_operations.py +244 -0
- sqlspec/builder/mixins/_join_operations.py +122 -0
- sqlspec/builder/mixins/_merge_operations.py +476 -0
- sqlspec/builder/mixins/_order_limit_operations.py +135 -0
- sqlspec/builder/mixins/_pivot_operations.py +153 -0
- sqlspec/builder/mixins/_select_operations.py +603 -0
- sqlspec/builder/mixins/_update_operations.py +187 -0
- sqlspec/builder/mixins/_where_clause.py +621 -0
- sqlspec/cli.py +247 -0
- sqlspec/config.py +395 -0
- sqlspec/core/__init__.py +63 -0
- sqlspec/core/cache.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/cache.py +871 -0
- sqlspec/core/compiler.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/compiler.py +417 -0
- sqlspec/core/filters.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/filters.py +830 -0
- sqlspec/core/hashing.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/hashing.py +310 -0
- sqlspec/core/parameters.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters.py +1237 -0
- sqlspec/core/result.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/result.py +677 -0
- sqlspec/core/splitter.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/splitter.py +819 -0
- sqlspec/core/statement.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/statement.py +676 -0
- sqlspec/driver/__init__.py +19 -0
- sqlspec/driver/_async.py +502 -0
- sqlspec/driver/_common.py +631 -0
- sqlspec/driver/_sync.py +503 -0
- sqlspec/driver/mixins/__init__.py +6 -0
- sqlspec/driver/mixins/_result_tools.py +193 -0
- sqlspec/driver/mixins/_sql_translator.py +86 -0
- sqlspec/exceptions.py +193 -0
- sqlspec/extensions/__init__.py +0 -0
- sqlspec/extensions/aiosql/__init__.py +10 -0
- sqlspec/extensions/aiosql/adapter.py +461 -0
- sqlspec/extensions/litestar/__init__.py +6 -0
- sqlspec/extensions/litestar/_utils.py +52 -0
- sqlspec/extensions/litestar/cli.py +48 -0
- sqlspec/extensions/litestar/config.py +92 -0
- sqlspec/extensions/litestar/handlers.py +260 -0
- sqlspec/extensions/litestar/plugin.py +145 -0
- sqlspec/extensions/litestar/providers.py +454 -0
- sqlspec/loader.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/loader.py +760 -0
- sqlspec/migrations/__init__.py +35 -0
- sqlspec/migrations/base.py +414 -0
- sqlspec/migrations/commands.py +443 -0
- sqlspec/migrations/loaders.py +402 -0
- sqlspec/migrations/runner.py +213 -0
- sqlspec/migrations/tracker.py +140 -0
- sqlspec/migrations/utils.py +129 -0
- sqlspec/protocols.py +407 -0
- sqlspec/py.typed +0 -0
- sqlspec/storage/__init__.py +23 -0
- sqlspec/storage/backends/__init__.py +0 -0
- sqlspec/storage/backends/base.py +163 -0
- sqlspec/storage/backends/fsspec.py +386 -0
- sqlspec/storage/backends/obstore.py +459 -0
- sqlspec/storage/capabilities.py +102 -0
- sqlspec/storage/registry.py +239 -0
- sqlspec/typing.py +299 -0
- sqlspec/utils/__init__.py +3 -0
- sqlspec/utils/correlation.py +150 -0
- sqlspec/utils/deprecation.py +106 -0
- sqlspec/utils/fixtures.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/fixtures.py +58 -0
- sqlspec/utils/logging.py +127 -0
- sqlspec/utils/module_loader.py +89 -0
- sqlspec/utils/serializers.py +4 -0
- sqlspec/utils/singleton.py +32 -0
- sqlspec/utils/sync_tools.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/sync_tools.py +237 -0
- sqlspec/utils/text.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/text.py +96 -0
- sqlspec/utils/type_guards.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/type_guards.py +1139 -0
- sqlspec-0.16.1.dist-info/METADATA +365 -0
- sqlspec-0.16.1.dist-info/RECORD +148 -0
- sqlspec-0.16.1.dist-info/WHEEL +7 -0
- sqlspec-0.16.1.dist-info/entry_points.txt +2 -0
- sqlspec-0.16.1.dist-info/licenses/LICENSE +21 -0
- sqlspec-0.16.1.dist-info/licenses/NOTICE +29 -0
sqlspec/base.py
ADDED
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import atexit
|
|
3
|
+
from collections.abc import Awaitable, Coroutine
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload
|
|
5
|
+
|
|
6
|
+
from sqlspec.config import (
|
|
7
|
+
AsyncConfigT,
|
|
8
|
+
AsyncDatabaseConfig,
|
|
9
|
+
DatabaseConfigProtocol,
|
|
10
|
+
DriverT,
|
|
11
|
+
NoPoolAsyncConfig,
|
|
12
|
+
NoPoolSyncConfig,
|
|
13
|
+
SyncConfigT,
|
|
14
|
+
SyncDatabaseConfig,
|
|
15
|
+
)
|
|
16
|
+
from sqlspec.core.cache import (
|
|
17
|
+
CacheConfig,
|
|
18
|
+
CacheStatsAggregate,
|
|
19
|
+
get_cache_config,
|
|
20
|
+
get_cache_stats,
|
|
21
|
+
log_cache_stats,
|
|
22
|
+
reset_cache_stats,
|
|
23
|
+
update_cache_config,
|
|
24
|
+
)
|
|
25
|
+
from sqlspec.utils.logging import get_logger
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from contextlib import AbstractAsyncContextManager, AbstractContextManager
|
|
29
|
+
|
|
30
|
+
from sqlspec.typing import ConnectionT, PoolT
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
__all__ = ("SQLSpec",)
|
|
34
|
+
|
|
35
|
+
logger = get_logger()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class SQLSpec:
|
|
39
|
+
"""Configuration manager and registry for database connections and pools."""
|
|
40
|
+
|
|
41
|
+
__slots__ = ("_cleanup_tasks", "_configs", "_instance_cache_config")
|
|
42
|
+
|
|
43
|
+
def __init__(self) -> None:
|
|
44
|
+
self._configs: dict[Any, DatabaseConfigProtocol[Any, Any, Any]] = {}
|
|
45
|
+
atexit.register(self._cleanup_pools)
|
|
46
|
+
self._instance_cache_config: Optional[CacheConfig] = None
|
|
47
|
+
self._cleanup_tasks: list[asyncio.Task[None]] = []
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def _get_config_name(obj: Any) -> str:
|
|
51
|
+
"""Get display name for configuration object."""
|
|
52
|
+
return getattr(obj, "__name__", str(obj))
|
|
53
|
+
|
|
54
|
+
def _cleanup_pools(self) -> None:
|
|
55
|
+
"""Clean up all registered connection pools."""
|
|
56
|
+
cleaned_count = 0
|
|
57
|
+
|
|
58
|
+
for config_type, config in self._configs.items():
|
|
59
|
+
if config.supports_connection_pooling:
|
|
60
|
+
try:
|
|
61
|
+
if config.is_async:
|
|
62
|
+
close_pool_awaitable = config.close_pool()
|
|
63
|
+
if close_pool_awaitable is not None:
|
|
64
|
+
try:
|
|
65
|
+
loop = asyncio.get_running_loop()
|
|
66
|
+
if loop.is_running():
|
|
67
|
+
task = asyncio.create_task(cast("Coroutine[Any, Any, None]", close_pool_awaitable))
|
|
68
|
+
self._cleanup_tasks.append(task)
|
|
69
|
+
else:
|
|
70
|
+
asyncio.run(cast("Coroutine[Any, Any, None]", close_pool_awaitable))
|
|
71
|
+
except RuntimeError:
|
|
72
|
+
asyncio.run(cast("Coroutine[Any, Any, None]", close_pool_awaitable))
|
|
73
|
+
else:
|
|
74
|
+
config.close_pool()
|
|
75
|
+
cleaned_count += 1
|
|
76
|
+
except Exception as e:
|
|
77
|
+
logger.warning("Failed to clean up pool for config %s: %s", config_type.__name__, e)
|
|
78
|
+
|
|
79
|
+
if self._cleanup_tasks:
|
|
80
|
+
try:
|
|
81
|
+
loop = asyncio.get_running_loop()
|
|
82
|
+
if loop.is_running():
|
|
83
|
+
asyncio.gather(*self._cleanup_tasks, return_exceptions=True)
|
|
84
|
+
except RuntimeError:
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
self._configs.clear()
|
|
88
|
+
logger.info("Pool cleanup completed. Cleaned %d pools.", cleaned_count)
|
|
89
|
+
|
|
90
|
+
@overload
|
|
91
|
+
def add_config(self, config: "SyncConfigT") -> "type[SyncConfigT]": # pyright: ignore[reportInvalidTypeVarUse]
|
|
92
|
+
...
|
|
93
|
+
|
|
94
|
+
@overload
|
|
95
|
+
def add_config(self, config: "AsyncConfigT") -> "type[AsyncConfigT]": # pyright: ignore[reportInvalidTypeVarUse]
|
|
96
|
+
...
|
|
97
|
+
|
|
98
|
+
def add_config(self, config: "Union[SyncConfigT, AsyncConfigT]") -> "type[Union[SyncConfigT, AsyncConfigT]]": # pyright: ignore[reportInvalidTypeVarUse]
|
|
99
|
+
"""Add a configuration instance to the registry.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
config: The configuration instance to add.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
The type of the added configuration, annotated with its ID for potential use in type systems.
|
|
106
|
+
"""
|
|
107
|
+
config_type = type(config)
|
|
108
|
+
if config_type in self._configs:
|
|
109
|
+
logger.warning("Configuration for %s already exists. Overwriting.", config_type.__name__)
|
|
110
|
+
self._configs[config_type] = config
|
|
111
|
+
return config_type
|
|
112
|
+
|
|
113
|
+
@overload
|
|
114
|
+
def get_config(self, name: "type[SyncConfigT]") -> "SyncConfigT": ...
|
|
115
|
+
|
|
116
|
+
@overload
|
|
117
|
+
def get_config(self, name: "type[AsyncConfigT]") -> "AsyncConfigT": ...
|
|
118
|
+
|
|
119
|
+
def get_config(
|
|
120
|
+
self, name: "Union[type[DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]], Any]"
|
|
121
|
+
) -> "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]":
|
|
122
|
+
"""Retrieve a configuration instance by its type or a key.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
name: The type of the configuration or a key associated with it.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
The configuration instance.
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
KeyError: If the configuration is not found.
|
|
132
|
+
"""
|
|
133
|
+
config = self._configs.get(name)
|
|
134
|
+
if not config:
|
|
135
|
+
logger.error("No configuration found for %s", name)
|
|
136
|
+
msg = f"No configuration found for {name}"
|
|
137
|
+
raise KeyError(msg)
|
|
138
|
+
|
|
139
|
+
logger.debug("Retrieved configuration: %s", self._get_config_name(name))
|
|
140
|
+
return config
|
|
141
|
+
|
|
142
|
+
@overload
|
|
143
|
+
def get_connection(
|
|
144
|
+
self,
|
|
145
|
+
name: Union[
|
|
146
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
147
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
148
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
149
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
150
|
+
],
|
|
151
|
+
) -> "ConnectionT": ...
|
|
152
|
+
|
|
153
|
+
@overload
|
|
154
|
+
def get_connection(
|
|
155
|
+
self,
|
|
156
|
+
name: Union[
|
|
157
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
158
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
159
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
160
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
161
|
+
],
|
|
162
|
+
) -> "Awaitable[ConnectionT]": ...
|
|
163
|
+
|
|
164
|
+
def get_connection(
|
|
165
|
+
self,
|
|
166
|
+
name: Union[
|
|
167
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
168
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
169
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
170
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
171
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
172
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
173
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
174
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
175
|
+
],
|
|
176
|
+
) -> "Union[ConnectionT, Awaitable[ConnectionT]]":
|
|
177
|
+
"""Get a database connection for the specified configuration.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
name: The configuration name or instance.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
A database connection or an awaitable yielding a connection.
|
|
184
|
+
"""
|
|
185
|
+
if isinstance(name, (NoPoolSyncConfig, NoPoolAsyncConfig, SyncDatabaseConfig, AsyncDatabaseConfig)):
|
|
186
|
+
config = name
|
|
187
|
+
config_name = config.__class__.__name__
|
|
188
|
+
else:
|
|
189
|
+
config = self.get_config(name)
|
|
190
|
+
config_name = self._get_config_name(name)
|
|
191
|
+
|
|
192
|
+
logger.debug("Getting connection for config: %s", config_name, extra={"config_type": config_name})
|
|
193
|
+
return config.create_connection()
|
|
194
|
+
|
|
195
|
+
@overload
|
|
196
|
+
def get_session(
|
|
197
|
+
self,
|
|
198
|
+
name: Union[
|
|
199
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
200
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
201
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
202
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
203
|
+
],
|
|
204
|
+
) -> "DriverT": ...
|
|
205
|
+
|
|
206
|
+
@overload
|
|
207
|
+
def get_session(
|
|
208
|
+
self,
|
|
209
|
+
name: Union[
|
|
210
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
211
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
212
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
213
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
214
|
+
],
|
|
215
|
+
) -> "Awaitable[DriverT]": ...
|
|
216
|
+
|
|
217
|
+
def get_session(
|
|
218
|
+
self,
|
|
219
|
+
name: Union[
|
|
220
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
221
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
222
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
223
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
224
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
225
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
226
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
227
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
228
|
+
],
|
|
229
|
+
) -> "Union[DriverT, Awaitable[DriverT]]":
|
|
230
|
+
"""Get a database session (driver adapter) for the specified configuration.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
name: The configuration name or instance.
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
A driver adapter instance or an awaitable yielding one.
|
|
237
|
+
"""
|
|
238
|
+
if isinstance(name, (NoPoolSyncConfig, NoPoolAsyncConfig, SyncDatabaseConfig, AsyncDatabaseConfig)):
|
|
239
|
+
config = name
|
|
240
|
+
config_name = config.__class__.__name__
|
|
241
|
+
else:
|
|
242
|
+
config = self.get_config(name)
|
|
243
|
+
config_name = self._get_config_name(name)
|
|
244
|
+
|
|
245
|
+
logger.debug("Getting session for config: %s", config_name, extra={"config_type": config_name})
|
|
246
|
+
|
|
247
|
+
connection_obj = self.get_connection(name)
|
|
248
|
+
|
|
249
|
+
if isinstance(connection_obj, Awaitable):
|
|
250
|
+
|
|
251
|
+
async def _create_driver_async() -> "DriverT":
|
|
252
|
+
resolved_connection = await connection_obj # pyright: ignore
|
|
253
|
+
return cast( # pyright: ignore
|
|
254
|
+
"DriverT", config.driver_type(connection=resolved_connection)
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
return _create_driver_async()
|
|
258
|
+
|
|
259
|
+
return cast( # pyright: ignore
|
|
260
|
+
"DriverT", config.driver_type(connection=connection_obj)
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
@overload
|
|
264
|
+
def provide_connection(
|
|
265
|
+
self,
|
|
266
|
+
name: Union[
|
|
267
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
268
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
269
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
270
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
271
|
+
],
|
|
272
|
+
*args: Any,
|
|
273
|
+
**kwargs: Any,
|
|
274
|
+
) -> "AbstractContextManager[ConnectionT]": ...
|
|
275
|
+
|
|
276
|
+
@overload
|
|
277
|
+
def provide_connection(
|
|
278
|
+
self,
|
|
279
|
+
name: Union[
|
|
280
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
281
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
282
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
283
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
284
|
+
],
|
|
285
|
+
*args: Any,
|
|
286
|
+
**kwargs: Any,
|
|
287
|
+
) -> "AbstractAsyncContextManager[ConnectionT]": ...
|
|
288
|
+
|
|
289
|
+
def provide_connection(
|
|
290
|
+
self,
|
|
291
|
+
name: Union[
|
|
292
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
293
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
294
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
295
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
296
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
297
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
298
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
299
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
300
|
+
],
|
|
301
|
+
*args: Any,
|
|
302
|
+
**kwargs: Any,
|
|
303
|
+
) -> "Union[AbstractContextManager[ConnectionT], AbstractAsyncContextManager[ConnectionT]]":
|
|
304
|
+
"""Create and provide a database connection from the specified configuration.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
name: The configuration name or instance.
|
|
308
|
+
*args: Positional arguments to pass to the config's provide_connection.
|
|
309
|
+
**kwargs: Keyword arguments to pass to the config's provide_connection.
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
A sync or async context manager yielding a connection.
|
|
314
|
+
"""
|
|
315
|
+
if isinstance(name, (NoPoolSyncConfig, NoPoolAsyncConfig, SyncDatabaseConfig, AsyncDatabaseConfig)):
|
|
316
|
+
config = name
|
|
317
|
+
config_name = config.__class__.__name__
|
|
318
|
+
else:
|
|
319
|
+
config = self.get_config(name)
|
|
320
|
+
config_name = self._get_config_name(name)
|
|
321
|
+
|
|
322
|
+
logger.debug("Providing connection context for config: %s", config_name, extra={"config_type": config_name})
|
|
323
|
+
return config.provide_connection(*args, **kwargs)
|
|
324
|
+
|
|
325
|
+
@overload
|
|
326
|
+
def provide_session(
|
|
327
|
+
self,
|
|
328
|
+
name: Union[
|
|
329
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
330
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
331
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
332
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
333
|
+
],
|
|
334
|
+
*args: Any,
|
|
335
|
+
**kwargs: Any,
|
|
336
|
+
) -> "AbstractContextManager[DriverT]": ...
|
|
337
|
+
|
|
338
|
+
@overload
|
|
339
|
+
def provide_session(
|
|
340
|
+
self,
|
|
341
|
+
name: Union[
|
|
342
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
343
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
344
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
345
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
346
|
+
],
|
|
347
|
+
*args: Any,
|
|
348
|
+
**kwargs: Any,
|
|
349
|
+
) -> "AbstractAsyncContextManager[DriverT]": ...
|
|
350
|
+
|
|
351
|
+
def provide_session(
|
|
352
|
+
self,
|
|
353
|
+
name: Union[
|
|
354
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
355
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
356
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
357
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
358
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
359
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
360
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
361
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
362
|
+
],
|
|
363
|
+
*args: Any,
|
|
364
|
+
**kwargs: Any,
|
|
365
|
+
) -> "Union[AbstractContextManager[DriverT], AbstractAsyncContextManager[DriverT]]":
|
|
366
|
+
"""Create and provide a database session from the specified configuration.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
name: The configuration name or instance.
|
|
370
|
+
*args: Positional arguments to pass to the config's provide_session.
|
|
371
|
+
**kwargs: Keyword arguments to pass to the config's provide_session.
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
A sync or async context manager yielding a driver adapter instance.
|
|
375
|
+
"""
|
|
376
|
+
if isinstance(name, (NoPoolSyncConfig, NoPoolAsyncConfig, SyncDatabaseConfig, AsyncDatabaseConfig)):
|
|
377
|
+
config = name
|
|
378
|
+
config_name = config.__class__.__name__
|
|
379
|
+
else:
|
|
380
|
+
config = self.get_config(name)
|
|
381
|
+
config_name = self._get_config_name(name)
|
|
382
|
+
|
|
383
|
+
logger.debug("Providing session context for config: %s", config_name, extra={"config_type": config_name})
|
|
384
|
+
return config.provide_session(*args, **kwargs)
|
|
385
|
+
|
|
386
|
+
@overload
|
|
387
|
+
def get_pool(
|
|
388
|
+
self,
|
|
389
|
+
name: "Union[type[Union[NoPoolSyncConfig[ConnectionT, DriverT], NoPoolAsyncConfig[ConnectionT, DriverT]]], NoPoolSyncConfig[ConnectionT, DriverT], NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
390
|
+
) -> "None": ...
|
|
391
|
+
@overload
|
|
392
|
+
def get_pool(
|
|
393
|
+
self,
|
|
394
|
+
name: "Union[type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]], SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
395
|
+
) -> "type[PoolT]": ...
|
|
396
|
+
@overload
|
|
397
|
+
def get_pool(
|
|
398
|
+
self,
|
|
399
|
+
name: "Union[type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]],AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
400
|
+
) -> "Awaitable[type[PoolT]]": ...
|
|
401
|
+
|
|
402
|
+
def get_pool(
|
|
403
|
+
self,
|
|
404
|
+
name: Union[
|
|
405
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
406
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
407
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
408
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
409
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
410
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
411
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
412
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
413
|
+
],
|
|
414
|
+
) -> "Union[type[PoolT], Awaitable[type[PoolT]], None]":
|
|
415
|
+
"""Get the connection pool for the specified configuration.
|
|
416
|
+
|
|
417
|
+
Args:
|
|
418
|
+
name: The configuration name or instance.
|
|
419
|
+
|
|
420
|
+
Returns:
|
|
421
|
+
The connection pool, an awaitable yielding the pool, or None if not supported.
|
|
422
|
+
"""
|
|
423
|
+
config = (
|
|
424
|
+
name
|
|
425
|
+
if isinstance(name, (NoPoolSyncConfig, NoPoolAsyncConfig, SyncDatabaseConfig, AsyncDatabaseConfig))
|
|
426
|
+
else self.get_config(name)
|
|
427
|
+
)
|
|
428
|
+
config_name = config.__class__.__name__
|
|
429
|
+
|
|
430
|
+
if config.supports_connection_pooling:
|
|
431
|
+
logger.debug("Getting pool for config: %s", config_name, extra={"config_type": config_name})
|
|
432
|
+
return cast("Union[type[PoolT], Awaitable[type[PoolT]]]", config.create_pool())
|
|
433
|
+
|
|
434
|
+
logger.debug("Config %s does not support connection pooling", config_name)
|
|
435
|
+
return None
|
|
436
|
+
|
|
437
|
+
@overload
|
|
438
|
+
def close_pool(
|
|
439
|
+
self,
|
|
440
|
+
name: Union[
|
|
441
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
442
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
443
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
444
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
445
|
+
],
|
|
446
|
+
) -> "None": ...
|
|
447
|
+
|
|
448
|
+
@overload
|
|
449
|
+
def close_pool(
|
|
450
|
+
self,
|
|
451
|
+
name: Union[
|
|
452
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
453
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
454
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
455
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
456
|
+
],
|
|
457
|
+
) -> "Awaitable[None]": ...
|
|
458
|
+
|
|
459
|
+
def close_pool(
|
|
460
|
+
self,
|
|
461
|
+
name: Union[
|
|
462
|
+
"type[NoPoolSyncConfig[ConnectionT, DriverT]]",
|
|
463
|
+
"type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
|
|
464
|
+
"type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
465
|
+
"type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
|
|
466
|
+
"NoPoolSyncConfig[ConnectionT, DriverT]",
|
|
467
|
+
"SyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
468
|
+
"NoPoolAsyncConfig[ConnectionT, DriverT]",
|
|
469
|
+
"AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]",
|
|
470
|
+
],
|
|
471
|
+
) -> "Optional[Awaitable[None]]":
|
|
472
|
+
"""Close the connection pool for the specified configuration.
|
|
473
|
+
|
|
474
|
+
Args:
|
|
475
|
+
name: The configuration name or instance.
|
|
476
|
+
|
|
477
|
+
Returns:
|
|
478
|
+
None, or an awaitable if closing an async pool.
|
|
479
|
+
"""
|
|
480
|
+
if isinstance(name, (NoPoolSyncConfig, NoPoolAsyncConfig, SyncDatabaseConfig, AsyncDatabaseConfig)):
|
|
481
|
+
config = name
|
|
482
|
+
config_name = config.__class__.__name__
|
|
483
|
+
else:
|
|
484
|
+
config = self.get_config(name)
|
|
485
|
+
config_name = self._get_config_name(name)
|
|
486
|
+
|
|
487
|
+
if config.supports_connection_pooling:
|
|
488
|
+
logger.debug("Closing pool for config: %s", config_name, extra={"config_type": config_name})
|
|
489
|
+
return config.close_pool()
|
|
490
|
+
|
|
491
|
+
logger.debug("Config %s does not support connection pooling - nothing to close", config_name)
|
|
492
|
+
return None
|
|
493
|
+
|
|
494
|
+
@staticmethod
|
|
495
|
+
def get_cache_config() -> CacheConfig:
|
|
496
|
+
"""Get the current global cache configuration.
|
|
497
|
+
|
|
498
|
+
Returns:
|
|
499
|
+
The current cache configuration.
|
|
500
|
+
"""
|
|
501
|
+
return get_cache_config()
|
|
502
|
+
|
|
503
|
+
@staticmethod
|
|
504
|
+
def update_cache_config(config: CacheConfig) -> None:
|
|
505
|
+
"""Update the global cache configuration.
|
|
506
|
+
|
|
507
|
+
Args:
|
|
508
|
+
config: The new cache configuration to apply.
|
|
509
|
+
"""
|
|
510
|
+
update_cache_config(config)
|
|
511
|
+
|
|
512
|
+
@staticmethod
|
|
513
|
+
def get_cache_stats() -> CacheStatsAggregate:
|
|
514
|
+
"""Get current cache statistics.
|
|
515
|
+
|
|
516
|
+
Returns:
|
|
517
|
+
Cache statistics object with detailed metrics.
|
|
518
|
+
"""
|
|
519
|
+
return get_cache_stats()
|
|
520
|
+
|
|
521
|
+
@staticmethod
|
|
522
|
+
def reset_cache_stats() -> None:
|
|
523
|
+
"""Reset all cache statistics to zero."""
|
|
524
|
+
reset_cache_stats()
|
|
525
|
+
|
|
526
|
+
@staticmethod
|
|
527
|
+
def log_cache_stats() -> None:
|
|
528
|
+
"""Log current cache statistics using the configured logger."""
|
|
529
|
+
log_cache_stats()
|
|
530
|
+
|
|
531
|
+
@staticmethod
|
|
532
|
+
def configure_cache(
|
|
533
|
+
*,
|
|
534
|
+
sql_cache_size: Optional[int] = None,
|
|
535
|
+
fragment_cache_size: Optional[int] = None,
|
|
536
|
+
optimized_cache_size: Optional[int] = None,
|
|
537
|
+
sql_cache_enabled: Optional[bool] = None,
|
|
538
|
+
fragment_cache_enabled: Optional[bool] = None,
|
|
539
|
+
optimized_cache_enabled: Optional[bool] = None,
|
|
540
|
+
) -> None:
|
|
541
|
+
"""Update cache configuration with partial values.
|
|
542
|
+
|
|
543
|
+
Args:
|
|
544
|
+
sql_cache_size: Size of the SQL statement cache
|
|
545
|
+
fragment_cache_size: Size of the AST fragment cache
|
|
546
|
+
optimized_cache_size: Size of the optimized expression cache
|
|
547
|
+
sql_cache_enabled: Enable/disable SQL cache
|
|
548
|
+
fragment_cache_enabled: Enable/disable fragment cache
|
|
549
|
+
optimized_cache_enabled: Enable/disable optimized cache
|
|
550
|
+
"""
|
|
551
|
+
current_config = get_cache_config()
|
|
552
|
+
update_cache_config(
|
|
553
|
+
CacheConfig(
|
|
554
|
+
sql_cache_size=sql_cache_size if sql_cache_size is not None else current_config.sql_cache_size,
|
|
555
|
+
fragment_cache_size=fragment_cache_size
|
|
556
|
+
if fragment_cache_size is not None
|
|
557
|
+
else current_config.fragment_cache_size,
|
|
558
|
+
optimized_cache_size=optimized_cache_size
|
|
559
|
+
if optimized_cache_size is not None
|
|
560
|
+
else current_config.optimized_cache_size,
|
|
561
|
+
sql_cache_enabled=sql_cache_enabled
|
|
562
|
+
if sql_cache_enabled is not None
|
|
563
|
+
else current_config.sql_cache_enabled,
|
|
564
|
+
fragment_cache_enabled=fragment_cache_enabled
|
|
565
|
+
if fragment_cache_enabled is not None
|
|
566
|
+
else current_config.fragment_cache_enabled,
|
|
567
|
+
optimized_cache_enabled=optimized_cache_enabled
|
|
568
|
+
if optimized_cache_enabled is not None
|
|
569
|
+
else current_config.optimized_cache_enabled,
|
|
570
|
+
)
|
|
571
|
+
)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""SQL query builders for safe SQL construction.
|
|
2
|
+
|
|
3
|
+
This package provides fluent interfaces for building SQL queries with automatic
|
|
4
|
+
parameter binding and validation.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from sqlspec.builder._base import QueryBuilder, SafeQuery
|
|
8
|
+
from sqlspec.builder._column import Column, ColumnExpression, FunctionColumn
|
|
9
|
+
from sqlspec.builder._ddl import (
|
|
10
|
+
AlterTable,
|
|
11
|
+
CommentOn,
|
|
12
|
+
CreateIndex,
|
|
13
|
+
CreateMaterializedView,
|
|
14
|
+
CreateSchema,
|
|
15
|
+
CreateTable,
|
|
16
|
+
CreateTableAsSelect,
|
|
17
|
+
CreateView,
|
|
18
|
+
DDLBuilder,
|
|
19
|
+
DropIndex,
|
|
20
|
+
DropSchema,
|
|
21
|
+
DropTable,
|
|
22
|
+
DropView,
|
|
23
|
+
RenameTable,
|
|
24
|
+
Truncate,
|
|
25
|
+
)
|
|
26
|
+
from sqlspec.builder._delete import Delete
|
|
27
|
+
from sqlspec.builder._insert import Insert
|
|
28
|
+
from sqlspec.builder._merge import Merge
|
|
29
|
+
from sqlspec.builder._select import Select
|
|
30
|
+
from sqlspec.builder._update import Update
|
|
31
|
+
from sqlspec.builder.mixins import WhereClauseMixin
|
|
32
|
+
from sqlspec.exceptions import SQLBuilderError
|
|
33
|
+
|
|
34
|
+
__all__ = (
|
|
35
|
+
"AlterTable",
|
|
36
|
+
"Column",
|
|
37
|
+
"ColumnExpression",
|
|
38
|
+
"CommentOn",
|
|
39
|
+
"CreateIndex",
|
|
40
|
+
"CreateMaterializedView",
|
|
41
|
+
"CreateSchema",
|
|
42
|
+
"CreateTable",
|
|
43
|
+
"CreateTableAsSelect",
|
|
44
|
+
"CreateView",
|
|
45
|
+
"DDLBuilder",
|
|
46
|
+
"Delete",
|
|
47
|
+
"DropIndex",
|
|
48
|
+
"DropSchema",
|
|
49
|
+
"DropTable",
|
|
50
|
+
"DropView",
|
|
51
|
+
"FunctionColumn",
|
|
52
|
+
"Insert",
|
|
53
|
+
"Merge",
|
|
54
|
+
"QueryBuilder",
|
|
55
|
+
"RenameTable",
|
|
56
|
+
"SQLBuilderError",
|
|
57
|
+
"SafeQuery",
|
|
58
|
+
"Select",
|
|
59
|
+
"Truncate",
|
|
60
|
+
"Update",
|
|
61
|
+
"WhereClauseMixin",
|
|
62
|
+
)
|