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