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/driver/_async.py
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
"""Asynchronous driver protocol implementation."""
|
|
2
2
|
|
|
3
3
|
from abc import abstractmethod
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Final,
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Final, TypeVar, overload
|
|
5
5
|
|
|
6
6
|
from sqlspec.core import SQL, Statement
|
|
7
|
-
from sqlspec.driver._common import
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
from sqlspec.driver._common import (
|
|
8
|
+
CommonDriverAttributesMixin,
|
|
9
|
+
DataDictionaryMixin,
|
|
10
|
+
ExecutionResult,
|
|
11
|
+
VersionInfo,
|
|
12
|
+
handle_single_row_error,
|
|
13
|
+
)
|
|
14
|
+
from sqlspec.driver.mixins import SQLTranslatorMixin
|
|
10
15
|
from sqlspec.utils.logging import get_logger
|
|
11
|
-
from sqlspec.utils.type_guards import is_dict_row, is_indexable_row
|
|
12
16
|
|
|
13
17
|
if TYPE_CHECKING:
|
|
14
18
|
from collections.abc import Sequence
|
|
@@ -16,22 +20,33 @@ if TYPE_CHECKING:
|
|
|
16
20
|
|
|
17
21
|
from sqlspec.builder import QueryBuilder
|
|
18
22
|
from sqlspec.core import SQLResult, StatementConfig, StatementFilter
|
|
19
|
-
from sqlspec.typing import
|
|
23
|
+
from sqlspec.typing import SchemaT, StatementParameters
|
|
20
24
|
|
|
21
25
|
_LOGGER_NAME: Final[str] = "sqlspec"
|
|
22
26
|
logger = get_logger(_LOGGER_NAME)
|
|
23
27
|
|
|
24
|
-
__all__ = ("AsyncDriverAdapterBase",)
|
|
28
|
+
__all__ = ("AsyncDataDictionaryBase", "AsyncDriverAdapterBase", "AsyncDriverT")
|
|
25
29
|
|
|
26
30
|
|
|
27
31
|
EMPTY_FILTERS: Final["list[StatementFilter]"] = []
|
|
28
32
|
|
|
33
|
+
AsyncDriverT = TypeVar("AsyncDriverT", bound="AsyncDriverAdapterBase")
|
|
29
34
|
|
|
30
|
-
|
|
35
|
+
|
|
36
|
+
class AsyncDriverAdapterBase(CommonDriverAttributesMixin, SQLTranslatorMixin):
|
|
31
37
|
"""Base class for asynchronous database drivers."""
|
|
32
38
|
|
|
33
39
|
__slots__ = ()
|
|
34
40
|
|
|
41
|
+
@property
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def data_dictionary(self) -> "AsyncDataDictionaryBase":
|
|
44
|
+
"""Get the data dictionary for this driver.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Data dictionary instance for metadata queries
|
|
48
|
+
"""
|
|
49
|
+
|
|
35
50
|
async def dispatch_statement_execution(self, statement: "SQL", connection: "Any") -> "SQLResult":
|
|
36
51
|
"""Central execution dispatcher using the Template Method Pattern.
|
|
37
52
|
|
|
@@ -85,7 +100,7 @@ class AsyncDriverAdapterBase(CommonDriverAttributesMixin, SQLTranslatorMixin, To
|
|
|
85
100
|
"""Commit the current transaction on the current connection."""
|
|
86
101
|
|
|
87
102
|
@abstractmethod
|
|
88
|
-
async def _try_special_handling(self, cursor: Any, statement: "SQL") -> "
|
|
103
|
+
async def _try_special_handling(self, cursor: Any, statement: "SQL") -> "SQLResult | None":
|
|
89
104
|
"""Hook for database-specific special operations (e.g., PostgreSQL COPY, bulk operations).
|
|
90
105
|
|
|
91
106
|
This method is called first in dispatch_statement_execution() to allow drivers to handle
|
|
@@ -158,10 +173,10 @@ class AsyncDriverAdapterBase(CommonDriverAttributesMixin, SQLTranslatorMixin, To
|
|
|
158
173
|
|
|
159
174
|
async def execute(
|
|
160
175
|
self,
|
|
161
|
-
statement: "
|
|
176
|
+
statement: "SQL | Statement | QueryBuilder",
|
|
162
177
|
/,
|
|
163
|
-
*parameters: "
|
|
164
|
-
statement_config: "
|
|
178
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
179
|
+
statement_config: "StatementConfig | None" = None,
|
|
165
180
|
**kwargs: Any,
|
|
166
181
|
) -> "SQLResult":
|
|
167
182
|
"""Execute a statement with parameter handling."""
|
|
@@ -172,11 +187,11 @@ class AsyncDriverAdapterBase(CommonDriverAttributesMixin, SQLTranslatorMixin, To
|
|
|
172
187
|
|
|
173
188
|
async def execute_many(
|
|
174
189
|
self,
|
|
175
|
-
statement: "
|
|
190
|
+
statement: "SQL | Statement | QueryBuilder",
|
|
176
191
|
/,
|
|
177
192
|
parameters: "Sequence[StatementParameters]",
|
|
178
|
-
*filters: "
|
|
179
|
-
statement_config: "
|
|
193
|
+
*filters: "StatementParameters | StatementFilter",
|
|
194
|
+
statement_config: "StatementConfig | None" = None,
|
|
180
195
|
**kwargs: Any,
|
|
181
196
|
) -> "SQLResult":
|
|
182
197
|
"""Execute statement multiple times with different parameters.
|
|
@@ -195,10 +210,10 @@ class AsyncDriverAdapterBase(CommonDriverAttributesMixin, SQLTranslatorMixin, To
|
|
|
195
210
|
|
|
196
211
|
async def execute_script(
|
|
197
212
|
self,
|
|
198
|
-
statement: "
|
|
213
|
+
statement: "str | SQL",
|
|
199
214
|
/,
|
|
200
|
-
*parameters: "
|
|
201
|
-
statement_config: "
|
|
215
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
216
|
+
statement_config: "StatementConfig | None" = None,
|
|
202
217
|
**kwargs: Any,
|
|
203
218
|
) -> "SQLResult":
|
|
204
219
|
"""Execute a multi-statement script.
|
|
@@ -214,140 +229,124 @@ class AsyncDriverAdapterBase(CommonDriverAttributesMixin, SQLTranslatorMixin, To
|
|
|
214
229
|
@overload
|
|
215
230
|
async def select_one(
|
|
216
231
|
self,
|
|
217
|
-
statement: "
|
|
232
|
+
statement: "Statement | QueryBuilder",
|
|
218
233
|
/,
|
|
219
|
-
*parameters: "
|
|
220
|
-
schema_type: "type[
|
|
221
|
-
statement_config: "
|
|
234
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
235
|
+
schema_type: "type[SchemaT]",
|
|
236
|
+
statement_config: "StatementConfig | None" = None,
|
|
222
237
|
**kwargs: Any,
|
|
223
|
-
) -> "
|
|
238
|
+
) -> "SchemaT": ...
|
|
224
239
|
|
|
225
240
|
@overload
|
|
226
241
|
async def select_one(
|
|
227
242
|
self,
|
|
228
|
-
statement: "
|
|
243
|
+
statement: "Statement | QueryBuilder",
|
|
229
244
|
/,
|
|
230
|
-
*parameters: "
|
|
245
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
231
246
|
schema_type: None = None,
|
|
232
|
-
statement_config: "
|
|
247
|
+
statement_config: "StatementConfig | None" = None,
|
|
233
248
|
**kwargs: Any,
|
|
234
249
|
) -> "dict[str, Any]": ...
|
|
235
250
|
|
|
236
251
|
async def select_one(
|
|
237
252
|
self,
|
|
238
|
-
statement: "
|
|
253
|
+
statement: "Statement | QueryBuilder",
|
|
239
254
|
/,
|
|
240
|
-
*parameters: "
|
|
241
|
-
schema_type: "
|
|
242
|
-
statement_config: "
|
|
255
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
256
|
+
schema_type: "type[SchemaT] | None" = None,
|
|
257
|
+
statement_config: "StatementConfig | None" = None,
|
|
243
258
|
**kwargs: Any,
|
|
244
|
-
) -> "
|
|
259
|
+
) -> "SchemaT | dict[str, Any]":
|
|
245
260
|
"""Execute a select statement and return exactly one row.
|
|
246
261
|
|
|
247
262
|
Raises an exception if no rows or more than one row is returned.
|
|
248
263
|
"""
|
|
249
264
|
result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if data_len > 1:
|
|
255
|
-
self._raise_expected_one_row(data_len)
|
|
256
|
-
first_row = data[0]
|
|
257
|
-
return self.to_schema(first_row, schema_type=schema_type) if schema_type else first_row
|
|
265
|
+
try:
|
|
266
|
+
return result.one(schema_type=schema_type)
|
|
267
|
+
except ValueError as error:
|
|
268
|
+
handle_single_row_error(error)
|
|
258
269
|
|
|
259
270
|
@overload
|
|
260
271
|
async def select_one_or_none(
|
|
261
272
|
self,
|
|
262
|
-
statement: "
|
|
273
|
+
statement: "Statement | QueryBuilder",
|
|
263
274
|
/,
|
|
264
|
-
*parameters: "
|
|
265
|
-
schema_type: "type[
|
|
266
|
-
statement_config: "
|
|
275
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
276
|
+
schema_type: "type[SchemaT]",
|
|
277
|
+
statement_config: "StatementConfig | None" = None,
|
|
267
278
|
**kwargs: Any,
|
|
268
|
-
) -> "
|
|
279
|
+
) -> "SchemaT | None": ...
|
|
269
280
|
|
|
270
281
|
@overload
|
|
271
282
|
async def select_one_or_none(
|
|
272
283
|
self,
|
|
273
|
-
statement: "
|
|
284
|
+
statement: "Statement | QueryBuilder",
|
|
274
285
|
/,
|
|
275
|
-
*parameters: "
|
|
286
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
276
287
|
schema_type: None = None,
|
|
277
|
-
statement_config: "
|
|
288
|
+
statement_config: "StatementConfig | None" = None,
|
|
278
289
|
**kwargs: Any,
|
|
279
|
-
) -> "
|
|
290
|
+
) -> "dict[str, Any] | None": ...
|
|
280
291
|
|
|
281
292
|
async def select_one_or_none(
|
|
282
293
|
self,
|
|
283
|
-
statement: "
|
|
294
|
+
statement: "Statement | QueryBuilder",
|
|
284
295
|
/,
|
|
285
|
-
*parameters: "
|
|
286
|
-
schema_type: "
|
|
287
|
-
statement_config: "
|
|
296
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
297
|
+
schema_type: "type[SchemaT] | None" = None,
|
|
298
|
+
statement_config: "StatementConfig | None" = None,
|
|
288
299
|
**kwargs: Any,
|
|
289
|
-
) -> "
|
|
300
|
+
) -> "SchemaT | dict[str, Any] | None":
|
|
290
301
|
"""Execute a select statement and return at most one row.
|
|
291
302
|
|
|
292
303
|
Returns None if no rows are found.
|
|
293
304
|
Raises an exception if more than one row is returned.
|
|
294
305
|
"""
|
|
295
306
|
result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
|
|
296
|
-
|
|
297
|
-
data_len: int = len(data)
|
|
298
|
-
if data_len == 0:
|
|
299
|
-
return None
|
|
300
|
-
if data_len > 1:
|
|
301
|
-
self._raise_expected_at_most_one_row(data_len)
|
|
302
|
-
first_row = data[0]
|
|
303
|
-
return cast(
|
|
304
|
-
"Optional[Union[dict[str, Any], ModelDTOT]]",
|
|
305
|
-
self.to_schema(first_row, schema_type=schema_type) if schema_type else first_row,
|
|
306
|
-
)
|
|
307
|
+
return result.one_or_none(schema_type=schema_type)
|
|
307
308
|
|
|
308
309
|
@overload
|
|
309
310
|
async def select(
|
|
310
311
|
self,
|
|
311
|
-
statement: "
|
|
312
|
+
statement: "Statement | QueryBuilder",
|
|
312
313
|
/,
|
|
313
|
-
*parameters: "
|
|
314
|
-
schema_type: "type[
|
|
315
|
-
statement_config: "
|
|
314
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
315
|
+
schema_type: "type[SchemaT]",
|
|
316
|
+
statement_config: "StatementConfig | None" = None,
|
|
316
317
|
**kwargs: Any,
|
|
317
|
-
) -> "list[
|
|
318
|
+
) -> "list[SchemaT]": ...
|
|
318
319
|
|
|
319
320
|
@overload
|
|
320
321
|
async def select(
|
|
321
322
|
self,
|
|
322
|
-
statement: "
|
|
323
|
+
statement: "Statement | QueryBuilder",
|
|
323
324
|
/,
|
|
324
|
-
*parameters: "
|
|
325
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
325
326
|
schema_type: None = None,
|
|
326
|
-
statement_config: "
|
|
327
|
+
statement_config: "StatementConfig | None" = None,
|
|
327
328
|
**kwargs: Any,
|
|
328
329
|
) -> "list[dict[str, Any]]": ...
|
|
329
330
|
|
|
330
331
|
async def select(
|
|
331
332
|
self,
|
|
332
|
-
statement: "
|
|
333
|
+
statement: "Statement | QueryBuilder",
|
|
333
334
|
/,
|
|
334
|
-
*parameters: "
|
|
335
|
-
schema_type: "
|
|
336
|
-
statement_config: "
|
|
335
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
336
|
+
schema_type: "type[SchemaT] | None" = None,
|
|
337
|
+
statement_config: "StatementConfig | None" = None,
|
|
337
338
|
**kwargs: Any,
|
|
338
|
-
) -> "
|
|
339
|
+
) -> "list[SchemaT] | list[dict[str, Any]]":
|
|
339
340
|
"""Execute a select statement and return all rows."""
|
|
340
341
|
result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
|
|
341
|
-
return
|
|
342
|
-
"Union[list[dict[str, Any]], list[ModelDTOT]]", self.to_schema(result.get_data(), schema_type=schema_type)
|
|
343
|
-
)
|
|
342
|
+
return result.get_data(schema_type=schema_type)
|
|
344
343
|
|
|
345
344
|
async def select_value(
|
|
346
345
|
self,
|
|
347
|
-
statement: "
|
|
346
|
+
statement: "Statement | QueryBuilder",
|
|
348
347
|
/,
|
|
349
|
-
*parameters: "
|
|
350
|
-
statement_config: "
|
|
348
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
349
|
+
statement_config: "StatementConfig | None" = None,
|
|
351
350
|
**kwargs: Any,
|
|
352
351
|
) -> Any:
|
|
353
352
|
"""Execute a select statement and return a single scalar value.
|
|
@@ -357,28 +356,16 @@ class AsyncDriverAdapterBase(CommonDriverAttributesMixin, SQLTranslatorMixin, To
|
|
|
357
356
|
"""
|
|
358
357
|
result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
|
|
359
358
|
try:
|
|
360
|
-
|
|
361
|
-
except ValueError as
|
|
362
|
-
|
|
363
|
-
if not row:
|
|
364
|
-
self._raise_no_rows_found()
|
|
365
|
-
if is_dict_row(row):
|
|
366
|
-
if not row:
|
|
367
|
-
self._raise_row_no_columns()
|
|
368
|
-
return next(iter(row.values()))
|
|
369
|
-
if is_indexable_row(row):
|
|
370
|
-
if not row:
|
|
371
|
-
self._raise_row_no_columns()
|
|
372
|
-
return row[0]
|
|
373
|
-
self._raise_unexpected_row_type(type(row))
|
|
374
|
-
return None
|
|
359
|
+
return result.scalar()
|
|
360
|
+
except ValueError as error:
|
|
361
|
+
handle_single_row_error(error)
|
|
375
362
|
|
|
376
363
|
async def select_value_or_none(
|
|
377
364
|
self,
|
|
378
|
-
statement: "
|
|
365
|
+
statement: "Statement | QueryBuilder",
|
|
379
366
|
/,
|
|
380
|
-
*parameters: "
|
|
381
|
-
statement_config: "
|
|
367
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
368
|
+
statement_config: "StatementConfig | None" = None,
|
|
382
369
|
**kwargs: Any,
|
|
383
370
|
) -> Any:
|
|
384
371
|
"""Execute a select statement and return a single scalar value or None.
|
|
@@ -388,53 +375,39 @@ class AsyncDriverAdapterBase(CommonDriverAttributesMixin, SQLTranslatorMixin, To
|
|
|
388
375
|
Raises an exception if more than one row is returned.
|
|
389
376
|
"""
|
|
390
377
|
result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
|
|
391
|
-
|
|
392
|
-
data_len: int = len(data)
|
|
393
|
-
if data_len == 0:
|
|
394
|
-
return None
|
|
395
|
-
if data_len > 1:
|
|
396
|
-
self._raise_expected_at_most_one_row(data_len)
|
|
397
|
-
row = data[0]
|
|
398
|
-
if is_dict_row(row):
|
|
399
|
-
if not row:
|
|
400
|
-
return None
|
|
401
|
-
return next(iter(row.values()))
|
|
402
|
-
if is_indexable_row(row):
|
|
403
|
-
return row[0]
|
|
404
|
-
self._raise_cannot_extract_value_from_row_type(type(row).__name__)
|
|
405
|
-
return None
|
|
378
|
+
return result.scalar_or_none()
|
|
406
379
|
|
|
407
380
|
@overload
|
|
408
381
|
async def select_with_total(
|
|
409
382
|
self,
|
|
410
|
-
statement: "
|
|
383
|
+
statement: "Statement | QueryBuilder",
|
|
411
384
|
/,
|
|
412
|
-
*parameters: "
|
|
413
|
-
schema_type: "type[
|
|
414
|
-
statement_config: "
|
|
385
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
386
|
+
schema_type: "type[SchemaT]",
|
|
387
|
+
statement_config: "StatementConfig | None" = None,
|
|
415
388
|
**kwargs: Any,
|
|
416
|
-
) -> "tuple[list[
|
|
389
|
+
) -> "tuple[list[SchemaT], int]": ...
|
|
417
390
|
|
|
418
391
|
@overload
|
|
419
392
|
async def select_with_total(
|
|
420
393
|
self,
|
|
421
|
-
statement: "
|
|
394
|
+
statement: "Statement | QueryBuilder",
|
|
422
395
|
/,
|
|
423
|
-
*parameters: "
|
|
396
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
424
397
|
schema_type: None = None,
|
|
425
|
-
statement_config: "
|
|
398
|
+
statement_config: "StatementConfig | None" = None,
|
|
426
399
|
**kwargs: Any,
|
|
427
400
|
) -> "tuple[list[dict[str, Any]], int]": ...
|
|
428
401
|
|
|
429
402
|
async def select_with_total(
|
|
430
403
|
self,
|
|
431
|
-
statement: "
|
|
404
|
+
statement: "Statement | QueryBuilder",
|
|
432
405
|
/,
|
|
433
|
-
*parameters: "
|
|
434
|
-
schema_type: "
|
|
435
|
-
statement_config: "
|
|
406
|
+
*parameters: "StatementParameters | StatementFilter",
|
|
407
|
+
schema_type: "type[SchemaT] | None" = None,
|
|
408
|
+
statement_config: "StatementConfig | None" = None,
|
|
436
409
|
**kwargs: Any,
|
|
437
|
-
) -> "tuple[
|
|
410
|
+
) -> "tuple[list[SchemaT] | list[dict[str, Any]], int]":
|
|
438
411
|
"""Execute a select statement and return both the data and total count.
|
|
439
412
|
|
|
440
413
|
This method is designed for pagination scenarios where you need both
|
|
@@ -458,32 +431,96 @@ class AsyncDriverAdapterBase(CommonDriverAttributesMixin, SQLTranslatorMixin, To
|
|
|
458
431
|
count_result = await self.dispatch_statement_execution(self._create_count_query(sql_statement), self.connection)
|
|
459
432
|
select_result = await self.execute(sql_statement)
|
|
460
433
|
|
|
461
|
-
return (
|
|
434
|
+
return (select_result.get_data(schema_type=schema_type), count_result.scalar())
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
class AsyncDataDictionaryBase(DataDictionaryMixin):
|
|
438
|
+
"""Base class for asynchronous data dictionary implementations."""
|
|
439
|
+
|
|
440
|
+
@abstractmethod
|
|
441
|
+
async def get_version(self, driver: "AsyncDriverAdapterBase") -> "VersionInfo | None":
|
|
442
|
+
"""Get database version information.
|
|
443
|
+
|
|
444
|
+
Args:
|
|
445
|
+
driver: Async database driver instance
|
|
462
446
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
447
|
+
Returns:
|
|
448
|
+
Version information or None if detection fails
|
|
449
|
+
"""
|
|
466
450
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
451
|
+
@abstractmethod
|
|
452
|
+
async def get_feature_flag(self, driver: "AsyncDriverAdapterBase", feature: str) -> bool:
|
|
453
|
+
"""Check if database supports a specific feature.
|
|
470
454
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
455
|
+
Args:
|
|
456
|
+
driver: Async database driver instance
|
|
457
|
+
feature: Feature name to check
|
|
474
458
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
459
|
+
Returns:
|
|
460
|
+
True if feature is supported, False otherwise
|
|
461
|
+
"""
|
|
478
462
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
463
|
+
@abstractmethod
|
|
464
|
+
async def get_optimal_type(self, driver: "AsyncDriverAdapterBase", type_category: str) -> str:
|
|
465
|
+
"""Get optimal database type for a category.
|
|
482
466
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
467
|
+
Args:
|
|
468
|
+
driver: Async database driver instance
|
|
469
|
+
type_category: Type category (e.g., 'json', 'uuid', 'boolean')
|
|
486
470
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
471
|
+
Returns:
|
|
472
|
+
Database-specific type name
|
|
473
|
+
"""
|
|
474
|
+
|
|
475
|
+
async def get_tables(self, driver: "AsyncDriverAdapterBase", schema: "str | None" = None) -> "list[str]":
|
|
476
|
+
"""Get list of tables in schema.
|
|
477
|
+
|
|
478
|
+
Args:
|
|
479
|
+
driver: Async database driver instance
|
|
480
|
+
schema: Schema name (None for default)
|
|
481
|
+
|
|
482
|
+
Returns:
|
|
483
|
+
List of table names
|
|
484
|
+
"""
|
|
485
|
+
_ = driver, schema
|
|
486
|
+
return []
|
|
487
|
+
|
|
488
|
+
async def get_columns(
|
|
489
|
+
self, driver: "AsyncDriverAdapterBase", table: str, schema: "str | None" = None
|
|
490
|
+
) -> "list[dict[str, Any]]":
|
|
491
|
+
"""Get column information for a table.
|
|
492
|
+
|
|
493
|
+
Args:
|
|
494
|
+
driver: Async database driver instance
|
|
495
|
+
table: Table name
|
|
496
|
+
schema: Schema name (None for default)
|
|
497
|
+
|
|
498
|
+
Returns:
|
|
499
|
+
List of column metadata dictionaries
|
|
500
|
+
"""
|
|
501
|
+
_ = driver, table, schema
|
|
502
|
+
return []
|
|
503
|
+
|
|
504
|
+
async def get_indexes(
|
|
505
|
+
self, driver: "AsyncDriverAdapterBase", table: str, schema: "str | None" = None
|
|
506
|
+
) -> "list[dict[str, Any]]":
|
|
507
|
+
"""Get index information for a table.
|
|
508
|
+
|
|
509
|
+
Args:
|
|
510
|
+
driver: Async database driver instance
|
|
511
|
+
table: Table name
|
|
512
|
+
schema: Schema name (None for default)
|
|
513
|
+
|
|
514
|
+
Returns:
|
|
515
|
+
List of index metadata dictionaries
|
|
516
|
+
"""
|
|
517
|
+
_ = driver, table, schema
|
|
518
|
+
return []
|
|
519
|
+
|
|
520
|
+
def list_available_features(self) -> "list[str]":
|
|
521
|
+
"""List all features that can be checked via get_feature_flag.
|
|
522
|
+
|
|
523
|
+
Returns:
|
|
524
|
+
List of feature names this data dictionary supports
|
|
525
|
+
"""
|
|
526
|
+
return self.get_default_features()
|