sqlspec 0.17.1__py3-none-any.whl → 0.18.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 (75) hide show
  1. sqlspec/__init__.py +1 -1
  2. sqlspec/_sql.py +54 -159
  3. sqlspec/adapters/adbc/config.py +24 -30
  4. sqlspec/adapters/adbc/driver.py +42 -61
  5. sqlspec/adapters/aiosqlite/config.py +5 -10
  6. sqlspec/adapters/aiosqlite/driver.py +9 -25
  7. sqlspec/adapters/aiosqlite/pool.py +43 -35
  8. sqlspec/adapters/asyncmy/config.py +10 -7
  9. sqlspec/adapters/asyncmy/driver.py +18 -39
  10. sqlspec/adapters/asyncpg/config.py +4 -0
  11. sqlspec/adapters/asyncpg/driver.py +32 -79
  12. sqlspec/adapters/bigquery/config.py +12 -65
  13. sqlspec/adapters/bigquery/driver.py +39 -133
  14. sqlspec/adapters/duckdb/config.py +11 -15
  15. sqlspec/adapters/duckdb/driver.py +61 -85
  16. sqlspec/adapters/duckdb/pool.py +2 -5
  17. sqlspec/adapters/oracledb/_types.py +8 -1
  18. sqlspec/adapters/oracledb/config.py +55 -38
  19. sqlspec/adapters/oracledb/driver.py +35 -92
  20. sqlspec/adapters/oracledb/migrations.py +257 -0
  21. sqlspec/adapters/psqlpy/config.py +13 -9
  22. sqlspec/adapters/psqlpy/driver.py +28 -103
  23. sqlspec/adapters/psycopg/config.py +9 -5
  24. sqlspec/adapters/psycopg/driver.py +107 -175
  25. sqlspec/adapters/sqlite/config.py +7 -5
  26. sqlspec/adapters/sqlite/driver.py +37 -73
  27. sqlspec/adapters/sqlite/pool.py +3 -12
  28. sqlspec/base.py +1 -8
  29. sqlspec/builder/__init__.py +1 -1
  30. sqlspec/builder/_base.py +34 -20
  31. sqlspec/builder/_ddl.py +407 -183
  32. sqlspec/builder/_insert.py +1 -1
  33. sqlspec/builder/mixins/_insert_operations.py +26 -6
  34. sqlspec/builder/mixins/_merge_operations.py +1 -1
  35. sqlspec/builder/mixins/_select_operations.py +1 -5
  36. sqlspec/config.py +32 -13
  37. sqlspec/core/__init__.py +89 -14
  38. sqlspec/core/cache.py +57 -104
  39. sqlspec/core/compiler.py +57 -112
  40. sqlspec/core/filters.py +1 -21
  41. sqlspec/core/hashing.py +13 -47
  42. sqlspec/core/parameters.py +272 -261
  43. sqlspec/core/result.py +12 -27
  44. sqlspec/core/splitter.py +17 -21
  45. sqlspec/core/statement.py +150 -159
  46. sqlspec/driver/_async.py +2 -15
  47. sqlspec/driver/_common.py +16 -95
  48. sqlspec/driver/_sync.py +2 -15
  49. sqlspec/driver/mixins/_result_tools.py +8 -29
  50. sqlspec/driver/mixins/_sql_translator.py +6 -8
  51. sqlspec/exceptions.py +1 -2
  52. sqlspec/loader.py +43 -115
  53. sqlspec/migrations/__init__.py +1 -1
  54. sqlspec/migrations/base.py +34 -45
  55. sqlspec/migrations/commands.py +34 -15
  56. sqlspec/migrations/loaders.py +1 -1
  57. sqlspec/migrations/runner.py +104 -19
  58. sqlspec/migrations/tracker.py +49 -2
  59. sqlspec/protocols.py +3 -6
  60. sqlspec/storage/__init__.py +4 -4
  61. sqlspec/storage/backends/fsspec.py +5 -6
  62. sqlspec/storage/backends/obstore.py +7 -8
  63. sqlspec/storage/registry.py +3 -3
  64. sqlspec/utils/__init__.py +2 -2
  65. sqlspec/utils/logging.py +6 -10
  66. sqlspec/utils/sync_tools.py +27 -4
  67. sqlspec/utils/text.py +6 -1
  68. {sqlspec-0.17.1.dist-info → sqlspec-0.18.0.dist-info}/METADATA +1 -1
  69. sqlspec-0.18.0.dist-info/RECORD +138 -0
  70. sqlspec/builder/_ddl_utils.py +0 -103
  71. sqlspec-0.17.1.dist-info/RECORD +0 -138
  72. {sqlspec-0.17.1.dist-info → sqlspec-0.18.0.dist-info}/WHEEL +0 -0
  73. {sqlspec-0.17.1.dist-info → sqlspec-0.18.0.dist-info}/entry_points.txt +0 -0
  74. {sqlspec-0.17.1.dist-info → sqlspec-0.18.0.dist-info}/licenses/LICENSE +0 -0
  75. {sqlspec-0.17.1.dist-info → sqlspec-0.18.0.dist-info}/licenses/NOTICE +0 -0
@@ -1,4 +1,4 @@
1
- """ADBC database configuration using TypedDict for better maintainability."""
1
+ """ADBC database configuration."""
2
2
 
3
3
  import logging
4
4
  from contextlib import contextmanager
@@ -60,16 +60,11 @@ __all__ = ("AdbcConfig", "AdbcConnectionParams")
60
60
  class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
61
61
  """ADBC configuration for Arrow Database Connectivity.
62
62
 
63
- ADBC (Arrow Database Connectivity) provides a unified interface for connecting
64
- to multiple database systems with Arrow-native data transfer.
63
+ ADBC provides an interface for connecting to multiple database systems
64
+ with Arrow-native data transfer.
65
65
 
66
- This configuration supports:
67
- - Universal driver detection and loading
68
- - Arrow data streaming
69
- - Bulk ingestion operations
70
- - Multiple database backends (PostgreSQL, SQLite, DuckDB, BigQuery, Snowflake, etc.)
71
- - Driver path resolution
72
- - Cloud database integrations
66
+ Supports multiple database backends including PostgreSQL, SQLite, DuckDB,
67
+ BigQuery, and Snowflake with automatic driver detection and loading.
73
68
  """
74
69
 
75
70
  driver_type: ClassVar[type[AdbcDriver]] = AdbcDriver
@@ -79,15 +74,17 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
79
74
  self,
80
75
  *,
81
76
  connection_config: Optional[Union[AdbcConnectionParams, dict[str, Any]]] = None,
82
- statement_config: Optional[StatementConfig] = None,
83
77
  migration_config: Optional[dict[str, Any]] = None,
78
+ statement_config: Optional[StatementConfig] = None,
79
+ driver_features: Optional[dict[str, Any]] = None,
84
80
  ) -> None:
85
- """Initialize ADBC configuration.
81
+ """Initialize configuration.
86
82
 
87
83
  Args:
88
84
  connection_config: Connection configuration parameters
89
- statement_config: Default SQL statement configuration
90
85
  migration_config: Migration configuration
86
+ statement_config: Default SQL statement configuration
87
+ driver_features: Driver feature configuration
91
88
  """
92
89
  if connection_config is None:
93
90
  connection_config = {}
@@ -106,11 +103,11 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
106
103
  connection_config=self.connection_config,
107
104
  migration_config=migration_config,
108
105
  statement_config=statement_config,
109
- driver_features={},
106
+ driver_features=driver_features or {},
110
107
  )
111
108
 
112
109
  def _resolve_driver_name(self) -> str:
113
- """Resolve and normalize the ADBC driver name.
110
+ """Resolve and normalize the driver name.
114
111
 
115
112
  Returns:
116
113
  The normalized driver connect function path.
@@ -164,7 +161,7 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
164
161
  return "adbc_driver_sqlite.dbapi.connect"
165
162
 
166
163
  def _get_connect_func(self) -> Callable[..., AdbcConnection]:
167
- """Get the ADBC driver connect function.
164
+ """Get the driver connect function.
168
165
 
169
166
  Returns:
170
167
  The driver connect function.
@@ -182,7 +179,7 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
182
179
  connect_func = import_string(driver_path_with_suffix)
183
180
  except ImportError as e2:
184
181
  msg = (
185
- f"Failed to import ADBC connect function from '{driver_path}' or "
182
+ f"Failed to import connect function from '{driver_path}' or "
186
183
  f"'{driver_path_with_suffix}'. Is the driver installed? "
187
184
  f"Original errors: {e} / {e2}"
188
185
  )
@@ -195,10 +192,10 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
195
192
  return connect_func # type: ignore[no-any-return]
196
193
 
197
194
  def _get_dialect(self) -> "DialectType":
198
- """Get the SQL dialect type based on the ADBC driver.
195
+ """Get the SQL dialect type based on the driver.
199
196
 
200
197
  Returns:
201
- The SQL dialect type for the ADBC driver.
198
+ The SQL dialect type for the driver.
202
199
  """
203
200
  try:
204
201
  driver_path = self._resolve_driver_name()
@@ -239,14 +236,14 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
239
236
  return (("qmark", "numeric"), "qmark")
240
237
 
241
238
  except Exception:
242
- logger.debug("Error resolving parameter styles for ADBC driver, using defaults")
239
+ logger.debug("Error resolving parameter styles, using defaults")
243
240
  return (("qmark",), "qmark")
244
241
 
245
242
  def create_connection(self) -> AdbcConnection:
246
- """Create and return a new ADBC connection using the specified driver.
243
+ """Create and return a new connection using the specified driver.
247
244
 
248
245
  Returns:
249
- A new ADBC connection instance.
246
+ A new connection instance.
250
247
 
251
248
  Raises:
252
249
  ImproperConfigurationError: If the connection could not be established.
@@ -258,20 +255,20 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
258
255
  connection = connect_func(**connection_config_dict)
259
256
  except Exception as e:
260
257
  driver_name = self.connection_config.get("driver_name", "Unknown")
261
- msg = f"Could not configure ADBC connection using driver '{driver_name}'. Error: {e}"
258
+ msg = f"Could not configure connection using driver '{driver_name}'. Error: {e}"
262
259
  raise ImproperConfigurationError(msg) from e
263
260
  return connection
264
261
 
265
262
  @contextmanager
266
263
  def provide_connection(self, *args: Any, **kwargs: Any) -> "Generator[AdbcConnection, None, None]":
267
- """Provide an ADBC connection context manager.
264
+ """Provide a connection context manager.
268
265
 
269
266
  Args:
270
267
  *args: Additional arguments.
271
268
  **kwargs: Additional keyword arguments.
272
269
 
273
270
  Yields:
274
- An ADBC connection instance.
271
+ A connection instance.
275
272
  """
276
273
  connection = self.create_connection()
277
274
  try:
@@ -282,7 +279,7 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
282
279
  def provide_session(
283
280
  self, *args: Any, statement_config: "Optional[StatementConfig]" = None, **kwargs: Any
284
281
  ) -> "AbstractContextManager[AdbcDriver]":
285
- """Provide an ADBC driver session context manager.
282
+ """Provide a driver session context manager.
286
283
 
287
284
  Args:
288
285
  *args: Additional arguments.
@@ -347,10 +344,7 @@ class AdbcConfig(NoPoolSyncConfig[AdbcConnection, AdbcDriver]):
347
344
  return config
348
345
 
349
346
  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.
347
+ """Get the signature namespace for types.
354
348
 
355
349
  Returns:
356
350
  Dictionary mapping type names to types.
@@ -1,10 +1,8 @@
1
1
  """ADBC driver implementation for Arrow Database Connectivity.
2
2
 
3
- This module provides ADBC driver integration with support for:
4
- - Multi-dialect database connections through ADBC
5
- - Arrow-native data handling with type coercion
6
- - Parameter style conversion for different database backends
7
- - Transaction management with proper error handling
3
+ Provides ADBC driver integration with multi-dialect database connections,
4
+ Arrow-native data handling with type coercion, parameter style conversion
5
+ for different database backends, and transaction management.
8
6
  """
9
7
 
10
8
  import contextlib
@@ -48,7 +46,7 @@ DIALECT_PARAMETER_STYLES = {
48
46
  "postgres": (ParameterStyle.NUMERIC, [ParameterStyle.NUMERIC]),
49
47
  "postgresql": (ParameterStyle.NUMERIC, [ParameterStyle.NUMERIC]),
50
48
  "bigquery": (ParameterStyle.NAMED_AT, [ParameterStyle.NAMED_AT]),
51
- "sqlite": (ParameterStyle.QMARK, [ParameterStyle.QMARK, ParameterStyle.NAMED_COLON]),
49
+ "sqlite": (ParameterStyle.QMARK, [ParameterStyle.QMARK]),
52
50
  "duckdb": (ParameterStyle.QMARK, [ParameterStyle.QMARK, ParameterStyle.NUMERIC, ParameterStyle.NAMED_DOLLAR]),
53
51
  "mysql": (ParameterStyle.POSITIONAL_PYFORMAT, [ParameterStyle.POSITIONAL_PYFORMAT, ParameterStyle.NAMED_PYFORMAT]),
54
52
  "snowflake": (ParameterStyle.QMARK, [ParameterStyle.QMARK, ParameterStyle.NUMERIC]),
@@ -56,17 +54,11 @@ DIALECT_PARAMETER_STYLES = {
56
54
 
57
55
 
58
56
  def _adbc_ast_transformer(expression: Any, parameters: Any) -> tuple[Any, Any]:
59
- """ADBC-specific AST transformer for NULL parameter handling.
57
+ """AST transformer for NULL parameter handling.
60
58
 
61
- For PostgreSQL, this transformer replaces NULL parameter placeholders with NULL literals
59
+ For PostgreSQL, replaces NULL parameter placeholders with NULL literals
62
60
  in the AST to prevent Arrow from inferring 'na' types which cause binding errors.
63
61
 
64
- The transformer:
65
- 1. Detects None parameters in the parameter list
66
- 2. Replaces corresponding placeholders in the AST with NULL literals
67
- 3. Removes the None parameters from the list
68
- 4. Renumbers remaining placeholders to maintain correct mapping
69
-
70
62
  Args:
71
63
  expression: SQLGlot AST expression
72
64
  parameters: Parameter values that may contain None
@@ -77,7 +69,6 @@ def _adbc_ast_transformer(expression: Any, parameters: Any) -> tuple[Any, Any]:
77
69
  if not parameters:
78
70
  return expression, parameters
79
71
 
80
- # Detect NULL parameter positions
81
72
  null_positions = set()
82
73
  if isinstance(parameters, (list, tuple)):
83
74
  for i, param in enumerate(parameters):
@@ -96,47 +87,42 @@ def _adbc_ast_transformer(expression: Any, parameters: Any) -> tuple[Any, Any]:
96
87
  if not null_positions:
97
88
  return expression, parameters
98
89
 
99
- # Track position for QMARK-style placeholders
100
90
  qmark_position = [0]
101
91
 
102
92
  def transform_node(node: Any) -> Any:
103
- """Transform parameter nodes to NULL literals and renumber remaining ones."""
104
- # Handle QMARK-style placeholders (?, ?, ?)
105
93
  if isinstance(node, exp.Placeholder) and (not hasattr(node, "this") or node.this is None):
106
94
  current_pos = qmark_position[0]
107
95
  qmark_position[0] += 1
108
96
 
109
97
  if current_pos in null_positions:
110
98
  return exp.Null()
111
- # Don't renumber QMARK placeholders - they stay as ?
99
+
112
100
  return node
113
101
 
114
- # Handle PostgreSQL-style placeholders ($1, $2, etc.)
115
102
  if isinstance(node, exp.Placeholder) and hasattr(node, "this") and node.this is not None:
116
103
  try:
117
104
  param_str = str(node.this).lstrip("$")
118
105
  param_num = int(param_str)
119
- param_index = param_num - 1 # Convert to 0-based
106
+ param_index = param_num - 1
120
107
 
121
108
  if param_index in null_positions:
122
109
  return exp.Null()
123
- # Renumber placeholder to account for removed NULLs
110
+
124
111
  nulls_before = sum(1 for idx in null_positions if idx < param_index)
125
112
  new_param_num = param_num - nulls_before
126
113
  return exp.Placeholder(this=f"${new_param_num}")
127
114
  except (ValueError, AttributeError):
128
115
  pass
129
116
 
130
- # Handle generic parameter nodes
131
117
  if isinstance(node, exp.Parameter) and hasattr(node, "this"):
132
118
  try:
133
119
  param_str = str(node.this)
134
120
  param_num = int(param_str)
135
- param_index = param_num - 1 # Convert to 0-based
121
+ param_index = param_num - 1
136
122
 
137
123
  if param_index in null_positions:
138
124
  return exp.Null()
139
- # Renumber parameter to account for removed NULLs
125
+
140
126
  nulls_before = sum(1 for idx in null_positions if idx < param_index)
141
127
  new_param_num = param_num - nulls_before
142
128
  return exp.Parameter(this=str(new_param_num))
@@ -145,10 +131,8 @@ def _adbc_ast_transformer(expression: Any, parameters: Any) -> tuple[Any, Any]:
145
131
 
146
132
  return node
147
133
 
148
- # Transform the AST
149
134
  modified_expression = expression.transform(transform_node)
150
135
 
151
- # Remove NULL parameters from the parameter list
152
136
  cleaned_params: Any
153
137
  if isinstance(parameters, (list, tuple)):
154
138
  cleaned_params = [p for i, p in enumerate(parameters) if i not in null_positions]
@@ -167,7 +151,7 @@ def _adbc_ast_transformer(expression: Any, parameters: Any) -> tuple[Any, Any]:
167
151
 
168
152
 
169
153
  def get_adbc_statement_config(detected_dialect: str) -> StatementConfig:
170
- """Create ADBC statement configuration for the specified dialect."""
154
+ """Create statement configuration for the specified dialect."""
171
155
  default_style, supported_styles = DIALECT_PARAMETER_STYLES.get(
172
156
  detected_dialect, (ParameterStyle.QMARK, [ParameterStyle.QMARK])
173
157
  )
@@ -199,14 +183,14 @@ def get_adbc_statement_config(detected_dialect: str) -> StatementConfig:
199
183
 
200
184
 
201
185
  def _convert_array_for_postgres_adbc(value: Any) -> Any:
202
- """Convert array values for PostgreSQL ADBC compatibility."""
186
+ """Convert array values for PostgreSQL compatibility."""
203
187
  if isinstance(value, tuple):
204
188
  return list(value)
205
189
  return value
206
190
 
207
191
 
208
192
  def get_type_coercion_map(dialect: str) -> "dict[type, Any]":
209
- """Get type coercion map for Arrow/ADBC type handling."""
193
+ """Get type coercion map for Arrow type handling."""
210
194
  type_map = {
211
195
  datetime.datetime: lambda x: x,
212
196
  datetime.date: lambda x: x,
@@ -229,7 +213,7 @@ def get_type_coercion_map(dialect: str) -> "dict[type, Any]":
229
213
 
230
214
 
231
215
  class AdbcCursor:
232
- """Context manager for ADBC cursor management."""
216
+ """Context manager for cursor management."""
233
217
 
234
218
  __slots__ = ("connection", "cursor")
235
219
 
@@ -249,7 +233,7 @@ class AdbcCursor:
249
233
 
250
234
 
251
235
  class AdbcExceptionHandler:
252
- """Custom sync context manager for handling ADBC database exceptions."""
236
+ """Context manager for handling database exceptions."""
253
237
 
254
238
  __slots__ = ()
255
239
 
@@ -265,23 +249,23 @@ class AdbcExceptionHandler:
265
249
 
266
250
  if issubclass(exc_type, IntegrityError):
267
251
  e = exc_val
268
- msg = f"ADBC integrity constraint violation: {e}"
252
+ msg = f"Integrity constraint violation: {e}"
269
253
  raise SQLSpecError(msg) from e
270
254
  if issubclass(exc_type, ProgrammingError):
271
255
  e = exc_val
272
256
  error_msg = str(e).lower()
273
257
  if "syntax" in error_msg or "parse" in error_msg:
274
- msg = f"ADBC SQL syntax error: {e}"
258
+ msg = f"SQL syntax error: {e}"
275
259
  raise SQLParsingError(msg) from e
276
- msg = f"ADBC programming error: {e}"
260
+ msg = f"Programming error: {e}"
277
261
  raise SQLSpecError(msg) from e
278
262
  if issubclass(exc_type, OperationalError):
279
263
  e = exc_val
280
- msg = f"ADBC operational error: {e}"
264
+ msg = f"Operational error: {e}"
281
265
  raise SQLSpecError(msg) from e
282
266
  if issubclass(exc_type, DatabaseError):
283
267
  e = exc_val
284
- msg = f"ADBC database error: {e}"
268
+ msg = f"Database error: {e}"
285
269
  raise SQLSpecError(msg) from e
286
270
  except ImportError:
287
271
  pass
@@ -298,11 +282,9 @@ class AdbcExceptionHandler:
298
282
  class AdbcDriver(SyncDriverAdapterBase):
299
283
  """ADBC driver for Arrow Database Connectivity.
300
284
 
301
- Provides database connectivity through ADBC with support for:
302
- - Multi-database dialect support with automatic detection
303
- - Arrow-native data handling with type coercion
304
- - Parameter style conversion for different backends
305
- - Transaction management with proper error handling
285
+ Provides database connectivity through ADBC with multi-database dialect
286
+ support, Arrow-native data handling with type coercion, parameter style
287
+ conversion for different backends, and transaction management.
306
288
  """
307
289
 
308
290
  __slots__ = ("_detected_dialect", "dialect")
@@ -318,17 +300,16 @@ class AdbcDriver(SyncDriverAdapterBase):
318
300
  if statement_config is None:
319
301
  cache_config = get_cache_config()
320
302
  base_config = get_adbc_statement_config(self._detected_dialect)
321
- enhanced_config = base_config.replace(
303
+ statement_config = base_config.replace(
322
304
  enable_caching=cache_config.compiled_cache_enabled, enable_parsing=True, enable_validation=True
323
305
  )
324
- statement_config = enhanced_config
325
306
 
326
307
  super().__init__(connection=connection, statement_config=statement_config, driver_features=driver_features)
327
308
  self.dialect = statement_config.dialect
328
309
 
329
310
  @staticmethod
330
311
  def _ensure_pyarrow_installed() -> None:
331
- """Ensure PyArrow is installed for Arrow operations."""
312
+ """Ensure PyArrow is installed."""
332
313
  from sqlspec.typing import PYARROW_INSTALLED
333
314
 
334
315
  if not PYARROW_INSTALLED:
@@ -336,7 +317,7 @@ class AdbcDriver(SyncDriverAdapterBase):
336
317
 
337
318
  @staticmethod
338
319
  def _get_dialect(connection: "AdbcConnection") -> str:
339
- """Detect database dialect from ADBC connection information."""
320
+ """Detect database dialect from connection information."""
340
321
  try:
341
322
  driver_info = connection.adbc_get_info()
342
323
  vendor_name = driver_info.get("vendor_name", "").lower()
@@ -344,12 +325,12 @@ class AdbcDriver(SyncDriverAdapterBase):
344
325
 
345
326
  for dialect, patterns in DIALECT_PATTERNS.items():
346
327
  if any(pattern in vendor_name or pattern in driver_name for pattern in patterns):
347
- logger.debug("ADBC dialect detected: %s (from %s/%s)", dialect, vendor_name, driver_name)
328
+ logger.debug("Dialect detected: %s (from %s/%s)", dialect, vendor_name, driver_name)
348
329
  return dialect
349
330
  except Exception as e:
350
- logger.debug("ADBC dialect detection failed: %s", e)
331
+ logger.debug("Dialect detection failed: %s", e)
351
332
 
352
- logger.warning("Could not reliably determine ADBC dialect from driver info. Defaulting to 'postgres'.")
333
+ logger.warning("Could not determine dialect from driver info. Defaulting to 'postgres'.")
353
334
  return "postgres"
354
335
 
355
336
  def _handle_postgres_rollback(self, cursor: "Cursor") -> None:
@@ -357,7 +338,7 @@ class AdbcDriver(SyncDriverAdapterBase):
357
338
  if self.dialect == "postgres":
358
339
  with contextlib.suppress(Exception):
359
340
  cursor.execute("ROLLBACK")
360
- logger.debug("PostgreSQL rollback executed after ADBC transaction failure")
341
+ logger.debug("PostgreSQL rollback executed after transaction failure")
361
342
 
362
343
  def _handle_postgres_empty_parameters(self, parameters: Any) -> Any:
363
344
  """Process empty parameters for PostgreSQL compatibility."""
@@ -366,7 +347,7 @@ class AdbcDriver(SyncDriverAdapterBase):
366
347
  return parameters
367
348
 
368
349
  def with_cursor(self, connection: "AdbcConnection") -> "AdbcCursor":
369
- """Create context manager for ADBC cursor."""
350
+ """Create context manager for cursor."""
370
351
  return AdbcCursor(connection)
371
352
 
372
353
  def handle_database_exceptions(self) -> "AbstractContextManager[None]":
@@ -374,10 +355,10 @@ class AdbcDriver(SyncDriverAdapterBase):
374
355
  return AdbcExceptionHandler()
375
356
 
376
357
  def _try_special_handling(self, cursor: "Cursor", statement: SQL) -> "Optional[SQLResult]":
377
- """Handle ADBC-specific operations.
358
+ """Handle special operations.
378
359
 
379
360
  Args:
380
- cursor: ADBC cursor object
361
+ cursor: Cursor object
381
362
  statement: SQL statement to analyze
382
363
 
383
364
  Returns:
@@ -387,7 +368,7 @@ class AdbcDriver(SyncDriverAdapterBase):
387
368
  return None
388
369
 
389
370
  def _execute_many(self, cursor: "Cursor", statement: SQL) -> "ExecutionResult":
390
- """Execute SQL with multiple parameter sets using batch processing."""
371
+ """Execute SQL with multiple parameter sets."""
391
372
  sql, prepared_parameters = self._get_compiled_sql(statement, self.statement_config)
392
373
 
393
374
  try:
@@ -411,13 +392,13 @@ class AdbcDriver(SyncDriverAdapterBase):
411
392
 
412
393
  except Exception:
413
394
  self._handle_postgres_rollback(cursor)
414
- logger.exception("ADBC executemany failed")
395
+ logger.exception("Executemany failed")
415
396
  raise
416
397
 
417
398
  return self.create_execution_result(cursor, rowcount_override=row_count, is_many_result=True)
418
399
 
419
400
  def _execute_statement(self, cursor: "Cursor", statement: SQL) -> "ExecutionResult":
420
- """Execute single SQL statement with ADBC-specific data handling."""
401
+ """Execute single SQL statement."""
421
402
  sql, prepared_parameters = self._get_compiled_sql(statement, self.statement_config)
422
403
 
423
404
  try:
@@ -449,7 +430,7 @@ class AdbcDriver(SyncDriverAdapterBase):
449
430
  return self.create_execution_result(cursor, rowcount_override=row_count)
450
431
 
451
432
  def _execute_script(self, cursor: "Cursor", statement: "SQL") -> "ExecutionResult":
452
- """Execute SQL script with ADBC-specific transaction handling."""
433
+ """Execute SQL script."""
453
434
  if statement.is_script:
454
435
  sql = statement._raw_sql
455
436
  prepared_parameters: list[Any] = []
@@ -473,7 +454,7 @@ class AdbcDriver(SyncDriverAdapterBase):
473
454
  last_rowcount = cursor.rowcount
474
455
  except Exception:
475
456
  self._handle_postgres_rollback(cursor)
476
- logger.exception("ADBC script execution failed")
457
+ logger.exception("Script execution failed")
477
458
  raise
478
459
 
479
460
  return self.create_execution_result(
@@ -490,7 +471,7 @@ class AdbcDriver(SyncDriverAdapterBase):
490
471
  with self.with_cursor(self.connection) as cursor:
491
472
  cursor.execute("BEGIN")
492
473
  except Exception as e:
493
- msg = f"Failed to begin ADBC transaction: {e}"
474
+ msg = f"Failed to begin transaction: {e}"
494
475
  raise SQLSpecError(msg) from e
495
476
 
496
477
  def rollback(self) -> None:
@@ -499,7 +480,7 @@ class AdbcDriver(SyncDriverAdapterBase):
499
480
  with self.with_cursor(self.connection) as cursor:
500
481
  cursor.execute("ROLLBACK")
501
482
  except Exception as e:
502
- msg = f"Failed to rollback ADBC transaction: {e}"
483
+ msg = f"Failed to rollback transaction: {e}"
503
484
  raise SQLSpecError(msg) from e
504
485
 
505
486
  def commit(self) -> None:
@@ -508,5 +489,5 @@ class AdbcDriver(SyncDriverAdapterBase):
508
489
  with self.with_cursor(self.connection) as cursor:
509
490
  cursor.execute("COMMIT")
510
491
  except Exception as e:
511
- msg = f"Failed to commit ADBC transaction: {e}"
492
+ msg = f"Failed to commit transaction: {e}"
512
493
  raise SQLSpecError(msg) from e
@@ -1,4 +1,4 @@
1
- """Aiosqlite database configuration with optimized connection management."""
1
+ """Aiosqlite database configuration."""
2
2
 
3
3
  import logging
4
4
  from contextlib import asynccontextmanager
@@ -61,7 +61,7 @@ class AiosqliteConfig(AsyncDatabaseConfig["AiosqliteConnection", AiosqliteConnec
61
61
  pool_instance: "Optional[AiosqliteConnectionPool]" = None,
62
62
  migration_config: "Optional[dict[str, Any]]" = None,
63
63
  statement_config: "Optional[StatementConfig]" = None,
64
- **kwargs: Any,
64
+ driver_features: "Optional[dict[str, Any]]" = None,
65
65
  ) -> None:
66
66
  """Initialize AioSQLite configuration.
67
67
 
@@ -70,12 +70,10 @@ class AiosqliteConfig(AsyncDatabaseConfig["AiosqliteConnection", AiosqliteConnec
70
70
  pool_instance: Optional pre-configured connection pool instance.
71
71
  migration_config: Optional migration configuration.
72
72
  statement_config: Optional statement configuration.
73
- **kwargs: Additional connection parameters that override pool_config.
73
+ driver_features: Optional driver feature configuration.
74
74
  """
75
75
  config_dict = dict(pool_config) if pool_config else {}
76
- config_dict.update(kwargs) # Allow kwargs to override pool_config values
77
76
 
78
- # Handle memory database URI conversion - test expectation is different than sqlite pattern
79
77
  if "database" not in config_dict or config_dict["database"] == ":memory:":
80
78
  config_dict["database"] = "file::memory:?cache=shared"
81
79
  config_dict["uri"] = True
@@ -85,7 +83,7 @@ class AiosqliteConfig(AsyncDatabaseConfig["AiosqliteConnection", AiosqliteConnec
85
83
  pool_instance=pool_instance,
86
84
  migration_config=migration_config,
87
85
  statement_config=statement_config or aiosqlite_statement_config,
88
- driver_features={},
86
+ driver_features=driver_features or {},
89
87
  )
90
88
 
91
89
  def _get_pool_config_dict(self) -> "dict[str, Any]":
@@ -105,7 +103,7 @@ class AiosqliteConfig(AsyncDatabaseConfig["AiosqliteConnection", AiosqliteConnec
105
103
  Returns:
106
104
  Dictionary with connection parameters for creating connections.
107
105
  """
108
- # Filter out all pool-specific parameters that aiosqlite.connect() doesn't accept
106
+
109
107
  excluded_keys = {
110
108
  "pool_size",
111
109
  "connect_timeout",
@@ -201,9 +199,6 @@ class AiosqliteConfig(AsyncDatabaseConfig["AiosqliteConnection", AiosqliteConnec
201
199
  def get_signature_namespace(self) -> "dict[str, type[Any]]":
202
200
  """Get the signature namespace for aiosqlite types.
203
201
 
204
- This provides all aiosqlite-specific types that Litestar needs to recognize
205
- to avoid serialization attempts.
206
-
207
202
  Returns:
208
203
  Dictionary mapping type names to types.
209
204
  """
@@ -1,11 +1,4 @@
1
- """AIOSQLite driver implementation for async SQLite operations.
2
-
3
- Provides async SQLite database connectivity with:
4
- - Async parameter processing with type coercion
5
- - Thread-safe caching system
6
- - Context management for resource handling
7
- - SQLite-specific optimizations
8
- """
1
+ """AIOSQLite driver implementation for async SQLite operations."""
9
2
 
10
3
  import asyncio
11
4
  import contextlib
@@ -61,7 +54,7 @@ aiosqlite_statement_config = StatementConfig(
61
54
 
62
55
 
63
56
  class AiosqliteCursor:
64
- """Async context manager for AIOSQLite cursor management."""
57
+ """Async context manager for AIOSQLite cursors."""
65
58
 
66
59
  __slots__ = ("connection", "cursor")
67
60
 
@@ -81,7 +74,7 @@ class AiosqliteCursor:
81
74
 
82
75
 
83
76
  class AiosqliteExceptionHandler:
84
- """Custom async context manager for handling AIOSQLite database exceptions."""
77
+ """Async context manager for AIOSQLite database exceptions."""
85
78
 
86
79
  __slots__ = ()
87
80
 
@@ -125,13 +118,7 @@ class AiosqliteExceptionHandler:
125
118
 
126
119
 
127
120
  class AiosqliteDriver(AsyncDriverAdapterBase):
128
- """AIOSQLite driver for async SQLite database operations.
129
-
130
- Provides async SQLite connectivity with:
131
- - Statement processing and parameter handling
132
- - Cursor management and resource cleanup
133
- - Exception handling for SQLite operations
134
- """
121
+ """AIOSQLite driver for async SQLite database operations."""
135
122
 
136
123
  __slots__ = ()
137
124
  dialect = "sqlite"
@@ -170,7 +157,7 @@ class AiosqliteDriver(AsyncDriverAdapterBase):
170
157
  return None
171
158
 
172
159
  async def _execute_script(self, cursor: "aiosqlite.Cursor", statement: "SQL") -> "ExecutionResult":
173
- """Execute SQL script using statement splitting and parameter handling."""
160
+ """Execute SQL script."""
174
161
  sql, prepared_parameters = self._get_compiled_sql(statement, self.statement_config)
175
162
  statements = self.split_script_statements(sql, statement.statement_config, strip_trailing_semicolon=True)
176
163
 
@@ -186,7 +173,7 @@ class AiosqliteDriver(AsyncDriverAdapterBase):
186
173
  )
187
174
 
188
175
  async def _execute_many(self, cursor: "aiosqlite.Cursor", statement: "SQL") -> "ExecutionResult":
189
- """Execute SQL with multiple parameter sets using async batch processing."""
176
+ """Execute SQL with multiple parameter sets."""
190
177
  sql, prepared_parameters = self._get_compiled_sql(statement, self.statement_config)
191
178
 
192
179
  if not prepared_parameters:
@@ -200,7 +187,7 @@ class AiosqliteDriver(AsyncDriverAdapterBase):
200
187
  return self.create_execution_result(cursor, rowcount_override=affected_rows, is_many_result=True)
201
188
 
202
189
  async def _execute_statement(self, cursor: "aiosqlite.Cursor", statement: "SQL") -> "ExecutionResult":
203
- """Execute single SQL statement with async data handling."""
190
+ """Execute single SQL statement."""
204
191
  sql, prepared_parameters = self._get_compiled_sql(statement, self.statement_config)
205
192
  await cursor.execute(sql, prepared_parameters or ())
206
193
 
@@ -218,14 +205,11 @@ class AiosqliteDriver(AsyncDriverAdapterBase):
218
205
  return self.create_execution_result(cursor, rowcount_override=affected_rows)
219
206
 
220
207
  async def begin(self) -> None:
221
- """Begin a database transaction with appropriate locking strategy."""
208
+ """Begin a database transaction."""
222
209
  try:
223
210
  if not self.connection.in_transaction:
224
- # For shared cache databases, use IMMEDIATE to reduce lock contention
225
- # For other databases, BEGIN IMMEDIATE is also safer for concurrent access
226
211
  await self.connection.execute("BEGIN IMMEDIATE")
227
212
  except aiosqlite.Error as e:
228
- # If IMMEDIATE fails due to lock, try with exponential backoff
229
213
  import random
230
214
 
231
215
  max_retries = 3
@@ -235,7 +219,7 @@ class AiosqliteDriver(AsyncDriverAdapterBase):
235
219
  try:
236
220
  await self.connection.execute("BEGIN IMMEDIATE")
237
221
  except aiosqlite.Error:
238
- if attempt == max_retries - 1: # Last attempt
222
+ if attempt == max_retries - 1:
239
223
  break
240
224
  else:
241
225
  return