sqlspec 0.8.0__py3-none-any.whl → 0.9.1__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/_typing.py +39 -6
- sqlspec/adapters/adbc/__init__.py +2 -2
- sqlspec/adapters/adbc/config.py +34 -11
- sqlspec/adapters/adbc/driver.py +302 -111
- sqlspec/adapters/aiosqlite/__init__.py +2 -2
- sqlspec/adapters/aiosqlite/config.py +2 -2
- sqlspec/adapters/aiosqlite/driver.py +164 -42
- sqlspec/adapters/asyncmy/__init__.py +3 -3
- sqlspec/adapters/asyncmy/config.py +11 -12
- sqlspec/adapters/asyncmy/driver.py +161 -37
- sqlspec/adapters/asyncpg/__init__.py +5 -5
- sqlspec/adapters/asyncpg/config.py +17 -19
- sqlspec/adapters/asyncpg/driver.py +386 -96
- sqlspec/adapters/duckdb/__init__.py +2 -2
- sqlspec/adapters/duckdb/config.py +2 -2
- sqlspec/adapters/duckdb/driver.py +190 -60
- sqlspec/adapters/oracledb/__init__.py +8 -8
- sqlspec/adapters/oracledb/config/__init__.py +6 -6
- sqlspec/adapters/oracledb/config/_asyncio.py +9 -10
- sqlspec/adapters/oracledb/config/_sync.py +8 -9
- sqlspec/adapters/oracledb/driver.py +384 -45
- sqlspec/adapters/psqlpy/__init__.py +0 -0
- sqlspec/adapters/psqlpy/config.py +250 -0
- sqlspec/adapters/psqlpy/driver.py +481 -0
- sqlspec/adapters/psycopg/__init__.py +10 -5
- sqlspec/adapters/psycopg/config/__init__.py +6 -6
- sqlspec/adapters/psycopg/config/_async.py +12 -12
- sqlspec/adapters/psycopg/config/_sync.py +13 -13
- sqlspec/adapters/psycopg/driver.py +432 -222
- sqlspec/adapters/sqlite/__init__.py +2 -2
- sqlspec/adapters/sqlite/config.py +2 -2
- sqlspec/adapters/sqlite/driver.py +176 -72
- sqlspec/base.py +687 -161
- sqlspec/exceptions.py +30 -0
- sqlspec/extensions/litestar/config.py +6 -0
- sqlspec/extensions/litestar/handlers.py +25 -0
- sqlspec/extensions/litestar/plugin.py +8 -1
- sqlspec/statement.py +373 -0
- sqlspec/typing.py +10 -1
- {sqlspec-0.8.0.dist-info → sqlspec-0.9.1.dist-info}/METADATA +144 -2
- sqlspec-0.9.1.dist-info/RECORD +61 -0
- sqlspec-0.8.0.dist-info/RECORD +0 -57
- {sqlspec-0.8.0.dist-info → sqlspec-0.9.1.dist-info}/WHEEL +0 -0
- {sqlspec-0.8.0.dist-info → sqlspec-0.9.1.dist-info}/licenses/LICENSE +0 -0
- {sqlspec-0.8.0.dist-info → sqlspec-0.9.1.dist-info}/licenses/NOTICE +0 -0
|
@@ -14,7 +14,7 @@ if TYPE_CHECKING:
|
|
|
14
14
|
from collections.abc import Generator, Sequence
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
__all__ = ("
|
|
17
|
+
__all__ = ("DuckDBConfig", "ExtensionConfig")
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class ExtensionConfig(TypedDict):
|
|
@@ -69,7 +69,7 @@ class SecretConfig(TypedDict):
|
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
@dataclass
|
|
72
|
-
class
|
|
72
|
+
class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
73
73
|
"""Configuration for DuckDB database connections.
|
|
74
74
|
|
|
75
75
|
This class provides configuration options for DuckDB database connections, wrapping all parameters
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
from contextlib import contextmanager
|
|
2
|
-
from typing import TYPE_CHECKING, Any, Optional, Union, cast
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload
|
|
3
3
|
|
|
4
|
-
from sqlspec.base import SyncDriverAdapterProtocol, T
|
|
4
|
+
from sqlspec.base import SyncArrowBulkOperationsMixin, SyncDriverAdapterProtocol, T
|
|
5
5
|
|
|
6
6
|
if TYPE_CHECKING:
|
|
7
|
-
from collections.abc import Generator
|
|
7
|
+
from collections.abc import Generator, Sequence
|
|
8
8
|
|
|
9
9
|
from duckdb import DuckDBPyConnection
|
|
10
10
|
|
|
11
|
-
from sqlspec.typing import ModelDTOT, StatementParameterType
|
|
11
|
+
from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType
|
|
12
12
|
|
|
13
13
|
__all__ = ("DuckDBDriver",)
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
class DuckDBDriver(SyncDriverAdapterProtocol["DuckDBPyConnection"]):
|
|
16
|
+
class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDriverAdapterProtocol["DuckDBPyConnection"]):
|
|
17
17
|
"""DuckDB Sync Driver Adapter."""
|
|
18
18
|
|
|
19
19
|
connection: "DuckDBPyConnection"
|
|
20
20
|
use_cursor: bool = True
|
|
21
|
-
|
|
21
|
+
dialect: str = "duckdb"
|
|
22
22
|
|
|
23
23
|
def __init__(self, connection: "DuckDBPyConnection", use_cursor: bool = True) -> None:
|
|
24
24
|
self.connection = connection
|
|
@@ -27,7 +27,6 @@ class DuckDBDriver(SyncDriverAdapterProtocol["DuckDBPyConnection"]):
|
|
|
27
27
|
# --- Helper Methods --- #
|
|
28
28
|
def _cursor(self, connection: "DuckDBPyConnection") -> "DuckDBPyConnection":
|
|
29
29
|
if self.use_cursor:
|
|
30
|
-
# Ignore lack of type hint on cursor()
|
|
31
30
|
return connection.cursor()
|
|
32
31
|
return connection
|
|
33
32
|
|
|
@@ -40,20 +39,43 @@ class DuckDBDriver(SyncDriverAdapterProtocol["DuckDBPyConnection"]):
|
|
|
40
39
|
finally:
|
|
41
40
|
cursor.close()
|
|
42
41
|
else:
|
|
43
|
-
yield connection
|
|
44
|
-
|
|
45
|
-
# --- Public API Methods (Original Implementation + _process_sql_params) --- #
|
|
42
|
+
yield connection
|
|
46
43
|
|
|
44
|
+
# --- Public API Methods --- #
|
|
45
|
+
@overload
|
|
47
46
|
def select(
|
|
48
47
|
self,
|
|
49
48
|
sql: str,
|
|
50
|
-
parameters: Optional[
|
|
49
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
51
50
|
/,
|
|
52
|
-
|
|
51
|
+
*,
|
|
52
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
53
|
+
schema_type: None = None,
|
|
54
|
+
**kwargs: Any,
|
|
55
|
+
) -> "Sequence[dict[str, Any]]": ...
|
|
56
|
+
@overload
|
|
57
|
+
def select(
|
|
58
|
+
self,
|
|
59
|
+
sql: str,
|
|
60
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
61
|
+
/,
|
|
62
|
+
*,
|
|
63
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
64
|
+
schema_type: "type[ModelDTOT]",
|
|
65
|
+
**kwargs: Any,
|
|
66
|
+
) -> "Sequence[ModelDTOT]": ...
|
|
67
|
+
def select(
|
|
68
|
+
self,
|
|
69
|
+
sql: str,
|
|
70
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
71
|
+
/,
|
|
72
|
+
*,
|
|
73
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
53
74
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
54
|
-
|
|
75
|
+
**kwargs: Any,
|
|
76
|
+
) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]":
|
|
55
77
|
connection = self._connection(connection)
|
|
56
|
-
sql, parameters = self._process_sql_params(sql, parameters)
|
|
78
|
+
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
57
79
|
with self._with_cursor(connection) as cursor:
|
|
58
80
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
59
81
|
results = cursor.fetchall() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
|
|
@@ -66,21 +88,44 @@ class DuckDBDriver(SyncDriverAdapterProtocol["DuckDBPyConnection"]):
|
|
|
66
88
|
return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] # pyright: ignore[reportUnknownArgumentType]
|
|
67
89
|
return [dict(zip(column_names, row)) for row in results] # pyright: ignore[reportUnknownArgumentType]
|
|
68
90
|
|
|
91
|
+
@overload
|
|
92
|
+
def select_one(
|
|
93
|
+
self,
|
|
94
|
+
sql: str,
|
|
95
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
96
|
+
/,
|
|
97
|
+
*,
|
|
98
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
99
|
+
schema_type: None = None,
|
|
100
|
+
**kwargs: Any,
|
|
101
|
+
) -> "dict[str, Any]": ...
|
|
102
|
+
@overload
|
|
103
|
+
def select_one(
|
|
104
|
+
self,
|
|
105
|
+
sql: str,
|
|
106
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
107
|
+
/,
|
|
108
|
+
*,
|
|
109
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
110
|
+
schema_type: "type[ModelDTOT]",
|
|
111
|
+
**kwargs: Any,
|
|
112
|
+
) -> "ModelDTOT": ...
|
|
69
113
|
def select_one(
|
|
70
114
|
self,
|
|
71
115
|
sql: str,
|
|
72
116
|
parameters: Optional["StatementParameterType"] = None,
|
|
73
117
|
/,
|
|
118
|
+
*,
|
|
74
119
|
connection: Optional["DuckDBPyConnection"] = None,
|
|
75
120
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
121
|
+
**kwargs: Any,
|
|
76
122
|
) -> "Union[ModelDTOT, dict[str, Any]]":
|
|
77
123
|
connection = self._connection(connection)
|
|
78
|
-
sql, parameters = self._process_sql_params(sql, parameters)
|
|
79
|
-
|
|
124
|
+
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
80
125
|
with self._with_cursor(connection) as cursor:
|
|
81
126
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
82
127
|
result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
|
|
83
|
-
result = self.check_not_found(result) #
|
|
128
|
+
result = self.check_not_found(result) # pyright: ignore
|
|
84
129
|
|
|
85
130
|
column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
|
|
86
131
|
if schema_type is not None:
|
|
@@ -88,17 +133,40 @@ class DuckDBDriver(SyncDriverAdapterProtocol["DuckDBPyConnection"]):
|
|
|
88
133
|
# Always return dictionaries
|
|
89
134
|
return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
|
|
90
135
|
|
|
136
|
+
@overload
|
|
137
|
+
def select_one_or_none(
|
|
138
|
+
self,
|
|
139
|
+
sql: str,
|
|
140
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
141
|
+
/,
|
|
142
|
+
*,
|
|
143
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
144
|
+
schema_type: None = None,
|
|
145
|
+
**kwargs: Any,
|
|
146
|
+
) -> "Optional[dict[str, Any]]": ...
|
|
147
|
+
@overload
|
|
148
|
+
def select_one_or_none(
|
|
149
|
+
self,
|
|
150
|
+
sql: str,
|
|
151
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
152
|
+
/,
|
|
153
|
+
*,
|
|
154
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
155
|
+
schema_type: "type[ModelDTOT]",
|
|
156
|
+
**kwargs: Any,
|
|
157
|
+
) -> "Optional[ModelDTOT]": ...
|
|
91
158
|
def select_one_or_none(
|
|
92
159
|
self,
|
|
93
160
|
sql: str,
|
|
94
161
|
parameters: Optional["StatementParameterType"] = None,
|
|
95
162
|
/,
|
|
163
|
+
*,
|
|
96
164
|
connection: Optional["DuckDBPyConnection"] = None,
|
|
97
165
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
166
|
+
**kwargs: Any,
|
|
98
167
|
) -> "Optional[Union[ModelDTOT, dict[str, Any]]]":
|
|
99
168
|
connection = self._connection(connection)
|
|
100
|
-
sql, parameters = self._process_sql_params(sql, parameters)
|
|
101
|
-
|
|
169
|
+
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
102
170
|
with self._with_cursor(connection) as cursor:
|
|
103
171
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
104
172
|
result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
|
|
@@ -110,35 +178,82 @@ class DuckDBDriver(SyncDriverAdapterProtocol["DuckDBPyConnection"]):
|
|
|
110
178
|
return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType]
|
|
111
179
|
return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
|
|
112
180
|
|
|
181
|
+
@overload
|
|
182
|
+
def select_value(
|
|
183
|
+
self,
|
|
184
|
+
sql: str,
|
|
185
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
186
|
+
/,
|
|
187
|
+
*,
|
|
188
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
189
|
+
schema_type: None = None,
|
|
190
|
+
**kwargs: Any,
|
|
191
|
+
) -> "Any": ...
|
|
192
|
+
@overload
|
|
113
193
|
def select_value(
|
|
114
194
|
self,
|
|
115
195
|
sql: str,
|
|
116
196
|
parameters: "Optional[StatementParameterType]" = None,
|
|
117
197
|
/,
|
|
198
|
+
*,
|
|
199
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
200
|
+
schema_type: "type[T]",
|
|
201
|
+
**kwargs: Any,
|
|
202
|
+
) -> "T": ...
|
|
203
|
+
def select_value(
|
|
204
|
+
self,
|
|
205
|
+
sql: str,
|
|
206
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
207
|
+
/,
|
|
208
|
+
*,
|
|
118
209
|
connection: "Optional[DuckDBPyConnection]" = None,
|
|
119
210
|
schema_type: "Optional[type[T]]" = None,
|
|
211
|
+
**kwargs: Any,
|
|
120
212
|
) -> "Union[T, Any]":
|
|
121
213
|
connection = self._connection(connection)
|
|
122
|
-
sql, parameters = self._process_sql_params(sql, parameters)
|
|
123
|
-
|
|
214
|
+
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
124
215
|
with self._with_cursor(connection) as cursor:
|
|
125
216
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
126
217
|
result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
|
|
127
|
-
result = self.check_not_found(result) #
|
|
218
|
+
result = self.check_not_found(result) # pyright: ignore
|
|
128
219
|
if schema_type is None:
|
|
129
220
|
return result[0] # pyright: ignore
|
|
130
221
|
return schema_type(result[0]) # type: ignore[call-arg]
|
|
131
222
|
|
|
223
|
+
@overload
|
|
132
224
|
def select_value_or_none(
|
|
133
225
|
self,
|
|
134
226
|
sql: str,
|
|
135
227
|
parameters: "Optional[StatementParameterType]" = None,
|
|
136
228
|
/,
|
|
229
|
+
*,
|
|
230
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
231
|
+
schema_type: None = None,
|
|
232
|
+
**kwargs: Any,
|
|
233
|
+
) -> "Optional[Any]": ...
|
|
234
|
+
@overload
|
|
235
|
+
def select_value_or_none(
|
|
236
|
+
self,
|
|
237
|
+
sql: str,
|
|
238
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
239
|
+
/,
|
|
240
|
+
*,
|
|
241
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
242
|
+
schema_type: "type[T]",
|
|
243
|
+
**kwargs: Any,
|
|
244
|
+
) -> "Optional[T]": ...
|
|
245
|
+
def select_value_or_none(
|
|
246
|
+
self,
|
|
247
|
+
sql: str,
|
|
248
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
249
|
+
/,
|
|
250
|
+
*,
|
|
137
251
|
connection: "Optional[DuckDBPyConnection]" = None,
|
|
138
252
|
schema_type: "Optional[type[T]]" = None,
|
|
253
|
+
**kwargs: Any,
|
|
139
254
|
) -> "Optional[Union[T, Any]]":
|
|
140
255
|
connection = self._connection(connection)
|
|
141
|
-
sql, parameters = self._process_sql_params(sql, parameters)
|
|
256
|
+
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
142
257
|
with self._with_cursor(connection) as cursor:
|
|
143
258
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
144
259
|
result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
|
|
@@ -153,73 +268,88 @@ class DuckDBDriver(SyncDriverAdapterProtocol["DuckDBPyConnection"]):
|
|
|
153
268
|
sql: str,
|
|
154
269
|
parameters: Optional["StatementParameterType"] = None,
|
|
155
270
|
/,
|
|
271
|
+
*,
|
|
156
272
|
connection: Optional["DuckDBPyConnection"] = None,
|
|
273
|
+
**kwargs: Any,
|
|
157
274
|
) -> int:
|
|
158
275
|
connection = self._connection(connection)
|
|
159
|
-
sql, parameters = self._process_sql_params(sql, parameters)
|
|
276
|
+
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
160
277
|
with self._with_cursor(connection) as cursor:
|
|
161
278
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
162
279
|
return getattr(cursor, "rowcount", -1) # pyright: ignore[reportUnknownMemberType]
|
|
163
280
|
|
|
281
|
+
@overload
|
|
164
282
|
def insert_update_delete_returning(
|
|
165
283
|
self,
|
|
166
284
|
sql: str,
|
|
167
|
-
parameters: Optional[
|
|
285
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
168
286
|
/,
|
|
169
|
-
|
|
287
|
+
*,
|
|
288
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
289
|
+
schema_type: None = None,
|
|
290
|
+
**kwargs: Any,
|
|
291
|
+
) -> "dict[str, Any]": ...
|
|
292
|
+
@overload
|
|
293
|
+
def insert_update_delete_returning(
|
|
294
|
+
self,
|
|
295
|
+
sql: str,
|
|
296
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
297
|
+
/,
|
|
298
|
+
*,
|
|
299
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
300
|
+
schema_type: "type[ModelDTOT]",
|
|
301
|
+
**kwargs: Any,
|
|
302
|
+
) -> "ModelDTOT": ...
|
|
303
|
+
def insert_update_delete_returning(
|
|
304
|
+
self,
|
|
305
|
+
sql: str,
|
|
306
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
307
|
+
/,
|
|
308
|
+
*,
|
|
309
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
170
310
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
171
|
-
|
|
311
|
+
**kwargs: Any,
|
|
312
|
+
) -> "Union[ModelDTOT, dict[str, Any]]":
|
|
172
313
|
connection = self._connection(connection)
|
|
173
|
-
sql, parameters = self._process_sql_params(sql, parameters)
|
|
314
|
+
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
174
315
|
with self._with_cursor(connection) as cursor:
|
|
175
316
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
176
317
|
result = cursor.fetchall() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
|
|
177
|
-
|
|
178
|
-
return None # pyright: ignore[reportUnknownArgumentType]
|
|
318
|
+
result = self.check_not_found(result) # pyright: ignore
|
|
179
319
|
column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
|
|
180
320
|
if schema_type is not None:
|
|
181
321
|
return cast("ModelDTOT", schema_type(**dict(zip(column_names, result[0])))) # pyright: ignore[reportUnknownArgumentType]
|
|
182
322
|
# Always return dictionaries
|
|
183
323
|
return dict(zip(column_names, result[0])) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
|
|
184
324
|
|
|
185
|
-
def _process_sql_params(
|
|
186
|
-
self, sql: str, parameters: "Optional[StatementParameterType]" = None
|
|
187
|
-
) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]":
|
|
188
|
-
"""Process SQL query and parameters for DB-API execution.
|
|
189
|
-
|
|
190
|
-
Converts named parameters (:name) to positional parameters (?) for DuckDB.
|
|
191
|
-
|
|
192
|
-
Args:
|
|
193
|
-
sql: The SQL query string.
|
|
194
|
-
parameters: The parameters for the query (dict, tuple, list, or None).
|
|
195
|
-
|
|
196
|
-
Returns:
|
|
197
|
-
A tuple containing the processed SQL string and the processed parameters.
|
|
198
|
-
"""
|
|
199
|
-
if not isinstance(parameters, dict) or not parameters:
|
|
200
|
-
# If parameters are not a dict, or empty dict, assume positional/no params
|
|
201
|
-
# Let the underlying driver handle tuples/lists directly
|
|
202
|
-
return sql, parameters
|
|
203
|
-
|
|
204
|
-
# Convert named parameters to positional parameters
|
|
205
|
-
processed_sql = sql
|
|
206
|
-
processed_params: list[Any] = []
|
|
207
|
-
for key, value in parameters.items():
|
|
208
|
-
# Replace :key with ? in the SQL
|
|
209
|
-
processed_sql = processed_sql.replace(f":{key}", "?")
|
|
210
|
-
processed_params.append(value)
|
|
211
|
-
|
|
212
|
-
return processed_sql, tuple(processed_params)
|
|
213
|
-
|
|
214
325
|
def execute_script(
|
|
215
326
|
self,
|
|
216
327
|
sql: str,
|
|
217
328
|
parameters: Optional["StatementParameterType"] = None,
|
|
218
329
|
/,
|
|
330
|
+
*,
|
|
219
331
|
connection: Optional["DuckDBPyConnection"] = None,
|
|
332
|
+
**kwargs: Any,
|
|
220
333
|
) -> str:
|
|
221
334
|
connection = self._connection(connection)
|
|
222
|
-
sql, parameters = self._process_sql_params(sql, parameters)
|
|
335
|
+
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
223
336
|
with self._with_cursor(connection) as cursor:
|
|
224
337
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
225
338
|
return cast("str", getattr(cursor, "statusmessage", "DONE")) # pyright: ignore[reportUnknownMemberType]
|
|
339
|
+
|
|
340
|
+
# --- Arrow Bulk Operations ---
|
|
341
|
+
|
|
342
|
+
def select_arrow( # pyright: ignore[reportUnknownParameterType]
|
|
343
|
+
self,
|
|
344
|
+
sql: str,
|
|
345
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
346
|
+
/,
|
|
347
|
+
*,
|
|
348
|
+
connection: "Optional[DuckDBPyConnection]" = None,
|
|
349
|
+
**kwargs: Any,
|
|
350
|
+
) -> "ArrowTable":
|
|
351
|
+
connection = self._connection(connection)
|
|
352
|
+
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
353
|
+
with self._with_cursor(connection) as cursor:
|
|
354
|
+
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
355
|
+
return cast("ArrowTable", cursor.fetch_arrow_table()) # pyright: ignore[reportUnknownMemberType]
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
from sqlspec.adapters.oracledb.config import (
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
OracleAsyncConfig,
|
|
3
|
+
OracleAsyncPoolConfig,
|
|
4
|
+
OracleSyncConfig,
|
|
5
|
+
OracleSyncPoolConfig,
|
|
6
6
|
)
|
|
7
7
|
from sqlspec.adapters.oracledb.driver import OracleAsyncDriver, OracleSyncDriver
|
|
8
8
|
|
|
9
9
|
__all__ = (
|
|
10
|
-
"
|
|
10
|
+
"OracleAsyncConfig",
|
|
11
11
|
"OracleAsyncDriver",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
12
|
+
"OracleAsyncPoolConfig",
|
|
13
|
+
"OracleSyncConfig",
|
|
14
14
|
"OracleSyncDriver",
|
|
15
|
-
"
|
|
15
|
+
"OracleSyncPoolConfig",
|
|
16
16
|
)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
from sqlspec.adapters.oracledb.config._asyncio import
|
|
2
|
-
from sqlspec.adapters.oracledb.config._sync import
|
|
1
|
+
from sqlspec.adapters.oracledb.config._asyncio import OracleAsyncConfig, OracleAsyncPoolConfig
|
|
2
|
+
from sqlspec.adapters.oracledb.config._sync import OracleSyncConfig, OracleSyncPoolConfig
|
|
3
3
|
|
|
4
4
|
__all__ = (
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
5
|
+
"OracleAsyncConfig",
|
|
6
|
+
"OracleAsyncPoolConfig",
|
|
7
|
+
"OracleSyncConfig",
|
|
8
|
+
"OracleSyncPoolConfig",
|
|
9
9
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from contextlib import asynccontextmanager
|
|
2
2
|
from dataclasses import dataclass, field
|
|
3
|
-
from typing import TYPE_CHECKING, Any, Optional
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Optional, cast
|
|
4
4
|
|
|
5
5
|
from oracledb import create_pool_async as oracledb_create_pool # pyright: ignore[reportUnknownVariableType]
|
|
6
6
|
from oracledb.connection import AsyncConnection
|
|
@@ -18,18 +18,18 @@ if TYPE_CHECKING:
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
__all__ = (
|
|
21
|
-
"
|
|
22
|
-
"
|
|
21
|
+
"OracleAsyncConfig",
|
|
22
|
+
"OracleAsyncPoolConfig",
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
@dataclass
|
|
27
|
-
class
|
|
27
|
+
class OracleAsyncPoolConfig(OracleGenericPoolConfig["AsyncConnection", "AsyncConnectionPool"]):
|
|
28
28
|
"""Async Oracle Pool Config"""
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
@dataclass
|
|
32
|
-
class
|
|
32
|
+
class OracleAsyncConfig(AsyncDatabaseConfig["AsyncConnection", "AsyncConnectionPool", "OracleAsyncDriver"]):
|
|
33
33
|
"""Oracle Async database Configuration.
|
|
34
34
|
|
|
35
35
|
This class provides the base configuration for Oracle database connections, extending
|
|
@@ -42,7 +42,7 @@ class OracleAsync(AsyncDatabaseConfig["AsyncConnection", "AsyncConnectionPool",
|
|
|
42
42
|
options.([2](https://python-oracledb.readthedocs.io/en/latest/user_guide/tuning.html))
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
|
-
pool_config: "Optional[
|
|
45
|
+
pool_config: "Optional[OracleAsyncPoolConfig]" = None
|
|
46
46
|
"""Oracle Pool configuration"""
|
|
47
47
|
pool_instance: "Optional[AsyncConnectionPool]" = None
|
|
48
48
|
"""Optional pool to use.
|
|
@@ -112,7 +112,7 @@ class OracleAsync(AsyncDatabaseConfig["AsyncConnection", "AsyncConnectionPool",
|
|
|
112
112
|
raise ImproperConfigurationError(msg)
|
|
113
113
|
|
|
114
114
|
async def create_connection(self) -> "AsyncConnection":
|
|
115
|
-
"""Create and return a new oracledb async connection.
|
|
115
|
+
"""Create and return a new oracledb async connection from the pool.
|
|
116
116
|
|
|
117
117
|
Returns:
|
|
118
118
|
An AsyncConnection instance.
|
|
@@ -121,9 +121,8 @@ class OracleAsync(AsyncDatabaseConfig["AsyncConnection", "AsyncConnectionPool",
|
|
|
121
121
|
ImproperConfigurationError: If the connection could not be created.
|
|
122
122
|
"""
|
|
123
123
|
try:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return await oracledb.connect_async(**self.connection_config_dict) # type: ignore[no-any-return]
|
|
124
|
+
pool = await self.provide_pool()
|
|
125
|
+
return cast("AsyncConnection", await pool.acquire()) # type: ignore[no-any-return,unused-ignore]
|
|
127
126
|
except Exception as e:
|
|
128
127
|
msg = f"Could not configure the Oracle async connection. Error: {e!s}"
|
|
129
128
|
raise ImproperConfigurationError(msg) from e
|
|
@@ -18,18 +18,18 @@ if TYPE_CHECKING:
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
__all__ = (
|
|
21
|
-
"
|
|
22
|
-
"
|
|
21
|
+
"OracleSyncConfig",
|
|
22
|
+
"OracleSyncPoolConfig",
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
@dataclass
|
|
27
|
-
class
|
|
27
|
+
class OracleSyncPoolConfig(OracleGenericPoolConfig["Connection", "ConnectionPool"]):
|
|
28
28
|
"""Sync Oracle Pool Config"""
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
@dataclass
|
|
32
|
-
class
|
|
32
|
+
class OracleSyncConfig(SyncDatabaseConfig["Connection", "ConnectionPool", "OracleSyncDriver"]):
|
|
33
33
|
"""Oracle Sync database Configuration.
|
|
34
34
|
|
|
35
35
|
This class provides the base configuration for Oracle database connections, extending
|
|
@@ -42,7 +42,7 @@ class OracleSync(SyncDatabaseConfig["Connection", "ConnectionPool", "OracleSyncD
|
|
|
42
42
|
options.([2](https://python-oracledb.readthedocs.io/en/latest/user_guide/tuning.html))
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
|
-
pool_config: "Optional[
|
|
45
|
+
pool_config: "Optional[OracleSyncPoolConfig]" = None
|
|
46
46
|
"""Oracle Pool configuration"""
|
|
47
47
|
pool_instance: "Optional[ConnectionPool]" = None
|
|
48
48
|
"""Optional pool to use.
|
|
@@ -112,7 +112,7 @@ class OracleSync(SyncDatabaseConfig["Connection", "ConnectionPool", "OracleSyncD
|
|
|
112
112
|
raise ImproperConfigurationError(msg)
|
|
113
113
|
|
|
114
114
|
def create_connection(self) -> "Connection":
|
|
115
|
-
"""Create and return a new oracledb connection.
|
|
115
|
+
"""Create and return a new oracledb connection from the pool.
|
|
116
116
|
|
|
117
117
|
Returns:
|
|
118
118
|
A Connection instance.
|
|
@@ -121,9 +121,8 @@ class OracleSync(SyncDatabaseConfig["Connection", "ConnectionPool", "OracleSyncD
|
|
|
121
121
|
ImproperConfigurationError: If the connection could not be created.
|
|
122
122
|
"""
|
|
123
123
|
try:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return oracledb.connect(**self.connection_config_dict)
|
|
124
|
+
pool = self.provide_pool()
|
|
125
|
+
return pool.acquire()
|
|
127
126
|
except Exception as e:
|
|
128
127
|
msg = f"Could not configure the Oracle connection. Error: {e!s}"
|
|
129
128
|
raise ImproperConfigurationError(msg) from e
|