sqlspec 0.14.0__py3-none-any.whl → 0.15.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 +50 -25
- sqlspec/__main__.py +12 -0
- sqlspec/__metadata__.py +1 -3
- sqlspec/_serialization.py +1 -2
- sqlspec/_sql.py +256 -120
- sqlspec/_typing.py +278 -142
- sqlspec/adapters/adbc/__init__.py +4 -3
- sqlspec/adapters/adbc/_types.py +12 -0
- sqlspec/adapters/adbc/config.py +115 -248
- sqlspec/adapters/adbc/driver.py +462 -353
- sqlspec/adapters/aiosqlite/__init__.py +18 -3
- sqlspec/adapters/aiosqlite/_types.py +13 -0
- sqlspec/adapters/aiosqlite/config.py +199 -129
- sqlspec/adapters/aiosqlite/driver.py +230 -269
- sqlspec/adapters/asyncmy/__init__.py +18 -3
- sqlspec/adapters/asyncmy/_types.py +12 -0
- sqlspec/adapters/asyncmy/config.py +80 -168
- sqlspec/adapters/asyncmy/driver.py +260 -225
- sqlspec/adapters/asyncpg/__init__.py +19 -4
- sqlspec/adapters/asyncpg/_types.py +17 -0
- sqlspec/adapters/asyncpg/config.py +82 -181
- sqlspec/adapters/asyncpg/driver.py +285 -383
- sqlspec/adapters/bigquery/__init__.py +17 -3
- sqlspec/adapters/bigquery/_types.py +12 -0
- sqlspec/adapters/bigquery/config.py +191 -258
- sqlspec/adapters/bigquery/driver.py +474 -646
- sqlspec/adapters/duckdb/__init__.py +14 -3
- sqlspec/adapters/duckdb/_types.py +12 -0
- sqlspec/adapters/duckdb/config.py +415 -351
- sqlspec/adapters/duckdb/driver.py +343 -413
- sqlspec/adapters/oracledb/__init__.py +19 -5
- sqlspec/adapters/oracledb/_types.py +14 -0
- sqlspec/adapters/oracledb/config.py +123 -379
- sqlspec/adapters/oracledb/driver.py +507 -560
- sqlspec/adapters/psqlpy/__init__.py +13 -3
- sqlspec/adapters/psqlpy/_types.py +11 -0
- sqlspec/adapters/psqlpy/config.py +93 -254
- sqlspec/adapters/psqlpy/driver.py +505 -234
- sqlspec/adapters/psycopg/__init__.py +19 -5
- sqlspec/adapters/psycopg/_types.py +17 -0
- sqlspec/adapters/psycopg/config.py +143 -403
- sqlspec/adapters/psycopg/driver.py +706 -872
- sqlspec/adapters/sqlite/__init__.py +14 -3
- sqlspec/adapters/sqlite/_types.py +11 -0
- sqlspec/adapters/sqlite/config.py +202 -118
- sqlspec/adapters/sqlite/driver.py +264 -303
- sqlspec/base.py +105 -9
- sqlspec/{statement/builder → builder}/__init__.py +12 -14
- sqlspec/{statement/builder → builder}/_base.py +120 -55
- sqlspec/{statement/builder → builder}/_column.py +17 -6
- sqlspec/{statement/builder → builder}/_ddl.py +46 -79
- sqlspec/{statement/builder → builder}/_ddl_utils.py +5 -10
- sqlspec/{statement/builder → builder}/_delete.py +6 -25
- sqlspec/{statement/builder → builder}/_insert.py +6 -64
- sqlspec/builder/_merge.py +56 -0
- sqlspec/{statement/builder → builder}/_parsing_utils.py +3 -10
- sqlspec/{statement/builder → builder}/_select.py +11 -56
- sqlspec/{statement/builder → builder}/_update.py +12 -18
- sqlspec/{statement/builder → builder}/mixins/__init__.py +10 -14
- sqlspec/{statement/builder → builder}/mixins/_cte_and_set_ops.py +48 -59
- sqlspec/{statement/builder → builder}/mixins/_insert_operations.py +22 -16
- sqlspec/{statement/builder → builder}/mixins/_join_operations.py +1 -3
- sqlspec/{statement/builder → builder}/mixins/_merge_operations.py +3 -5
- sqlspec/{statement/builder → builder}/mixins/_order_limit_operations.py +3 -3
- sqlspec/{statement/builder → builder}/mixins/_pivot_operations.py +4 -8
- sqlspec/{statement/builder → builder}/mixins/_select_operations.py +21 -36
- sqlspec/{statement/builder → builder}/mixins/_update_operations.py +3 -14
- sqlspec/{statement/builder → builder}/mixins/_where_clause.py +52 -79
- sqlspec/cli.py +4 -5
- sqlspec/config.py +180 -133
- sqlspec/core/__init__.py +63 -0
- sqlspec/core/cache.py +873 -0
- sqlspec/core/compiler.py +396 -0
- sqlspec/core/filters.py +828 -0
- sqlspec/core/hashing.py +310 -0
- sqlspec/core/parameters.py +1209 -0
- sqlspec/core/result.py +664 -0
- sqlspec/{statement → core}/splitter.py +321 -191
- sqlspec/core/statement.py +651 -0
- sqlspec/driver/__init__.py +7 -10
- sqlspec/driver/_async.py +387 -176
- sqlspec/driver/_common.py +527 -289
- sqlspec/driver/_sync.py +390 -172
- sqlspec/driver/mixins/__init__.py +2 -19
- sqlspec/driver/mixins/_result_tools.py +168 -0
- sqlspec/driver/mixins/_sql_translator.py +6 -3
- sqlspec/exceptions.py +5 -252
- sqlspec/extensions/aiosql/adapter.py +93 -96
- sqlspec/extensions/litestar/config.py +0 -1
- sqlspec/extensions/litestar/handlers.py +15 -26
- sqlspec/extensions/litestar/plugin.py +16 -14
- sqlspec/extensions/litestar/providers.py +17 -52
- sqlspec/loader.py +424 -105
- sqlspec/migrations/__init__.py +12 -0
- sqlspec/migrations/base.py +92 -68
- sqlspec/migrations/commands.py +24 -106
- sqlspec/migrations/loaders.py +402 -0
- sqlspec/migrations/runner.py +49 -51
- sqlspec/migrations/tracker.py +31 -44
- sqlspec/migrations/utils.py +64 -24
- sqlspec/protocols.py +7 -183
- sqlspec/storage/__init__.py +1 -1
- sqlspec/storage/backends/base.py +37 -40
- sqlspec/storage/backends/fsspec.py +136 -112
- sqlspec/storage/backends/obstore.py +138 -160
- sqlspec/storage/capabilities.py +5 -4
- sqlspec/storage/registry.py +57 -106
- sqlspec/typing.py +136 -115
- sqlspec/utils/__init__.py +2 -3
- sqlspec/utils/correlation.py +0 -3
- sqlspec/utils/deprecation.py +6 -6
- sqlspec/utils/fixtures.py +6 -6
- sqlspec/utils/logging.py +0 -2
- sqlspec/utils/module_loader.py +7 -12
- sqlspec/utils/singleton.py +0 -1
- sqlspec/utils/sync_tools.py +16 -37
- sqlspec/utils/text.py +12 -51
- sqlspec/utils/type_guards.py +443 -232
- {sqlspec-0.14.0.dist-info → sqlspec-0.15.0.dist-info}/METADATA +7 -2
- sqlspec-0.15.0.dist-info/RECORD +134 -0
- sqlspec-0.15.0.dist-info/entry_points.txt +2 -0
- sqlspec/driver/connection.py +0 -207
- sqlspec/driver/mixins/_cache.py +0 -114
- sqlspec/driver/mixins/_csv_writer.py +0 -91
- sqlspec/driver/mixins/_pipeline.py +0 -508
- sqlspec/driver/mixins/_query_tools.py +0 -796
- sqlspec/driver/mixins/_result_utils.py +0 -138
- sqlspec/driver/mixins/_storage.py +0 -912
- sqlspec/driver/mixins/_type_coercion.py +0 -128
- sqlspec/driver/parameters.py +0 -138
- sqlspec/statement/__init__.py +0 -21
- sqlspec/statement/builder/_merge.py +0 -95
- sqlspec/statement/cache.py +0 -50
- sqlspec/statement/filters.py +0 -625
- sqlspec/statement/parameters.py +0 -996
- sqlspec/statement/pipelines/__init__.py +0 -210
- sqlspec/statement/pipelines/analyzers/__init__.py +0 -9
- sqlspec/statement/pipelines/analyzers/_analyzer.py +0 -646
- sqlspec/statement/pipelines/context.py +0 -115
- sqlspec/statement/pipelines/transformers/__init__.py +0 -7
- sqlspec/statement/pipelines/transformers/_expression_simplifier.py +0 -88
- sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +0 -1247
- sqlspec/statement/pipelines/transformers/_remove_comments_and_hints.py +0 -76
- sqlspec/statement/pipelines/validators/__init__.py +0 -23
- sqlspec/statement/pipelines/validators/_dml_safety.py +0 -290
- sqlspec/statement/pipelines/validators/_parameter_style.py +0 -370
- sqlspec/statement/pipelines/validators/_performance.py +0 -714
- sqlspec/statement/pipelines/validators/_security.py +0 -967
- sqlspec/statement/result.py +0 -435
- sqlspec/statement/sql.py +0 -1774
- sqlspec/utils/cached_property.py +0 -25
- sqlspec/utils/statement_hashing.py +0 -203
- sqlspec-0.14.0.dist-info/RECORD +0 -143
- sqlspec-0.14.0.dist-info/entry_points.txt +0 -2
- /sqlspec/{statement/builder → builder}/mixins/_delete_operations.py +0 -0
- {sqlspec-0.14.0.dist-info → sqlspec-0.15.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.14.0.dist-info → sqlspec-0.15.0.dist-info}/licenses/LICENSE +0 -0
- {sqlspec-0.14.0.dist-info → sqlspec-0.15.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
from sqlspec.adapters.aiosqlite.
|
|
2
|
-
from sqlspec.adapters.aiosqlite.
|
|
1
|
+
from sqlspec.adapters.aiosqlite._types import AiosqliteConnection
|
|
2
|
+
from sqlspec.adapters.aiosqlite.config import AiosqliteConfig, AiosqliteConnectionParams, AiosqliteConnectionPool
|
|
3
|
+
from sqlspec.adapters.aiosqlite.driver import (
|
|
4
|
+
AiosqliteCursor,
|
|
5
|
+
AiosqliteDriver,
|
|
6
|
+
AiosqliteExceptionHandler,
|
|
7
|
+
aiosqlite_statement_config,
|
|
8
|
+
)
|
|
3
9
|
|
|
4
|
-
__all__ = (
|
|
10
|
+
__all__ = (
|
|
11
|
+
"AiosqliteConfig",
|
|
12
|
+
"AiosqliteConnection",
|
|
13
|
+
"AiosqliteConnectionParams",
|
|
14
|
+
"AiosqliteConnectionPool",
|
|
15
|
+
"AiosqliteCursor",
|
|
16
|
+
"AiosqliteDriver",
|
|
17
|
+
"AiosqliteExceptionHandler",
|
|
18
|
+
"aiosqlite_statement_config",
|
|
19
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# pyright: reportCallIssue=false, reportAttributeAccessIssue=false, reportArgumentType=false
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
import aiosqlite
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from typing_extensions import TypeAlias
|
|
8
|
+
|
|
9
|
+
AiosqliteConnection: TypeAlias = aiosqlite.Connection
|
|
10
|
+
else:
|
|
11
|
+
AiosqliteConnection = aiosqlite.Connection
|
|
12
|
+
|
|
13
|
+
__all__ = ("AiosqliteConnection",)
|
|
@@ -1,183 +1,253 @@
|
|
|
1
|
-
"""Aiosqlite database configuration with
|
|
1
|
+
"""Aiosqlite database configuration with optimized connection management."""
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
3
4
|
import logging
|
|
4
|
-
from collections.abc import AsyncGenerator
|
|
5
5
|
from contextlib import asynccontextmanager
|
|
6
|
-
from typing import TYPE_CHECKING, Any, ClassVar, Optional
|
|
6
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Final, Optional, TypedDict
|
|
7
7
|
|
|
8
8
|
import aiosqlite
|
|
9
|
+
from typing_extensions import NotRequired
|
|
9
10
|
|
|
10
|
-
from sqlspec.adapters.aiosqlite.driver import
|
|
11
|
+
from sqlspec.adapters.aiosqlite.driver import AiosqliteCursor, AiosqliteDriver, aiosqlite_statement_config
|
|
11
12
|
from sqlspec.config import AsyncDatabaseConfig
|
|
12
|
-
from sqlspec.exceptions import ImproperConfigurationError
|
|
13
|
-
from sqlspec.statement.sql import SQLConfig
|
|
14
|
-
from sqlspec.typing import DictRow, Empty
|
|
15
13
|
|
|
16
14
|
if TYPE_CHECKING:
|
|
17
|
-
from
|
|
15
|
+
from collections.abc import AsyncGenerator
|
|
18
16
|
|
|
17
|
+
from sqlspec.adapters.aiosqlite._types import AiosqliteConnection
|
|
18
|
+
from sqlspec.core.statement import StatementConfig
|
|
19
19
|
|
|
20
|
-
__all__ = ("
|
|
20
|
+
__all__ = ("AiosqliteConfig", "AiosqliteConnectionParams", "AiosqliteConnectionPool")
|
|
21
21
|
|
|
22
22
|
logger = logging.getLogger(__name__)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
# Core PRAGMAs for SQLite performance optimization
|
|
25
|
+
WAL_PRAGMA_SQL: Final[str] = "PRAGMA journal_mode = WAL"
|
|
26
|
+
FOREIGN_KEYS_SQL: Final[str] = "PRAGMA foreign_keys = ON"
|
|
27
|
+
SYNC_NORMAL_SQL: Final[str] = "PRAGMA synchronous = NORMAL"
|
|
28
|
+
BUSY_TIMEOUT_SQL: Final[str] = "PRAGMA busy_timeout = 5000" # 5 seconds
|
|
27
29
|
|
|
28
30
|
|
|
29
|
-
class
|
|
30
|
-
"""
|
|
31
|
+
class AiosqliteConnectionPool:
|
|
32
|
+
"""Connection pool for Aiosqlite using a single shared connection approach.
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
Uses a single shared connection per database file since aiosqlite internally
|
|
35
|
+
handles queuing and serialization of operations.
|
|
33
36
|
"""
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
supports_connection_pooling: ClassVar[bool] = False
|
|
38
|
+
__slots__ = ("_closed", "_connection", "_connection_parameters", "_lock")
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
def __init__(self, connection_parameters: "dict[str, Any]") -> None:
|
|
41
|
+
"""Initialize connection manager.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
connection_parameters: SQLite connection parameters
|
|
45
|
+
"""
|
|
46
|
+
self._connection: Optional[AiosqliteConnection] = None
|
|
47
|
+
self._connection_parameters = connection_parameters
|
|
48
|
+
self._lock = asyncio.Lock()
|
|
49
|
+
self._closed = False
|
|
50
|
+
|
|
51
|
+
async def _ensure_connection(self) -> "AiosqliteConnection":
|
|
52
|
+
"""Ensure we have a valid connection, creating one if needed."""
|
|
53
|
+
async with self._lock:
|
|
54
|
+
if self._connection is None or self._closed:
|
|
55
|
+
self._connection = await aiosqlite.connect(**self._connection_parameters)
|
|
56
|
+
|
|
57
|
+
await self._connection.execute(WAL_PRAGMA_SQL)
|
|
58
|
+
await self._connection.execute(FOREIGN_KEYS_SQL)
|
|
59
|
+
await self._connection.execute(SYNC_NORMAL_SQL)
|
|
60
|
+
await self._connection.execute(BUSY_TIMEOUT_SQL)
|
|
61
|
+
await self._connection.commit()
|
|
62
|
+
|
|
63
|
+
self._closed = False
|
|
64
|
+
logger.debug("Created new aiosqlite connection")
|
|
65
|
+
|
|
66
|
+
return self._connection
|
|
67
|
+
|
|
68
|
+
@asynccontextmanager
|
|
69
|
+
async def get_connection(self) -> "AsyncGenerator[AiosqliteConnection, None]":
|
|
70
|
+
"""Get the shared connection.
|
|
71
|
+
|
|
72
|
+
Yields:
|
|
73
|
+
The shared Aiosqlite connection instance.
|
|
74
|
+
"""
|
|
75
|
+
connection = await self._ensure_connection()
|
|
76
|
+
yield connection
|
|
77
|
+
|
|
78
|
+
async def close(self) -> None:
|
|
79
|
+
"""Close the shared connection."""
|
|
80
|
+
async with self._lock:
|
|
81
|
+
if self._connection is not None and not self._closed:
|
|
82
|
+
await self._connection.close()
|
|
83
|
+
self._connection = None
|
|
84
|
+
self._closed = True
|
|
85
|
+
logger.debug("Closed aiosqlite connection")
|
|
86
|
+
|
|
87
|
+
def size(self) -> int:
|
|
88
|
+
"""Get connection count."""
|
|
89
|
+
return 0 if self._closed or self._connection is None else 1
|
|
90
|
+
|
|
91
|
+
def checked_out(self) -> int:
|
|
92
|
+
"""Get number of checked out connections."""
|
|
93
|
+
return 0
|
|
94
|
+
|
|
95
|
+
async def acquire(self) -> "AiosqliteConnection":
|
|
96
|
+
"""Get the shared connection directly.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
The shared connection instance.
|
|
100
|
+
"""
|
|
101
|
+
return await self._ensure_connection()
|
|
102
|
+
|
|
103
|
+
async def release(self, connection: "AiosqliteConnection") -> None:
|
|
104
|
+
"""No-op release for compatibility.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
connection: Connection to release (ignored)
|
|
108
|
+
"""
|
|
109
|
+
_ = connection
|
|
40
110
|
|
|
41
|
-
# Parameter style support information
|
|
42
|
-
supported_parameter_styles: ClassVar[tuple[str, ...]] = ("qmark", "named_colon")
|
|
43
|
-
"""AIOSQLite supports ? (qmark) and :name (named_colon) parameter styles."""
|
|
44
111
|
|
|
45
|
-
|
|
46
|
-
"""
|
|
112
|
+
class AiosqliteConnectionParams(TypedDict, total=False):
|
|
113
|
+
"""aiosqlite connection parameters."""
|
|
114
|
+
|
|
115
|
+
database: NotRequired[str]
|
|
116
|
+
timeout: NotRequired[float]
|
|
117
|
+
detect_types: NotRequired[int]
|
|
118
|
+
isolation_level: NotRequired[Optional[str]]
|
|
119
|
+
check_same_thread: NotRequired[bool]
|
|
120
|
+
cached_statements: NotRequired[int]
|
|
121
|
+
uri: NotRequired[bool]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class AiosqliteConfig(AsyncDatabaseConfig):
|
|
125
|
+
"""Database configuration for AioSQLite engine."""
|
|
126
|
+
|
|
127
|
+
driver_type: ClassVar[type[AiosqliteDriver]] = AiosqliteDriver
|
|
128
|
+
cursor_type: ClassVar[type[AiosqliteCursor]] = AiosqliteCursor
|
|
47
129
|
|
|
48
130
|
def __init__(
|
|
49
131
|
self,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
detect_types: Optional[int] = None,
|
|
56
|
-
isolation_level: Optional["Optional[Literal['DEFERRED', 'IMMEDIATE', 'EXCLUSIVE']]"] = None,
|
|
57
|
-
check_same_thread: Optional[bool] = None,
|
|
58
|
-
cached_statements: Optional[int] = None,
|
|
59
|
-
uri: Optional[bool] = None,
|
|
132
|
+
*,
|
|
133
|
+
pool_instance: "Optional[AiosqliteConnectionPool]" = None,
|
|
134
|
+
pool_config: "Optional[dict[str, Any]]" = None,
|
|
135
|
+
migration_config: "Optional[dict[str, Any]]" = None,
|
|
136
|
+
statement_config: "Optional[StatementConfig]" = None,
|
|
60
137
|
**kwargs: Any,
|
|
61
138
|
) -> None:
|
|
62
|
-
"""Initialize
|
|
139
|
+
"""Initialize AioSQLite configuration.
|
|
63
140
|
|
|
64
141
|
Args:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
isolation_level: The isolation_level of the connection. This can be None for autocommit mode or one of "DEFERRED", "IMMEDIATE" or "EXCLUSIVE"
|
|
71
|
-
check_same_thread: If True (default), ProgrammingError is raised if the database connection is used by a thread other than the one that created it
|
|
72
|
-
cached_statements: The number of statements that SQLite will cache for this connection. The default is 128
|
|
73
|
-
uri: If set to True, database is interpreted as a URI with supported options
|
|
74
|
-
**kwargs: Additional parameters (stored in extras)
|
|
142
|
+
pool_instance: Optional pre-configured connection pool instance.
|
|
143
|
+
pool_config: Optional pool configuration dict (AiosqliteConnectionParams).
|
|
144
|
+
migration_config: Optional migration configuration.
|
|
145
|
+
statement_config: Optional statement configuration.
|
|
146
|
+
**kwargs: Additional connection parameters.
|
|
75
147
|
"""
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
self.isolation_level = isolation_level
|
|
81
|
-
self.check_same_thread = check_same_thread
|
|
82
|
-
self.cached_statements = cached_statements
|
|
83
|
-
self.uri = uri
|
|
84
|
-
self.extras = kwargs or {}
|
|
85
|
-
# Store other config
|
|
86
|
-
self.statement_config = statement_config or SQLConfig()
|
|
87
|
-
self.default_row_type = default_row_type
|
|
88
|
-
|
|
89
|
-
super().__init__()
|
|
90
|
-
|
|
91
|
-
@property
|
|
92
|
-
def connection_config_dict(self) -> dict[str, Any]:
|
|
93
|
-
"""Return the connection configuration as a dict for aiosqlite.connect()."""
|
|
94
|
-
# Gather non-None connection parameters
|
|
95
|
-
config = {
|
|
96
|
-
field: getattr(self, field)
|
|
97
|
-
for field in CONNECTION_FIELDS
|
|
98
|
-
if getattr(self, field, None) is not None and getattr(self, field) is not Empty
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
# Merge extras parameters
|
|
102
|
-
config.update(self.extras)
|
|
103
|
-
|
|
104
|
-
return config
|
|
105
|
-
|
|
106
|
-
async def _create_pool(self) -> None:
|
|
107
|
-
"""Aiosqlite doesn't support pooling."""
|
|
108
|
-
return
|
|
148
|
+
connection_params = {}
|
|
149
|
+
if pool_config:
|
|
150
|
+
connection_params.update(pool_config)
|
|
151
|
+
connection_params.update(kwargs)
|
|
109
152
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
153
|
+
super().__init__(
|
|
154
|
+
pool_config=connection_params,
|
|
155
|
+
pool_instance=pool_instance,
|
|
156
|
+
migration_config=migration_config or {},
|
|
157
|
+
statement_config=statement_config or aiosqlite_statement_config,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
self._connection_parameters = self._parse_connection_parameters(connection_params)
|
|
113
161
|
|
|
114
|
-
|
|
115
|
-
|
|
162
|
+
if pool_instance is None:
|
|
163
|
+
self.pool_instance: AiosqliteConnectionPool = AiosqliteConnectionPool(self._connection_parameters)
|
|
164
|
+
|
|
165
|
+
def _parse_connection_parameters(self, params: "dict[str, Any]") -> "dict[str, Any]":
|
|
166
|
+
"""Parse connection parameters for AioSQLite.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
params: Connection parameters dict.
|
|
116
170
|
|
|
117
171
|
Returns:
|
|
118
|
-
|
|
172
|
+
Processed connection parameters dict.
|
|
119
173
|
"""
|
|
120
|
-
|
|
121
|
-
config = self.connection_config_dict
|
|
122
|
-
return await aiosqlite.connect(**config)
|
|
123
|
-
except Exception as e:
|
|
124
|
-
msg = f"Could not configure the Aiosqlite connection. Error: {e!s}"
|
|
125
|
-
raise ImproperConfigurationError(msg) from e
|
|
174
|
+
result = params.copy()
|
|
126
175
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
176
|
+
if "database" not in result:
|
|
177
|
+
# Default to in-memory database
|
|
178
|
+
result["database"] = ":memory:"
|
|
130
179
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
180
|
+
# Convert regular :memory: to shared memory for multi-connection access
|
|
181
|
+
if result.get("database") == ":memory:":
|
|
182
|
+
result["database"] = "file::memory:?cache=shared"
|
|
183
|
+
result["uri"] = True
|
|
184
|
+
|
|
185
|
+
for pool_param in ["pool_min_size", "pool_max_size", "pool_timeout", "pool_recycle_seconds"]:
|
|
186
|
+
result.pop(pool_param, None)
|
|
187
|
+
|
|
188
|
+
return result
|
|
189
|
+
|
|
190
|
+
@asynccontextmanager
|
|
191
|
+
async def provide_connection(self) -> "AsyncGenerator[AiosqliteConnection, None]":
|
|
192
|
+
"""Provide a database connection.
|
|
134
193
|
|
|
135
194
|
Yields:
|
|
136
|
-
|
|
195
|
+
AiosqliteConnection: Database connection instance.
|
|
137
196
|
"""
|
|
138
|
-
|
|
139
|
-
try:
|
|
197
|
+
async with self.pool_instance.get_connection() as connection:
|
|
140
198
|
yield connection
|
|
141
|
-
finally:
|
|
142
|
-
await connection.close()
|
|
143
199
|
|
|
144
200
|
@asynccontextmanager
|
|
145
|
-
async def provide_session(
|
|
146
|
-
""
|
|
201
|
+
async def provide_session(
|
|
202
|
+
self, *args: Any, statement_config: "Optional[StatementConfig]" = None, **kwargs: Any
|
|
203
|
+
) -> "AsyncGenerator[AiosqliteDriver, None]":
|
|
204
|
+
"""Provide an async database session.
|
|
147
205
|
|
|
148
206
|
Args:
|
|
149
|
-
*args: Additional arguments.
|
|
207
|
+
*args: Additional positional arguments.
|
|
208
|
+
statement_config: Optional statement configuration override.
|
|
150
209
|
**kwargs: Additional keyword arguments.
|
|
151
210
|
|
|
152
211
|
Yields:
|
|
153
|
-
|
|
212
|
+
AiosqliteDriver: Database session instance.
|
|
154
213
|
"""
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
214
|
+
_ = args, kwargs
|
|
215
|
+
effective_statement_config = statement_config or self.statement_config
|
|
216
|
+
async with self.pool_instance.get_connection() as connection:
|
|
217
|
+
session = self.driver_type(connection, statement_config=effective_statement_config)
|
|
218
|
+
try:
|
|
219
|
+
yield session
|
|
220
|
+
finally:
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
async def close(self) -> None:
|
|
224
|
+
"""Close the connection manager."""
|
|
225
|
+
if self.pool_instance:
|
|
226
|
+
await self.pool_instance.close()
|
|
227
|
+
|
|
228
|
+
def _get_connection_config_dict(self) -> "dict[str, Any]":
|
|
229
|
+
"""Get connection configuration dictionary.
|
|
171
230
|
|
|
172
|
-
|
|
173
|
-
|
|
231
|
+
Returns:
|
|
232
|
+
Connection parameters for creating connections.
|
|
233
|
+
"""
|
|
234
|
+
return self._connection_parameters.copy()
|
|
174
235
|
|
|
175
|
-
|
|
176
|
-
|
|
236
|
+
async def _create_pool(self) -> "AiosqliteConnectionPool":
|
|
237
|
+
"""Create the connection manager instance.
|
|
177
238
|
|
|
178
239
|
Returns:
|
|
179
|
-
|
|
240
|
+
AiosqliteConnectionPool: The connection manager instance.
|
|
180
241
|
"""
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return
|
|
242
|
+
if self.pool_instance is None:
|
|
243
|
+
self.pool_instance = AiosqliteConnectionPool(self._connection_parameters)
|
|
244
|
+
return self.pool_instance
|
|
245
|
+
|
|
246
|
+
async def _close_pool(self) -> None:
|
|
247
|
+
"""Close the connection manager."""
|
|
248
|
+
if self.pool_instance:
|
|
249
|
+
await self.pool_instance.close()
|
|
250
|
+
|
|
251
|
+
async def close_pool(self) -> None:
|
|
252
|
+
"""Close the connection pool (delegates to _close_pool)."""
|
|
253
|
+
await self._close_pool()
|