sqlspec 0.26.0__py3-none-any.whl → 0.27.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 +62 -52
- sqlspec/adapters/adbc/_types.py +1 -1
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +870 -0
- sqlspec/adapters/adbc/config.py +62 -12
- sqlspec/adapters/adbc/data_dictionary.py +52 -2
- sqlspec/adapters/adbc/driver.py +144 -45
- 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 +527 -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 +493 -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 +450 -0
- sqlspec/adapters/asyncpg/config.py +57 -36
- sqlspec/adapters/asyncpg/data_dictionary.py +41 -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 +576 -0
- sqlspec/adapters/bigquery/config.py +25 -11
- sqlspec/adapters/bigquery/data_dictionary.py +42 -2
- sqlspec/adapters/bigquery/driver.py +352 -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 +553 -0
- sqlspec/adapters/duckdb/config.py +79 -21
- sqlspec/adapters/duckdb/data_dictionary.py +41 -2
- sqlspec/adapters/duckdb/driver.py +138 -43
- 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 +1745 -0
- sqlspec/adapters/oracledb/config.py +120 -36
- sqlspec/adapters/oracledb/data_dictionary.py +87 -20
- sqlspec/adapters/oracledb/driver.py +292 -84
- sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
- sqlspec/adapters/oracledb/litestar/store.py +767 -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 +482 -0
- sqlspec/adapters/psqlpy/config.py +45 -19
- sqlspec/adapters/psqlpy/data_dictionary.py +41 -2
- sqlspec/adapters/psqlpy/driver.py +101 -31
- 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 +944 -0
- sqlspec/adapters/psycopg/config.py +65 -37
- sqlspec/adapters/psycopg/data_dictionary.py +77 -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 +572 -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 +231 -60
- sqlspec/core/__init__.py +5 -4
- sqlspec/core/cache.py +18 -18
- sqlspec/core/compiler.py +6 -8
- sqlspec/core/filters.py +37 -37
- sqlspec/core/hashing.py +9 -9
- sqlspec/core/parameters.py +76 -45
- sqlspec/core/result.py +102 -46
- 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 +95 -161
- sqlspec/driver/_common.py +133 -80
- sqlspec/driver/_sync.py +95 -162
- 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 +73 -53
- sqlspec/extensions/litestar/__init__.py +21 -4
- sqlspec/extensions/litestar/cli.py +54 -10
- sqlspec/extensions/litestar/config.py +59 -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 +324 -223
- sqlspec/extensions/litestar/providers.py +25 -25
- sqlspec/extensions/litestar/store.py +265 -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 +66 -36
- sqlspec/storage/_utils.py +98 -0
- sqlspec/storage/backends/fsspec.py +134 -106
- sqlspec/storage/backends/local.py +78 -51
- sqlspec/storage/backends/obstore.py +278 -162
- sqlspec/storage/registry.py +75 -39
- sqlspec/typing.py +14 -84
- 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 +2 -2
- sqlspec/utils/schema.py +288 -0
- sqlspec/utils/serializers.py +3 -3
- sqlspec/utils/sync_tools.py +21 -17
- sqlspec/utils/text.py +1 -2
- sqlspec/utils/type_guards.py +111 -20
- sqlspec/utils/version.py +433 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/METADATA +40 -21
- sqlspec-0.27.0.dist-info/RECORD +207 -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.27.0.dist-info}/WHEEL +0 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/entry_points.txt +0 -0
- {sqlspec-0.26.0.dist-info → sqlspec-0.27.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
|
|
|
@@ -186,7 +186,7 @@ class ObjectStoreItemProtocol(Protocol):
|
|
|
186
186
|
"""Protocol for object store items with path/key attributes."""
|
|
187
187
|
|
|
188
188
|
path: str
|
|
189
|
-
key: "
|
|
189
|
+
key: "str | None"
|
|
190
190
|
|
|
191
191
|
|
|
192
192
|
@runtime_checkable
|
|
@@ -199,35 +199,35 @@ class ObjectStoreProtocol(Protocol):
|
|
|
199
199
|
def __init__(self, uri: str, **kwargs: Any) -> None:
|
|
200
200
|
return
|
|
201
201
|
|
|
202
|
-
def read_bytes(self, path: "
|
|
202
|
+
def read_bytes(self, path: "str | Path", **kwargs: Any) -> bytes:
|
|
203
203
|
"""Read bytes from an object."""
|
|
204
204
|
return b""
|
|
205
205
|
|
|
206
|
-
def write_bytes(self, path: "
|
|
206
|
+
def write_bytes(self, path: "str | Path", data: bytes, **kwargs: Any) -> None:
|
|
207
207
|
"""Write bytes to an object."""
|
|
208
208
|
return
|
|
209
209
|
|
|
210
|
-
def read_text(self, path: "
|
|
210
|
+
def read_text(self, path: "str | Path", encoding: str = "utf-8", **kwargs: Any) -> str:
|
|
211
211
|
"""Read text from an object."""
|
|
212
212
|
return ""
|
|
213
213
|
|
|
214
|
-
def write_text(self, path: "
|
|
214
|
+
def write_text(self, path: "str | Path", data: str, encoding: str = "utf-8", **kwargs: Any) -> None:
|
|
215
215
|
"""Write text to an object."""
|
|
216
216
|
return
|
|
217
217
|
|
|
218
|
-
def exists(self, path: "
|
|
218
|
+
def exists(self, path: "str | Path", **kwargs: Any) -> bool:
|
|
219
219
|
"""Check if an object exists."""
|
|
220
220
|
return False
|
|
221
221
|
|
|
222
|
-
def delete(self, path: "
|
|
222
|
+
def delete(self, path: "str | Path", **kwargs: Any) -> None:
|
|
223
223
|
"""Delete an object."""
|
|
224
224
|
return
|
|
225
225
|
|
|
226
|
-
def copy(self, source: "
|
|
226
|
+
def copy(self, source: "str | Path", destination: "str | Path", **kwargs: Any) -> None:
|
|
227
227
|
"""Copy an object."""
|
|
228
228
|
return
|
|
229
229
|
|
|
230
|
-
def move(self, source: "
|
|
230
|
+
def move(self, source: "str | Path", destination: "str | Path", **kwargs: Any) -> None:
|
|
231
231
|
"""Move an object."""
|
|
232
232
|
return
|
|
233
233
|
|
|
@@ -239,24 +239,24 @@ class ObjectStoreProtocol(Protocol):
|
|
|
239
239
|
"""Find objects matching a glob pattern."""
|
|
240
240
|
return []
|
|
241
241
|
|
|
242
|
-
def is_object(self, path: "
|
|
242
|
+
def is_object(self, path: "str | Path") -> bool:
|
|
243
243
|
"""Check if path points to an object."""
|
|
244
244
|
return False
|
|
245
245
|
|
|
246
|
-
def is_path(self, path: "
|
|
246
|
+
def is_path(self, path: "str | Path") -> bool:
|
|
247
247
|
"""Check if path points to a prefix (directory-like)."""
|
|
248
248
|
return False
|
|
249
249
|
|
|
250
|
-
def get_metadata(self, path: "
|
|
250
|
+
def get_metadata(self, path: "str | Path", **kwargs: Any) -> dict[str, Any]:
|
|
251
251
|
"""Get object metadata."""
|
|
252
252
|
return {}
|
|
253
253
|
|
|
254
|
-
def read_arrow(self, path: "
|
|
254
|
+
def read_arrow(self, path: "str | Path", **kwargs: Any) -> "ArrowTable":
|
|
255
255
|
"""Read an Arrow table from storage."""
|
|
256
256
|
msg = "Arrow reading not implemented"
|
|
257
257
|
raise NotImplementedError(msg)
|
|
258
258
|
|
|
259
|
-
def write_arrow(self, path: "
|
|
259
|
+
def write_arrow(self, path: "str | Path", table: "ArrowTable", **kwargs: Any) -> None:
|
|
260
260
|
"""Write an Arrow table to storage."""
|
|
261
261
|
msg = "Arrow writing not implemented"
|
|
262
262
|
raise NotImplementedError(msg)
|
|
@@ -266,34 +266,32 @@ class ObjectStoreProtocol(Protocol):
|
|
|
266
266
|
msg = "Arrow streaming not implemented"
|
|
267
267
|
raise NotImplementedError(msg)
|
|
268
268
|
|
|
269
|
-
async def read_bytes_async(self, path: "
|
|
269
|
+
async def read_bytes_async(self, path: "str | Path", **kwargs: Any) -> bytes:
|
|
270
270
|
"""Async read bytes from an object."""
|
|
271
271
|
msg = "Async operations not implemented"
|
|
272
272
|
raise NotImplementedError(msg)
|
|
273
273
|
|
|
274
|
-
async def write_bytes_async(self, path: "
|
|
274
|
+
async def write_bytes_async(self, path: "str | Path", data: bytes, **kwargs: Any) -> None:
|
|
275
275
|
"""Async write bytes to an object."""
|
|
276
276
|
msg = "Async operations not implemented"
|
|
277
277
|
raise NotImplementedError(msg)
|
|
278
278
|
|
|
279
|
-
async def read_text_async(self, path: "
|
|
279
|
+
async def read_text_async(self, path: "str | Path", encoding: str = "utf-8", **kwargs: Any) -> str:
|
|
280
280
|
"""Async read text from an object."""
|
|
281
281
|
msg = "Async operations not implemented"
|
|
282
282
|
raise NotImplementedError(msg)
|
|
283
283
|
|
|
284
|
-
async def write_text_async(
|
|
285
|
-
self, path: "Union[str, Path]", data: str, encoding: str = "utf-8", **kwargs: Any
|
|
286
|
-
) -> None:
|
|
284
|
+
async def write_text_async(self, path: "str | Path", data: str, encoding: str = "utf-8", **kwargs: Any) -> None:
|
|
287
285
|
"""Async write text to an object."""
|
|
288
286
|
msg = "Async operations not implemented"
|
|
289
287
|
raise NotImplementedError(msg)
|
|
290
288
|
|
|
291
|
-
async def exists_async(self, path: "
|
|
289
|
+
async def exists_async(self, path: "str | Path", **kwargs: Any) -> bool:
|
|
292
290
|
"""Async check if an object exists."""
|
|
293
291
|
msg = "Async operations not implemented"
|
|
294
292
|
raise NotImplementedError(msg)
|
|
295
293
|
|
|
296
|
-
async def delete_async(self, path: "
|
|
294
|
+
async def delete_async(self, path: "str | Path", **kwargs: Any) -> None:
|
|
297
295
|
"""Async delete an object."""
|
|
298
296
|
msg = "Async operations not implemented"
|
|
299
297
|
raise NotImplementedError(msg)
|
|
@@ -303,27 +301,27 @@ class ObjectStoreProtocol(Protocol):
|
|
|
303
301
|
msg = "Async operations not implemented"
|
|
304
302
|
raise NotImplementedError(msg)
|
|
305
303
|
|
|
306
|
-
async def copy_async(self, source: "
|
|
304
|
+
async def copy_async(self, source: "str | Path", destination: "str | Path", **kwargs: Any) -> None:
|
|
307
305
|
"""Async copy an object."""
|
|
308
306
|
msg = "Async operations not implemented"
|
|
309
307
|
raise NotImplementedError(msg)
|
|
310
308
|
|
|
311
|
-
async def move_async(self, source: "
|
|
309
|
+
async def move_async(self, source: "str | Path", destination: "str | Path", **kwargs: Any) -> None:
|
|
312
310
|
"""Async move an object."""
|
|
313
311
|
msg = "Async operations not implemented"
|
|
314
312
|
raise NotImplementedError(msg)
|
|
315
313
|
|
|
316
|
-
async def get_metadata_async(self, path: "
|
|
314
|
+
async def get_metadata_async(self, path: "str | Path", **kwargs: Any) -> dict[str, Any]:
|
|
317
315
|
"""Async get object metadata."""
|
|
318
316
|
msg = "Async operations not implemented"
|
|
319
317
|
raise NotImplementedError(msg)
|
|
320
318
|
|
|
321
|
-
async def read_arrow_async(self, path: "
|
|
319
|
+
async def read_arrow_async(self, path: "str | Path", **kwargs: Any) -> "ArrowTable":
|
|
322
320
|
"""Async read an Arrow table from storage."""
|
|
323
321
|
msg = "Async arrow reading not implemented"
|
|
324
322
|
raise NotImplementedError(msg)
|
|
325
323
|
|
|
326
|
-
async def write_arrow_async(self, path: "
|
|
324
|
+
async def write_arrow_async(self, path: "str | Path", table: "ArrowTable", **kwargs: Any) -> None:
|
|
327
325
|
"""Async write an Arrow table to storage."""
|
|
328
326
|
msg = "Async arrow writing not implemented"
|
|
329
327
|
raise NotImplementedError(msg)
|
|
@@ -339,7 +337,7 @@ class HasSQLGlotExpressionProtocol(Protocol):
|
|
|
339
337
|
"""Protocol for objects with a sqlglot_expression property."""
|
|
340
338
|
|
|
341
339
|
@property
|
|
342
|
-
def sqlglot_expression(self) -> "
|
|
340
|
+
def sqlglot_expression(self) -> "exp.Expression | None":
|
|
343
341
|
"""Return the SQLGlot expression for this object."""
|
|
344
342
|
...
|
|
345
343
|
|
|
@@ -348,16 +346,24 @@ class HasSQLGlotExpressionProtocol(Protocol):
|
|
|
348
346
|
class HasParameterBuilderProtocol(Protocol):
|
|
349
347
|
"""Protocol for objects that can add parameters."""
|
|
350
348
|
|
|
351
|
-
def add_parameter(self, value: Any, name: "
|
|
349
|
+
def add_parameter(self, value: Any, name: "str | None" = None) -> tuple[Any, str]:
|
|
352
350
|
"""Add a parameter to the builder."""
|
|
353
351
|
...
|
|
354
352
|
|
|
353
|
+
def get_expression(self) -> "exp.Expression | None":
|
|
354
|
+
"""Return the underlying SQLGlot expression."""
|
|
355
|
+
...
|
|
356
|
+
|
|
357
|
+
def set_expression(self, expression: "exp.Expression") -> None:
|
|
358
|
+
"""Replace the underlying SQLGlot expression."""
|
|
359
|
+
...
|
|
360
|
+
|
|
355
361
|
|
|
356
362
|
@runtime_checkable
|
|
357
363
|
class HasExpressionProtocol(Protocol):
|
|
358
364
|
"""Protocol for objects with an _expression attribute."""
|
|
359
365
|
|
|
360
|
-
_expression: "
|
|
366
|
+
_expression: "exp.Expression | None"
|
|
361
367
|
|
|
362
368
|
|
|
363
369
|
@runtime_checkable
|
|
@@ -373,21 +379,21 @@ class HasToStatementProtocol(Protocol):
|
|
|
373
379
|
class SQLBuilderProtocol(Protocol):
|
|
374
380
|
"""Protocol for SQL query builders."""
|
|
375
381
|
|
|
376
|
-
_expression: "
|
|
382
|
+
_expression: "exp.Expression | None"
|
|
377
383
|
_parameters: dict[str, Any]
|
|
378
384
|
_parameter_counter: int
|
|
379
385
|
_columns: Any # Optional attribute for some builders
|
|
380
386
|
_table: Any # Optional attribute for some builders
|
|
381
387
|
_with_ctes: Any # Optional attribute for some builders
|
|
382
388
|
dialect: Any
|
|
383
|
-
dialect_name: "
|
|
389
|
+
dialect_name: "str | None"
|
|
384
390
|
|
|
385
391
|
@property
|
|
386
392
|
def parameters(self) -> dict[str, Any]:
|
|
387
393
|
"""Public access to query parameters."""
|
|
388
394
|
...
|
|
389
395
|
|
|
390
|
-
def add_parameter(self, value: Any, name: "
|
|
396
|
+
def add_parameter(self, value: Any, name: "str | None" = None) -> tuple[Any, str]:
|
|
391
397
|
"""Add a parameter to the builder."""
|
|
392
398
|
...
|
|
393
399
|
|
|
@@ -399,14 +405,38 @@ class SQLBuilderProtocol(Protocol):
|
|
|
399
405
|
"""Replace literal values in an expression with bound parameters."""
|
|
400
406
|
...
|
|
401
407
|
|
|
402
|
-
def build(self) -> "
|
|
408
|
+
def build(self) -> "exp.Expression | Any":
|
|
403
409
|
"""Build and return the final expression."""
|
|
404
410
|
...
|
|
405
411
|
|
|
412
|
+
def _merge_sql_object_parameters(self, sql_obj: Any) -> None:
|
|
413
|
+
"""Merge parameters from SQL objects into the builder."""
|
|
414
|
+
...
|
|
415
|
+
|
|
416
|
+
def _build_final_expression(self, *, copy: bool = False) -> "exp.Expression":
|
|
417
|
+
"""Return the expression with attached CTEs."""
|
|
418
|
+
...
|
|
419
|
+
|
|
420
|
+
def _spawn_like_self(self) -> "Self":
|
|
421
|
+
"""Create a new builder with matching configuration."""
|
|
422
|
+
...
|
|
423
|
+
|
|
424
|
+
def get_expression(self) -> "exp.Expression | None":
|
|
425
|
+
"""Return the underlying SQLGlot expression."""
|
|
426
|
+
...
|
|
427
|
+
|
|
428
|
+
def set_expression(self, expression: "exp.Expression") -> None:
|
|
429
|
+
"""Replace the underlying SQLGlot expression."""
|
|
430
|
+
...
|
|
431
|
+
|
|
432
|
+
def generate_unique_parameter_name(self, base_name: str) -> str:
|
|
433
|
+
"""Generate a unique parameter name exposed via public API."""
|
|
434
|
+
...
|
|
435
|
+
|
|
406
436
|
|
|
407
437
|
class SelectBuilderProtocol(SQLBuilderProtocol, Protocol):
|
|
408
438
|
"""Protocol for SELECT query builders."""
|
|
409
439
|
|
|
410
|
-
def select(self, *columns: "
|
|
440
|
+
def select(self, *columns: "str | exp.Expression") -> Self:
|
|
411
441
|
"""Add SELECT columns to the query."""
|
|
412
442
|
...
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Shared utilities for storage backends."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from sqlspec.exceptions import MissingDependencyError
|
|
6
|
+
from sqlspec.typing import PYARROW_INSTALLED
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
__all__ = ("ensure_pyarrow", "resolve_storage_path")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def ensure_pyarrow() -> None:
|
|
15
|
+
"""Ensure PyArrow is available for Arrow operations.
|
|
16
|
+
|
|
17
|
+
Raises:
|
|
18
|
+
MissingDependencyError: If pyarrow is not installed.
|
|
19
|
+
"""
|
|
20
|
+
if not PYARROW_INSTALLED:
|
|
21
|
+
raise MissingDependencyError(package="pyarrow", install_package="pyarrow")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def resolve_storage_path(
|
|
25
|
+
path: "str | Path", base_path: str = "", protocol: str = "file", strip_file_scheme: bool = True
|
|
26
|
+
) -> str:
|
|
27
|
+
"""Resolve path relative to base_path with protocol-specific handling.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
path: Path to resolve (may include file:// scheme).
|
|
31
|
+
base_path: Base path to prepend if path is relative.
|
|
32
|
+
protocol: Storage protocol (file, s3, gs, etc.).
|
|
33
|
+
strip_file_scheme: Whether to strip file:// prefix.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Resolved path string suitable for the storage backend.
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
>>> resolve_storage_path("/data/file.txt", protocol="file")
|
|
40
|
+
'data/file.txt'
|
|
41
|
+
|
|
42
|
+
>>> resolve_storage_path(
|
|
43
|
+
... "file.txt", base_path="/base", protocol="file"
|
|
44
|
+
... )
|
|
45
|
+
'base/file.txt'
|
|
46
|
+
|
|
47
|
+
>>> resolve_storage_path(
|
|
48
|
+
... "file:///data/file.txt", strip_file_scheme=True
|
|
49
|
+
... )
|
|
50
|
+
'data/file.txt'
|
|
51
|
+
|
|
52
|
+
>>> resolve_storage_path(
|
|
53
|
+
... "/data/subdir/file.txt",
|
|
54
|
+
... base_path="/data",
|
|
55
|
+
... protocol="file",
|
|
56
|
+
... )
|
|
57
|
+
'subdir/file.txt'
|
|
58
|
+
"""
|
|
59
|
+
from pathlib import Path as PathlibPath
|
|
60
|
+
|
|
61
|
+
path_str = str(path)
|
|
62
|
+
|
|
63
|
+
if strip_file_scheme and path_str.startswith("file://"):
|
|
64
|
+
path_str = path_str.removeprefix("file://")
|
|
65
|
+
|
|
66
|
+
# For local file protocol
|
|
67
|
+
if protocol == "file":
|
|
68
|
+
path_obj = PathlibPath(path_str)
|
|
69
|
+
|
|
70
|
+
# Absolute path handling
|
|
71
|
+
if path_obj.is_absolute():
|
|
72
|
+
if base_path:
|
|
73
|
+
base_obj = PathlibPath(base_path)
|
|
74
|
+
# Try to make path relative to base_path
|
|
75
|
+
try:
|
|
76
|
+
relative = path_obj.relative_to(base_obj)
|
|
77
|
+
# Return joined path for FSSpec-style backends
|
|
78
|
+
return f"{base_path.rstrip('/')}/{relative}"
|
|
79
|
+
except ValueError:
|
|
80
|
+
# Path is outside base_path
|
|
81
|
+
return path_str.lstrip("/")
|
|
82
|
+
# No base_path - strip leading /
|
|
83
|
+
return path_str.lstrip("/")
|
|
84
|
+
|
|
85
|
+
# Relative path with base_path - join them
|
|
86
|
+
if base_path:
|
|
87
|
+
return f"{base_path.rstrip('/')}/{path_str}"
|
|
88
|
+
|
|
89
|
+
# Relative path without base_path
|
|
90
|
+
return path_str
|
|
91
|
+
|
|
92
|
+
# For cloud storage protocols (s3, gs, etc.), join with base_path
|
|
93
|
+
if not base_path:
|
|
94
|
+
return path_str
|
|
95
|
+
|
|
96
|
+
clean_base = base_path.rstrip("/")
|
|
97
|
+
clean_path = path_str.lstrip("/")
|
|
98
|
+
return f"{clean_base}/{clean_path}"
|