sqlspec 0.36.0__cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.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.
- ac8f31065839703b4e70__mypyc.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/__init__.py +140 -0
- sqlspec/__main__.py +12 -0
- sqlspec/__metadata__.py +14 -0
- sqlspec/_serialization.py +315 -0
- sqlspec/_typing.py +700 -0
- sqlspec/adapters/__init__.py +0 -0
- sqlspec/adapters/adbc/__init__.py +5 -0
- sqlspec/adapters/adbc/_typing.py +82 -0
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +1273 -0
- sqlspec/adapters/adbc/config.py +295 -0
- sqlspec/adapters/adbc/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/adbc/core.py +735 -0
- sqlspec/adapters/adbc/data_dictionary.py +334 -0
- sqlspec/adapters/adbc/driver.py +529 -0
- sqlspec/adapters/adbc/events/__init__.py +5 -0
- sqlspec/adapters/adbc/events/store.py +285 -0
- sqlspec/adapters/adbc/litestar/__init__.py +5 -0
- sqlspec/adapters/adbc/litestar/store.py +502 -0
- sqlspec/adapters/adbc/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/adbc/type_converter.py +140 -0
- sqlspec/adapters/aiosqlite/__init__.py +25 -0
- sqlspec/adapters/aiosqlite/_typing.py +82 -0
- sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/adk/store.py +818 -0
- sqlspec/adapters/aiosqlite/config.py +334 -0
- sqlspec/adapters/aiosqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/aiosqlite/core.py +315 -0
- sqlspec/adapters/aiosqlite/data_dictionary.py +208 -0
- sqlspec/adapters/aiosqlite/driver.py +313 -0
- sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/events/store.py +20 -0
- sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
- sqlspec/adapters/aiosqlite/pool.py +533 -0
- sqlspec/adapters/asyncmy/__init__.py +21 -0
- sqlspec/adapters/asyncmy/_typing.py +87 -0
- sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
- sqlspec/adapters/asyncmy/adk/store.py +703 -0
- sqlspec/adapters/asyncmy/config.py +302 -0
- sqlspec/adapters/asyncmy/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/asyncmy/core.py +360 -0
- sqlspec/adapters/asyncmy/data_dictionary.py +124 -0
- sqlspec/adapters/asyncmy/driver.py +383 -0
- sqlspec/adapters/asyncmy/events/__init__.py +5 -0
- sqlspec/adapters/asyncmy/events/store.py +104 -0
- sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncmy/litestar/store.py +296 -0
- sqlspec/adapters/asyncpg/__init__.py +19 -0
- sqlspec/adapters/asyncpg/_typing.py +88 -0
- sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
- sqlspec/adapters/asyncpg/adk/store.py +748 -0
- sqlspec/adapters/asyncpg/config.py +569 -0
- sqlspec/adapters/asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/asyncpg/core.py +367 -0
- sqlspec/adapters/asyncpg/data_dictionary.py +162 -0
- sqlspec/adapters/asyncpg/driver.py +487 -0
- sqlspec/adapters/asyncpg/events/__init__.py +6 -0
- sqlspec/adapters/asyncpg/events/backend.py +286 -0
- sqlspec/adapters/asyncpg/events/store.py +40 -0
- sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncpg/litestar/store.py +251 -0
- sqlspec/adapters/bigquery/__init__.py +14 -0
- sqlspec/adapters/bigquery/_typing.py +86 -0
- sqlspec/adapters/bigquery/adk/__init__.py +5 -0
- sqlspec/adapters/bigquery/adk/store.py +827 -0
- sqlspec/adapters/bigquery/config.py +353 -0
- sqlspec/adapters/bigquery/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/bigquery/core.py +715 -0
- sqlspec/adapters/bigquery/data_dictionary.py +128 -0
- sqlspec/adapters/bigquery/driver.py +548 -0
- sqlspec/adapters/bigquery/events/__init__.py +5 -0
- sqlspec/adapters/bigquery/events/store.py +139 -0
- sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
- sqlspec/adapters/bigquery/litestar/store.py +325 -0
- sqlspec/adapters/bigquery/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/bigquery/type_converter.py +107 -0
- sqlspec/adapters/cockroach_asyncpg/__init__.py +24 -0
- sqlspec/adapters/cockroach_asyncpg/_typing.py +72 -0
- sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/adk/store.py +410 -0
- sqlspec/adapters/cockroach_asyncpg/config.py +238 -0
- sqlspec/adapters/cockroach_asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
- sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +107 -0
- sqlspec/adapters/cockroach_asyncpg/driver.py +144 -0
- sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
- sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
- sqlspec/adapters/cockroach_psycopg/__init__.py +38 -0
- sqlspec/adapters/cockroach_psycopg/_typing.py +129 -0
- sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
- sqlspec/adapters/cockroach_psycopg/adk/store.py +868 -0
- sqlspec/adapters/cockroach_psycopg/config.py +484 -0
- sqlspec/adapters/cockroach_psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/cockroach_psycopg/core.py +63 -0
- sqlspec/adapters/cockroach_psycopg/data_dictionary.py +215 -0
- sqlspec/adapters/cockroach_psycopg/driver.py +284 -0
- sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
- sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
- sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
- sqlspec/adapters/cockroach_psycopg/litestar/store.py +325 -0
- sqlspec/adapters/duckdb/__init__.py +25 -0
- sqlspec/adapters/duckdb/_typing.py +81 -0
- sqlspec/adapters/duckdb/adk/__init__.py +14 -0
- sqlspec/adapters/duckdb/adk/store.py +850 -0
- sqlspec/adapters/duckdb/config.py +463 -0
- sqlspec/adapters/duckdb/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/duckdb/core.py +257 -0
- sqlspec/adapters/duckdb/data_dictionary.py +140 -0
- sqlspec/adapters/duckdb/driver.py +430 -0
- sqlspec/adapters/duckdb/events/__init__.py +5 -0
- sqlspec/adapters/duckdb/events/store.py +57 -0
- sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
- sqlspec/adapters/duckdb/litestar/store.py +330 -0
- sqlspec/adapters/duckdb/pool.py +293 -0
- sqlspec/adapters/duckdb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/duckdb/type_converter.py +118 -0
- sqlspec/adapters/mock/__init__.py +72 -0
- sqlspec/adapters/mock/_typing.py +147 -0
- sqlspec/adapters/mock/config.py +483 -0
- sqlspec/adapters/mock/core.py +319 -0
- sqlspec/adapters/mock/data_dictionary.py +366 -0
- sqlspec/adapters/mock/driver.py +721 -0
- sqlspec/adapters/mysqlconnector/__init__.py +36 -0
- sqlspec/adapters/mysqlconnector/_typing.py +141 -0
- sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
- sqlspec/adapters/mysqlconnector/adk/store.py +1060 -0
- sqlspec/adapters/mysqlconnector/config.py +394 -0
- sqlspec/adapters/mysqlconnector/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/mysqlconnector/core.py +303 -0
- sqlspec/adapters/mysqlconnector/data_dictionary.py +235 -0
- sqlspec/adapters/mysqlconnector/driver.py +483 -0
- sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
- sqlspec/adapters/mysqlconnector/events/store.py +98 -0
- sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
- sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
- sqlspec/adapters/oracledb/__init__.py +60 -0
- sqlspec/adapters/oracledb/_numpy_handlers.py +141 -0
- sqlspec/adapters/oracledb/_typing.py +182 -0
- sqlspec/adapters/oracledb/_uuid_handlers.py +166 -0
- sqlspec/adapters/oracledb/adk/__init__.py +10 -0
- sqlspec/adapters/oracledb/adk/store.py +2369 -0
- sqlspec/adapters/oracledb/config.py +550 -0
- sqlspec/adapters/oracledb/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/oracledb/core.py +543 -0
- sqlspec/adapters/oracledb/data_dictionary.py +536 -0
- sqlspec/adapters/oracledb/driver.py +1229 -0
- sqlspec/adapters/oracledb/events/__init__.py +16 -0
- sqlspec/adapters/oracledb/events/backend.py +347 -0
- sqlspec/adapters/oracledb/events/store.py +420 -0
- sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
- sqlspec/adapters/oracledb/litestar/store.py +781 -0
- sqlspec/adapters/oracledb/migrations.py +535 -0
- sqlspec/adapters/oracledb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/oracledb/type_converter.py +211 -0
- sqlspec/adapters/psqlpy/__init__.py +17 -0
- sqlspec/adapters/psqlpy/_typing.py +79 -0
- sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
- sqlspec/adapters/psqlpy/adk/store.py +766 -0
- sqlspec/adapters/psqlpy/config.py +304 -0
- sqlspec/adapters/psqlpy/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psqlpy/core.py +480 -0
- sqlspec/adapters/psqlpy/data_dictionary.py +126 -0
- sqlspec/adapters/psqlpy/driver.py +438 -0
- sqlspec/adapters/psqlpy/events/__init__.py +6 -0
- sqlspec/adapters/psqlpy/events/backend.py +310 -0
- sqlspec/adapters/psqlpy/events/store.py +20 -0
- sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
- sqlspec/adapters/psqlpy/litestar/store.py +270 -0
- sqlspec/adapters/psqlpy/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psqlpy/type_converter.py +113 -0
- sqlspec/adapters/psycopg/__init__.py +32 -0
- sqlspec/adapters/psycopg/_typing.py +164 -0
- sqlspec/adapters/psycopg/adk/__init__.py +10 -0
- sqlspec/adapters/psycopg/adk/store.py +1387 -0
- sqlspec/adapters/psycopg/config.py +576 -0
- sqlspec/adapters/psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psycopg/core.py +450 -0
- sqlspec/adapters/psycopg/data_dictionary.py +289 -0
- sqlspec/adapters/psycopg/driver.py +975 -0
- sqlspec/adapters/psycopg/events/__init__.py +20 -0
- sqlspec/adapters/psycopg/events/backend.py +458 -0
- sqlspec/adapters/psycopg/events/store.py +42 -0
- sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
- sqlspec/adapters/psycopg/litestar/store.py +552 -0
- sqlspec/adapters/psycopg/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psycopg/type_converter.py +93 -0
- sqlspec/adapters/pymysql/__init__.py +21 -0
- sqlspec/adapters/pymysql/_typing.py +71 -0
- sqlspec/adapters/pymysql/adk/__init__.py +5 -0
- sqlspec/adapters/pymysql/adk/store.py +540 -0
- sqlspec/adapters/pymysql/config.py +195 -0
- sqlspec/adapters/pymysql/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/pymysql/core.py +299 -0
- sqlspec/adapters/pymysql/data_dictionary.py +122 -0
- sqlspec/adapters/pymysql/driver.py +259 -0
- sqlspec/adapters/pymysql/events/__init__.py +5 -0
- sqlspec/adapters/pymysql/events/store.py +50 -0
- sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
- sqlspec/adapters/pymysql/litestar/store.py +232 -0
- sqlspec/adapters/pymysql/pool.py +137 -0
- sqlspec/adapters/spanner/__init__.py +40 -0
- sqlspec/adapters/spanner/_typing.py +86 -0
- sqlspec/adapters/spanner/adk/__init__.py +5 -0
- sqlspec/adapters/spanner/adk/store.py +732 -0
- sqlspec/adapters/spanner/config.py +352 -0
- sqlspec/adapters/spanner/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/spanner/core.py +188 -0
- sqlspec/adapters/spanner/data_dictionary.py +120 -0
- sqlspec/adapters/spanner/dialect/__init__.py +6 -0
- sqlspec/adapters/spanner/dialect/_spangres.py +57 -0
- sqlspec/adapters/spanner/dialect/_spanner.py +130 -0
- sqlspec/adapters/spanner/driver.py +373 -0
- sqlspec/adapters/spanner/events/__init__.py +5 -0
- sqlspec/adapters/spanner/events/store.py +187 -0
- sqlspec/adapters/spanner/litestar/__init__.py +5 -0
- sqlspec/adapters/spanner/litestar/store.py +291 -0
- sqlspec/adapters/spanner/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/spanner/type_converter.py +331 -0
- sqlspec/adapters/sqlite/__init__.py +19 -0
- sqlspec/adapters/sqlite/_typing.py +80 -0
- sqlspec/adapters/sqlite/adk/__init__.py +5 -0
- sqlspec/adapters/sqlite/adk/store.py +958 -0
- sqlspec/adapters/sqlite/config.py +280 -0
- sqlspec/adapters/sqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/sqlite/core.py +312 -0
- sqlspec/adapters/sqlite/data_dictionary.py +202 -0
- sqlspec/adapters/sqlite/driver.py +359 -0
- sqlspec/adapters/sqlite/events/__init__.py +5 -0
- sqlspec/adapters/sqlite/events/store.py +20 -0
- sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/sqlite/litestar/store.py +316 -0
- sqlspec/adapters/sqlite/pool.py +198 -0
- sqlspec/adapters/sqlite/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/sqlite/type_converter.py +114 -0
- sqlspec/base.py +747 -0
- sqlspec/builder/__init__.py +179 -0
- sqlspec/builder/_base.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_base.py +1022 -0
- sqlspec/builder/_column.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_column.py +521 -0
- sqlspec/builder/_ddl.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_ddl.py +1642 -0
- sqlspec/builder/_delete.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_delete.py +95 -0
- sqlspec/builder/_dml.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_dml.py +365 -0
- sqlspec/builder/_explain.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_explain.py +579 -0
- sqlspec/builder/_expression_wrappers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_expression_wrappers.py +46 -0
- sqlspec/builder/_factory.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_factory.py +1697 -0
- sqlspec/builder/_insert.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_insert.py +328 -0
- sqlspec/builder/_join.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_join.py +499 -0
- sqlspec/builder/_merge.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_merge.py +821 -0
- sqlspec/builder/_parsing_utils.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_parsing_utils.py +297 -0
- sqlspec/builder/_select.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_select.py +1660 -0
- sqlspec/builder/_temporal.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_temporal.py +139 -0
- sqlspec/builder/_update.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_update.py +173 -0
- sqlspec/builder/_vector_expressions.py +267 -0
- sqlspec/cli.py +911 -0
- sqlspec/config.py +1755 -0
- sqlspec/core/__init__.py +374 -0
- sqlspec/core/_correlation.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/_correlation.py +176 -0
- sqlspec/core/cache.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/cache.py +1069 -0
- sqlspec/core/compiler.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/compiler.py +954 -0
- sqlspec/core/explain.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/explain.py +275 -0
- sqlspec/core/filters.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/filters.py +952 -0
- sqlspec/core/hashing.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/hashing.py +262 -0
- sqlspec/core/metrics.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/metrics.py +83 -0
- sqlspec/core/parameters/__init__.py +71 -0
- sqlspec/core/parameters/_alignment.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_alignment.py +270 -0
- sqlspec/core/parameters/_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_converter.py +543 -0
- sqlspec/core/parameters/_processor.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_processor.py +505 -0
- sqlspec/core/parameters/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_registry.py +206 -0
- sqlspec/core/parameters/_transformers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_transformers.py +292 -0
- sqlspec/core/parameters/_types.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_types.py +499 -0
- sqlspec/core/parameters/_validator.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_validator.py +180 -0
- sqlspec/core/pipeline.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/pipeline.py +319 -0
- sqlspec/core/query_modifiers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/query_modifiers.py +437 -0
- sqlspec/core/result/__init__.py +23 -0
- sqlspec/core/result/_base.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/result/_base.py +1121 -0
- sqlspec/core/result/_io.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/result/_io.py +28 -0
- sqlspec/core/splitter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/splitter.py +966 -0
- sqlspec/core/stack.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/stack.py +163 -0
- sqlspec/core/statement.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/statement.py +1503 -0
- sqlspec/core/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/type_converter.py +339 -0
- sqlspec/data_dictionary/__init__.py +22 -0
- sqlspec/data_dictionary/_loader.py +123 -0
- sqlspec/data_dictionary/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/_registry.py +74 -0
- sqlspec/data_dictionary/_types.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/_types.py +121 -0
- sqlspec/data_dictionary/dialects/__init__.py +21 -0
- sqlspec/data_dictionary/dialects/bigquery.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/bigquery.py +49 -0
- sqlspec/data_dictionary/dialects/cockroachdb.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/cockroachdb.py +43 -0
- sqlspec/data_dictionary/dialects/duckdb.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/duckdb.py +47 -0
- sqlspec/data_dictionary/dialects/mysql.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/mysql.py +42 -0
- sqlspec/data_dictionary/dialects/oracle.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/oracle.py +34 -0
- sqlspec/data_dictionary/dialects/postgres.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/postgres.py +46 -0
- sqlspec/data_dictionary/dialects/spanner.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/spanner.py +37 -0
- sqlspec/data_dictionary/dialects/sqlite.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/sqlite.py +42 -0
- sqlspec/data_dictionary/sql/.gitkeep +0 -0
- sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
- sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
- sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
- sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
- sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
- sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
- sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
- sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
- sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
- sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
- sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
- sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
- sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
- sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
- sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
- sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
- sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
- sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
- sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
- sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
- sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
- sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
- sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
- sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
- sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
- sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
- sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
- sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
- sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
- sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
- sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
- sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
- sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
- sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
- sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
- sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
- sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
- sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
- sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
- sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
- sqlspec/driver/__init__.py +32 -0
- sqlspec/driver/_async.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_async.py +1737 -0
- sqlspec/driver/_common.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_common.py +1478 -0
- sqlspec/driver/_sql_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_sql_helpers.py +148 -0
- sqlspec/driver/_storage_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_storage_helpers.py +144 -0
- sqlspec/driver/_sync.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_sync.py +1710 -0
- sqlspec/exceptions.py +338 -0
- sqlspec/extensions/__init__.py +0 -0
- sqlspec/extensions/adk/__init__.py +70 -0
- sqlspec/extensions/adk/_types.py +51 -0
- sqlspec/extensions/adk/converters.py +172 -0
- sqlspec/extensions/adk/memory/__init__.py +69 -0
- sqlspec/extensions/adk/memory/_types.py +30 -0
- sqlspec/extensions/adk/memory/converters.py +149 -0
- sqlspec/extensions/adk/memory/service.py +217 -0
- sqlspec/extensions/adk/memory/store.py +569 -0
- sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +246 -0
- sqlspec/extensions/adk/migrations/__init__.py +0 -0
- sqlspec/extensions/adk/service.py +225 -0
- sqlspec/extensions/adk/store.py +567 -0
- sqlspec/extensions/events/__init__.py +51 -0
- sqlspec/extensions/events/_channel.py +703 -0
- sqlspec/extensions/events/_hints.py +45 -0
- sqlspec/extensions/events/_models.py +23 -0
- sqlspec/extensions/events/_payload.py +69 -0
- sqlspec/extensions/events/_protocols.py +134 -0
- sqlspec/extensions/events/_queue.py +461 -0
- sqlspec/extensions/events/_store.py +209 -0
- sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
- sqlspec/extensions/events/migrations/__init__.py +3 -0
- sqlspec/extensions/fastapi/__init__.py +19 -0
- sqlspec/extensions/fastapi/extension.py +351 -0
- sqlspec/extensions/fastapi/providers.py +607 -0
- sqlspec/extensions/flask/__init__.py +37 -0
- sqlspec/extensions/flask/_state.py +76 -0
- sqlspec/extensions/flask/_utils.py +71 -0
- sqlspec/extensions/flask/extension.py +519 -0
- sqlspec/extensions/litestar/__init__.py +28 -0
- sqlspec/extensions/litestar/_utils.py +52 -0
- sqlspec/extensions/litestar/channels.py +165 -0
- sqlspec/extensions/litestar/cli.py +102 -0
- sqlspec/extensions/litestar/config.py +90 -0
- sqlspec/extensions/litestar/handlers.py +316 -0
- sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
- sqlspec/extensions/litestar/migrations/__init__.py +3 -0
- sqlspec/extensions/litestar/plugin.py +671 -0
- sqlspec/extensions/litestar/providers.py +526 -0
- sqlspec/extensions/litestar/store.py +296 -0
- sqlspec/extensions/otel/__init__.py +58 -0
- sqlspec/extensions/prometheus/__init__.py +113 -0
- sqlspec/extensions/starlette/__init__.py +19 -0
- sqlspec/extensions/starlette/_state.py +30 -0
- sqlspec/extensions/starlette/_utils.py +96 -0
- sqlspec/extensions/starlette/extension.py +346 -0
- sqlspec/extensions/starlette/middleware.py +235 -0
- sqlspec/loader.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/loader.py +702 -0
- sqlspec/migrations/__init__.py +36 -0
- sqlspec/migrations/base.py +731 -0
- sqlspec/migrations/commands.py +1232 -0
- sqlspec/migrations/context.py +157 -0
- sqlspec/migrations/fix.py +204 -0
- sqlspec/migrations/loaders.py +443 -0
- sqlspec/migrations/runner.py +1172 -0
- sqlspec/migrations/templates.py +234 -0
- sqlspec/migrations/tracker.py +611 -0
- sqlspec/migrations/utils.py +256 -0
- sqlspec/migrations/validation.py +207 -0
- sqlspec/migrations/version.py +446 -0
- sqlspec/observability/__init__.py +55 -0
- sqlspec/observability/_common.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_common.py +77 -0
- sqlspec/observability/_config.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_config.py +348 -0
- sqlspec/observability/_diagnostics.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_diagnostics.py +74 -0
- sqlspec/observability/_dispatcher.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_dispatcher.py +152 -0
- sqlspec/observability/_formatters/__init__.py +13 -0
- sqlspec/observability/_formatters/_aws.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_aws.py +102 -0
- sqlspec/observability/_formatters/_azure.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_azure.py +96 -0
- sqlspec/observability/_formatters/_base.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_base.py +57 -0
- sqlspec/observability/_formatters/_gcp.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_gcp.py +131 -0
- sqlspec/observability/_formatting.py +58 -0
- sqlspec/observability/_observer.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_observer.py +357 -0
- sqlspec/observability/_runtime.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_runtime.py +420 -0
- sqlspec/observability/_sampling.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_sampling.py +188 -0
- sqlspec/observability/_spans.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_spans.py +161 -0
- sqlspec/protocols.py +916 -0
- sqlspec/py.typed +0 -0
- sqlspec/storage/__init__.py +48 -0
- sqlspec/storage/_utils.py +104 -0
- sqlspec/storage/backends/__init__.py +1 -0
- sqlspec/storage/backends/base.py +253 -0
- sqlspec/storage/backends/fsspec.py +529 -0
- sqlspec/storage/backends/local.py +441 -0
- sqlspec/storage/backends/obstore.py +916 -0
- sqlspec/storage/errors.py +104 -0
- sqlspec/storage/pipeline.py +582 -0
- sqlspec/storage/registry.py +301 -0
- sqlspec/typing.py +395 -0
- sqlspec/utils/__init__.py +7 -0
- sqlspec/utils/arrow_helpers.py +318 -0
- sqlspec/utils/config_tools.py +332 -0
- sqlspec/utils/correlation.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/correlation.py +134 -0
- sqlspec/utils/deprecation.py +190 -0
- sqlspec/utils/fixtures.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/fixtures.py +258 -0
- sqlspec/utils/logging.py +222 -0
- sqlspec/utils/module_loader.py +306 -0
- sqlspec/utils/portal.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/portal.py +375 -0
- sqlspec/utils/schema.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/schema.py +485 -0
- sqlspec/utils/serializers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/serializers.py +408 -0
- sqlspec/utils/singleton.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/singleton.py +41 -0
- sqlspec/utils/sync_tools.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/sync_tools.py +311 -0
- sqlspec/utils/text.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/text.py +108 -0
- sqlspec/utils/type_converters.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/type_converters.py +128 -0
- sqlspec/utils/type_guards.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/type_guards.py +1360 -0
- sqlspec/utils/uuids.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/uuids.py +225 -0
- sqlspec-0.36.0.dist-info/METADATA +205 -0
- sqlspec-0.36.0.dist-info/RECORD +531 -0
- sqlspec-0.36.0.dist-info/WHEEL +7 -0
- sqlspec-0.36.0.dist-info/entry_points.txt +2 -0
- sqlspec-0.36.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# pyright: reportPrivateUsage=false
|
|
2
|
+
"""Native and hybrid PostgreSQL backends for EventChannel."""
|
|
3
|
+
|
|
4
|
+
import asyncio
|
|
5
|
+
import contextlib
|
|
6
|
+
import logging
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
9
|
+
|
|
10
|
+
from sqlspec.core import SQL
|
|
11
|
+
from sqlspec.exceptions import EventChannelError, ImproperConfigurationError
|
|
12
|
+
from sqlspec.extensions.events import (
|
|
13
|
+
AsyncTableEventQueue,
|
|
14
|
+
EventMessage,
|
|
15
|
+
build_queue_backend,
|
|
16
|
+
decode_notify_payload,
|
|
17
|
+
encode_notify_payload,
|
|
18
|
+
normalize_event_channel_name,
|
|
19
|
+
)
|
|
20
|
+
from sqlspec.utils.logging import get_logger, log_with_context
|
|
21
|
+
from sqlspec.utils.serializers import to_json
|
|
22
|
+
from sqlspec.utils.type_guards import has_add_listener, has_notifies, is_notification
|
|
23
|
+
from sqlspec.utils.uuids import uuid4
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from sqlspec.adapters.asyncpg.config import AsyncpgConfig
|
|
27
|
+
|
|
28
|
+
logger = get_logger("sqlspec.events.postgres")
|
|
29
|
+
|
|
30
|
+
__all__ = ("AsyncpgEventsBackend", "AsyncpgHybridEventsBackend", "create_event_backend")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class _AsyncpgNotificationListener:
|
|
34
|
+
__slots__ = ("_channel", "_future", "_loop")
|
|
35
|
+
|
|
36
|
+
def __init__(self, channel: str, future: "asyncio.Future[str]", loop: "asyncio.AbstractEventLoop") -> None:
|
|
37
|
+
self._channel = channel
|
|
38
|
+
self._future = future
|
|
39
|
+
self._loop = loop
|
|
40
|
+
|
|
41
|
+
def __call__(self, _conn: Any, _pid: int, notified_channel: str, payload: str) -> None:
|
|
42
|
+
if notified_channel != self._channel or self._future.done():
|
|
43
|
+
return
|
|
44
|
+
self._loop.call_soon_threadsafe(self._future.set_result, payload)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class AsyncpgHybridEventsBackend:
|
|
48
|
+
"""Hybrid backend combining durable queue with LISTEN/NOTIFY wakeups."""
|
|
49
|
+
|
|
50
|
+
__slots__ = ("_config", "_listen_connection", "_listen_connection_cm", "_queue", "_runtime")
|
|
51
|
+
|
|
52
|
+
supports_sync = False
|
|
53
|
+
supports_async = True
|
|
54
|
+
backend_name = "listen_notify_durable"
|
|
55
|
+
|
|
56
|
+
def __init__(self, config: "AsyncpgConfig", queue: "AsyncTableEventQueue") -> None:
|
|
57
|
+
if not config.is_async:
|
|
58
|
+
msg = "Asyncpg hybrid backend requires an async adapter"
|
|
59
|
+
raise ImproperConfigurationError(msg)
|
|
60
|
+
self._config = config
|
|
61
|
+
self._runtime = config.get_observability_runtime()
|
|
62
|
+
self._queue = queue
|
|
63
|
+
self._listen_connection: Any | None = None
|
|
64
|
+
self._listen_connection_cm: Any | None = None
|
|
65
|
+
log_with_context(
|
|
66
|
+
logger,
|
|
67
|
+
logging.DEBUG,
|
|
68
|
+
"event.listen",
|
|
69
|
+
adapter_name="asyncpg",
|
|
70
|
+
backend_name=self.backend_name,
|
|
71
|
+
mode="async",
|
|
72
|
+
status="backend_ready",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
async def publish(self, channel: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None" = None) -> str:
|
|
76
|
+
event_id = uuid4().hex
|
|
77
|
+
await self._publish_durable(channel, event_id, payload, metadata)
|
|
78
|
+
self._runtime.increment_metric("events.publish.native")
|
|
79
|
+
return event_id
|
|
80
|
+
|
|
81
|
+
async def dequeue(self, channel: str, poll_interval: float) -> EventMessage | None:
|
|
82
|
+
connection = await self._ensure_listener(channel)
|
|
83
|
+
if has_notifies(connection):
|
|
84
|
+
message = await self._dequeue_with_notifies(connection, channel, poll_interval)
|
|
85
|
+
else:
|
|
86
|
+
message = await self._queue.dequeue(channel, poll_interval)
|
|
87
|
+
return message
|
|
88
|
+
|
|
89
|
+
async def ack(self, event_id: str) -> None:
|
|
90
|
+
await self._queue.ack(event_id)
|
|
91
|
+
self._runtime.increment_metric("events.ack")
|
|
92
|
+
|
|
93
|
+
async def nack(self, event_id: str) -> None:
|
|
94
|
+
await self._queue.nack(event_id)
|
|
95
|
+
self._runtime.increment_metric("events.nack")
|
|
96
|
+
|
|
97
|
+
async def shutdown(self) -> None:
|
|
98
|
+
"""Shutdown the listener connection and release resources."""
|
|
99
|
+
if self._listen_connection_cm is not None:
|
|
100
|
+
with contextlib.suppress(Exception):
|
|
101
|
+
await self._listen_connection_cm.__aexit__(None, None, None)
|
|
102
|
+
self._listen_connection = None
|
|
103
|
+
self._listen_connection_cm = None
|
|
104
|
+
|
|
105
|
+
async def _ensure_listener(self, channel: str) -> Any:
|
|
106
|
+
"""Ensure a dedicated connection is listening on the given channel."""
|
|
107
|
+
if self._listen_connection is None:
|
|
108
|
+
validated_channel = normalize_event_channel_name(channel)
|
|
109
|
+
self._listen_connection_cm = self._config.provide_connection()
|
|
110
|
+
self._listen_connection = await self._listen_connection_cm.__aenter__()
|
|
111
|
+
if self._listen_connection is not None:
|
|
112
|
+
await self._listen_connection.execute(f"LISTEN {validated_channel}")
|
|
113
|
+
return self._listen_connection
|
|
114
|
+
|
|
115
|
+
async def _publish_durable(
|
|
116
|
+
self, channel: str, event_id: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None"
|
|
117
|
+
) -> None:
|
|
118
|
+
"""Insert event into durable queue and send NOTIFY wakeup signal."""
|
|
119
|
+
now = datetime.now(timezone.utc)
|
|
120
|
+
async with self._config.provide_session() as driver:
|
|
121
|
+
await driver.execute(
|
|
122
|
+
SQL(
|
|
123
|
+
self._queue._upsert_sql,
|
|
124
|
+
{
|
|
125
|
+
"event_id": event_id,
|
|
126
|
+
"channel": channel,
|
|
127
|
+
"payload_json": to_json(payload),
|
|
128
|
+
"metadata_json": to_json(metadata) if metadata else None,
|
|
129
|
+
"status": "pending",
|
|
130
|
+
"available_at": now,
|
|
131
|
+
"lease_expires_at": None,
|
|
132
|
+
"attempts": 0,
|
|
133
|
+
"created_at": now,
|
|
134
|
+
},
|
|
135
|
+
statement_config=self._queue._statement_config,
|
|
136
|
+
)
|
|
137
|
+
)
|
|
138
|
+
await driver.execute(SQL("SELECT pg_notify($1, $2)", channel, to_json({"event_id": event_id})))
|
|
139
|
+
await driver.commit()
|
|
140
|
+
|
|
141
|
+
async def _dequeue_with_notifies(self, connection: Any, channel: str, poll_interval: float) -> EventMessage | None:
|
|
142
|
+
"""Wait for a NOTIFY wakeup then dequeue from the durable table."""
|
|
143
|
+
try:
|
|
144
|
+
notify = await asyncio.wait_for(connection.notifies.get(), timeout=poll_interval)
|
|
145
|
+
except asyncio.TimeoutError:
|
|
146
|
+
return None
|
|
147
|
+
notify_payload = notify.payload if is_notification(notify) else None
|
|
148
|
+
if notify_payload:
|
|
149
|
+
return await self._queue.dequeue(channel)
|
|
150
|
+
return None
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class AsyncpgEventsBackend:
|
|
154
|
+
"""Async backend that relies on PostgreSQL LISTEN/NOTIFY primitives.
|
|
155
|
+
|
|
156
|
+
This backend uses asyncpg's native LISTEN/NOTIFY support for real-time
|
|
157
|
+
event delivery. Messages are ephemeral and not persisted.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
__slots__ = ("_config", "_listen_connection", "_listen_connection_cm", "_notify_mode", "_runtime")
|
|
161
|
+
|
|
162
|
+
supports_sync = False
|
|
163
|
+
supports_async = True
|
|
164
|
+
backend_name = "listen_notify"
|
|
165
|
+
|
|
166
|
+
def __init__(self, config: "AsyncpgConfig") -> None:
|
|
167
|
+
if not config.is_async:
|
|
168
|
+
msg = "AsyncpgEventsBackend requires an async adapter"
|
|
169
|
+
raise ImproperConfigurationError(msg)
|
|
170
|
+
self._config = config
|
|
171
|
+
self._runtime = config.get_observability_runtime()
|
|
172
|
+
self._listen_connection: Any | None = None
|
|
173
|
+
self._listen_connection_cm: Any | None = None
|
|
174
|
+
self._notify_mode: str | None = None
|
|
175
|
+
log_with_context(
|
|
176
|
+
logger,
|
|
177
|
+
logging.DEBUG,
|
|
178
|
+
"event.listen",
|
|
179
|
+
adapter_name="asyncpg",
|
|
180
|
+
backend_name=self.backend_name,
|
|
181
|
+
mode="async",
|
|
182
|
+
status="backend_ready",
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
async def publish(self, channel: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None" = None) -> str:
|
|
186
|
+
event_id = uuid4().hex
|
|
187
|
+
async with self._config.provide_session() as driver:
|
|
188
|
+
await driver.execute(
|
|
189
|
+
SQL("SELECT pg_notify($1, $2)", channel, encode_notify_payload(event_id, payload, metadata))
|
|
190
|
+
)
|
|
191
|
+
await driver.commit()
|
|
192
|
+
self._runtime.increment_metric("events.publish.native")
|
|
193
|
+
return event_id
|
|
194
|
+
|
|
195
|
+
async def dequeue(self, channel: str, poll_interval: float) -> EventMessage | None:
|
|
196
|
+
connection = await self._ensure_listener(channel)
|
|
197
|
+
match self._notify_mode:
|
|
198
|
+
case "add_listener":
|
|
199
|
+
return await self._dequeue_with_listener(connection, channel, poll_interval)
|
|
200
|
+
case "notifies":
|
|
201
|
+
return await self._dequeue_with_notifies(connection, channel, poll_interval)
|
|
202
|
+
case _:
|
|
203
|
+
msg = "PostgreSQL connection does not support LISTEN/NOTIFY callbacks"
|
|
204
|
+
raise EventChannelError(msg)
|
|
205
|
+
|
|
206
|
+
async def ack(self, _event_id: str) -> None:
|
|
207
|
+
"""Acknowledge an event. Native notifications are fire-and-forget."""
|
|
208
|
+
self._runtime.increment_metric("events.ack")
|
|
209
|
+
|
|
210
|
+
async def nack(self, _event_id: str) -> None:
|
|
211
|
+
"""Return an event to the queue (no-op for native LISTEN/NOTIFY)."""
|
|
212
|
+
|
|
213
|
+
async def shutdown(self) -> None:
|
|
214
|
+
"""Shutdown the listener connection and release resources."""
|
|
215
|
+
if self._listen_connection_cm is not None:
|
|
216
|
+
with contextlib.suppress(Exception):
|
|
217
|
+
await self._listen_connection_cm.__aexit__(None, None, None)
|
|
218
|
+
self._listen_connection = None
|
|
219
|
+
self._listen_connection_cm = None
|
|
220
|
+
self._notify_mode = None
|
|
221
|
+
|
|
222
|
+
async def _ensure_listener(self, channel: str) -> Any:
|
|
223
|
+
"""Ensure a dedicated connection is listening and detect notify mode."""
|
|
224
|
+
if self._listen_connection is None:
|
|
225
|
+
validated_channel = normalize_event_channel_name(channel)
|
|
226
|
+
self._listen_connection_cm = self._config.provide_connection()
|
|
227
|
+
self._listen_connection = await self._listen_connection_cm.__aenter__()
|
|
228
|
+
if self._listen_connection is not None and has_add_listener(self._listen_connection):
|
|
229
|
+
self._notify_mode = "add_listener"
|
|
230
|
+
elif self._listen_connection is not None and has_notifies(self._listen_connection):
|
|
231
|
+
self._notify_mode = "notifies"
|
|
232
|
+
if self._listen_connection is not None:
|
|
233
|
+
await self._listen_connection.execute(f"LISTEN {validated_channel}")
|
|
234
|
+
else:
|
|
235
|
+
msg = "PostgreSQL connection does not support LISTEN/NOTIFY callbacks"
|
|
236
|
+
raise EventChannelError(msg)
|
|
237
|
+
return self._listen_connection
|
|
238
|
+
|
|
239
|
+
async def _dequeue_with_listener(self, connection: Any, channel: str, poll_interval: float) -> EventMessage | None:
|
|
240
|
+
"""Wait for notification using add_listener callback API."""
|
|
241
|
+
loop = asyncio.get_running_loop()
|
|
242
|
+
future: asyncio.Future[str] = loop.create_future()
|
|
243
|
+
listener = _AsyncpgNotificationListener(channel, future, loop)
|
|
244
|
+
|
|
245
|
+
await connection.add_listener(channel, listener)
|
|
246
|
+
try:
|
|
247
|
+
payload_str = await asyncio.wait_for(future, timeout=poll_interval)
|
|
248
|
+
except asyncio.TimeoutError:
|
|
249
|
+
return None
|
|
250
|
+
finally:
|
|
251
|
+
with contextlib.suppress(Exception):
|
|
252
|
+
await connection.remove_listener(channel, listener)
|
|
253
|
+
return decode_notify_payload(channel, payload_str)
|
|
254
|
+
|
|
255
|
+
async def _dequeue_with_notifies(self, connection: Any, channel: str, poll_interval: float) -> EventMessage | None:
|
|
256
|
+
"""Wait for notification using notifies queue API."""
|
|
257
|
+
try:
|
|
258
|
+
notify = await asyncio.wait_for(connection.notifies.get(), timeout=poll_interval)
|
|
259
|
+
except asyncio.TimeoutError:
|
|
260
|
+
return None
|
|
261
|
+
notify_channel = notify.channel if is_notification(notify) else None
|
|
262
|
+
if notify_channel != channel:
|
|
263
|
+
return None
|
|
264
|
+
return decode_notify_payload(channel, notify.payload)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def create_event_backend(
|
|
268
|
+
config: "AsyncpgConfig", backend_name: str, extension_settings: "dict[str, Any]"
|
|
269
|
+
) -> AsyncpgEventsBackend | AsyncpgHybridEventsBackend | None:
|
|
270
|
+
"""Factory used by EventChannel to create the native backend."""
|
|
271
|
+
match backend_name:
|
|
272
|
+
case "listen_notify":
|
|
273
|
+
try:
|
|
274
|
+
return AsyncpgEventsBackend(config)
|
|
275
|
+
except ImproperConfigurationError:
|
|
276
|
+
return None
|
|
277
|
+
case "listen_notify_durable":
|
|
278
|
+
queue_backend = cast(
|
|
279
|
+
"AsyncTableEventQueue", build_queue_backend(config, extension_settings, adapter_name="asyncpg")
|
|
280
|
+
)
|
|
281
|
+
try:
|
|
282
|
+
return AsyncpgHybridEventsBackend(config, queue_backend)
|
|
283
|
+
except ImproperConfigurationError:
|
|
284
|
+
return None
|
|
285
|
+
case _:
|
|
286
|
+
return None
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""AsyncPG event queue store for PostgreSQL JSONB storage."""
|
|
2
|
+
|
|
3
|
+
from sqlspec.adapters.asyncpg.config import AsyncpgConfig
|
|
4
|
+
from sqlspec.extensions.events import BaseEventQueueStore
|
|
5
|
+
|
|
6
|
+
__all__ = ("AsyncpgEventQueueStore",)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AsyncpgEventQueueStore(BaseEventQueueStore[AsyncpgConfig]):
|
|
10
|
+
"""PostgreSQL event queue store with JSONB columns.
|
|
11
|
+
|
|
12
|
+
Uses PostgreSQL-native JSONB for efficient JSON storage and querying.
|
|
13
|
+
TIMESTAMPTZ ensures proper timezone handling.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
config: AsyncpgConfig with extension_config["events"] settings.
|
|
17
|
+
|
|
18
|
+
Notes:
|
|
19
|
+
Configuration is read from config.extension_config["events"]:
|
|
20
|
+
- queue_table: Table name (default: "sqlspec_event_queue")
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
from sqlspec.adapters.asyncpg import AsyncpgConfig
|
|
24
|
+
from sqlspec.adapters.asyncpg.events import AsyncpgEventQueueStore
|
|
25
|
+
|
|
26
|
+
config = AsyncpgConfig(connection_config={"dsn": "postgresql://..."})
|
|
27
|
+
store = AsyncpgEventQueueStore(config)
|
|
28
|
+
for stmt in store.create_statements():
|
|
29
|
+
await driver.execute_script(stmt)
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
__slots__ = ()
|
|
33
|
+
|
|
34
|
+
def _column_types(self) -> "tuple[str, str, str]":
|
|
35
|
+
"""Return PostgreSQL-native column types.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Tuple of (payload_type, metadata_type, timestamp_type).
|
|
39
|
+
"""
|
|
40
|
+
return "JSONB", "JSONB", "TIMESTAMPTZ"
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""AsyncPG session store for Litestar integration."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timedelta, timezone
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from sqlspec.extensions.litestar.store import BaseSQLSpecStore
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from sqlspec.adapters.asyncpg.config import AsyncpgConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__all__ = ("AsyncpgStore",)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AsyncpgStore(BaseSQLSpecStore["AsyncpgConfig"]):
|
|
16
|
+
"""PostgreSQL session store using AsyncPG driver.
|
|
17
|
+
|
|
18
|
+
Implements server-side session storage for Litestar using PostgreSQL
|
|
19
|
+
via the AsyncPG driver. Provides efficient session management with:
|
|
20
|
+
- Native async PostgreSQL operations
|
|
21
|
+
- UPSERT support using ON CONFLICT
|
|
22
|
+
- Automatic expiration handling
|
|
23
|
+
- Efficient cleanup of expired sessions
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
config: AsyncpgConfig instance with extension_config["litestar"] settings.
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
from sqlspec.adapters.asyncpg import AsyncpgConfig
|
|
30
|
+
from sqlspec.adapters.asyncpg.litestar.store import AsyncpgStore
|
|
31
|
+
|
|
32
|
+
config = AsyncpgConfig(
|
|
33
|
+
connection_config={"dsn": "postgresql://..."},
|
|
34
|
+
extension_config={"litestar": {"session_table": "my_sessions"}}
|
|
35
|
+
)
|
|
36
|
+
store = AsyncpgStore(config)
|
|
37
|
+
await store.create_table()
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
__slots__ = ()
|
|
41
|
+
|
|
42
|
+
def __init__(self, config: "AsyncpgConfig") -> None:
|
|
43
|
+
"""Initialize AsyncPG session store.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
config: AsyncpgConfig instance.
|
|
47
|
+
|
|
48
|
+
Notes:
|
|
49
|
+
Table name is read from config.extension_config["litestar"]["session_table"].
|
|
50
|
+
"""
|
|
51
|
+
super().__init__(config)
|
|
52
|
+
|
|
53
|
+
def _get_create_table_sql(self) -> str:
|
|
54
|
+
"""Get PostgreSQL CREATE TABLE SQL with optimized schema.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
SQL statement to create the sessions table with proper indexes.
|
|
58
|
+
|
|
59
|
+
Notes:
|
|
60
|
+
- Uses TIMESTAMPTZ for timezone-aware expiration timestamps
|
|
61
|
+
- Partial index WHERE expires_at IS NOT NULL reduces index size/maintenance
|
|
62
|
+
- FILLFACTOR 80 leaves space for HOT updates, reducing table bloat
|
|
63
|
+
- Audit columns (created_at, updated_at) help with debugging
|
|
64
|
+
- Table name is internally controlled, not user input (S608 suppressed)
|
|
65
|
+
"""
|
|
66
|
+
return f"""
|
|
67
|
+
CREATE TABLE IF NOT EXISTS {self._table_name} (
|
|
68
|
+
session_id TEXT PRIMARY KEY,
|
|
69
|
+
data BYTEA NOT NULL,
|
|
70
|
+
expires_at TIMESTAMPTZ,
|
|
71
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
72
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
73
|
+
) WITH (fillfactor = 80);
|
|
74
|
+
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_{self._table_name}_expires_at
|
|
76
|
+
ON {self._table_name}(expires_at) WHERE expires_at IS NOT NULL;
|
|
77
|
+
|
|
78
|
+
ALTER TABLE {self._table_name} SET (
|
|
79
|
+
autovacuum_vacuum_scale_factor = 0.05,
|
|
80
|
+
autovacuum_analyze_scale_factor = 0.02
|
|
81
|
+
);
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
def _get_drop_table_sql(self) -> "list[str]":
|
|
85
|
+
"""Get PostgreSQL DROP TABLE SQL statements.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
List of SQL statements to drop indexes and table.
|
|
89
|
+
"""
|
|
90
|
+
return [f"DROP INDEX IF EXISTS idx_{self._table_name}_expires_at", f"DROP TABLE IF EXISTS {self._table_name}"]
|
|
91
|
+
|
|
92
|
+
async def create_table(self) -> None:
|
|
93
|
+
"""Create the session table if it doesn't exist."""
|
|
94
|
+
sql = self._get_create_table_sql()
|
|
95
|
+
async with self._config.provide_session() as driver:
|
|
96
|
+
await driver.execute_script(sql)
|
|
97
|
+
self._log_table_created()
|
|
98
|
+
|
|
99
|
+
async def get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
|
|
100
|
+
"""Get a session value by key.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
key: Session ID to retrieve.
|
|
104
|
+
renew_for: If given, renew the expiry time for this duration.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Session data as bytes if found and not expired, None otherwise.
|
|
108
|
+
|
|
109
|
+
Notes:
|
|
110
|
+
Uses CURRENT_TIMESTAMP instead of NOW() for SQL standard compliance.
|
|
111
|
+
The query planner can use the partial index for expires_at > CURRENT_TIMESTAMP.
|
|
112
|
+
"""
|
|
113
|
+
sql = f"""
|
|
114
|
+
SELECT data, expires_at FROM {self._table_name}
|
|
115
|
+
WHERE session_id = $1
|
|
116
|
+
AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
async with self._config.provide_connection() as conn:
|
|
120
|
+
row = await conn.fetchrow(sql, key)
|
|
121
|
+
|
|
122
|
+
if row is None:
|
|
123
|
+
return None
|
|
124
|
+
|
|
125
|
+
if renew_for is not None and row["expires_at"] is not None:
|
|
126
|
+
new_expires_at = self._calculate_expires_at(renew_for)
|
|
127
|
+
if new_expires_at is not None:
|
|
128
|
+
update_sql = f"""
|
|
129
|
+
UPDATE {self._table_name}
|
|
130
|
+
SET expires_at = $1, updated_at = CURRENT_TIMESTAMP
|
|
131
|
+
WHERE session_id = $2
|
|
132
|
+
"""
|
|
133
|
+
await conn.execute(update_sql, new_expires_at, key)
|
|
134
|
+
|
|
135
|
+
return bytes(row["data"])
|
|
136
|
+
|
|
137
|
+
async def set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
|
|
138
|
+
"""Store a session value.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
key: Session ID.
|
|
142
|
+
value: Session data.
|
|
143
|
+
expires_in: Time until expiration.
|
|
144
|
+
|
|
145
|
+
Notes:
|
|
146
|
+
Uses EXCLUDED to reference the proposed insert values in ON CONFLICT.
|
|
147
|
+
Updates updated_at timestamp on every write for audit trail.
|
|
148
|
+
"""
|
|
149
|
+
data = self._value_to_bytes(value)
|
|
150
|
+
expires_at = self._calculate_expires_at(expires_in)
|
|
151
|
+
|
|
152
|
+
sql = f"""
|
|
153
|
+
INSERT INTO {self._table_name} (session_id, data, expires_at)
|
|
154
|
+
VALUES ($1, $2, $3)
|
|
155
|
+
ON CONFLICT (session_id)
|
|
156
|
+
DO UPDATE SET
|
|
157
|
+
data = EXCLUDED.data,
|
|
158
|
+
expires_at = EXCLUDED.expires_at,
|
|
159
|
+
updated_at = CURRENT_TIMESTAMP
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
async with self._config.provide_connection() as conn:
|
|
163
|
+
await conn.execute(sql, key, data, expires_at)
|
|
164
|
+
|
|
165
|
+
async def delete(self, key: str) -> None:
|
|
166
|
+
"""Delete a session by key.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
key: Session ID to delete.
|
|
170
|
+
"""
|
|
171
|
+
sql = f"DELETE FROM {self._table_name} WHERE session_id = $1"
|
|
172
|
+
|
|
173
|
+
async with self._config.provide_connection() as conn:
|
|
174
|
+
await conn.execute(sql, key)
|
|
175
|
+
|
|
176
|
+
async def delete_all(self) -> None:
|
|
177
|
+
"""Delete all sessions from the store."""
|
|
178
|
+
sql = f"DELETE FROM {self._table_name}"
|
|
179
|
+
|
|
180
|
+
async with self._config.provide_connection() as conn:
|
|
181
|
+
await conn.execute(sql)
|
|
182
|
+
self._log_delete_all()
|
|
183
|
+
|
|
184
|
+
async def exists(self, key: str) -> bool:
|
|
185
|
+
"""Check if a session key exists and is not expired.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
key: Session ID to check.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
True if the session exists and is not expired.
|
|
192
|
+
|
|
193
|
+
Notes:
|
|
194
|
+
Uses CURRENT_TIMESTAMP for consistency with get() method.
|
|
195
|
+
"""
|
|
196
|
+
sql = f"""
|
|
197
|
+
SELECT 1 FROM {self._table_name}
|
|
198
|
+
WHERE session_id = $1
|
|
199
|
+
AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
async with self._config.provide_connection() as conn:
|
|
203
|
+
result = await conn.fetchval(sql, key)
|
|
204
|
+
return result is not None
|
|
205
|
+
|
|
206
|
+
async def expires_in(self, key: str) -> "int | None":
|
|
207
|
+
"""Get the time in seconds until the session expires.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
key: Session ID to check.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Seconds until expiration, or None if no expiry or key doesn't exist.
|
|
214
|
+
"""
|
|
215
|
+
sql = f"""
|
|
216
|
+
SELECT expires_at FROM {self._table_name}
|
|
217
|
+
WHERE session_id = $1
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
async with self._config.provide_connection() as conn:
|
|
221
|
+
expires_at = await conn.fetchval(sql, key)
|
|
222
|
+
|
|
223
|
+
if expires_at is None:
|
|
224
|
+
return None
|
|
225
|
+
|
|
226
|
+
now = datetime.now(timezone.utc)
|
|
227
|
+
if expires_at <= now:
|
|
228
|
+
return 0
|
|
229
|
+
|
|
230
|
+
delta = expires_at - now
|
|
231
|
+
return int(delta.total_seconds())
|
|
232
|
+
|
|
233
|
+
async def delete_expired(self) -> int:
|
|
234
|
+
"""Delete all expired sessions.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
Number of sessions deleted.
|
|
238
|
+
|
|
239
|
+
Notes:
|
|
240
|
+
Uses CURRENT_TIMESTAMP for consistency.
|
|
241
|
+
For very large tables (10M+ rows), consider batching deletes
|
|
242
|
+
to avoid holding locks too long.
|
|
243
|
+
"""
|
|
244
|
+
sql = f"DELETE FROM {self._table_name} WHERE expires_at <= CURRENT_TIMESTAMP"
|
|
245
|
+
|
|
246
|
+
async with self._config.provide_connection() as conn:
|
|
247
|
+
result = await conn.execute(sql)
|
|
248
|
+
count = int(result.split()[-1])
|
|
249
|
+
if count > 0:
|
|
250
|
+
self._log_delete_expired(count)
|
|
251
|
+
return count
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from sqlspec.adapters.bigquery._typing import BigQueryConnection
|
|
2
|
+
from sqlspec.adapters.bigquery.config import BigQueryConfig, BigQueryConnectionParams
|
|
3
|
+
from sqlspec.adapters.bigquery.core import default_statement_config
|
|
4
|
+
from sqlspec.adapters.bigquery.driver import BigQueryCursor, BigQueryDriver, BigQueryExceptionHandler
|
|
5
|
+
|
|
6
|
+
__all__ = (
|
|
7
|
+
"BigQueryConfig",
|
|
8
|
+
"BigQueryConnection",
|
|
9
|
+
"BigQueryConnectionParams",
|
|
10
|
+
"BigQueryCursor",
|
|
11
|
+
"BigQueryDriver",
|
|
12
|
+
"BigQueryExceptionHandler",
|
|
13
|
+
"default_statement_config",
|
|
14
|
+
)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""BigQuery adapter type definitions.
|
|
2
|
+
|
|
3
|
+
This module contains type aliases and classes that are excluded from mypyc
|
|
4
|
+
compilation to avoid ABI boundary issues.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from collections.abc import Callable
|
|
11
|
+
from typing import TypeAlias
|
|
12
|
+
|
|
13
|
+
from google.cloud.bigquery import ArrayQueryParameter, Client, ScalarQueryParameter
|
|
14
|
+
|
|
15
|
+
from sqlspec.adapters.bigquery.driver import BigQueryDriver
|
|
16
|
+
from sqlspec.core import StatementConfig
|
|
17
|
+
|
|
18
|
+
BigQueryConnection: TypeAlias = Client
|
|
19
|
+
BigQueryParam: TypeAlias = ArrayQueryParameter | ScalarQueryParameter
|
|
20
|
+
else:
|
|
21
|
+
try:
|
|
22
|
+
from google.cloud.bigquery import ArrayQueryParameter, Client, ScalarQueryParameter
|
|
23
|
+
except Exception:
|
|
24
|
+
BigQueryConnection = Any
|
|
25
|
+
BigQueryParam = Any
|
|
26
|
+
else:
|
|
27
|
+
BigQueryConnection = Client
|
|
28
|
+
BigQueryParam = ArrayQueryParameter | ScalarQueryParameter
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class BigQuerySessionContext:
|
|
32
|
+
"""Sync context manager for BigQuery sessions.
|
|
33
|
+
|
|
34
|
+
This class is intentionally excluded from mypyc compilation to avoid ABI
|
|
35
|
+
boundary issues. It receives callables from uncompiled config classes and
|
|
36
|
+
instantiates compiled Driver objects, acting as a bridge between compiled
|
|
37
|
+
and uncompiled code.
|
|
38
|
+
|
|
39
|
+
Uses callable-based connection management to decouple from config implementation.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
__slots__ = (
|
|
43
|
+
"_acquire_connection",
|
|
44
|
+
"_connection",
|
|
45
|
+
"_driver",
|
|
46
|
+
"_driver_features",
|
|
47
|
+
"_prepare_driver",
|
|
48
|
+
"_release_connection",
|
|
49
|
+
"_statement_config",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def __init__(
|
|
53
|
+
self,
|
|
54
|
+
acquire_connection: "Callable[[], Any]",
|
|
55
|
+
release_connection: "Callable[[Any], Any]",
|
|
56
|
+
statement_config: "StatementConfig",
|
|
57
|
+
driver_features: "dict[str, Any]",
|
|
58
|
+
prepare_driver: "Callable[[BigQueryDriver], BigQueryDriver]",
|
|
59
|
+
) -> None:
|
|
60
|
+
self._acquire_connection = acquire_connection
|
|
61
|
+
self._release_connection = release_connection
|
|
62
|
+
self._statement_config = statement_config
|
|
63
|
+
self._driver_features = driver_features
|
|
64
|
+
self._prepare_driver = prepare_driver
|
|
65
|
+
self._connection: Any = None
|
|
66
|
+
self._driver: BigQueryDriver | None = None
|
|
67
|
+
|
|
68
|
+
def __enter__(self) -> "BigQueryDriver":
|
|
69
|
+
from sqlspec.adapters.bigquery.driver import BigQueryDriver
|
|
70
|
+
|
|
71
|
+
self._connection = self._acquire_connection()
|
|
72
|
+
self._driver = BigQueryDriver(
|
|
73
|
+
connection=self._connection, statement_config=self._statement_config, driver_features=self._driver_features
|
|
74
|
+
)
|
|
75
|
+
return self._prepare_driver(self._driver)
|
|
76
|
+
|
|
77
|
+
def __exit__(
|
|
78
|
+
self, exc_type: "type[BaseException] | None", exc_val: "BaseException | None", exc_tb: Any
|
|
79
|
+
) -> "bool | None":
|
|
80
|
+
if self._connection is not None:
|
|
81
|
+
self._release_connection(self._connection)
|
|
82
|
+
self._connection = None
|
|
83
|
+
return None
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
__all__ = ("BigQueryConnection", "BigQueryParam", "BigQuerySessionContext")
|