sqlspec 0.8.0__py3-none-any.whl → 0.9.1__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 (45) hide show
  1. sqlspec/_typing.py +39 -6
  2. sqlspec/adapters/adbc/__init__.py +2 -2
  3. sqlspec/adapters/adbc/config.py +34 -11
  4. sqlspec/adapters/adbc/driver.py +302 -111
  5. sqlspec/adapters/aiosqlite/__init__.py +2 -2
  6. sqlspec/adapters/aiosqlite/config.py +2 -2
  7. sqlspec/adapters/aiosqlite/driver.py +164 -42
  8. sqlspec/adapters/asyncmy/__init__.py +3 -3
  9. sqlspec/adapters/asyncmy/config.py +11 -12
  10. sqlspec/adapters/asyncmy/driver.py +161 -37
  11. sqlspec/adapters/asyncpg/__init__.py +5 -5
  12. sqlspec/adapters/asyncpg/config.py +17 -19
  13. sqlspec/adapters/asyncpg/driver.py +386 -96
  14. sqlspec/adapters/duckdb/__init__.py +2 -2
  15. sqlspec/adapters/duckdb/config.py +2 -2
  16. sqlspec/adapters/duckdb/driver.py +190 -60
  17. sqlspec/adapters/oracledb/__init__.py +8 -8
  18. sqlspec/adapters/oracledb/config/__init__.py +6 -6
  19. sqlspec/adapters/oracledb/config/_asyncio.py +9 -10
  20. sqlspec/adapters/oracledb/config/_sync.py +8 -9
  21. sqlspec/adapters/oracledb/driver.py +384 -45
  22. sqlspec/adapters/psqlpy/__init__.py +0 -0
  23. sqlspec/adapters/psqlpy/config.py +250 -0
  24. sqlspec/adapters/psqlpy/driver.py +481 -0
  25. sqlspec/adapters/psycopg/__init__.py +10 -5
  26. sqlspec/adapters/psycopg/config/__init__.py +6 -6
  27. sqlspec/adapters/psycopg/config/_async.py +12 -12
  28. sqlspec/adapters/psycopg/config/_sync.py +13 -13
  29. sqlspec/adapters/psycopg/driver.py +432 -222
  30. sqlspec/adapters/sqlite/__init__.py +2 -2
  31. sqlspec/adapters/sqlite/config.py +2 -2
  32. sqlspec/adapters/sqlite/driver.py +176 -72
  33. sqlspec/base.py +687 -161
  34. sqlspec/exceptions.py +30 -0
  35. sqlspec/extensions/litestar/config.py +6 -0
  36. sqlspec/extensions/litestar/handlers.py +25 -0
  37. sqlspec/extensions/litestar/plugin.py +8 -1
  38. sqlspec/statement.py +373 -0
  39. sqlspec/typing.py +10 -1
  40. {sqlspec-0.8.0.dist-info → sqlspec-0.9.1.dist-info}/METADATA +144 -2
  41. sqlspec-0.9.1.dist-info/RECORD +61 -0
  42. sqlspec-0.8.0.dist-info/RECORD +0 -57
  43. {sqlspec-0.8.0.dist-info → sqlspec-0.9.1.dist-info}/WHEEL +0 -0
  44. {sqlspec-0.8.0.dist-info → sqlspec-0.9.1.dist-info}/licenses/LICENSE +0 -0
  45. {sqlspec-0.8.0.dist-info → sqlspec-0.9.1.dist-info}/licenses/NOTICE +0 -0
sqlspec/base.py CHANGED
@@ -1,10 +1,12 @@
1
1
  # ruff: noqa: PLR6301
2
+ import atexit
3
+ import contextlib
2
4
  import re
3
5
  from abc import ABC, abstractmethod
4
- from collections.abc import AsyncGenerator, Awaitable, Generator
5
- from contextlib import AbstractAsyncContextManager, AbstractContextManager
6
+ from collections.abc import Awaitable, Sequence
6
7
  from dataclasses import dataclass, field
7
8
  from typing import (
9
+ TYPE_CHECKING,
8
10
  Annotated,
9
11
  Any,
10
12
  ClassVar,
@@ -17,15 +19,29 @@ from typing import (
17
19
  )
18
20
 
19
21
  from sqlspec.exceptions import NotFoundError
22
+ from sqlspec.statement import SQLStatement
20
23
  from sqlspec.typing import ModelDTOT, StatementParameterType
24
+ from sqlspec.utils.sync_tools import maybe_async_
25
+
26
+ if TYPE_CHECKING:
27
+ from contextlib import AbstractAsyncContextManager, AbstractContextManager
28
+
29
+ from pyarrow import Table as ArrowTable
21
30
 
22
31
  __all__ = (
32
+ "AsyncArrowBulkOperationsMixin",
23
33
  "AsyncDatabaseConfig",
34
+ "AsyncDriverAdapterProtocol",
35
+ "CommonDriverAttributes",
24
36
  "DatabaseConfigProtocol",
25
37
  "GenericPoolConfig",
26
38
  "NoPoolAsyncConfig",
27
39
  "NoPoolSyncConfig",
40
+ "SQLSpec",
41
+ "SQLStatement",
42
+ "SyncArrowBulkOperationsMixin",
28
43
  "SyncDatabaseConfig",
44
+ "SyncDriverAdapterProtocol",
29
45
  )
30
46
 
31
47
  T = TypeVar("T")
@@ -39,13 +55,15 @@ ConfigT = TypeVar(
39
55
  bound="Union[Union[AsyncDatabaseConfig[Any, Any, Any], NoPoolAsyncConfig[Any, Any]], SyncDatabaseConfig[Any, Any, Any], NoPoolSyncConfig[Any, Any]]",
40
56
  )
41
57
  DriverT = TypeVar("DriverT", bound="Union[SyncDriverAdapterProtocol[Any], AsyncDriverAdapterProtocol[Any]]")
42
-
43
- # Regex to find :param style placeholders, avoiding those inside quotes
44
- # Handles basic cases, might need refinement for complex SQL
58
+ # Regex to find :param or %(param)s style placeholders, skipping those inside quotes
45
59
  PARAM_REGEX = re.compile(
46
- r"(?P<dquote>\"(?:[^\"]|\"\")*\")|" # Double-quoted strings
47
- r"(?P<squote>'(?:[^']|'')*')|" # Single-quoted strings
48
- r"(?P<lead>[^:]):(?P<var_name>[a-zA-Z_][a-zA-Z0-9_]*)" # :param placeholder
60
+ r"""
61
+ (?P<dquote>"([^"]|\\")*") | # Double-quoted strings
62
+ (?P<squote>'([^']|\\')*') | # Single-quoted strings
63
+ : (?P<var_name_colon>[a-zA-Z_][a-zA-Z0-9_]*) | # :var_name
64
+ % \( (?P<var_name_perc>[a-zA-Z_][a-zA-Z0-9_]*) \) s # %(var_name)s
65
+ """,
66
+ re.VERBOSE,
49
67
  )
50
68
 
51
69
 
@@ -56,14 +74,14 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
56
74
  connection_type: "type[ConnectionT]" = field(init=False)
57
75
  driver_type: "type[DriverT]" = field(init=False)
58
76
  pool_instance: "Optional[PoolT]" = field(default=None)
59
- __is_async__: ClassVar[bool] = False
60
- __supports_connection_pooling__: ClassVar[bool] = False
77
+ __is_async__: "ClassVar[bool]" = False
78
+ __supports_connection_pooling__: "ClassVar[bool]" = False
61
79
 
62
80
  def __hash__(self) -> int:
63
81
  return id(self)
64
82
 
65
83
  @abstractmethod
66
- def create_connection(self) -> Union[ConnectionT, Awaitable[ConnectionT]]:
84
+ def create_connection(self) -> "Union[ConnectionT, Awaitable[ConnectionT]]":
67
85
  """Create and return a new database connection."""
68
86
  raise NotImplementedError
69
87
 
@@ -72,28 +90,32 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
72
90
  self,
73
91
  *args: Any,
74
92
  **kwargs: Any,
75
- ) -> Union[
76
- Generator[ConnectionT, None, None],
77
- AsyncGenerator[ConnectionT, None],
78
- AbstractContextManager[ConnectionT],
79
- AbstractAsyncContextManager[ConnectionT],
80
- ]:
93
+ ) -> "Union[AbstractContextManager[ConnectionT], AbstractAsyncContextManager[ConnectionT]]":
81
94
  """Provide a database connection context manager."""
82
95
  raise NotImplementedError
83
96
 
97
+ @abstractmethod
98
+ def provide_session(
99
+ self,
100
+ *args: Any,
101
+ **kwargs: Any,
102
+ ) -> "Union[AbstractContextManager[DriverT], AbstractAsyncContextManager[DriverT]]":
103
+ """Provide a database session context manager."""
104
+ raise NotImplementedError
105
+
84
106
  @property
85
107
  @abstractmethod
86
- def connection_config_dict(self) -> dict[str, Any]:
108
+ def connection_config_dict(self) -> "dict[str, Any]":
87
109
  """Return the connection configuration as a dict."""
88
110
  raise NotImplementedError
89
111
 
90
112
  @abstractmethod
91
- def create_pool(self) -> Union[PoolT, Awaitable[PoolT]]:
113
+ def create_pool(self) -> "Union[PoolT, Awaitable[PoolT]]":
92
114
  """Create and return connection pool."""
93
115
  raise NotImplementedError
94
116
 
95
117
  @abstractmethod
96
- def close_pool(self) -> Optional[Awaitable[None]]:
118
+ def close_pool(self) -> "Optional[Awaitable[None]]":
97
119
  """Terminate the connection pool."""
98
120
  raise NotImplementedError
99
121
 
@@ -102,7 +124,7 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
102
124
  self,
103
125
  *args: Any,
104
126
  **kwargs: Any,
105
- ) -> Union[PoolT, Awaitable[PoolT], AbstractContextManager[PoolT], AbstractAsyncContextManager[PoolT]]:
127
+ ) -> "Union[PoolT, Awaitable[PoolT], AbstractContextManager[PoolT], AbstractAsyncContextManager[PoolT]]":
106
128
  """Provide pool instance."""
107
129
  raise NotImplementedError
108
130
 
@@ -183,20 +205,26 @@ class SQLSpec:
183
205
 
184
206
  def __init__(self) -> None:
185
207
  self._configs: dict[Any, DatabaseConfigProtocol[Any, Any, Any]] = {}
208
+ # Register the cleanup handler to run at program exit
209
+ atexit.register(self._cleanup_pools)
210
+
211
+ def _cleanup_pools(self) -> None:
212
+ """Clean up all open database pools at program exit."""
213
+ for config in self._configs.values():
214
+ if config.support_connection_pooling and config.pool_instance is not None:
215
+ with contextlib.suppress(Exception):
216
+ maybe_async_(config.close_pool)()
186
217
 
187
218
  @overload
188
- def add_config(self, config: SyncConfigT) -> type[SyncConfigT]: ...
219
+ def add_config(self, config: "SyncConfigT") -> "type[SyncConfigT]": ...
189
220
 
190
221
  @overload
191
- def add_config(self, config: AsyncConfigT) -> type[AsyncConfigT]: ...
222
+ def add_config(self, config: "AsyncConfigT") -> "type[AsyncConfigT]": ...
192
223
 
193
224
  def add_config(
194
225
  self,
195
- config: Union[
196
- SyncConfigT,
197
- AsyncConfigT,
198
- ],
199
- ) -> Union[Annotated[type[SyncConfigT], int], Annotated[type[AsyncConfigT], int]]: # pyright: ignore[reportInvalidTypeVarUse]
226
+ config: "Union[SyncConfigT, AsyncConfigT]",
227
+ ) -> "Union[Annotated[type[SyncConfigT], int], Annotated[type[AsyncConfigT], int]]": # pyright: ignore[reportInvalidTypeVarUse]
200
228
  """Add a new configuration to the manager.
201
229
 
202
230
  Returns:
@@ -207,15 +235,15 @@ class SQLSpec:
207
235
  return key # type: ignore[return-value] # pyright: ignore[reportReturnType]
208
236
 
209
237
  @overload
210
- def get_config(self, name: type[SyncConfigT]) -> SyncConfigT: ...
238
+ def get_config(self, name: "type[SyncConfigT]") -> "SyncConfigT": ...
211
239
 
212
240
  @overload
213
- def get_config(self, name: type[AsyncConfigT]) -> AsyncConfigT: ...
241
+ def get_config(self, name: "type[AsyncConfigT]") -> "AsyncConfigT": ...
214
242
 
215
243
  def get_config(
216
244
  self,
217
- name: Union[type[DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]], Any],
218
- ) -> DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]:
245
+ name: "Union[type[DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]], Any]",
246
+ ) -> "DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]":
219
247
  """Retrieve a configuration by its type.
220
248
 
221
249
  Returns:
@@ -234,61 +262,197 @@ class SQLSpec:
234
262
  def get_connection(
235
263
  self,
236
264
  name: Union[
237
- type[NoPoolSyncConfig[ConnectionT, DriverT]],
238
- type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]], # pyright: ignore[reportInvalidTypeVarUse]
265
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
266
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]", # pyright: ignore[reportInvalidTypeVarUse]
239
267
  ],
240
- ) -> ConnectionT: ...
268
+ ) -> "ConnectionT": ...
241
269
 
242
270
  @overload
243
271
  def get_connection(
244
272
  self,
245
273
  name: Union[
246
- type[NoPoolAsyncConfig[ConnectionT, DriverT]],
247
- type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]], # pyright: ignore[reportInvalidTypeVarUse]
274
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
275
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]", # pyright: ignore[reportInvalidTypeVarUse]
248
276
  ],
249
- ) -> Awaitable[ConnectionT]: ...
277
+ ) -> "Awaitable[ConnectionT]": ...
250
278
 
251
279
  def get_connection(
252
280
  self,
253
281
  name: Union[
254
- type[NoPoolSyncConfig[ConnectionT, DriverT]],
255
- type[NoPoolAsyncConfig[ConnectionT, DriverT]],
256
- type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]],
257
- type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]],
282
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
283
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
284
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
285
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
258
286
  ],
259
- ) -> Union[ConnectionT, Awaitable[ConnectionT]]:
260
- """Create and return a connection from the specified configuration.
287
+ ) -> "Union[ConnectionT, Awaitable[ConnectionT]]":
288
+ """Create and return a new database connection from the specified configuration.
261
289
 
262
290
  Args:
263
291
  name: The configuration type to use for creating the connection.
264
292
 
265
293
  Returns:
266
- Either a connection instance or an awaitable that resolves to a connection,
267
- depending on whether the configuration is sync or async.
294
+ Either a connection instance or an awaitable that resolves to a connection instance.
268
295
  """
269
296
  config = self.get_config(name)
270
297
  return config.create_connection()
271
298
 
299
+ @overload
300
+ def get_session(
301
+ self,
302
+ name: Union[
303
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
304
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
305
+ ],
306
+ ) -> "DriverT": ...
307
+
308
+ @overload
309
+ def get_session(
310
+ self,
311
+ name: Union[
312
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
313
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
314
+ ],
315
+ ) -> "Awaitable[DriverT]": ...
316
+
317
+ def get_session(
318
+ self,
319
+ name: Union[
320
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
321
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
322
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
323
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
324
+ ],
325
+ ) -> "Union[DriverT, Awaitable[DriverT]]":
326
+ """Create and return a new database session from the specified configuration.
327
+
328
+ Args:
329
+ name: The configuration type to use for creating the session.
330
+
331
+ Returns:
332
+ Either a driver instance or an awaitable that resolves to a driver instance.
333
+ """
334
+ config = self.get_config(name)
335
+ connection = self.get_connection(name)
336
+ if isinstance(connection, Awaitable):
337
+
338
+ async def _create_session() -> DriverT:
339
+ return cast("DriverT", config.driver_type(await connection)) # pyright: ignore
340
+
341
+ return _create_session()
342
+ return cast("DriverT", config.driver_type(connection)) # pyright: ignore
343
+
344
+ @overload
345
+ def provide_connection(
346
+ self,
347
+ name: Union[
348
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
349
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
350
+ ],
351
+ *args: Any,
352
+ **kwargs: Any,
353
+ ) -> "AbstractContextManager[ConnectionT]": ...
354
+
355
+ @overload
356
+ def provide_connection(
357
+ self,
358
+ name: Union[
359
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
360
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
361
+ ],
362
+ *args: Any,
363
+ **kwargs: Any,
364
+ ) -> "AbstractAsyncContextManager[ConnectionT]": ...
365
+
366
+ def provide_connection(
367
+ self,
368
+ name: Union[
369
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
370
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
371
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
372
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
373
+ ],
374
+ *args: Any,
375
+ **kwargs: Any,
376
+ ) -> "Union[AbstractContextManager[ConnectionT], AbstractAsyncContextManager[ConnectionT]]":
377
+ """Create and provide a database connection from the specified configuration.
378
+
379
+ Args:
380
+ name: The configuration type to use for creating the connection.
381
+ *args: Positional arguments to pass to the configuration's provide_connection method.
382
+ **kwargs: Keyword arguments to pass to the configuration's provide_connection method.
383
+
384
+ Returns:
385
+ Either a synchronous or asynchronous context manager that provides a database connection.
386
+ """
387
+ config = self.get_config(name)
388
+ return config.provide_connection(*args, **kwargs)
389
+
390
+ @overload
391
+ def provide_session(
392
+ self,
393
+ name: Union[
394
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
395
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
396
+ ],
397
+ *args: Any,
398
+ **kwargs: Any,
399
+ ) -> "AbstractContextManager[DriverT]": ...
400
+
401
+ @overload
402
+ def provide_session(
403
+ self,
404
+ name: Union[
405
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
406
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
407
+ ],
408
+ *args: Any,
409
+ **kwargs: Any,
410
+ ) -> "AbstractAsyncContextManager[DriverT]": ...
411
+
412
+ def provide_session(
413
+ self,
414
+ name: Union[
415
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
416
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
417
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
418
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
419
+ ],
420
+ *args: Any,
421
+ **kwargs: Any,
422
+ ) -> "Union[AbstractContextManager[DriverT], AbstractAsyncContextManager[DriverT]]":
423
+ """Create and provide a database session from the specified configuration.
424
+
425
+ Args:
426
+ name: The configuration type to use for creating the session.
427
+ *args: Positional arguments to pass to the configuration's provide_session method.
428
+ **kwargs: Keyword arguments to pass to the configuration's provide_session method.
429
+
430
+ Returns:
431
+ Either a synchronous or asynchronous context manager that provides a database session.
432
+ """
433
+ config = self.get_config(name)
434
+ return config.provide_session(*args, **kwargs)
435
+
272
436
  @overload
273
437
  def get_pool(
274
- self, name: type[Union[NoPoolSyncConfig[ConnectionT, DriverT], NoPoolAsyncConfig[ConnectionT, DriverT]]]
275
- ) -> None: ... # pyright: ignore[reportInvalidTypeVarUse]
438
+ self, name: "type[Union[NoPoolSyncConfig[ConnectionT, DriverT], NoPoolAsyncConfig[ConnectionT, DriverT]]]"
439
+ ) -> "None": ... # pyright: ignore[reportInvalidTypeVarUse]
276
440
 
277
441
  @overload
278
- def get_pool(self, name: type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]) -> type[PoolT]: ... # pyright: ignore[reportInvalidTypeVarUse]
442
+ def get_pool(self, name: "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]") -> "type[PoolT]": ... # pyright: ignore[reportInvalidTypeVarUse]
279
443
 
280
444
  @overload
281
- def get_pool(self, name: type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]) -> Awaitable[type[PoolT]]: ... # pyright: ignore[reportInvalidTypeVarUse]
445
+ def get_pool(self, name: "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]") -> "Awaitable[type[PoolT]]": ... # pyright: ignore[reportInvalidTypeVarUse]
282
446
 
283
447
  def get_pool(
284
448
  self,
285
449
  name: Union[
286
- type[NoPoolSyncConfig[ConnectionT, DriverT]],
287
- type[NoPoolAsyncConfig[ConnectionT, DriverT]],
288
- type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]],
289
- type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]],
450
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
451
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
452
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
453
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
290
454
  ],
291
- ) -> Union[type[PoolT], Awaitable[type[PoolT]], None]:
455
+ ) -> "Union[type[PoolT], Awaitable[type[PoolT]], None]":
292
456
  """Create and return a connection pool from the specified configuration.
293
457
 
294
458
  Args:
@@ -303,15 +467,33 @@ class SQLSpec:
303
467
  return cast("Union[type[PoolT], Awaitable[type[PoolT]]]", config.create_pool())
304
468
  return None
305
469
 
470
+ @overload
471
+ def close_pool(
472
+ self,
473
+ name: Union[
474
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
475
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
476
+ ],
477
+ ) -> "None": ...
478
+
479
+ @overload
480
+ def close_pool(
481
+ self,
482
+ name: Union[
483
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
484
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
485
+ ],
486
+ ) -> "Awaitable[None]": ...
487
+
306
488
  def close_pool(
307
489
  self,
308
490
  name: Union[
309
- type[NoPoolSyncConfig[ConnectionT, DriverT]],
310
- type[NoPoolAsyncConfig[ConnectionT, DriverT]],
311
- type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]],
312
- type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]],
491
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
492
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
493
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
494
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
313
495
  ],
314
- ) -> Optional[Awaitable[None]]:
496
+ ) -> "Optional[Awaitable[None]]":
315
497
  """Close the connection pool for the specified configuration.
316
498
 
317
499
  Args:
@@ -329,10 +511,12 @@ class SQLSpec:
329
511
  class CommonDriverAttributes(Generic[ConnectionT]):
330
512
  """Common attributes and methods for driver adapters."""
331
513
 
332
- param_style: str = "?"
333
- """The parameter style placeholder supported by the underlying database driver (e.g., '?', '%s')."""
514
+ dialect: str
515
+ """The SQL dialect supported by the underlying database driver (e.g., 'postgres', 'mysql')."""
334
516
  connection: ConnectionT
335
517
  """The connection to the underlying database."""
518
+ __supports_arrow__: ClassVar[bool] = False
519
+ """Indicates if the driver supports Apache Arrow operations."""
336
520
 
337
521
  def _connection(self, connection: "Optional[ConnectionT]" = None) -> "ConnectionT":
338
522
  return connection if connection is not None else self.connection
@@ -355,100 +539,123 @@ class CommonDriverAttributes(Generic[ConnectionT]):
355
539
  raise NotFoundError(msg)
356
540
  return item_or_none
357
541
 
358
- def _process_sql_statement(self, sql: str) -> str:
359
- """Perform any preprocessing of the SQL query string if needed.
360
- Default implementation returns the SQL unchanged.
542
+ def _process_sql_params(
543
+ self, sql: str, parameters: "Optional[StatementParameterType]" = None, /, **kwargs: Any
544
+ ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]":
545
+ """Process SQL query and parameters using SQLStatement for validation and formatting.
361
546
 
362
547
  Args:
363
548
  sql: The SQL query string.
549
+ parameters: Parameters for the query.
550
+ **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict.
364
551
 
365
552
  Returns:
366
- The processed SQL query string.
553
+ A tuple containing the processed SQL query and parameters.
367
554
  """
368
- return sql
555
+ # Instantiate SQLStatement with parameters and kwargs for internal merging
556
+ stmt = SQLStatement(sql=sql, parameters=parameters, dialect=self.dialect, kwargs=kwargs or None)
557
+ # Process uses the merged parameters internally
558
+ return stmt.process()
369
559
 
370
- def _process_sql_params(
371
- self, sql: str, parameters: "Optional[StatementParameterType]" = None
372
- ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]":
373
- """Process SQL query and parameters for DB-API execution.
374
560
 
375
- Converts named parameters (:name) to positional parameters specified by `self.param_style`
376
- if the input parameters are a dictionary.
561
+ class SyncArrowBulkOperationsMixin(Generic[ConnectionT]):
562
+ """Mixin for sync drivers supporting bulk Apache Arrow operations."""
563
+
564
+ __supports_arrow__: "ClassVar[bool]" = True
565
+
566
+ @abstractmethod
567
+ def select_arrow( # pyright: ignore[reportUnknownParameterType]
568
+ self,
569
+ sql: str,
570
+ parameters: "Optional[StatementParameterType]" = None,
571
+ /,
572
+ *,
573
+ connection: "Optional[ConnectionT]" = None,
574
+ **kwargs: Any,
575
+ ) -> "ArrowTable": # pyright: ignore[reportUnknownReturnType]
576
+ """Execute a SQL query and return results as an Apache Arrow Table.
377
577
 
378
578
  Args:
379
579
  sql: The SQL query string.
380
- parameters: The parameters for the query (dict, tuple, list, or None).
580
+ parameters: Parameters for the query.
581
+ connection: Optional connection override.
582
+ **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict.
381
583
 
382
584
  Returns:
383
- A tuple containing the processed SQL string and the processed parameters
384
- (always a tuple or None if the input was a dictionary, otherwise the original type).
385
-
386
- Raises:
387
- ValueError: If a named parameter in the SQL is not found in the dictionary
388
- or if a parameter in the dictionary is not used in the SQL.
585
+ An Apache Arrow Table containing the query results.
389
586
  """
390
- if not isinstance(parameters, dict) or not parameters:
391
- # If parameters are not a dict, or empty dict, assume positional/no params
392
- # Let the underlying driver handle tuples/lists directly
393
- return self._process_sql_statement(sql), parameters
394
-
395
- processed_sql = ""
396
- processed_params_list: list[Any] = []
397
- last_end = 0
398
- found_params: set[str] = set()
399
-
400
- for match in PARAM_REGEX.finditer(sql):
401
- if match.group("dquote") is not None or match.group("squote") is not None:
402
- # Skip placeholders within quotes
403
- continue
404
-
405
- var_name = match.group("var_name")
406
- if var_name is None: # Should not happen with the regex, but safeguard
407
- continue
408
-
409
- if var_name not in parameters:
410
- msg = f"Named parameter ':{var_name}' found in SQL but not provided in parameters dictionary."
411
- raise ValueError(msg)
412
-
413
- # Append segment before the placeholder + the leading character + the driver's positional placeholder
414
- # The match.start("var_name") -1 includes the character before the ':'
415
- processed_sql += sql[last_end : match.start("var_name")] + self.param_style
416
- processed_params_list.append(parameters[var_name])
417
- found_params.add(var_name)
418
- last_end = match.end("var_name")
419
-
420
- # Append the rest of the SQL string
421
- processed_sql += sql[last_end:]
422
-
423
- # Check if all provided parameters were used
424
- unused_params = set(parameters.keys()) - found_params
425
- if unused_params:
426
- msg = f"Parameters provided but not found in SQL: {unused_params}"
427
- # Depending on desired strictness, this could be a warning or an error
428
- # For now, let's raise an error for clarity
429
- raise ValueError(msg)
430
-
431
- processed_params = tuple(processed_params_list)
432
- # Pass the processed SQL through the driver-specific processor if needed
433
- final_sql = self._process_sql_statement(processed_sql)
434
- return final_sql, processed_params
587
+ raise NotImplementedError
435
588
 
436
589
 
437
590
  class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generic[ConnectionT]):
438
- connection: ConnectionT
591
+ connection: "ConnectionT"
439
592
 
440
- def __init__(self, connection: ConnectionT) -> None:
593
+ def __init__(self, connection: "ConnectionT", **kwargs: Any) -> None:
441
594
  self.connection = connection
442
595
 
596
+ @overload
443
597
  @abstractmethod
444
598
  def select(
445
599
  self,
446
600
  sql: str,
447
- parameters: Optional[StatementParameterType] = None,
601
+ parameters: "Optional[StatementParameterType]" = None,
448
602
  /,
449
- connection: Optional[ConnectionT] = None,
603
+ *,
604
+ connection: "Optional[ConnectionT]" = None,
605
+ schema_type: None = None,
606
+ **kwargs: Any,
607
+ ) -> "Sequence[dict[str, Any]]": ...
608
+
609
+ @overload
610
+ @abstractmethod
611
+ def select(
612
+ self,
613
+ sql: str,
614
+ parameters: "Optional[StatementParameterType]" = None,
615
+ /,
616
+ *,
617
+ connection: "Optional[ConnectionT]" = None,
618
+ schema_type: "type[ModelDTOT]",
619
+ **kwargs: Any,
620
+ ) -> "Sequence[ModelDTOT]": ...
621
+
622
+ @abstractmethod
623
+ def select(
624
+ self,
625
+ sql: str,
626
+ parameters: "Optional[StatementParameterType]" = None,
627
+ /,
628
+ *,
629
+ connection: "Optional[ConnectionT]" = None,
450
630
  schema_type: Optional[type[ModelDTOT]] = None,
451
- ) -> "list[Union[ModelDTOT, dict[str, Any]]]": ...
631
+ **kwargs: Any,
632
+ ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": ...
633
+
634
+ @overload
635
+ @abstractmethod
636
+ def select_one(
637
+ self,
638
+ sql: str,
639
+ parameters: "Optional[StatementParameterType]" = None,
640
+ /,
641
+ *,
642
+ connection: "Optional[ConnectionT]" = None,
643
+ schema_type: None = None,
644
+ **kwargs: Any,
645
+ ) -> "dict[str, Any]": ...
646
+
647
+ @overload
648
+ @abstractmethod
649
+ def select_one(
650
+ self,
651
+ sql: str,
652
+ parameters: "Optional[StatementParameterType]" = None,
653
+ /,
654
+ *,
655
+ connection: "Optional[ConnectionT]" = None,
656
+ schema_type: "type[ModelDTOT]",
657
+ **kwargs: Any,
658
+ ) -> "ModelDTOT": ...
452
659
 
453
660
  @abstractmethod
454
661
  def select_one(
@@ -456,29 +663,113 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
456
663
  sql: str,
457
664
  parameters: Optional[StatementParameterType] = None,
458
665
  /,
666
+ *,
459
667
  connection: Optional[ConnectionT] = None,
460
668
  schema_type: Optional[type[ModelDTOT]] = None,
669
+ **kwargs: Any,
461
670
  ) -> "Union[ModelDTOT, dict[str, Any]]": ...
462
671
 
672
+ @overload
673
+ @abstractmethod
674
+ def select_one_or_none(
675
+ self,
676
+ sql: str,
677
+ parameters: "Optional[StatementParameterType]" = None,
678
+ /,
679
+ *,
680
+ connection: "Optional[ConnectionT]" = None,
681
+ schema_type: None = None,
682
+ **kwargs: Any,
683
+ ) -> "Optional[dict[str, Any]]": ...
684
+
685
+ @overload
686
+ @abstractmethod
687
+ def select_one_or_none(
688
+ self,
689
+ sql: str,
690
+ parameters: "Optional[StatementParameterType]" = None,
691
+ /,
692
+ *,
693
+ connection: "Optional[ConnectionT]" = None,
694
+ schema_type: "type[ModelDTOT]",
695
+ **kwargs: Any,
696
+ ) -> "Optional[ModelDTOT]": ...
697
+
463
698
  @abstractmethod
464
699
  def select_one_or_none(
465
700
  self,
466
701
  sql: str,
467
702
  parameters: Optional[StatementParameterType] = None,
468
703
  /,
704
+ *,
469
705
  connection: Optional[ConnectionT] = None,
470
706
  schema_type: Optional[type[ModelDTOT]] = None,
707
+ **kwargs: Any,
471
708
  ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": ...
472
709
 
710
+ @overload
711
+ @abstractmethod
712
+ def select_value(
713
+ self,
714
+ sql: str,
715
+ parameters: "Optional[StatementParameterType]" = None,
716
+ /,
717
+ *,
718
+ connection: "Optional[ConnectionT]" = None,
719
+ schema_type: None = None,
720
+ **kwargs: Any,
721
+ ) -> "Any": ...
722
+
723
+ @overload
724
+ @abstractmethod
725
+ def select_value(
726
+ self,
727
+ sql: str,
728
+ parameters: "Optional[StatementParameterType]" = None,
729
+ /,
730
+ *,
731
+ connection: "Optional[ConnectionT]" = None,
732
+ schema_type: "type[T]",
733
+ **kwargs: Any,
734
+ ) -> "T": ...
735
+
473
736
  @abstractmethod
474
737
  def select_value(
475
738
  self,
476
739
  sql: str,
477
740
  parameters: Optional[StatementParameterType] = None,
478
741
  /,
742
+ *,
479
743
  connection: Optional[ConnectionT] = None,
480
744
  schema_type: Optional[type[T]] = None,
481
- ) -> "Union[Any, T]": ...
745
+ **kwargs: Any,
746
+ ) -> "Union[T, Any]": ...
747
+
748
+ @overload
749
+ @abstractmethod
750
+ def select_value_or_none(
751
+ self,
752
+ sql: str,
753
+ parameters: "Optional[StatementParameterType]" = None,
754
+ /,
755
+ *,
756
+ connection: "Optional[ConnectionT]" = None,
757
+ schema_type: None = None,
758
+ **kwargs: Any,
759
+ ) -> "Optional[Any]": ...
760
+
761
+ @overload
762
+ @abstractmethod
763
+ def select_value_or_none(
764
+ self,
765
+ sql: str,
766
+ parameters: "Optional[StatementParameterType]" = None,
767
+ /,
768
+ *,
769
+ connection: "Optional[ConnectionT]" = None,
770
+ schema_type: "type[T]",
771
+ **kwargs: Any,
772
+ ) -> "Optional[T]": ...
482
773
 
483
774
  @abstractmethod
484
775
  def select_value_or_none(
@@ -486,9 +777,11 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
486
777
  sql: str,
487
778
  parameters: Optional[StatementParameterType] = None,
488
779
  /,
780
+ *,
489
781
  connection: Optional[ConnectionT] = None,
490
782
  schema_type: Optional[type[T]] = None,
491
- ) -> "Optional[Union[Any, T]]": ...
783
+ **kwargs: Any,
784
+ ) -> "Optional[Union[T, Any]]": ...
492
785
 
493
786
  @abstractmethod
494
787
  def insert_update_delete(
@@ -496,18 +789,48 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
496
789
  sql: str,
497
790
  parameters: Optional[StatementParameterType] = None,
498
791
  /,
792
+ *,
499
793
  connection: Optional[ConnectionT] = None,
794
+ **kwargs: Any,
500
795
  ) -> int: ...
501
796
 
797
+ @overload
798
+ @abstractmethod
799
+ def insert_update_delete_returning(
800
+ self,
801
+ sql: str,
802
+ parameters: "Optional[StatementParameterType]" = None,
803
+ /,
804
+ *,
805
+ connection: "Optional[ConnectionT]" = None,
806
+ schema_type: None = None,
807
+ **kwargs: Any,
808
+ ) -> "dict[str, Any]": ...
809
+
810
+ @overload
811
+ @abstractmethod
812
+ def insert_update_delete_returning(
813
+ self,
814
+ sql: str,
815
+ parameters: "Optional[StatementParameterType]" = None,
816
+ /,
817
+ *,
818
+ connection: "Optional[ConnectionT]" = None,
819
+ schema_type: "type[ModelDTOT]",
820
+ **kwargs: Any,
821
+ ) -> "ModelDTOT": ...
822
+
502
823
  @abstractmethod
503
824
  def insert_update_delete_returning(
504
825
  self,
505
826
  sql: str,
506
827
  parameters: Optional[StatementParameterType] = None,
507
828
  /,
829
+ *,
508
830
  connection: Optional[ConnectionT] = None,
509
831
  schema_type: Optional[type[ModelDTOT]] = None,
510
- ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": ...
832
+ **kwargs: Any,
833
+ ) -> "Union[ModelDTOT, dict[str, Any]]": ...
511
834
 
512
835
  @abstractmethod
513
836
  def execute_script(
@@ -515,92 +838,295 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
515
838
  sql: str,
516
839
  parameters: Optional[StatementParameterType] = None,
517
840
  /,
841
+ *,
518
842
  connection: Optional[ConnectionT] = None,
843
+ **kwargs: Any,
519
844
  ) -> str: ...
520
845
 
521
846
 
847
+ class AsyncArrowBulkOperationsMixin(Generic[ConnectionT]):
848
+ """Mixin for async drivers supporting bulk Apache Arrow operations."""
849
+
850
+ __supports_arrow__: "ClassVar[bool]" = True
851
+
852
+ @abstractmethod
853
+ async def select_arrow( # pyright: ignore[reportUnknownParameterType]
854
+ self,
855
+ sql: str,
856
+ parameters: "Optional[StatementParameterType]" = None,
857
+ /,
858
+ *,
859
+ connection: "Optional[ConnectionT]" = None,
860
+ **kwargs: Any,
861
+ ) -> "ArrowTable": # pyright: ignore[reportUnknownReturnType]
862
+ """Execute a SQL query and return results as an Apache Arrow Table.
863
+
864
+ Args:
865
+ sql: The SQL query string.
866
+ parameters: Parameters for the query.
867
+ connection: Optional connection override.
868
+ **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict.
869
+
870
+ Returns:
871
+ An Apache Arrow Table containing the query results.
872
+ """
873
+ raise NotImplementedError
874
+
875
+
522
876
  class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generic[ConnectionT]):
523
- connection: ConnectionT
877
+ connection: "ConnectionT"
524
878
 
525
- def __init__(self, connection: ConnectionT) -> None:
879
+ def __init__(self, connection: "ConnectionT") -> None:
526
880
  self.connection = connection
527
881
 
882
+ @overload
528
883
  @abstractmethod
529
884
  async def select(
530
885
  self,
531
886
  sql: str,
532
- parameters: Optional[StatementParameterType] = None,
887
+ parameters: "Optional[StatementParameterType]" = None,
533
888
  /,
534
- connection: Optional[ConnectionT] = None,
535
- schema_type: Optional[type[ModelDTOT]] = None,
536
- ) -> "list[Union[ModelDTOT, dict[str, Any]]]": ...
889
+ *,
890
+ connection: "Optional[ConnectionT]" = None,
891
+ schema_type: None = None,
892
+ **kwargs: Any,
893
+ ) -> "Sequence[dict[str, Any]]": ...
894
+
895
+ @overload
896
+ @abstractmethod
897
+ async def select(
898
+ self,
899
+ sql: str,
900
+ parameters: "Optional[StatementParameterType]" = None,
901
+ /,
902
+ *,
903
+ connection: "Optional[ConnectionT]" = None,
904
+ schema_type: "type[ModelDTOT]",
905
+ **kwargs: Any,
906
+ ) -> "Sequence[ModelDTOT]": ...
537
907
 
908
+ @abstractmethod
909
+ async def select(
910
+ self,
911
+ sql: str,
912
+ parameters: "Optional[StatementParameterType]" = None,
913
+ /,
914
+ *,
915
+ connection: "Optional[ConnectionT]" = None,
916
+ schema_type: "Optional[type[ModelDTOT]]" = None,
917
+ **kwargs: Any,
918
+ ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": ...
919
+
920
+ @overload
538
921
  @abstractmethod
539
922
  async def select_one(
540
923
  self,
541
924
  sql: str,
542
- parameters: Optional[StatementParameterType] = None,
925
+ parameters: "Optional[StatementParameterType]" = None,
543
926
  /,
544
- connection: Optional[ConnectionT] = None,
545
- schema_type: Optional[type[ModelDTOT]] = None,
927
+ *,
928
+ connection: "Optional[ConnectionT]" = None,
929
+ schema_type: None = None,
930
+ **kwargs: Any,
931
+ ) -> "dict[str, Any]": ...
932
+
933
+ @overload
934
+ @abstractmethod
935
+ async def select_one(
936
+ self,
937
+ sql: str,
938
+ parameters: "Optional[StatementParameterType]" = None,
939
+ /,
940
+ *,
941
+ connection: "Optional[ConnectionT]" = None,
942
+ schema_type: "type[ModelDTOT]",
943
+ **kwargs: Any,
944
+ ) -> "ModelDTOT": ...
945
+
946
+ @abstractmethod
947
+ async def select_one(
948
+ self,
949
+ sql: str,
950
+ parameters: "Optional[StatementParameterType]" = None,
951
+ /,
952
+ *,
953
+ connection: "Optional[ConnectionT]" = None,
954
+ schema_type: "Optional[type[ModelDTOT]]" = None,
955
+ **kwargs: Any,
546
956
  ) -> "Union[ModelDTOT, dict[str, Any]]": ...
547
957
 
958
+ @overload
548
959
  @abstractmethod
549
960
  async def select_one_or_none(
550
961
  self,
551
962
  sql: str,
552
- parameters: Optional[StatementParameterType] = None,
963
+ parameters: "Optional[StatementParameterType]" = None,
553
964
  /,
554
- connection: Optional[ConnectionT] = None,
555
- schema_type: Optional[type[ModelDTOT]] = None,
965
+ *,
966
+ connection: "Optional[ConnectionT]" = None,
967
+ schema_type: None = None,
968
+ **kwargs: Any,
969
+ ) -> "Optional[dict[str, Any]]": ...
970
+
971
+ @overload
972
+ @abstractmethod
973
+ async def select_one_or_none(
974
+ self,
975
+ sql: str,
976
+ parameters: "Optional[StatementParameterType]" = None,
977
+ /,
978
+ *,
979
+ connection: "Optional[ConnectionT]" = None,
980
+ schema_type: "type[ModelDTOT]",
981
+ **kwargs: Any,
982
+ ) -> "Optional[ModelDTOT]": ...
983
+
984
+ @abstractmethod
985
+ async def select_one_or_none(
986
+ self,
987
+ sql: str,
988
+ parameters: "Optional[StatementParameterType]" = None,
989
+ /,
990
+ *,
991
+ connection: "Optional[ConnectionT]" = None,
992
+ schema_type: "Optional[type[ModelDTOT]]" = None,
993
+ **kwargs: Any,
556
994
  ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": ...
557
995
 
996
+ @overload
558
997
  @abstractmethod
559
998
  async def select_value(
560
999
  self,
561
1000
  sql: str,
562
- parameters: Optional[StatementParameterType] = None,
1001
+ parameters: "Optional[StatementParameterType]" = None,
563
1002
  /,
564
- connection: Optional[ConnectionT] = None,
565
- schema_type: Optional[type[T]] = None,
566
- ) -> "Union[Any, T]": ...
1003
+ *,
1004
+ connection: "Optional[ConnectionT]" = None,
1005
+ schema_type: None = None,
1006
+ **kwargs: Any,
1007
+ ) -> "Any": ...
567
1008
 
1009
+ @overload
1010
+ @abstractmethod
1011
+ async def select_value(
1012
+ self,
1013
+ sql: str,
1014
+ parameters: "Optional[StatementParameterType]" = None,
1015
+ /,
1016
+ *,
1017
+ connection: "Optional[ConnectionT]" = None,
1018
+ schema_type: "type[T]",
1019
+ **kwargs: Any,
1020
+ ) -> "T": ...
1021
+
1022
+ @abstractmethod
1023
+ async def select_value(
1024
+ self,
1025
+ sql: str,
1026
+ parameters: "Optional[StatementParameterType]" = None,
1027
+ /,
1028
+ *,
1029
+ connection: "Optional[ConnectionT]" = None,
1030
+ schema_type: "Optional[type[T]]" = None,
1031
+ **kwargs: Any,
1032
+ ) -> "Union[T, Any]": ...
1033
+
1034
+ @overload
568
1035
  @abstractmethod
569
1036
  async def select_value_or_none(
570
1037
  self,
571
1038
  sql: str,
572
- parameters: Optional[StatementParameterType] = None,
1039
+ parameters: "Optional[StatementParameterType]" = None,
573
1040
  /,
574
- connection: Optional[ConnectionT] = None,
575
- schema_type: Optional[type[T]] = None,
576
- ) -> "Optional[Union[Any, T]]": ...
1041
+ *,
1042
+ connection: "Optional[ConnectionT]" = None,
1043
+ schema_type: None = None,
1044
+ **kwargs: Any,
1045
+ ) -> "Optional[Any]": ...
1046
+
1047
+ @overload
1048
+ @abstractmethod
1049
+ async def select_value_or_none(
1050
+ self,
1051
+ sql: str,
1052
+ parameters: "Optional[StatementParameterType]" = None,
1053
+ /,
1054
+ *,
1055
+ connection: "Optional[ConnectionT]" = None,
1056
+ schema_type: "type[T]",
1057
+ **kwargs: Any,
1058
+ ) -> "Optional[T]": ...
1059
+
1060
+ @abstractmethod
1061
+ async def select_value_or_none(
1062
+ self,
1063
+ sql: str,
1064
+ parameters: "Optional[StatementParameterType]" = None,
1065
+ /,
1066
+ *,
1067
+ connection: "Optional[ConnectionT]" = None,
1068
+ schema_type: "Optional[type[T]]" = None,
1069
+ **kwargs: Any,
1070
+ ) -> "Optional[Union[T, Any]]": ...
577
1071
 
578
1072
  @abstractmethod
579
1073
  async def insert_update_delete(
580
1074
  self,
581
1075
  sql: str,
582
- parameters: Optional[StatementParameterType] = None,
1076
+ parameters: "Optional[StatementParameterType]" = None,
583
1077
  /,
584
- connection: Optional[ConnectionT] = None,
1078
+ *,
1079
+ connection: "Optional[ConnectionT]" = None,
1080
+ **kwargs: Any,
585
1081
  ) -> int: ...
586
1082
 
1083
+ @overload
587
1084
  @abstractmethod
588
1085
  async def insert_update_delete_returning(
589
1086
  self,
590
1087
  sql: str,
591
- parameters: Optional[StatementParameterType] = None,
1088
+ parameters: "Optional[StatementParameterType]" = None,
592
1089
  /,
593
- connection: Optional[ConnectionT] = None,
594
- schema_type: Optional[type[ModelDTOT]] = None,
595
- ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": ...
1090
+ *,
1091
+ connection: "Optional[ConnectionT]" = None,
1092
+ schema_type: None = None,
1093
+ **kwargs: Any,
1094
+ ) -> "dict[str, Any]": ...
1095
+
1096
+ @overload
1097
+ @abstractmethod
1098
+ async def insert_update_delete_returning(
1099
+ self,
1100
+ sql: str,
1101
+ parameters: "Optional[StatementParameterType]" = None,
1102
+ /,
1103
+ *,
1104
+ connection: "Optional[ConnectionT]" = None,
1105
+ schema_type: "type[ModelDTOT]",
1106
+ **kwargs: Any,
1107
+ ) -> "ModelDTOT": ...
1108
+
1109
+ @abstractmethod
1110
+ async def insert_update_delete_returning(
1111
+ self,
1112
+ sql: str,
1113
+ parameters: "Optional[StatementParameterType]" = None,
1114
+ /,
1115
+ *,
1116
+ connection: "Optional[ConnectionT]" = None,
1117
+ schema_type: "Optional[type[ModelDTOT]]" = None,
1118
+ **kwargs: Any,
1119
+ ) -> "Union[ModelDTOT, dict[str, Any]]": ...
596
1120
 
597
1121
  @abstractmethod
598
1122
  async def execute_script(
599
1123
  self,
600
1124
  sql: str,
601
- parameters: Optional[StatementParameterType] = None,
1125
+ parameters: "Optional[StatementParameterType]" = None,
602
1126
  /,
603
- connection: Optional[ConnectionT] = None,
1127
+ *,
1128
+ connection: "Optional[ConnectionT]" = None,
1129
+ **kwargs: Any,
604
1130
  ) -> str: ...
605
1131
 
606
1132