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.

Files changed (47) hide show
  1. sqlspec/__init__.py +2 -1
  2. sqlspec/adapters/adbc/__init__.py +2 -1
  3. sqlspec/adapters/adbc/config.py +7 -13
  4. sqlspec/adapters/adbc/driver.py +160 -21
  5. sqlspec/adapters/aiosqlite/__init__.py +2 -1
  6. sqlspec/adapters/aiosqlite/config.py +10 -12
  7. sqlspec/adapters/aiosqlite/driver.py +160 -22
  8. sqlspec/adapters/asyncmy/__init__.py +2 -1
  9. sqlspec/adapters/asyncmy/driver.py +158 -22
  10. sqlspec/adapters/asyncpg/config.py +1 -3
  11. sqlspec/adapters/asyncpg/driver.py +143 -5
  12. sqlspec/adapters/bigquery/__init__.py +4 -0
  13. sqlspec/adapters/bigquery/config/__init__.py +3 -0
  14. sqlspec/adapters/bigquery/config/_common.py +40 -0
  15. sqlspec/adapters/bigquery/config/_sync.py +87 -0
  16. sqlspec/adapters/bigquery/driver.py +701 -0
  17. sqlspec/adapters/duckdb/__init__.py +2 -1
  18. sqlspec/adapters/duckdb/config.py +17 -18
  19. sqlspec/adapters/duckdb/driver.py +165 -27
  20. sqlspec/adapters/oracledb/__init__.py +8 -1
  21. sqlspec/adapters/oracledb/config/_asyncio.py +7 -8
  22. sqlspec/adapters/oracledb/config/_sync.py +6 -7
  23. sqlspec/adapters/oracledb/driver.py +311 -42
  24. sqlspec/adapters/psqlpy/__init__.py +9 -0
  25. sqlspec/adapters/psqlpy/config.py +11 -19
  26. sqlspec/adapters/psqlpy/driver.py +171 -19
  27. sqlspec/adapters/psycopg/__init__.py +8 -1
  28. sqlspec/adapters/psycopg/config/__init__.py +10 -0
  29. sqlspec/adapters/psycopg/config/_async.py +6 -7
  30. sqlspec/adapters/psycopg/config/_sync.py +7 -8
  31. sqlspec/adapters/psycopg/driver.py +344 -86
  32. sqlspec/adapters/sqlite/__init__.py +2 -1
  33. sqlspec/adapters/sqlite/config.py +12 -11
  34. sqlspec/adapters/sqlite/driver.py +160 -51
  35. sqlspec/base.py +402 -63
  36. sqlspec/exceptions.py +9 -0
  37. sqlspec/extensions/litestar/config.py +3 -11
  38. sqlspec/extensions/litestar/handlers.py +2 -1
  39. sqlspec/extensions/litestar/plugin.py +6 -2
  40. sqlspec/mixins.py +156 -0
  41. sqlspec/typing.py +19 -1
  42. {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/METADATA +147 -3
  43. sqlspec-0.10.0.dist-info/RECORD +67 -0
  44. sqlspec-0.9.0.dist-info/RECORD +0 -61
  45. {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/WHEEL +0 -0
  46. {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/licenses/LICENSE +0 -0
  47. {sqlspec-0.9.0.dist-info → sqlspec-0.10.0.dist-info}/licenses/NOTICE +0 -0
@@ -1,19 +1,22 @@
1
1
  import logging
2
2
  import re
3
- from typing import TYPE_CHECKING, Any, Optional, Union, cast
3
+ from typing import TYPE_CHECKING, Any, Optional, Union, cast, overload
4
4
 
5
5
  from asyncpg import Connection
6
6
  from typing_extensions import TypeAlias
7
7
 
8
- from sqlspec.base import AsyncDriverAdapterProtocol, T
8
+ from sqlspec.base import AsyncDriverAdapterProtocol
9
9
  from sqlspec.exceptions import SQLParsingError
10
+ from sqlspec.mixins import SQLTranslatorMixin
10
11
  from sqlspec.statement import PARAM_REGEX, SQLStatement
11
12
 
12
13
  if TYPE_CHECKING:
14
+ from collections.abc import Sequence
15
+
13
16
  from asyncpg.connection import Connection
14
17
  from asyncpg.pool import PoolConnectionProxy
15
18
 
16
- from sqlspec.typing import ModelDTOT, StatementParameterType
19
+ from sqlspec.typing import ModelDTOT, StatementParameterType, T
17
20
 
18
21
  __all__ = ("AsyncpgConnection", "AsyncpgDriver")
19
22
 
@@ -33,7 +36,10 @@ QMARK_REGEX = re.compile(
33
36
  AsyncpgConnection: TypeAlias = "Union[Connection[Any], PoolConnectionProxy[Any]]" # pyright: ignore[reportMissingTypeArgument]
34
37
 
35
38
 
36
- class AsyncpgDriver(AsyncDriverAdapterProtocol["AsyncpgConnection"]):
39
+ class AsyncpgDriver(
40
+ SQLTranslatorMixin["AsyncpgConnection"],
41
+ AsyncDriverAdapterProtocol["AsyncpgConnection"],
42
+ ):
37
43
  """AsyncPG Postgres Driver Adapter."""
38
44
 
39
45
  connection: "AsyncpgConnection"
@@ -196,6 +202,28 @@ class AsyncpgDriver(AsyncDriverAdapterProtocol["AsyncpgConnection"]):
196
202
  # No parameters provided and none found in SQL, return original SQL from SQLStatement and empty tuple
197
203
  return sql, () # asyncpg expects a sequence, even if empty
198
204
 
205
+ @overload
206
+ async def select(
207
+ self,
208
+ sql: str,
209
+ parameters: "Optional[StatementParameterType]" = None,
210
+ /,
211
+ *,
212
+ connection: "Optional[AsyncpgConnection]" = None,
213
+ schema_type: None = None,
214
+ **kwargs: Any,
215
+ ) -> "Sequence[dict[str, Any]]": ...
216
+ @overload
217
+ async def select(
218
+ self,
219
+ sql: str,
220
+ parameters: "Optional[StatementParameterType]" = None,
221
+ /,
222
+ *,
223
+ connection: "Optional[AsyncpgConnection]" = None,
224
+ schema_type: "type[ModelDTOT]",
225
+ **kwargs: Any,
226
+ ) -> "Sequence[ModelDTOT]": ...
199
227
  async def select(
200
228
  self,
201
229
  sql: str,
@@ -205,7 +233,7 @@ class AsyncpgDriver(AsyncDriverAdapterProtocol["AsyncpgConnection"]):
205
233
  connection: Optional["AsyncpgConnection"] = None,
206
234
  schema_type: "Optional[type[ModelDTOT]]" = None,
207
235
  **kwargs: Any,
208
- ) -> "list[Union[ModelDTOT, dict[str, Any]]]":
236
+ ) -> "Sequence[Union[ModelDTOT, dict[str, Any]]]":
209
237
  """Fetch data from the database.
210
238
 
211
239
  Args:
@@ -229,6 +257,28 @@ class AsyncpgDriver(AsyncDriverAdapterProtocol["AsyncpgConnection"]):
229
257
  return [dict(row.items()) for row in results] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
230
258
  return [cast("ModelDTOT", schema_type(**dict(row.items()))) for row in results] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType]
231
259
 
260
+ @overload
261
+ async def select_one(
262
+ self,
263
+ sql: str,
264
+ parameters: "Optional[StatementParameterType]" = None,
265
+ /,
266
+ *,
267
+ connection: "Optional[AsyncpgConnection]" = None,
268
+ schema_type: None = None,
269
+ **kwargs: Any,
270
+ ) -> "dict[str, Any]": ...
271
+ @overload
272
+ async def select_one(
273
+ self,
274
+ sql: str,
275
+ parameters: "Optional[StatementParameterType]" = None,
276
+ /,
277
+ *,
278
+ connection: "Optional[AsyncpgConnection]" = None,
279
+ schema_type: "type[ModelDTOT]",
280
+ **kwargs: Any,
281
+ ) -> "ModelDTOT": ...
232
282
  async def select_one(
233
283
  self,
234
284
  sql: str,
@@ -262,6 +312,28 @@ class AsyncpgDriver(AsyncDriverAdapterProtocol["AsyncpgConnection"]):
262
312
  return dict(result.items()) # type: ignore[attr-defined]
263
313
  return cast("ModelDTOT", schema_type(**dict(result.items()))) # type: ignore[attr-defined]
264
314
 
315
+ @overload
316
+ async def select_one_or_none(
317
+ self,
318
+ sql: str,
319
+ parameters: "Optional[StatementParameterType]" = None,
320
+ /,
321
+ *,
322
+ connection: "Optional[AsyncpgConnection]" = None,
323
+ schema_type: None = None,
324
+ **kwargs: Any,
325
+ ) -> "Optional[dict[str, Any]]": ...
326
+ @overload
327
+ async def select_one_or_none(
328
+ self,
329
+ sql: str,
330
+ parameters: "Optional[StatementParameterType]" = None,
331
+ /,
332
+ *,
333
+ connection: "Optional[AsyncpgConnection]" = None,
334
+ schema_type: "type[ModelDTOT]",
335
+ **kwargs: Any,
336
+ ) -> "Optional[ModelDTOT]": ...
265
337
  async def select_one_or_none(
266
338
  self,
267
339
  sql: str,
@@ -295,6 +367,28 @@ class AsyncpgDriver(AsyncDriverAdapterProtocol["AsyncpgConnection"]):
295
367
  return dict(result.items())
296
368
  return cast("ModelDTOT", schema_type(**dict(result.items())))
297
369
 
370
+ @overload
371
+ async def select_value(
372
+ self,
373
+ sql: str,
374
+ parameters: "Optional[StatementParameterType]" = None,
375
+ /,
376
+ *,
377
+ connection: "Optional[AsyncpgConnection]" = None,
378
+ schema_type: None = None,
379
+ **kwargs: Any,
380
+ ) -> "Any": ...
381
+ @overload
382
+ async def select_value(
383
+ self,
384
+ sql: str,
385
+ parameters: "Optional[StatementParameterType]" = None,
386
+ /,
387
+ *,
388
+ connection: "Optional[AsyncpgConnection]" = None,
389
+ schema_type: "type[T]",
390
+ **kwargs: Any,
391
+ ) -> "T": ...
298
392
  async def select_value(
299
393
  self,
300
394
  sql: str,
@@ -326,6 +420,28 @@ class AsyncpgDriver(AsyncDriverAdapterProtocol["AsyncpgConnection"]):
326
420
  return result
327
421
  return schema_type(result) # type: ignore[call-arg]
328
422
 
423
+ @overload
424
+ async def select_value_or_none(
425
+ self,
426
+ sql: str,
427
+ parameters: "Optional[StatementParameterType]" = None,
428
+ /,
429
+ *,
430
+ connection: "Optional[AsyncpgConnection]" = None,
431
+ schema_type: None = None,
432
+ **kwargs: Any,
433
+ ) -> "Optional[Any]": ...
434
+ @overload
435
+ async def select_value_or_none(
436
+ self,
437
+ sql: str,
438
+ parameters: "Optional[StatementParameterType]" = None,
439
+ /,
440
+ *,
441
+ connection: "Optional[AsyncpgConnection]" = None,
442
+ schema_type: "type[T]",
443
+ **kwargs: Any,
444
+ ) -> "Optional[T]": ...
329
445
  async def select_value_or_none(
330
446
  self,
331
447
  sql: str,
@@ -381,6 +497,28 @@ class AsyncpgDriver(AsyncDriverAdapterProtocol["AsyncpgConnection"]):
381
497
  except (ValueError, IndexError, AttributeError):
382
498
  return -1 # Fallback if we can't parse the status
383
499
 
500
+ @overload
501
+ async def insert_update_delete_returning(
502
+ self,
503
+ sql: str,
504
+ parameters: "Optional[StatementParameterType]" = None,
505
+ /,
506
+ *,
507
+ connection: "Optional[AsyncpgConnection]" = None,
508
+ schema_type: None = None,
509
+ **kwargs: Any,
510
+ ) -> "dict[str, Any]": ...
511
+ @overload
512
+ async def insert_update_delete_returning(
513
+ self,
514
+ sql: str,
515
+ parameters: "Optional[StatementParameterType]" = None,
516
+ /,
517
+ *,
518
+ connection: "Optional[AsyncpgConnection]" = None,
519
+ schema_type: "type[ModelDTOT]",
520
+ **kwargs: Any,
521
+ ) -> "ModelDTOT": ...
384
522
  async def insert_update_delete_returning(
385
523
  self,
386
524
  sql: str,
@@ -0,0 +1,4 @@
1
+ from sqlspec.adapters.bigquery.config import BigQueryConfig, BigQueryConnectionConfig
2
+ from sqlspec.adapters.bigquery.driver import BigQueryConnection, BigQueryDriver
3
+
4
+ __all__ = ("BigQueryConfig", "BigQueryConnection", "BigQueryConnectionConfig", "BigQueryDriver")
@@ -0,0 +1,3 @@
1
+ from sqlspec.adapters.bigquery.config._sync import BigQueryConfig, BigQueryConnectionConfig
2
+
3
+ __all__ = ("BigQueryConfig", "BigQueryConnectionConfig")
@@ -0,0 +1,40 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import TYPE_CHECKING, Optional
3
+
4
+ from google.cloud.bigquery import LoadJobConfig, QueryJobConfig
5
+
6
+ if TYPE_CHECKING:
7
+ from google.api_core.client_info import ClientInfo
8
+ from google.api_core.client_options import ClientOptions
9
+ from google.auth.credentials import Credentials
10
+
11
+ __all__ = ("BigQueryConnectionConfigCommon",)
12
+
13
+
14
+ @dataclass
15
+ class BigQueryConnectionConfigCommon:
16
+ """Common configuration options for BigQuery."""
17
+
18
+ project: "Optional[str]" = field(default=None)
19
+ """Google Cloud project ID."""
20
+ location: "Optional[str]" = field(default=None)
21
+ """Default geographic location for jobs and datasets."""
22
+ credentials: "Optional[Credentials]" = field(default=None, hash=False)
23
+ """Credentials to use for authentication."""
24
+ dataset_id: "Optional[str]" = field(default=None)
25
+ """Default dataset ID to use if not specified in queries."""
26
+ credentials_path: "Optional[str]" = field(default=None)
27
+ """Path to Google Cloud service account key file (JSON). If None, attempts default authentication."""
28
+ client_options: "Optional[ClientOptions]" = field(default=None, hash=False)
29
+ """Client options used to set user options on the client (e.g., api_endpoint)."""
30
+ default_query_job_config: "Optional[QueryJobConfig]" = field(default=None, hash=False)
31
+ """Default QueryJobConfig settings."""
32
+ default_load_job_config: "Optional[LoadJobConfig]" = field(default=None, hash=False)
33
+ """Default LoadJobConfig settings."""
34
+ client_info: "Optional[ClientInfo]" = field(default=None, hash=False)
35
+ """Client info used to send a user-agent string along with API requests."""
36
+
37
+ def __post_init__(self) -> None:
38
+ """Post-initialization hook."""
39
+ if self.default_query_job_config is None:
40
+ self.default_query_job_config = QueryJobConfig(default_dataset=self.dataset_id)
@@ -0,0 +1,87 @@
1
+ import contextlib
2
+ from dataclasses import dataclass, field
3
+ from typing import TYPE_CHECKING, Any, Optional
4
+
5
+ from sqlspec.adapters.bigquery.config._common import BigQueryConnectionConfigCommon
6
+ from sqlspec.adapters.bigquery.driver import BigQueryConnection, BigQueryDriver
7
+ from sqlspec.base import NoPoolSyncConfig
8
+ from sqlspec.typing import dataclass_to_dict
9
+
10
+ if TYPE_CHECKING:
11
+ from collections.abc import Iterator
12
+
13
+ __all__ = ("BigQueryConfig", "BigQueryConnectionConfig")
14
+
15
+
16
+ class BigQueryConnectionConfig(BigQueryConnectionConfigCommon):
17
+ """BigQuery Connection Configuration."""
18
+
19
+
20
+ @dataclass
21
+ class BigQueryConfig(NoPoolSyncConfig["BigQueryConnection", "BigQueryDriver"]):
22
+ """BigQuery Synchronous Driver Configuration."""
23
+
24
+ connection_config: "BigQueryConnectionConfig" = field(default_factory=BigQueryConnectionConfig)
25
+ """BigQuery Connection Configuration."""
26
+ driver_type: "type[BigQueryDriver]" = field(init=False, repr=False, default=BigQueryDriver)
27
+ """BigQuery Driver Type."""
28
+ connection_type: "type[BigQueryConnection]" = field(init=False, repr=False, default=BigQueryConnection)
29
+ """BigQuery Connection Type."""
30
+ pool_instance: "None" = field(init=False, repr=False, default=None, hash=False)
31
+ """This is set to have a init=False since BigQuery does not support pooling."""
32
+ connection_instance: "Optional[BigQueryConnection]" = field(init=False, repr=False, default=None, hash=False)
33
+ """BigQuery Connection Instance."""
34
+
35
+ @property
36
+ def connection_config_dict(self) -> "dict[str, Any]":
37
+ """Return the connection configuration as a dict.
38
+
39
+ Returns:
40
+ A string keyed dict of config kwargs for the BigQueryConnection constructor.
41
+ """
42
+ return dataclass_to_dict(
43
+ self.connection_config,
44
+ exclude_empty=True,
45
+ exclude_none=True,
46
+ exclude={"dataset_id", "credentials_path"},
47
+ )
48
+
49
+ def create_connection(self) -> "BigQueryConnection":
50
+ """Create a BigQuery Client instance.
51
+
52
+ Returns:
53
+ A BigQuery Client instance.
54
+ """
55
+ if self.connection_instance is not None:
56
+ return self.connection_instance
57
+
58
+ self.connection_instance = self.connection_type(**self.connection_config_dict)
59
+ return self.connection_instance
60
+
61
+ @contextlib.contextmanager
62
+ def provide_connection(self, *args: Any, **kwargs: Any) -> "Iterator[BigQueryConnection]":
63
+ """Provide a BigQuery client within a context manager.
64
+
65
+ Args:
66
+ *args: Additional arguments to pass to the connection.
67
+ **kwargs: Additional keyword arguments to pass to the connection.
68
+
69
+ Yields:
70
+ An iterator of BigQuery Client instances.
71
+ """
72
+ conn = self.create_connection()
73
+ yield conn
74
+
75
+ @contextlib.contextmanager
76
+ def provide_session(self, *args: Any, **kwargs: Any) -> "Iterator[BigQueryDriver]":
77
+ """Provide a BigQuery driver session within a context manager.
78
+
79
+ Args:
80
+ *args: Additional arguments to pass to the driver.
81
+ **kwargs: Additional keyword arguments to pass to the driver.
82
+
83
+ Yields:
84
+ An iterator of BigQueryDriver instances.
85
+ """
86
+ conn = self.create_connection()
87
+ yield self.driver_type(connection=conn)