sqlspec 0.11.0__py3-none-any.whl → 0.12.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 (155) hide show
  1. sqlspec/__init__.py +16 -3
  2. sqlspec/_serialization.py +3 -10
  3. sqlspec/_sql.py +1147 -0
  4. sqlspec/_typing.py +343 -41
  5. sqlspec/adapters/adbc/__init__.py +2 -6
  6. sqlspec/adapters/adbc/config.py +474 -149
  7. sqlspec/adapters/adbc/driver.py +330 -644
  8. sqlspec/adapters/aiosqlite/__init__.py +2 -6
  9. sqlspec/adapters/aiosqlite/config.py +143 -57
  10. sqlspec/adapters/aiosqlite/driver.py +269 -462
  11. sqlspec/adapters/asyncmy/__init__.py +3 -8
  12. sqlspec/adapters/asyncmy/config.py +247 -202
  13. sqlspec/adapters/asyncmy/driver.py +217 -451
  14. sqlspec/adapters/asyncpg/__init__.py +4 -7
  15. sqlspec/adapters/asyncpg/config.py +329 -176
  16. sqlspec/adapters/asyncpg/driver.py +418 -498
  17. sqlspec/adapters/bigquery/__init__.py +2 -2
  18. sqlspec/adapters/bigquery/config.py +407 -0
  19. sqlspec/adapters/bigquery/driver.py +592 -634
  20. sqlspec/adapters/duckdb/__init__.py +4 -1
  21. sqlspec/adapters/duckdb/config.py +432 -321
  22. sqlspec/adapters/duckdb/driver.py +393 -436
  23. sqlspec/adapters/oracledb/__init__.py +3 -8
  24. sqlspec/adapters/oracledb/config.py +625 -0
  25. sqlspec/adapters/oracledb/driver.py +549 -942
  26. sqlspec/adapters/psqlpy/__init__.py +4 -7
  27. sqlspec/adapters/psqlpy/config.py +372 -203
  28. sqlspec/adapters/psqlpy/driver.py +197 -550
  29. sqlspec/adapters/psycopg/__init__.py +3 -8
  30. sqlspec/adapters/psycopg/config.py +741 -0
  31. sqlspec/adapters/psycopg/driver.py +732 -733
  32. sqlspec/adapters/sqlite/__init__.py +2 -6
  33. sqlspec/adapters/sqlite/config.py +146 -81
  34. sqlspec/adapters/sqlite/driver.py +243 -426
  35. sqlspec/base.py +220 -825
  36. sqlspec/config.py +354 -0
  37. sqlspec/driver/__init__.py +22 -0
  38. sqlspec/driver/_async.py +252 -0
  39. sqlspec/driver/_common.py +338 -0
  40. sqlspec/driver/_sync.py +261 -0
  41. sqlspec/driver/mixins/__init__.py +17 -0
  42. sqlspec/driver/mixins/_pipeline.py +523 -0
  43. sqlspec/driver/mixins/_result_utils.py +122 -0
  44. sqlspec/driver/mixins/_sql_translator.py +35 -0
  45. sqlspec/driver/mixins/_storage.py +993 -0
  46. sqlspec/driver/mixins/_type_coercion.py +131 -0
  47. sqlspec/exceptions.py +299 -7
  48. sqlspec/extensions/aiosql/__init__.py +10 -0
  49. sqlspec/extensions/aiosql/adapter.py +474 -0
  50. sqlspec/extensions/litestar/__init__.py +1 -6
  51. sqlspec/extensions/litestar/_utils.py +1 -5
  52. sqlspec/extensions/litestar/config.py +5 -6
  53. sqlspec/extensions/litestar/handlers.py +13 -12
  54. sqlspec/extensions/litestar/plugin.py +22 -24
  55. sqlspec/extensions/litestar/providers.py +37 -55
  56. sqlspec/loader.py +528 -0
  57. sqlspec/service/__init__.py +3 -0
  58. sqlspec/service/base.py +24 -0
  59. sqlspec/service/pagination.py +26 -0
  60. sqlspec/statement/__init__.py +21 -0
  61. sqlspec/statement/builder/__init__.py +54 -0
  62. sqlspec/statement/builder/_ddl_utils.py +119 -0
  63. sqlspec/statement/builder/_parsing_utils.py +135 -0
  64. sqlspec/statement/builder/base.py +328 -0
  65. sqlspec/statement/builder/ddl.py +1379 -0
  66. sqlspec/statement/builder/delete.py +80 -0
  67. sqlspec/statement/builder/insert.py +274 -0
  68. sqlspec/statement/builder/merge.py +95 -0
  69. sqlspec/statement/builder/mixins/__init__.py +65 -0
  70. sqlspec/statement/builder/mixins/_aggregate_functions.py +151 -0
  71. sqlspec/statement/builder/mixins/_case_builder.py +91 -0
  72. sqlspec/statement/builder/mixins/_common_table_expr.py +91 -0
  73. sqlspec/statement/builder/mixins/_delete_from.py +34 -0
  74. sqlspec/statement/builder/mixins/_from.py +61 -0
  75. sqlspec/statement/builder/mixins/_group_by.py +119 -0
  76. sqlspec/statement/builder/mixins/_having.py +35 -0
  77. sqlspec/statement/builder/mixins/_insert_from_select.py +48 -0
  78. sqlspec/statement/builder/mixins/_insert_into.py +36 -0
  79. sqlspec/statement/builder/mixins/_insert_values.py +69 -0
  80. sqlspec/statement/builder/mixins/_join.py +110 -0
  81. sqlspec/statement/builder/mixins/_limit_offset.py +53 -0
  82. sqlspec/statement/builder/mixins/_merge_clauses.py +405 -0
  83. sqlspec/statement/builder/mixins/_order_by.py +46 -0
  84. sqlspec/statement/builder/mixins/_pivot.py +82 -0
  85. sqlspec/statement/builder/mixins/_returning.py +37 -0
  86. sqlspec/statement/builder/mixins/_select_columns.py +60 -0
  87. sqlspec/statement/builder/mixins/_set_ops.py +122 -0
  88. sqlspec/statement/builder/mixins/_unpivot.py +80 -0
  89. sqlspec/statement/builder/mixins/_update_from.py +54 -0
  90. sqlspec/statement/builder/mixins/_update_set.py +91 -0
  91. sqlspec/statement/builder/mixins/_update_table.py +29 -0
  92. sqlspec/statement/builder/mixins/_where.py +374 -0
  93. sqlspec/statement/builder/mixins/_window_functions.py +86 -0
  94. sqlspec/statement/builder/protocols.py +20 -0
  95. sqlspec/statement/builder/select.py +206 -0
  96. sqlspec/statement/builder/update.py +178 -0
  97. sqlspec/statement/filters.py +571 -0
  98. sqlspec/statement/parameters.py +736 -0
  99. sqlspec/statement/pipelines/__init__.py +67 -0
  100. sqlspec/statement/pipelines/analyzers/__init__.py +9 -0
  101. sqlspec/statement/pipelines/analyzers/_analyzer.py +649 -0
  102. sqlspec/statement/pipelines/base.py +315 -0
  103. sqlspec/statement/pipelines/context.py +119 -0
  104. sqlspec/statement/pipelines/result_types.py +41 -0
  105. sqlspec/statement/pipelines/transformers/__init__.py +8 -0
  106. sqlspec/statement/pipelines/transformers/_expression_simplifier.py +256 -0
  107. sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +623 -0
  108. sqlspec/statement/pipelines/transformers/_remove_comments.py +66 -0
  109. sqlspec/statement/pipelines/transformers/_remove_hints.py +81 -0
  110. sqlspec/statement/pipelines/validators/__init__.py +23 -0
  111. sqlspec/statement/pipelines/validators/_dml_safety.py +275 -0
  112. sqlspec/statement/pipelines/validators/_parameter_style.py +297 -0
  113. sqlspec/statement/pipelines/validators/_performance.py +703 -0
  114. sqlspec/statement/pipelines/validators/_security.py +990 -0
  115. sqlspec/statement/pipelines/validators/base.py +67 -0
  116. sqlspec/statement/result.py +527 -0
  117. sqlspec/statement/splitter.py +701 -0
  118. sqlspec/statement/sql.py +1198 -0
  119. sqlspec/storage/__init__.py +15 -0
  120. sqlspec/storage/backends/__init__.py +0 -0
  121. sqlspec/storage/backends/base.py +166 -0
  122. sqlspec/storage/backends/fsspec.py +315 -0
  123. sqlspec/storage/backends/obstore.py +464 -0
  124. sqlspec/storage/protocol.py +170 -0
  125. sqlspec/storage/registry.py +315 -0
  126. sqlspec/typing.py +157 -36
  127. sqlspec/utils/correlation.py +155 -0
  128. sqlspec/utils/deprecation.py +3 -6
  129. sqlspec/utils/fixtures.py +6 -11
  130. sqlspec/utils/logging.py +135 -0
  131. sqlspec/utils/module_loader.py +45 -43
  132. sqlspec/utils/serializers.py +4 -0
  133. sqlspec/utils/singleton.py +6 -8
  134. sqlspec/utils/sync_tools.py +15 -27
  135. sqlspec/utils/text.py +58 -26
  136. {sqlspec-0.11.0.dist-info → sqlspec-0.12.0.dist-info}/METADATA +100 -26
  137. sqlspec-0.12.0.dist-info/RECORD +145 -0
  138. sqlspec/adapters/bigquery/config/__init__.py +0 -3
  139. sqlspec/adapters/bigquery/config/_common.py +0 -40
  140. sqlspec/adapters/bigquery/config/_sync.py +0 -87
  141. sqlspec/adapters/oracledb/config/__init__.py +0 -9
  142. sqlspec/adapters/oracledb/config/_asyncio.py +0 -186
  143. sqlspec/adapters/oracledb/config/_common.py +0 -131
  144. sqlspec/adapters/oracledb/config/_sync.py +0 -186
  145. sqlspec/adapters/psycopg/config/__init__.py +0 -19
  146. sqlspec/adapters/psycopg/config/_async.py +0 -169
  147. sqlspec/adapters/psycopg/config/_common.py +0 -56
  148. sqlspec/adapters/psycopg/config/_sync.py +0 -168
  149. sqlspec/filters.py +0 -330
  150. sqlspec/mixins.py +0 -306
  151. sqlspec/statement.py +0 -378
  152. sqlspec-0.11.0.dist-info/RECORD +0 -69
  153. {sqlspec-0.11.0.dist-info → sqlspec-0.12.0.dist-info}/WHEEL +0 -0
  154. {sqlspec-0.11.0.dist-info → sqlspec-0.12.0.dist-info}/licenses/LICENSE +0 -0
  155. {sqlspec-0.11.0.dist-info → sqlspec-0.12.0.dist-info}/licenses/NOTICE +0 -0
@@ -1,8 +1,4 @@
1
- from sqlspec.adapters.sqlite.config import SqliteConfig
1
+ from sqlspec.adapters.sqlite.config import CONNECTION_FIELDS, SqliteConfig
2
2
  from sqlspec.adapters.sqlite.driver import SqliteConnection, SqliteDriver
3
3
 
4
- __all__ = (
5
- "SqliteConfig",
6
- "SqliteConnection",
7
- "SqliteDriver",
8
- )
4
+ __all__ = ("CONNECTION_FIELDS", "SqliteConfig", "SqliteConnection", "SqliteDriver")
@@ -1,93 +1,148 @@
1
+ """SQLite database configuration with direct field-based configuration."""
2
+
3
+ import logging
1
4
  import sqlite3
2
5
  from contextlib import contextmanager
3
- from dataclasses import dataclass, field
4
- from typing import TYPE_CHECKING, Any, Literal, Optional, Union
6
+ from dataclasses import replace
7
+ from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union
5
8
 
6
9
  from sqlspec.adapters.sqlite.driver import SqliteConnection, SqliteDriver
7
- from sqlspec.base import NoPoolSyncConfig
8
- from sqlspec.exceptions import ImproperConfigurationError
9
- from sqlspec.typing import Empty, EmptyType, dataclass_to_dict
10
+ from sqlspec.config import NoPoolSyncConfig
11
+ from sqlspec.statement.sql import SQLConfig
12
+ from sqlspec.typing import DictRow
10
13
 
11
14
  if TYPE_CHECKING:
12
15
  from collections.abc import Generator
13
16
 
14
-
15
- __all__ = ("SqliteConfig",)
16
-
17
-
18
- @dataclass
19
- class SqliteConfig(NoPoolSyncConfig["SqliteConnection", "SqliteDriver"]):
20
- """Configuration for SQLite database connections.
21
-
22
- This class provides configuration options for SQLite database connections, wrapping all parameters
23
- available to sqlite3.connect().
24
-
25
- For details see: https://docs.python.org/3/library/sqlite3.html#sqlite3.connect
26
- """
27
-
28
- database: str = ":memory:"
29
- """The path to the database file to be opened. Pass ":memory:" to open a connection to a database that resides in RAM instead of on disk."""
30
-
31
- timeout: "Union[float, EmptyType]" = Empty
32
- """How many seconds the connection should wait before raising an OperationalError when a table is locked. If another thread or process has acquired a shared lock, a wait for the specified timeout occurs."""
33
-
34
- detect_types: "Union[int, EmptyType]" = Empty
35
- """Control whether and how data types are detected. It can be 0 (default) or a combination of PARSE_DECLTYPES and PARSE_COLNAMES."""
36
-
37
- isolation_level: "Optional[Union[Literal['DEFERRED', 'IMMEDIATE', 'EXCLUSIVE'], EmptyType]]" = Empty
38
- """The isolation_level of the connection. This can be None for autocommit mode or one of "DEFERRED", "IMMEDIATE" or "EXCLUSIVE"."""
39
-
40
- check_same_thread: "Union[bool, EmptyType]" = Empty
41
- """If True (default), ProgrammingError is raised if the database connection is used by a thread other than the one that created it. If False, the connection may be shared across multiple threads."""
42
-
43
- factory: "Union[type[SqliteConnection], EmptyType]" = Empty
44
- """A custom Connection class factory. If given, must be a callable that returns a Connection instance."""
45
-
46
- cached_statements: "Union[int, EmptyType]" = Empty
47
- """The number of statements that SQLite will cache for this connection. The default is 128."""
48
-
49
- uri: "Union[bool, EmptyType]" = Empty
50
- """If set to True, database is interpreted as a URI with supported options."""
51
- driver_type: "type[SqliteDriver]" = field(init=False, default_factory=lambda: SqliteDriver)
52
- """Type of the driver object"""
53
- connection_type: "type[SqliteConnection]" = field(init=False, default_factory=lambda: SqliteConnection)
54
- """Type of the connection object"""
55
-
56
- @property
57
- def connection_config_dict(self) -> "dict[str, Any]":
58
- """Return the connection configuration as a dict.
59
-
60
- Returns:
61
- A string keyed dict of config kwargs for the sqlite3.connect() function.
17
+ from sqlglot.dialects.dialect import DialectType
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+ CONNECTION_FIELDS = frozenset(
22
+ {
23
+ "database",
24
+ "timeout",
25
+ "detect_types",
26
+ "isolation_level",
27
+ "check_same_thread",
28
+ "factory",
29
+ "cached_statements",
30
+ "uri",
31
+ }
32
+ )
33
+
34
+ __all__ = ("CONNECTION_FIELDS", "SqliteConfig", "sqlite3")
35
+
36
+
37
+ class SqliteConfig(NoPoolSyncConfig[SqliteConnection, SqliteDriver]):
38
+ """Configuration for SQLite database connections with direct field-based configuration."""
39
+
40
+ __slots__ = (
41
+ "_dialect",
42
+ "cached_statements",
43
+ "check_same_thread",
44
+ "database",
45
+ "default_row_type",
46
+ "detect_types",
47
+ "extras",
48
+ "factory",
49
+ "isolation_level",
50
+ "pool_instance",
51
+ "statement_config",
52
+ "timeout",
53
+ "uri",
54
+ )
55
+
56
+ driver_type: type[SqliteDriver] = SqliteDriver
57
+ connection_type: type[SqliteConnection] = SqliteConnection
58
+ supported_parameter_styles: ClassVar[tuple[str, ...]] = ("qmark", "named_colon")
59
+ preferred_parameter_style: ClassVar[str] = "qmark"
60
+
61
+ def __init__(
62
+ self,
63
+ database: str = ":memory:",
64
+ statement_config: Optional[SQLConfig] = None,
65
+ default_row_type: type[DictRow] = DictRow,
66
+ # SQLite connection parameters
67
+ timeout: Optional[float] = None,
68
+ detect_types: Optional[int] = None,
69
+ isolation_level: Optional[Union[str, None]] = None,
70
+ check_same_thread: Optional[bool] = None,
71
+ factory: Optional[type[SqliteConnection]] = None,
72
+ cached_statements: Optional[int] = None,
73
+ uri: Optional[bool] = None,
74
+ **kwargs: Any,
75
+ ) -> None:
76
+ """Initialize SQLite configuration.
77
+
78
+ Args:
79
+ database: Path to the SQLite database file. Use ':memory:' for in-memory database.
80
+ statement_config: Default SQL statement configuration
81
+ default_row_type: Default row type for results
82
+ timeout: Connection timeout in seconds
83
+ detect_types: Type detection flags (sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES)
84
+ isolation_level: Transaction isolation level
85
+ check_same_thread: Whether to check that connection is used on same thread
86
+ factory: Custom Connection class factory
87
+ cached_statements: Number of statements to cache
88
+ uri: Whether to interpret database as URI
89
+ **kwargs: Additional parameters (stored in extras)
62
90
  """
63
- return dataclass_to_dict(
64
- self,
65
- exclude_empty=True,
66
- convert_nested=False,
67
- exclude={"pool_instance", "driver_type", "connection_type"},
68
- )
91
+ # Validate required parameters
92
+ if database is None:
93
+ msg = "database parameter cannot be None"
94
+ raise TypeError(msg)
95
+
96
+ # Store connection parameters as instance attributes
97
+ self.database = database
98
+ self.timeout = timeout
99
+ self.detect_types = detect_types
100
+ self.isolation_level = isolation_level
101
+ self.check_same_thread = check_same_thread
102
+ self.factory = factory
103
+ self.cached_statements = cached_statements
104
+ self.uri = uri
105
+
106
+ self.extras = kwargs or {}
107
+
108
+ # Store other config
109
+ self.statement_config = statement_config or SQLConfig()
110
+ self.default_row_type = default_row_type
111
+ self._dialect: DialectType = None
112
+ super().__init__()
69
113
 
70
- def create_connection(self) -> "SqliteConnection":
71
- """Create and return a new database connection.
72
-
73
- Returns:
74
- A new SQLite connection instance.
75
-
76
- Raises:
77
- ImproperConfigurationError: If the connection could not be established.
78
- """
79
- try:
80
- return sqlite3.connect(**self.connection_config_dict) # type: ignore[no-any-return,unused-ignore]
81
- except Exception as e:
82
- msg = f"Could not configure the SQLite connection. Error: {e!s}"
83
- raise ImproperConfigurationError(msg) from e
114
+ @property
115
+ def connection_config_dict(self) -> dict[str, Any]:
116
+ """Return a dictionary of connection parameters for SQLite."""
117
+ config = {
118
+ "database": self.database,
119
+ "timeout": self.timeout,
120
+ "detect_types": self.detect_types,
121
+ "isolation_level": self.isolation_level,
122
+ "check_same_thread": self.check_same_thread,
123
+ "factory": self.factory,
124
+ "cached_statements": self.cached_statements,
125
+ "uri": self.uri,
126
+ }
127
+ # Filter out None values since sqlite3.connect doesn't accept them
128
+ return {k: v for k, v in config.items() if v is not None}
129
+
130
+ def create_connection(self) -> SqliteConnection:
131
+ """Create and return a SQLite connection."""
132
+ connection = sqlite3.connect(**self.connection_config_dict)
133
+ connection.row_factory = sqlite3.Row
134
+ return connection # type: ignore[no-any-return]
84
135
 
85
136
  @contextmanager
86
- def provide_connection(self, *args: "Any", **kwargs: "Any") -> "Generator[SqliteConnection, None, None]":
87
- """Create and provide a database connection.
137
+ def provide_connection(self, *args: Any, **kwargs: Any) -> "Generator[SqliteConnection, None, None]":
138
+ """Provide a SQLite connection context manager.
139
+
140
+ Args:
141
+ *args: Variable length argument list
142
+ **kwargs: Arbitrary keyword arguments
88
143
 
89
144
  Yields:
90
- A SQLite connection instance.
145
+ SqliteConnection: A SQLite connection
91
146
 
92
147
  """
93
148
  connection = self.create_connection()
@@ -98,12 +153,22 @@ class SqliteConfig(NoPoolSyncConfig["SqliteConnection", "SqliteDriver"]):
98
153
 
99
154
  @contextmanager
100
155
  def provide_session(self, *args: Any, **kwargs: Any) -> "Generator[SqliteDriver, None, None]":
101
- """Create and provide a database connection.
102
-
103
- Yields:
104
- A SQLite driver instance.
156
+ """Provide a SQLite driver session context manager.
105
157
 
158
+ Args:
159
+ *args: Variable length argument list
160
+ **kwargs: Arbitrary keyword arguments
106
161
 
162
+ Yields:
163
+ SqliteDriver: A SQLite driver
107
164
  """
108
165
  with self.provide_connection(*args, **kwargs) as connection:
109
- yield self.driver_type(connection)
166
+ statement_config = self.statement_config
167
+ if statement_config.allowed_parameter_styles is None:
168
+ statement_config = replace(
169
+ statement_config,
170
+ allowed_parameter_styles=self.supported_parameter_styles,
171
+ target_parameter_style=self.preferred_parameter_style,
172
+ )
173
+
174
+ yield self.driver_type(connection=connection, config=statement_config)