sqlspec 0.9.0__py3-none-any.whl → 0.10.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/__init__.py +2 -1
- sqlspec/adapters/adbc/__init__.py +2 -1
- sqlspec/adapters/adbc/config.py +7 -13
- sqlspec/adapters/adbc/driver.py +160 -21
- sqlspec/adapters/aiosqlite/__init__.py +2 -1
- sqlspec/adapters/aiosqlite/config.py +10 -12
- sqlspec/adapters/aiosqlite/driver.py +160 -22
- sqlspec/adapters/asyncmy/__init__.py +2 -1
- sqlspec/adapters/asyncmy/driver.py +158 -22
- sqlspec/adapters/asyncpg/config.py +1 -3
- sqlspec/adapters/asyncpg/driver.py +143 -5
- sqlspec/adapters/bigquery/__init__.py +4 -0
- sqlspec/adapters/bigquery/config/__init__.py +3 -0
- sqlspec/adapters/bigquery/config/_common.py +40 -0
- sqlspec/adapters/bigquery/config/_sync.py +87 -0
- sqlspec/adapters/bigquery/driver.py +701 -0
- sqlspec/adapters/duckdb/__init__.py +2 -1
- sqlspec/adapters/duckdb/config.py +17 -18
- sqlspec/adapters/duckdb/driver.py +165 -27
- sqlspec/adapters/oracledb/__init__.py +8 -1
- sqlspec/adapters/oracledb/config/_asyncio.py +7 -8
- sqlspec/adapters/oracledb/config/_sync.py +6 -7
- sqlspec/adapters/oracledb/driver.py +311 -42
- sqlspec/adapters/psqlpy/__init__.py +9 -0
- sqlspec/adapters/psqlpy/config.py +11 -19
- sqlspec/adapters/psqlpy/driver.py +171 -19
- sqlspec/adapters/psycopg/__init__.py +8 -1
- sqlspec/adapters/psycopg/config/__init__.py +10 -0
- sqlspec/adapters/psycopg/config/_async.py +6 -7
- sqlspec/adapters/psycopg/config/_sync.py +7 -8
- sqlspec/adapters/psycopg/driver.py +344 -86
- sqlspec/adapters/sqlite/__init__.py +2 -1
- sqlspec/adapters/sqlite/config.py +12 -11
- sqlspec/adapters/sqlite/driver.py +160 -51
- sqlspec/base.py +402 -63
- sqlspec/exceptions.py +9 -0
- sqlspec/extensions/litestar/config.py +3 -11
- sqlspec/extensions/litestar/handlers.py +2 -1
- sqlspec/extensions/litestar/plugin.py +6 -2
- sqlspec/mixins.py +156 -0
- sqlspec/typing.py +19 -1
- {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/METADATA +147 -3
- sqlspec-0.10.0.dist-info/RECORD +67 -0
- sqlspec-0.9.0.dist-info/RECORD +0 -61
- {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/licenses/LICENSE +0 -0
- {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from sqlspec.adapters.duckdb.config import DuckDBConfig
|
|
2
|
-
from sqlspec.adapters.duckdb.driver import DuckDBDriver
|
|
2
|
+
from sqlspec.adapters.duckdb.driver import DuckDBConnection, DuckDBDriver
|
|
3
3
|
|
|
4
4
|
__all__ = (
|
|
5
5
|
"DuckDBConfig",
|
|
6
|
+
"DuckDBConnection",
|
|
6
7
|
"DuckDBDriver",
|
|
7
8
|
)
|
|
@@ -2,10 +2,9 @@ from contextlib import contextmanager
|
|
|
2
2
|
from dataclasses import dataclass, field
|
|
3
3
|
from typing import TYPE_CHECKING, Any, Callable, Optional, Union, cast
|
|
4
4
|
|
|
5
|
-
from duckdb import DuckDBPyConnection
|
|
6
5
|
from typing_extensions import Literal, NotRequired, TypedDict
|
|
7
6
|
|
|
8
|
-
from sqlspec.adapters.duckdb.driver import DuckDBDriver
|
|
7
|
+
from sqlspec.adapters.duckdb.driver import DuckDBConnection, DuckDBDriver
|
|
9
8
|
from sqlspec.base import NoPoolSyncConfig
|
|
10
9
|
from sqlspec.exceptions import ImproperConfigurationError
|
|
11
10
|
from sqlspec.typing import Empty, EmptyType, dataclass_to_dict
|
|
@@ -69,7 +68,7 @@ class SecretConfig(TypedDict):
|
|
|
69
68
|
|
|
70
69
|
|
|
71
70
|
@dataclass
|
|
72
|
-
class DuckDBConfig(NoPoolSyncConfig["
|
|
71
|
+
class DuckDBConfig(NoPoolSyncConfig["DuckDBConnection", "DuckDBDriver"]):
|
|
73
72
|
"""Configuration for DuckDB database connections.
|
|
74
73
|
|
|
75
74
|
This class provides configuration options for DuckDB database connections, wrapping all parameters
|
|
@@ -96,10 +95,10 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
96
95
|
"""A dictionary of secrets to store in the connection for later retrieval."""
|
|
97
96
|
auto_update_extensions: "bool" = False
|
|
98
97
|
"""Whether to automatically update on connection creation"""
|
|
99
|
-
on_connection_create: "Optional[Callable[[
|
|
98
|
+
on_connection_create: "Optional[Callable[[DuckDBConnection], Optional[DuckDBConnection]]]" = None
|
|
100
99
|
"""A callable to be called after the connection is created."""
|
|
101
|
-
connection_type: "type[
|
|
102
|
-
"""The type of connection to create. Defaults to
|
|
100
|
+
connection_type: "type[DuckDBConnection]" = field(init=False, default_factory=lambda: DuckDBConnection)
|
|
101
|
+
"""The type of connection to create. Defaults to DuckDBConnection."""
|
|
103
102
|
driver_type: "type[DuckDBDriver]" = field(init=False, default_factory=lambda: DuckDBDriver) # type: ignore[type-abstract,unused-ignore]
|
|
104
103
|
"""The type of driver to use. Defaults to DuckDBDriver."""
|
|
105
104
|
pool_instance: "None" = field(init=False, default=None)
|
|
@@ -139,7 +138,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
139
138
|
raise ImproperConfigurationError(msg) from e
|
|
140
139
|
self.extensions.extend(config_exts)
|
|
141
140
|
|
|
142
|
-
def _configure_connection(self, connection: "
|
|
141
|
+
def _configure_connection(self, connection: "DuckDBConnection") -> None:
|
|
143
142
|
"""Configure the connection.
|
|
144
143
|
|
|
145
144
|
Args:
|
|
@@ -148,7 +147,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
148
147
|
for key, value in cast("dict[str,Any]", self.config).items():
|
|
149
148
|
connection.execute(f"SET {key}='{value}'")
|
|
150
149
|
|
|
151
|
-
def _configure_extensions(self, connection: "
|
|
150
|
+
def _configure_extensions(self, connection: "DuckDBConnection") -> None:
|
|
152
151
|
"""Configure extensions for the connection.
|
|
153
152
|
|
|
154
153
|
Args:
|
|
@@ -165,7 +164,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
165
164
|
connection.execute("update extensions")
|
|
166
165
|
|
|
167
166
|
@staticmethod
|
|
168
|
-
def _secret_exists(connection: "
|
|
167
|
+
def _secret_exists(connection: "DuckDBConnection", name: "str") -> bool:
|
|
169
168
|
"""Check if a secret exists in the connection.
|
|
170
169
|
|
|
171
170
|
Args:
|
|
@@ -179,7 +178,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
179
178
|
return results is not None
|
|
180
179
|
|
|
181
180
|
@classmethod
|
|
182
|
-
def _is_community_extension(cls, connection: "
|
|
181
|
+
def _is_community_extension(cls, connection: "DuckDBConnection", name: "str") -> bool:
|
|
183
182
|
"""Check if an extension is a community extension.
|
|
184
183
|
|
|
185
184
|
Args:
|
|
@@ -195,7 +194,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
195
194
|
return results is None
|
|
196
195
|
|
|
197
196
|
@classmethod
|
|
198
|
-
def _extension_installed(cls, connection: "
|
|
197
|
+
def _extension_installed(cls, connection: "DuckDBConnection", name: "str") -> bool:
|
|
199
198
|
"""Check if a extension exists in the connection.
|
|
200
199
|
|
|
201
200
|
Args:
|
|
@@ -211,7 +210,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
211
210
|
return results is not None
|
|
212
211
|
|
|
213
212
|
@classmethod
|
|
214
|
-
def _extension_loaded(cls, connection: "
|
|
213
|
+
def _extension_loaded(cls, connection: "DuckDBConnection", name: "str") -> bool:
|
|
215
214
|
"""Check if a extension is loaded in the connection.
|
|
216
215
|
|
|
217
216
|
Args:
|
|
@@ -229,7 +228,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
229
228
|
@classmethod
|
|
230
229
|
def _configure_secrets(
|
|
231
230
|
cls,
|
|
232
|
-
connection: "
|
|
231
|
+
connection: "DuckDBConnection",
|
|
233
232
|
secrets: "Sequence[SecretConfig]",
|
|
234
233
|
) -> None:
|
|
235
234
|
"""Configure persistent secrets for the connection.
|
|
@@ -258,7 +257,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
258
257
|
raise ImproperConfigurationError(msg) from e
|
|
259
258
|
|
|
260
259
|
@classmethod
|
|
261
|
-
def _configure_extension(cls, connection: "
|
|
260
|
+
def _configure_extension(cls, connection: "DuckDBConnection", extension: "ExtensionConfig") -> None:
|
|
262
261
|
"""Configure a single extension for the connection.
|
|
263
262
|
|
|
264
263
|
Args:
|
|
@@ -320,6 +319,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
320
319
|
"auto_update_extensions",
|
|
321
320
|
"driver_type",
|
|
322
321
|
"connection_type",
|
|
322
|
+
"connection_instance",
|
|
323
323
|
},
|
|
324
324
|
convert_nested=False,
|
|
325
325
|
)
|
|
@@ -327,7 +327,7 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
327
327
|
config["database"] = ":memory:"
|
|
328
328
|
return config
|
|
329
329
|
|
|
330
|
-
def create_connection(self) -> "
|
|
330
|
+
def create_connection(self) -> "DuckDBConnection":
|
|
331
331
|
"""Create and return a new database connection with configured extensions.
|
|
332
332
|
|
|
333
333
|
Returns:
|
|
@@ -349,11 +349,10 @@ class DuckDBConfig(NoPoolSyncConfig["DuckDBPyConnection", "DuckDBDriver"]):
|
|
|
349
349
|
except Exception as e:
|
|
350
350
|
msg = f"Could not configure the DuckDB connection. Error: {e!s}"
|
|
351
351
|
raise ImproperConfigurationError(msg) from e
|
|
352
|
-
|
|
353
|
-
return connection
|
|
352
|
+
return connection
|
|
354
353
|
|
|
355
354
|
@contextmanager
|
|
356
|
-
def provide_connection(self, *args: Any, **kwargs: Any) -> "Generator[
|
|
355
|
+
def provide_connection(self, *args: Any, **kwargs: Any) -> "Generator[DuckDBConnection, None, None]":
|
|
357
356
|
"""Create and provide a database connection.
|
|
358
357
|
|
|
359
358
|
Yields:
|
|
@@ -1,37 +1,45 @@
|
|
|
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
|
|
4
|
+
from duckdb import DuckDBPyConnection
|
|
5
|
+
|
|
6
|
+
from sqlspec.base import SyncDriverAdapterProtocol
|
|
7
|
+
from sqlspec.mixins import SQLTranslatorMixin, SyncArrowBulkOperationsMixin
|
|
8
|
+
from sqlspec.typing import ArrowTable, StatementParameterType
|
|
5
9
|
|
|
6
10
|
if TYPE_CHECKING:
|
|
7
|
-
from collections.abc import Generator
|
|
11
|
+
from collections.abc import Generator, Sequence
|
|
8
12
|
|
|
9
|
-
from
|
|
13
|
+
from sqlspec.typing import ArrowTable, ModelDTOT, StatementParameterType, T
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
__all__ = ("DuckDBConnection", "DuckDBDriver")
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
DuckDBConnection = DuckDBPyConnection
|
|
14
18
|
|
|
15
19
|
|
|
16
|
-
class DuckDBDriver(
|
|
20
|
+
class DuckDBDriver(
|
|
21
|
+
SyncArrowBulkOperationsMixin["DuckDBConnection"],
|
|
22
|
+
SQLTranslatorMixin["DuckDBConnection"],
|
|
23
|
+
SyncDriverAdapterProtocol["DuckDBConnection"],
|
|
24
|
+
):
|
|
17
25
|
"""DuckDB Sync Driver Adapter."""
|
|
18
26
|
|
|
19
|
-
connection: "
|
|
27
|
+
connection: "DuckDBConnection"
|
|
20
28
|
use_cursor: bool = True
|
|
21
29
|
dialect: str = "duckdb"
|
|
22
30
|
|
|
23
|
-
def __init__(self, connection: "
|
|
31
|
+
def __init__(self, connection: "DuckDBConnection", use_cursor: bool = True) -> None:
|
|
24
32
|
self.connection = connection
|
|
25
33
|
self.use_cursor = use_cursor
|
|
26
34
|
|
|
27
35
|
# --- Helper Methods --- #
|
|
28
|
-
def _cursor(self, connection: "
|
|
36
|
+
def _cursor(self, connection: "DuckDBConnection") -> "DuckDBConnection":
|
|
29
37
|
if self.use_cursor:
|
|
30
38
|
return connection.cursor()
|
|
31
39
|
return connection
|
|
32
40
|
|
|
33
41
|
@contextmanager
|
|
34
|
-
def _with_cursor(self, connection: "
|
|
42
|
+
def _with_cursor(self, connection: "DuckDBConnection") -> "Generator[DuckDBConnection, None, None]":
|
|
35
43
|
if self.use_cursor:
|
|
36
44
|
cursor = self._cursor(connection)
|
|
37
45
|
try:
|
|
@@ -42,17 +50,38 @@ class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDrive
|
|
|
42
50
|
yield connection
|
|
43
51
|
|
|
44
52
|
# --- Public API Methods --- #
|
|
45
|
-
|
|
53
|
+
@overload
|
|
46
54
|
def select(
|
|
47
55
|
self,
|
|
48
56
|
sql: str,
|
|
49
|
-
parameters: Optional[
|
|
57
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
58
|
+
/,
|
|
59
|
+
*,
|
|
60
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
61
|
+
schema_type: None = None,
|
|
62
|
+
**kwargs: Any,
|
|
63
|
+
) -> "Sequence[dict[str, Any]]": ...
|
|
64
|
+
@overload
|
|
65
|
+
def select(
|
|
66
|
+
self,
|
|
67
|
+
sql: str,
|
|
68
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
50
69
|
/,
|
|
51
70
|
*,
|
|
52
|
-
connection: Optional["
|
|
71
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
72
|
+
schema_type: "type[ModelDTOT]",
|
|
73
|
+
**kwargs: Any,
|
|
74
|
+
) -> "Sequence[ModelDTOT]": ...
|
|
75
|
+
def select(
|
|
76
|
+
self,
|
|
77
|
+
sql: str,
|
|
78
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
79
|
+
/,
|
|
80
|
+
*,
|
|
81
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
53
82
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
54
83
|
**kwargs: Any,
|
|
55
|
-
) -> "
|
|
84
|
+
) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]":
|
|
56
85
|
connection = self._connection(connection)
|
|
57
86
|
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
58
87
|
with self._with_cursor(connection) as cursor:
|
|
@@ -67,13 +96,35 @@ class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDrive
|
|
|
67
96
|
return [cast("ModelDTOT", schema_type(**dict(zip(column_names, row)))) for row in results] # pyright: ignore[reportUnknownArgumentType]
|
|
68
97
|
return [dict(zip(column_names, row)) for row in results] # pyright: ignore[reportUnknownArgumentType]
|
|
69
98
|
|
|
99
|
+
@overload
|
|
100
|
+
def select_one(
|
|
101
|
+
self,
|
|
102
|
+
sql: str,
|
|
103
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
104
|
+
/,
|
|
105
|
+
*,
|
|
106
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
107
|
+
schema_type: None = None,
|
|
108
|
+
**kwargs: Any,
|
|
109
|
+
) -> "dict[str, Any]": ...
|
|
110
|
+
@overload
|
|
111
|
+
def select_one(
|
|
112
|
+
self,
|
|
113
|
+
sql: str,
|
|
114
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
115
|
+
/,
|
|
116
|
+
*,
|
|
117
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
118
|
+
schema_type: "type[ModelDTOT]",
|
|
119
|
+
**kwargs: Any,
|
|
120
|
+
) -> "ModelDTOT": ...
|
|
70
121
|
def select_one(
|
|
71
122
|
self,
|
|
72
123
|
sql: str,
|
|
73
124
|
parameters: Optional["StatementParameterType"] = None,
|
|
74
125
|
/,
|
|
75
126
|
*,
|
|
76
|
-
connection: Optional["
|
|
127
|
+
connection: Optional["DuckDBConnection"] = None,
|
|
77
128
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
78
129
|
**kwargs: Any,
|
|
79
130
|
) -> "Union[ModelDTOT, dict[str, Any]]":
|
|
@@ -90,13 +141,35 @@ class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDrive
|
|
|
90
141
|
# Always return dictionaries
|
|
91
142
|
return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
|
|
92
143
|
|
|
144
|
+
@overload
|
|
145
|
+
def select_one_or_none(
|
|
146
|
+
self,
|
|
147
|
+
sql: str,
|
|
148
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
149
|
+
/,
|
|
150
|
+
*,
|
|
151
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
152
|
+
schema_type: None = None,
|
|
153
|
+
**kwargs: Any,
|
|
154
|
+
) -> "Optional[dict[str, Any]]": ...
|
|
155
|
+
@overload
|
|
156
|
+
def select_one_or_none(
|
|
157
|
+
self,
|
|
158
|
+
sql: str,
|
|
159
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
160
|
+
/,
|
|
161
|
+
*,
|
|
162
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
163
|
+
schema_type: "type[ModelDTOT]",
|
|
164
|
+
**kwargs: Any,
|
|
165
|
+
) -> "Optional[ModelDTOT]": ...
|
|
93
166
|
def select_one_or_none(
|
|
94
167
|
self,
|
|
95
168
|
sql: str,
|
|
96
169
|
parameters: Optional["StatementParameterType"] = None,
|
|
97
170
|
/,
|
|
98
171
|
*,
|
|
99
|
-
connection: Optional["
|
|
172
|
+
connection: Optional["DuckDBConnection"] = None,
|
|
100
173
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
101
174
|
**kwargs: Any,
|
|
102
175
|
) -> "Optional[Union[ModelDTOT, dict[str, Any]]]":
|
|
@@ -113,13 +186,35 @@ class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDrive
|
|
|
113
186
|
return cast("ModelDTOT", schema_type(**dict(zip(column_names, result)))) # pyright: ignore[reportUnknownArgumentType]
|
|
114
187
|
return dict(zip(column_names, result)) # pyright: ignore[reportUnknownArgumentType,reportUnknownVariableType]
|
|
115
188
|
|
|
189
|
+
@overload
|
|
116
190
|
def select_value(
|
|
117
191
|
self,
|
|
118
192
|
sql: str,
|
|
119
193
|
parameters: "Optional[StatementParameterType]" = None,
|
|
120
194
|
/,
|
|
121
195
|
*,
|
|
122
|
-
connection: "Optional[
|
|
196
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
197
|
+
schema_type: None = None,
|
|
198
|
+
**kwargs: Any,
|
|
199
|
+
) -> "Any": ...
|
|
200
|
+
@overload
|
|
201
|
+
def select_value(
|
|
202
|
+
self,
|
|
203
|
+
sql: str,
|
|
204
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
205
|
+
/,
|
|
206
|
+
*,
|
|
207
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
208
|
+
schema_type: "type[T]",
|
|
209
|
+
**kwargs: Any,
|
|
210
|
+
) -> "T": ...
|
|
211
|
+
def select_value(
|
|
212
|
+
self,
|
|
213
|
+
sql: str,
|
|
214
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
215
|
+
/,
|
|
216
|
+
*,
|
|
217
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
123
218
|
schema_type: "Optional[type[T]]" = None,
|
|
124
219
|
**kwargs: Any,
|
|
125
220
|
) -> "Union[T, Any]":
|
|
@@ -133,13 +228,35 @@ class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDrive
|
|
|
133
228
|
return result[0] # pyright: ignore
|
|
134
229
|
return schema_type(result[0]) # type: ignore[call-arg]
|
|
135
230
|
|
|
231
|
+
@overload
|
|
232
|
+
def select_value_or_none(
|
|
233
|
+
self,
|
|
234
|
+
sql: str,
|
|
235
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
236
|
+
/,
|
|
237
|
+
*,
|
|
238
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
239
|
+
schema_type: None = None,
|
|
240
|
+
**kwargs: Any,
|
|
241
|
+
) -> "Optional[Any]": ...
|
|
242
|
+
@overload
|
|
243
|
+
def select_value_or_none(
|
|
244
|
+
self,
|
|
245
|
+
sql: str,
|
|
246
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
247
|
+
/,
|
|
248
|
+
*,
|
|
249
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
250
|
+
schema_type: "type[T]",
|
|
251
|
+
**kwargs: Any,
|
|
252
|
+
) -> "Optional[T]": ...
|
|
136
253
|
def select_value_or_none(
|
|
137
254
|
self,
|
|
138
255
|
sql: str,
|
|
139
256
|
parameters: "Optional[StatementParameterType]" = None,
|
|
140
257
|
/,
|
|
141
258
|
*,
|
|
142
|
-
connection: "Optional[
|
|
259
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
143
260
|
schema_type: "Optional[type[T]]" = None,
|
|
144
261
|
**kwargs: Any,
|
|
145
262
|
) -> "Optional[Union[T, Any]]":
|
|
@@ -160,7 +277,7 @@ class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDrive
|
|
|
160
277
|
parameters: Optional["StatementParameterType"] = None,
|
|
161
278
|
/,
|
|
162
279
|
*,
|
|
163
|
-
connection: Optional["
|
|
280
|
+
connection: Optional["DuckDBConnection"] = None,
|
|
164
281
|
**kwargs: Any,
|
|
165
282
|
) -> int:
|
|
166
283
|
connection = self._connection(connection)
|
|
@@ -169,23 +286,44 @@ class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDrive
|
|
|
169
286
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
170
287
|
return getattr(cursor, "rowcount", -1) # pyright: ignore[reportUnknownMemberType]
|
|
171
288
|
|
|
289
|
+
@overload
|
|
172
290
|
def insert_update_delete_returning(
|
|
173
291
|
self,
|
|
174
292
|
sql: str,
|
|
175
|
-
parameters: Optional[
|
|
293
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
176
294
|
/,
|
|
177
295
|
*,
|
|
178
|
-
connection: Optional["
|
|
296
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
297
|
+
schema_type: None = None,
|
|
298
|
+
**kwargs: Any,
|
|
299
|
+
) -> "dict[str, Any]": ...
|
|
300
|
+
@overload
|
|
301
|
+
def insert_update_delete_returning(
|
|
302
|
+
self,
|
|
303
|
+
sql: str,
|
|
304
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
305
|
+
/,
|
|
306
|
+
*,
|
|
307
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
308
|
+
schema_type: "type[ModelDTOT]",
|
|
309
|
+
**kwargs: Any,
|
|
310
|
+
) -> "ModelDTOT": ...
|
|
311
|
+
def insert_update_delete_returning(
|
|
312
|
+
self,
|
|
313
|
+
sql: str,
|
|
314
|
+
parameters: "Optional[StatementParameterType]" = None,
|
|
315
|
+
/,
|
|
316
|
+
*,
|
|
317
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
179
318
|
schema_type: "Optional[type[ModelDTOT]]" = None,
|
|
180
319
|
**kwargs: Any,
|
|
181
|
-
) -> "
|
|
320
|
+
) -> "Union[ModelDTOT, dict[str, Any]]":
|
|
182
321
|
connection = self._connection(connection)
|
|
183
322
|
sql, parameters = self._process_sql_params(sql, parameters, **kwargs)
|
|
184
323
|
with self._with_cursor(connection) as cursor:
|
|
185
324
|
cursor.execute(sql, parameters) # pyright: ignore[reportUnknownMemberType]
|
|
186
325
|
result = cursor.fetchall() # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
|
|
187
|
-
|
|
188
|
-
return None # pyright: ignore[reportUnknownArgumentType]
|
|
326
|
+
result = self.check_not_found(result) # pyright: ignore
|
|
189
327
|
column_names = [col[0] for col in cursor.description or []] # pyright: ignore[reportUnknownMemberType,reportUnknownVariableType]
|
|
190
328
|
if schema_type is not None:
|
|
191
329
|
return cast("ModelDTOT", schema_type(**dict(zip(column_names, result[0])))) # pyright: ignore[reportUnknownArgumentType]
|
|
@@ -198,7 +336,7 @@ class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDrive
|
|
|
198
336
|
parameters: Optional["StatementParameterType"] = None,
|
|
199
337
|
/,
|
|
200
338
|
*,
|
|
201
|
-
connection: Optional["
|
|
339
|
+
connection: Optional["DuckDBConnection"] = None,
|
|
202
340
|
**kwargs: Any,
|
|
203
341
|
) -> str:
|
|
204
342
|
connection = self._connection(connection)
|
|
@@ -215,7 +353,7 @@ class DuckDBDriver(SyncArrowBulkOperationsMixin["DuckDBPyConnection"], SyncDrive
|
|
|
215
353
|
parameters: "Optional[StatementParameterType]" = None,
|
|
216
354
|
/,
|
|
217
355
|
*,
|
|
218
|
-
connection: "Optional[
|
|
356
|
+
connection: "Optional[DuckDBConnection]" = None,
|
|
219
357
|
**kwargs: Any,
|
|
220
358
|
) -> "ArrowTable":
|
|
221
359
|
connection = self._connection(connection)
|
|
@@ -4,13 +4,20 @@ from sqlspec.adapters.oracledb.config import (
|
|
|
4
4
|
OracleSyncConfig,
|
|
5
5
|
OracleSyncPoolConfig,
|
|
6
6
|
)
|
|
7
|
-
from sqlspec.adapters.oracledb.driver import
|
|
7
|
+
from sqlspec.adapters.oracledb.driver import (
|
|
8
|
+
OracleAsyncConnection,
|
|
9
|
+
OracleAsyncDriver,
|
|
10
|
+
OracleSyncConnection,
|
|
11
|
+
OracleSyncDriver,
|
|
12
|
+
)
|
|
8
13
|
|
|
9
14
|
__all__ = (
|
|
10
15
|
"OracleAsyncConfig",
|
|
16
|
+
"OracleAsyncConnection",
|
|
11
17
|
"OracleAsyncDriver",
|
|
12
18
|
"OracleAsyncPoolConfig",
|
|
13
19
|
"OracleSyncConfig",
|
|
20
|
+
"OracleSyncConnection",
|
|
14
21
|
"OracleSyncDriver",
|
|
15
22
|
"OracleSyncPoolConfig",
|
|
16
23
|
)
|
|
@@ -3,10 +3,9 @@ from dataclasses import dataclass, field
|
|
|
3
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
|
-
from oracledb.connection import AsyncConnection
|
|
7
6
|
|
|
8
7
|
from sqlspec.adapters.oracledb.config._common import OracleGenericPoolConfig
|
|
9
|
-
from sqlspec.adapters.oracledb.driver import OracleAsyncDriver
|
|
8
|
+
from sqlspec.adapters.oracledb.driver import OracleAsyncConnection, OracleAsyncDriver
|
|
10
9
|
from sqlspec.base import AsyncDatabaseConfig
|
|
11
10
|
from sqlspec.exceptions import ImproperConfigurationError
|
|
12
11
|
from sqlspec.typing import dataclass_to_dict
|
|
@@ -24,12 +23,12 @@ __all__ = (
|
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
@dataclass
|
|
27
|
-
class OracleAsyncPoolConfig(OracleGenericPoolConfig["
|
|
26
|
+
class OracleAsyncPoolConfig(OracleGenericPoolConfig["OracleAsyncConnection", "AsyncConnectionPool"]):
|
|
28
27
|
"""Async Oracle Pool Config"""
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
@dataclass
|
|
32
|
-
class OracleAsyncConfig(AsyncDatabaseConfig["
|
|
31
|
+
class OracleAsyncConfig(AsyncDatabaseConfig["OracleAsyncConnection", "AsyncConnectionPool", "OracleAsyncDriver"]):
|
|
33
32
|
"""Oracle Async database Configuration.
|
|
34
33
|
|
|
35
34
|
This class provides the base configuration for Oracle database connections, extending
|
|
@@ -49,7 +48,7 @@ class OracleAsyncConfig(AsyncDatabaseConfig["AsyncConnection", "AsyncConnectionP
|
|
|
49
48
|
|
|
50
49
|
If set, the plugin will use the provided pool rather than instantiate one.
|
|
51
50
|
"""
|
|
52
|
-
connection_type: "type[
|
|
51
|
+
connection_type: "type[OracleAsyncConnection]" = field(init=False, default_factory=lambda: OracleAsyncConnection)
|
|
53
52
|
"""Connection class to use.
|
|
54
53
|
|
|
55
54
|
Defaults to :class:`AsyncConnection`.
|
|
@@ -111,7 +110,7 @@ class OracleAsyncConfig(AsyncDatabaseConfig["AsyncConnection", "AsyncConnectionP
|
|
|
111
110
|
msg = "'pool_config' methods can not be used when a 'pool_instance' is provided."
|
|
112
111
|
raise ImproperConfigurationError(msg)
|
|
113
112
|
|
|
114
|
-
async def create_connection(self) -> "
|
|
113
|
+
async def create_connection(self) -> "OracleAsyncConnection":
|
|
115
114
|
"""Create and return a new oracledb async connection from the pool.
|
|
116
115
|
|
|
117
116
|
Returns:
|
|
@@ -122,7 +121,7 @@ class OracleAsyncConfig(AsyncDatabaseConfig["AsyncConnection", "AsyncConnectionP
|
|
|
122
121
|
"""
|
|
123
122
|
try:
|
|
124
123
|
pool = await self.provide_pool()
|
|
125
|
-
return cast("
|
|
124
|
+
return cast("OracleAsyncConnection", await pool.acquire()) # type: ignore[no-any-return,unused-ignore]
|
|
126
125
|
except Exception as e:
|
|
127
126
|
msg = f"Could not configure the Oracle async connection. Error: {e!s}"
|
|
128
127
|
raise ImproperConfigurationError(msg) from e
|
|
@@ -160,7 +159,7 @@ class OracleAsyncConfig(AsyncDatabaseConfig["AsyncConnection", "AsyncConnectionP
|
|
|
160
159
|
return self.create_pool()
|
|
161
160
|
|
|
162
161
|
@asynccontextmanager
|
|
163
|
-
async def provide_connection(self, *args: "Any", **kwargs: "Any") -> "AsyncGenerator[
|
|
162
|
+
async def provide_connection(self, *args: "Any", **kwargs: "Any") -> "AsyncGenerator[OracleAsyncConnection, None]":
|
|
164
163
|
"""Create a connection instance.
|
|
165
164
|
|
|
166
165
|
Yields:
|
|
@@ -3,10 +3,9 @@ from dataclasses import dataclass, field
|
|
|
3
3
|
from typing import TYPE_CHECKING, Any, Optional
|
|
4
4
|
|
|
5
5
|
from oracledb import create_pool as oracledb_create_pool # pyright: ignore[reportUnknownVariableType]
|
|
6
|
-
from oracledb.connection import Connection
|
|
7
6
|
|
|
8
7
|
from sqlspec.adapters.oracledb.config._common import OracleGenericPoolConfig
|
|
9
|
-
from sqlspec.adapters.oracledb.driver import OracleSyncDriver
|
|
8
|
+
from sqlspec.adapters.oracledb.driver import OracleSyncConnection, OracleSyncDriver
|
|
10
9
|
from sqlspec.base import SyncDatabaseConfig
|
|
11
10
|
from sqlspec.exceptions import ImproperConfigurationError
|
|
12
11
|
from sqlspec.typing import dataclass_to_dict
|
|
@@ -24,12 +23,12 @@ __all__ = (
|
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
@dataclass
|
|
27
|
-
class OracleSyncPoolConfig(OracleGenericPoolConfig["
|
|
26
|
+
class OracleSyncPoolConfig(OracleGenericPoolConfig["OracleSyncConnection", "ConnectionPool"]):
|
|
28
27
|
"""Sync Oracle Pool Config"""
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
@dataclass
|
|
32
|
-
class OracleSyncConfig(SyncDatabaseConfig["
|
|
31
|
+
class OracleSyncConfig(SyncDatabaseConfig["OracleSyncConnection", "ConnectionPool", "OracleSyncDriver"]):
|
|
33
32
|
"""Oracle Sync database Configuration.
|
|
34
33
|
|
|
35
34
|
This class provides the base configuration for Oracle database connections, extending
|
|
@@ -49,7 +48,7 @@ class OracleSyncConfig(SyncDatabaseConfig["Connection", "ConnectionPool", "Oracl
|
|
|
49
48
|
|
|
50
49
|
If set, the plugin will use the provided pool rather than instantiate one.
|
|
51
50
|
"""
|
|
52
|
-
connection_type: "type[
|
|
51
|
+
connection_type: "type[OracleSyncConnection]" = field(init=False, default_factory=lambda: OracleSyncConnection) # pyright: ignore
|
|
53
52
|
"""Connection class to use.
|
|
54
53
|
|
|
55
54
|
Defaults to :class:`Connection`.
|
|
@@ -111,7 +110,7 @@ class OracleSyncConfig(SyncDatabaseConfig["Connection", "ConnectionPool", "Oracl
|
|
|
111
110
|
msg = "'pool_config' methods can not be used when a 'pool_instance' is provided."
|
|
112
111
|
raise ImproperConfigurationError(msg)
|
|
113
112
|
|
|
114
|
-
def create_connection(self) -> "
|
|
113
|
+
def create_connection(self) -> "OracleSyncConnection":
|
|
115
114
|
"""Create and return a new oracledb connection from the pool.
|
|
116
115
|
|
|
117
116
|
Returns:
|
|
@@ -160,7 +159,7 @@ class OracleSyncConfig(SyncDatabaseConfig["Connection", "ConnectionPool", "Oracl
|
|
|
160
159
|
return self.create_pool()
|
|
161
160
|
|
|
162
161
|
@contextmanager
|
|
163
|
-
def provide_connection(self, *args: "Any", **kwargs: "Any") -> "Generator[
|
|
162
|
+
def provide_connection(self, *args: "Any", **kwargs: "Any") -> "Generator[OracleSyncConnection, None, None]":
|
|
164
163
|
"""Create a connection instance.
|
|
165
164
|
|
|
166
165
|
Yields:
|