sqlspec 0.26.0__py3-none-any.whl → 0.27.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 (197) hide show
  1. sqlspec/__init__.py +7 -15
  2. sqlspec/_serialization.py +55 -25
  3. sqlspec/_typing.py +62 -52
  4. sqlspec/adapters/adbc/_types.py +1 -1
  5. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  6. sqlspec/adapters/adbc/adk/store.py +870 -0
  7. sqlspec/adapters/adbc/config.py +62 -12
  8. sqlspec/adapters/adbc/data_dictionary.py +52 -2
  9. sqlspec/adapters/adbc/driver.py +144 -45
  10. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  11. sqlspec/adapters/adbc/litestar/store.py +504 -0
  12. sqlspec/adapters/adbc/type_converter.py +44 -50
  13. sqlspec/adapters/aiosqlite/_types.py +1 -1
  14. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  15. sqlspec/adapters/aiosqlite/adk/store.py +527 -0
  16. sqlspec/adapters/aiosqlite/config.py +86 -16
  17. sqlspec/adapters/aiosqlite/data_dictionary.py +34 -2
  18. sqlspec/adapters/aiosqlite/driver.py +127 -38
  19. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  20. sqlspec/adapters/aiosqlite/litestar/store.py +281 -0
  21. sqlspec/adapters/aiosqlite/pool.py +7 -7
  22. sqlspec/adapters/asyncmy/__init__.py +7 -1
  23. sqlspec/adapters/asyncmy/_types.py +1 -1
  24. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  25. sqlspec/adapters/asyncmy/adk/store.py +493 -0
  26. sqlspec/adapters/asyncmy/config.py +59 -17
  27. sqlspec/adapters/asyncmy/data_dictionary.py +41 -2
  28. sqlspec/adapters/asyncmy/driver.py +293 -62
  29. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  30. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  31. sqlspec/adapters/asyncpg/__init__.py +2 -1
  32. sqlspec/adapters/asyncpg/_type_handlers.py +71 -0
  33. sqlspec/adapters/asyncpg/_types.py +11 -7
  34. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  35. sqlspec/adapters/asyncpg/adk/store.py +450 -0
  36. sqlspec/adapters/asyncpg/config.py +57 -36
  37. sqlspec/adapters/asyncpg/data_dictionary.py +41 -2
  38. sqlspec/adapters/asyncpg/driver.py +153 -23
  39. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  40. sqlspec/adapters/asyncpg/litestar/store.py +253 -0
  41. sqlspec/adapters/bigquery/_types.py +1 -1
  42. sqlspec/adapters/bigquery/adk/__init__.py +5 -0
  43. sqlspec/adapters/bigquery/adk/store.py +576 -0
  44. sqlspec/adapters/bigquery/config.py +25 -11
  45. sqlspec/adapters/bigquery/data_dictionary.py +42 -2
  46. sqlspec/adapters/bigquery/driver.py +352 -144
  47. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  48. sqlspec/adapters/bigquery/litestar/store.py +327 -0
  49. sqlspec/adapters/bigquery/type_converter.py +55 -23
  50. sqlspec/adapters/duckdb/_types.py +2 -2
  51. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  52. sqlspec/adapters/duckdb/adk/store.py +553 -0
  53. sqlspec/adapters/duckdb/config.py +79 -21
  54. sqlspec/adapters/duckdb/data_dictionary.py +41 -2
  55. sqlspec/adapters/duckdb/driver.py +138 -43
  56. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  57. sqlspec/adapters/duckdb/litestar/store.py +332 -0
  58. sqlspec/adapters/duckdb/pool.py +5 -5
  59. sqlspec/adapters/duckdb/type_converter.py +51 -21
  60. sqlspec/adapters/oracledb/_numpy_handlers.py +133 -0
  61. sqlspec/adapters/oracledb/_types.py +20 -2
  62. sqlspec/adapters/oracledb/adk/__init__.py +5 -0
  63. sqlspec/adapters/oracledb/adk/store.py +1745 -0
  64. sqlspec/adapters/oracledb/config.py +120 -36
  65. sqlspec/adapters/oracledb/data_dictionary.py +87 -20
  66. sqlspec/adapters/oracledb/driver.py +292 -84
  67. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  68. sqlspec/adapters/oracledb/litestar/store.py +767 -0
  69. sqlspec/adapters/oracledb/migrations.py +316 -25
  70. sqlspec/adapters/oracledb/type_converter.py +91 -16
  71. sqlspec/adapters/psqlpy/_type_handlers.py +44 -0
  72. sqlspec/adapters/psqlpy/_types.py +2 -1
  73. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  74. sqlspec/adapters/psqlpy/adk/store.py +482 -0
  75. sqlspec/adapters/psqlpy/config.py +45 -19
  76. sqlspec/adapters/psqlpy/data_dictionary.py +41 -2
  77. sqlspec/adapters/psqlpy/driver.py +101 -31
  78. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  79. sqlspec/adapters/psqlpy/litestar/store.py +272 -0
  80. sqlspec/adapters/psqlpy/type_converter.py +40 -11
  81. sqlspec/adapters/psycopg/_type_handlers.py +80 -0
  82. sqlspec/adapters/psycopg/_types.py +2 -1
  83. sqlspec/adapters/psycopg/adk/__init__.py +5 -0
  84. sqlspec/adapters/psycopg/adk/store.py +944 -0
  85. sqlspec/adapters/psycopg/config.py +65 -37
  86. sqlspec/adapters/psycopg/data_dictionary.py +77 -3
  87. sqlspec/adapters/psycopg/driver.py +200 -78
  88. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  89. sqlspec/adapters/psycopg/litestar/store.py +554 -0
  90. sqlspec/adapters/sqlite/__init__.py +2 -1
  91. sqlspec/adapters/sqlite/_type_handlers.py +86 -0
  92. sqlspec/adapters/sqlite/_types.py +1 -1
  93. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  94. sqlspec/adapters/sqlite/adk/store.py +572 -0
  95. sqlspec/adapters/sqlite/config.py +85 -16
  96. sqlspec/adapters/sqlite/data_dictionary.py +34 -2
  97. sqlspec/adapters/sqlite/driver.py +120 -52
  98. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  99. sqlspec/adapters/sqlite/litestar/store.py +318 -0
  100. sqlspec/adapters/sqlite/pool.py +5 -5
  101. sqlspec/base.py +45 -26
  102. sqlspec/builder/__init__.py +73 -4
  103. sqlspec/builder/_base.py +91 -58
  104. sqlspec/builder/_column.py +5 -5
  105. sqlspec/builder/_ddl.py +98 -89
  106. sqlspec/builder/_delete.py +5 -4
  107. sqlspec/builder/_dml.py +388 -0
  108. sqlspec/{_sql.py → builder/_factory.py} +41 -44
  109. sqlspec/builder/_insert.py +5 -82
  110. sqlspec/builder/{mixins/_join_operations.py → _join.py} +145 -143
  111. sqlspec/builder/_merge.py +446 -11
  112. sqlspec/builder/_parsing_utils.py +9 -11
  113. sqlspec/builder/_select.py +1313 -25
  114. sqlspec/builder/_update.py +11 -42
  115. sqlspec/cli.py +76 -69
  116. sqlspec/config.py +231 -60
  117. sqlspec/core/__init__.py +5 -4
  118. sqlspec/core/cache.py +18 -18
  119. sqlspec/core/compiler.py +6 -8
  120. sqlspec/core/filters.py +37 -37
  121. sqlspec/core/hashing.py +9 -9
  122. sqlspec/core/parameters.py +76 -45
  123. sqlspec/core/result.py +102 -46
  124. sqlspec/core/splitter.py +16 -17
  125. sqlspec/core/statement.py +32 -31
  126. sqlspec/core/type_conversion.py +3 -2
  127. sqlspec/driver/__init__.py +1 -3
  128. sqlspec/driver/_async.py +95 -161
  129. sqlspec/driver/_common.py +133 -80
  130. sqlspec/driver/_sync.py +95 -162
  131. sqlspec/driver/mixins/_result_tools.py +20 -236
  132. sqlspec/driver/mixins/_sql_translator.py +4 -4
  133. sqlspec/exceptions.py +70 -7
  134. sqlspec/extensions/adk/__init__.py +53 -0
  135. sqlspec/extensions/adk/_types.py +51 -0
  136. sqlspec/extensions/adk/converters.py +172 -0
  137. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +144 -0
  138. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  139. sqlspec/extensions/adk/service.py +181 -0
  140. sqlspec/extensions/adk/store.py +536 -0
  141. sqlspec/extensions/aiosql/adapter.py +73 -53
  142. sqlspec/extensions/litestar/__init__.py +21 -4
  143. sqlspec/extensions/litestar/cli.py +54 -10
  144. sqlspec/extensions/litestar/config.py +59 -266
  145. sqlspec/extensions/litestar/handlers.py +46 -17
  146. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  147. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  148. sqlspec/extensions/litestar/plugin.py +324 -223
  149. sqlspec/extensions/litestar/providers.py +25 -25
  150. sqlspec/extensions/litestar/store.py +265 -0
  151. sqlspec/loader.py +30 -49
  152. sqlspec/migrations/base.py +200 -76
  153. sqlspec/migrations/commands.py +591 -62
  154. sqlspec/migrations/context.py +6 -9
  155. sqlspec/migrations/fix.py +199 -0
  156. sqlspec/migrations/loaders.py +47 -19
  157. sqlspec/migrations/runner.py +241 -75
  158. sqlspec/migrations/tracker.py +237 -21
  159. sqlspec/migrations/utils.py +51 -3
  160. sqlspec/migrations/validation.py +177 -0
  161. sqlspec/protocols.py +66 -36
  162. sqlspec/storage/_utils.py +98 -0
  163. sqlspec/storage/backends/fsspec.py +134 -106
  164. sqlspec/storage/backends/local.py +78 -51
  165. sqlspec/storage/backends/obstore.py +278 -162
  166. sqlspec/storage/registry.py +75 -39
  167. sqlspec/typing.py +14 -84
  168. sqlspec/utils/config_resolver.py +6 -6
  169. sqlspec/utils/correlation.py +4 -5
  170. sqlspec/utils/data_transformation.py +3 -2
  171. sqlspec/utils/deprecation.py +9 -8
  172. sqlspec/utils/fixtures.py +4 -4
  173. sqlspec/utils/logging.py +46 -6
  174. sqlspec/utils/module_loader.py +2 -2
  175. sqlspec/utils/schema.py +288 -0
  176. sqlspec/utils/serializers.py +3 -3
  177. sqlspec/utils/sync_tools.py +21 -17
  178. sqlspec/utils/text.py +1 -2
  179. sqlspec/utils/type_guards.py +111 -20
  180. sqlspec/utils/version.py +433 -0
  181. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/METADATA +40 -21
  182. sqlspec-0.27.0.dist-info/RECORD +207 -0
  183. sqlspec/builder/mixins/__init__.py +0 -55
  184. sqlspec/builder/mixins/_cte_and_set_ops.py +0 -253
  185. sqlspec/builder/mixins/_delete_operations.py +0 -50
  186. sqlspec/builder/mixins/_insert_operations.py +0 -282
  187. sqlspec/builder/mixins/_merge_operations.py +0 -698
  188. sqlspec/builder/mixins/_order_limit_operations.py +0 -145
  189. sqlspec/builder/mixins/_pivot_operations.py +0 -157
  190. sqlspec/builder/mixins/_select_operations.py +0 -930
  191. sqlspec/builder/mixins/_update_operations.py +0 -199
  192. sqlspec/builder/mixins/_where_clause.py +0 -1298
  193. sqlspec-0.26.0.dist-info/RECORD +0 -157
  194. sqlspec-0.26.0.dist-info/licenses/NOTICE +0 -29
  195. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/WHEEL +0 -0
  196. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/entry_points.txt +0 -0
  197. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/licenses/LICENSE +0 -0
sqlspec/config.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from abc import ABC, abstractmethod
2
+ from collections.abc import Callable
2
3
  from pathlib import Path
3
- from typing import TYPE_CHECKING, Any, Callable, ClassVar, Generic, Optional, TypeVar, Union, cast
4
+ from typing import TYPE_CHECKING, Any, ClassVar, Generic, Literal, TypeVar, cast
4
5
 
5
6
  from typing_extensions import NotRequired, TypedDict
6
7
 
@@ -19,12 +20,14 @@ if TYPE_CHECKING:
19
20
 
20
21
 
21
22
  __all__ = (
23
+ "ADKConfig",
22
24
  "AsyncConfigT",
23
25
  "AsyncDatabaseConfig",
24
26
  "ConfigT",
25
27
  "DatabaseConfigProtocol",
26
28
  "DriverT",
27
29
  "LifecycleConfig",
30
+ "LitestarConfig",
28
31
  "MigrationConfig",
29
32
  "NoPoolAsyncConfig",
30
33
  "NoPoolSyncConfig",
@@ -32,22 +35,22 @@ __all__ = (
32
35
  "SyncDatabaseConfig",
33
36
  )
34
37
 
35
- AsyncConfigT = TypeVar("AsyncConfigT", bound="Union[AsyncDatabaseConfig[Any, Any, Any], NoPoolAsyncConfig[Any, Any]]")
36
- SyncConfigT = TypeVar("SyncConfigT", bound="Union[SyncDatabaseConfig[Any, Any, Any], NoPoolSyncConfig[Any, Any]]")
38
+ AsyncConfigT = TypeVar("AsyncConfigT", bound="AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]")
39
+ SyncConfigT = TypeVar("SyncConfigT", bound="SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any]")
37
40
  ConfigT = TypeVar(
38
41
  "ConfigT",
39
- bound="Union[Union[AsyncDatabaseConfig[Any, Any, Any], NoPoolAsyncConfig[Any, Any]], SyncDatabaseConfig[Any, Any, Any], NoPoolSyncConfig[Any, Any]]",
42
+ bound="AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any] | SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any]",
40
43
  )
41
44
 
42
45
  # Define TypeVars for Generic classes
43
46
  ConnectionT = TypeVar("ConnectionT")
44
47
  PoolT = TypeVar("PoolT")
45
- DriverT = TypeVar("DriverT", bound="Union[SyncDriverAdapterBase, AsyncDriverAdapterBase]")
48
+ DriverT = TypeVar("DriverT", bound="SyncDriverAdapterBase | AsyncDriverAdapterBase")
46
49
 
47
50
  logger = get_logger("config")
48
51
 
49
52
 
50
- class LifecycleConfig(TypedDict, total=False):
53
+ class LifecycleConfig(TypedDict):
51
54
  """Lifecycle hooks for database adapters.
52
55
 
53
56
  Each hook accepts a list of callables to support multiple handlers.
@@ -64,14 +67,14 @@ class LifecycleConfig(TypedDict, total=False):
64
67
  on_error: NotRequired[list[Callable[[Exception, str, dict], None]]]
65
68
 
66
69
 
67
- class MigrationConfig(TypedDict, total=False):
70
+ class MigrationConfig(TypedDict):
68
71
  """Configuration options for database migrations.
69
72
 
70
73
  All fields are optional with default values.
71
74
  """
72
75
 
73
- script_location: NotRequired[str]
74
- """Path to the migrations directory. Defaults to 'migrations'."""
76
+ script_location: NotRequired["str | Path"]
77
+ """Path to the migrations directory. Accepts string or Path object. Defaults to 'migrations'."""
75
78
 
76
79
  version_table_name: NotRequired[str]
77
80
  """Name of the table used to track applied migrations. Defaults to 'sqlspec_migrations'."""
@@ -82,6 +85,164 @@ class MigrationConfig(TypedDict, total=False):
82
85
  enabled: NotRequired[bool]
83
86
  """Whether this configuration should be included in CLI operations. Defaults to True."""
84
87
 
88
+ auto_sync: NotRequired[bool]
89
+ """Enable automatic version reconciliation during upgrade. When enabled (default), SQLSpec automatically updates database tracking when migrations are renamed from timestamp to sequential format. Defaults to True."""
90
+
91
+ strict_ordering: NotRequired[bool]
92
+ """Enforce strict migration ordering. When enabled, prevents out-of-order migrations from being applied. Defaults to False."""
93
+
94
+ include_extensions: NotRequired["list[str]"]
95
+ """List of extension names whose migrations should be included. Extension migrations maintain separate versioning and are prefixed with 'ext_{name}_'."""
96
+
97
+ transactional: NotRequired[bool]
98
+ """Wrap migrations in transactions when supported. When enabled (default for adapters that support it), each migration runs in a transaction that is committed on success or rolled back on failure. This prevents partial migrations from leaving the database in an inconsistent state. Requires adapter support for transactional DDL. Defaults to True for PostgreSQL, SQLite, and DuckDB; False for MySQL, Oracle, and BigQuery. Individual migrations can override this with a '-- transactional: false' comment."""
99
+
100
+
101
+ class LitestarConfig(TypedDict):
102
+ """Configuration options for Litestar SQLSpec plugin.
103
+
104
+ All fields are optional with sensible defaults.
105
+ """
106
+
107
+ connection_key: NotRequired[str]
108
+ """Key for storing connection in ASGI scope. Default: 'db_connection'"""
109
+
110
+ pool_key: NotRequired[str]
111
+ """Key for storing connection pool in application state. Default: 'db_pool'"""
112
+
113
+ session_key: NotRequired[str]
114
+ """Key for storing session in ASGI scope. Default: 'db_session'"""
115
+
116
+ commit_mode: NotRequired[Literal["manual", "autocommit", "autocommit_include_redirect"]]
117
+ """Transaction commit mode. Default: 'manual'"""
118
+
119
+ enable_correlation_middleware: NotRequired[bool]
120
+ """Enable request correlation ID middleware. Default: True"""
121
+
122
+ extra_commit_statuses: NotRequired[set[int]]
123
+ """Additional HTTP status codes that trigger commit. Default: set()"""
124
+
125
+ extra_rollback_statuses: NotRequired[set[int]]
126
+ """Additional HTTP status codes that trigger rollback. Default: set()"""
127
+
128
+
129
+ class ADKConfig(TypedDict):
130
+ """Configuration options for ADK session store extension.
131
+
132
+ All fields are optional with sensible defaults. Use in extension_config["adk"]:
133
+
134
+ Example:
135
+ from sqlspec.adapters.asyncpg import AsyncpgConfig
136
+
137
+ config = AsyncpgConfig(
138
+ pool_config={"dsn": "postgresql://localhost/mydb"},
139
+ extension_config={
140
+ "adk": {
141
+ "session_table": "my_sessions",
142
+ "events_table": "my_events",
143
+ "owner_id_column": "tenant_id INTEGER REFERENCES tenants(id)"
144
+ }
145
+ }
146
+ )
147
+
148
+ Notes:
149
+ This TypedDict provides type safety for extension config but is not required.
150
+ You can use plain dicts as well.
151
+ """
152
+
153
+ session_table: NotRequired[str]
154
+ """Name of the sessions table. Default: 'adk_sessions'
155
+
156
+ Examples:
157
+ "agent_sessions"
158
+ "my_app_sessions"
159
+ "tenant_acme_sessions"
160
+ """
161
+
162
+ events_table: NotRequired[str]
163
+ """Name of the events table. Default: 'adk_events'
164
+
165
+ Examples:
166
+ "agent_events"
167
+ "my_app_events"
168
+ "tenant_acme_events"
169
+ """
170
+
171
+ owner_id_column: NotRequired[str]
172
+ """Optional owner ID column definition to link sessions to a user, tenant, team, or other entity.
173
+
174
+ Format: "column_name TYPE [NOT NULL] REFERENCES table(column) [options...]"
175
+
176
+ The entire definition is passed through to DDL verbatim. We only parse
177
+ the column name (first word) for use in INSERT/SELECT statements.
178
+
179
+ Supports:
180
+ - Foreign key constraints: REFERENCES table(column)
181
+ - Nullable or NOT NULL
182
+ - CASCADE options: ON DELETE CASCADE, ON UPDATE CASCADE
183
+ - Dialect-specific options (DEFERRABLE, ENABLE VALIDATE, etc.)
184
+ - Plain columns without FK (just extra column storage)
185
+
186
+ Examples:
187
+ PostgreSQL with UUID FK:
188
+ "account_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE"
189
+
190
+ MySQL with BIGINT FK:
191
+ "user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE RESTRICT"
192
+
193
+ Oracle with NUMBER FK:
194
+ "user_id NUMBER(10) REFERENCES users(id) ENABLE VALIDATE"
195
+
196
+ SQLite with INTEGER FK:
197
+ "tenant_id INTEGER NOT NULL REFERENCES tenants(id)"
198
+
199
+ Nullable FK (optional relationship):
200
+ "workspace_id UUID REFERENCES workspaces(id) ON DELETE SET NULL"
201
+
202
+ No FK (just extra column):
203
+ "organization_name VARCHAR(128) NOT NULL"
204
+
205
+ Deferred constraint (PostgreSQL):
206
+ "user_id UUID REFERENCES users(id) DEFERRABLE INITIALLY DEFERRED"
207
+
208
+ Notes:
209
+ - Column name (first word) is extracted for INSERT/SELECT queries
210
+ - Rest of definition is passed through to CREATE TABLE DDL
211
+ - Database validates the DDL syntax (fail-fast on errors)
212
+ - Works with all database dialects (PostgreSQL, MySQL, SQLite, Oracle, etc.)
213
+ """
214
+
215
+ in_memory: NotRequired[bool]
216
+ """Enable in-memory table storage (Oracle-specific). Default: False.
217
+
218
+ When enabled, tables are created with the INMEMORY clause for Oracle Database,
219
+ which stores table data in columnar format in memory for faster query performance.
220
+
221
+ This is an Oracle-specific feature that requires:
222
+ - Oracle Database 12.1.0.2 or higher
223
+ - Database In-Memory option license (Enterprise Edition)
224
+ - Sufficient INMEMORY_SIZE configured in the database instance
225
+
226
+ Other database adapters ignore this setting.
227
+
228
+ Examples:
229
+ Oracle with in-memory enabled:
230
+ config = OracleAsyncConfig(
231
+ pool_config={"dsn": "oracle://..."},
232
+ extension_config={
233
+ "adk": {
234
+ "in_memory": True
235
+ }
236
+ }
237
+ )
238
+
239
+ Notes:
240
+ - Improves query performance for analytics (10-100x faster)
241
+ - Tables created with INMEMORY clause
242
+ - Requires Oracle Database In-Memory option license
243
+ - Ignored by non-Oracle adapters
244
+ """
245
+
85
246
 
86
247
  class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
87
248
  """Protocol defining the interface for database configurations."""
@@ -97,19 +258,21 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
97
258
  )
98
259
 
99
260
  _migration_loader: "SQLFileLoader"
100
- _migration_commands: "Union[SyncMigrationCommands, AsyncMigrationCommands]"
261
+ _migration_commands: "SyncMigrationCommands | AsyncMigrationCommands"
101
262
  driver_type: "ClassVar[type[Any]]"
102
263
  connection_type: "ClassVar[type[Any]]"
103
264
  is_async: "ClassVar[bool]" = False
104
265
  supports_connection_pooling: "ClassVar[bool]" = False
266
+ supports_transactional_ddl: "ClassVar[bool]" = False
105
267
  supports_native_arrow_import: "ClassVar[bool]" = False
106
268
  supports_native_arrow_export: "ClassVar[bool]" = False
107
269
  supports_native_parquet_import: "ClassVar[bool]" = False
108
270
  supports_native_parquet_export: "ClassVar[bool]" = False
109
- bind_key: "Optional[str]"
271
+ bind_key: "str | None"
110
272
  statement_config: "StatementConfig"
111
- pool_instance: "Optional[PoolT]"
112
- migration_config: "Union[dict[str, Any], MigrationConfig]"
273
+ pool_instance: "PoolT | None"
274
+ migration_config: "dict[str, Any] | MigrationConfig"
275
+ driver_features: "dict[str, Any]"
113
276
 
114
277
  def __hash__(self) -> int:
115
278
  return id(self)
@@ -124,38 +287,38 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
124
287
  return f"{type(self).__name__}({parts})"
125
288
 
126
289
  @abstractmethod
127
- def create_connection(self) -> "Union[ConnectionT, Awaitable[ConnectionT]]":
290
+ def create_connection(self) -> "ConnectionT | Awaitable[ConnectionT]":
128
291
  """Create and return a new database connection."""
129
292
  raise NotImplementedError
130
293
 
131
294
  @abstractmethod
132
295
  def provide_connection(
133
296
  self, *args: Any, **kwargs: Any
134
- ) -> "Union[AbstractContextManager[ConnectionT], AbstractAsyncContextManager[ConnectionT]]":
297
+ ) -> "AbstractContextManager[ConnectionT] | AbstractAsyncContextManager[ConnectionT]":
135
298
  """Provide a database connection context manager."""
136
299
  raise NotImplementedError
137
300
 
138
301
  @abstractmethod
139
302
  def provide_session(
140
303
  self, *args: Any, **kwargs: Any
141
- ) -> "Union[AbstractContextManager[DriverT], AbstractAsyncContextManager[DriverT]]":
304
+ ) -> "AbstractContextManager[DriverT] | AbstractAsyncContextManager[DriverT]":
142
305
  """Provide a database session context manager."""
143
306
  raise NotImplementedError
144
307
 
145
308
  @abstractmethod
146
- def create_pool(self) -> "Union[PoolT, Awaitable[PoolT]]":
309
+ def create_pool(self) -> "PoolT | Awaitable[PoolT]":
147
310
  """Create and return connection pool."""
148
311
  raise NotImplementedError
149
312
 
150
313
  @abstractmethod
151
- def close_pool(self) -> "Optional[Awaitable[None]]":
314
+ def close_pool(self) -> "Awaitable[None] | None":
152
315
  """Terminate the connection pool."""
153
316
  raise NotImplementedError
154
317
 
155
318
  @abstractmethod
156
319
  def provide_pool(
157
320
  self, *args: Any, **kwargs: Any
158
- ) -> "Union[PoolT, Awaitable[PoolT], AbstractContextManager[PoolT], AbstractAsyncContextManager[PoolT]]":
321
+ ) -> "PoolT | Awaitable[PoolT] | AbstractContextManager[PoolT] | AbstractAsyncContextManager[PoolT]":
159
322
  """Provide pool instance."""
160
323
  raise NotImplementedError
161
324
 
@@ -181,7 +344,7 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
181
344
  from sqlspec.migrations.commands import create_migration_commands
182
345
 
183
346
  self._migration_loader = SQLFileLoader()
184
- self._migration_commands = create_migration_commands(self) # type: ignore[arg-type]
347
+ self._migration_commands = create_migration_commands(self) # pyright: ignore
185
348
 
186
349
  def _ensure_migration_loader(self) -> "SQLFileLoader":
187
350
  """Get the migration SQL loader and auto-load files if needed.
@@ -202,7 +365,7 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
202
365
 
203
366
  return self._migration_loader
204
367
 
205
- def _ensure_migration_commands(self) -> "Union[SyncMigrationCommands, AsyncMigrationCommands]":
368
+ def _ensure_migration_commands(self) -> "SyncMigrationCommands | AsyncMigrationCommands":
206
369
  """Get the migration commands instance.
207
370
 
208
371
  Returns:
@@ -221,7 +384,7 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
221
384
  """
222
385
  return self._ensure_migration_loader()
223
386
 
224
- def load_migration_sql_files(self, *paths: "Union[str, Path]") -> None:
387
+ def load_migration_sql_files(self, *paths: "str | Path") -> None:
225
388
  """Load additional migration SQL files from specified paths.
226
389
 
227
390
  Args:
@@ -237,7 +400,7 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
237
400
  else:
238
401
  logger.warning("Migration path does not exist: %s", path_obj)
239
402
 
240
- def get_migration_commands(self) -> "Union[SyncMigrationCommands, AsyncMigrationCommands]":
403
+ def get_migration_commands(self) -> "SyncMigrationCommands | AsyncMigrationCommands":
241
404
  """Get migration commands for this configuration.
242
405
 
243
406
  Returns:
@@ -265,7 +428,7 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
265
428
 
266
429
  await cast("AsyncMigrationCommands", commands).downgrade(revision)
267
430
 
268
- async def get_current_migration(self, verbose: bool = False) -> "Optional[str]":
431
+ async def get_current_migration(self, verbose: bool = False) -> "str | None":
269
432
  """Get the current migration version.
270
433
 
271
434
  Args:
@@ -289,7 +452,7 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
289
452
 
290
453
  await cast("AsyncMigrationCommands", commands).revision(message, file_type)
291
454
 
292
- async def init_migrations(self, directory: "Optional[str]" = None, package: bool = True) -> None:
455
+ async def init_migrations(self, directory: "str | None" = None, package: bool = True) -> None:
293
456
  """Initialize migration directory structure.
294
457
 
295
458
  Args:
@@ -298,7 +461,7 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
298
461
  """
299
462
  if directory is None:
300
463
  migration_config = self.migration_config or {}
301
- directory = migration_config.get("script_location") or "migrations"
464
+ directory = str(migration_config.get("script_location") or "migrations")
302
465
 
303
466
  commands = self._ensure_migration_commands()
304
467
  assert directory is not None
@@ -309,7 +472,7 @@ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
309
472
  class NoPoolSyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
310
473
  """Base class for sync database configurations that do not implement a pool."""
311
474
 
312
- __slots__ = ("connection_config",)
475
+ __slots__ = ("connection_config", "extension_config")
313
476
  is_async: "ClassVar[bool]" = False
314
477
  supports_connection_pooling: "ClassVar[bool]" = False
315
478
  migration_tracker_type: "ClassVar[type[Any]]" = SyncMigrationTracker
@@ -317,16 +480,18 @@ class NoPoolSyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
317
480
  def __init__(
318
481
  self,
319
482
  *,
320
- connection_config: Optional[dict[str, Any]] = None,
321
- migration_config: "Optional[Union[dict[str, Any], MigrationConfig]]" = None,
322
- statement_config: "Optional[StatementConfig]" = None,
323
- driver_features: "Optional[dict[str, Any]]" = None,
324
- bind_key: "Optional[str]" = None,
483
+ connection_config: dict[str, Any] | None = None,
484
+ migration_config: "dict[str, Any] | MigrationConfig | None" = None,
485
+ statement_config: "StatementConfig | None" = None,
486
+ driver_features: "dict[str, Any] | None" = None,
487
+ bind_key: "str | None" = None,
488
+ extension_config: "dict[str, dict[str, Any]] | None" = None,
325
489
  ) -> None:
326
490
  self.bind_key = bind_key
327
491
  self.pool_instance = None
328
492
  self.connection_config = connection_config or {}
329
- self.migration_config: Union[dict[str, Any], MigrationConfig] = migration_config or {}
493
+ self.extension_config: dict[str, dict[str, Any]] = extension_config or {}
494
+ self.migration_config: dict[str, Any] | MigrationConfig = migration_config or {}
330
495
  self._initialize_migration_components()
331
496
 
332
497
  if statement_config is None:
@@ -347,7 +512,7 @@ class NoPoolSyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
347
512
  raise NotImplementedError
348
513
 
349
514
  def provide_session(
350
- self, *args: Any, statement_config: "Optional[StatementConfig]" = None, **kwargs: Any
515
+ self, *args: Any, statement_config: "StatementConfig | None" = None, **kwargs: Any
351
516
  ) -> "AbstractContextManager[DriverT]":
352
517
  """Provide a database session context manager."""
353
518
  raise NotImplementedError
@@ -365,7 +530,7 @@ class NoPoolSyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
365
530
  class NoPoolAsyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
366
531
  """Base class for async database configurations that do not implement a pool."""
367
532
 
368
- __slots__ = ("connection_config",)
533
+ __slots__ = ("connection_config", "extension_config")
369
534
  is_async: "ClassVar[bool]" = True
370
535
  supports_connection_pooling: "ClassVar[bool]" = False
371
536
  migration_tracker_type: "ClassVar[type[Any]]" = AsyncMigrationTracker
@@ -373,16 +538,18 @@ class NoPoolAsyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
373
538
  def __init__(
374
539
  self,
375
540
  *,
376
- connection_config: "Optional[dict[str, Any]]" = None,
377
- migration_config: "Optional[Union[dict[str, Any], MigrationConfig]]" = None,
378
- statement_config: "Optional[StatementConfig]" = None,
379
- driver_features: "Optional[dict[str, Any]]" = None,
380
- bind_key: "Optional[str]" = None,
541
+ connection_config: "dict[str, Any] | None" = None,
542
+ migration_config: "dict[str, Any] | MigrationConfig | None" = None,
543
+ statement_config: "StatementConfig | None" = None,
544
+ driver_features: "dict[str, Any] | None" = None,
545
+ bind_key: "str | None" = None,
546
+ extension_config: "dict[str, dict[str, Any]] | None" = None,
381
547
  ) -> None:
382
548
  self.bind_key = bind_key
383
549
  self.pool_instance = None
384
550
  self.connection_config = connection_config or {}
385
- self.migration_config: Union[dict[str, Any], MigrationConfig] = migration_config or {}
551
+ self.extension_config: dict[str, dict[str, Any]] = extension_config or {}
552
+ self.migration_config: dict[str, Any] | MigrationConfig = migration_config or {}
386
553
  self._initialize_migration_components()
387
554
 
388
555
  if statement_config is None:
@@ -403,7 +570,7 @@ class NoPoolAsyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
403
570
  raise NotImplementedError
404
571
 
405
572
  def provide_session(
406
- self, *args: Any, statement_config: "Optional[StatementConfig]" = None, **kwargs: Any
573
+ self, *args: Any, statement_config: "StatementConfig | None" = None, **kwargs: Any
407
574
  ) -> "AbstractAsyncContextManager[DriverT]":
408
575
  """Provide a database session context manager."""
409
576
  raise NotImplementedError
@@ -421,7 +588,7 @@ class NoPoolAsyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
421
588
  class SyncDatabaseConfig(DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]):
422
589
  """Base class for sync database configurations with connection pooling."""
423
590
 
424
- __slots__ = ("pool_config",)
591
+ __slots__ = ("extension_config", "pool_config")
425
592
  is_async: "ClassVar[bool]" = False
426
593
  supports_connection_pooling: "ClassVar[bool]" = True
427
594
  migration_tracker_type: "ClassVar[type[Any]]" = SyncMigrationTracker
@@ -429,17 +596,19 @@ class SyncDatabaseConfig(DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]):
429
596
  def __init__(
430
597
  self,
431
598
  *,
432
- pool_config: "Optional[dict[str, Any]]" = None,
433
- pool_instance: "Optional[PoolT]" = None,
434
- migration_config: "Optional[Union[dict[str, Any], MigrationConfig]]" = None,
435
- statement_config: "Optional[StatementConfig]" = None,
436
- driver_features: "Optional[dict[str, Any]]" = None,
437
- bind_key: "Optional[str]" = None,
599
+ pool_config: "dict[str, Any] | None" = None,
600
+ pool_instance: "PoolT | None" = None,
601
+ migration_config: "dict[str, Any] | MigrationConfig | None" = None,
602
+ statement_config: "StatementConfig | None" = None,
603
+ driver_features: "dict[str, Any] | None" = None,
604
+ bind_key: "str | None" = None,
605
+ extension_config: "dict[str, dict[str, Any]] | None" = None,
438
606
  ) -> None:
439
607
  self.bind_key = bind_key
440
608
  self.pool_instance = pool_instance
441
609
  self.pool_config = pool_config or {}
442
- self.migration_config: Union[dict[str, Any], MigrationConfig] = migration_config or {}
610
+ self.extension_config: dict[str, dict[str, Any]] = extension_config or {}
611
+ self.migration_config: dict[str, Any] | MigrationConfig = migration_config or {}
443
612
  self._initialize_migration_components()
444
613
 
445
614
  if statement_config is None:
@@ -481,7 +650,7 @@ class SyncDatabaseConfig(DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]):
481
650
  raise NotImplementedError
482
651
 
483
652
  def provide_session(
484
- self, *args: Any, statement_config: "Optional[StatementConfig]" = None, **kwargs: Any
653
+ self, *args: Any, statement_config: "StatementConfig | None" = None, **kwargs: Any
485
654
  ) -> "AbstractContextManager[DriverT]":
486
655
  """Provide a database session context manager."""
487
656
  raise NotImplementedError
@@ -500,7 +669,7 @@ class SyncDatabaseConfig(DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]):
500
669
  class AsyncDatabaseConfig(DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]):
501
670
  """Base class for async database configurations with connection pooling."""
502
671
 
503
- __slots__ = ("pool_config",)
672
+ __slots__ = ("extension_config", "pool_config")
504
673
  is_async: "ClassVar[bool]" = True
505
674
  supports_connection_pooling: "ClassVar[bool]" = True
506
675
  migration_tracker_type: "ClassVar[type[Any]]" = AsyncMigrationTracker
@@ -508,17 +677,19 @@ class AsyncDatabaseConfig(DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]):
508
677
  def __init__(
509
678
  self,
510
679
  *,
511
- pool_config: "Optional[dict[str, Any]]" = None,
512
- pool_instance: "Optional[PoolT]" = None,
513
- migration_config: "Optional[Union[dict[str, Any], MigrationConfig]]" = None,
514
- statement_config: "Optional[StatementConfig]" = None,
515
- driver_features: "Optional[dict[str, Any]]" = None,
516
- bind_key: "Optional[str]" = None,
680
+ pool_config: "dict[str, Any] | None" = None,
681
+ pool_instance: "PoolT | None" = None,
682
+ migration_config: "dict[str, Any] | MigrationConfig | None" = None,
683
+ statement_config: "StatementConfig | None" = None,
684
+ driver_features: "dict[str, Any] | None" = None,
685
+ bind_key: "str | None" = None,
686
+ extension_config: "dict[str, dict[str, Any]] | None" = None,
517
687
  ) -> None:
518
688
  self.bind_key = bind_key
519
689
  self.pool_instance = pool_instance
520
690
  self.pool_config = pool_config or {}
521
- self.migration_config: Union[dict[str, Any], MigrationConfig] = migration_config or {}
691
+ self.extension_config: dict[str, dict[str, Any]] = extension_config or {}
692
+ self.migration_config: dict[str, Any] | MigrationConfig = migration_config or {}
522
693
  self._initialize_migration_components()
523
694
 
524
695
  if statement_config is None:
@@ -562,7 +733,7 @@ class AsyncDatabaseConfig(DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]):
562
733
  raise NotImplementedError
563
734
 
564
735
  def provide_session(
565
- self, *args: Any, statement_config: "Optional[StatementConfig]" = None, **kwargs: Any
736
+ self, *args: Any, statement_config: "StatementConfig | None" = None, **kwargs: Any
566
737
  ) -> "AbstractAsyncContextManager[DriverT]":
567
738
  """Provide a database session context manager."""
568
739
  raise NotImplementedError
sqlspec/core/__init__.py CHANGED
@@ -1,9 +1,9 @@
1
- """SQLSpec Core Module - High-Performance SQL Processing System.
1
+ """SQLSpec Core Module - SQL Processing System.
2
2
 
3
3
  This module provides the core SQL processing infrastructure for SQLSpec, implementing
4
4
  a complete pipeline for SQL statement compilation, parameter processing, caching,
5
- and result management. All components are optimized for MyPyC compilation and
6
- designed for maximum performance with minimal overhead.
5
+ and result management. All components are optimized for MyPyC compilation to
6
+ reduce overhead.
7
7
 
8
8
  Architecture Overview:
9
9
  The core module implements a single-pass processing pipeline where SQL statements
@@ -90,7 +90,7 @@ Example Usage:
90
90
  """
91
91
 
92
92
  from sqlspec.core import filters
93
- from sqlspec.core.cache import CacheConfig, CacheStats, MultiLevelCache, UnifiedCache, get_cache
93
+ from sqlspec.core.cache import CacheConfig, CacheStats, MultiLevelCache, UnifiedCache, get_cache, get_cache_config
94
94
  from sqlspec.core.compiler import OperationType, SQLProcessor
95
95
  from sqlspec.core.filters import StatementFilter
96
96
  from sqlspec.core.hashing import (
@@ -131,6 +131,7 @@ __all__ = (
131
131
  "UnifiedCache",
132
132
  "filters",
133
133
  "get_cache",
134
+ "get_cache_config",
134
135
  "hash_expression",
135
136
  "hash_expression_node",
136
137
  "hash_optimized_expression",