sqlspec 0.9.0__tar.gz → 0.10.0__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.

Files changed (147) hide show
  1. {sqlspec-0.9.0 → sqlspec-0.10.0}/PKG-INFO +147 -3
  2. {sqlspec-0.9.0 → sqlspec-0.10.0}/README.md +145 -2
  3. {sqlspec-0.9.0 → sqlspec-0.10.0}/pyproject.toml +3 -3
  4. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/__init__.py +2 -1
  5. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/adbc/__init__.py +2 -1
  6. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/adbc/config.py +7 -13
  7. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/adbc/driver.py +160 -21
  8. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/aiosqlite/__init__.py +2 -1
  9. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/aiosqlite/config.py +10 -12
  10. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/aiosqlite/driver.py +160 -22
  11. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/asyncmy/__init__.py +2 -1
  12. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/asyncmy/driver.py +158 -22
  13. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/asyncpg/config.py +1 -3
  14. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/asyncpg/driver.py +143 -5
  15. sqlspec-0.10.0/sqlspec/adapters/bigquery/__init__.py +4 -0
  16. sqlspec-0.10.0/sqlspec/adapters/bigquery/config/__init__.py +3 -0
  17. sqlspec-0.10.0/sqlspec/adapters/bigquery/config/_common.py +40 -0
  18. sqlspec-0.10.0/sqlspec/adapters/bigquery/config/_sync.py +87 -0
  19. sqlspec-0.10.0/sqlspec/adapters/bigquery/driver.py +701 -0
  20. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/duckdb/__init__.py +2 -1
  21. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/duckdb/config.py +17 -18
  22. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/duckdb/driver.py +165 -27
  23. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/oracledb/__init__.py +8 -1
  24. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/oracledb/config/_asyncio.py +7 -8
  25. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/oracledb/config/_sync.py +6 -7
  26. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/oracledb/driver.py +311 -42
  27. sqlspec-0.10.0/sqlspec/adapters/psqlpy/__init__.py +9 -0
  28. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/psqlpy/config.py +11 -19
  29. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/psqlpy/driver.py +171 -19
  30. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/psycopg/__init__.py +8 -1
  31. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/psycopg/config/__init__.py +10 -0
  32. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/psycopg/config/_async.py +6 -7
  33. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/psycopg/config/_sync.py +7 -8
  34. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/psycopg/driver.py +344 -86
  35. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/sqlite/__init__.py +2 -1
  36. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/sqlite/config.py +12 -11
  37. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/sqlite/driver.py +160 -51
  38. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/base.py +402 -63
  39. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/exceptions.py +9 -0
  40. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/extensions/litestar/config.py +3 -11
  41. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/extensions/litestar/handlers.py +2 -1
  42. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/extensions/litestar/plugin.py +6 -2
  43. sqlspec-0.10.0/sqlspec/mixins.py +156 -0
  44. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/typing.py +19 -1
  45. sqlspec-0.10.0/tests/integration/test_adapters/test_bigquery/conftest.py +31 -0
  46. sqlspec-0.10.0/tests/integration/test_adapters/test_bigquery/test_connection.py +14 -0
  47. sqlspec-0.10.0/tests/integration/test_adapters/test_bigquery/test_driver.py +288 -0
  48. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_aiosqlite/test_config.py +0 -3
  49. {sqlspec-0.9.0 → sqlspec-0.10.0}/uv.lock +9 -7
  50. {sqlspec-0.9.0 → sqlspec-0.10.0}/.gitignore +0 -0
  51. {sqlspec-0.9.0 → sqlspec-0.10.0}/.pre-commit-config.yaml +0 -0
  52. {sqlspec-0.9.0 → sqlspec-0.10.0}/CONTRIBUTING.rst +0 -0
  53. {sqlspec-0.9.0 → sqlspec-0.10.0}/LICENSE +0 -0
  54. {sqlspec-0.9.0 → sqlspec-0.10.0}/Makefile +0 -0
  55. {sqlspec-0.9.0 → sqlspec-0.10.0}/NOTICE +0 -0
  56. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/__metadata__.py +0 -0
  57. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/_serialization.py +0 -0
  58. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/_typing.py +0 -0
  59. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/__init__.py +0 -0
  60. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/asyncmy/config.py +0 -0
  61. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/asyncpg/__init__.py +0 -0
  62. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/oracledb/config/__init__.py +0 -0
  63. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/oracledb/config/_common.py +0 -0
  64. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/adapters/psycopg/config/_common.py +0 -0
  65. {sqlspec-0.9.0/sqlspec/adapters/psqlpy → sqlspec-0.10.0/sqlspec/extensions}/__init__.py +0 -0
  66. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/extensions/litestar/__init__.py +0 -0
  67. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/extensions/litestar/_utils.py +0 -0
  68. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/filters.py +0 -0
  69. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/py.typed +0 -0
  70. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/statement.py +0 -0
  71. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/utils/__init__.py +0 -0
  72. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/utils/deprecation.py +0 -0
  73. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/utils/fixtures.py +0 -0
  74. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/utils/module_loader.py +0 -0
  75. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/utils/sync_tools.py +0 -0
  76. {sqlspec-0.9.0 → sqlspec-0.10.0}/sqlspec/utils/text.py +0 -0
  77. {sqlspec-0.9.0/sqlspec/extensions → sqlspec-0.10.0/tests}/__init__.py +0 -0
  78. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/conftest.py +0 -0
  79. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/fixtures/__init__.py +0 -0
  80. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/fixtures/example_usage.py +0 -0
  81. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/fixtures/sql_utils.py +0 -0
  82. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/__init__.py +0 -0
  83. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/__init__.py +0 -0
  84. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_adbc/__init__.py +0 -0
  85. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_adbc/conftest.py +0 -0
  86. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_adbc/test_connection.py +0 -0
  87. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_adbc/test_driver_bigquery.py +0 -0
  88. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_adbc/test_driver_duckdb.py +0 -0
  89. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_adbc/test_driver_postgres.py +0 -0
  90. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_adbc/test_driver_sqlite.py +0 -0
  91. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_aiosqlite/__init__.py +0 -0
  92. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_aiosqlite/test_connection.py +0 -0
  93. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_aiosqlite/test_driver.py +0 -0
  94. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_asyncmy/__init__.py +0 -0
  95. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_asyncmy/test_connection.py +0 -0
  96. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_asyncmy/test_driver.py +0 -0
  97. {sqlspec-0.9.0/tests → sqlspec-0.10.0/tests/integration/test_adapters/test_asyncpg}/__init__.py +0 -0
  98. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_asyncpg/test_connection.py +0 -0
  99. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_asyncpg/test_driver.py +0 -0
  100. {sqlspec-0.9.0/tests/integration/test_adapters/test_asyncpg → sqlspec-0.10.0/tests/integration/test_adapters/test_bigquery}/__init__.py +0 -0
  101. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_duckdb/__init__.py +0 -0
  102. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_duckdb/test_connection.py +0 -0
  103. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_duckdb/test_driver.py +0 -0
  104. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_oracledb/__init__.py +0 -0
  105. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_oracledb/test_connection.py +0 -0
  106. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_oracledb/test_driver_async.py +0 -0
  107. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_oracledb/test_driver_sync.py +0 -0
  108. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_psqlpy/__init__.py +0 -0
  109. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_psqlpy/test_connection.py +0 -0
  110. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_psqlpy/test_driver.py +0 -0
  111. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_psycopg/__init__.py +0 -0
  112. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_psycopg/test_connection.py +0 -0
  113. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_psycopg/test_driver.py +0 -0
  114. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_sqlite/__init__.py +0 -0
  115. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_sqlite/test_connection.py +0 -0
  116. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/integration/test_adapters/test_sqlite/test_driver.py +0 -0
  117. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/__init__.py +0 -0
  118. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/__init__.py +0 -0
  119. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_adbc/__init__.py +0 -0
  120. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_adbc/test_config.py +0 -0
  121. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_aiosqlite/__init__.py +0 -0
  122. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_asyncmy/__init__.py +0 -0
  123. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_asyncmy/test_config.py +0 -0
  124. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_asyncpg/__init__.py +0 -0
  125. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_asyncpg/test_config.py +0 -0
  126. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_duckdb/__init__.py +0 -0
  127. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_duckdb/test_config.py +0 -0
  128. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_oracledb/__init__.py +0 -0
  129. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_oracledb/test_async_config.py +0 -0
  130. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_oracledb/test_sync_config.py +0 -0
  131. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_psycopg/__init__.py +0 -0
  132. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_psycopg/test_async_config.py +0 -0
  133. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_psycopg/test_sync_config.py +0 -0
  134. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_sqlite/__init__.py +0 -0
  135. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_adapters/test_sqlite/test_config.py +0 -0
  136. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_base.py +0 -0
  137. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_typing.py +0 -0
  138. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_utils/__init__.py +0 -0
  139. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_utils/test_module_loader.py +0 -0
  140. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_utils/test_sync_tools.py +0 -0
  141. {sqlspec-0.9.0 → sqlspec-0.10.0}/tests/unit/test_utils/test_text.py +0 -0
  142. {sqlspec-0.9.0 → sqlspec-0.10.0}/tools/__init__.py +0 -0
  143. {sqlspec-0.9.0 → sqlspec-0.10.0}/tools/build_docs.py +0 -0
  144. {sqlspec-0.9.0 → sqlspec-0.10.0}/tools/pypi_readme.py +0 -0
  145. {sqlspec-0.9.0 → sqlspec-0.10.0}/tools/sphinx_ext/__init__.py +0 -0
  146. {sqlspec-0.9.0 → sqlspec-0.10.0}/tools/sphinx_ext/changelog.py +0 -0
  147. {sqlspec-0.9.0 → sqlspec-0.10.0}/tools/sphinx_ext/missing_references.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlspec
3
- Version: 0.9.0
3
+ Version: 0.10.0
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>
@@ -41,6 +41,7 @@ Requires-Dist: oracledb; extra == 'oracledb'
41
41
  Provides-Extra: orjson
42
42
  Requires-Dist: orjson; extra == 'orjson'
43
43
  Provides-Extra: performance
44
+ Requires-Dist: msgspec; extra == 'performance'
44
45
  Requires-Dist: sqlglot[rs]; extra == 'performance'
45
46
  Provides-Extra: psqlpy
46
47
  Requires-Dist: psqlpy; extra == 'psqlpy'
@@ -83,6 +84,149 @@ SQLSpec is an experimental Python library designed to streamline and modernize y
83
84
 
84
85
  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.
85
86
 
87
+ ## Examples
88
+
89
+ We've talked about what SQLSpec is not, so let's look at what it can do.
90
+
91
+ 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.
92
+
93
+ ### DuckDB LLM
94
+
95
+ This is a quick implementation using some of the built in Secret and Extension management features of SQLSpec's DuckDB integration.
96
+
97
+ It allows you to communicate with any compatible OpenAPI conversations endpoint (such as Ollama). This examples:
98
+
99
+ - auto installs the `open_prompt` DuckDB extensions
100
+ - automatically creates the correct `open_prompt` comptaible secret required to use the extension
101
+
102
+ ```py
103
+ # /// script
104
+ # dependencies = [
105
+ # "sqlspec[duckdb,performance]",
106
+ # ]
107
+ # ///
108
+ import os
109
+
110
+ from sqlspec import SQLSpec
111
+ from sqlspec.adapters.duckdb import DuckDBConfig
112
+ from pydantic import BaseModel
113
+
114
+ class ChatMessage(BaseModel):
115
+ message: str
116
+
117
+ sql = SQLSpec()
118
+ etl_config = sql.add_config(
119
+ DuckDBConfig(
120
+ extensions=[{"name": "open_prompt"}],
121
+ secrets=[
122
+ {
123
+ "secret_type": "open_prompt",
124
+ "name": "open_prompt",
125
+ "value": {
126
+ "api_url": "http://127.0.0.1:11434/v1/chat/completions",
127
+ "model_name": "gemma3:1b",
128
+ "api_timeout": "120",
129
+ },
130
+ }
131
+ ],
132
+ )
133
+ )
134
+ with sql.provide_session(etl_config) as session:
135
+ result = session.select_one(
136
+ "SELECT open_prompt(?)",
137
+ "Can you write a haiku about DuckDB?",
138
+ schema_type=ChatMessage
139
+ )
140
+ print(result) # result is a ChatMessage pydantic model
141
+ ```
142
+
143
+ ### DuckDB Gemini Embeddings
144
+
145
+ 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.
146
+
147
+ This example will
148
+
149
+ - auto installs the `http_client` and `vss` (vector similarity search) DuckDB extensions
150
+ - when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database.
151
+ - Execute a simple query to call the Google API
152
+
153
+ ```py
154
+ # /// script
155
+ # dependencies = [
156
+ # "sqlspec[duckdb,performance]",
157
+ # ]
158
+ # ///
159
+ import os
160
+
161
+ from sqlspec import SQLSpec
162
+ from sqlspec.adapters.duckdb import DuckDBConfig
163
+
164
+ EMBEDDING_MODEL = "gemini-embedding-exp-03-07"
165
+ GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
166
+ API_URL = (
167
+ f"https://generativelanguage.googleapis.com/v1beta/models/{EMBEDDING_MODEL}:embedContent?key=${GOOGLE_API_KEY}"
168
+ )
169
+
170
+ sql = SQLSpec()
171
+ etl_config = sql.add_config(
172
+ DuckDBConfig(
173
+ extensions=[{"name": "vss"}, {"name": "http_client"}],
174
+ on_connection_create=lambda connection: connection.execute(f"""
175
+ CREATE IF NOT EXISTS MACRO generate_embedding(q) AS (
176
+ WITH __request AS (
177
+ SELECT http_post(
178
+ '{API_URL}',
179
+ headers => MAP {{
180
+ 'accept': 'application/json',
181
+ }},
182
+ params => MAP {{
183
+ 'model': 'models/{EMBEDDING_MODEL}',
184
+ 'parts': [{{ 'text': q }}],
185
+ 'taskType': 'SEMANTIC_SIMILARITY'
186
+ }}
187
+ ) AS response
188
+ )
189
+ SELECT *
190
+ FROM __request,
191
+ );
192
+ """),
193
+ )
194
+ )
195
+ with sql.provide_session(etl_config) as session:
196
+ result = session.select_one("SELECT generate_embedding('example text')")
197
+ print(result) # result is a dictionary when `schema_type` is omitted.
198
+ ```
199
+
200
+ ### Basic Litestar Integration
201
+
202
+ In this example we are going to demonstrate how to create a basic configuration that integrates into Litestar.
203
+
204
+ ```py
205
+ # /// script
206
+ # dependencies = [
207
+ # "sqlspec[aiosqlite]",
208
+ # "litestar[standard]",
209
+ # ]
210
+ # ///
211
+
212
+ from aiosqlite import Connection
213
+ from litestar import Litestar, get
214
+
215
+ from sqlspec.adapters.aiosqlite import AiosqliteConfig, AiosqliteDriver
216
+ from sqlspec.extensions.litestar import SQLSpec
217
+
218
+
219
+ @get("/")
220
+ async def simple_sqlite(db_session: AiosqliteDriver) -> dict[str, str]:
221
+ return await db_session.select_one("SELECT 'Hello, world!' AS greeting")
222
+
223
+
224
+ sqlspec = SQLSpec(config=DatabaseConfig(
225
+ config=[AiosqliteConfig(), commit_mode="autocommit")],
226
+ )
227
+ app = Litestar(route_handlers=[simple_sqlite], plugins=[sqlspec])
228
+ ```
229
+
86
230
  ## Inspiration and Future Direction
87
231
 
88
232
  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.
@@ -110,7 +254,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
110
254
  | [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Async | ✅ |
111
255
  | [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Sync | ✅ |
112
256
  | [`duckdb`](https://duckdb.org/) | DuckDB | Sync | ✅ |
113
- | [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | 🗓️ |
257
+ | [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | |
114
258
  | [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️ |
115
259
  | [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️ |
116
260
  | [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️ |
@@ -121,7 +265,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
121
265
  - `sqlspec/`:
122
266
  - `adapters/`: Contains all database drivers and associated configuration.
123
267
  - `extensions/`:
124
- - `litestar/`: Future home of `litestar` integration.
268
+ - `litestar/`: Litestar framework integration
125
269
  - `fastapi/`: Future home of `fastapi` integration.
126
270
  - `flask/`: Future home of `flask` integration.
127
271
  - `*/`: Future home of your favorite framework integration 🔌 ✨
@@ -22,6 +22,149 @@ 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(
74
+ "SELECT open_prompt(?)",
75
+ "Can you write a haiku about DuckDB?",
76
+ schema_type=ChatMessage
77
+ )
78
+ print(result) # result is a ChatMessage pydantic model
79
+ ```
80
+
81
+ ### DuckDB Gemini Embeddings
82
+
83
+ 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.
84
+
85
+ This example will
86
+
87
+ - auto installs the `http_client` and `vss` (vector similarity search) DuckDB extensions
88
+ - when a connection is created, it ensures that the `generate_embeddings` macro exists in the DuckDB database.
89
+ - Execute a simple query to call the Google API
90
+
91
+ ```py
92
+ # /// script
93
+ # dependencies = [
94
+ # "sqlspec[duckdb,performance]",
95
+ # ]
96
+ # ///
97
+ import os
98
+
99
+ from sqlspec import SQLSpec
100
+ from sqlspec.adapters.duckdb import DuckDBConfig
101
+
102
+ EMBEDDING_MODEL = "gemini-embedding-exp-03-07"
103
+ GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
104
+ API_URL = (
105
+ f"https://generativelanguage.googleapis.com/v1beta/models/{EMBEDDING_MODEL}:embedContent?key=${GOOGLE_API_KEY}"
106
+ )
107
+
108
+ sql = SQLSpec()
109
+ etl_config = sql.add_config(
110
+ DuckDBConfig(
111
+ extensions=[{"name": "vss"}, {"name": "http_client"}],
112
+ on_connection_create=lambda connection: connection.execute(f"""
113
+ CREATE IF NOT EXISTS MACRO generate_embedding(q) AS (
114
+ WITH __request AS (
115
+ SELECT http_post(
116
+ '{API_URL}',
117
+ headers => MAP {{
118
+ 'accept': 'application/json',
119
+ }},
120
+ params => MAP {{
121
+ 'model': 'models/{EMBEDDING_MODEL}',
122
+ 'parts': [{{ 'text': q }}],
123
+ 'taskType': 'SEMANTIC_SIMILARITY'
124
+ }}
125
+ ) AS response
126
+ )
127
+ SELECT *
128
+ FROM __request,
129
+ );
130
+ """),
131
+ )
132
+ )
133
+ with sql.provide_session(etl_config) as session:
134
+ result = session.select_one("SELECT generate_embedding('example text')")
135
+ print(result) # result is a dictionary when `schema_type` is omitted.
136
+ ```
137
+
138
+ ### Basic Litestar Integration
139
+
140
+ In this example we are going to demonstrate how to create a basic configuration that integrates into Litestar.
141
+
142
+ ```py
143
+ # /// script
144
+ # dependencies = [
145
+ # "sqlspec[aiosqlite]",
146
+ # "litestar[standard]",
147
+ # ]
148
+ # ///
149
+
150
+ from aiosqlite import Connection
151
+ from litestar import Litestar, get
152
+
153
+ from sqlspec.adapters.aiosqlite import AiosqliteConfig, AiosqliteDriver
154
+ from sqlspec.extensions.litestar import SQLSpec
155
+
156
+
157
+ @get("/")
158
+ async def simple_sqlite(db_session: AiosqliteDriver) -> dict[str, str]:
159
+ return await db_session.select_one("SELECT 'Hello, world!' AS greeting")
160
+
161
+
162
+ sqlspec = SQLSpec(config=DatabaseConfig(
163
+ config=[AiosqliteConfig(), commit_mode="autocommit")],
164
+ )
165
+ app = Litestar(route_handlers=[simple_sqlite], plugins=[sqlspec])
166
+ ```
167
+
25
168
  ## Inspiration and Future Direction
26
169
 
27
170
  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.
@@ -49,7 +192,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
49
192
  | [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Async | ✅ |
50
193
  | [`oracledb`](https://oracle.github.io/python-oracledb/) | Oracle | Sync | ✅ |
51
194
  | [`duckdb`](https://duckdb.org/) | DuckDB | Sync | ✅ |
52
- | [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | 🗓️ |
195
+ | [`bigquery`](https://googleapis.dev/python/bigquery/latest/index.html) | BigQuery | Sync | |
53
196
  | [`spanner`](https://googleapis.dev/python/spanner/latest/index.html) | Spanner | Sync | 🗓️ |
54
197
  | [`sqlserver`](https://docs.microsoft.com/en-us/sql/connect/python/pyodbc/python-sql-driver-for-pyodbc?view=sql-server-ver16) | SQL Server | Sync | 🗓️ |
55
198
  | [`mysql`](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-python.html) | MySQL | Sync | 🗓️ |
@@ -60,7 +203,7 @@ This list is not final. If you have a driver you'd like to see added, please ope
60
203
  - `sqlspec/`:
61
204
  - `adapters/`: Contains all database drivers and associated configuration.
62
205
  - `extensions/`:
63
- - `litestar/`: Future home of `litestar` integration.
206
+ - `litestar/`: Litestar framework integration
64
207
  - `fastapi/`: Future home of `fastapi` integration.
65
208
  - `flask/`: Future home of `flask` integration.
66
209
  - `*/`: 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.9.0"
10
+ version = "0.10.0"
11
11
 
12
12
  [project.optional-dependencies]
13
13
  adbc = ["adbc_driver_manager", "pyarrow"]
@@ -24,7 +24,7 @@ msgspec = ["msgspec"]
24
24
  nanoid = ["fastnanoid>=0.4.1"]
25
25
  oracledb = ["oracledb"]
26
26
  orjson = ["orjson"]
27
- performance = ["sqlglot[rs]"]
27
+ performance = ["sqlglot[rs]", "msgspec"]
28
28
  psqlpy = ["psqlpy"]
29
29
  psycopg = ["psycopg[binary,pool]"]
30
30
  pydantic = ["pydantic", "pydantic-extra-types"]
@@ -109,7 +109,7 @@ packages = ["sqlspec"]
109
109
  allow_dirty = true
110
110
  commit = false
111
111
  commit_args = "--no-verify"
112
- current_version = "0.9.0"
112
+ current_version = "0.10.0"
113
113
  ignore_missing_files = false
114
114
  ignore_missing_version = false
115
115
  message = "chore(release): bump to v{new_version}"
@@ -1,4 +1,4 @@
1
- from sqlspec import adapters, base, exceptions, extensions, filters, typing, utils
1
+ from sqlspec import adapters, base, exceptions, extensions, filters, mixins, typing, utils
2
2
  from sqlspec.__metadata__ import __version__
3
3
  from sqlspec.base import SQLSpec
4
4
 
@@ -10,6 +10,7 @@ __all__ = (
10
10
  "exceptions",
11
11
  "extensions",
12
12
  "filters",
13
+ "mixins",
13
14
  "typing",
14
15
  "utils",
15
16
  )
@@ -1,7 +1,8 @@
1
1
  from sqlspec.adapters.adbc.config import AdbcConfig
2
- from sqlspec.adapters.adbc.driver import AdbcDriver
2
+ from sqlspec.adapters.adbc.driver import AdbcConnection, AdbcDriver
3
3
 
4
4
  __all__ = (
5
5
  "AdbcConfig",
6
+ "AdbcConnection",
6
7
  "AdbcDriver",
7
8
  )
@@ -2,9 +2,7 @@ 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 adbc_driver_manager.dbapi import Connection
6
-
7
- from sqlspec.adapters.adbc.driver import AdbcDriver
5
+ from sqlspec.adapters.adbc.driver import AdbcConnection, AdbcDriver
8
6
  from sqlspec.base import NoPoolSyncConfig
9
7
  from sqlspec.exceptions import ImproperConfigurationError
10
8
  from sqlspec.typing import Empty, EmptyType
@@ -18,7 +16,7 @@ __all__ = ("AdbcConfig",)
18
16
 
19
17
 
20
18
  @dataclass
21
- class AdbcConfig(NoPoolSyncConfig["Connection", "AdbcDriver"]):
19
+ class AdbcConfig(NoPoolSyncConfig["AdbcConnection", "AdbcDriver"]):
22
20
  """Configuration for ADBC connections.
23
21
 
24
22
  This class provides configuration options for ADBC database connections using the
@@ -33,20 +31,16 @@ class AdbcConfig(NoPoolSyncConfig["Connection", "AdbcDriver"]):
33
31
  """Additional database-specific connection parameters"""
34
32
  conn_kwargs: "Optional[dict[str, Any]]" = None
35
33
  """Additional database-specific connection parameters"""
36
- connection_type: "type[Connection]" = field(init=False, default_factory=lambda: Connection)
34
+ connection_type: "type[AdbcConnection]" = field(init=False, default_factory=lambda: AdbcConnection)
37
35
  """Type of the connection object"""
38
36
  driver_type: "type[AdbcDriver]" = field(init=False, default_factory=lambda: AdbcDriver) # type: ignore[type-abstract,unused-ignore]
39
37
  """Type of the driver object"""
40
- pool_instance: None = field(init=False, default=None)
38
+ pool_instance: None = field(init=False, default=None, hash=False)
41
39
  """No connection pool is used for ADBC connections"""
42
- _is_in_memory: bool = field(init=False, default=False)
43
- """Flag indicating if the connection is for an in-memory database"""
44
40
 
45
41
  def _set_adbc(self) -> str: # noqa: PLR0912
46
42
  """Identify the driver type based on the URI (if provided) or preset driver name.
47
43
 
48
- Also sets the `_is_in_memory` flag for specific in-memory URIs.
49
-
50
44
  Raises:
51
45
  ImproperConfigurationError: If the driver name is not recognized or supported.
52
46
 
@@ -143,7 +137,7 @@ class AdbcConfig(NoPoolSyncConfig["Connection", "AdbcDriver"]):
143
137
  config["conn_kwargs"] = conn_kwargs
144
138
  return config
145
139
 
146
- def _get_connect_func(self) -> "Callable[..., Connection]":
140
+ def _get_connect_func(self) -> "Callable[..., AdbcConnection]":
147
141
  self._set_adbc()
148
142
  driver_path = cast("str", self.driver_name)
149
143
  try:
@@ -166,7 +160,7 @@ class AdbcConfig(NoPoolSyncConfig["Connection", "AdbcDriver"]):
166
160
  raise ImproperConfigurationError(msg)
167
161
  return connect_func # type: ignore[no-any-return]
168
162
 
169
- def create_connection(self) -> "Connection":
163
+ def create_connection(self) -> "AdbcConnection":
170
164
  """Create and return a new database connection using the specific driver.
171
165
 
172
166
  Returns:
@@ -189,7 +183,7 @@ class AdbcConfig(NoPoolSyncConfig["Connection", "AdbcDriver"]):
189
183
  raise ImproperConfigurationError(msg) from e
190
184
 
191
185
  @contextmanager
192
- def provide_connection(self, *args: "Any", **kwargs: "Any") -> "Generator[Connection, None, None]":
186
+ def provide_connection(self, *args: "Any", **kwargs: "Any") -> "Generator[AdbcConnection, None, None]":
193
187
  """Create and provide a database connection using the specific driver.
194
188
 
195
189
  Yields: