sqlspec 0.9.0__py3-none-any.whl → 0.10.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 (47) hide show
  1. sqlspec/__init__.py +2 -1
  2. sqlspec/adapters/adbc/__init__.py +2 -1
  3. sqlspec/adapters/adbc/config.py +7 -13
  4. sqlspec/adapters/adbc/driver.py +160 -21
  5. sqlspec/adapters/aiosqlite/__init__.py +2 -1
  6. sqlspec/adapters/aiosqlite/config.py +10 -12
  7. sqlspec/adapters/aiosqlite/driver.py +160 -22
  8. sqlspec/adapters/asyncmy/__init__.py +2 -1
  9. sqlspec/adapters/asyncmy/driver.py +158 -22
  10. sqlspec/adapters/asyncpg/config.py +1 -3
  11. sqlspec/adapters/asyncpg/driver.py +143 -5
  12. sqlspec/adapters/bigquery/__init__.py +4 -0
  13. sqlspec/adapters/bigquery/config/__init__.py +3 -0
  14. sqlspec/adapters/bigquery/config/_common.py +40 -0
  15. sqlspec/adapters/bigquery/config/_sync.py +87 -0
  16. sqlspec/adapters/bigquery/driver.py +701 -0
  17. sqlspec/adapters/duckdb/__init__.py +2 -1
  18. sqlspec/adapters/duckdb/config.py +17 -18
  19. sqlspec/adapters/duckdb/driver.py +165 -27
  20. sqlspec/adapters/oracledb/__init__.py +8 -1
  21. sqlspec/adapters/oracledb/config/_asyncio.py +7 -8
  22. sqlspec/adapters/oracledb/config/_sync.py +6 -7
  23. sqlspec/adapters/oracledb/driver.py +311 -42
  24. sqlspec/adapters/psqlpy/__init__.py +9 -0
  25. sqlspec/adapters/psqlpy/config.py +11 -19
  26. sqlspec/adapters/psqlpy/driver.py +171 -19
  27. sqlspec/adapters/psycopg/__init__.py +8 -1
  28. sqlspec/adapters/psycopg/config/__init__.py +10 -0
  29. sqlspec/adapters/psycopg/config/_async.py +6 -7
  30. sqlspec/adapters/psycopg/config/_sync.py +7 -8
  31. sqlspec/adapters/psycopg/driver.py +344 -86
  32. sqlspec/adapters/sqlite/__init__.py +2 -1
  33. sqlspec/adapters/sqlite/config.py +12 -11
  34. sqlspec/adapters/sqlite/driver.py +160 -51
  35. sqlspec/base.py +402 -63
  36. sqlspec/exceptions.py +9 -0
  37. sqlspec/extensions/litestar/config.py +3 -11
  38. sqlspec/extensions/litestar/handlers.py +2 -1
  39. sqlspec/extensions/litestar/plugin.py +6 -2
  40. sqlspec/mixins.py +156 -0
  41. sqlspec/typing.py +19 -1
  42. {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/METADATA +147 -3
  43. sqlspec-0.10.0.dist-info/RECORD +67 -0
  44. sqlspec-0.9.0.dist-info/RECORD +0 -61
  45. {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/WHEEL +0 -0
  46. {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/licenses/LICENSE +0 -0
  47. {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/licenses/NOTICE +0 -0
sqlspec/base.py CHANGED
@@ -1,7 +1,9 @@
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 Awaitable
6
+ from collections.abc import Awaitable, Sequence
5
7
  from dataclasses import dataclass, field
6
8
  from typing import (
7
9
  TYPE_CHECKING,
@@ -18,15 +20,14 @@ from typing import (
18
20
 
19
21
  from sqlspec.exceptions import NotFoundError
20
22
  from sqlspec.statement import SQLStatement
21
- from sqlspec.typing import ModelDTOT, StatementParameterType
23
+ from sqlspec.typing import ConnectionT, ModelDTOT, PoolT, StatementParameterType, T
24
+ from sqlspec.utils.sync_tools import maybe_async_
22
25
 
23
26
  if TYPE_CHECKING:
24
27
  from contextlib import AbstractAsyncContextManager, AbstractContextManager
25
28
 
26
- from pyarrow import Table as ArrowTable
27
29
 
28
30
  __all__ = (
29
- "AsyncArrowBulkOperationsMixin",
30
31
  "AsyncDatabaseConfig",
31
32
  "AsyncDriverAdapterProtocol",
32
33
  "CommonDriverAttributes",
@@ -36,15 +37,10 @@ __all__ = (
36
37
  "NoPoolSyncConfig",
37
38
  "SQLSpec",
38
39
  "SQLStatement",
39
- "SyncArrowBulkOperationsMixin",
40
40
  "SyncDatabaseConfig",
41
41
  "SyncDriverAdapterProtocol",
42
42
  )
43
43
 
44
- T = TypeVar("T")
45
- ConnectionT = TypeVar("ConnectionT")
46
- PoolT = TypeVar("PoolT")
47
- PoolT_co = TypeVar("PoolT_co", covariant=True)
48
44
  AsyncConfigT = TypeVar("AsyncConfigT", bound="Union[AsyncDatabaseConfig[Any, Any, Any], NoPoolAsyncConfig[Any, Any]]")
49
45
  SyncConfigT = TypeVar("SyncConfigT", bound="Union[SyncDatabaseConfig[Any, Any, Any], NoPoolSyncConfig[Any, Any]]")
50
46
  ConfigT = TypeVar(
@@ -202,6 +198,15 @@ class SQLSpec:
202
198
 
203
199
  def __init__(self) -> None:
204
200
  self._configs: dict[Any, DatabaseConfigProtocol[Any, Any, Any]] = {}
201
+ # Register the cleanup handler to run at program exit
202
+ atexit.register(self._cleanup_pools)
203
+
204
+ def _cleanup_pools(self) -> None:
205
+ """Clean up all open database pools at program exit."""
206
+ for config in self._configs.values():
207
+ if config.support_connection_pooling and config.pool_instance is not None:
208
+ with contextlib.suppress(Exception):
209
+ maybe_async_(config.close_pool)()
205
210
 
206
211
  @overload
207
212
  def add_config(self, config: "SyncConfigT") -> "type[SyncConfigT]": ...
@@ -284,6 +289,24 @@ class SQLSpec:
284
289
  config = self.get_config(name)
285
290
  return config.create_connection()
286
291
 
292
+ @overload
293
+ def get_session(
294
+ self,
295
+ name: Union[
296
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
297
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
298
+ ],
299
+ ) -> "DriverT": ...
300
+
301
+ @overload
302
+ def get_session(
303
+ self,
304
+ name: Union[
305
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
306
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
307
+ ],
308
+ ) -> "Awaitable[DriverT]": ...
309
+
287
310
  def get_session(
288
311
  self,
289
312
  name: Union[
@@ -311,6 +334,28 @@ class SQLSpec:
311
334
  return _create_session()
312
335
  return cast("DriverT", config.driver_type(connection)) # pyright: ignore
313
336
 
337
+ @overload
338
+ def provide_connection(
339
+ self,
340
+ name: Union[
341
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
342
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
343
+ ],
344
+ *args: Any,
345
+ **kwargs: Any,
346
+ ) -> "AbstractContextManager[ConnectionT]": ...
347
+
348
+ @overload
349
+ def provide_connection(
350
+ self,
351
+ name: Union[
352
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
353
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
354
+ ],
355
+ *args: Any,
356
+ **kwargs: Any,
357
+ ) -> "AbstractAsyncContextManager[ConnectionT]": ...
358
+
314
359
  def provide_connection(
315
360
  self,
316
361
  name: Union[
@@ -335,6 +380,28 @@ class SQLSpec:
335
380
  config = self.get_config(name)
336
381
  return config.provide_connection(*args, **kwargs)
337
382
 
383
+ @overload
384
+ def provide_session(
385
+ self,
386
+ name: Union[
387
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
388
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
389
+ ],
390
+ *args: Any,
391
+ **kwargs: Any,
392
+ ) -> "AbstractContextManager[DriverT]": ...
393
+
394
+ @overload
395
+ def provide_session(
396
+ self,
397
+ name: Union[
398
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
399
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
400
+ ],
401
+ *args: Any,
402
+ **kwargs: Any,
403
+ ) -> "AbstractAsyncContextManager[DriverT]": ...
404
+
338
405
  def provide_session(
339
406
  self,
340
407
  name: Union[
@@ -393,6 +460,24 @@ class SQLSpec:
393
460
  return cast("Union[type[PoolT], Awaitable[type[PoolT]]]", config.create_pool())
394
461
  return None
395
462
 
463
+ @overload
464
+ def close_pool(
465
+ self,
466
+ name: Union[
467
+ "type[NoPoolSyncConfig[ConnectionT, DriverT]]",
468
+ "type[SyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
469
+ ],
470
+ ) -> "None": ...
471
+
472
+ @overload
473
+ def close_pool(
474
+ self,
475
+ name: Union[
476
+ "type[NoPoolAsyncConfig[ConnectionT, DriverT]]",
477
+ "type[AsyncDatabaseConfig[ConnectionT, PoolT, DriverT]]",
478
+ ],
479
+ ) -> "Awaitable[None]": ...
480
+
396
481
  def close_pool(
397
482
  self,
398
483
  name: Union[
@@ -466,40 +551,37 @@ class CommonDriverAttributes(Generic[ConnectionT]):
466
551
  return stmt.process()
467
552
 
468
553
 
469
- class SyncArrowBulkOperationsMixin(Generic[ConnectionT]):
470
- """Mixin for sync drivers supporting bulk Apache Arrow operations."""
554
+ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generic[ConnectionT]):
555
+ connection: "ConnectionT"
471
556
 
472
- __supports_arrow__: "ClassVar[bool]" = True
557
+ def __init__(self, connection: "ConnectionT", **kwargs: Any) -> None:
558
+ self.connection = connection
473
559
 
560
+ @overload
474
561
  @abstractmethod
475
- def select_arrow( # pyright: ignore[reportUnknownParameterType]
562
+ def select(
476
563
  self,
477
564
  sql: str,
478
565
  parameters: "Optional[StatementParameterType]" = None,
479
566
  /,
480
567
  *,
481
568
  connection: "Optional[ConnectionT]" = None,
569
+ schema_type: None = None,
482
570
  **kwargs: Any,
483
- ) -> "ArrowTable": # pyright: ignore[reportUnknownReturnType]
484
- """Execute a SQL query and return results as an Apache Arrow Table.
571
+ ) -> "Sequence[dict[str, Any]]": ...
485
572
 
486
- Args:
487
- sql: The SQL query string.
488
- parameters: Parameters for the query.
489
- connection: Optional connection override.
490
- **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict.
491
-
492
- Returns:
493
- An Apache Arrow Table containing the query results.
494
- """
495
- raise NotImplementedError
496
-
497
-
498
- class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generic[ConnectionT]):
499
- connection: "ConnectionT"
500
-
501
- def __init__(self, connection: "ConnectionT", **kwargs: Any) -> None:
502
- self.connection = connection
573
+ @overload
574
+ @abstractmethod
575
+ def select(
576
+ self,
577
+ sql: str,
578
+ parameters: "Optional[StatementParameterType]" = None,
579
+ /,
580
+ *,
581
+ connection: "Optional[ConnectionT]" = None,
582
+ schema_type: "type[ModelDTOT]",
583
+ **kwargs: Any,
584
+ ) -> "Sequence[ModelDTOT]": ...
503
585
 
504
586
  @abstractmethod
505
587
  def select(
@@ -511,7 +593,33 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
511
593
  connection: "Optional[ConnectionT]" = None,
512
594
  schema_type: Optional[type[ModelDTOT]] = None,
513
595
  **kwargs: Any,
514
- ) -> "list[Union[ModelDTOT, dict[str, Any]]]": ...
596
+ ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": ...
597
+
598
+ @overload
599
+ @abstractmethod
600
+ def select_one(
601
+ self,
602
+ sql: str,
603
+ parameters: "Optional[StatementParameterType]" = None,
604
+ /,
605
+ *,
606
+ connection: "Optional[ConnectionT]" = None,
607
+ schema_type: None = None,
608
+ **kwargs: Any,
609
+ ) -> "dict[str, Any]": ...
610
+
611
+ @overload
612
+ @abstractmethod
613
+ def select_one(
614
+ self,
615
+ sql: str,
616
+ parameters: "Optional[StatementParameterType]" = None,
617
+ /,
618
+ *,
619
+ connection: "Optional[ConnectionT]" = None,
620
+ schema_type: "type[ModelDTOT]",
621
+ **kwargs: Any,
622
+ ) -> "ModelDTOT": ...
515
623
 
516
624
  @abstractmethod
517
625
  def select_one(
@@ -525,6 +633,32 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
525
633
  **kwargs: Any,
526
634
  ) -> "Union[ModelDTOT, dict[str, Any]]": ...
527
635
 
636
+ @overload
637
+ @abstractmethod
638
+ def select_one_or_none(
639
+ self,
640
+ sql: str,
641
+ parameters: "Optional[StatementParameterType]" = None,
642
+ /,
643
+ *,
644
+ connection: "Optional[ConnectionT]" = None,
645
+ schema_type: None = None,
646
+ **kwargs: Any,
647
+ ) -> "Optional[dict[str, Any]]": ...
648
+
649
+ @overload
650
+ @abstractmethod
651
+ def select_one_or_none(
652
+ self,
653
+ sql: str,
654
+ parameters: "Optional[StatementParameterType]" = None,
655
+ /,
656
+ *,
657
+ connection: "Optional[ConnectionT]" = None,
658
+ schema_type: "type[ModelDTOT]",
659
+ **kwargs: Any,
660
+ ) -> "Optional[ModelDTOT]": ...
661
+
528
662
  @abstractmethod
529
663
  def select_one_or_none(
530
664
  self,
@@ -537,6 +671,32 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
537
671
  **kwargs: Any,
538
672
  ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": ...
539
673
 
674
+ @overload
675
+ @abstractmethod
676
+ def select_value(
677
+ self,
678
+ sql: str,
679
+ parameters: "Optional[StatementParameterType]" = None,
680
+ /,
681
+ *,
682
+ connection: "Optional[ConnectionT]" = None,
683
+ schema_type: None = None,
684
+ **kwargs: Any,
685
+ ) -> "Any": ...
686
+
687
+ @overload
688
+ @abstractmethod
689
+ def select_value(
690
+ self,
691
+ sql: str,
692
+ parameters: "Optional[StatementParameterType]" = None,
693
+ /,
694
+ *,
695
+ connection: "Optional[ConnectionT]" = None,
696
+ schema_type: "type[T]",
697
+ **kwargs: Any,
698
+ ) -> "T": ...
699
+
540
700
  @abstractmethod
541
701
  def select_value(
542
702
  self,
@@ -547,7 +707,33 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
547
707
  connection: Optional[ConnectionT] = None,
548
708
  schema_type: Optional[type[T]] = None,
549
709
  **kwargs: Any,
550
- ) -> "Union[Any, T]": ...
710
+ ) -> "Union[T, Any]": ...
711
+
712
+ @overload
713
+ @abstractmethod
714
+ def select_value_or_none(
715
+ self,
716
+ sql: str,
717
+ parameters: "Optional[StatementParameterType]" = None,
718
+ /,
719
+ *,
720
+ connection: "Optional[ConnectionT]" = None,
721
+ schema_type: None = None,
722
+ **kwargs: Any,
723
+ ) -> "Optional[Any]": ...
724
+
725
+ @overload
726
+ @abstractmethod
727
+ def select_value_or_none(
728
+ self,
729
+ sql: str,
730
+ parameters: "Optional[StatementParameterType]" = None,
731
+ /,
732
+ *,
733
+ connection: "Optional[ConnectionT]" = None,
734
+ schema_type: "type[T]",
735
+ **kwargs: Any,
736
+ ) -> "Optional[T]": ...
551
737
 
552
738
  @abstractmethod
553
739
  def select_value_or_none(
@@ -559,7 +745,7 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
559
745
  connection: Optional[ConnectionT] = None,
560
746
  schema_type: Optional[type[T]] = None,
561
747
  **kwargs: Any,
562
- ) -> "Optional[Union[Any, T]]": ...
748
+ ) -> "Optional[Union[T, Any]]": ...
563
749
 
564
750
  @abstractmethod
565
751
  def insert_update_delete(
@@ -572,6 +758,32 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
572
758
  **kwargs: Any,
573
759
  ) -> int: ...
574
760
 
761
+ @overload
762
+ @abstractmethod
763
+ def insert_update_delete_returning(
764
+ self,
765
+ sql: str,
766
+ parameters: "Optional[StatementParameterType]" = None,
767
+ /,
768
+ *,
769
+ connection: "Optional[ConnectionT]" = None,
770
+ schema_type: None = None,
771
+ **kwargs: Any,
772
+ ) -> "dict[str, Any]": ...
773
+
774
+ @overload
775
+ @abstractmethod
776
+ def insert_update_delete_returning(
777
+ self,
778
+ sql: str,
779
+ parameters: "Optional[StatementParameterType]" = None,
780
+ /,
781
+ *,
782
+ connection: "Optional[ConnectionT]" = None,
783
+ schema_type: "type[ModelDTOT]",
784
+ **kwargs: Any,
785
+ ) -> "ModelDTOT": ...
786
+
575
787
  @abstractmethod
576
788
  def insert_update_delete_returning(
577
789
  self,
@@ -582,7 +794,7 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
582
794
  connection: Optional[ConnectionT] = None,
583
795
  schema_type: Optional[type[ModelDTOT]] = None,
584
796
  **kwargs: Any,
585
- ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": ...
797
+ ) -> "Union[ModelDTOT, dict[str, Any]]": ...
586
798
 
587
799
  @abstractmethod
588
800
  def execute_script(
@@ -596,40 +808,37 @@ class SyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generi
596
808
  ) -> str: ...
597
809
 
598
810
 
599
- class AsyncArrowBulkOperationsMixin(Generic[ConnectionT]):
600
- """Mixin for async drivers supporting bulk Apache Arrow operations."""
811
+ class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generic[ConnectionT]):
812
+ connection: "ConnectionT"
601
813
 
602
- __supports_arrow__: "ClassVar[bool]" = True
814
+ def __init__(self, connection: "ConnectionT") -> None:
815
+ self.connection = connection
603
816
 
817
+ @overload
604
818
  @abstractmethod
605
- async def select_arrow( # pyright: ignore[reportUnknownParameterType]
819
+ async def select(
606
820
  self,
607
821
  sql: str,
608
822
  parameters: "Optional[StatementParameterType]" = None,
609
823
  /,
610
824
  *,
611
825
  connection: "Optional[ConnectionT]" = None,
826
+ schema_type: None = None,
612
827
  **kwargs: Any,
613
- ) -> "ArrowTable": # pyright: ignore[reportUnknownReturnType]
614
- """Execute a SQL query and return results as an Apache Arrow Table.
828
+ ) -> "Sequence[dict[str, Any]]": ...
615
829
 
616
- Args:
617
- sql: The SQL query string.
618
- parameters: Parameters for the query.
619
- connection: Optional connection override.
620
- **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict.
621
-
622
- Returns:
623
- An Apache Arrow Table containing the query results.
624
- """
625
- raise NotImplementedError
626
-
627
-
628
- class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Generic[ConnectionT]):
629
- connection: "ConnectionT"
630
-
631
- def __init__(self, connection: "ConnectionT") -> None:
632
- self.connection = connection
830
+ @overload
831
+ @abstractmethod
832
+ async def select(
833
+ self,
834
+ sql: str,
835
+ parameters: "Optional[StatementParameterType]" = None,
836
+ /,
837
+ *,
838
+ connection: "Optional[ConnectionT]" = None,
839
+ schema_type: "type[ModelDTOT]",
840
+ **kwargs: Any,
841
+ ) -> "Sequence[ModelDTOT]": ...
633
842
 
634
843
  @abstractmethod
635
844
  async def select(
@@ -641,7 +850,33 @@ class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Gener
641
850
  connection: "Optional[ConnectionT]" = None,
642
851
  schema_type: "Optional[type[ModelDTOT]]" = None,
643
852
  **kwargs: Any,
644
- ) -> "list[Union[ModelDTOT, dict[str, Any]]]": ...
853
+ ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]": ...
854
+
855
+ @overload
856
+ @abstractmethod
857
+ async def select_one(
858
+ self,
859
+ sql: str,
860
+ parameters: "Optional[StatementParameterType]" = None,
861
+ /,
862
+ *,
863
+ connection: "Optional[ConnectionT]" = None,
864
+ schema_type: None = None,
865
+ **kwargs: Any,
866
+ ) -> "dict[str, Any]": ...
867
+
868
+ @overload
869
+ @abstractmethod
870
+ async def select_one(
871
+ self,
872
+ sql: str,
873
+ parameters: "Optional[StatementParameterType]" = None,
874
+ /,
875
+ *,
876
+ connection: "Optional[ConnectionT]" = None,
877
+ schema_type: "type[ModelDTOT]",
878
+ **kwargs: Any,
879
+ ) -> "ModelDTOT": ...
645
880
 
646
881
  @abstractmethod
647
882
  async def select_one(
@@ -655,6 +890,32 @@ class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Gener
655
890
  **kwargs: Any,
656
891
  ) -> "Union[ModelDTOT, dict[str, Any]]": ...
657
892
 
893
+ @overload
894
+ @abstractmethod
895
+ async def select_one_or_none(
896
+ self,
897
+ sql: str,
898
+ parameters: "Optional[StatementParameterType]" = None,
899
+ /,
900
+ *,
901
+ connection: "Optional[ConnectionT]" = None,
902
+ schema_type: None = None,
903
+ **kwargs: Any,
904
+ ) -> "Optional[dict[str, Any]]": ...
905
+
906
+ @overload
907
+ @abstractmethod
908
+ async def select_one_or_none(
909
+ self,
910
+ sql: str,
911
+ parameters: "Optional[StatementParameterType]" = None,
912
+ /,
913
+ *,
914
+ connection: "Optional[ConnectionT]" = None,
915
+ schema_type: "type[ModelDTOT]",
916
+ **kwargs: Any,
917
+ ) -> "Optional[ModelDTOT]": ...
918
+
658
919
  @abstractmethod
659
920
  async def select_one_or_none(
660
921
  self,
@@ -667,6 +928,32 @@ class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Gener
667
928
  **kwargs: Any,
668
929
  ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]": ...
669
930
 
931
+ @overload
932
+ @abstractmethod
933
+ async def select_value(
934
+ self,
935
+ sql: str,
936
+ parameters: "Optional[StatementParameterType]" = None,
937
+ /,
938
+ *,
939
+ connection: "Optional[ConnectionT]" = None,
940
+ schema_type: None = None,
941
+ **kwargs: Any,
942
+ ) -> "Any": ...
943
+
944
+ @overload
945
+ @abstractmethod
946
+ async def select_value(
947
+ self,
948
+ sql: str,
949
+ parameters: "Optional[StatementParameterType]" = None,
950
+ /,
951
+ *,
952
+ connection: "Optional[ConnectionT]" = None,
953
+ schema_type: "type[T]",
954
+ **kwargs: Any,
955
+ ) -> "T": ...
956
+
670
957
  @abstractmethod
671
958
  async def select_value(
672
959
  self,
@@ -677,7 +964,33 @@ class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Gener
677
964
  connection: "Optional[ConnectionT]" = None,
678
965
  schema_type: "Optional[type[T]]" = None,
679
966
  **kwargs: Any,
680
- ) -> "Union[Any, T]": ...
967
+ ) -> "Union[T, Any]": ...
968
+
969
+ @overload
970
+ @abstractmethod
971
+ async def select_value_or_none(
972
+ self,
973
+ sql: str,
974
+ parameters: "Optional[StatementParameterType]" = None,
975
+ /,
976
+ *,
977
+ connection: "Optional[ConnectionT]" = None,
978
+ schema_type: None = None,
979
+ **kwargs: Any,
980
+ ) -> "Optional[Any]": ...
981
+
982
+ @overload
983
+ @abstractmethod
984
+ async def select_value_or_none(
985
+ self,
986
+ sql: str,
987
+ parameters: "Optional[StatementParameterType]" = None,
988
+ /,
989
+ *,
990
+ connection: "Optional[ConnectionT]" = None,
991
+ schema_type: "type[T]",
992
+ **kwargs: Any,
993
+ ) -> "Optional[T]": ...
681
994
 
682
995
  @abstractmethod
683
996
  async def select_value_or_none(
@@ -689,7 +1002,7 @@ class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Gener
689
1002
  connection: "Optional[ConnectionT]" = None,
690
1003
  schema_type: "Optional[type[T]]" = None,
691
1004
  **kwargs: Any,
692
- ) -> "Optional[Union[Any, T]]": ...
1005
+ ) -> "Optional[Union[T, Any]]": ...
693
1006
 
694
1007
  @abstractmethod
695
1008
  async def insert_update_delete(
@@ -702,6 +1015,32 @@ class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Gener
702
1015
  **kwargs: Any,
703
1016
  ) -> int: ...
704
1017
 
1018
+ @overload
1019
+ @abstractmethod
1020
+ async def insert_update_delete_returning(
1021
+ self,
1022
+ sql: str,
1023
+ parameters: "Optional[StatementParameterType]" = None,
1024
+ /,
1025
+ *,
1026
+ connection: "Optional[ConnectionT]" = None,
1027
+ schema_type: None = None,
1028
+ **kwargs: Any,
1029
+ ) -> "dict[str, Any]": ...
1030
+
1031
+ @overload
1032
+ @abstractmethod
1033
+ async def insert_update_delete_returning(
1034
+ self,
1035
+ sql: str,
1036
+ parameters: "Optional[StatementParameterType]" = None,
1037
+ /,
1038
+ *,
1039
+ connection: "Optional[ConnectionT]" = None,
1040
+ schema_type: "type[ModelDTOT]",
1041
+ **kwargs: Any,
1042
+ ) -> "ModelDTOT": ...
1043
+
705
1044
  @abstractmethod
706
1045
  async def insert_update_delete_returning(
707
1046
  self,
@@ -712,7 +1051,7 @@ class AsyncDriverAdapterProtocol(CommonDriverAttributes[ConnectionT], ABC, Gener
712
1051
  connection: "Optional[ConnectionT]" = None,
713
1052
  schema_type: "Optional[type[ModelDTOT]]" = None,
714
1053
  **kwargs: Any,
715
- ) -> "Optional[Union[dict[str, Any], ModelDTOT]]": ...
1054
+ ) -> "Union[ModelDTOT, dict[str, Any]]": ...
716
1055
 
717
1056
  @abstractmethod
718
1057
  async def execute_script(
sqlspec/exceptions.py CHANGED
@@ -78,6 +78,15 @@ class SQLParsingError(SQLSpecError):
78
78
  super().__init__(message)
79
79
 
80
80
 
81
+ class SQLConversionError(SQLSpecError):
82
+ """Issues converting SQL statements."""
83
+
84
+ def __init__(self, message: Optional[str] = None) -> None:
85
+ if message is None:
86
+ message = "Issues converting SQL statement."
87
+ super().__init__(message)
88
+
89
+
81
90
  class ParameterStyleMismatchError(SQLSpecError):
82
91
  """Error when parameter style doesn't match SQL placeholder style.
83
92
 
@@ -1,10 +1,6 @@
1
1
  from dataclasses import dataclass, field
2
2
  from typing import TYPE_CHECKING, Callable, Literal, Optional, Union
3
3
 
4
- from sqlspec.base import (
5
- ConnectionT,
6
- PoolT,
7
- )
8
4
  from sqlspec.exceptions import ImproperConfigurationError
9
5
  from sqlspec.extensions.litestar.handlers import (
10
6
  autocommit_handler_maker,
@@ -23,13 +19,9 @@ if TYPE_CHECKING:
23
19
  from litestar.datastructures.state import State
24
20
  from litestar.types import BeforeMessageSendHookHandler, Scope
25
21
 
26
- from sqlspec.base import (
27
- AsyncConfigT,
28
- ConnectionT,
29
- DriverT,
30
- PoolT,
31
- SyncConfigT,
32
- )
22
+ from sqlspec.base import AsyncConfigT, DriverT, SyncConfigT
23
+ from sqlspec.typing import ConnectionT, PoolT
24
+
33
25
 
34
26
  CommitMode = Literal["manual", "autocommit", "autocommit_include_redirect"]
35
27
  DEFAULT_COMMIT_MODE: CommitMode = "manual"