sqlspec 0.7.1__py3-none-any.whl → 0.9.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 (54) hide show
  1. sqlspec/__init__.py +15 -0
  2. sqlspec/_serialization.py +16 -2
  3. sqlspec/_typing.py +40 -7
  4. sqlspec/adapters/adbc/__init__.py +7 -0
  5. sqlspec/adapters/adbc/config.py +183 -17
  6. sqlspec/adapters/adbc/driver.py +392 -0
  7. sqlspec/adapters/aiosqlite/__init__.py +5 -1
  8. sqlspec/adapters/aiosqlite/config.py +24 -6
  9. sqlspec/adapters/aiosqlite/driver.py +264 -0
  10. sqlspec/adapters/asyncmy/__init__.py +7 -2
  11. sqlspec/adapters/asyncmy/config.py +71 -11
  12. sqlspec/adapters/asyncmy/driver.py +246 -0
  13. sqlspec/adapters/asyncpg/__init__.py +9 -0
  14. sqlspec/adapters/asyncpg/config.py +102 -25
  15. sqlspec/adapters/asyncpg/driver.py +444 -0
  16. sqlspec/adapters/duckdb/__init__.py +5 -1
  17. sqlspec/adapters/duckdb/config.py +194 -12
  18. sqlspec/adapters/duckdb/driver.py +225 -0
  19. sqlspec/adapters/oracledb/__init__.py +7 -4
  20. sqlspec/adapters/oracledb/config/__init__.py +4 -4
  21. sqlspec/adapters/oracledb/config/_asyncio.py +96 -12
  22. sqlspec/adapters/oracledb/config/_common.py +1 -1
  23. sqlspec/adapters/oracledb/config/_sync.py +96 -12
  24. sqlspec/adapters/oracledb/driver.py +571 -0
  25. sqlspec/adapters/psqlpy/__init__.py +0 -0
  26. sqlspec/adapters/psqlpy/config.py +258 -0
  27. sqlspec/adapters/psqlpy/driver.py +335 -0
  28. sqlspec/adapters/psycopg/__init__.py +16 -0
  29. sqlspec/adapters/psycopg/config/__init__.py +6 -6
  30. sqlspec/adapters/psycopg/config/_async.py +107 -15
  31. sqlspec/adapters/psycopg/config/_common.py +2 -2
  32. sqlspec/adapters/psycopg/config/_sync.py +107 -15
  33. sqlspec/adapters/psycopg/driver.py +578 -0
  34. sqlspec/adapters/sqlite/__init__.py +7 -0
  35. sqlspec/adapters/sqlite/config.py +24 -6
  36. sqlspec/adapters/sqlite/driver.py +305 -0
  37. sqlspec/base.py +565 -63
  38. sqlspec/exceptions.py +30 -0
  39. sqlspec/extensions/litestar/__init__.py +19 -0
  40. sqlspec/extensions/litestar/_utils.py +56 -0
  41. sqlspec/extensions/litestar/config.py +87 -0
  42. sqlspec/extensions/litestar/handlers.py +213 -0
  43. sqlspec/extensions/litestar/plugin.py +105 -11
  44. sqlspec/statement.py +373 -0
  45. sqlspec/typing.py +81 -17
  46. sqlspec/utils/__init__.py +3 -0
  47. sqlspec/utils/fixtures.py +4 -5
  48. sqlspec/utils/sync_tools.py +335 -0
  49. {sqlspec-0.7.1.dist-info → sqlspec-0.9.0.dist-info}/METADATA +4 -1
  50. sqlspec-0.9.0.dist-info/RECORD +61 -0
  51. sqlspec-0.7.1.dist-info/RECORD +0 -46
  52. {sqlspec-0.7.1.dist-info → sqlspec-0.9.0.dist-info}/WHEEL +0 -0
  53. {sqlspec-0.7.1.dist-info → sqlspec-0.9.0.dist-info}/licenses/LICENSE +0 -0
  54. {sqlspec-0.7.1.dist-info → sqlspec-0.9.0.dist-info}/licenses/NOTICE +0 -0
@@ -0,0 +1,571 @@
1
+ from contextlib import asynccontextmanager, contextmanager
2
+ from typing import TYPE_CHECKING, Any, Optional, Union, cast
3
+
4
+ from sqlspec.base import (
5
+ AsyncArrowBulkOperationsMixin,
6
+ AsyncDriverAdapterProtocol,
7
+ SyncArrowBulkOperationsMixin,
8
+ SyncDriverAdapterProtocol,
9
+ T,
10
+ )
11
+ from sqlspec.typing import ArrowTable, StatementParameterType
12
+
13
+ if TYPE_CHECKING:
14
+ from collections.abc import AsyncGenerator, Generator
15
+
16
+ from oracledb import AsyncConnection, AsyncCursor, Connection, Cursor
17
+
18
+ # Conditionally import ArrowTable for type checking
19
+ from sqlspec.typing import ModelDTOT
20
+
21
+ __all__ = ("OracleAsyncDriver", "OracleSyncDriver")
22
+
23
+
24
+ class OracleSyncDriver(SyncArrowBulkOperationsMixin["Connection"], SyncDriverAdapterProtocol["Connection"]):
25
+ """Oracle Sync Driver Adapter."""
26
+
27
+ connection: "Connection"
28
+ dialect: str = "oracle"
29
+
30
+ def __init__(self, connection: "Connection") -> None:
31
+ self.connection = connection
32
+
33
+ @staticmethod
34
+ @contextmanager
35
+ def _with_cursor(connection: "Connection") -> "Generator[Cursor, None, None]":
36
+ cursor = connection.cursor()
37
+ try:
38
+ yield cursor
39
+ finally:
40
+ cursor.close()
41
+
42
+ def select(
43
+ self,
44
+ sql: str,
45
+ parameters: "Optional[StatementParameterType]" = None,
46
+ /,
47
+ *,
48
+ connection: "Optional[Connection]" = None,
49
+ schema_type: "Optional[type[ModelDTOT]]" = None,
50
+ **kwargs: Any,
51
+ ) -> "list[Union[ModelDTOT, dict[str, Any]]]":
52
+ """Fetch data from the database.
53
+
54
+ Args:
55
+ sql: The SQL query string.
56
+ parameters: The parameters for the query (dict, tuple, list, or None).
57
+ connection: Optional connection override.
58
+ schema_type: Optional schema class for the result.
59
+ **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict.
60
+
61
+ Returns:
62
+ List of row data as either model instances or dictionaries.
63
+ """
64
+ connection = self._connection(connection)
65
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
66
+ with self._with_cursor(connection) as cursor:
67
+ cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
68
+ results = cursor.fetchall() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
69
+ if not results:
70
+ return []
71
+ # Get column names
72
+ column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
73
+
74
+ if schema_type:
75
+ return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] # pyright: ignore
76
+
77
+ return [dict(zip(column_names, row)) for row in results] # pyright: ignore
78
+
79
+ def select_one(
80
+ self,
81
+ sql: str,
82
+ parameters: "Optional[StatementParameterType]" = None,
83
+ /,
84
+ *,
85
+ connection: "Optional[Connection]" = None,
86
+ schema_type: "Optional[type[ModelDTOT]]" = None,
87
+ **kwargs: Any,
88
+ ) -> "Union[ModelDTOT, dict[str, Any]]":
89
+ """Fetch one row from the database.
90
+
91
+ Args:
92
+ sql: The SQL query string.
93
+ parameters: The parameters for the query (dict, tuple, list, or None).
94
+ connection: Optional connection override.
95
+ schema_type: Optional schema class for the result.
96
+ **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict.
97
+
98
+ Returns:
99
+ The first row of the query results.
100
+ """
101
+ connection = self._connection(connection)
102
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
103
+
104
+ with self._with_cursor(connection) as cursor:
105
+ cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
106
+ result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
107
+ result = self.check_not_found(result) # pyright: ignore[reportUnknownArgumentType]
108
+
109
+ # Get column names
110
+ column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
111
+
112
+ if schema_type is not None:
113
+ return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType]
114
+ # Always return dictionaries
115
+ return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
116
+
117
+ def select_one_or_none(
118
+ self,
119
+ sql: str,
120
+ parameters: "Optional[StatementParameterType]" = None,
121
+ /,
122
+ *,
123
+ connection: "Optional[Connection]" = None,
124
+ schema_type: "Optional[type[ModelDTOT]]" = None,
125
+ **kwargs: Any,
126
+ ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]":
127
+ """Fetch one row from the database.
128
+
129
+ Returns:
130
+ The first row of the query results.
131
+ """
132
+ connection = self._connection(connection)
133
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
134
+
135
+ with self._with_cursor(connection) as cursor:
136
+ cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
137
+ result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
138
+
139
+ if result is None:
140
+ return None
141
+
142
+ # Get column names
143
+ column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
144
+
145
+ if schema_type is not None:
146
+ return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType]
147
+ # Always return dictionaries
148
+ return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
149
+
150
+ def select_value(
151
+ self,
152
+ sql: str,
153
+ parameters: "Optional[StatementParameterType]" = None,
154
+ /,
155
+ *,
156
+ connection: "Optional[Connection]" = None,
157
+ schema_type: "Optional[type[T]]" = None,
158
+ **kwargs: Any,
159
+ ) -> "Union[T, Any]":
160
+ """Fetch a single value from the database.
161
+
162
+ Returns:
163
+ The first value from the first row of results, or None if no results.
164
+ """
165
+ connection = self._connection(connection)
166
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
167
+
168
+ with self._with_cursor(connection) as cursor:
169
+ cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
170
+ result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
171
+ result = self.check_not_found(result) # pyright: ignore[reportUnknownArgumentType]
172
+
173
+ if schema_type is None:
174
+ return result[0] # pyright: ignore[reportUnknownArgumentType]
175
+ return schema_type(result[0]) # type: ignore[call-arg]
176
+
177
+ def select_value_or_none(
178
+ self,
179
+ sql: str,
180
+ parameters: "Optional[StatementParameterType]" = None,
181
+ /,
182
+ *,
183
+ connection: "Optional[Connection]" = None,
184
+ schema_type: "Optional[type[T]]" = None,
185
+ **kwargs: Any,
186
+ ) -> "Optional[Union[T, Any]]":
187
+ """Fetch a single value from the database.
188
+
189
+ Returns:
190
+ The first value from the first row of results, or None if no results.
191
+ """
192
+ connection = self._connection(connection)
193
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
194
+
195
+ with self._with_cursor(connection) as cursor:
196
+ cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
197
+ result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
198
+
199
+ if result is None:
200
+ return None
201
+
202
+ if schema_type is None:
203
+ return result[0] # pyright: ignore[reportUnknownArgumentType]
204
+ return schema_type(result[0]) # type: ignore[call-arg]
205
+
206
+ def insert_update_delete(
207
+ self,
208
+ sql: str,
209
+ parameters: "Optional[StatementParameterType]" = None,
210
+ /,
211
+ *,
212
+ connection: "Optional[Connection]" = None,
213
+ **kwargs: Any,
214
+ ) -> int:
215
+ """Insert, update, or delete data from the database.
216
+
217
+ Returns:
218
+ Row count affected by the operation.
219
+ """
220
+ connection = self._connection(connection)
221
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
222
+
223
+ with self._with_cursor(connection) as cursor:
224
+ cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
225
+ return cursor.rowcount # pyright: ignore[reportUnknownMemberType]
226
+
227
+ def insert_update_delete_returning(
228
+ self,
229
+ sql: str,
230
+ parameters: "Optional[StatementParameterType]" = None,
231
+ /,
232
+ *,
233
+ connection: "Optional[Connection]" = None,
234
+ schema_type: "Optional[type[ModelDTOT]]" = None,
235
+ **kwargs: Any,
236
+ ) -> "Optional[Union[dict[str, Any], ModelDTOT]]":
237
+ """Insert, update, or delete data from the database and return result.
238
+
239
+ Returns:
240
+ The first row of results.
241
+ """
242
+ connection = self._connection(connection)
243
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
244
+
245
+ with self._with_cursor(connection) as cursor:
246
+ cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
247
+ result = cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
248
+
249
+ if result is None:
250
+ return None
251
+
252
+ # Get column names
253
+ column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
254
+
255
+ if schema_type is not None:
256
+ return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType]
257
+ # Always return dictionaries
258
+ return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
259
+
260
+ def execute_script(
261
+ self,
262
+ sql: str,
263
+ parameters: "Optional[StatementParameterType]" = None,
264
+ /,
265
+ *,
266
+ connection: "Optional[Connection]" = None,
267
+ **kwargs: Any,
268
+ ) -> str:
269
+ """Execute a script.
270
+
271
+ Returns:
272
+ Status message for the operation.
273
+ """
274
+ connection = self._connection(connection)
275
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
276
+
277
+ with self._with_cursor(connection) as cursor:
278
+ cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
279
+ return str(cursor.rowcount) # pyright: ignore[reportUnknownMemberType]
280
+
281
+ def select_arrow( # pyright: ignore[reportUnknownParameterType]
282
+ self,
283
+ sql: str,
284
+ parameters: "Optional[StatementParameterType]" = None,
285
+ /,
286
+ *,
287
+ connection: "Optional[Connection]" = None,
288
+ **kwargs: Any,
289
+ ) -> "ArrowTable": # pyright: ignore[reportUnknownVariableType]
290
+ """Execute a SQL query and return results as an Apache Arrow Table.
291
+
292
+ Returns:
293
+ An Apache Arrow Table containing the query results.
294
+ """
295
+
296
+ connection = self._connection(connection)
297
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
298
+ results = connection.fetch_df_all(sql, parameters)
299
+ return cast("ArrowTable", ArrowTable.from_arrays(arrays=results.column_arrays(), names=results.column_names())) # pyright: ignore
300
+
301
+
302
+ class OracleAsyncDriver(
303
+ AsyncArrowBulkOperationsMixin["AsyncConnection"], AsyncDriverAdapterProtocol["AsyncConnection"]
304
+ ):
305
+ """Oracle Async Driver Adapter."""
306
+
307
+ connection: "AsyncConnection"
308
+ dialect: str = "oracle"
309
+
310
+ def __init__(self, connection: "AsyncConnection") -> None:
311
+ self.connection = connection
312
+
313
+ @staticmethod
314
+ @asynccontextmanager
315
+ async def _with_cursor(connection: "AsyncConnection") -> "AsyncGenerator[AsyncCursor, None]":
316
+ cursor = connection.cursor()
317
+ try:
318
+ yield cursor
319
+ finally:
320
+ cursor.close()
321
+
322
+ async def select(
323
+ self,
324
+ sql: str,
325
+ parameters: "Optional[StatementParameterType]" = None,
326
+ /,
327
+ *,
328
+ connection: "Optional[AsyncConnection]" = None,
329
+ schema_type: "Optional[type[ModelDTOT]]" = None,
330
+ **kwargs: Any,
331
+ ) -> "list[Union[ModelDTOT, dict[str, Any]]]":
332
+ """Fetch data from the database.
333
+
334
+ Returns:
335
+ List of row data as either model instances or dictionaries.
336
+ """
337
+ connection = self._connection(connection)
338
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
339
+
340
+ async with self._with_cursor(connection) as cursor:
341
+ await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
342
+ results = await cursor.fetchall() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
343
+ if not results:
344
+ return []
345
+ # Get column names
346
+ column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
347
+
348
+ if schema_type:
349
+ return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] # pyright: ignore
350
+
351
+ return [dict(zip(column_names, row)) for row in results] # pyright: ignore
352
+
353
+ async def select_one(
354
+ self,
355
+ sql: str,
356
+ parameters: "Optional[StatementParameterType]" = None,
357
+ /,
358
+ *,
359
+ connection: "Optional[AsyncConnection]" = None,
360
+ schema_type: "Optional[type[ModelDTOT]]" = None,
361
+ **kwargs: Any,
362
+ ) -> "Union[ModelDTOT, dict[str, Any]]":
363
+ """Fetch one row from the database.
364
+
365
+ Returns:
366
+ The first row of the query results.
367
+ """
368
+ connection = self._connection(connection)
369
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
370
+
371
+ async with self._with_cursor(connection) as cursor:
372
+ await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
373
+ result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
374
+ result = self.check_not_found(result) # pyright: ignore[reportUnknownArgumentType]
375
+ # Get column names
376
+ column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
377
+
378
+ if schema_type is not None:
379
+ return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType]
380
+ # Always return dictionaries
381
+ return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
382
+
383
+ async def select_one_or_none(
384
+ self,
385
+ sql: str,
386
+ parameters: "Optional[StatementParameterType]" = None,
387
+ /,
388
+ *,
389
+ connection: "Optional[AsyncConnection]" = None,
390
+ schema_type: "Optional[type[ModelDTOT]]" = None,
391
+ **kwargs: Any,
392
+ ) -> "Optional[Union[ModelDTOT, dict[str, Any]]]":
393
+ """Fetch one row from the database.
394
+
395
+ Returns:
396
+ The first row of the query results.
397
+ """
398
+ connection = self._connection(connection)
399
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
400
+
401
+ async with self._with_cursor(connection) as cursor:
402
+ await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
403
+ result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
404
+
405
+ if result is None:
406
+ return None
407
+
408
+ # Get column names
409
+ column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
410
+
411
+ if schema_type is not None:
412
+ return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType]
413
+ # Always return dictionaries
414
+ return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
415
+
416
+ async def select_value(
417
+ self,
418
+ sql: str,
419
+ parameters: "Optional[StatementParameterType]" = None,
420
+ /,
421
+ *,
422
+ connection: "Optional[AsyncConnection]" = None,
423
+ schema_type: "Optional[type[T]]" = None,
424
+ **kwargs: Any,
425
+ ) -> "Union[T, Any]":
426
+ """Fetch a single value from the database.
427
+
428
+ Returns:
429
+ The first value from the first row of results, or None if no results.
430
+ """
431
+ connection = self._connection(connection)
432
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
433
+
434
+ async with self._with_cursor(connection) as cursor:
435
+ await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
436
+ result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
437
+ result = self.check_not_found(result) # pyright: ignore[reportUnknownArgumentType]
438
+
439
+ if schema_type is None:
440
+ return result[0] # pyright: ignore[reportUnknownArgumentType]
441
+ return schema_type(result[0]) # type: ignore[call-arg]
442
+
443
+ async def select_value_or_none(
444
+ self,
445
+ sql: str,
446
+ parameters: "Optional[StatementParameterType]" = None,
447
+ /,
448
+ *,
449
+ connection: "Optional[AsyncConnection]" = None,
450
+ schema_type: "Optional[type[T]]" = None,
451
+ **kwargs: Any,
452
+ ) -> "Optional[Union[T, Any]]":
453
+ """Fetch a single value from the database.
454
+
455
+ Returns:
456
+ The first value from the first row of results, or None if no results.
457
+ """
458
+ connection = self._connection(connection)
459
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
460
+
461
+ async with self._with_cursor(connection) as cursor:
462
+ await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
463
+ result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
464
+
465
+ if result is None:
466
+ return None
467
+
468
+ if schema_type is None:
469
+ return result[0] # pyright: ignore[reportUnknownArgumentType]
470
+ return schema_type(result[0]) # type: ignore[call-arg]
471
+
472
+ async def insert_update_delete(
473
+ self,
474
+ sql: str,
475
+ parameters: "Optional[StatementParameterType]" = None,
476
+ /,
477
+ *,
478
+ connection: "Optional[AsyncConnection]" = None,
479
+ **kwargs: Any,
480
+ ) -> int:
481
+ """Insert, update, or delete data from the database.
482
+
483
+ Returns:
484
+ Row count affected by the operation.
485
+ """
486
+ connection = self._connection(connection)
487
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
488
+
489
+ async with self._with_cursor(connection) as cursor:
490
+ await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
491
+ return cursor.rowcount # pyright: ignore[reportUnknownMemberType]
492
+
493
+ async def insert_update_delete_returning(
494
+ self,
495
+ sql: str,
496
+ parameters: "Optional[StatementParameterType]" = None,
497
+ /,
498
+ *,
499
+ connection: "Optional[AsyncConnection]" = None,
500
+ schema_type: "Optional[type[ModelDTOT]]" = None,
501
+ **kwargs: Any,
502
+ ) -> "Optional[Union[dict[str, Any], ModelDTOT]]":
503
+ """Insert, update, or delete data from the database and return result.
504
+
505
+ Returns:
506
+ The first row of results.
507
+ """
508
+ connection = self._connection(connection)
509
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
510
+
511
+ async with self._with_cursor(connection) as cursor:
512
+ await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
513
+ result = await cursor.fetchone() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
514
+
515
+ if result is None:
516
+ return None
517
+
518
+ # Get column names
519
+ column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
520
+
521
+ if schema_type is not None:
522
+ return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType]
523
+ # Always return dictionaries
524
+ return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
525
+
526
+ async def execute_script(
527
+ self,
528
+ sql: str,
529
+ parameters: "Optional[StatementParameterType]" = None,
530
+ /,
531
+ *,
532
+ connection: "Optional[AsyncConnection]" = None,
533
+ **kwargs: Any,
534
+ ) -> str:
535
+ """Execute a script.
536
+
537
+ Returns:
538
+ Status message for the operation.
539
+ """
540
+ connection = self._connection(connection)
541
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
542
+
543
+ async with self._with_cursor(connection) as cursor:
544
+ await cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
545
+ return str(cursor.rowcount) # pyright: ignore[reportUnknownMemberType]
546
+
547
+ async def select_arrow( # pyright: ignore[reportUnknownParameterType]
548
+ self,
549
+ sql: str,
550
+ parameters: "Optional[StatementParameterType]" = None,
551
+ /,
552
+ *,
553
+ connection: "Optional[AsyncConnection]" = None,
554
+ **kwargs: Any,
555
+ ) -> "ArrowTable": # pyright: ignore[reportUnknownVariableType]
556
+ """Execute a SQL query asynchronously and return results as an Apache Arrow Table.
557
+
558
+ Args:
559
+ sql: The SQL query string.
560
+ parameters: Parameters for the query.
561
+ connection: Optional connection override.
562
+ **kwargs: Additional keyword arguments to merge with parameters if parameters is a dict.
563
+
564
+ Returns:
565
+ An Apache Arrow Table containing the query results.
566
+ """
567
+
568
+ connection = self._connection(connection)
569
+ sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
570
+ results = await connection.fetch_df_all(sql, parameters)
571
+ return ArrowTable.from_arrays(arrays=results.column_arrays(), names=results.column_names()) # pyright: ignore
File without changes