sqlspec 0.8.0__tar.gz → 0.9.1__tar.gz
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-0.8.0 → sqlspec-0.9.1}/Makefile +2 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/PKG-INFO +144 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/README.md +141 -1
- {sqlspec-0.8.0 → sqlspec-0.9.1}/pyproject.toml +31 -4
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/_typing.py +39 -6
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/adbc/__init__.py +2 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/adbc/config.py +34 -11
- sqlspec-0.9.1/sqlspec/adapters/adbc/driver.py +524 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/aiosqlite/__init__.py +2 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/aiosqlite/config.py +2 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/aiosqlite/driver.py +164 -42
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/asyncmy/__init__.py +3 -3
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/asyncmy/config.py +11 -12
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/asyncmy/driver.py +161 -37
- sqlspec-0.9.1/sqlspec/adapters/asyncpg/__init__.py +9 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/asyncpg/config.py +17 -19
- sqlspec-0.9.1/sqlspec/adapters/asyncpg/driver.py +578 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/duckdb/__init__.py +2 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/duckdb/config.py +2 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/duckdb/driver.py +190 -60
- sqlspec-0.9.1/sqlspec/adapters/oracledb/__init__.py +16 -0
- sqlspec-0.9.1/sqlspec/adapters/oracledb/config/__init__.py +9 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/oracledb/config/_asyncio.py +9 -10
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/oracledb/config/_sync.py +8 -9
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/oracledb/driver.py +384 -45
- sqlspec-0.9.1/sqlspec/adapters/psqlpy/config.py +250 -0
- sqlspec-0.9.1/sqlspec/adapters/psqlpy/driver.py +481 -0
- sqlspec-0.9.1/sqlspec/adapters/psycopg/__init__.py +16 -0
- sqlspec-0.9.1/sqlspec/adapters/psycopg/config/__init__.py +9 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/psycopg/config/_async.py +12 -12
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/psycopg/config/_sync.py +13 -13
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/psycopg/driver.py +432 -222
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/sqlite/__init__.py +2 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/sqlite/config.py +2 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/sqlite/driver.py +176 -72
- sqlspec-0.9.1/sqlspec/base.py +1133 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/exceptions.py +30 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/extensions/litestar/config.py +6 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/extensions/litestar/handlers.py +25 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/extensions/litestar/plugin.py +8 -1
- sqlspec-0.9.1/sqlspec/statement.py +373 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/typing.py +10 -1
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/fixtures/sql_utils.py +4 -2
- sqlspec-0.9.1/tests/integration/__init__.py +3 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_adbc/__init__.py +4 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_adbc/conftest.py +3 -3
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_adbc/test_connection.py +4 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_adbc/test_driver_bigquery.py +54 -17
- sqlspec-0.9.1/tests/integration/test_adapters/test_adbc/test_driver_duckdb.py +444 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_adbc/test_driver_postgres.py +37 -3
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_adbc/test_driver_sqlite.py +125 -17
- sqlspec-0.9.1/tests/integration/test_adapters/test_aiosqlite/__init__.py +5 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_aiosqlite/test_connection.py +3 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_aiosqlite/test_driver.py +11 -24
- sqlspec-0.9.1/tests/integration/test_adapters/test_asyncmy/__init__.py +3 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_asyncmy/test_connection.py +6 -5
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_asyncmy/test_driver.py +15 -10
- sqlspec-0.9.1/tests/integration/test_adapters/test_asyncpg/test_connection.py +42 -0
- sqlspec-0.9.1/tests/integration/test_adapters/test_asyncpg/test_driver.py +275 -0
- sqlspec-0.9.1/tests/integration/test_adapters/test_duckdb/__init__.py +5 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_duckdb/test_connection.py +5 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_duckdb/test_driver.py +43 -9
- sqlspec-0.9.1/tests/integration/test_adapters/test_oracledb/__init__.py +5 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_oracledb/test_connection.py +11 -11
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_oracledb/test_driver_async.py +59 -24
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_oracledb/test_driver_sync.py +55 -21
- sqlspec-0.9.1/tests/integration/test_adapters/test_psqlpy/test_connection.py +66 -0
- sqlspec-0.9.1/tests/integration/test_adapters/test_psqlpy/test_driver.py +191 -0
- sqlspec-0.9.1/tests/integration/test_adapters/test_psycopg/__init__.py +5 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_psycopg/test_connection.py +36 -37
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_psycopg/test_driver.py +48 -41
- sqlspec-0.9.1/tests/integration/test_adapters/test_sqlite/__init__.py +5 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_sqlite/test_connection.py +5 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/test_sqlite/test_driver.py +6 -2
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_adbc/test_config.py +5 -7
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_aiosqlite/test_config.py +7 -7
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_asyncmy/test_config.py +8 -8
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_asyncpg/test_config.py +9 -9
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_duckdb/test_config.py +6 -6
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_oracledb/test_async_config.py +8 -8
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_oracledb/test_sync_config.py +8 -8
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_psycopg/test_async_config.py +5 -5
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_psycopg/test_sync_config.py +5 -5
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_sqlite/test_config.py +7 -7
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_base.py +24 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/uv.lock +113 -20
- sqlspec-0.8.0/sqlspec/adapters/adbc/driver.py +0 -333
- sqlspec-0.8.0/sqlspec/adapters/asyncpg/__init__.py +0 -9
- sqlspec-0.8.0/sqlspec/adapters/asyncpg/driver.py +0 -288
- sqlspec-0.8.0/sqlspec/adapters/oracledb/__init__.py +0 -16
- sqlspec-0.8.0/sqlspec/adapters/oracledb/config/__init__.py +0 -9
- sqlspec-0.8.0/sqlspec/adapters/psycopg/__init__.py +0 -11
- sqlspec-0.8.0/sqlspec/adapters/psycopg/config/__init__.py +0 -9
- sqlspec-0.8.0/sqlspec/base.py +0 -607
- sqlspec-0.8.0/tests/integration/test_adapters/test_adbc/test_driver_duckdb.py +0 -228
- sqlspec-0.8.0/tests/integration/test_adapters/test_aiosqlite/__init__.py +0 -1
- sqlspec-0.8.0/tests/integration/test_adapters/test_aiosqlite/conftest.py +0 -16
- sqlspec-0.8.0/tests/integration/test_adapters/test_duckdb/__init__.py +0 -1
- sqlspec-0.8.0/tests/integration/test_adapters/test_oracledb/__init__.py +0 -1
- sqlspec-0.8.0/tests/integration/test_adapters/test_psycopg/__init__.py +0 -1
- sqlspec-0.8.0/tests/integration/test_adapters/test_sqlite/__init__.py +0 -1
- {sqlspec-0.8.0 → sqlspec-0.9.1}/.gitignore +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/.pre-commit-config.yaml +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/CONTRIBUTING.rst +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/LICENSE +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/NOTICE +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/__metadata__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/_serialization.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/oracledb/config/_common.py +0 -0
- {sqlspec-0.8.0/sqlspec/extensions → sqlspec-0.9.1/sqlspec/adapters/psqlpy}/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/adapters/psycopg/config/_common.py +0 -0
- {sqlspec-0.8.0/tests → sqlspec-0.9.1/sqlspec/extensions}/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/extensions/litestar/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/extensions/litestar/_utils.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/filters.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/py.typed +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/utils/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/utils/deprecation.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/utils/fixtures.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/utils/module_loader.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/utils/sync_tools.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/sqlspec/utils/text.py +0 -0
- {sqlspec-0.8.0/tests/integration → sqlspec-0.9.1/tests}/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/conftest.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/fixtures/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/fixtures/example_usage.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/integration/test_adapters/__init__.py +0 -0
- {sqlspec-0.8.0/tests/integration/test_adapters/test_asyncmy → sqlspec-0.9.1/tests/integration/test_adapters/test_asyncpg}/__init__.py +0 -0
- {sqlspec-0.8.0/tests/unit → sqlspec-0.9.1/tests/integration/test_adapters/test_psqlpy}/__init__.py +0 -0
- {sqlspec-0.8.0/tests/unit/test_adapters → sqlspec-0.9.1/tests/unit}/__init__.py +0 -0
- {sqlspec-0.8.0/tests/unit/test_adapters/test_duckdb → sqlspec-0.9.1/tests/unit/test_adapters}/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_adbc/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_aiosqlite/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_asyncmy/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_asyncpg/__init__.py +0 -0
- {sqlspec-0.8.0/tests/unit/test_utils → sqlspec-0.9.1/tests/unit/test_adapters/test_duckdb}/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_oracledb/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_psycopg/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_adapters/test_sqlite/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_typing.py +0 -0
- {sqlspec-0.8.0/tools → sqlspec-0.9.1/tests/unit/test_utils}/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_utils/test_module_loader.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_utils/test_sync_tools.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tests/unit/test_utils/test_text.py +0 -0
- /sqlspec-0.8.0/tests/integration/test_adapters/test_psycopg/conftest.py → /sqlspec-0.9.1/tools/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tools/build_docs.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tools/pypi_readme.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tools/sphinx_ext/__init__.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tools/sphinx_ext/changelog.py +0 -0
- {sqlspec-0.8.0 → sqlspec-0.9.1}/tools/sphinx_ext/missing_references.py +0 -0
|
@@ -118,7 +118,7 @@ clean: ## Cleanup temporary build a
|
|
|
118
118
|
.PHONY: test
|
|
119
119
|
test: ## Run the tests
|
|
120
120
|
@echo "${INFO} Running test cases... 🧪"
|
|
121
|
-
@uv run pytest tests
|
|
121
|
+
@uv run pytest -n 2 --dist=loadgroup tests
|
|
122
122
|
@echo "${OK} Tests complete ✨"
|
|
123
123
|
|
|
124
124
|
.PHONY: test-all
|
|
@@ -128,7 +128,7 @@ test-all: tests ## Run all tests
|
|
|
128
128
|
.PHONY: coverage
|
|
129
129
|
coverage: ## Run tests with coverage report
|
|
130
130
|
@echo "${INFO} Running tests with coverage... 📊"
|
|
131
|
-
@uv run pytest --cov -n
|
|
131
|
+
@uv run pytest --cov -n 2 --dist=loadgroup --quiet
|
|
132
132
|
@uv run coverage html >/dev/null 2>&1
|
|
133
133
|
@uv run coverage xml >/dev/null 2>&1
|
|
134
134
|
@echo "${OK} Coverage report generated ✨"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlspec
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: SQL Experiments in Python
|
|
5
5
|
Author-email: Cody Fincher <cody@litestar.dev>
|
|
6
6
|
Maintainer-email: Litestar Developers <hello@litestar.dev>
|
|
@@ -42,6 +42,8 @@ Provides-Extra: orjson
|
|
|
42
42
|
Requires-Dist: orjson; extra == 'orjson'
|
|
43
43
|
Provides-Extra: performance
|
|
44
44
|
Requires-Dist: sqlglot[rs]; extra == 'performance'
|
|
45
|
+
Provides-Extra: psqlpy
|
|
46
|
+
Requires-Dist: psqlpy; extra == 'psqlpy'
|
|
45
47
|
Provides-Extra: psycopg
|
|
46
48
|
Requires-Dist: psycopg[binary,pool]; extra == 'psycopg'
|
|
47
49
|
Provides-Extra: pydantic
|
|
@@ -81,6 +83,145 @@ SQLSpec is an experimental Python library designed to streamline and modernize y
|
|
|
81
83
|
|
|
82
84
|
SQLSpec is a work in progress. While it offers a solid foundation for modern SQL interactions, it does not yet include every feature you might find in a mature ORM or database toolkit. The focus is on building a robust, flexible core that can be extended over time.
|
|
83
85
|
|
|
86
|
+
## Examples
|
|
87
|
+
|
|
88
|
+
We've talked about what SQLSpec is not, so let's look at what it can do.
|
|
89
|
+
|
|
90
|
+
These are just a few of the examples that demonstrate SQLSpec's flexibility and each of the bundled adapters offer the same config and driver interfaces.
|
|
91
|
+
|
|
92
|
+
### DuckDB LLM
|
|
93
|
+
|
|
94
|
+
This is a quick implementation using some of the built in Secret and Extension management features of SQLSpec's DuckDB integration.
|
|
95
|
+
|
|
96
|
+
It allows you to communicate with any compatible OpenAPI conversations endpoint (such as Ollama). This examples:
|
|
97
|
+
|
|
98
|
+
- auto installs the `open_prompt` DuckDB extensions
|
|
99
|
+
- automatically creates the correct `open_prompt` comptaible secret required to use the extension
|
|
100
|
+
|
|
101
|
+
```py
|
|
102
|
+
# /// script
|
|
103
|
+
# dependencies = [
|
|
104
|
+
# "sqlspec[duckdb,performance]",
|
|
105
|
+
# ]
|
|
106
|
+
# ///
|
|
107
|
+
import os
|
|
108
|
+
|
|
109
|
+
from sqlspec import SQLSpec
|
|
110
|
+
from sqlspec.adapters.duckdb import DuckDBConfig
|
|
111
|
+
from pydantic import BaseModel
|
|
112
|
+
|
|
113
|
+
class ChatMessage(BaseModel):
|
|
114
|
+
message: str
|
|
115
|
+
|
|
116
|
+
sql = SQLSpec()
|
|
117
|
+
etl_config = sql.add_config(
|
|
118
|
+
DuckDBConfig(
|
|
119
|
+
extensions=[{"name": "open_prompt"}],
|
|
120
|
+
secrets=[
|
|
121
|
+
{
|
|
122
|
+
"secret_type": "open_prompt",
|
|
123
|
+
"name": "open_prompt",
|
|
124
|
+
"value": {
|
|
125
|
+
"api_url": "http://127.0.0.1:11434/v1/chat/completions",
|
|
126
|
+
"model_name": "gemma3:1b",
|
|
127
|
+
"api_timeout": "120",
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
with sql.provide_session(etl_config) as session:
|
|
134
|
+
result = session.select_one("SELECT open_prompt(?)", data.message, schema_type=ChatMessage)
|
|
135
|
+
print(result) # result is a ChatMessage pydantic model
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### DuckDB Gemini Embeddings
|
|
139
|
+
|
|
140
|
+
In this example, we are again using DuckDB. However, we are going to use the built in to call the Google Gemini embeddings service directly from the database.
|
|
141
|
+
|
|
142
|
+
This example will
|
|
143
|
+
|
|
144
|
+
- auto installs the `http_client` and `vss` (vector similarity search) DuckDB extensions
|
|
145
|
+
- when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database.
|
|
146
|
+
- Execute a simple query to call the Google API
|
|
147
|
+
|
|
148
|
+
```py
|
|
149
|
+
# /// script
|
|
150
|
+
# dependencies = [
|
|
151
|
+
# "sqlspec[duckdb,performance]",
|
|
152
|
+
# ]
|
|
153
|
+
# ///
|
|
154
|
+
import os
|
|
155
|
+
|
|
156
|
+
from sqlspec import SQLSpec
|
|
157
|
+
from sqlspec.adapters.duckdb import DuckDBConfig
|
|
158
|
+
|
|
159
|
+
EMBEDDING_MODEL = "gemini-embedding-exp-03-07"
|
|
160
|
+
GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
|
|
161
|
+
API_URL = (
|
|
162
|
+
f"https://generativelanguage.googleapis.com/v1beta/models/{EMBEDDING_MODEL}:embedContent?key=${GOOGLE_API_KEY}"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
sql = SQLSpec()
|
|
166
|
+
etl_config = sql.add_config(
|
|
167
|
+
DuckDBConfig(
|
|
168
|
+
extensions=[{"name": "vss"}, {"name": "http_client"}],
|
|
169
|
+
on_connection_create=lambda connection: connection.execute(f"""
|
|
170
|
+
CREATE IF NOT EXISTS MACRO generate_embedding(q) AS (
|
|
171
|
+
WITH __request AS (
|
|
172
|
+
SELECT http_post(
|
|
173
|
+
'{API_URL}',
|
|
174
|
+
headers => MAP {{
|
|
175
|
+
'accept': 'application/json',
|
|
176
|
+
}},
|
|
177
|
+
params => MAP {{
|
|
178
|
+
'model': 'models/{EMBEDDING_MODEL}',
|
|
179
|
+
'parts': [{{ 'text': q }}],
|
|
180
|
+
'taskType': 'SEMANTIC_SIMILARITY'
|
|
181
|
+
}}
|
|
182
|
+
) AS response
|
|
183
|
+
)
|
|
184
|
+
SELECT *
|
|
185
|
+
FROM __request,
|
|
186
|
+
);
|
|
187
|
+
"""),
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
with sql.provide_session(etl_config) as session:
|
|
191
|
+
result = session.select_one("SELECT generate_embedding('example text')")
|
|
192
|
+
print(result) # result is a dictionary when `schema_type` is omitted.
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Basic Litestar Integration
|
|
196
|
+
|
|
197
|
+
In this example we are going to demonstrate how to create a basic configuration that integrates into Litestar.
|
|
198
|
+
|
|
199
|
+
```py
|
|
200
|
+
# /// script
|
|
201
|
+
# dependencies = [
|
|
202
|
+
# "sqlspec[aiosqlite]",
|
|
203
|
+
# "litestar[standard]",
|
|
204
|
+
# ]
|
|
205
|
+
# ///
|
|
206
|
+
|
|
207
|
+
from aiosqlite import Connection
|
|
208
|
+
from litestar import Litestar, get
|
|
209
|
+
|
|
210
|
+
from sqlspec.adapters.aiosqlite import AiosqliteConfig, AiosqliteDriver
|
|
211
|
+
from sqlspec.extensions.litestar import SQLSpec
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@get("/")
|
|
215
|
+
async def simple_sqlite(db_session: AiosqliteDriver) -> dict[str, str]:
|
|
216
|
+
return await db_session.select_one("SELECT 'Hello, world!' AS greeting")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
sqlspec = SQLSpec(config=DatabaseConfig(
|
|
220
|
+
config=[AiosqliteConfig(), commit_mode="autocommit")],
|
|
221
|
+
)
|
|
222
|
+
app = Litestar(route_handlers=[simple_sqlite], plugins=[sqlspec])
|
|
223
|
+
```
|
|
224
|
+
|
|
84
225
|
## Inspiration and Future Direction
|
|
85
226
|
|
|
86
227
|
SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executed SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
|
|
@@ -102,6 +243,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
|
|
|
102
243
|
| [`asyncpg`](https://magicstack.github.io/asyncpg/current/) | PostgreSQL | Async | ✅ |
|
|
103
244
|
| [`psycopg`](https://www.psycopg.org/) | PostgreSQL | Sync | ✅ |
|
|
104
245
|
| [`psycopg`](https://www.psycopg.org/) | PostgreSQL | Async | ✅ |
|
|
246
|
+
| [`psqlpy`](https://psqlpy-python.github.io/) | PostgreSQL | Async | ✅ |
|
|
105
247
|
| [`aiosqlite`](https://github.com/omnilib/aiosqlite) | SQLite | Async | ✅ |
|
|
106
248
|
| `sqlite3` | SQLite | Sync | ✅ |
|
|
107
249
|
| [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Async | ✅ |
|
|
@@ -118,7 +260,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
|
|
|
118
260
|
- `sqlspec/`:
|
|
119
261
|
- `adapters/`: Contains all database drivers and associated configuration.
|
|
120
262
|
- `extensions/`:
|
|
121
|
-
- `litestar/`:
|
|
263
|
+
- `litestar/`: Litestar framework integration ✅
|
|
122
264
|
- `fastapi/`: Future home of `fastapi` integration.
|
|
123
265
|
- `flask/`: Future home of `flask` integration.
|
|
124
266
|
- `*/`: Future home of your favorite framework integration 🔌 ✨
|
|
@@ -22,6 +22,145 @@ SQLSpec is an experimental Python library designed to streamline and modernize y
|
|
|
22
22
|
|
|
23
23
|
SQLSpec is a work in progress. While it offers a solid foundation for modern SQL interactions, it does not yet include every feature you might find in a mature ORM or database toolkit. The focus is on building a robust, flexible core that can be extended over time.
|
|
24
24
|
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
We've talked about what SQLSpec is not, so let's look at what it can do.
|
|
28
|
+
|
|
29
|
+
These are just a few of the examples that demonstrate SQLSpec's flexibility and each of the bundled adapters offer the same config and driver interfaces.
|
|
30
|
+
|
|
31
|
+
### DuckDB LLM
|
|
32
|
+
|
|
33
|
+
This is a quick implementation using some of the built in Secret and Extension management features of SQLSpec's DuckDB integration.
|
|
34
|
+
|
|
35
|
+
It allows you to communicate with any compatible OpenAPI conversations endpoint (such as Ollama). This examples:
|
|
36
|
+
|
|
37
|
+
- auto installs the `open_prompt` DuckDB extensions
|
|
38
|
+
- automatically creates the correct `open_prompt` comptaible secret required to use the extension
|
|
39
|
+
|
|
40
|
+
```py
|
|
41
|
+
# /// script
|
|
42
|
+
# dependencies = [
|
|
43
|
+
# "sqlspec[duckdb,performance]",
|
|
44
|
+
# ]
|
|
45
|
+
# ///
|
|
46
|
+
import os
|
|
47
|
+
|
|
48
|
+
from sqlspec import SQLSpec
|
|
49
|
+
from sqlspec.adapters.duckdb import DuckDBConfig
|
|
50
|
+
from pydantic import BaseModel
|
|
51
|
+
|
|
52
|
+
class ChatMessage(BaseModel):
|
|
53
|
+
message: str
|
|
54
|
+
|
|
55
|
+
sql = SQLSpec()
|
|
56
|
+
etl_config = sql.add_config(
|
|
57
|
+
DuckDBConfig(
|
|
58
|
+
extensions=[{"name": "open_prompt"}],
|
|
59
|
+
secrets=[
|
|
60
|
+
{
|
|
61
|
+
"secret_type": "open_prompt",
|
|
62
|
+
"name": "open_prompt",
|
|
63
|
+
"value": {
|
|
64
|
+
"api_url": "http://127.0.0.1:11434/v1/chat/completions",
|
|
65
|
+
"model_name": "gemma3:1b",
|
|
66
|
+
"api_timeout": "120",
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
with sql.provide_session(etl_config) as session:
|
|
73
|
+
result = session.select_one("SELECT open_prompt(?)", data.message, schema_type=ChatMessage)
|
|
74
|
+
print(result) # result is a ChatMessage pydantic model
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### DuckDB Gemini Embeddings
|
|
78
|
+
|
|
79
|
+
In this example, we are again using DuckDB. However, we are going to use the built in to call the Google Gemini embeddings service directly from the database.
|
|
80
|
+
|
|
81
|
+
This example will
|
|
82
|
+
|
|
83
|
+
- auto installs the `http_client` and `vss` (vector similarity search) DuckDB extensions
|
|
84
|
+
- when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database.
|
|
85
|
+
- Execute a simple query to call the Google API
|
|
86
|
+
|
|
87
|
+
```py
|
|
88
|
+
# /// script
|
|
89
|
+
# dependencies = [
|
|
90
|
+
# "sqlspec[duckdb,performance]",
|
|
91
|
+
# ]
|
|
92
|
+
# ///
|
|
93
|
+
import os
|
|
94
|
+
|
|
95
|
+
from sqlspec import SQLSpec
|
|
96
|
+
from sqlspec.adapters.duckdb import DuckDBConfig
|
|
97
|
+
|
|
98
|
+
EMBEDDING_MODEL = "gemini-embedding-exp-03-07"
|
|
99
|
+
GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
|
|
100
|
+
API_URL = (
|
|
101
|
+
f"https://generativelanguage.googleapis.com/v1beta/models/{EMBEDDING_MODEL}:embedContent?key=${GOOGLE_API_KEY}"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
sql = SQLSpec()
|
|
105
|
+
etl_config = sql.add_config(
|
|
106
|
+
DuckDBConfig(
|
|
107
|
+
extensions=[{"name": "vss"}, {"name": "http_client"}],
|
|
108
|
+
on_connection_create=lambda connection: connection.execute(f"""
|
|
109
|
+
CREATE IF NOT EXISTS MACRO generate_embedding(q) AS (
|
|
110
|
+
WITH __request AS (
|
|
111
|
+
SELECT http_post(
|
|
112
|
+
'{API_URL}',
|
|
113
|
+
headers => MAP {{
|
|
114
|
+
'accept': 'application/json',
|
|
115
|
+
}},
|
|
116
|
+
params => MAP {{
|
|
117
|
+
'model': 'models/{EMBEDDING_MODEL}',
|
|
118
|
+
'parts': [{{ 'text': q }}],
|
|
119
|
+
'taskType': 'SEMANTIC_SIMILARITY'
|
|
120
|
+
}}
|
|
121
|
+
) AS response
|
|
122
|
+
)
|
|
123
|
+
SELECT *
|
|
124
|
+
FROM __request,
|
|
125
|
+
);
|
|
126
|
+
"""),
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
with sql.provide_session(etl_config) as session:
|
|
130
|
+
result = session.select_one("SELECT generate_embedding('example text')")
|
|
131
|
+
print(result) # result is a dictionary when `schema_type` is omitted.
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Basic Litestar Integration
|
|
135
|
+
|
|
136
|
+
In this example we are going to demonstrate how to create a basic configuration that integrates into Litestar.
|
|
137
|
+
|
|
138
|
+
```py
|
|
139
|
+
# /// script
|
|
140
|
+
# dependencies = [
|
|
141
|
+
# "sqlspec[aiosqlite]",
|
|
142
|
+
# "litestar[standard]",
|
|
143
|
+
# ]
|
|
144
|
+
# ///
|
|
145
|
+
|
|
146
|
+
from aiosqlite import Connection
|
|
147
|
+
from litestar import Litestar, get
|
|
148
|
+
|
|
149
|
+
from sqlspec.adapters.aiosqlite import AiosqliteConfig, AiosqliteDriver
|
|
150
|
+
from sqlspec.extensions.litestar import SQLSpec
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@get("/")
|
|
154
|
+
async def simple_sqlite(db_session: AiosqliteDriver) -> dict[str, str]:
|
|
155
|
+
return await db_session.select_one("SELECT 'Hello, world!' AS greeting")
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
sqlspec = SQLSpec(config=DatabaseConfig(
|
|
159
|
+
config=[AiosqliteConfig(), commit_mode="autocommit")],
|
|
160
|
+
)
|
|
161
|
+
app = Litestar(route_handlers=[simple_sqlite], plugins=[sqlspec])
|
|
162
|
+
```
|
|
163
|
+
|
|
25
164
|
## Inspiration and Future Direction
|
|
26
165
|
|
|
27
166
|
SQLSpec originally drew inspiration from features found in the `aiosql` library. This is a great library for working with and executed SQL stored in files. It's unclear how much of an overlap there will be between the two libraries, but it's possible that some features will be contributed back to `aiosql` where appropriate.
|
|
@@ -43,6 +182,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
|
|
|
43
182
|
| [`asyncpg`](https://magicstack.github.io/asyncpg/current/) | PostgreSQL | Async | ✅ |
|
|
44
183
|
| [`psycopg`](https://www.psycopg.org/) | PostgreSQL | Sync | ✅ |
|
|
45
184
|
| [`psycopg`](https://www.psycopg.org/) | PostgreSQL | Async | ✅ |
|
|
185
|
+
| [`psqlpy`](https://psqlpy-python.github.io/) | PostgreSQL | Async | ✅ |
|
|
46
186
|
| [`aiosqlite`](https://github.com/omnilib/aiosqlite) | SQLite | Async | ✅ |
|
|
47
187
|
| `sqlite3` | SQLite | Sync | ✅ |
|
|
48
188
|
| [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Async | ✅ |
|
|
@@ -59,7 +199,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
|
|
|
59
199
|
- `sqlspec/`:
|
|
60
200
|
- `adapters/`: Contains all database drivers and associated configuration.
|
|
61
201
|
- `extensions/`:
|
|
62
|
-
- `litestar/`:
|
|
202
|
+
- `litestar/`: Litestar framework integration ✅
|
|
63
203
|
- `fastapi/`: Future home of `fastapi` integration.
|
|
64
204
|
- `flask/`: Future home of `flask` integration.
|
|
65
205
|
- `*/`: Future home of your favorite framework integration 🔌 ✨
|
|
@@ -7,7 +7,7 @@ maintainers = [{ name = "Litestar Developers", email = "hello@litestar.dev" }]
|
|
|
7
7
|
name = "sqlspec"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
requires-python = ">=3.9, <4.0"
|
|
10
|
-
version = "0.
|
|
10
|
+
version = "0.9.1"
|
|
11
11
|
|
|
12
12
|
[project.optional-dependencies]
|
|
13
13
|
adbc = ["adbc_driver_manager", "pyarrow"]
|
|
@@ -25,6 +25,7 @@ nanoid = ["fastnanoid>=0.4.1"]
|
|
|
25
25
|
oracledb = ["oracledb"]
|
|
26
26
|
orjson = ["orjson"]
|
|
27
27
|
performance = ["sqlglot[rs]"]
|
|
28
|
+
psqlpy = ["psqlpy"]
|
|
28
29
|
psycopg = ["psycopg[binary,pool]"]
|
|
29
30
|
pydantic = ["pydantic", "pydantic-extra-types"]
|
|
30
31
|
pymssql = ["pymssql"]
|
|
@@ -108,7 +109,7 @@ packages = ["sqlspec"]
|
|
|
108
109
|
allow_dirty = true
|
|
109
110
|
commit = false
|
|
110
111
|
commit_args = "--no-verify"
|
|
111
|
-
current_version = "0.
|
|
112
|
+
current_version = "0.9.1"
|
|
112
113
|
ignore_missing_files = false
|
|
113
114
|
ignore_missing_version = false
|
|
114
115
|
message = "chore(release): bump to v{new_version}"
|
|
@@ -175,7 +176,7 @@ exclude_lines = [
|
|
|
175
176
|
]
|
|
176
177
|
|
|
177
178
|
[tool.pytest.ini_options]
|
|
178
|
-
addopts = "-
|
|
179
|
+
addopts = ["-q", "-ra"]
|
|
179
180
|
asyncio_default_fixture_loop_scope = "function"
|
|
180
181
|
asyncio_mode = "auto"
|
|
181
182
|
filterwarnings = [
|
|
@@ -189,8 +190,32 @@ filterwarnings = [
|
|
|
189
190
|
"ignore::DeprecationWarning:websockets.connection",
|
|
190
191
|
"ignore::DeprecationWarning:websockets.legacy",
|
|
191
192
|
]
|
|
193
|
+
markers = [
|
|
194
|
+
"integration: marks tests that require an external database",
|
|
195
|
+
"postgres: marks tests specific to PostgreSQL",
|
|
196
|
+
"duckdb: marks tests specific to DuckDB",
|
|
197
|
+
"sqlite: marks tests specific to SQLite",
|
|
198
|
+
"bigquery: marks tests specific to Google BigQuery",
|
|
199
|
+
"mysql: marks tests specific to MySQL",
|
|
200
|
+
"oracle: marks tests specific to Oracle",
|
|
201
|
+
"spanner: marks tests specific to Google Cloud Spanner",
|
|
202
|
+
"mssql: marks tests specific to Microsoft SQL Server",
|
|
203
|
+
# Driver markers
|
|
204
|
+
"adbc: marks tests using ADBC drivers",
|
|
205
|
+
"aioodbc: marks tests using aioodbc",
|
|
206
|
+
"aiosqlite: marks tests using aiosqlite",
|
|
207
|
+
"asyncmy: marks tests using asyncmy",
|
|
208
|
+
"asyncpg: marks tests using asyncpg",
|
|
209
|
+
"duckdb_driver: marks tests using the duckdb driver",
|
|
210
|
+
"google_bigquery: marks tests using google-cloud-bigquery",
|
|
211
|
+
"google_spanner: marks tests using google-cloud-spanner",
|
|
212
|
+
"oracledb: marks tests using oracledb",
|
|
213
|
+
"psycopg: marks tests using psycopg",
|
|
214
|
+
"pymssql: marks tests using pymssql",
|
|
215
|
+
"pymysql: marks tests using pymysql",
|
|
216
|
+
"psqlpy: marks tests using psqlpy",
|
|
217
|
+
]
|
|
192
218
|
testpaths = ["tests"]
|
|
193
|
-
xfail_strict = true
|
|
194
219
|
|
|
195
220
|
[tool.mypy]
|
|
196
221
|
packages = ["sqlspec", "tests"]
|
|
@@ -220,6 +245,8 @@ module = [
|
|
|
220
245
|
"uvloop.*",
|
|
221
246
|
"asyncmy",
|
|
222
247
|
"asyncmy.*",
|
|
248
|
+
"pyarrow",
|
|
249
|
+
"pyarrow.*",
|
|
223
250
|
]
|
|
224
251
|
|
|
225
252
|
[tool.pyright]
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# ruff: noqa: RUF100, PLR0913, A002, DOC201, PLR6301
|
|
1
2
|
"""This is a simple wrapper around a few important classes in each library.
|
|
2
3
|
|
|
3
4
|
This is used to ensure compatibility when one or more of the libraries are installed.
|
|
4
5
|
"""
|
|
5
6
|
|
|
7
|
+
from collections.abc import Iterable, Mapping
|
|
6
8
|
from enum import Enum
|
|
7
9
|
from typing import (
|
|
8
10
|
Any,
|
|
@@ -96,7 +98,7 @@ except ImportError:
|
|
|
96
98
|
|
|
97
99
|
def validate_python(
|
|
98
100
|
self,
|
|
99
|
-
object: Any,
|
|
101
|
+
object: Any,
|
|
100
102
|
/,
|
|
101
103
|
*,
|
|
102
104
|
strict: "Optional[bool]" = None,
|
|
@@ -127,10 +129,7 @@ try:
|
|
|
127
129
|
except ImportError:
|
|
128
130
|
import enum
|
|
129
131
|
from collections.abc import Iterable
|
|
130
|
-
from typing import
|
|
131
|
-
|
|
132
|
-
if TYPE_CHECKING:
|
|
133
|
-
from collections.abc import Iterable
|
|
132
|
+
from typing import Callable, Optional, Union
|
|
134
133
|
|
|
135
134
|
@dataclass_transform()
|
|
136
135
|
@runtime_checkable
|
|
@@ -174,7 +173,6 @@ except ImportError:
|
|
|
174
173
|
"""Placeholder init"""
|
|
175
174
|
|
|
176
175
|
def create_instance(self, **kwargs: Any) -> "T":
|
|
177
|
-
"""Placeholder implementation"""
|
|
178
176
|
return cast("T", kwargs)
|
|
179
177
|
|
|
180
178
|
def update_instance(self, instance: "T", **kwargs: Any) -> "T":
|
|
@@ -198,11 +196,46 @@ EmptyType = Union[Literal[EmptyEnum.EMPTY], UnsetType]
|
|
|
198
196
|
Empty: Final = EmptyEnum.EMPTY
|
|
199
197
|
|
|
200
198
|
|
|
199
|
+
try:
|
|
200
|
+
from pyarrow import Table as ArrowTable
|
|
201
|
+
|
|
202
|
+
PYARROW_INSTALLED = True
|
|
203
|
+
except ImportError:
|
|
204
|
+
|
|
205
|
+
@runtime_checkable
|
|
206
|
+
class ArrowTable(Protocol): # type: ignore[no-redef]
|
|
207
|
+
"""Placeholder Implementation"""
|
|
208
|
+
|
|
209
|
+
def to_batches(self, batch_size: int) -> Any: ...
|
|
210
|
+
def num_rows(self) -> int: ...
|
|
211
|
+
def num_columns(self) -> int: ...
|
|
212
|
+
def to_pydict(self) -> dict[str, Any]: ...
|
|
213
|
+
def to_string(self) -> str: ...
|
|
214
|
+
def from_arrays(
|
|
215
|
+
self,
|
|
216
|
+
arrays: list[Any],
|
|
217
|
+
names: "Optional[list[str]]" = None,
|
|
218
|
+
schema: "Optional[Any]" = None,
|
|
219
|
+
metadata: "Optional[Mapping[str, Any]]" = None,
|
|
220
|
+
) -> Any: ...
|
|
221
|
+
def from_pydict(
|
|
222
|
+
self,
|
|
223
|
+
mapping: dict[str, Any],
|
|
224
|
+
schema: "Optional[Any]" = None,
|
|
225
|
+
metadata: "Optional[Mapping[str, Any]]" = None,
|
|
226
|
+
) -> Any: ...
|
|
227
|
+
def from_batches(self, batches: Iterable[Any], schema: Optional[Any] = None) -> Any: ...
|
|
228
|
+
|
|
229
|
+
PYARROW_INSTALLED = False # pyright: ignore[reportConstantRedefinition]
|
|
230
|
+
|
|
231
|
+
|
|
201
232
|
__all__ = (
|
|
202
233
|
"LITESTAR_INSTALLED",
|
|
203
234
|
"MSGSPEC_INSTALLED",
|
|
235
|
+
"PYARROW_INSTALLED",
|
|
204
236
|
"PYDANTIC_INSTALLED",
|
|
205
237
|
"UNSET",
|
|
238
|
+
"ArrowTable",
|
|
206
239
|
"BaseModel",
|
|
207
240
|
"DTOData",
|
|
208
241
|
"DataclassProtocol",
|
|
@@ -14,11 +14,11 @@ if TYPE_CHECKING:
|
|
|
14
14
|
from collections.abc import Generator
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
__all__ = ("
|
|
17
|
+
__all__ = ("AdbcConfig",)
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
@dataclass
|
|
21
|
-
class
|
|
21
|
+
class AdbcConfig(NoPoolSyncConfig["Connection", "AdbcDriver"]):
|
|
22
22
|
"""Configuration for ADBC connections.
|
|
23
23
|
|
|
24
24
|
This class provides configuration options for ADBC database connections using the
|
|
@@ -55,17 +55,41 @@ class Adbc(NoPoolSyncConfig["Connection", "AdbcDriver"]):
|
|
|
55
55
|
"""
|
|
56
56
|
|
|
57
57
|
if isinstance(self.driver_name, str):
|
|
58
|
-
if self.driver_name != "adbc_driver_sqlite.dbapi.connect" and
|
|
58
|
+
if self.driver_name != "adbc_driver_sqlite.dbapi.connect" and self.driver_name in {
|
|
59
|
+
"sqlite",
|
|
60
|
+
"sqlite3",
|
|
61
|
+
"adbc_driver_sqlite",
|
|
62
|
+
}:
|
|
59
63
|
self.driver_name = "adbc_driver_sqlite.dbapi.connect"
|
|
60
|
-
elif self.driver_name != "adbc_driver_duckdb.dbapi.connect" and
|
|
64
|
+
elif self.driver_name != "adbc_driver_duckdb.dbapi.connect" and self.driver_name in {
|
|
65
|
+
"duckdb",
|
|
66
|
+
"adbc_driver_duckdb",
|
|
67
|
+
}:
|
|
61
68
|
self.driver_name = "adbc_driver_duckdb.dbapi.connect"
|
|
62
|
-
elif self.driver_name != "adbc_driver_postgresql.dbapi.connect" and
|
|
69
|
+
elif self.driver_name != "adbc_driver_postgresql.dbapi.connect" and self.driver_name in {
|
|
70
|
+
"postgres",
|
|
71
|
+
"adbc_driver_postgresql",
|
|
72
|
+
"postgresql",
|
|
73
|
+
"pg",
|
|
74
|
+
}:
|
|
63
75
|
self.driver_name = "adbc_driver_postgresql.dbapi.connect"
|
|
64
|
-
elif self.driver_name != "adbc_driver_snowflake.dbapi.connect" and
|
|
76
|
+
elif self.driver_name != "adbc_driver_snowflake.dbapi.connect" and self.driver_name in {
|
|
77
|
+
"snowflake",
|
|
78
|
+
"adbc_driver_snowflake",
|
|
79
|
+
"sf",
|
|
80
|
+
}:
|
|
65
81
|
self.driver_name = "adbc_driver_snowflake.dbapi.connect"
|
|
66
|
-
elif self.driver_name != "adbc_driver_bigquery.dbapi.connect" and
|
|
82
|
+
elif self.driver_name != "adbc_driver_bigquery.dbapi.connect" and self.driver_name in {
|
|
83
|
+
"bigquery",
|
|
84
|
+
"adbc_driver_bigquery",
|
|
85
|
+
"bq",
|
|
86
|
+
}:
|
|
67
87
|
self.driver_name = "adbc_driver_bigquery.dbapi.connect"
|
|
68
|
-
elif self.driver_name != "adbc_driver_flightsql.dbapi.connect" and
|
|
88
|
+
elif self.driver_name != "adbc_driver_flightsql.dbapi.connect" and self.driver_name in {
|
|
89
|
+
"flightsql",
|
|
90
|
+
"adbc_driver_flightsql",
|
|
91
|
+
"grpc",
|
|
92
|
+
}:
|
|
69
93
|
self.driver_name = "adbc_driver_flightsql.dbapi.connect"
|
|
70
94
|
return self.driver_name
|
|
71
95
|
|
|
@@ -153,11 +177,10 @@ class Adbc(NoPoolSyncConfig["Connection", "AdbcDriver"]):
|
|
|
153
177
|
"""
|
|
154
178
|
try:
|
|
155
179
|
connect_func = self._get_connect_func()
|
|
156
|
-
|
|
157
|
-
return connect_func(**_config)
|
|
180
|
+
return connect_func(**self.connection_config_dict)
|
|
158
181
|
except Exception as e:
|
|
159
182
|
# Include driver name in error message for better context
|
|
160
|
-
driver_name = self.driver_name if isinstance(self.driver_name, str) else "Unknown/
|
|
183
|
+
driver_name = self.driver_name if isinstance(self.driver_name, str) else "Unknown/Missing"
|
|
161
184
|
# Use the potentially modified driver_path from _get_connect_func if available,
|
|
162
185
|
# otherwise fallback to self.driver_name for the error message.
|
|
163
186
|
# This requires _get_connect_func to potentially return the used path or store it.
|