sqlspec 0.14.1__py3-none-any.whl → 0.16.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 +50 -25
- sqlspec/__main__.py +1 -1
- sqlspec/__metadata__.py +1 -3
- sqlspec/_serialization.py +1 -2
- sqlspec/_sql.py +480 -121
- sqlspec/_typing.py +278 -142
- sqlspec/adapters/adbc/__init__.py +4 -3
- sqlspec/adapters/adbc/_types.py +12 -0
- sqlspec/adapters/adbc/config.py +115 -260
- sqlspec/adapters/adbc/driver.py +462 -367
- sqlspec/adapters/aiosqlite/__init__.py +18 -3
- sqlspec/adapters/aiosqlite/_types.py +13 -0
- sqlspec/adapters/aiosqlite/config.py +199 -129
- sqlspec/adapters/aiosqlite/driver.py +230 -269
- sqlspec/adapters/asyncmy/__init__.py +18 -3
- sqlspec/adapters/asyncmy/_types.py +12 -0
- sqlspec/adapters/asyncmy/config.py +80 -168
- sqlspec/adapters/asyncmy/driver.py +260 -225
- sqlspec/adapters/asyncpg/__init__.py +19 -4
- sqlspec/adapters/asyncpg/_types.py +17 -0
- sqlspec/adapters/asyncpg/config.py +82 -181
- sqlspec/adapters/asyncpg/driver.py +285 -383
- sqlspec/adapters/bigquery/__init__.py +17 -3
- sqlspec/adapters/bigquery/_types.py +12 -0
- sqlspec/adapters/bigquery/config.py +191 -258
- sqlspec/adapters/bigquery/driver.py +474 -646
- sqlspec/adapters/duckdb/__init__.py +14 -3
- sqlspec/adapters/duckdb/_types.py +12 -0
- sqlspec/adapters/duckdb/config.py +415 -351
- sqlspec/adapters/duckdb/driver.py +343 -413
- sqlspec/adapters/oracledb/__init__.py +19 -5
- sqlspec/adapters/oracledb/_types.py +14 -0
- sqlspec/adapters/oracledb/config.py +123 -379
- sqlspec/adapters/oracledb/driver.py +507 -560
- sqlspec/adapters/psqlpy/__init__.py +13 -3
- sqlspec/adapters/psqlpy/_types.py +11 -0
- sqlspec/adapters/psqlpy/config.py +93 -254
- sqlspec/adapters/psqlpy/driver.py +505 -234
- sqlspec/adapters/psycopg/__init__.py +19 -5
- sqlspec/adapters/psycopg/_types.py +17 -0
- sqlspec/adapters/psycopg/config.py +143 -403
- sqlspec/adapters/psycopg/driver.py +706 -872
- sqlspec/adapters/sqlite/__init__.py +14 -3
- sqlspec/adapters/sqlite/_types.py +11 -0
- sqlspec/adapters/sqlite/config.py +202 -118
- sqlspec/adapters/sqlite/driver.py +264 -303
- sqlspec/base.py +105 -9
- sqlspec/{statement/builder → builder}/__init__.py +12 -14
- sqlspec/{statement/builder → builder}/_base.py +120 -55
- sqlspec/{statement/builder → builder}/_column.py +17 -6
- sqlspec/{statement/builder → builder}/_ddl.py +46 -79
- sqlspec/{statement/builder → builder}/_ddl_utils.py +5 -10
- sqlspec/{statement/builder → builder}/_delete.py +6 -25
- sqlspec/{statement/builder → builder}/_insert.py +18 -65
- sqlspec/builder/_merge.py +56 -0
- sqlspec/{statement/builder → builder}/_parsing_utils.py +8 -11
- sqlspec/{statement/builder → builder}/_select.py +11 -56
- sqlspec/{statement/builder → builder}/_update.py +12 -18
- sqlspec/{statement/builder → builder}/mixins/__init__.py +10 -14
- sqlspec/{statement/builder → builder}/mixins/_cte_and_set_ops.py +48 -59
- sqlspec/{statement/builder → builder}/mixins/_insert_operations.py +34 -18
- sqlspec/{statement/builder → builder}/mixins/_join_operations.py +1 -3
- sqlspec/{statement/builder → builder}/mixins/_merge_operations.py +19 -9
- sqlspec/{statement/builder → builder}/mixins/_order_limit_operations.py +3 -3
- sqlspec/{statement/builder → builder}/mixins/_pivot_operations.py +4 -8
- sqlspec/{statement/builder → builder}/mixins/_select_operations.py +25 -38
- sqlspec/{statement/builder → builder}/mixins/_update_operations.py +15 -16
- sqlspec/{statement/builder → builder}/mixins/_where_clause.py +210 -137
- sqlspec/cli.py +4 -5
- sqlspec/config.py +180 -133
- sqlspec/core/__init__.py +63 -0
- sqlspec/core/cache.py +873 -0
- sqlspec/core/compiler.py +396 -0
- sqlspec/core/filters.py +830 -0
- sqlspec/core/hashing.py +310 -0
- sqlspec/core/parameters.py +1209 -0
- sqlspec/core/result.py +664 -0
- sqlspec/{statement → core}/splitter.py +321 -191
- sqlspec/core/statement.py +666 -0
- sqlspec/driver/__init__.py +7 -10
- sqlspec/driver/_async.py +387 -176
- sqlspec/driver/_common.py +527 -289
- sqlspec/driver/_sync.py +390 -172
- sqlspec/driver/mixins/__init__.py +2 -19
- sqlspec/driver/mixins/_result_tools.py +164 -0
- sqlspec/driver/mixins/_sql_translator.py +6 -3
- sqlspec/exceptions.py +5 -252
- sqlspec/extensions/aiosql/adapter.py +93 -96
- sqlspec/extensions/litestar/cli.py +1 -1
- sqlspec/extensions/litestar/config.py +0 -1
- sqlspec/extensions/litestar/handlers.py +15 -26
- sqlspec/extensions/litestar/plugin.py +18 -16
- sqlspec/extensions/litestar/providers.py +17 -52
- sqlspec/loader.py +424 -105
- sqlspec/migrations/__init__.py +12 -0
- sqlspec/migrations/base.py +92 -68
- sqlspec/migrations/commands.py +24 -106
- sqlspec/migrations/loaders.py +402 -0
- sqlspec/migrations/runner.py +49 -51
- sqlspec/migrations/tracker.py +31 -44
- sqlspec/migrations/utils.py +64 -24
- sqlspec/protocols.py +7 -183
- sqlspec/storage/__init__.py +1 -1
- sqlspec/storage/backends/base.py +37 -40
- sqlspec/storage/backends/fsspec.py +136 -112
- sqlspec/storage/backends/obstore.py +138 -160
- sqlspec/storage/capabilities.py +5 -4
- sqlspec/storage/registry.py +57 -106
- sqlspec/typing.py +136 -115
- sqlspec/utils/__init__.py +2 -3
- sqlspec/utils/correlation.py +0 -3
- sqlspec/utils/deprecation.py +6 -6
- sqlspec/utils/fixtures.py +6 -6
- sqlspec/utils/logging.py +0 -2
- sqlspec/utils/module_loader.py +7 -12
- sqlspec/utils/singleton.py +0 -1
- sqlspec/utils/sync_tools.py +17 -38
- sqlspec/utils/text.py +12 -51
- sqlspec/utils/type_guards.py +443 -232
- {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/METADATA +7 -2
- sqlspec-0.16.0.dist-info/RECORD +134 -0
- sqlspec/adapters/adbc/transformers.py +0 -108
- sqlspec/driver/connection.py +0 -207
- sqlspec/driver/mixins/_cache.py +0 -114
- sqlspec/driver/mixins/_csv_writer.py +0 -91
- sqlspec/driver/mixins/_pipeline.py +0 -508
- sqlspec/driver/mixins/_query_tools.py +0 -796
- sqlspec/driver/mixins/_result_utils.py +0 -138
- sqlspec/driver/mixins/_storage.py +0 -912
- sqlspec/driver/mixins/_type_coercion.py +0 -128
- sqlspec/driver/parameters.py +0 -138
- sqlspec/statement/__init__.py +0 -21
- sqlspec/statement/builder/_merge.py +0 -95
- sqlspec/statement/cache.py +0 -50
- sqlspec/statement/filters.py +0 -625
- sqlspec/statement/parameters.py +0 -956
- sqlspec/statement/pipelines/__init__.py +0 -210
- sqlspec/statement/pipelines/analyzers/__init__.py +0 -9
- sqlspec/statement/pipelines/analyzers/_analyzer.py +0 -646
- sqlspec/statement/pipelines/context.py +0 -109
- sqlspec/statement/pipelines/transformers/__init__.py +0 -7
- sqlspec/statement/pipelines/transformers/_expression_simplifier.py +0 -88
- sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +0 -1247
- sqlspec/statement/pipelines/transformers/_remove_comments_and_hints.py +0 -76
- sqlspec/statement/pipelines/validators/__init__.py +0 -23
- sqlspec/statement/pipelines/validators/_dml_safety.py +0 -290
- sqlspec/statement/pipelines/validators/_parameter_style.py +0 -370
- sqlspec/statement/pipelines/validators/_performance.py +0 -714
- sqlspec/statement/pipelines/validators/_security.py +0 -967
- sqlspec/statement/result.py +0 -435
- sqlspec/statement/sql.py +0 -1774
- sqlspec/utils/cached_property.py +0 -25
- sqlspec/utils/statement_hashing.py +0 -203
- sqlspec-0.14.1.dist-info/RECORD +0 -145
- /sqlspec/{statement/builder → builder}/mixins/_delete_operations.py +0 -0
- {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/entry_points.txt +0 -0
- {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/licenses/LICENSE +0 -0
- {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/licenses/NOTICE +0 -0
sqlspec/adapters/adbc/config.py
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
from contextlib import contextmanager
|
|
5
|
-
from
|
|
6
|
-
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TypedDict, Union
|
|
7
6
|
|
|
8
|
-
from
|
|
9
|
-
|
|
7
|
+
from typing_extensions import NotRequired
|
|
8
|
+
|
|
9
|
+
from sqlspec.adapters.adbc._types import AdbcConnection
|
|
10
|
+
from sqlspec.adapters.adbc.driver import AdbcCursor, AdbcDriver, get_adbc_statement_config
|
|
10
11
|
from sqlspec.config import NoPoolSyncConfig
|
|
12
|
+
from sqlspec.core.statement import StatementConfig
|
|
11
13
|
from sqlspec.exceptions import ImproperConfigurationError
|
|
12
|
-
from sqlspec.statement.sql import SQLConfig
|
|
13
|
-
from sqlspec.typing import DictRow, Empty
|
|
14
14
|
from sqlspec.utils.module_loader import import_string
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
@@ -21,219 +21,103 @@ if TYPE_CHECKING:
|
|
|
21
21
|
|
|
22
22
|
logger = logging.getLogger("sqlspec.adapters.adbc")
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
24
|
+
|
|
25
|
+
class AdbcConnectionParams(TypedDict, total=False):
|
|
26
|
+
"""ADBC connection parameters."""
|
|
27
|
+
|
|
28
|
+
uri: NotRequired[str]
|
|
29
|
+
driver_name: NotRequired[str]
|
|
30
|
+
db_kwargs: NotRequired[dict[str, Any]]
|
|
31
|
+
conn_kwargs: NotRequired[dict[str, Any]]
|
|
32
|
+
adbc_driver_manager_entrypoint: NotRequired[str]
|
|
33
|
+
autocommit: NotRequired[bool]
|
|
34
|
+
isolation_level: NotRequired[str]
|
|
35
|
+
batch_size: NotRequired[int]
|
|
36
|
+
query_timeout: NotRequired[float]
|
|
37
|
+
connection_timeout: NotRequired[float]
|
|
38
|
+
ssl_mode: NotRequired[str]
|
|
39
|
+
ssl_cert: NotRequired[str]
|
|
40
|
+
ssl_key: NotRequired[str]
|
|
41
|
+
ssl_ca: NotRequired[str]
|
|
42
|
+
username: NotRequired[str]
|
|
43
|
+
password: NotRequired[str]
|
|
44
|
+
token: NotRequired[str]
|
|
45
|
+
project_id: NotRequired[str]
|
|
46
|
+
dataset_id: NotRequired[str]
|
|
47
|
+
account: NotRequired[str]
|
|
48
|
+
warehouse: NotRequired[str]
|
|
49
|
+
database: NotRequired[str]
|
|
50
|
+
schema: NotRequired[str]
|
|
51
|
+
role: NotRequired[str]
|
|
52
|
+
authorization_header: NotRequired[str]
|
|
53
|
+
grpc_options: NotRequired[dict[str, Any]]
|
|
54
|
+
extra: NotRequired[dict[str, Any]]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
__all__ = ("AdbcConfig", "AdbcConnectionParams")
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
|
|
59
|
-
"""
|
|
61
|
+
"""ADBC configuration for Arrow Database Connectivity.
|
|
60
62
|
|
|
61
63
|
ADBC (Arrow Database Connectivity) provides a unified interface for connecting
|
|
62
|
-
to multiple database systems with
|
|
64
|
+
to multiple database systems with Arrow-native data transfer.
|
|
63
65
|
|
|
64
66
|
This configuration supports:
|
|
65
67
|
- Universal driver detection and loading
|
|
66
|
-
-
|
|
68
|
+
- Arrow data streaming
|
|
67
69
|
- Bulk ingestion operations
|
|
68
70
|
- Multiple database backends (PostgreSQL, SQLite, DuckDB, BigQuery, Snowflake, etc.)
|
|
69
|
-
-
|
|
71
|
+
- Driver path resolution
|
|
70
72
|
- Cloud database integrations
|
|
71
73
|
"""
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
driver_type: type[AdbcDriver] = AdbcDriver
|
|
76
|
-
connection_type: type[AdbcConnection] = AdbcConnection
|
|
77
|
-
|
|
78
|
-
# Parameter style support information - dynamic based on driver
|
|
79
|
-
# These are used as defaults when driver cannot be determined
|
|
80
|
-
supported_parameter_styles: ClassVar[tuple[str, ...]] = ("qmark",)
|
|
81
|
-
"""ADBC parameter styles depend on the underlying driver."""
|
|
82
|
-
|
|
83
|
-
default_parameter_style: ClassVar[str] = "qmark"
|
|
84
|
-
"""ADBC default parameter style is ? (qmark)."""
|
|
75
|
+
driver_type: ClassVar[type[AdbcDriver]] = AdbcDriver
|
|
76
|
+
connection_type: "ClassVar[type[AdbcConnection]]" = AdbcConnection
|
|
85
77
|
|
|
86
78
|
def __init__(
|
|
87
79
|
self,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
uri: Optional[str] = None,
|
|
93
|
-
driver_name: Optional[str] = None,
|
|
94
|
-
# Database-specific parameters
|
|
95
|
-
db_kwargs: Optional[dict[str, Any]] = None,
|
|
96
|
-
conn_kwargs: Optional[dict[str, Any]] = None,
|
|
97
|
-
# Driver-specific configurations
|
|
98
|
-
adbc_driver_manager_entrypoint: Optional[str] = None,
|
|
99
|
-
# Connection options
|
|
100
|
-
autocommit: Optional[bool] = None,
|
|
101
|
-
isolation_level: Optional[str] = None,
|
|
102
|
-
# Performance options
|
|
103
|
-
batch_size: Optional[int] = None,
|
|
104
|
-
query_timeout: Optional[int] = None,
|
|
105
|
-
connection_timeout: Optional[int] = None,
|
|
106
|
-
# Security options
|
|
107
|
-
ssl_mode: Optional[str] = None,
|
|
108
|
-
ssl_cert: Optional[str] = None,
|
|
109
|
-
ssl_key: Optional[str] = None,
|
|
110
|
-
ssl_ca: Optional[str] = None,
|
|
111
|
-
# Authentication
|
|
112
|
-
username: Optional[str] = None,
|
|
113
|
-
password: Optional[str] = None,
|
|
114
|
-
token: Optional[str] = None,
|
|
115
|
-
# Cloud-specific options
|
|
116
|
-
project_id: Optional[str] = None,
|
|
117
|
-
dataset_id: Optional[str] = None,
|
|
118
|
-
account: Optional[str] = None,
|
|
119
|
-
warehouse: Optional[str] = None,
|
|
120
|
-
database: Optional[str] = None,
|
|
121
|
-
schema: Optional[str] = None,
|
|
122
|
-
role: Optional[str] = None,
|
|
123
|
-
# Flight SQL specific
|
|
124
|
-
authorization_header: Optional[str] = None,
|
|
125
|
-
grpc_options: Optional[dict[str, Any]] = None,
|
|
126
|
-
**kwargs: Any,
|
|
80
|
+
*,
|
|
81
|
+
connection_config: Optional[Union[AdbcConnectionParams, dict[str, Any]]] = None,
|
|
82
|
+
statement_config: Optional[StatementConfig] = None,
|
|
83
|
+
migration_config: Optional[dict[str, Any]] = None,
|
|
127
84
|
) -> None:
|
|
128
|
-
"""Initialize ADBC configuration
|
|
85
|
+
"""Initialize ADBC configuration.
|
|
129
86
|
|
|
130
87
|
Args:
|
|
88
|
+
connection_config: Connection configuration parameters
|
|
131
89
|
statement_config: Default SQL statement configuration
|
|
132
|
-
|
|
133
|
-
default_row_type: Default row type for results
|
|
134
|
-
on_connection_create: Callback executed when connection is created
|
|
135
|
-
uri: Database URI (e.g., 'postgresql://...', 'sqlite://...', 'bigquery://...')
|
|
136
|
-
driver_name: Full dotted path to ADBC driver connect function or driver alias
|
|
137
|
-
driver: Backward compatibility alias for driver_name
|
|
138
|
-
db_kwargs: Additional database-specific connection parameters
|
|
139
|
-
conn_kwargs: Additional connection-specific parameters
|
|
140
|
-
adbc_driver_manager_entrypoint: Override for driver manager entrypoint
|
|
141
|
-
autocommit: Enable autocommit mode
|
|
142
|
-
isolation_level: Transaction isolation level
|
|
143
|
-
batch_size: Batch size for bulk operations
|
|
144
|
-
query_timeout: Query timeout in seconds
|
|
145
|
-
connection_timeout: Connection timeout in seconds
|
|
146
|
-
ssl_mode: SSL mode for secure connections
|
|
147
|
-
ssl_cert: SSL certificate path
|
|
148
|
-
ssl_key: SSL private key path
|
|
149
|
-
ssl_ca: SSL certificate authority path
|
|
150
|
-
username: Database username
|
|
151
|
-
password: Database password
|
|
152
|
-
token: Authentication token (for cloud services)
|
|
153
|
-
project_id: Project ID (BigQuery)
|
|
154
|
-
dataset_id: Dataset ID (BigQuery)
|
|
155
|
-
account: Account identifier (Snowflake)
|
|
156
|
-
warehouse: Warehouse name (Snowflake)
|
|
157
|
-
database: Database name
|
|
158
|
-
schema: Schema name
|
|
159
|
-
role: Role name (Snowflake)
|
|
160
|
-
authorization_header: Authorization header for Flight SQL
|
|
161
|
-
grpc_options: gRPC specific options for Flight SQL
|
|
162
|
-
**kwargs: Additional parameters (stored in extras)
|
|
163
|
-
|
|
164
|
-
Example:
|
|
165
|
-
>>> # PostgreSQL via ADBC
|
|
166
|
-
>>> config = AdbcConfig(
|
|
167
|
-
... uri="postgresql://user:pass@localhost/db",
|
|
168
|
-
... driver_name="adbc_driver_postgresql",
|
|
169
|
-
... )
|
|
170
|
-
|
|
171
|
-
>>> # DuckDB via ADBC
|
|
172
|
-
>>> config = AdbcConfig(
|
|
173
|
-
... uri="duckdb://mydata.db",
|
|
174
|
-
... driver_name="duckdb",
|
|
175
|
-
... db_kwargs={"read_only": False},
|
|
176
|
-
... )
|
|
177
|
-
|
|
178
|
-
>>> # BigQuery via ADBC
|
|
179
|
-
>>> config = AdbcConfig(
|
|
180
|
-
... driver_name="bigquery",
|
|
181
|
-
... project_id="my-project",
|
|
182
|
-
... dataset_id="my_dataset",
|
|
183
|
-
... )
|
|
90
|
+
migration_config: Migration configuration
|
|
184
91
|
"""
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
self.
|
|
192
|
-
self.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
self.project_id = project_id
|
|
205
|
-
self.dataset_id = dataset_id
|
|
206
|
-
self.account = account
|
|
207
|
-
self.warehouse = warehouse
|
|
208
|
-
self.database = database
|
|
209
|
-
self.schema = schema
|
|
210
|
-
self.role = role
|
|
211
|
-
self.authorization_header = authorization_header
|
|
212
|
-
self.grpc_options = grpc_options
|
|
213
|
-
|
|
214
|
-
self.extras = kwargs or {}
|
|
215
|
-
|
|
216
|
-
# Store other config
|
|
217
|
-
self.statement_config = statement_config or SQLConfig()
|
|
218
|
-
self.default_row_type = default_row_type
|
|
219
|
-
self.on_connection_create = on_connection_create
|
|
220
|
-
super().__init__()
|
|
92
|
+
if connection_config is None:
|
|
93
|
+
connection_config = {}
|
|
94
|
+
extras = connection_config.pop("extra", {})
|
|
95
|
+
if not isinstance(extras, dict):
|
|
96
|
+
msg = "The 'extra' field in connection_config must be a dictionary."
|
|
97
|
+
raise ImproperConfigurationError(msg)
|
|
98
|
+
self.connection_config: dict[str, Any] = dict(connection_config)
|
|
99
|
+
self.connection_config.update(extras)
|
|
100
|
+
|
|
101
|
+
if statement_config is None:
|
|
102
|
+
detected_dialect = str(self._get_dialect() or "sqlite")
|
|
103
|
+
statement_config = get_adbc_statement_config(detected_dialect)
|
|
104
|
+
|
|
105
|
+
super().__init__(
|
|
106
|
+
connection_config=self.connection_config,
|
|
107
|
+
migration_config=migration_config,
|
|
108
|
+
statement_config=statement_config,
|
|
109
|
+
driver_features={},
|
|
110
|
+
)
|
|
221
111
|
|
|
222
112
|
def _resolve_driver_name(self) -> str:
|
|
223
113
|
"""Resolve and normalize the ADBC driver name.
|
|
224
114
|
|
|
225
|
-
Supports both full driver paths and convenient aliases.
|
|
226
|
-
|
|
227
115
|
Returns:
|
|
228
116
|
The normalized driver connect function path.
|
|
229
|
-
|
|
230
|
-
Raises:
|
|
231
|
-
ImproperConfigurationError: If driver cannot be determined.
|
|
232
117
|
"""
|
|
233
|
-
driver_name = self.driver_name
|
|
234
|
-
uri = self.uri
|
|
118
|
+
driver_name = self.connection_config.get("driver_name")
|
|
119
|
+
uri = self.connection_config.get("uri")
|
|
235
120
|
|
|
236
|
-
# If explicit driver path is provided, normalize it
|
|
237
121
|
if isinstance(driver_name, str):
|
|
238
122
|
driver_aliases = {
|
|
239
123
|
"sqlite": "adbc_driver_sqlite.dbapi.connect",
|
|
@@ -263,9 +147,8 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
|
|
|
263
147
|
|
|
264
148
|
return resolved_driver
|
|
265
149
|
|
|
266
|
-
# Auto-detect from URI if no explicit driver
|
|
267
150
|
if isinstance(uri, str):
|
|
268
|
-
if uri.startswith("postgresql://"):
|
|
151
|
+
if uri.startswith(("postgresql://", "postgres://")):
|
|
269
152
|
return "adbc_driver_postgresql.dbapi.connect"
|
|
270
153
|
if uri.startswith("sqlite://"):
|
|
271
154
|
return "adbc_driver_sqlite.dbapi.connect"
|
|
@@ -278,13 +161,7 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
|
|
|
278
161
|
if uri.startswith("bigquery://"):
|
|
279
162
|
return "adbc_driver_bigquery.dbapi.connect"
|
|
280
163
|
|
|
281
|
-
|
|
282
|
-
msg = (
|
|
283
|
-
"Could not determine ADBC driver connect path. Please specify 'driver_name' "
|
|
284
|
-
"(e.g., 'adbc_driver_postgresql' or 'postgresql') or provide a supported 'uri'. "
|
|
285
|
-
f"URI: {uri}, Driver Name: {driver_name}"
|
|
286
|
-
)
|
|
287
|
-
raise ImproperConfigurationError(msg)
|
|
164
|
+
return "adbc_driver_sqlite.dbapi.connect"
|
|
288
165
|
|
|
289
166
|
def _get_connect_func(self) -> Callable[..., AdbcConnection]:
|
|
290
167
|
"""Get the ADBC driver connect function.
|
|
@@ -350,22 +227,19 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
|
|
|
350
227
|
"""
|
|
351
228
|
try:
|
|
352
229
|
driver_path = self._resolve_driver_name()
|
|
353
|
-
|
|
354
|
-
# Map driver paths to parameter styles
|
|
355
230
|
if "postgresql" in driver_path:
|
|
356
|
-
return (("numeric",), "numeric")
|
|
231
|
+
return (("numeric",), "numeric")
|
|
357
232
|
if "sqlite" in driver_path:
|
|
358
|
-
return (("qmark", "named_colon"), "qmark")
|
|
233
|
+
return (("qmark", "named_colon"), "qmark")
|
|
359
234
|
if "duckdb" in driver_path:
|
|
360
|
-
return (("qmark", "numeric"), "qmark")
|
|
235
|
+
return (("qmark", "numeric"), "qmark")
|
|
361
236
|
if "bigquery" in driver_path:
|
|
362
|
-
return (("named_at",), "named_at")
|
|
237
|
+
return (("named_at",), "named_at")
|
|
363
238
|
if "snowflake" in driver_path:
|
|
364
|
-
return (("qmark", "numeric"), "qmark")
|
|
239
|
+
return (("qmark", "numeric"), "qmark")
|
|
365
240
|
|
|
366
241
|
except Exception:
|
|
367
|
-
|
|
368
|
-
return (self.supported_parameter_styles, self.default_parameter_style)
|
|
242
|
+
logger.debug("Error resolving parameter styles for ADBC driver, using defaults")
|
|
369
243
|
return (("qmark",), "qmark")
|
|
370
244
|
|
|
371
245
|
def create_connection(self) -> AdbcConnection:
|
|
@@ -380,12 +254,10 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
|
|
|
380
254
|
|
|
381
255
|
try:
|
|
382
256
|
connect_func = self._get_connect_func()
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
if self.on_connection_create:
|
|
386
|
-
self.on_connection_create(connection)
|
|
257
|
+
connection_config_dict = self._get_connection_config_dict()
|
|
258
|
+
connection = connect_func(**connection_config_dict)
|
|
387
259
|
except Exception as e:
|
|
388
|
-
driver_name = self.driver_name
|
|
260
|
+
driver_name = self.connection_config.get("driver_name", "Unknown")
|
|
389
261
|
msg = f"Could not configure ADBC connection using driver '{driver_name}'. Error: {e}"
|
|
390
262
|
raise ImproperConfigurationError(msg) from e
|
|
391
263
|
return connection
|
|
@@ -407,11 +279,14 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
|
|
|
407
279
|
finally:
|
|
408
280
|
connection.close()
|
|
409
281
|
|
|
410
|
-
def provide_session(
|
|
282
|
+
def provide_session(
|
|
283
|
+
self, *args: Any, statement_config: "Optional[StatementConfig]" = None, **kwargs: Any
|
|
284
|
+
) -> "AbstractContextManager[AdbcDriver]":
|
|
411
285
|
"""Provide an ADBC driver session context manager.
|
|
412
286
|
|
|
413
287
|
Args:
|
|
414
288
|
*args: Additional arguments.
|
|
289
|
+
statement_config: Optional statement configuration override.
|
|
415
290
|
**kwargs: Additional keyword arguments.
|
|
416
291
|
|
|
417
292
|
Returns:
|
|
@@ -421,52 +296,22 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
|
|
|
421
296
|
@contextmanager
|
|
422
297
|
def session_manager() -> "Generator[AdbcDriver, None, None]":
|
|
423
298
|
with self.provide_connection(*args, **kwargs) as connection:
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if statement_config.allowed_parameter_styles is None:
|
|
432
|
-
statement_config = replace(
|
|
433
|
-
statement_config,
|
|
434
|
-
allowed_parameter_styles=supported_styles,
|
|
435
|
-
default_parameter_style=preferred_style,
|
|
436
|
-
)
|
|
437
|
-
|
|
438
|
-
# Add ADBC PostgreSQL transformer if needed
|
|
439
|
-
if self._get_dialect() == "postgres":
|
|
440
|
-
# Get the default transformers from the pipeline
|
|
441
|
-
pipeline = statement_config.get_statement_pipeline()
|
|
442
|
-
existing_transformers = list(pipeline.transformers)
|
|
443
|
-
|
|
444
|
-
# Append our transformer to the existing ones
|
|
445
|
-
existing_transformers.append(AdbcPostgresTransformer())
|
|
446
|
-
|
|
447
|
-
statement_config = replace(statement_config, transformers=existing_transformers)
|
|
448
|
-
|
|
449
|
-
driver = self.driver_type(connection=connection, config=statement_config)
|
|
450
|
-
yield driver
|
|
299
|
+
final_statement_config = (
|
|
300
|
+
statement_config
|
|
301
|
+
or self.statement_config
|
|
302
|
+
or get_adbc_statement_config(str(self._get_dialect() or "sqlite"))
|
|
303
|
+
)
|
|
304
|
+
yield self.driver_type(connection=connection, statement_config=final_statement_config)
|
|
451
305
|
|
|
452
306
|
return session_manager()
|
|
453
307
|
|
|
454
|
-
|
|
455
|
-
def connection_config_dict(self) -> dict[str, Any]:
|
|
308
|
+
def _get_connection_config_dict(self) -> dict[str, Any]:
|
|
456
309
|
"""Get the connection configuration dictionary.
|
|
457
310
|
|
|
458
311
|
Returns:
|
|
459
312
|
The connection configuration dictionary.
|
|
460
313
|
"""
|
|
461
|
-
|
|
462
|
-
config = {
|
|
463
|
-
field: getattr(self, field)
|
|
464
|
-
for field in CONNECTION_FIELDS
|
|
465
|
-
if getattr(self, field, None) is not None and getattr(self, field) is not Empty
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
# Merge extras parameters
|
|
469
|
-
config.update(self.extras)
|
|
314
|
+
config = dict(self.connection_config)
|
|
470
315
|
|
|
471
316
|
if "driver_name" in config:
|
|
472
317
|
driver_name = config["driver_name"]
|
|
@@ -474,28 +319,24 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
|
|
|
474
319
|
if "uri" in config:
|
|
475
320
|
uri = config["uri"]
|
|
476
321
|
|
|
477
|
-
# SQLite: strip sqlite:// prefix
|
|
478
322
|
if driver_name in {"sqlite", "sqlite3", "adbc_driver_sqlite"} and uri.startswith("sqlite://"): # pyright: ignore
|
|
479
|
-
config["uri"] = uri[9:] #
|
|
323
|
+
config["uri"] = uri[9:] # pyright: ignore
|
|
480
324
|
|
|
481
|
-
# DuckDB: convert uri to path
|
|
482
325
|
elif driver_name in {"duckdb", "adbc_driver_duckdb"} and uri.startswith("duckdb://"): # pyright: ignore
|
|
483
|
-
config["path"] = uri[9:] #
|
|
326
|
+
config["path"] = uri[9:] # pyright: ignore
|
|
484
327
|
config.pop("uri", None)
|
|
485
328
|
|
|
486
|
-
# BigQuery: wrap certain parameters in db_kwargs
|
|
487
329
|
if driver_name in {"bigquery", "bq", "adbc_driver_bigquery"}:
|
|
488
|
-
|
|
330
|
+
bigquery_parameters = ["project_id", "dataset_id", "token"]
|
|
489
331
|
db_kwargs = config.get("db_kwargs", {})
|
|
490
332
|
|
|
491
|
-
for param in
|
|
333
|
+
for param in bigquery_parameters:
|
|
492
334
|
if param in config and param != "db_kwargs":
|
|
493
335
|
db_kwargs[param] = config.pop(param) # pyright: ignore
|
|
494
336
|
|
|
495
337
|
if db_kwargs:
|
|
496
338
|
config["db_kwargs"] = db_kwargs
|
|
497
339
|
|
|
498
|
-
# For other drivers (like PostgreSQL), merge db_kwargs into top level
|
|
499
340
|
elif "db_kwargs" in config and driver_name not in {"bigquery", "bq", "adbc_driver_bigquery"}:
|
|
500
341
|
db_kwargs = config.pop("db_kwargs")
|
|
501
342
|
if isinstance(db_kwargs, dict):
|
|
@@ -504,3 +345,17 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
|
|
|
504
345
|
config.pop("driver_name", None)
|
|
505
346
|
|
|
506
347
|
return config
|
|
348
|
+
|
|
349
|
+
def get_signature_namespace(self) -> "dict[str, type[Any]]":
|
|
350
|
+
"""Get the signature namespace for ADBC types.
|
|
351
|
+
|
|
352
|
+
This provides all ADBC-specific types that Litestar needs to recognize
|
|
353
|
+
to avoid serialization attempts.
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
Dictionary mapping type names to types.
|
|
357
|
+
"""
|
|
358
|
+
|
|
359
|
+
namespace = super().get_signature_namespace()
|
|
360
|
+
namespace.update({"AdbcConnection": AdbcConnection, "AdbcCursor": AdbcCursor})
|
|
361
|
+
return namespace
|