sqlspec 0.26.0__py3-none-any.whl → 0.28.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 +7 -15
- sqlspec/_serialization.py +55 -25
- sqlspec/_typing.py +155 -52
- sqlspec/adapters/adbc/_types.py +1 -1
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +880 -0
- sqlspec/adapters/adbc/config.py +62 -12
- sqlspec/adapters/adbc/data_dictionary.py +74 -2
- sqlspec/adapters/adbc/driver.py +226 -58
- sqlspec/adapters/adbc/litestar/__init__.py +5 -0
- sqlspec/adapters/adbc/litestar/store.py +504 -0
- sqlspec/adapters/adbc/type_converter.py +44 -50
- sqlspec/adapters/aiosqlite/_types.py +1 -1
- sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/adk/store.py +536 -0
- sqlspec/adapters/aiosqlite/config.py +86 -16
- sqlspec/adapters/aiosqlite/data_dictionary.py +34 -2
- sqlspec/adapters/aiosqlite/driver.py +127 -38
- sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/litestar/store.py +281 -0
- sqlspec/adapters/aiosqlite/pool.py +7 -7
- sqlspec/adapters/asyncmy/__init__.py +7 -1
- sqlspec/adapters/asyncmy/_types.py +1 -1
- sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
- sqlspec/adapters/asyncmy/adk/store.py +503 -0
- sqlspec/adapters/asyncmy/config.py +59 -17
- sqlspec/adapters/asyncmy/data_dictionary.py +41 -2
- sqlspec/adapters/asyncmy/driver.py +293 -62
- sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncmy/litestar/store.py +296 -0
- sqlspec/adapters/asyncpg/__init__.py +2 -1
- sqlspec/adapters/asyncpg/_type_handlers.py +71 -0
- sqlspec/adapters/asyncpg/_types.py +11 -7
- sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
- sqlspec/adapters/asyncpg/adk/store.py +460 -0
- sqlspec/adapters/asyncpg/config.py +57 -36
- sqlspec/adapters/asyncpg/data_dictionary.py +48 -2
- sqlspec/adapters/asyncpg/driver.py +153 -23
- sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncpg/litestar/store.py +253 -0
- sqlspec/adapters/bigquery/_types.py +1 -1
- sqlspec/adapters/bigquery/adk/__init__.py +5 -0
- sqlspec/adapters/bigquery/adk/store.py +585 -0
- sqlspec/adapters/bigquery/config.py +36 -11
- sqlspec/adapters/bigquery/data_dictionary.py +42 -2
- sqlspec/adapters/bigquery/driver.py +489 -144
- sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
- sqlspec/adapters/bigquery/litestar/store.py +327 -0
- sqlspec/adapters/bigquery/type_converter.py +55 -23
- sqlspec/adapters/duckdb/_types.py +2 -2
- sqlspec/adapters/duckdb/adk/__init__.py +14 -0
- sqlspec/adapters/duckdb/adk/store.py +563 -0
- sqlspec/adapters/duckdb/config.py +79 -21
- sqlspec/adapters/duckdb/data_dictionary.py +41 -2
- sqlspec/adapters/duckdb/driver.py +225 -44
- sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
- sqlspec/adapters/duckdb/litestar/store.py +332 -0
- sqlspec/adapters/duckdb/pool.py +5 -5
- sqlspec/adapters/duckdb/type_converter.py +51 -21
- sqlspec/adapters/oracledb/_numpy_handlers.py +133 -0
- sqlspec/adapters/oracledb/_types.py +20 -2
- sqlspec/adapters/oracledb/adk/__init__.py +5 -0
- sqlspec/adapters/oracledb/adk/store.py +1628 -0
- sqlspec/adapters/oracledb/config.py +120 -36
- sqlspec/adapters/oracledb/data_dictionary.py +87 -20
- sqlspec/adapters/oracledb/driver.py +475 -86
- sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
- sqlspec/adapters/oracledb/litestar/store.py +765 -0
- sqlspec/adapters/oracledb/migrations.py +316 -25
- sqlspec/adapters/oracledb/type_converter.py +91 -16
- sqlspec/adapters/psqlpy/_type_handlers.py +44 -0
- sqlspec/adapters/psqlpy/_types.py +2 -1
- sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
- sqlspec/adapters/psqlpy/adk/store.py +483 -0
- sqlspec/adapters/psqlpy/config.py +45 -19
- sqlspec/adapters/psqlpy/data_dictionary.py +48 -2
- sqlspec/adapters/psqlpy/driver.py +108 -41
- sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
- sqlspec/adapters/psqlpy/litestar/store.py +272 -0
- sqlspec/adapters/psqlpy/type_converter.py +40 -11
- sqlspec/adapters/psycopg/_type_handlers.py +80 -0
- sqlspec/adapters/psycopg/_types.py +2 -1
- sqlspec/adapters/psycopg/adk/__init__.py +5 -0
- sqlspec/adapters/psycopg/adk/store.py +962 -0
- sqlspec/adapters/psycopg/config.py +65 -37
- sqlspec/adapters/psycopg/data_dictionary.py +91 -3
- sqlspec/adapters/psycopg/driver.py +200 -78
- sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
- sqlspec/adapters/psycopg/litestar/store.py +554 -0
- sqlspec/adapters/sqlite/__init__.py +2 -1
- sqlspec/adapters/sqlite/_type_handlers.py +86 -0
- sqlspec/adapters/sqlite/_types.py +1 -1
- sqlspec/adapters/sqlite/adk/__init__.py +5 -0
- sqlspec/adapters/sqlite/adk/store.py +582 -0
- sqlspec/adapters/sqlite/config.py +85 -16
- sqlspec/adapters/sqlite/data_dictionary.py +34 -2
- sqlspec/adapters/sqlite/driver.py +120 -52
- sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/sqlite/litestar/store.py +318 -0
- sqlspec/adapters/sqlite/pool.py +5 -5
- sqlspec/base.py +45 -26
- sqlspec/builder/__init__.py +73 -4
- sqlspec/builder/_base.py +91 -58
- sqlspec/builder/_column.py +5 -5
- sqlspec/builder/_ddl.py +98 -89
- sqlspec/builder/_delete.py +5 -4
- sqlspec/builder/_dml.py +388 -0
- sqlspec/{_sql.py → builder/_factory.py} +41 -44
- sqlspec/builder/_insert.py +5 -82
- sqlspec/builder/{mixins/_join_operations.py → _join.py} +145 -143
- sqlspec/builder/_merge.py +446 -11
- sqlspec/builder/_parsing_utils.py +9 -11
- sqlspec/builder/_select.py +1313 -25
- sqlspec/builder/_update.py +11 -42
- sqlspec/cli.py +76 -69
- sqlspec/config.py +331 -62
- sqlspec/core/__init__.py +5 -4
- sqlspec/core/cache.py +18 -18
- sqlspec/core/compiler.py +6 -8
- sqlspec/core/filters.py +55 -47
- sqlspec/core/hashing.py +9 -9
- sqlspec/core/parameters.py +76 -45
- sqlspec/core/result.py +234 -47
- sqlspec/core/splitter.py +16 -17
- sqlspec/core/statement.py +32 -31
- sqlspec/core/type_conversion.py +3 -2
- sqlspec/driver/__init__.py +1 -3
- sqlspec/driver/_async.py +183 -160
- sqlspec/driver/_common.py +197 -109
- sqlspec/driver/_sync.py +189 -161
- sqlspec/driver/mixins/_result_tools.py +20 -236
- sqlspec/driver/mixins/_sql_translator.py +4 -4
- sqlspec/exceptions.py +70 -7
- sqlspec/extensions/adk/__init__.py +53 -0
- sqlspec/extensions/adk/_types.py +51 -0
- sqlspec/extensions/adk/converters.py +172 -0
- sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +144 -0
- sqlspec/extensions/adk/migrations/__init__.py +0 -0
- sqlspec/extensions/adk/service.py +181 -0
- sqlspec/extensions/adk/store.py +536 -0
- sqlspec/extensions/aiosql/adapter.py +69 -61
- sqlspec/extensions/fastapi/__init__.py +21 -0
- sqlspec/extensions/fastapi/extension.py +331 -0
- sqlspec/extensions/fastapi/providers.py +543 -0
- sqlspec/extensions/flask/__init__.py +36 -0
- sqlspec/extensions/flask/_state.py +71 -0
- sqlspec/extensions/flask/_utils.py +40 -0
- sqlspec/extensions/flask/extension.py +389 -0
- sqlspec/extensions/litestar/__init__.py +21 -4
- sqlspec/extensions/litestar/cli.py +54 -10
- sqlspec/extensions/litestar/config.py +56 -266
- sqlspec/extensions/litestar/handlers.py +46 -17
- sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
- sqlspec/extensions/litestar/migrations/__init__.py +3 -0
- sqlspec/extensions/litestar/plugin.py +349 -224
- sqlspec/extensions/litestar/providers.py +25 -25
- sqlspec/extensions/litestar/store.py +265 -0
- sqlspec/extensions/starlette/__init__.py +10 -0
- sqlspec/extensions/starlette/_state.py +25 -0
- sqlspec/extensions/starlette/_utils.py +52 -0
- sqlspec/extensions/starlette/extension.py +254 -0
- sqlspec/extensions/starlette/middleware.py +154 -0
- sqlspec/loader.py +30 -49
- sqlspec/migrations/base.py +200 -76
- sqlspec/migrations/commands.py +591 -62
- sqlspec/migrations/context.py +6 -9
- sqlspec/migrations/fix.py +199 -0
- sqlspec/migrations/loaders.py +47 -19
- sqlspec/migrations/runner.py +241 -75
- sqlspec/migrations/tracker.py +237 -21
- sqlspec/migrations/utils.py +51 -3
- sqlspec/migrations/validation.py +177 -0
- sqlspec/protocols.py +106 -36
- sqlspec/storage/_utils.py +85 -0
- sqlspec/storage/backends/fsspec.py +133 -107
- sqlspec/storage/backends/local.py +78 -51
- sqlspec/storage/backends/obstore.py +276 -168
- sqlspec/storage/registry.py +75 -39
- sqlspec/typing.py +30 -84
- sqlspec/utils/__init__.py +25 -4
- sqlspec/utils/arrow_helpers.py +81 -0
- sqlspec/utils/config_resolver.py +6 -6
- sqlspec/utils/correlation.py +4 -5
- sqlspec/utils/data_transformation.py +3 -2
- sqlspec/utils/deprecation.py +9 -8
- sqlspec/utils/fixtures.py +4 -4
- sqlspec/utils/logging.py +46 -6
- sqlspec/utils/module_loader.py +205 -5
- sqlspec/utils/portal.py +311 -0
- sqlspec/utils/schema.py +288 -0
- sqlspec/utils/serializers.py +113 -4
- sqlspec/utils/sync_tools.py +36 -22
- sqlspec/utils/text.py +1 -2
- sqlspec/utils/type_guards.py +136 -20
- sqlspec/utils/version.py +433 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.28.0.dist-info}/METADATA +41 -22
- sqlspec-0.28.0.dist-info/RECORD +221 -0
- sqlspec/builder/mixins/__init__.py +0 -55
- sqlspec/builder/mixins/_cte_and_set_ops.py +0 -253
- sqlspec/builder/mixins/_delete_operations.py +0 -50
- sqlspec/builder/mixins/_insert_operations.py +0 -282
- sqlspec/builder/mixins/_merge_operations.py +0 -698
- sqlspec/builder/mixins/_order_limit_operations.py +0 -145
- sqlspec/builder/mixins/_pivot_operations.py +0 -157
- sqlspec/builder/mixins/_select_operations.py +0 -930
- sqlspec/builder/mixins/_update_operations.py +0 -199
- sqlspec/builder/mixins/_where_clause.py +0 -1298
- sqlspec-0.26.0.dist-info/RECORD +0 -157
- sqlspec-0.26.0.dist-info/licenses/NOTICE +0 -29
- {sqlspec-0.26.0.dist-info → sqlspec-0.28.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.28.0.dist-info}/entry_points.txt +0 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.28.0.dist-info}/licenses/LICENSE +0 -0
sqlspec/protocols.py
CHANGED
|
@@ -4,7 +4,7 @@ This module provides protocols that can be used for static type checking
|
|
|
4
4
|
and runtime isinstance() checks.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from typing import TYPE_CHECKING, Any,
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
|
|
8
8
|
|
|
9
9
|
from typing_extensions import Self
|
|
10
10
|
|
|
@@ -39,6 +39,7 @@ __all__ = (
|
|
|
39
39
|
"ParameterValueProtocol",
|
|
40
40
|
"SQLBuilderProtocol",
|
|
41
41
|
"SelectBuilderProtocol",
|
|
42
|
+
"SupportsArrowResults",
|
|
42
43
|
"WithMethodProtocol",
|
|
43
44
|
)
|
|
44
45
|
|
|
@@ -186,7 +187,7 @@ class ObjectStoreItemProtocol(Protocol):
|
|
|
186
187
|
"""Protocol for object store items with path/key attributes."""
|
|
187
188
|
|
|
188
189
|
path: str
|
|
189
|
-
key: "
|
|
190
|
+
key: "str | None"
|
|
190
191
|
|
|
191
192
|
|
|
192
193
|
@runtime_checkable
|
|
@@ -199,35 +200,35 @@ class ObjectStoreProtocol(Protocol):
|
|
|
199
200
|
def __init__(self, uri: str, **kwargs: Any) -> None:
|
|
200
201
|
return
|
|
201
202
|
|
|
202
|
-
def read_bytes(self, path: "
|
|
203
|
+
def read_bytes(self, path: "str | Path", **kwargs: Any) -> bytes:
|
|
203
204
|
"""Read bytes from an object."""
|
|
204
205
|
return b""
|
|
205
206
|
|
|
206
|
-
def write_bytes(self, path: "
|
|
207
|
+
def write_bytes(self, path: "str | Path", data: bytes, **kwargs: Any) -> None:
|
|
207
208
|
"""Write bytes to an object."""
|
|
208
209
|
return
|
|
209
210
|
|
|
210
|
-
def read_text(self, path: "
|
|
211
|
+
def read_text(self, path: "str | Path", encoding: str = "utf-8", **kwargs: Any) -> str:
|
|
211
212
|
"""Read text from an object."""
|
|
212
213
|
return ""
|
|
213
214
|
|
|
214
|
-
def write_text(self, path: "
|
|
215
|
+
def write_text(self, path: "str | Path", data: str, encoding: str = "utf-8", **kwargs: Any) -> None:
|
|
215
216
|
"""Write text to an object."""
|
|
216
217
|
return
|
|
217
218
|
|
|
218
|
-
def exists(self, path: "
|
|
219
|
+
def exists(self, path: "str | Path", **kwargs: Any) -> bool:
|
|
219
220
|
"""Check if an object exists."""
|
|
220
221
|
return False
|
|
221
222
|
|
|
222
|
-
def delete(self, path: "
|
|
223
|
+
def delete(self, path: "str | Path", **kwargs: Any) -> None:
|
|
223
224
|
"""Delete an object."""
|
|
224
225
|
return
|
|
225
226
|
|
|
226
|
-
def copy(self, source: "
|
|
227
|
+
def copy(self, source: "str | Path", destination: "str | Path", **kwargs: Any) -> None:
|
|
227
228
|
"""Copy an object."""
|
|
228
229
|
return
|
|
229
230
|
|
|
230
|
-
def move(self, source: "
|
|
231
|
+
def move(self, source: "str | Path", destination: "str | Path", **kwargs: Any) -> None:
|
|
231
232
|
"""Move an object."""
|
|
232
233
|
return
|
|
233
234
|
|
|
@@ -239,24 +240,24 @@ class ObjectStoreProtocol(Protocol):
|
|
|
239
240
|
"""Find objects matching a glob pattern."""
|
|
240
241
|
return []
|
|
241
242
|
|
|
242
|
-
def is_object(self, path: "
|
|
243
|
+
def is_object(self, path: "str | Path") -> bool:
|
|
243
244
|
"""Check if path points to an object."""
|
|
244
245
|
return False
|
|
245
246
|
|
|
246
|
-
def is_path(self, path: "
|
|
247
|
+
def is_path(self, path: "str | Path") -> bool:
|
|
247
248
|
"""Check if path points to a prefix (directory-like)."""
|
|
248
249
|
return False
|
|
249
250
|
|
|
250
|
-
def get_metadata(self, path: "
|
|
251
|
+
def get_metadata(self, path: "str | Path", **kwargs: Any) -> dict[str, Any]:
|
|
251
252
|
"""Get object metadata."""
|
|
252
253
|
return {}
|
|
253
254
|
|
|
254
|
-
def read_arrow(self, path: "
|
|
255
|
+
def read_arrow(self, path: "str | Path", **kwargs: Any) -> "ArrowTable":
|
|
255
256
|
"""Read an Arrow table from storage."""
|
|
256
257
|
msg = "Arrow reading not implemented"
|
|
257
258
|
raise NotImplementedError(msg)
|
|
258
259
|
|
|
259
|
-
def write_arrow(self, path: "
|
|
260
|
+
def write_arrow(self, path: "str | Path", table: "ArrowTable", **kwargs: Any) -> None:
|
|
260
261
|
"""Write an Arrow table to storage."""
|
|
261
262
|
msg = "Arrow writing not implemented"
|
|
262
263
|
raise NotImplementedError(msg)
|
|
@@ -266,34 +267,32 @@ class ObjectStoreProtocol(Protocol):
|
|
|
266
267
|
msg = "Arrow streaming not implemented"
|
|
267
268
|
raise NotImplementedError(msg)
|
|
268
269
|
|
|
269
|
-
async def read_bytes_async(self, path: "
|
|
270
|
+
async def read_bytes_async(self, path: "str | Path", **kwargs: Any) -> bytes:
|
|
270
271
|
"""Async read bytes from an object."""
|
|
271
272
|
msg = "Async operations not implemented"
|
|
272
273
|
raise NotImplementedError(msg)
|
|
273
274
|
|
|
274
|
-
async def write_bytes_async(self, path: "
|
|
275
|
+
async def write_bytes_async(self, path: "str | Path", data: bytes, **kwargs: Any) -> None:
|
|
275
276
|
"""Async write bytes to an object."""
|
|
276
277
|
msg = "Async operations not implemented"
|
|
277
278
|
raise NotImplementedError(msg)
|
|
278
279
|
|
|
279
|
-
async def read_text_async(self, path: "
|
|
280
|
+
async def read_text_async(self, path: "str | Path", encoding: str = "utf-8", **kwargs: Any) -> str:
|
|
280
281
|
"""Async read text from an object."""
|
|
281
282
|
msg = "Async operations not implemented"
|
|
282
283
|
raise NotImplementedError(msg)
|
|
283
284
|
|
|
284
|
-
async def write_text_async(
|
|
285
|
-
self, path: "Union[str, Path]", data: str, encoding: str = "utf-8", **kwargs: Any
|
|
286
|
-
) -> None:
|
|
285
|
+
async def write_text_async(self, path: "str | Path", data: str, encoding: str = "utf-8", **kwargs: Any) -> None:
|
|
287
286
|
"""Async write text to an object."""
|
|
288
287
|
msg = "Async operations not implemented"
|
|
289
288
|
raise NotImplementedError(msg)
|
|
290
289
|
|
|
291
|
-
async def exists_async(self, path: "
|
|
290
|
+
async def exists_async(self, path: "str | Path", **kwargs: Any) -> bool:
|
|
292
291
|
"""Async check if an object exists."""
|
|
293
292
|
msg = "Async operations not implemented"
|
|
294
293
|
raise NotImplementedError(msg)
|
|
295
294
|
|
|
296
|
-
async def delete_async(self, path: "
|
|
295
|
+
async def delete_async(self, path: "str | Path", **kwargs: Any) -> None:
|
|
297
296
|
"""Async delete an object."""
|
|
298
297
|
msg = "Async operations not implemented"
|
|
299
298
|
raise NotImplementedError(msg)
|
|
@@ -303,27 +302,27 @@ class ObjectStoreProtocol(Protocol):
|
|
|
303
302
|
msg = "Async operations not implemented"
|
|
304
303
|
raise NotImplementedError(msg)
|
|
305
304
|
|
|
306
|
-
async def copy_async(self, source: "
|
|
305
|
+
async def copy_async(self, source: "str | Path", destination: "str | Path", **kwargs: Any) -> None:
|
|
307
306
|
"""Async copy an object."""
|
|
308
307
|
msg = "Async operations not implemented"
|
|
309
308
|
raise NotImplementedError(msg)
|
|
310
309
|
|
|
311
|
-
async def move_async(self, source: "
|
|
310
|
+
async def move_async(self, source: "str | Path", destination: "str | Path", **kwargs: Any) -> None:
|
|
312
311
|
"""Async move an object."""
|
|
313
312
|
msg = "Async operations not implemented"
|
|
314
313
|
raise NotImplementedError(msg)
|
|
315
314
|
|
|
316
|
-
async def get_metadata_async(self, path: "
|
|
315
|
+
async def get_metadata_async(self, path: "str | Path", **kwargs: Any) -> dict[str, Any]:
|
|
317
316
|
"""Async get object metadata."""
|
|
318
317
|
msg = "Async operations not implemented"
|
|
319
318
|
raise NotImplementedError(msg)
|
|
320
319
|
|
|
321
|
-
async def read_arrow_async(self, path: "
|
|
320
|
+
async def read_arrow_async(self, path: "str | Path", **kwargs: Any) -> "ArrowTable":
|
|
322
321
|
"""Async read an Arrow table from storage."""
|
|
323
322
|
msg = "Async arrow reading not implemented"
|
|
324
323
|
raise NotImplementedError(msg)
|
|
325
324
|
|
|
326
|
-
async def write_arrow_async(self, path: "
|
|
325
|
+
async def write_arrow_async(self, path: "str | Path", table: "ArrowTable", **kwargs: Any) -> None:
|
|
327
326
|
"""Async write an Arrow table to storage."""
|
|
328
327
|
msg = "Async arrow writing not implemented"
|
|
329
328
|
raise NotImplementedError(msg)
|
|
@@ -339,7 +338,7 @@ class HasSQLGlotExpressionProtocol(Protocol):
|
|
|
339
338
|
"""Protocol for objects with a sqlglot_expression property."""
|
|
340
339
|
|
|
341
340
|
@property
|
|
342
|
-
def sqlglot_expression(self) -> "
|
|
341
|
+
def sqlglot_expression(self) -> "exp.Expression | None":
|
|
343
342
|
"""Return the SQLGlot expression for this object."""
|
|
344
343
|
...
|
|
345
344
|
|
|
@@ -348,16 +347,24 @@ class HasSQLGlotExpressionProtocol(Protocol):
|
|
|
348
347
|
class HasParameterBuilderProtocol(Protocol):
|
|
349
348
|
"""Protocol for objects that can add parameters."""
|
|
350
349
|
|
|
351
|
-
def add_parameter(self, value: Any, name: "
|
|
350
|
+
def add_parameter(self, value: Any, name: "str | None" = None) -> tuple[Any, str]:
|
|
352
351
|
"""Add a parameter to the builder."""
|
|
353
352
|
...
|
|
354
353
|
|
|
354
|
+
def get_expression(self) -> "exp.Expression | None":
|
|
355
|
+
"""Return the underlying SQLGlot expression."""
|
|
356
|
+
...
|
|
357
|
+
|
|
358
|
+
def set_expression(self, expression: "exp.Expression") -> None:
|
|
359
|
+
"""Replace the underlying SQLGlot expression."""
|
|
360
|
+
...
|
|
361
|
+
|
|
355
362
|
|
|
356
363
|
@runtime_checkable
|
|
357
364
|
class HasExpressionProtocol(Protocol):
|
|
358
365
|
"""Protocol for objects with an _expression attribute."""
|
|
359
366
|
|
|
360
|
-
_expression: "
|
|
367
|
+
_expression: "exp.Expression | None"
|
|
361
368
|
|
|
362
369
|
|
|
363
370
|
@runtime_checkable
|
|
@@ -373,21 +380,21 @@ class HasToStatementProtocol(Protocol):
|
|
|
373
380
|
class SQLBuilderProtocol(Protocol):
|
|
374
381
|
"""Protocol for SQL query builders."""
|
|
375
382
|
|
|
376
|
-
_expression: "
|
|
383
|
+
_expression: "exp.Expression | None"
|
|
377
384
|
_parameters: dict[str, Any]
|
|
378
385
|
_parameter_counter: int
|
|
379
386
|
_columns: Any # Optional attribute for some builders
|
|
380
387
|
_table: Any # Optional attribute for some builders
|
|
381
388
|
_with_ctes: Any # Optional attribute for some builders
|
|
382
389
|
dialect: Any
|
|
383
|
-
dialect_name: "
|
|
390
|
+
dialect_name: "str | None"
|
|
384
391
|
|
|
385
392
|
@property
|
|
386
393
|
def parameters(self) -> dict[str, Any]:
|
|
387
394
|
"""Public access to query parameters."""
|
|
388
395
|
...
|
|
389
396
|
|
|
390
|
-
def add_parameter(self, value: Any, name: "
|
|
397
|
+
def add_parameter(self, value: Any, name: "str | None" = None) -> tuple[Any, str]:
|
|
391
398
|
"""Add a parameter to the builder."""
|
|
392
399
|
...
|
|
393
400
|
|
|
@@ -399,14 +406,77 @@ class SQLBuilderProtocol(Protocol):
|
|
|
399
406
|
"""Replace literal values in an expression with bound parameters."""
|
|
400
407
|
...
|
|
401
408
|
|
|
402
|
-
def build(self) -> "
|
|
409
|
+
def build(self) -> "exp.Expression | Any":
|
|
403
410
|
"""Build and return the final expression."""
|
|
404
411
|
...
|
|
405
412
|
|
|
413
|
+
def _merge_sql_object_parameters(self, sql_obj: Any) -> None:
|
|
414
|
+
"""Merge parameters from SQL objects into the builder."""
|
|
415
|
+
...
|
|
416
|
+
|
|
417
|
+
def _build_final_expression(self, *, copy: bool = False) -> "exp.Expression":
|
|
418
|
+
"""Return the expression with attached CTEs."""
|
|
419
|
+
...
|
|
420
|
+
|
|
421
|
+
def _spawn_like_self(self) -> "Self":
|
|
422
|
+
"""Create a new builder with matching configuration."""
|
|
423
|
+
...
|
|
424
|
+
|
|
425
|
+
def get_expression(self) -> "exp.Expression | None":
|
|
426
|
+
"""Return the underlying SQLGlot expression."""
|
|
427
|
+
...
|
|
428
|
+
|
|
429
|
+
def set_expression(self, expression: "exp.Expression") -> None:
|
|
430
|
+
"""Replace the underlying SQLGlot expression."""
|
|
431
|
+
...
|
|
432
|
+
|
|
433
|
+
def generate_unique_parameter_name(self, base_name: str) -> str:
|
|
434
|
+
"""Generate a unique parameter name exposed via public API."""
|
|
435
|
+
...
|
|
436
|
+
|
|
406
437
|
|
|
407
438
|
class SelectBuilderProtocol(SQLBuilderProtocol, Protocol):
|
|
408
439
|
"""Protocol for SELECT query builders."""
|
|
409
440
|
|
|
410
|
-
def select(self, *columns: "
|
|
441
|
+
def select(self, *columns: "str | exp.Expression") -> Self:
|
|
411
442
|
"""Add SELECT columns to the query."""
|
|
412
443
|
...
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
@runtime_checkable
|
|
447
|
+
class SupportsArrowResults(Protocol):
|
|
448
|
+
"""Protocol for adapters that support Arrow result format.
|
|
449
|
+
|
|
450
|
+
Adapters implementing this protocol can return query results in Apache Arrow
|
|
451
|
+
format via the select_to_arrow() method, enabling zero-copy data transfer and
|
|
452
|
+
efficient integration with data science tools.
|
|
453
|
+
"""
|
|
454
|
+
|
|
455
|
+
def select_to_arrow(
|
|
456
|
+
self,
|
|
457
|
+
statement: Any,
|
|
458
|
+
/,
|
|
459
|
+
*parameters: Any,
|
|
460
|
+
statement_config: Any | None = None,
|
|
461
|
+
return_format: str = "table",
|
|
462
|
+
native_only: bool = False,
|
|
463
|
+
batch_size: int | None = None,
|
|
464
|
+
arrow_schema: Any | None = None,
|
|
465
|
+
**kwargs: Any,
|
|
466
|
+
) -> "ArrowTable | ArrowRecordBatch":
|
|
467
|
+
"""Execute query and return results as Apache Arrow Table or RecordBatch.
|
|
468
|
+
|
|
469
|
+
Args:
|
|
470
|
+
statement: SQL statement to execute.
|
|
471
|
+
*parameters: Query parameters and filters.
|
|
472
|
+
statement_config: Optional statement configuration override.
|
|
473
|
+
return_format: Output format - "table", "reader", or "batches".
|
|
474
|
+
native_only: If True, raise error when native Arrow path unavailable.
|
|
475
|
+
batch_size: Chunk size for streaming modes.
|
|
476
|
+
arrow_schema: Optional target Arrow schema for type casting.
|
|
477
|
+
**kwargs: Additional keyword arguments.
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
ArrowResult containing Arrow data.
|
|
481
|
+
"""
|
|
482
|
+
...
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Shared utilities for storage backends."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
__all__ = ("resolve_storage_path",)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def resolve_storage_path(
|
|
12
|
+
path: "str | Path", base_path: str = "", protocol: str = "file", strip_file_scheme: bool = True
|
|
13
|
+
) -> str:
|
|
14
|
+
"""Resolve path relative to base_path with protocol-specific handling.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
path: Path to resolve (may include file:// scheme).
|
|
18
|
+
base_path: Base path to prepend if path is relative.
|
|
19
|
+
protocol: Storage protocol (file, s3, gs, etc.).
|
|
20
|
+
strip_file_scheme: Whether to strip file:// prefix.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Resolved path string suitable for the storage backend.
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
>>> resolve_storage_path("/data/file.txt", protocol="file")
|
|
27
|
+
'data/file.txt'
|
|
28
|
+
|
|
29
|
+
>>> resolve_storage_path(
|
|
30
|
+
... "file.txt", base_path="/base", protocol="file"
|
|
31
|
+
... )
|
|
32
|
+
'base/file.txt'
|
|
33
|
+
|
|
34
|
+
>>> resolve_storage_path(
|
|
35
|
+
... "file:///data/file.txt", strip_file_scheme=True
|
|
36
|
+
... )
|
|
37
|
+
'data/file.txt'
|
|
38
|
+
|
|
39
|
+
>>> resolve_storage_path(
|
|
40
|
+
... "/data/subdir/file.txt",
|
|
41
|
+
... base_path="/data",
|
|
42
|
+
... protocol="file",
|
|
43
|
+
... )
|
|
44
|
+
'subdir/file.txt'
|
|
45
|
+
"""
|
|
46
|
+
from pathlib import Path as PathlibPath
|
|
47
|
+
|
|
48
|
+
path_str = str(path)
|
|
49
|
+
|
|
50
|
+
if strip_file_scheme and path_str.startswith("file://"):
|
|
51
|
+
path_str = path_str.removeprefix("file://")
|
|
52
|
+
|
|
53
|
+
# For local file protocol
|
|
54
|
+
if protocol == "file":
|
|
55
|
+
path_obj = PathlibPath(path_str)
|
|
56
|
+
|
|
57
|
+
# Absolute path handling
|
|
58
|
+
if path_obj.is_absolute():
|
|
59
|
+
if base_path:
|
|
60
|
+
base_obj = PathlibPath(base_path)
|
|
61
|
+
# Try to make path relative to base_path
|
|
62
|
+
try:
|
|
63
|
+
relative = path_obj.relative_to(base_obj)
|
|
64
|
+
# Return joined path for FSSpec-style backends
|
|
65
|
+
return f"{base_path.rstrip('/')}/{relative}"
|
|
66
|
+
except ValueError:
|
|
67
|
+
# Path is outside base_path
|
|
68
|
+
return path_str.lstrip("/")
|
|
69
|
+
# No base_path - strip leading /
|
|
70
|
+
return path_str.lstrip("/")
|
|
71
|
+
|
|
72
|
+
# Relative path with base_path - join them
|
|
73
|
+
if base_path:
|
|
74
|
+
return f"{base_path.rstrip('/')}/{path_str}"
|
|
75
|
+
|
|
76
|
+
# Relative path without base_path
|
|
77
|
+
return path_str
|
|
78
|
+
|
|
79
|
+
# For cloud storage protocols (s3, gs, etc.), join with base_path
|
|
80
|
+
if not base_path:
|
|
81
|
+
return path_str
|
|
82
|
+
|
|
83
|
+
clean_base = base_path.rstrip("/")
|
|
84
|
+
clean_path = path_str.lstrip("/")
|
|
85
|
+
return f"{clean_base}/{clean_path}"
|