sqlspec 0.10.1__py3-none-any.whl → 0.11.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/adapters/adbc/config.py +1 -1
- sqlspec/adapters/adbc/driver.py +336 -165
- sqlspec/adapters/aiosqlite/driver.py +211 -126
- sqlspec/adapters/asyncmy/driver.py +164 -68
- sqlspec/adapters/asyncpg/config.py +3 -1
- sqlspec/adapters/asyncpg/driver.py +190 -231
- sqlspec/adapters/bigquery/driver.py +178 -169
- sqlspec/adapters/duckdb/driver.py +175 -84
- sqlspec/adapters/oracledb/driver.py +224 -90
- sqlspec/adapters/psqlpy/driver.py +267 -187
- sqlspec/adapters/psycopg/driver.py +138 -184
- sqlspec/adapters/sqlite/driver.py +153 -121
- sqlspec/base.py +57 -45
- sqlspec/extensions/litestar/__init__.py +3 -12
- sqlspec/extensions/litestar/config.py +22 -7
- sqlspec/extensions/litestar/handlers.py +142 -85
- sqlspec/extensions/litestar/plugin.py +9 -8
- sqlspec/extensions/litestar/providers.py +521 -0
- sqlspec/filters.py +214 -11
- sqlspec/mixins.py +152 -2
- sqlspec/statement.py +276 -271
- sqlspec/typing.py +18 -1
- sqlspec/utils/__init__.py +2 -2
- sqlspec/utils/singleton.py +35 -0
- sqlspec/utils/sync_tools.py +90 -151
- sqlspec/utils/text.py +68 -5
- {sqlspec-0.10.1.dist-info → sqlspec-0.11.0.dist-info}/METADATA +5 -1
- {sqlspec-0.10.1.dist-info → sqlspec-0.11.0.dist-info}/RECORD +31 -29
- {sqlspec-0.10.1.dist-info → sqlspec-0.11.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.10.1.dist-info → sqlspec-0.11.0.dist-info}/licenses/LICENSE +0 -0
- {sqlspec-0.10.1.dist-info → sqlspec-0.11.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,23 +1,31 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from contextlib import asynccontextmanager
|
|
2
|
-
from typing import TYPE_CHECKING, Any, Optional, Union,
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Optional, Union, overload
|
|
3
4
|
|
|
4
5
|
import aiosqlite
|
|
6
|
+
from sqlglot import exp
|
|
5
7
|
|
|
6
8
|
from sqlspec.base import AsyncDriverAdapterProtocol
|
|
7
|
-
from sqlspec.mixins import SQLTranslatorMixin
|
|
9
|
+
from sqlspec.mixins import ResultConverter, SQLTranslatorMixin
|
|
10
|
+
from sqlspec.statement import SQLStatement
|
|
11
|
+
from sqlspec.typing import is_dict
|
|
8
12
|
|
|
9
13
|
if TYPE_CHECKING:
|
|
10
14
|
from collections.abc import AsyncGenerator, Sequence
|
|
11
15
|
|
|
16
|
+
from sqlspec.filters import StatementFilter
|
|
12
17
|
from sqlspec.typing import ModelDTOT, StatementParameterType, T
|
|
13
18
|
|
|
14
19
|
__all__ = ("AiosqliteConnection", "AiosqliteDriver")
|
|
15
20
|
AiosqliteConnection = aiosqlite.Connection
|
|
16
21
|
|
|
22
|
+
logger = logging.getLogger("sqlspec")
|
|
23
|
+
|
|
17
24
|
|
|
18
25
|
class AiosqliteDriver(
|
|
19
26
|
SQLTranslatorMixin["AiosqliteConnection"],
|
|
20
27
|
AsyncDriverAdapterProtocol["AiosqliteConnection"],
|
|
28
|
+
ResultConverter,
|
|
21
29
|
):
|
|
22
30
|
"""SQLite Async Driver Adapter."""
|
|
23
31
|
|
|
@@ -39,6 +47,74 @@ class AiosqliteDriver(
|
|
|
39
47
|
finally:
|
|
40
48
|
await cursor.close()
|
|
41
49
|
|
|
50
|
+
def _process_sql_params(
|
|
51
|
+
self,
|
|
52
|
+
sql: str,
|
|
53
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
54
|
+
/,
|
|
55
|
+
*filters: "StatementFilter",
|
|
56
|
+
**kwargs: Any,
|
|
57
|
+
) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]]]":
|
|
58
|
+
"""Process SQL and parameters for aiosqlite using SQLStatement.
|
|
59
|
+
|
|
60
|
+
aiosqlite supports both named (:name) and positional (?) parameters.
|
|
61
|
+
This method processes the SQL with dialect-aware parsing and handles
|
|
62
|
+
parameters appropriately for aiosqlite.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
sql: SQL statement.
|
|
66
|
+
parameters: Query parameters.
|
|
67
|
+
*filters: Statement filters to apply.
|
|
68
|
+
**kwargs: Additional keyword arguments.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Tuple of processed SQL and parameters.
|
|
72
|
+
"""
|
|
73
|
+
statement = SQLStatement(sql, parameters, kwargs=kwargs, dialect=self.dialect)
|
|
74
|
+
|
|
75
|
+
# Apply any filters
|
|
76
|
+
for filter_obj in filters:
|
|
77
|
+
statement = statement.apply_filter(filter_obj)
|
|
78
|
+
|
|
79
|
+
processed_sql, processed_params, parsed_expr = statement.process()
|
|
80
|
+
if processed_params is None:
|
|
81
|
+
return processed_sql, None
|
|
82
|
+
|
|
83
|
+
if is_dict(processed_params):
|
|
84
|
+
# For dict parameters, we need to use ordered ? placeholders
|
|
85
|
+
# but only if we have a parsed expression to work with
|
|
86
|
+
if parsed_expr:
|
|
87
|
+
# Collect named parameters in the order they appear in the SQL
|
|
88
|
+
named_params = []
|
|
89
|
+
for node in parsed_expr.find_all(exp.Parameter, exp.Placeholder):
|
|
90
|
+
if isinstance(node, exp.Parameter) and node.name and node.name in processed_params:
|
|
91
|
+
named_params.append(node.name)
|
|
92
|
+
elif (
|
|
93
|
+
isinstance(node, exp.Placeholder)
|
|
94
|
+
and isinstance(node.this, str)
|
|
95
|
+
and node.this in processed_params
|
|
96
|
+
):
|
|
97
|
+
named_params.append(node.this)
|
|
98
|
+
|
|
99
|
+
if named_params:
|
|
100
|
+
# Transform SQL to use ? placeholders
|
|
101
|
+
def _convert_to_qmark(node: exp.Expression) -> exp.Expression:
|
|
102
|
+
if (isinstance(node, exp.Parameter) and node.name and node.name in processed_params) or (
|
|
103
|
+
isinstance(node, exp.Placeholder)
|
|
104
|
+
and isinstance(node.this, str)
|
|
105
|
+
and node.this in processed_params
|
|
106
|
+
):
|
|
107
|
+
return exp.Placeholder() # ? placeholder
|
|
108
|
+
return node
|
|
109
|
+
|
|
110
|
+
return parsed_expr.transform(_convert_to_qmark, copy=True).sql(dialect=self.dialect), tuple(
|
|
111
|
+
processed_params[name] for name in named_params
|
|
112
|
+
)
|
|
113
|
+
return processed_sql, processed_params
|
|
114
|
+
if isinstance(processed_params, (list, tuple)):
|
|
115
|
+
return processed_sql, tuple(processed_params)
|
|
116
|
+
return processed_sql, (processed_params,)
|
|
117
|
+
|
|
42
118
|
# --- Public API Methods --- #
|
|
43
119
|
@overload
|
|
44
120
|
async def select(
|
|
@@ -46,7 +122,7 @@ class AiosqliteDriver(
|
|
|
46
122
|
sql: str,
|
|
47
123
|
parameters: "Optional[StatementParameterType]" = None,
|
|
48
124
|
/,
|
|
49
|
-
|
|
125
|
+
*filters: "StatementFilter",
|
|
50
126
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
51
127
|
schema_type: None = None,
|
|
52
128
|
**kwargs: Any,
|
|
@@ -57,7 +133,7 @@ class AiosqliteDriver(
|
|
|
57
133
|
sql: str,
|
|
58
134
|
parameters: "Optional[StatementParameterType]" = None,
|
|
59
135
|
/,
|
|
60
|
-
|
|
136
|
+
*filters: "StatementFilter",
|
|
61
137
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
62
138
|
schema_type: "type[ModelDTOT]",
|
|
63
139
|
**kwargs: Any,
|
|
@@ -65,29 +141,33 @@ class AiosqliteDriver(
|
|
|
65
141
|
async def select(
|
|
66
142
|
self,
|
|
67
143
|
sql: str,
|
|
68
|
-
parameters: Optional[
|
|
144
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
69
145
|
/,
|
|
70
|
-
|
|
71
|
-
connection: Optional[
|
|
146
|
+
*filters: "StatementFilter",
|
|
147
|
+
connection: "Optional[AiosqliteConnection]" = None,
|
|
72
148
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
73
149
|
**kwargs: Any,
|
|
74
|
-
) -> "Sequence[Union[
|
|
150
|
+
) -> "Sequence[Union[dict[str, Any], ModelDTOT]]":
|
|
75
151
|
"""Fetch data from the database.
|
|
76
152
|
|
|
77
153
|
Returns:
|
|
78
154
|
List of row data as either model instances or dictionaries.
|
|
79
155
|
"""
|
|
80
156
|
connection = self._connection(connection)
|
|
81
|
-
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
157
|
+
sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs)
|
|
158
|
+
|
|
159
|
+
# Execute the query
|
|
160
|
+
cursor = await connection.execute(sql, parameters or ())
|
|
161
|
+
results = await cursor.fetchall()
|
|
162
|
+
if not results:
|
|
163
|
+
return []
|
|
164
|
+
|
|
165
|
+
# Get column names
|
|
166
|
+
column_names = [column[0] for column in cursor.description]
|
|
167
|
+
|
|
168
|
+
# Convert to dicts first
|
|
169
|
+
dict_results = [dict(zip(column_names, row)) for row in results]
|
|
170
|
+
return self.to_schema(dict_results, schema_type=schema_type)
|
|
91
171
|
|
|
92
172
|
@overload
|
|
93
173
|
async def select_one(
|
|
@@ -95,7 +175,7 @@ class AiosqliteDriver(
|
|
|
95
175
|
sql: str,
|
|
96
176
|
parameters: "Optional[StatementParameterType]" = None,
|
|
97
177
|
/,
|
|
98
|
-
|
|
178
|
+
*filters: "StatementFilter",
|
|
99
179
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
100
180
|
schema_type: None = None,
|
|
101
181
|
**kwargs: Any,
|
|
@@ -106,7 +186,7 @@ class AiosqliteDriver(
|
|
|
106
186
|
sql: str,
|
|
107
187
|
parameters: "Optional[StatementParameterType]" = None,
|
|
108
188
|
/,
|
|
109
|
-
|
|
189
|
+
*filters: "StatementFilter",
|
|
110
190
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
111
191
|
schema_type: "type[ModelDTOT]",
|
|
112
192
|
**kwargs: Any,
|
|
@@ -114,28 +194,32 @@ class AiosqliteDriver(
|
|
|
114
194
|
async def select_one(
|
|
115
195
|
self,
|
|
116
196
|
sql: str,
|
|
117
|
-
parameters: Optional[
|
|
197
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
118
198
|
/,
|
|
119
|
-
|
|
120
|
-
connection: Optional[
|
|
199
|
+
*filters: "StatementFilter",
|
|
200
|
+
connection: "Optional[AiosqliteConnection]" = None,
|
|
121
201
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
122
202
|
**kwargs: Any,
|
|
123
|
-
) -> "Union[
|
|
203
|
+
) -> "Union[dict[str, Any], ModelDTOT]":
|
|
124
204
|
"""Fetch one row from the database.
|
|
125
205
|
|
|
126
206
|
Returns:
|
|
127
207
|
The first row of the query results.
|
|
128
208
|
"""
|
|
129
209
|
connection = self._connection(connection)
|
|
130
|
-
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
210
|
+
sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs)
|
|
211
|
+
|
|
212
|
+
# Execute the query
|
|
213
|
+
cursor = await connection.execute(sql, parameters or ())
|
|
214
|
+
result = await cursor.fetchone()
|
|
215
|
+
result = self.check_not_found(result)
|
|
216
|
+
|
|
217
|
+
# Get column names
|
|
218
|
+
column_names = [column[0] for column in cursor.description]
|
|
219
|
+
|
|
220
|
+
# Convert to dict and then use ResultConverter
|
|
221
|
+
dict_result = dict(zip(column_names, result))
|
|
222
|
+
return self.to_schema(dict_result, schema_type=schema_type)
|
|
139
223
|
|
|
140
224
|
@overload
|
|
141
225
|
async def select_one_or_none(
|
|
@@ -143,7 +227,7 @@ class AiosqliteDriver(
|
|
|
143
227
|
sql: str,
|
|
144
228
|
parameters: "Optional[StatementParameterType]" = None,
|
|
145
229
|
/,
|
|
146
|
-
|
|
230
|
+
*filters: "StatementFilter",
|
|
147
231
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
148
232
|
schema_type: None = None,
|
|
149
233
|
**kwargs: Any,
|
|
@@ -154,7 +238,7 @@ class AiosqliteDriver(
|
|
|
154
238
|
sql: str,
|
|
155
239
|
parameters: "Optional[StatementParameterType]" = None,
|
|
156
240
|
/,
|
|
157
|
-
|
|
241
|
+
*filters: "StatementFilter",
|
|
158
242
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
159
243
|
schema_type: "type[ModelDTOT]",
|
|
160
244
|
**kwargs: Any,
|
|
@@ -162,29 +246,33 @@ class AiosqliteDriver(
|
|
|
162
246
|
async def select_one_or_none(
|
|
163
247
|
self,
|
|
164
248
|
sql: str,
|
|
165
|
-
parameters: Optional[
|
|
249
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
166
250
|
/,
|
|
167
|
-
|
|
168
|
-
connection: Optional[
|
|
251
|
+
*filters: "StatementFilter",
|
|
252
|
+
connection: "Optional[AiosqliteConnection]" = None,
|
|
169
253
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
170
254
|
**kwargs: Any,
|
|
171
|
-
) -> "Optional[Union[
|
|
255
|
+
) -> "Optional[Union[dict[str, Any], ModelDTOT]]":
|
|
172
256
|
"""Fetch one row from the database.
|
|
173
257
|
|
|
174
258
|
Returns:
|
|
175
259
|
The first row of the query results.
|
|
176
260
|
"""
|
|
177
261
|
connection = self._connection(connection)
|
|
178
|
-
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
262
|
+
sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs)
|
|
263
|
+
|
|
264
|
+
# Execute the query
|
|
265
|
+
cursor = await connection.execute(sql, parameters or ())
|
|
266
|
+
result = await cursor.fetchone()
|
|
267
|
+
if result is None:
|
|
268
|
+
return None
|
|
269
|
+
|
|
270
|
+
# Get column names
|
|
271
|
+
column_names = [column[0] for column in cursor.description]
|
|
272
|
+
|
|
273
|
+
# Convert to dict and then use ResultConverter
|
|
274
|
+
dict_result = dict(zip(column_names, result))
|
|
275
|
+
return self.to_schema(dict_result, schema_type=schema_type)
|
|
188
276
|
|
|
189
277
|
@overload
|
|
190
278
|
async def select_value(
|
|
@@ -192,7 +280,7 @@ class AiosqliteDriver(
|
|
|
192
280
|
sql: str,
|
|
193
281
|
parameters: "Optional[StatementParameterType]" = None,
|
|
194
282
|
/,
|
|
195
|
-
|
|
283
|
+
*filters: "StatementFilter",
|
|
196
284
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
197
285
|
schema_type: None = None,
|
|
198
286
|
**kwargs: Any,
|
|
@@ -203,7 +291,7 @@ class AiosqliteDriver(
|
|
|
203
291
|
sql: str,
|
|
204
292
|
parameters: "Optional[StatementParameterType]" = None,
|
|
205
293
|
/,
|
|
206
|
-
|
|
294
|
+
*filters: "StatementFilter",
|
|
207
295
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
208
296
|
schema_type: "type[T]",
|
|
209
297
|
**kwargs: Any,
|
|
@@ -213,7 +301,7 @@ class AiosqliteDriver(
|
|
|
213
301
|
sql: str,
|
|
214
302
|
parameters: "Optional[StatementParameterType]" = None,
|
|
215
303
|
/,
|
|
216
|
-
|
|
304
|
+
*filters: "StatementFilter",
|
|
217
305
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
218
306
|
schema_type: "Optional[type[T]]" = None,
|
|
219
307
|
**kwargs: Any,
|
|
@@ -221,17 +309,21 @@ class AiosqliteDriver(
|
|
|
221
309
|
"""Fetch a single value from the database.
|
|
222
310
|
|
|
223
311
|
Returns:
|
|
224
|
-
The first value from the first row of results
|
|
312
|
+
The first value from the first row of results.
|
|
225
313
|
"""
|
|
226
314
|
connection = self._connection(connection)
|
|
227
|
-
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
315
|
+
sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs)
|
|
316
|
+
|
|
317
|
+
# Execute the query
|
|
318
|
+
cursor = await connection.execute(sql, parameters or ())
|
|
319
|
+
result = await cursor.fetchone()
|
|
320
|
+
result = self.check_not_found(result)
|
|
321
|
+
|
|
322
|
+
# Return first value from the row
|
|
323
|
+
result_value = result[0]
|
|
324
|
+
if schema_type is None:
|
|
325
|
+
return result_value
|
|
326
|
+
return schema_type(result_value) # type: ignore[call-arg]
|
|
235
327
|
|
|
236
328
|
@overload
|
|
237
329
|
async def select_value_or_none(
|
|
@@ -239,7 +331,7 @@ class AiosqliteDriver(
|
|
|
239
331
|
sql: str,
|
|
240
332
|
parameters: "Optional[StatementParameterType]" = None,
|
|
241
333
|
/,
|
|
242
|
-
|
|
334
|
+
*filters: "StatementFilter",
|
|
243
335
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
244
336
|
schema_type: None = None,
|
|
245
337
|
**kwargs: Any,
|
|
@@ -250,7 +342,7 @@ class AiosqliteDriver(
|
|
|
250
342
|
sql: str,
|
|
251
343
|
parameters: "Optional[StatementParameterType]" = None,
|
|
252
344
|
/,
|
|
253
|
-
|
|
345
|
+
*filters: "StatementFilter",
|
|
254
346
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
255
347
|
schema_type: "type[T]",
|
|
256
348
|
**kwargs: Any,
|
|
@@ -260,7 +352,7 @@ class AiosqliteDriver(
|
|
|
260
352
|
sql: str,
|
|
261
353
|
parameters: "Optional[StatementParameterType]" = None,
|
|
262
354
|
/,
|
|
263
|
-
|
|
355
|
+
*filters: "StatementFilter",
|
|
264
356
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
265
357
|
schema_type: "Optional[type[T]]" = None,
|
|
266
358
|
**kwargs: Any,
|
|
@@ -271,23 +363,27 @@ class AiosqliteDriver(
|
|
|
271
363
|
The first value from the first row of results, or None if no results.
|
|
272
364
|
"""
|
|
273
365
|
connection = self._connection(connection)
|
|
274
|
-
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
366
|
+
sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs)
|
|
367
|
+
|
|
368
|
+
# Execute the query
|
|
369
|
+
cursor = await connection.execute(sql, parameters or ())
|
|
370
|
+
result = await cursor.fetchone()
|
|
371
|
+
if result is None:
|
|
372
|
+
return None
|
|
373
|
+
|
|
374
|
+
# Return first value from the row
|
|
375
|
+
result_value = result[0]
|
|
376
|
+
if schema_type is None:
|
|
377
|
+
return result_value
|
|
378
|
+
return schema_type(result_value) # type: ignore[call-arg]
|
|
283
379
|
|
|
284
380
|
async def insert_update_delete(
|
|
285
381
|
self,
|
|
286
382
|
sql: str,
|
|
287
|
-
parameters: Optional[
|
|
383
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
288
384
|
/,
|
|
289
|
-
|
|
290
|
-
connection: Optional[
|
|
385
|
+
*filters: "StatementFilter",
|
|
386
|
+
connection: "Optional[AiosqliteConnection]" = None,
|
|
291
387
|
**kwargs: Any,
|
|
292
388
|
) -> int:
|
|
293
389
|
"""Insert, update, or delete data from the database.
|
|
@@ -296,11 +392,12 @@ class AiosqliteDriver(
|
|
|
296
392
|
Row count affected by the operation.
|
|
297
393
|
"""
|
|
298
394
|
connection = self._connection(connection)
|
|
299
|
-
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
395
|
+
sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs)
|
|
300
396
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
397
|
+
# Execute the query
|
|
398
|
+
cursor = await connection.execute(sql, parameters or ())
|
|
399
|
+
await connection.commit()
|
|
400
|
+
return cursor.rowcount
|
|
304
401
|
|
|
305
402
|
@overload
|
|
306
403
|
async def insert_update_delete_returning(
|
|
@@ -308,7 +405,7 @@ class AiosqliteDriver(
|
|
|
308
405
|
sql: str,
|
|
309
406
|
parameters: "Optional[StatementParameterType]" = None,
|
|
310
407
|
/,
|
|
311
|
-
|
|
408
|
+
*filters: "StatementFilter",
|
|
312
409
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
313
410
|
schema_type: None = None,
|
|
314
411
|
**kwargs: Any,
|
|
@@ -319,7 +416,7 @@ class AiosqliteDriver(
|
|
|
319
416
|
sql: str,
|
|
320
417
|
parameters: "Optional[StatementParameterType]" = None,
|
|
321
418
|
/,
|
|
322
|
-
|
|
419
|
+
*filters: "StatementFilter",
|
|
323
420
|
connection: "Optional[AiosqliteConnection]" = None,
|
|
324
421
|
schema_type: "type[ModelDTOT]",
|
|
325
422
|
**kwargs: Any,
|
|
@@ -327,38 +424,42 @@ class AiosqliteDriver(
|
|
|
327
424
|
async def insert_update_delete_returning(
|
|
328
425
|
self,
|
|
329
426
|
sql: str,
|
|
330
|
-
parameters: Optional[
|
|
427
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
331
428
|
/,
|
|
332
|
-
|
|
333
|
-
connection: Optional[
|
|
429
|
+
*filters: "StatementFilter",
|
|
430
|
+
connection: "Optional[AiosqliteConnection]" = None,
|
|
334
431
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
335
432
|
**kwargs: Any,
|
|
336
|
-
) -> "
|
|
433
|
+
) -> "Union[dict[str, Any], ModelDTOT]":
|
|
337
434
|
"""Insert, update, or delete data from the database and return result.
|
|
338
435
|
|
|
339
436
|
Returns:
|
|
340
437
|
The first row of results.
|
|
341
438
|
"""
|
|
342
439
|
connection = self._connection(connection)
|
|
343
|
-
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
440
|
+
sql, parameters = self._process_sql_params(sql, parameters, *filters, **kwargs)
|
|
441
|
+
|
|
442
|
+
# Execute the query
|
|
443
|
+
cursor = await connection.execute(sql, parameters or ())
|
|
444
|
+
result = await cursor.fetchone()
|
|
445
|
+
await connection.commit()
|
|
446
|
+
await cursor.close()
|
|
344
447
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
return dict(zip(column_names, results[0])) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType]
|
|
448
|
+
result = self.check_not_found(result)
|
|
449
|
+
|
|
450
|
+
# Get column names
|
|
451
|
+
column_names = [column[0] for column in cursor.description]
|
|
452
|
+
|
|
453
|
+
# Convert to dict and then use ResultConverter
|
|
454
|
+
dict_result = dict(zip(column_names, result))
|
|
455
|
+
return self.to_schema(dict_result, schema_type=schema_type)
|
|
354
456
|
|
|
355
457
|
async def execute_script(
|
|
356
458
|
self,
|
|
357
459
|
sql: str,
|
|
358
|
-
parameters: Optional[
|
|
460
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
359
461
|
/,
|
|
360
|
-
|
|
361
|
-
connection: Optional["AiosqliteConnection"] = None,
|
|
462
|
+
connection: "Optional[AiosqliteConnection]" = None,
|
|
362
463
|
**kwargs: Any,
|
|
363
464
|
) -> str:
|
|
364
465
|
"""Execute a script.
|
|
@@ -369,34 +470,18 @@ class AiosqliteDriver(
|
|
|
369
470
|
connection = self._connection(connection)
|
|
370
471
|
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
371
472
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
473
|
+
# Execute the script
|
|
474
|
+
await connection.executescript(sql)
|
|
475
|
+
await connection.commit()
|
|
476
|
+
return "Script executed successfully."
|
|
375
477
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
*,
|
|
382
|
-
connection: Optional["AiosqliteConnection"] = None,
|
|
383
|
-
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
384
|
-
**kwargs: Any,
|
|
385
|
-
) -> "Optional[Union[dict[str, Any], ModelDTOT]]":
|
|
386
|
-
"""Execute a script and return result.
|
|
478
|
+
def _connection(self, connection: "Optional[AiosqliteConnection]" = None) -> "AiosqliteConnection":
|
|
479
|
+
"""Get the connection to use for the operation.
|
|
480
|
+
|
|
481
|
+
Args:
|
|
482
|
+
connection: Optional connection to use.
|
|
387
483
|
|
|
388
484
|
Returns:
|
|
389
|
-
The
|
|
485
|
+
The connection to use.
|
|
390
486
|
"""
|
|
391
|
-
connection
|
|
392
|
-
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
393
|
-
|
|
394
|
-
async with self._with_cursor(connection) as cursor:
|
|
395
|
-
await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
396
|
-
results = list(await cursor.fetchall()) # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
|
|
397
|
-
if not results: # Check if empty
|
|
398
|
-
return None
|
|
399
|
-
column_names = [c[0] for c in cursor.description or []] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
|
|
400
|
-
if schema_type is not None:
|
|
401
|
-
return cast("ModelDTOT", schema_type(**dict(zip(column_names, results[0])))) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType]
|
|
402
|
-
return dict(zip(column_names, results[0])) # pyright: ignore[reportUnknownArgumentType, reportUnknownVariableType]
|
|
487
|
+
return connection or self.connection
|