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.
- sqlspec/__init__.py +7 -15
- sqlspec/_serialization.py +55 -25
- sqlspec/_typing.py +62 -52
- sqlspec/adapters/adbc/_types.py +1 -1
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +870 -0
- sqlspec/adapters/adbc/config.py +62 -12
- sqlspec/adapters/adbc/data_dictionary.py +52 -2
- sqlspec/adapters/adbc/driver.py +144 -45
- sqlspec/adapters/adbc/litestar/__init__.py +5 -0
- sqlspec/adapters/adbc/litestar/store.py +504 -0
- sqlspec/adapters/adbc/type_converter.py +44 -50
- sqlspec/adapters/aiosqlite/_types.py +1 -1
- sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/adk/store.py +527 -0
- sqlspec/adapters/aiosqlite/config.py +86 -16
- sqlspec/adapters/aiosqlite/data_dictionary.py +34 -2
- sqlspec/adapters/aiosqlite/driver.py +127 -38
- sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/litestar/store.py +281 -0
- sqlspec/adapters/aiosqlite/pool.py +7 -7
- sqlspec/adapters/asyncmy/__init__.py +7 -1
- sqlspec/adapters/asyncmy/_types.py +1 -1
- sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
- sqlspec/adapters/asyncmy/adk/store.py +493 -0
- sqlspec/adapters/asyncmy/config.py +59 -17
- sqlspec/adapters/asyncmy/data_dictionary.py +41 -2
- sqlspec/adapters/asyncmy/driver.py +293 -62
- sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncmy/litestar/store.py +296 -0
- sqlspec/adapters/asyncpg/__init__.py +2 -1
- sqlspec/adapters/asyncpg/_type_handlers.py +71 -0
- sqlspec/adapters/asyncpg/_types.py +11 -7
- sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
- sqlspec/adapters/asyncpg/adk/store.py +450 -0
- sqlspec/adapters/asyncpg/config.py +57 -36
- sqlspec/adapters/asyncpg/data_dictionary.py +41 -2
- sqlspec/adapters/asyncpg/driver.py +153 -23
- sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncpg/litestar/store.py +253 -0
- sqlspec/adapters/bigquery/_types.py +1 -1
- sqlspec/adapters/bigquery/adk/__init__.py +5 -0
- sqlspec/adapters/bigquery/adk/store.py +576 -0
- sqlspec/adapters/bigquery/config.py +25 -11
- sqlspec/adapters/bigquery/data_dictionary.py +42 -2
- sqlspec/adapters/bigquery/driver.py +352 -144
- sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
- sqlspec/adapters/bigquery/litestar/store.py +327 -0
- sqlspec/adapters/bigquery/type_converter.py +55 -23
- sqlspec/adapters/duckdb/_types.py +2 -2
- sqlspec/adapters/duckdb/adk/__init__.py +14 -0
- sqlspec/adapters/duckdb/adk/store.py +553 -0
- sqlspec/adapters/duckdb/config.py +79 -21
- sqlspec/adapters/duckdb/data_dictionary.py +41 -2
- sqlspec/adapters/duckdb/driver.py +138 -43
- sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
- sqlspec/adapters/duckdb/litestar/store.py +332 -0
- sqlspec/adapters/duckdb/pool.py +5 -5
- sqlspec/adapters/duckdb/type_converter.py +51 -21
- sqlspec/adapters/oracledb/_numpy_handlers.py +133 -0
- sqlspec/adapters/oracledb/_types.py +20 -2
- sqlspec/adapters/oracledb/adk/__init__.py +5 -0
- sqlspec/adapters/oracledb/adk/store.py +1745 -0
- sqlspec/adapters/oracledb/config.py +120 -36
- sqlspec/adapters/oracledb/data_dictionary.py +87 -20
- sqlspec/adapters/oracledb/driver.py +292 -84
- sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
- sqlspec/adapters/oracledb/litestar/store.py +767 -0
- sqlspec/adapters/oracledb/migrations.py +316 -25
- sqlspec/adapters/oracledb/type_converter.py +91 -16
- sqlspec/adapters/psqlpy/_type_handlers.py +44 -0
- sqlspec/adapters/psqlpy/_types.py +2 -1
- sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
- sqlspec/adapters/psqlpy/adk/store.py +482 -0
- sqlspec/adapters/psqlpy/config.py +45 -19
- sqlspec/adapters/psqlpy/data_dictionary.py +41 -2
- sqlspec/adapters/psqlpy/driver.py +101 -31
- sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
- sqlspec/adapters/psqlpy/litestar/store.py +272 -0
- sqlspec/adapters/psqlpy/type_converter.py +40 -11
- sqlspec/adapters/psycopg/_type_handlers.py +80 -0
- sqlspec/adapters/psycopg/_types.py +2 -1
- sqlspec/adapters/psycopg/adk/__init__.py +5 -0
- sqlspec/adapters/psycopg/adk/store.py +944 -0
- sqlspec/adapters/psycopg/config.py +65 -37
- sqlspec/adapters/psycopg/data_dictionary.py +77 -3
- sqlspec/adapters/psycopg/driver.py +200 -78
- sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
- sqlspec/adapters/psycopg/litestar/store.py +554 -0
- sqlspec/adapters/sqlite/__init__.py +2 -1
- sqlspec/adapters/sqlite/_type_handlers.py +86 -0
- sqlspec/adapters/sqlite/_types.py +1 -1
- sqlspec/adapters/sqlite/adk/__init__.py +5 -0
- sqlspec/adapters/sqlite/adk/store.py +572 -0
- sqlspec/adapters/sqlite/config.py +85 -16
- sqlspec/adapters/sqlite/data_dictionary.py +34 -2
- sqlspec/adapters/sqlite/driver.py +120 -52
- sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/sqlite/litestar/store.py +318 -0
- sqlspec/adapters/sqlite/pool.py +5 -5
- sqlspec/base.py +45 -26
- sqlspec/builder/__init__.py +73 -4
- sqlspec/builder/_base.py +91 -58
- sqlspec/builder/_column.py +5 -5
- sqlspec/builder/_ddl.py +98 -89
- sqlspec/builder/_delete.py +5 -4
- sqlspec/builder/_dml.py +388 -0
- sqlspec/{_sql.py → builder/_factory.py} +41 -44
- sqlspec/builder/_insert.py +5 -82
- sqlspec/builder/{mixins/_join_operations.py → _join.py} +145 -143
- sqlspec/builder/_merge.py +446 -11
- sqlspec/builder/_parsing_utils.py +9 -11
- sqlspec/builder/_select.py +1313 -25
- sqlspec/builder/_update.py +11 -42
- sqlspec/cli.py +76 -69
- sqlspec/config.py +231 -60
- sqlspec/core/__init__.py +5 -4
- sqlspec/core/cache.py +18 -18
- sqlspec/core/compiler.py +6 -8
- sqlspec/core/filters.py +37 -37
- sqlspec/core/hashing.py +9 -9
- sqlspec/core/parameters.py +76 -45
- sqlspec/core/result.py +102 -46
- sqlspec/core/splitter.py +16 -17
- sqlspec/core/statement.py +32 -31
- sqlspec/core/type_conversion.py +3 -2
- sqlspec/driver/__init__.py +1 -3
- sqlspec/driver/_async.py +95 -161
- sqlspec/driver/_common.py +133 -80
- sqlspec/driver/_sync.py +95 -162
- sqlspec/driver/mixins/_result_tools.py +20 -236
- sqlspec/driver/mixins/_sql_translator.py +4 -4
- sqlspec/exceptions.py +70 -7
- sqlspec/extensions/adk/__init__.py +53 -0
- sqlspec/extensions/adk/_types.py +51 -0
- sqlspec/extensions/adk/converters.py +172 -0
- sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +144 -0
- sqlspec/extensions/adk/migrations/__init__.py +0 -0
- sqlspec/extensions/adk/service.py +181 -0
- sqlspec/extensions/adk/store.py +536 -0
- sqlspec/extensions/aiosql/adapter.py +73 -53
- sqlspec/extensions/litestar/__init__.py +21 -4
- sqlspec/extensions/litestar/cli.py +54 -10
- sqlspec/extensions/litestar/config.py +59 -266
- sqlspec/extensions/litestar/handlers.py +46 -17
- sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
- sqlspec/extensions/litestar/migrations/__init__.py +3 -0
- sqlspec/extensions/litestar/plugin.py +324 -223
- sqlspec/extensions/litestar/providers.py +25 -25
- sqlspec/extensions/litestar/store.py +265 -0
- sqlspec/loader.py +30 -49
- sqlspec/migrations/base.py +200 -76
- sqlspec/migrations/commands.py +591 -62
- sqlspec/migrations/context.py +6 -9
- sqlspec/migrations/fix.py +199 -0
- sqlspec/migrations/loaders.py +47 -19
- sqlspec/migrations/runner.py +241 -75
- sqlspec/migrations/tracker.py +237 -21
- sqlspec/migrations/utils.py +51 -3
- sqlspec/migrations/validation.py +177 -0
- sqlspec/protocols.py +66 -36
- sqlspec/storage/_utils.py +98 -0
- sqlspec/storage/backends/fsspec.py +134 -106
- sqlspec/storage/backends/local.py +78 -51
- sqlspec/storage/backends/obstore.py +278 -162
- sqlspec/storage/registry.py +75 -39
- sqlspec/typing.py +14 -84
- sqlspec/utils/config_resolver.py +6 -6
- sqlspec/utils/correlation.py +4 -5
- sqlspec/utils/data_transformation.py +3 -2
- sqlspec/utils/deprecation.py +9 -8
- sqlspec/utils/fixtures.py +4 -4
- sqlspec/utils/logging.py +46 -6
- sqlspec/utils/module_loader.py +2 -2
- sqlspec/utils/schema.py +288 -0
- sqlspec/utils/serializers.py +3 -3
- sqlspec/utils/sync_tools.py +21 -17
- sqlspec/utils/text.py +1 -2
- sqlspec/utils/type_guards.py +111 -20
- sqlspec/utils/version.py +433 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/METADATA +40 -21
- sqlspec-0.27.0.dist-info/RECORD +207 -0
- sqlspec/builder/mixins/__init__.py +0 -55
- sqlspec/builder/mixins/_cte_and_set_ops.py +0 -253
- sqlspec/builder/mixins/_delete_operations.py +0 -50
- sqlspec/builder/mixins/_insert_operations.py +0 -282
- sqlspec/builder/mixins/_merge_operations.py +0 -698
- sqlspec/builder/mixins/_order_limit_operations.py +0 -145
- sqlspec/builder/mixins/_pivot_operations.py +0 -157
- sqlspec/builder/mixins/_select_operations.py +0 -930
- sqlspec/builder/mixins/_update_operations.py +0 -199
- sqlspec/builder/mixins/_where_clause.py +0 -1298
- sqlspec-0.26.0.dist-info/RECORD +0 -157
- sqlspec-0.26.0.dist-info/licenses/NOTICE +0 -29
- {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/entry_points.txt +0 -0
- {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,
|
|
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="
|
|
36
|
-
SyncConfigT = TypeVar("SyncConfigT", bound="
|
|
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="
|
|
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="
|
|
48
|
+
DriverT = TypeVar("DriverT", bound="SyncDriverAdapterBase | AsyncDriverAdapterBase")
|
|
46
49
|
|
|
47
50
|
logger = get_logger("config")
|
|
48
51
|
|
|
49
52
|
|
|
50
|
-
class LifecycleConfig(TypedDict
|
|
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
|
|
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: "
|
|
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: "
|
|
271
|
+
bind_key: "str | None"
|
|
110
272
|
statement_config: "StatementConfig"
|
|
111
|
-
pool_instance: "
|
|
112
|
-
migration_config: "
|
|
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) -> "
|
|
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
|
-
) -> "
|
|
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
|
-
) -> "
|
|
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) -> "
|
|
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) -> "
|
|
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
|
-
) -> "
|
|
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) #
|
|
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) -> "
|
|
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: "
|
|
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) -> "
|
|
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) -> "
|
|
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: "
|
|
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:
|
|
321
|
-
migration_config: "
|
|
322
|
-
statement_config: "
|
|
323
|
-
driver_features: "
|
|
324
|
-
bind_key: "
|
|
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.
|
|
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: "
|
|
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: "
|
|
377
|
-
migration_config: "
|
|
378
|
-
statement_config: "
|
|
379
|
-
driver_features: "
|
|
380
|
-
bind_key: "
|
|
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.
|
|
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: "
|
|
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: "
|
|
433
|
-
pool_instance: "
|
|
434
|
-
migration_config: "
|
|
435
|
-
statement_config: "
|
|
436
|
-
driver_features: "
|
|
437
|
-
bind_key: "
|
|
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.
|
|
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: "
|
|
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: "
|
|
512
|
-
pool_instance: "
|
|
513
|
-
migration_config: "
|
|
514
|
-
statement_config: "
|
|
515
|
-
driver_features: "
|
|
516
|
-
bind_key: "
|
|
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.
|
|
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: "
|
|
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 -
|
|
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
|
|
6
|
-
|
|
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",
|