sqlspec 0.13.1__py3-none-any.whl → 0.16.2__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.

Files changed (185) hide show
  1. sqlspec/__init__.py +71 -8
  2. sqlspec/__main__.py +12 -0
  3. sqlspec/__metadata__.py +1 -3
  4. sqlspec/_serialization.py +1 -2
  5. sqlspec/_sql.py +930 -136
  6. sqlspec/_typing.py +278 -142
  7. sqlspec/adapters/adbc/__init__.py +4 -3
  8. sqlspec/adapters/adbc/_types.py +12 -0
  9. sqlspec/adapters/adbc/config.py +116 -285
  10. sqlspec/adapters/adbc/driver.py +462 -340
  11. sqlspec/adapters/aiosqlite/__init__.py +18 -3
  12. sqlspec/adapters/aiosqlite/_types.py +13 -0
  13. sqlspec/adapters/aiosqlite/config.py +202 -150
  14. sqlspec/adapters/aiosqlite/driver.py +226 -247
  15. sqlspec/adapters/asyncmy/__init__.py +18 -3
  16. sqlspec/adapters/asyncmy/_types.py +12 -0
  17. sqlspec/adapters/asyncmy/config.py +80 -199
  18. sqlspec/adapters/asyncmy/driver.py +257 -215
  19. sqlspec/adapters/asyncpg/__init__.py +19 -4
  20. sqlspec/adapters/asyncpg/_types.py +17 -0
  21. sqlspec/adapters/asyncpg/config.py +81 -214
  22. sqlspec/adapters/asyncpg/driver.py +284 -359
  23. sqlspec/adapters/bigquery/__init__.py +17 -3
  24. sqlspec/adapters/bigquery/_types.py +12 -0
  25. sqlspec/adapters/bigquery/config.py +191 -299
  26. sqlspec/adapters/bigquery/driver.py +474 -634
  27. sqlspec/adapters/duckdb/__init__.py +14 -3
  28. sqlspec/adapters/duckdb/_types.py +12 -0
  29. sqlspec/adapters/duckdb/config.py +414 -397
  30. sqlspec/adapters/duckdb/driver.py +342 -393
  31. sqlspec/adapters/oracledb/__init__.py +19 -5
  32. sqlspec/adapters/oracledb/_types.py +14 -0
  33. sqlspec/adapters/oracledb/config.py +123 -458
  34. sqlspec/adapters/oracledb/driver.py +505 -531
  35. sqlspec/adapters/psqlpy/__init__.py +13 -3
  36. sqlspec/adapters/psqlpy/_types.py +11 -0
  37. sqlspec/adapters/psqlpy/config.py +93 -307
  38. sqlspec/adapters/psqlpy/driver.py +504 -213
  39. sqlspec/adapters/psycopg/__init__.py +19 -5
  40. sqlspec/adapters/psycopg/_types.py +17 -0
  41. sqlspec/adapters/psycopg/config.py +143 -472
  42. sqlspec/adapters/psycopg/driver.py +704 -825
  43. sqlspec/adapters/sqlite/__init__.py +14 -3
  44. sqlspec/adapters/sqlite/_types.py +11 -0
  45. sqlspec/adapters/sqlite/config.py +208 -142
  46. sqlspec/adapters/sqlite/driver.py +263 -278
  47. sqlspec/base.py +105 -9
  48. sqlspec/{statement/builder → builder}/__init__.py +12 -14
  49. sqlspec/{statement/builder/base.py → builder/_base.py} +184 -86
  50. sqlspec/{statement/builder/column.py → builder/_column.py} +97 -60
  51. sqlspec/{statement/builder/ddl.py → builder/_ddl.py} +61 -131
  52. sqlspec/{statement/builder → builder}/_ddl_utils.py +4 -10
  53. sqlspec/{statement/builder/delete.py → builder/_delete.py} +10 -30
  54. sqlspec/builder/_insert.py +421 -0
  55. sqlspec/builder/_merge.py +71 -0
  56. sqlspec/{statement/builder → builder}/_parsing_utils.py +49 -26
  57. sqlspec/builder/_select.py +170 -0
  58. sqlspec/{statement/builder/update.py → builder/_update.py} +16 -20
  59. sqlspec/builder/mixins/__init__.py +55 -0
  60. sqlspec/builder/mixins/_cte_and_set_ops.py +222 -0
  61. sqlspec/{statement/builder/mixins/_delete_from.py → builder/mixins/_delete_operations.py} +8 -1
  62. sqlspec/builder/mixins/_insert_operations.py +244 -0
  63. sqlspec/{statement/builder/mixins/_join.py → builder/mixins/_join_operations.py} +45 -13
  64. sqlspec/{statement/builder/mixins/_merge_clauses.py → builder/mixins/_merge_operations.py} +188 -30
  65. sqlspec/builder/mixins/_order_limit_operations.py +135 -0
  66. sqlspec/builder/mixins/_pivot_operations.py +153 -0
  67. sqlspec/builder/mixins/_select_operations.py +604 -0
  68. sqlspec/builder/mixins/_update_operations.py +202 -0
  69. sqlspec/builder/mixins/_where_clause.py +644 -0
  70. sqlspec/cli.py +247 -0
  71. sqlspec/config.py +183 -138
  72. sqlspec/core/__init__.py +63 -0
  73. sqlspec/core/cache.py +871 -0
  74. sqlspec/core/compiler.py +417 -0
  75. sqlspec/core/filters.py +830 -0
  76. sqlspec/core/hashing.py +310 -0
  77. sqlspec/core/parameters.py +1237 -0
  78. sqlspec/core/result.py +677 -0
  79. sqlspec/{statement → core}/splitter.py +321 -191
  80. sqlspec/core/statement.py +676 -0
  81. sqlspec/driver/__init__.py +7 -10
  82. sqlspec/driver/_async.py +422 -163
  83. sqlspec/driver/_common.py +545 -287
  84. sqlspec/driver/_sync.py +426 -160
  85. sqlspec/driver/mixins/__init__.py +2 -13
  86. sqlspec/driver/mixins/_result_tools.py +193 -0
  87. sqlspec/driver/mixins/_sql_translator.py +65 -14
  88. sqlspec/exceptions.py +5 -252
  89. sqlspec/extensions/aiosql/adapter.py +93 -96
  90. sqlspec/extensions/litestar/__init__.py +2 -1
  91. sqlspec/extensions/litestar/cli.py +48 -0
  92. sqlspec/extensions/litestar/config.py +0 -1
  93. sqlspec/extensions/litestar/handlers.py +15 -26
  94. sqlspec/extensions/litestar/plugin.py +21 -16
  95. sqlspec/extensions/litestar/providers.py +17 -52
  96. sqlspec/loader.py +423 -104
  97. sqlspec/migrations/__init__.py +35 -0
  98. sqlspec/migrations/base.py +414 -0
  99. sqlspec/migrations/commands.py +443 -0
  100. sqlspec/migrations/loaders.py +402 -0
  101. sqlspec/migrations/runner.py +213 -0
  102. sqlspec/migrations/tracker.py +140 -0
  103. sqlspec/migrations/utils.py +129 -0
  104. sqlspec/protocols.py +51 -186
  105. sqlspec/storage/__init__.py +1 -1
  106. sqlspec/storage/backends/base.py +37 -40
  107. sqlspec/storage/backends/fsspec.py +136 -112
  108. sqlspec/storage/backends/obstore.py +138 -160
  109. sqlspec/storage/capabilities.py +5 -4
  110. sqlspec/storage/registry.py +57 -106
  111. sqlspec/typing.py +136 -115
  112. sqlspec/utils/__init__.py +2 -2
  113. sqlspec/utils/correlation.py +0 -3
  114. sqlspec/utils/deprecation.py +6 -6
  115. sqlspec/utils/fixtures.py +6 -6
  116. sqlspec/utils/logging.py +0 -2
  117. sqlspec/utils/module_loader.py +7 -12
  118. sqlspec/utils/singleton.py +0 -1
  119. sqlspec/utils/sync_tools.py +17 -38
  120. sqlspec/utils/text.py +12 -51
  121. sqlspec/utils/type_guards.py +482 -235
  122. {sqlspec-0.13.1.dist-info → sqlspec-0.16.2.dist-info}/METADATA +7 -2
  123. sqlspec-0.16.2.dist-info/RECORD +134 -0
  124. sqlspec-0.16.2.dist-info/entry_points.txt +2 -0
  125. sqlspec/driver/connection.py +0 -207
  126. sqlspec/driver/mixins/_csv_writer.py +0 -91
  127. sqlspec/driver/mixins/_pipeline.py +0 -512
  128. sqlspec/driver/mixins/_result_utils.py +0 -140
  129. sqlspec/driver/mixins/_storage.py +0 -926
  130. sqlspec/driver/mixins/_type_coercion.py +0 -130
  131. sqlspec/driver/parameters.py +0 -138
  132. sqlspec/service/__init__.py +0 -4
  133. sqlspec/service/_util.py +0 -147
  134. sqlspec/service/base.py +0 -1131
  135. sqlspec/service/pagination.py +0 -26
  136. sqlspec/statement/__init__.py +0 -21
  137. sqlspec/statement/builder/insert.py +0 -288
  138. sqlspec/statement/builder/merge.py +0 -95
  139. sqlspec/statement/builder/mixins/__init__.py +0 -65
  140. sqlspec/statement/builder/mixins/_aggregate_functions.py +0 -250
  141. sqlspec/statement/builder/mixins/_case_builder.py +0 -91
  142. sqlspec/statement/builder/mixins/_common_table_expr.py +0 -90
  143. sqlspec/statement/builder/mixins/_from.py +0 -63
  144. sqlspec/statement/builder/mixins/_group_by.py +0 -118
  145. sqlspec/statement/builder/mixins/_having.py +0 -35
  146. sqlspec/statement/builder/mixins/_insert_from_select.py +0 -47
  147. sqlspec/statement/builder/mixins/_insert_into.py +0 -36
  148. sqlspec/statement/builder/mixins/_insert_values.py +0 -67
  149. sqlspec/statement/builder/mixins/_limit_offset.py +0 -53
  150. sqlspec/statement/builder/mixins/_order_by.py +0 -46
  151. sqlspec/statement/builder/mixins/_pivot.py +0 -79
  152. sqlspec/statement/builder/mixins/_returning.py +0 -37
  153. sqlspec/statement/builder/mixins/_select_columns.py +0 -61
  154. sqlspec/statement/builder/mixins/_set_ops.py +0 -122
  155. sqlspec/statement/builder/mixins/_unpivot.py +0 -77
  156. sqlspec/statement/builder/mixins/_update_from.py +0 -55
  157. sqlspec/statement/builder/mixins/_update_set.py +0 -94
  158. sqlspec/statement/builder/mixins/_update_table.py +0 -29
  159. sqlspec/statement/builder/mixins/_where.py +0 -401
  160. sqlspec/statement/builder/mixins/_window_functions.py +0 -86
  161. sqlspec/statement/builder/select.py +0 -221
  162. sqlspec/statement/filters.py +0 -596
  163. sqlspec/statement/parameter_manager.py +0 -220
  164. sqlspec/statement/parameters.py +0 -867
  165. sqlspec/statement/pipelines/__init__.py +0 -210
  166. sqlspec/statement/pipelines/analyzers/__init__.py +0 -9
  167. sqlspec/statement/pipelines/analyzers/_analyzer.py +0 -646
  168. sqlspec/statement/pipelines/context.py +0 -115
  169. sqlspec/statement/pipelines/transformers/__init__.py +0 -7
  170. sqlspec/statement/pipelines/transformers/_expression_simplifier.py +0 -88
  171. sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +0 -1247
  172. sqlspec/statement/pipelines/transformers/_remove_comments_and_hints.py +0 -76
  173. sqlspec/statement/pipelines/validators/__init__.py +0 -23
  174. sqlspec/statement/pipelines/validators/_dml_safety.py +0 -290
  175. sqlspec/statement/pipelines/validators/_parameter_style.py +0 -370
  176. sqlspec/statement/pipelines/validators/_performance.py +0 -718
  177. sqlspec/statement/pipelines/validators/_security.py +0 -967
  178. sqlspec/statement/result.py +0 -435
  179. sqlspec/statement/sql.py +0 -1704
  180. sqlspec/statement/sql_compiler.py +0 -140
  181. sqlspec/utils/cached_property.py +0 -25
  182. sqlspec-0.13.1.dist-info/RECORD +0 -150
  183. {sqlspec-0.13.1.dist-info → sqlspec-0.16.2.dist-info}/WHEEL +0 -0
  184. {sqlspec-0.13.1.dist-info → sqlspec-0.16.2.dist-info}/licenses/LICENSE +0 -0
  185. {sqlspec-0.13.1.dist-info → sqlspec-0.16.2.dist-info}/licenses/NOTICE +0 -0
@@ -2,14 +2,15 @@
2
2
 
3
3
  import logging
4
4
  from contextlib import contextmanager
5
- from dataclasses import replace
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 sqlspec.adapters.adbc.driver import AdbcConnection, AdbcDriver
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
9
11
  from sqlspec.config import NoPoolSyncConfig
12
+ from sqlspec.core.statement import StatementConfig
10
13
  from sqlspec.exceptions import ImproperConfigurationError
11
- from sqlspec.statement.sql import SQLConfig
12
- from sqlspec.typing import DictRow, Empty
13
14
  from sqlspec.utils.module_loader import import_string
14
15
 
15
16
  if TYPE_CHECKING:
@@ -20,255 +21,103 @@ if TYPE_CHECKING:
20
21
 
21
22
  logger = logging.getLogger("sqlspec.adapters.adbc")
22
23
 
23
- CONNECTION_FIELDS = frozenset(
24
- {
25
- "uri",
26
- "driver_name",
27
- "db_kwargs",
28
- "conn_kwargs",
29
- "adbc_driver_manager_entrypoint",
30
- "autocommit",
31
- "isolation_level",
32
- "batch_size",
33
- "query_timeout",
34
- "connection_timeout",
35
- "ssl_mode",
36
- "ssl_cert",
37
- "ssl_key",
38
- "ssl_ca",
39
- "username",
40
- "password",
41
- "token",
42
- "project_id",
43
- "dataset_id",
44
- "account",
45
- "warehouse",
46
- "database",
47
- "schema",
48
- "role",
49
- "authorization_header",
50
- "grpc_options",
51
- }
52
- )
53
-
54
- __all__ = ("CONNECTION_FIELDS", "AdbcConfig")
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")
55
58
 
56
59
 
57
60
  class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
58
- """Enhanced ADBC configuration with universal database connectivity.
61
+ """ADBC configuration for Arrow Database Connectivity.
59
62
 
60
63
  ADBC (Arrow Database Connectivity) provides a unified interface for connecting
61
- to multiple database systems with high-performance Arrow-native data transfer.
64
+ to multiple database systems with Arrow-native data transfer.
62
65
 
63
66
  This configuration supports:
64
67
  - Universal driver detection and loading
65
- - High-performance Arrow data streaming
68
+ - Arrow data streaming
66
69
  - Bulk ingestion operations
67
70
  - Multiple database backends (PostgreSQL, SQLite, DuckDB, BigQuery, Snowflake, etc.)
68
- - Intelligent driver path resolution
71
+ - Driver path resolution
69
72
  - Cloud database integrations
70
73
  """
71
74
 
72
- __slots__ = (
73
- "_dialect",
74
- "account",
75
- "adbc_driver_manager_entrypoint",
76
- "authorization_header",
77
- "autocommit",
78
- "batch_size",
79
- "conn_kwargs",
80
- "connection_timeout",
81
- "database",
82
- "dataset_id",
83
- "db_kwargs",
84
- "default_row_type",
85
- "driver_name",
86
- "extras",
87
- "grpc_options",
88
- "isolation_level",
89
- "on_connection_create",
90
- "password",
91
- "pool_instance",
92
- "project_id",
93
- "query_timeout",
94
- "role",
95
- "schema",
96
- "ssl_ca",
97
- "ssl_cert",
98
- "ssl_key",
99
- "ssl_mode",
100
- "statement_config",
101
- "token",
102
- "uri",
103
- "username",
104
- "warehouse",
105
- )
106
-
107
- is_async: ClassVar[bool] = False
108
- supports_connection_pooling: ClassVar[bool] = False
109
- driver_type: type[AdbcDriver] = AdbcDriver
110
- connection_type: type[AdbcConnection] = AdbcConnection
111
-
112
- # Parameter style support information - dynamic based on driver
113
- # These are used as defaults when driver cannot be determined
114
- supported_parameter_styles: ClassVar[tuple[str, ...]] = ("qmark",)
115
- """ADBC parameter styles depend on the underlying driver."""
116
-
117
- preferred_parameter_style: ClassVar[str] = "qmark"
118
- """ADBC default parameter style is ? (qmark)."""
75
+ driver_type: ClassVar[type[AdbcDriver]] = AdbcDriver
76
+ connection_type: "ClassVar[type[AdbcConnection]]" = AdbcConnection
119
77
 
120
78
  def __init__(
121
79
  self,
122
- statement_config: Optional[SQLConfig] = None,
123
- default_row_type: type[DictRow] = DictRow,
124
- on_connection_create: Optional[Callable[[AdbcConnection], None]] = None,
125
- # Core connection parameters
126
- uri: Optional[str] = None,
127
- driver_name: Optional[str] = None,
128
- # Database-specific parameters
129
- db_kwargs: Optional[dict[str, Any]] = None,
130
- conn_kwargs: Optional[dict[str, Any]] = None,
131
- # Driver-specific configurations
132
- adbc_driver_manager_entrypoint: Optional[str] = None,
133
- # Connection options
134
- autocommit: Optional[bool] = None,
135
- isolation_level: Optional[str] = None,
136
- # Performance options
137
- batch_size: Optional[int] = None,
138
- query_timeout: Optional[int] = None,
139
- connection_timeout: Optional[int] = None,
140
- # Security options
141
- ssl_mode: Optional[str] = None,
142
- ssl_cert: Optional[str] = None,
143
- ssl_key: Optional[str] = None,
144
- ssl_ca: Optional[str] = None,
145
- # Authentication
146
- username: Optional[str] = None,
147
- password: Optional[str] = None,
148
- token: Optional[str] = None,
149
- # Cloud-specific options
150
- project_id: Optional[str] = None,
151
- dataset_id: Optional[str] = None,
152
- account: Optional[str] = None,
153
- warehouse: Optional[str] = None,
154
- database: Optional[str] = None,
155
- schema: Optional[str] = None,
156
- role: Optional[str] = None,
157
- # Flight SQL specific
158
- authorization_header: Optional[str] = None,
159
- grpc_options: Optional[dict[str, Any]] = None,
160
- **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,
161
84
  ) -> None:
162
- """Initialize ADBC configuration with universal connectivity features.
85
+ """Initialize ADBC configuration.
163
86
 
164
87
  Args:
88
+ connection_config: Connection configuration parameters
165
89
  statement_config: Default SQL statement configuration
166
- instrumentation: Instrumentation configuration
167
- default_row_type: Default row type for results
168
- on_connection_create: Callback executed when connection is created
169
- uri: Database URI (e.g., 'postgresql://...', 'sqlite://...', 'bigquery://...')
170
- driver_name: Full dotted path to ADBC driver connect function or driver alias
171
- driver: Backward compatibility alias for driver_name
172
- db_kwargs: Additional database-specific connection parameters
173
- conn_kwargs: Additional connection-specific parameters
174
- adbc_driver_manager_entrypoint: Override for driver manager entrypoint
175
- autocommit: Enable autocommit mode
176
- isolation_level: Transaction isolation level
177
- batch_size: Batch size for bulk operations
178
- query_timeout: Query timeout in seconds
179
- connection_timeout: Connection timeout in seconds
180
- ssl_mode: SSL mode for secure connections
181
- ssl_cert: SSL certificate path
182
- ssl_key: SSL private key path
183
- ssl_ca: SSL certificate authority path
184
- username: Database username
185
- password: Database password
186
- token: Authentication token (for cloud services)
187
- project_id: Project ID (BigQuery)
188
- dataset_id: Dataset ID (BigQuery)
189
- account: Account identifier (Snowflake)
190
- warehouse: Warehouse name (Snowflake)
191
- database: Database name
192
- schema: Schema name
193
- role: Role name (Snowflake)
194
- authorization_header: Authorization header for Flight SQL
195
- grpc_options: gRPC specific options for Flight SQL
196
- **kwargs: Additional parameters (stored in extras)
197
-
198
- Example:
199
- >>> # PostgreSQL via ADBC
200
- >>> config = AdbcConfig(
201
- ... uri="postgresql://user:pass@localhost/db",
202
- ... driver_name="adbc_driver_postgresql",
203
- ... )
204
-
205
- >>> # DuckDB via ADBC
206
- >>> config = AdbcConfig(
207
- ... uri="duckdb://mydata.db",
208
- ... driver_name="duckdb",
209
- ... db_kwargs={"read_only": False},
210
- ... )
211
-
212
- >>> # BigQuery via ADBC
213
- >>> config = AdbcConfig(
214
- ... driver_name="bigquery",
215
- ... project_id="my-project",
216
- ... dataset_id="my_dataset",
217
- ... )
90
+ migration_config: Migration configuration
218
91
  """
219
-
220
- # Store connection parameters as instance attributes
221
- self.uri = uri
222
- self.driver_name = driver_name
223
- self.db_kwargs = db_kwargs
224
- self.conn_kwargs = conn_kwargs
225
- self.adbc_driver_manager_entrypoint = adbc_driver_manager_entrypoint
226
- self.autocommit = autocommit
227
- self.isolation_level = isolation_level
228
- self.batch_size = batch_size
229
- self.query_timeout = query_timeout
230
- self.connection_timeout = connection_timeout
231
- self.ssl_mode = ssl_mode
232
- self.ssl_cert = ssl_cert
233
- self.ssl_key = ssl_key
234
- self.ssl_ca = ssl_ca
235
- self.username = username
236
- self.password = password
237
- self.token = token
238
- self.project_id = project_id
239
- self.dataset_id = dataset_id
240
- self.account = account
241
- self.warehouse = warehouse
242
- self.database = database
243
- self.schema = schema
244
- self.role = role
245
- self.authorization_header = authorization_header
246
- self.grpc_options = grpc_options
247
-
248
- self.extras = kwargs or {}
249
-
250
- # Store other config
251
- self.statement_config = statement_config or SQLConfig()
252
- self.default_row_type = default_row_type
253
- self.on_connection_create = on_connection_create
254
- self._dialect: DialectType = None
255
- 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
+ )
256
111
 
257
112
  def _resolve_driver_name(self) -> str:
258
113
  """Resolve and normalize the ADBC driver name.
259
114
 
260
- Supports both full driver paths and convenient aliases.
261
-
262
115
  Returns:
263
116
  The normalized driver connect function path.
264
-
265
- Raises:
266
- ImproperConfigurationError: If driver cannot be determined.
267
117
  """
268
- driver_name = self.driver_name
269
- uri = self.uri
118
+ driver_name = self.connection_config.get("driver_name")
119
+ uri = self.connection_config.get("uri")
270
120
 
271
- # If explicit driver path is provided, normalize it
272
121
  if isinstance(driver_name, str):
273
122
  driver_aliases = {
274
123
  "sqlite": "adbc_driver_sqlite.dbapi.connect",
@@ -298,9 +147,8 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
298
147
 
299
148
  return resolved_driver
300
149
 
301
- # Auto-detect from URI if no explicit driver
302
150
  if isinstance(uri, str):
303
- if uri.startswith("postgresql://"):
151
+ if uri.startswith(("postgresql://", "postgres://")):
304
152
  return "adbc_driver_postgresql.dbapi.connect"
305
153
  if uri.startswith("sqlite://"):
306
154
  return "adbc_driver_sqlite.dbapi.connect"
@@ -313,13 +161,7 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
313
161
  if uri.startswith("bigquery://"):
314
162
  return "adbc_driver_bigquery.dbapi.connect"
315
163
 
316
- # Could not determine driver
317
- msg = (
318
- "Could not determine ADBC driver connect path. Please specify 'driver_name' "
319
- "(e.g., 'adbc_driver_postgresql' or 'postgresql') or provide a supported 'uri'. "
320
- f"URI: {uri}, Driver Name: {driver_name}"
321
- )
322
- raise ImproperConfigurationError(msg)
164
+ return "adbc_driver_sqlite.dbapi.connect"
323
165
 
324
166
  def _get_connect_func(self) -> Callable[..., AdbcConnection]:
325
167
  """Get the ADBC driver connect function.
@@ -381,26 +223,23 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
381
223
  """Get parameter styles based on the underlying driver.
382
224
 
383
225
  Returns:
384
- Tuple of (supported_parameter_styles, preferred_parameter_style)
226
+ Tuple of (supported_parameter_styles, default_parameter_style)
385
227
  """
386
228
  try:
387
229
  driver_path = self._resolve_driver_name()
388
-
389
- # Map driver paths to parameter styles
390
230
  if "postgresql" in driver_path:
391
- return (("numeric",), "numeric") # $1, $2, ...
231
+ return (("numeric",), "numeric")
392
232
  if "sqlite" in driver_path:
393
- return (("qmark", "named_colon"), "qmark") # ? or :name
233
+ return (("qmark", "named_colon"), "qmark")
394
234
  if "duckdb" in driver_path:
395
- return (("qmark", "numeric"), "qmark") # ? or $1
235
+ return (("qmark", "numeric"), "qmark")
396
236
  if "bigquery" in driver_path:
397
- return (("named_at",), "named_at") # @name
237
+ return (("named_at",), "named_at")
398
238
  if "snowflake" in driver_path:
399
- return (("qmark", "numeric"), "qmark") # ? or :1
239
+ return (("qmark", "numeric"), "qmark")
400
240
 
401
241
  except Exception:
402
- # If we can't determine driver, use defaults
403
- return (self.supported_parameter_styles, self.preferred_parameter_style)
242
+ logger.debug("Error resolving parameter styles for ADBC driver, using defaults")
404
243
  return (("qmark",), "qmark")
405
244
 
406
245
  def create_connection(self) -> AdbcConnection:
@@ -415,12 +254,10 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
415
254
 
416
255
  try:
417
256
  connect_func = self._get_connect_func()
418
- connection = connect_func(**self.connection_config_dict)
419
-
420
- if self.on_connection_create:
421
- self.on_connection_create(connection)
257
+ connection_config_dict = self._get_connection_config_dict()
258
+ connection = connect_func(**connection_config_dict)
422
259
  except Exception as e:
423
- driver_name = self.driver_name or "Unknown"
260
+ driver_name = self.connection_config.get("driver_name", "Unknown")
424
261
  msg = f"Could not configure ADBC connection using driver '{driver_name}'. Error: {e}"
425
262
  raise ImproperConfigurationError(msg) from e
426
263
  return connection
@@ -442,11 +279,14 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
442
279
  finally:
443
280
  connection.close()
444
281
 
445
- def provide_session(self, *args: Any, **kwargs: Any) -> "AbstractContextManager[AdbcDriver]":
282
+ def provide_session(
283
+ self, *args: Any, statement_config: "Optional[StatementConfig]" = None, **kwargs: Any
284
+ ) -> "AbstractContextManager[AdbcDriver]":
446
285
  """Provide an ADBC driver session context manager.
447
286
 
448
287
  Args:
449
288
  *args: Additional arguments.
289
+ statement_config: Optional statement configuration override.
450
290
  **kwargs: Additional keyword arguments.
451
291
 
452
292
  Returns:
@@ -456,41 +296,22 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
456
296
  @contextmanager
457
297
  def session_manager() -> "Generator[AdbcDriver, None, None]":
458
298
  with self.provide_connection(*args, **kwargs) as connection:
459
- supported_styles, preferred_style = self._get_parameter_styles()
460
-
461
- statement_config = self.statement_config
462
- if statement_config is not None:
463
- if statement_config.dialect is None:
464
- statement_config = replace(statement_config, dialect=self._get_dialect())
465
-
466
- if statement_config.allowed_parameter_styles is None:
467
- statement_config = replace(
468
- statement_config,
469
- allowed_parameter_styles=supported_styles,
470
- target_parameter_style=preferred_style,
471
- )
472
-
473
- driver = self.driver_type(connection=connection, config=statement_config)
474
- 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)
475
305
 
476
306
  return session_manager()
477
307
 
478
- @property
479
- def connection_config_dict(self) -> dict[str, Any]:
308
+ def _get_connection_config_dict(self) -> dict[str, Any]:
480
309
  """Get the connection configuration dictionary.
481
310
 
482
311
  Returns:
483
312
  The connection configuration dictionary.
484
313
  """
485
- # Gather non-None connection parameters
486
- config = {
487
- field: getattr(self, field)
488
- for field in CONNECTION_FIELDS
489
- if getattr(self, field, None) is not None and getattr(self, field) is not Empty
490
- }
491
-
492
- # Merge extras parameters
493
- config.update(self.extras)
314
+ config = dict(self.connection_config)
494
315
 
495
316
  if "driver_name" in config:
496
317
  driver_name = config["driver_name"]
@@ -498,28 +319,24 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
498
319
  if "uri" in config:
499
320
  uri = config["uri"]
500
321
 
501
- # SQLite: strip sqlite:// prefix
502
322
  if driver_name in {"sqlite", "sqlite3", "adbc_driver_sqlite"} and uri.startswith("sqlite://"): # pyright: ignore
503
- config["uri"] = uri[9:] # Remove "sqlite://" # pyright: ignore
323
+ config["uri"] = uri[9:] # pyright: ignore
504
324
 
505
- # DuckDB: convert uri to path
506
325
  elif driver_name in {"duckdb", "adbc_driver_duckdb"} and uri.startswith("duckdb://"): # pyright: ignore
507
- config["path"] = uri[9:] # Remove "duckdb://" # pyright: ignore
326
+ config["path"] = uri[9:] # pyright: ignore
508
327
  config.pop("uri", None)
509
328
 
510
- # BigQuery: wrap certain parameters in db_kwargs
511
329
  if driver_name in {"bigquery", "bq", "adbc_driver_bigquery"}:
512
- bigquery_params = ["project_id", "dataset_id", "token"]
330
+ bigquery_parameters = ["project_id", "dataset_id", "token"]
513
331
  db_kwargs = config.get("db_kwargs", {})
514
332
 
515
- for param in bigquery_params:
333
+ for param in bigquery_parameters:
516
334
  if param in config and param != "db_kwargs":
517
335
  db_kwargs[param] = config.pop(param) # pyright: ignore
518
336
 
519
337
  if db_kwargs:
520
338
  config["db_kwargs"] = db_kwargs
521
339
 
522
- # For other drivers (like PostgreSQL), merge db_kwargs into top level
523
340
  elif "db_kwargs" in config and driver_name not in {"bigquery", "bq", "adbc_driver_bigquery"}:
524
341
  db_kwargs = config.pop("db_kwargs")
525
342
  if isinstance(db_kwargs, dict):
@@ -528,3 +345,17 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
528
345
  config.pop("driver_name", None)
529
346
 
530
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