sqlspec 0.14.1__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.

Files changed (158) hide show
  1. sqlspec/__init__.py +50 -25
  2. sqlspec/__main__.py +1 -1
  3. sqlspec/__metadata__.py +1 -3
  4. sqlspec/_serialization.py +1 -2
  5. sqlspec/_sql.py +256 -120
  6. sqlspec/_typing.py +278 -142
  7. sqlspec/adapters/adbc/__init__.py +4 -3
  8. sqlspec/adapters/adbc/_types.py +12 -0
  9. sqlspec/adapters/adbc/config.py +115 -260
  10. sqlspec/adapters/adbc/driver.py +462 -367
  11. sqlspec/adapters/aiosqlite/__init__.py +18 -3
  12. sqlspec/adapters/aiosqlite/_types.py +13 -0
  13. sqlspec/adapters/aiosqlite/config.py +199 -129
  14. sqlspec/adapters/aiosqlite/driver.py +230 -269
  15. sqlspec/adapters/asyncmy/__init__.py +18 -3
  16. sqlspec/adapters/asyncmy/_types.py +12 -0
  17. sqlspec/adapters/asyncmy/config.py +80 -168
  18. sqlspec/adapters/asyncmy/driver.py +260 -225
  19. sqlspec/adapters/asyncpg/__init__.py +19 -4
  20. sqlspec/adapters/asyncpg/_types.py +17 -0
  21. sqlspec/adapters/asyncpg/config.py +82 -181
  22. sqlspec/adapters/asyncpg/driver.py +285 -383
  23. sqlspec/adapters/bigquery/__init__.py +17 -3
  24. sqlspec/adapters/bigquery/_types.py +12 -0
  25. sqlspec/adapters/bigquery/config.py +191 -258
  26. sqlspec/adapters/bigquery/driver.py +474 -646
  27. sqlspec/adapters/duckdb/__init__.py +14 -3
  28. sqlspec/adapters/duckdb/_types.py +12 -0
  29. sqlspec/adapters/duckdb/config.py +415 -351
  30. sqlspec/adapters/duckdb/driver.py +343 -413
  31. sqlspec/adapters/oracledb/__init__.py +19 -5
  32. sqlspec/adapters/oracledb/_types.py +14 -0
  33. sqlspec/adapters/oracledb/config.py +123 -379
  34. sqlspec/adapters/oracledb/driver.py +507 -560
  35. sqlspec/adapters/psqlpy/__init__.py +13 -3
  36. sqlspec/adapters/psqlpy/_types.py +11 -0
  37. sqlspec/adapters/psqlpy/config.py +93 -254
  38. sqlspec/adapters/psqlpy/driver.py +505 -234
  39. sqlspec/adapters/psycopg/__init__.py +19 -5
  40. sqlspec/adapters/psycopg/_types.py +17 -0
  41. sqlspec/adapters/psycopg/config.py +143 -403
  42. sqlspec/adapters/psycopg/driver.py +706 -872
  43. sqlspec/adapters/sqlite/__init__.py +14 -3
  44. sqlspec/adapters/sqlite/_types.py +11 -0
  45. sqlspec/adapters/sqlite/config.py +202 -118
  46. sqlspec/adapters/sqlite/driver.py +264 -303
  47. sqlspec/base.py +105 -9
  48. sqlspec/{statement/builder → builder}/__init__.py +12 -14
  49. sqlspec/{statement/builder → builder}/_base.py +120 -55
  50. sqlspec/{statement/builder → builder}/_column.py +17 -6
  51. sqlspec/{statement/builder → builder}/_ddl.py +46 -79
  52. sqlspec/{statement/builder → builder}/_ddl_utils.py +5 -10
  53. sqlspec/{statement/builder → builder}/_delete.py +6 -25
  54. sqlspec/{statement/builder → builder}/_insert.py +6 -64
  55. sqlspec/builder/_merge.py +56 -0
  56. sqlspec/{statement/builder → builder}/_parsing_utils.py +3 -10
  57. sqlspec/{statement/builder → builder}/_select.py +11 -56
  58. sqlspec/{statement/builder → builder}/_update.py +12 -18
  59. sqlspec/{statement/builder → builder}/mixins/__init__.py +10 -14
  60. sqlspec/{statement/builder → builder}/mixins/_cte_and_set_ops.py +48 -59
  61. sqlspec/{statement/builder → builder}/mixins/_insert_operations.py +22 -16
  62. sqlspec/{statement/builder → builder}/mixins/_join_operations.py +1 -3
  63. sqlspec/{statement/builder → builder}/mixins/_merge_operations.py +3 -5
  64. sqlspec/{statement/builder → builder}/mixins/_order_limit_operations.py +3 -3
  65. sqlspec/{statement/builder → builder}/mixins/_pivot_operations.py +4 -8
  66. sqlspec/{statement/builder → builder}/mixins/_select_operations.py +21 -36
  67. sqlspec/{statement/builder → builder}/mixins/_update_operations.py +3 -14
  68. sqlspec/{statement/builder → builder}/mixins/_where_clause.py +52 -79
  69. sqlspec/cli.py +4 -5
  70. sqlspec/config.py +180 -133
  71. sqlspec/core/__init__.py +63 -0
  72. sqlspec/core/cache.py +873 -0
  73. sqlspec/core/compiler.py +396 -0
  74. sqlspec/core/filters.py +828 -0
  75. sqlspec/core/hashing.py +310 -0
  76. sqlspec/core/parameters.py +1209 -0
  77. sqlspec/core/result.py +664 -0
  78. sqlspec/{statement → core}/splitter.py +321 -191
  79. sqlspec/core/statement.py +651 -0
  80. sqlspec/driver/__init__.py +7 -10
  81. sqlspec/driver/_async.py +387 -176
  82. sqlspec/driver/_common.py +527 -289
  83. sqlspec/driver/_sync.py +390 -172
  84. sqlspec/driver/mixins/__init__.py +2 -19
  85. sqlspec/driver/mixins/_result_tools.py +168 -0
  86. sqlspec/driver/mixins/_sql_translator.py +6 -3
  87. sqlspec/exceptions.py +5 -252
  88. sqlspec/extensions/aiosql/adapter.py +93 -96
  89. sqlspec/extensions/litestar/config.py +0 -1
  90. sqlspec/extensions/litestar/handlers.py +15 -26
  91. sqlspec/extensions/litestar/plugin.py +16 -14
  92. sqlspec/extensions/litestar/providers.py +17 -52
  93. sqlspec/loader.py +424 -105
  94. sqlspec/migrations/__init__.py +12 -0
  95. sqlspec/migrations/base.py +92 -68
  96. sqlspec/migrations/commands.py +24 -106
  97. sqlspec/migrations/loaders.py +402 -0
  98. sqlspec/migrations/runner.py +49 -51
  99. sqlspec/migrations/tracker.py +31 -44
  100. sqlspec/migrations/utils.py +64 -24
  101. sqlspec/protocols.py +7 -183
  102. sqlspec/storage/__init__.py +1 -1
  103. sqlspec/storage/backends/base.py +37 -40
  104. sqlspec/storage/backends/fsspec.py +136 -112
  105. sqlspec/storage/backends/obstore.py +138 -160
  106. sqlspec/storage/capabilities.py +5 -4
  107. sqlspec/storage/registry.py +57 -106
  108. sqlspec/typing.py +136 -115
  109. sqlspec/utils/__init__.py +2 -3
  110. sqlspec/utils/correlation.py +0 -3
  111. sqlspec/utils/deprecation.py +6 -6
  112. sqlspec/utils/fixtures.py +6 -6
  113. sqlspec/utils/logging.py +0 -2
  114. sqlspec/utils/module_loader.py +7 -12
  115. sqlspec/utils/singleton.py +0 -1
  116. sqlspec/utils/sync_tools.py +16 -37
  117. sqlspec/utils/text.py +12 -51
  118. sqlspec/utils/type_guards.py +443 -232
  119. {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/METADATA +7 -2
  120. sqlspec-0.15.0.dist-info/RECORD +134 -0
  121. sqlspec/adapters/adbc/transformers.py +0 -108
  122. sqlspec/driver/connection.py +0 -207
  123. sqlspec/driver/mixins/_cache.py +0 -114
  124. sqlspec/driver/mixins/_csv_writer.py +0 -91
  125. sqlspec/driver/mixins/_pipeline.py +0 -508
  126. sqlspec/driver/mixins/_query_tools.py +0 -796
  127. sqlspec/driver/mixins/_result_utils.py +0 -138
  128. sqlspec/driver/mixins/_storage.py +0 -912
  129. sqlspec/driver/mixins/_type_coercion.py +0 -128
  130. sqlspec/driver/parameters.py +0 -138
  131. sqlspec/statement/__init__.py +0 -21
  132. sqlspec/statement/builder/_merge.py +0 -95
  133. sqlspec/statement/cache.py +0 -50
  134. sqlspec/statement/filters.py +0 -625
  135. sqlspec/statement/parameters.py +0 -956
  136. sqlspec/statement/pipelines/__init__.py +0 -210
  137. sqlspec/statement/pipelines/analyzers/__init__.py +0 -9
  138. sqlspec/statement/pipelines/analyzers/_analyzer.py +0 -646
  139. sqlspec/statement/pipelines/context.py +0 -109
  140. sqlspec/statement/pipelines/transformers/__init__.py +0 -7
  141. sqlspec/statement/pipelines/transformers/_expression_simplifier.py +0 -88
  142. sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +0 -1247
  143. sqlspec/statement/pipelines/transformers/_remove_comments_and_hints.py +0 -76
  144. sqlspec/statement/pipelines/validators/__init__.py +0 -23
  145. sqlspec/statement/pipelines/validators/_dml_safety.py +0 -290
  146. sqlspec/statement/pipelines/validators/_parameter_style.py +0 -370
  147. sqlspec/statement/pipelines/validators/_performance.py +0 -714
  148. sqlspec/statement/pipelines/validators/_security.py +0 -967
  149. sqlspec/statement/result.py +0 -435
  150. sqlspec/statement/sql.py +0 -1774
  151. sqlspec/utils/cached_property.py +0 -25
  152. sqlspec/utils/statement_hashing.py +0 -203
  153. sqlspec-0.14.1.dist-info/RECORD +0 -145
  154. /sqlspec/{statement/builder → builder}/mixins/_delete_operations.py +0 -0
  155. {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/WHEEL +0 -0
  156. {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/entry_points.txt +0 -0
  157. {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/licenses/LICENSE +0 -0
  158. {sqlspec-0.14.1.dist-info → sqlspec-0.15.0.dist-info}/licenses/NOTICE +0 -0
@@ -1,4 +1,15 @@
1
- from sqlspec.adapters.sqlite.config import CONNECTION_FIELDS, SqliteConfig
2
- from sqlspec.adapters.sqlite.driver import SqliteConnection, SqliteDriver
1
+ """SQLite adapter for SQLSpec."""
3
2
 
4
- __all__ = ("CONNECTION_FIELDS", "SqliteConfig", "SqliteConnection", "SqliteDriver")
3
+ from sqlspec.adapters.sqlite._types import SqliteConnection
4
+ from sqlspec.adapters.sqlite.config import SqliteConfig, SqliteConnectionParams
5
+ from sqlspec.adapters.sqlite.driver import SqliteCursor, SqliteDriver, SqliteExceptionHandler, sqlite_statement_config
6
+
7
+ __all__ = (
8
+ "SqliteConfig",
9
+ "SqliteConnection",
10
+ "SqliteConnectionParams",
11
+ "SqliteCursor",
12
+ "SqliteDriver",
13
+ "SqliteExceptionHandler",
14
+ "sqlite_statement_config",
15
+ )
@@ -0,0 +1,11 @@
1
+ import sqlite3
2
+ from typing import TYPE_CHECKING
3
+
4
+ if TYPE_CHECKING:
5
+ from typing_extensions import TypeAlias
6
+
7
+ SqliteConnection: TypeAlias = sqlite3.Connection
8
+ else:
9
+ SqliteConnection = sqlite3.Connection
10
+
11
+ __all__ = ("SqliteConnection",)
@@ -1,156 +1,240 @@
1
- """SQLite database configuration with direct field-based configuration."""
1
+ """SQLite database configuration with thread-local connections."""
2
2
 
3
- import logging
4
3
  import sqlite3
4
+ import threading
5
5
  from contextlib import contextmanager
6
- from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union
6
+ from typing import TYPE_CHECKING, Any, ClassVar, Optional, TypedDict, Union, cast
7
7
 
8
- from sqlspec.adapters.sqlite.driver import SqliteConnection, SqliteDriver
9
- from sqlspec.config import NoPoolSyncConfig
10
- from sqlspec.statement.sql import SQLConfig
11
- from sqlspec.typing import DictRow
8
+ from typing_extensions import NotRequired
9
+
10
+ from sqlspec.adapters.sqlite._types import SqliteConnection
11
+ from sqlspec.adapters.sqlite.driver import SqliteCursor, SqliteDriver, sqlite_statement_config
12
+ from sqlspec.config import SyncDatabaseConfig
12
13
 
13
14
  if TYPE_CHECKING:
14
15
  from collections.abc import Generator
15
16
 
17
+ from sqlspec.core.statement import StatementConfig
18
+
19
+
20
+ class SqliteConnectionParams(TypedDict, total=False):
21
+ """SQLite connection parameters."""
22
+
23
+ database: NotRequired[str]
24
+ timeout: NotRequired[float]
25
+ detect_types: NotRequired[int]
26
+ isolation_level: "NotRequired[Optional[str]]"
27
+ check_same_thread: NotRequired[bool]
28
+ factory: "NotRequired[Optional[type[SqliteConnection]]]"
29
+ cached_statements: NotRequired[int]
30
+ uri: NotRequired[bool]
16
31
 
17
- logger = logging.getLogger(__name__)
18
32
 
19
- CONNECTION_FIELDS = frozenset(
20
- {
21
- "database",
22
- "timeout",
23
- "detect_types",
24
- "isolation_level",
25
- "check_same_thread",
26
- "factory",
27
- "cached_statements",
28
- "uri",
29
- }
30
- )
33
+ __all__ = ("SqliteConfig", "SqliteConnectionParams", "SqliteConnectionPool")
31
34
 
32
- __all__ = ("CONNECTION_FIELDS", "SqliteConfig", "sqlite3")
33
35
 
36
+ class SqliteConnectionPool:
37
+ """Thread-local connection manager for SQLite.
34
38
 
35
- class SqliteConfig(NoPoolSyncConfig[SqliteConnection, SqliteDriver]):
36
- """Configuration for SQLite database connections with direct field-based configuration."""
39
+ SQLite connections aren't thread-safe, so we use thread-local storage
40
+ to ensure each thread has its own connection. This is simpler and more
41
+ efficient than a traditional pool for SQLite's constraints.
42
+ """
37
43
 
38
- driver_type: type[SqliteDriver] = SqliteDriver
39
- connection_type: type[SqliteConnection] = SqliteConnection
40
- supported_parameter_styles: ClassVar[tuple[str, ...]] = ("qmark", "named_colon")
41
- default_parameter_style: ClassVar[str] = "qmark"
44
+ __slots__ = ("_connection_parameters", "_enable_optimizations", "_thread_local")
42
45
 
43
46
  def __init__(
44
47
  self,
45
- database: str = ":memory:",
46
- statement_config: Optional[SQLConfig] = None,
47
- default_row_type: type[DictRow] = DictRow,
48
- # SQLite connection parameters
49
- timeout: Optional[float] = None,
50
- detect_types: Optional[int] = None,
51
- isolation_level: Union[None, str] = None,
52
- check_same_thread: Optional[bool] = None,
53
- factory: Optional[type[SqliteConnection]] = None,
54
- cached_statements: Optional[int] = None,
55
- uri: Optional[bool] = None,
56
- **kwargs: Any,
48
+ connection_parameters: "dict[str, Any]",
49
+ enable_optimizations: bool = True,
50
+ **kwargs: Any, # Accept and ignore pool parameters for compatibility
51
+ ) -> None:
52
+ """Initialize the thread-local connection manager.
53
+
54
+ Args:
55
+ connection_parameters: SQLite connection parameters
56
+ enable_optimizations: Whether to apply performance PRAGMAs
57
+ **kwargs: Ignored pool parameters for compatibility
58
+ """
59
+ self._connection_parameters = connection_parameters
60
+ self._thread_local = threading.local()
61
+ self._enable_optimizations = enable_optimizations
62
+
63
+ def _create_connection(self) -> SqliteConnection:
64
+ """Create a new SQLite connection with optimizations."""
65
+ connection = sqlite3.connect(**self._connection_parameters)
66
+
67
+ # Only apply optimizations if requested and not in-memory
68
+ if self._enable_optimizations:
69
+ database = self._connection_parameters.get("database", ":memory:")
70
+ is_memory = database == ":memory:" or database.startswith("file::memory:")
71
+
72
+ if not is_memory:
73
+ # WAL mode doesn't work with in-memory databases
74
+ connection.execute("PRAGMA journal_mode = WAL")
75
+ # Set busy timeout for better concurrent access
76
+ connection.execute("PRAGMA busy_timeout = 5000")
77
+ connection.execute("PRAGMA optimize")
78
+ # These work for all database types
79
+ connection.execute("PRAGMA foreign_keys = ON")
80
+ connection.execute("PRAGMA synchronous = NORMAL")
81
+
82
+ return connection # type: ignore[no-any-return]
83
+
84
+ def _get_thread_connection(self) -> SqliteConnection:
85
+ """Get or create a connection for the current thread."""
86
+ try:
87
+ return cast("SqliteConnection", self._thread_local.connection)
88
+ except AttributeError:
89
+ # Connection doesn't exist for this thread yet
90
+ connection = self._create_connection()
91
+ self._thread_local.connection = connection
92
+ return connection
93
+
94
+ def _close_thread_connection(self) -> None:
95
+ """Close the connection for the current thread."""
96
+ try:
97
+ connection = self._thread_local.connection
98
+ connection.close()
99
+ del self._thread_local.connection
100
+ except AttributeError:
101
+ # No connection for this thread
102
+ pass
103
+
104
+ @contextmanager
105
+ def get_connection(self) -> "Generator[SqliteConnection, None, None]":
106
+ """Get a thread-local connection.
107
+
108
+ Yields:
109
+ SqliteConnection: A thread-local connection.
110
+ """
111
+ yield self._get_thread_connection()
112
+
113
+ def close(self) -> None:
114
+ """Close the thread-local connection if it exists."""
115
+ self._close_thread_connection()
116
+
117
+ def acquire(self) -> SqliteConnection:
118
+ """Acquire a thread-local connection.
119
+
120
+ Returns:
121
+ SqliteConnection: A thread-local connection
122
+ """
123
+ return self._get_thread_connection()
124
+
125
+ def release(self, connection: SqliteConnection) -> None:
126
+ """Release a connection (no-op for thread-local connections).
127
+
128
+ Args:
129
+ connection: The connection to release (ignored)
130
+ """
131
+ # No-op: thread-local connections are managed per-thread
132
+
133
+ # Compatibility methods that return dummy values
134
+ def size(self) -> int:
135
+ """Get pool size (always 1 for thread-local)."""
136
+ try:
137
+ _ = self._thread_local.connection
138
+ except AttributeError:
139
+ return 0
140
+ return 1
141
+
142
+ def checked_out(self) -> int:
143
+ """Get number of checked out connections (always 0)."""
144
+ return 0
145
+
146
+
147
+ class SqliteConfig(SyncDatabaseConfig[SqliteConnection, SqliteConnectionPool, SqliteDriver]):
148
+ """SQLite configuration with thread-local connections."""
149
+
150
+ driver_type: "ClassVar[type[SqliteDriver]]" = SqliteDriver
151
+ connection_type: "ClassVar[type[SqliteConnection]]" = SqliteConnection
152
+
153
+ def __init__(
154
+ self,
155
+ *,
156
+ pool_config: "Optional[Union[SqliteConnectionParams, dict[str, Any]]]" = None,
157
+ pool_instance: "Optional[SqliteConnectionPool]" = None,
158
+ statement_config: "Optional[StatementConfig]" = None,
159
+ migration_config: "Optional[dict[str, Any]]" = None,
57
160
  ) -> None:
58
161
  """Initialize SQLite configuration.
59
162
 
60
163
  Args:
61
- database: Path to the SQLite database file. Use ':memory:' for in-memory database.
164
+ pool_config: Configuration parameters including connection settings
165
+ pool_instance: Pre-created pool instance
62
166
  statement_config: Default SQL statement configuration
63
- default_row_type: Default row type for results
64
- timeout: Connection timeout in seconds
65
- detect_types: Type detection flags (sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES)
66
- isolation_level: Transaction isolation level
67
- check_same_thread: Whether to check that connection is used on same thread
68
- factory: Custom Connection class factory
69
- cached_statements: Number of statements to cache
70
- uri: Whether to interpret database as URI
71
- **kwargs: Additional parameters (stored in extras)
167
+ migration_config: Migration configuration
72
168
  """
73
- if database is None:
74
- msg = "database parameter cannot be None"
75
- raise TypeError(msg)
76
-
77
- # Store connection parameters as instance attributes
78
- self.database = database
79
- self.timeout = timeout
80
- self.detect_types = detect_types
81
- self.isolation_level = isolation_level
82
- self.check_same_thread = check_same_thread
83
- self.factory = factory
84
- self.cached_statements = cached_statements
85
- self.uri = uri
86
-
87
- self.extras = kwargs or {}
88
-
89
- # Store other config
90
- self.statement_config = statement_config or SQLConfig()
91
- self.default_row_type = default_row_type
92
- super().__init__()
93
-
94
- @property
95
- def connection_config_dict(self) -> dict[str, Any]:
96
- """Return a dictionary of connection parameters for SQLite."""
97
- config = {
98
- "database": self.database,
99
- "timeout": self.timeout,
100
- "detect_types": self.detect_types,
101
- "isolation_level": self.isolation_level,
102
- "check_same_thread": self.check_same_thread,
103
- "factory": self.factory,
104
- "cached_statements": self.cached_statements,
105
- "uri": self.uri,
106
- }
107
- # Filter out None values since sqlite3.connect doesn't accept them
108
- return {k: v for k, v in config.items() if v is not None}
169
+ if pool_config is None:
170
+ pool_config = {}
171
+ if "database" not in pool_config or pool_config["database"] == ":memory:":
172
+ pool_config["database"] = "file::memory:?cache=shared"
173
+ pool_config["uri"] = True
174
+
175
+ super().__init__(
176
+ pool_instance=pool_instance,
177
+ pool_config=cast("dict[str, Any]", pool_config),
178
+ migration_config=migration_config,
179
+ statement_config=statement_config or sqlite_statement_config,
180
+ driver_features={},
181
+ )
182
+
183
+ def _get_connection_config_dict(self) -> "dict[str, Any]":
184
+ """Get connection configuration as plain dict for pool creation."""
185
+ # Filter out pool-specific parameters that SQLite doesn't use
186
+ excluded_keys = {"pool_min_size", "pool_max_size", "pool_timeout", "pool_recycle_seconds", "extra"}
187
+ return {k: v for k, v in self.pool_config.items() if v is not None and k not in excluded_keys}
188
+
189
+ def _create_pool(self) -> SqliteConnectionPool:
190
+ """Create connection pool from configuration."""
191
+ config_dict = self._get_connection_config_dict()
192
+ # Pass all pool_config as kwargs to be ignored by the pool
193
+ return SqliteConnectionPool(connection_parameters=config_dict, **self.pool_config)
194
+
195
+ def _close_pool(self) -> None:
196
+ """Close the connection pool."""
197
+ if self.pool_instance:
198
+ self.pool_instance.close()
109
199
 
110
200
  def create_connection(self) -> SqliteConnection:
111
- """Create and return a SQLite connection."""
112
- connection = sqlite3.connect(**self.connection_config_dict)
113
- connection.row_factory = sqlite3.Row
114
- return connection # type: ignore[no-any-return]
201
+ """Get a SQLite connection from the pool.
202
+
203
+ Returns:
204
+ SqliteConnection: A connection from the pool
205
+ """
206
+ pool = self.provide_pool()
207
+ return pool.acquire()
115
208
 
116
209
  @contextmanager
117
- def provide_connection(self, *args: Any, **kwargs: Any) -> "Generator[SqliteConnection, None, None]":
210
+ def provide_connection(self, *args: "Any", **kwargs: "Any") -> "Generator[SqliteConnection, None, None]":
118
211
  """Provide a SQLite connection context manager.
119
212
 
120
- Args:
121
- *args: Variable length argument list
122
- **kwargs: Arbitrary keyword arguments
123
-
124
213
  Yields:
125
- SqliteConnection: A SQLite connection
126
-
214
+ SqliteConnection: A thread-local connection
127
215
  """
128
- connection = self.create_connection()
129
- try:
216
+ pool = self.provide_pool()
217
+ with pool.get_connection() as connection:
130
218
  yield connection
131
- finally:
132
- connection.close()
133
219
 
134
220
  @contextmanager
135
- def provide_session(self, *args: Any, **kwargs: Any) -> "Generator[SqliteDriver, None, None]":
136
- """Provide a SQLite driver session context manager.
137
-
138
- Args:
139
- *args: Variable length argument list
140
- **kwargs: Arbitrary keyword arguments
221
+ def provide_session(
222
+ self, *args: "Any", statement_config: "Optional[StatementConfig]" = None, **kwargs: "Any"
223
+ ) -> "Generator[SqliteDriver, None, None]":
224
+ """Provide a SQLite driver session.
141
225
 
142
226
  Yields:
143
- SqliteDriver: A SQLite driver
227
+ SqliteDriver: A driver instance with thread-local connection
144
228
  """
145
229
  with self.provide_connection(*args, **kwargs) as connection:
146
- statement_config = self.statement_config
147
- # Inject parameter style info if not already set
148
- if statement_config.allowed_parameter_styles is None:
149
- from dataclasses import replace
150
-
151
- statement_config = replace(
152
- statement_config,
153
- allowed_parameter_styles=self.supported_parameter_styles,
154
- default_parameter_style=self.default_parameter_style,
155
- )
156
- yield self.driver_type(connection=connection, config=statement_config)
230
+ yield self.driver_type(connection=connection, statement_config=statement_config or self.statement_config)
231
+
232
+ def get_signature_namespace(self) -> "dict[str, type[Any]]":
233
+ """Get the signature namespace for SQLite types.
234
+
235
+ Returns:
236
+ Dictionary mapping type names to types.
237
+ """
238
+ namespace = super().get_signature_namespace()
239
+ namespace.update({"SqliteConnection": SqliteConnection, "SqliteCursor": SqliteCursor})
240
+ return namespace