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.

Files changed (159) hide show
  1. sqlspec/__init__.py +50 -25
  2. sqlspec/__main__.py +1 -1
  3. sqlspec/__metadata__.py +1 -3
  4. sqlspec/_serialization.py +1 -2
  5. sqlspec/_sql.py +480 -121
  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 +115 -260
  10. sqlspec/adapters/adbc/driver.py +462 -367
  11. sqlspec/adapters/aiosqlite/__init__.py +18 -3
  12. sqlspec/adapters/aiosqlite/_types.py +13 -0
  13. sqlspec/adapters/aiosqlite/config.py +199 -129
  14. sqlspec/adapters/aiosqlite/driver.py +230 -269
  15. sqlspec/adapters/asyncmy/__init__.py +18 -3
  16. sqlspec/adapters/asyncmy/_types.py +12 -0
  17. sqlspec/adapters/asyncmy/config.py +80 -168
  18. sqlspec/adapters/asyncmy/driver.py +260 -225
  19. sqlspec/adapters/asyncpg/__init__.py +19 -4
  20. sqlspec/adapters/asyncpg/_types.py +17 -0
  21. sqlspec/adapters/asyncpg/config.py +82 -181
  22. sqlspec/adapters/asyncpg/driver.py +285 -383
  23. sqlspec/adapters/bigquery/__init__.py +17 -3
  24. sqlspec/adapters/bigquery/_types.py +12 -0
  25. sqlspec/adapters/bigquery/config.py +191 -258
  26. sqlspec/adapters/bigquery/driver.py +474 -646
  27. sqlspec/adapters/duckdb/__init__.py +14 -3
  28. sqlspec/adapters/duckdb/_types.py +12 -0
  29. sqlspec/adapters/duckdb/config.py +415 -351
  30. sqlspec/adapters/duckdb/driver.py +343 -413
  31. sqlspec/adapters/oracledb/__init__.py +19 -5
  32. sqlspec/adapters/oracledb/_types.py +14 -0
  33. sqlspec/adapters/oracledb/config.py +123 -379
  34. sqlspec/adapters/oracledb/driver.py +507 -560
  35. sqlspec/adapters/psqlpy/__init__.py +13 -3
  36. sqlspec/adapters/psqlpy/_types.py +11 -0
  37. sqlspec/adapters/psqlpy/config.py +93 -254
  38. sqlspec/adapters/psqlpy/driver.py +505 -234
  39. sqlspec/adapters/psycopg/__init__.py +19 -5
  40. sqlspec/adapters/psycopg/_types.py +17 -0
  41. sqlspec/adapters/psycopg/config.py +143 -403
  42. sqlspec/adapters/psycopg/driver.py +706 -872
  43. sqlspec/adapters/sqlite/__init__.py +14 -3
  44. sqlspec/adapters/sqlite/_types.py +11 -0
  45. sqlspec/adapters/sqlite/config.py +202 -118
  46. sqlspec/adapters/sqlite/driver.py +264 -303
  47. sqlspec/base.py +105 -9
  48. sqlspec/{statement/builder → builder}/__init__.py +12 -14
  49. sqlspec/{statement/builder → builder}/_base.py +120 -55
  50. sqlspec/{statement/builder → builder}/_column.py +17 -6
  51. sqlspec/{statement/builder → builder}/_ddl.py +46 -79
  52. sqlspec/{statement/builder → builder}/_ddl_utils.py +5 -10
  53. sqlspec/{statement/builder → builder}/_delete.py +6 -25
  54. sqlspec/{statement/builder → builder}/_insert.py +18 -65
  55. sqlspec/builder/_merge.py +56 -0
  56. sqlspec/{statement/builder → builder}/_parsing_utils.py +8 -11
  57. sqlspec/{statement/builder → builder}/_select.py +11 -56
  58. sqlspec/{statement/builder → builder}/_update.py +12 -18
  59. sqlspec/{statement/builder → builder}/mixins/__init__.py +10 -14
  60. sqlspec/{statement/builder → builder}/mixins/_cte_and_set_ops.py +48 -59
  61. sqlspec/{statement/builder → builder}/mixins/_insert_operations.py +34 -18
  62. sqlspec/{statement/builder → builder}/mixins/_join_operations.py +1 -3
  63. sqlspec/{statement/builder → builder}/mixins/_merge_operations.py +19 -9
  64. sqlspec/{statement/builder → builder}/mixins/_order_limit_operations.py +3 -3
  65. sqlspec/{statement/builder → builder}/mixins/_pivot_operations.py +4 -8
  66. sqlspec/{statement/builder → builder}/mixins/_select_operations.py +25 -38
  67. sqlspec/{statement/builder → builder}/mixins/_update_operations.py +15 -16
  68. sqlspec/{statement/builder → builder}/mixins/_where_clause.py +210 -137
  69. sqlspec/cli.py +4 -5
  70. sqlspec/config.py +180 -133
  71. sqlspec/core/__init__.py +63 -0
  72. sqlspec/core/cache.py +873 -0
  73. sqlspec/core/compiler.py +396 -0
  74. sqlspec/core/filters.py +830 -0
  75. sqlspec/core/hashing.py +310 -0
  76. sqlspec/core/parameters.py +1209 -0
  77. sqlspec/core/result.py +664 -0
  78. sqlspec/{statement → core}/splitter.py +321 -191
  79. sqlspec/core/statement.py +666 -0
  80. sqlspec/driver/__init__.py +7 -10
  81. sqlspec/driver/_async.py +387 -176
  82. sqlspec/driver/_common.py +527 -289
  83. sqlspec/driver/_sync.py +390 -172
  84. sqlspec/driver/mixins/__init__.py +2 -19
  85. sqlspec/driver/mixins/_result_tools.py +164 -0
  86. sqlspec/driver/mixins/_sql_translator.py +6 -3
  87. sqlspec/exceptions.py +5 -252
  88. sqlspec/extensions/aiosql/adapter.py +93 -96
  89. sqlspec/extensions/litestar/cli.py +1 -1
  90. sqlspec/extensions/litestar/config.py +0 -1
  91. sqlspec/extensions/litestar/handlers.py +15 -26
  92. sqlspec/extensions/litestar/plugin.py +18 -16
  93. sqlspec/extensions/litestar/providers.py +17 -52
  94. sqlspec/loader.py +424 -105
  95. sqlspec/migrations/__init__.py +12 -0
  96. sqlspec/migrations/base.py +92 -68
  97. sqlspec/migrations/commands.py +24 -106
  98. sqlspec/migrations/loaders.py +402 -0
  99. sqlspec/migrations/runner.py +49 -51
  100. sqlspec/migrations/tracker.py +31 -44
  101. sqlspec/migrations/utils.py +64 -24
  102. sqlspec/protocols.py +7 -183
  103. sqlspec/storage/__init__.py +1 -1
  104. sqlspec/storage/backends/base.py +37 -40
  105. sqlspec/storage/backends/fsspec.py +136 -112
  106. sqlspec/storage/backends/obstore.py +138 -160
  107. sqlspec/storage/capabilities.py +5 -4
  108. sqlspec/storage/registry.py +57 -106
  109. sqlspec/typing.py +136 -115
  110. sqlspec/utils/__init__.py +2 -3
  111. sqlspec/utils/correlation.py +0 -3
  112. sqlspec/utils/deprecation.py +6 -6
  113. sqlspec/utils/fixtures.py +6 -6
  114. sqlspec/utils/logging.py +0 -2
  115. sqlspec/utils/module_loader.py +7 -12
  116. sqlspec/utils/singleton.py +0 -1
  117. sqlspec/utils/sync_tools.py +17 -38
  118. sqlspec/utils/text.py +12 -51
  119. sqlspec/utils/type_guards.py +443 -232
  120. {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/METADATA +7 -2
  121. sqlspec-0.16.0.dist-info/RECORD +134 -0
  122. sqlspec/adapters/adbc/transformers.py +0 -108
  123. sqlspec/driver/connection.py +0 -207
  124. sqlspec/driver/mixins/_cache.py +0 -114
  125. sqlspec/driver/mixins/_csv_writer.py +0 -91
  126. sqlspec/driver/mixins/_pipeline.py +0 -508
  127. sqlspec/driver/mixins/_query_tools.py +0 -796
  128. sqlspec/driver/mixins/_result_utils.py +0 -138
  129. sqlspec/driver/mixins/_storage.py +0 -912
  130. sqlspec/driver/mixins/_type_coercion.py +0 -128
  131. sqlspec/driver/parameters.py +0 -138
  132. sqlspec/statement/__init__.py +0 -21
  133. sqlspec/statement/builder/_merge.py +0 -95
  134. sqlspec/statement/cache.py +0 -50
  135. sqlspec/statement/filters.py +0 -625
  136. sqlspec/statement/parameters.py +0 -956
  137. sqlspec/statement/pipelines/__init__.py +0 -210
  138. sqlspec/statement/pipelines/analyzers/__init__.py +0 -9
  139. sqlspec/statement/pipelines/analyzers/_analyzer.py +0 -646
  140. sqlspec/statement/pipelines/context.py +0 -109
  141. sqlspec/statement/pipelines/transformers/__init__.py +0 -7
  142. sqlspec/statement/pipelines/transformers/_expression_simplifier.py +0 -88
  143. sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +0 -1247
  144. sqlspec/statement/pipelines/transformers/_remove_comments_and_hints.py +0 -76
  145. sqlspec/statement/pipelines/validators/__init__.py +0 -23
  146. sqlspec/statement/pipelines/validators/_dml_safety.py +0 -290
  147. sqlspec/statement/pipelines/validators/_parameter_style.py +0 -370
  148. sqlspec/statement/pipelines/validators/_performance.py +0 -714
  149. sqlspec/statement/pipelines/validators/_security.py +0 -967
  150. sqlspec/statement/result.py +0 -435
  151. sqlspec/statement/sql.py +0 -1774
  152. sqlspec/utils/cached_property.py +0 -25
  153. sqlspec/utils/statement_hashing.py +0 -203
  154. sqlspec-0.14.1.dist-info/RECORD +0 -145
  155. /sqlspec/{statement/builder → builder}/mixins/_delete_operations.py +0 -0
  156. {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/WHEEL +0 -0
  157. {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/entry_points.txt +0 -0
  158. {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/licenses/LICENSE +0 -0
  159. {sqlspec-0.14.1.dist-info → sqlspec-0.16.0.dist-info}/licenses/NOTICE +0 -0
@@ -2,15 +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
9
- from sqlspec.adapters.adbc.transformers import AdbcPostgresTransformer
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
- CONNECTION_FIELDS = frozenset(
25
- {
26
- "uri",
27
- "driver_name",
28
- "db_kwargs",
29
- "conn_kwargs",
30
- "adbc_driver_manager_entrypoint",
31
- "autocommit",
32
- "isolation_level",
33
- "batch_size",
34
- "query_timeout",
35
- "connection_timeout",
36
- "ssl_mode",
37
- "ssl_cert",
38
- "ssl_key",
39
- "ssl_ca",
40
- "username",
41
- "password",
42
- "token",
43
- "project_id",
44
- "dataset_id",
45
- "account",
46
- "warehouse",
47
- "database",
48
- "schema",
49
- "role",
50
- "authorization_header",
51
- "grpc_options",
52
- }
53
- )
54
-
55
- __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")
56
58
 
57
59
 
58
60
  class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
59
- """Enhanced ADBC configuration with universal database connectivity.
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 high-performance Arrow-native data transfer.
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
- - High-performance Arrow data streaming
68
+ - Arrow data streaming
67
69
  - Bulk ingestion operations
68
70
  - Multiple database backends (PostgreSQL, SQLite, DuckDB, BigQuery, Snowflake, etc.)
69
- - Intelligent driver path resolution
71
+ - Driver path resolution
70
72
  - Cloud database integrations
71
73
  """
72
74
 
73
- is_async: ClassVar[bool] = False
74
- supports_connection_pooling: ClassVar[bool] = False
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
- statement_config: Optional[SQLConfig] = None,
89
- default_row_type: type[DictRow] = DictRow,
90
- on_connection_create: Optional[Callable[[AdbcConnection], None]] = None,
91
- # Core connection parameters
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 with universal connectivity features.
85
+ """Initialize ADBC configuration.
129
86
 
130
87
  Args:
88
+ connection_config: Connection configuration parameters
131
89
  statement_config: Default SQL statement configuration
132
- instrumentation: Instrumentation configuration
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
- # Store connection parameters as instance attributes
187
- self.uri = uri
188
- self.driver_name = driver_name
189
- self.db_kwargs = db_kwargs
190
- self.conn_kwargs = conn_kwargs
191
- self.adbc_driver_manager_entrypoint = adbc_driver_manager_entrypoint
192
- self.autocommit = autocommit
193
- self.isolation_level = isolation_level
194
- self.batch_size = batch_size
195
- self.query_timeout = query_timeout
196
- self.connection_timeout = connection_timeout
197
- self.ssl_mode = ssl_mode
198
- self.ssl_cert = ssl_cert
199
- self.ssl_key = ssl_key
200
- self.ssl_ca = ssl_ca
201
- self.username = username
202
- self.password = password
203
- self.token = token
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
- # Could not determine driver
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") # $1, $2, ...
231
+ return (("numeric",), "numeric")
357
232
  if "sqlite" in driver_path:
358
- return (("qmark", "named_colon"), "qmark") # ? or :name
233
+ return (("qmark", "named_colon"), "qmark")
359
234
  if "duckdb" in driver_path:
360
- return (("qmark", "numeric"), "qmark") # ? or $1
235
+ return (("qmark", "numeric"), "qmark")
361
236
  if "bigquery" in driver_path:
362
- return (("named_at",), "named_at") # @name
237
+ return (("named_at",), "named_at")
363
238
  if "snowflake" in driver_path:
364
- return (("qmark", "numeric"), "qmark") # ? or :1
239
+ return (("qmark", "numeric"), "qmark")
365
240
 
366
241
  except Exception:
367
- # If we can't determine driver, use defaults
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
- connection = connect_func(**self.connection_config_dict)
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 or "Unknown"
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(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]":
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
- supported_styles, preferred_style = self._get_parameter_styles()
425
-
426
- statement_config = self.statement_config
427
- if statement_config is not None:
428
- if statement_config.dialect is None:
429
- statement_config = replace(statement_config, dialect=self._get_dialect())
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
- @property
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
- # Gather non-None connection parameters
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:] # Remove "sqlite://" # pyright: ignore
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:] # Remove "duckdb://" # pyright: ignore
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
- bigquery_params = ["project_id", "dataset_id", "token"]
330
+ bigquery_parameters = ["project_id", "dataset_id", "token"]
489
331
  db_kwargs = config.get("db_kwargs", {})
490
332
 
491
- for param in bigquery_params:
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