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,316 @@
|
|
|
1
|
+
"""SQLite sync 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
|
+
from sqlspec.utils.sync_tools import async_
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from sqlspec.adapters.sqlite.config import SqliteConfig
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
SECONDS_PER_DAY = 86400.0
|
|
14
|
+
JULIAN_EPOCH = 2440587.5
|
|
15
|
+
|
|
16
|
+
__all__ = ("SQLiteStore",)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SQLiteStore(BaseSQLSpecStore["SqliteConfig"]):
|
|
20
|
+
"""SQLite session store using synchronous SQLite driver.
|
|
21
|
+
|
|
22
|
+
Implements server-side session storage for Litestar using SQLite
|
|
23
|
+
via the synchronous sqlite3 driver. Uses Litestar's sync_to_thread
|
|
24
|
+
utility to provide an async interface compatible with the Store protocol.
|
|
25
|
+
|
|
26
|
+
Provides efficient session management with:
|
|
27
|
+
- Sync operations wrapped for async compatibility
|
|
28
|
+
- INSERT OR REPLACE for UPSERT functionality
|
|
29
|
+
- Automatic expiration handling
|
|
30
|
+
- Efficient cleanup of expired sessions
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
config: SqliteConfig instance.
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
from sqlspec.adapters.sqlite import SqliteConfig
|
|
37
|
+
from sqlspec.adapters.sqlite.litestar.store import SQLiteStore
|
|
38
|
+
|
|
39
|
+
config = SqliteConfig(database=":memory:")
|
|
40
|
+
store = SQLiteStore(config)
|
|
41
|
+
await store.create_table()
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
__slots__ = ()
|
|
45
|
+
|
|
46
|
+
def __init__(self, config: "SqliteConfig") -> None:
|
|
47
|
+
"""Initialize SQLite session store.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
config: SqliteConfig instance.
|
|
51
|
+
|
|
52
|
+
Notes:
|
|
53
|
+
Table name is read from config.extension_config["litestar"]["session_table"].
|
|
54
|
+
"""
|
|
55
|
+
super().__init__(config)
|
|
56
|
+
|
|
57
|
+
def _get_create_table_sql(self) -> str:
|
|
58
|
+
"""Get SQLite CREATE TABLE SQL.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
SQL statement to create the sessions table with proper indexes.
|
|
62
|
+
|
|
63
|
+
Notes:
|
|
64
|
+
- Uses REAL type for expires_at (stores Julian Day number)
|
|
65
|
+
- Julian Day enables direct comparison with julianday('now')
|
|
66
|
+
- Partial index WHERE expires_at IS NOT NULL reduces index size
|
|
67
|
+
- This approach ensures the index is actually used by query optimizer
|
|
68
|
+
"""
|
|
69
|
+
return f"""
|
|
70
|
+
CREATE TABLE IF NOT EXISTS {self._table_name} (
|
|
71
|
+
session_id TEXT PRIMARY KEY,
|
|
72
|
+
data BLOB NOT NULL,
|
|
73
|
+
expires_at REAL
|
|
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
|
+
|
|
79
|
+
def _get_drop_table_sql(self) -> "list[str]":
|
|
80
|
+
"""Get SQLite DROP TABLE SQL statements.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
List of SQL statements to drop indexes and table.
|
|
84
|
+
"""
|
|
85
|
+
return [f"DROP INDEX IF EXISTS idx_{self._table_name}_expires_at", f"DROP TABLE IF EXISTS {self._table_name}"]
|
|
86
|
+
|
|
87
|
+
def _datetime_to_julian(self, dt: "datetime | None") -> "float | None":
|
|
88
|
+
"""Convert datetime to Julian Day number for SQLite storage.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
dt: Datetime to convert (must be UTC-aware).
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Julian Day number as REAL, or None if dt is None.
|
|
95
|
+
|
|
96
|
+
Notes:
|
|
97
|
+
Julian Day number is days since November 24, 4714 BCE (proleptic Gregorian).
|
|
98
|
+
This enables direct comparison with julianday('now') in SQL queries.
|
|
99
|
+
"""
|
|
100
|
+
if dt is None:
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
|
|
104
|
+
delta_days = (dt - epoch).total_seconds() / SECONDS_PER_DAY
|
|
105
|
+
return JULIAN_EPOCH + delta_days
|
|
106
|
+
|
|
107
|
+
def _julian_to_datetime(self, julian: "float | None") -> "datetime | None":
|
|
108
|
+
"""Convert Julian Day number back to datetime.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
julian: Julian Day number.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
UTC-aware datetime, or None if julian is None.
|
|
115
|
+
"""
|
|
116
|
+
if julian is None:
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
days_since_epoch = julian - JULIAN_EPOCH
|
|
120
|
+
timestamp = days_since_epoch * SECONDS_PER_DAY
|
|
121
|
+
return datetime.fromtimestamp(timestamp, tz=timezone.utc)
|
|
122
|
+
|
|
123
|
+
def _create_table(self) -> None:
|
|
124
|
+
"""Synchronous implementation of create_table."""
|
|
125
|
+
sql = self._get_create_table_sql()
|
|
126
|
+
with self._config.provide_session() as driver:
|
|
127
|
+
driver.execute_script(sql)
|
|
128
|
+
self._log_table_created()
|
|
129
|
+
|
|
130
|
+
async def create_table(self) -> None:
|
|
131
|
+
"""Create the session table if it doesn't exist."""
|
|
132
|
+
await async_(self._create_table)()
|
|
133
|
+
|
|
134
|
+
def _get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
|
|
135
|
+
"""Synchronous implementation of get."""
|
|
136
|
+
sql = f"""
|
|
137
|
+
SELECT data, expires_at FROM {self._table_name}
|
|
138
|
+
WHERE session_id = ?
|
|
139
|
+
AND (expires_at IS NULL OR julianday(expires_at) > julianday('now'))
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
with self._config.provide_connection() as conn:
|
|
143
|
+
cursor = conn.execute(sql, (key,))
|
|
144
|
+
row = cursor.fetchone()
|
|
145
|
+
|
|
146
|
+
if row is None:
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
data, expires_at_julian = row
|
|
150
|
+
|
|
151
|
+
if renew_for is not None and expires_at_julian is not None:
|
|
152
|
+
new_expires_at = self._calculate_expires_at(renew_for)
|
|
153
|
+
new_expires_at_julian = self._datetime_to_julian(new_expires_at)
|
|
154
|
+
if new_expires_at_julian is not None:
|
|
155
|
+
update_sql = f"""
|
|
156
|
+
UPDATE {self._table_name}
|
|
157
|
+
SET expires_at = ?
|
|
158
|
+
WHERE session_id = ?
|
|
159
|
+
"""
|
|
160
|
+
conn.execute(update_sql, (new_expires_at_julian, key))
|
|
161
|
+
conn.commit()
|
|
162
|
+
|
|
163
|
+
return bytes(data)
|
|
164
|
+
|
|
165
|
+
async def get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
|
|
166
|
+
"""Get a session value by key.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
key: Session ID to retrieve.
|
|
170
|
+
renew_for: If given, renew the expiry time for this duration.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Session data as bytes if found and not expired, None otherwise.
|
|
174
|
+
"""
|
|
175
|
+
return await async_(self._get)(key, renew_for)
|
|
176
|
+
|
|
177
|
+
def _set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
|
|
178
|
+
"""Synchronous implementation of set.
|
|
179
|
+
|
|
180
|
+
Notes:
|
|
181
|
+
Stores expires_at as Julian Day number (REAL) for optimal index usage.
|
|
182
|
+
"""
|
|
183
|
+
data = self._value_to_bytes(value)
|
|
184
|
+
expires_at = self._calculate_expires_at(expires_in)
|
|
185
|
+
expires_at_julian = self._datetime_to_julian(expires_at)
|
|
186
|
+
|
|
187
|
+
sql = f"""
|
|
188
|
+
INSERT OR REPLACE INTO {self._table_name} (session_id, data, expires_at)
|
|
189
|
+
VALUES (?, ?, ?)
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
with self._config.provide_connection() as conn:
|
|
193
|
+
conn.execute(sql, (key, data, expires_at_julian))
|
|
194
|
+
conn.commit()
|
|
195
|
+
|
|
196
|
+
async def set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
|
|
197
|
+
"""Store a session value.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
key: Session ID.
|
|
201
|
+
value: Session data.
|
|
202
|
+
expires_in: Time until expiration.
|
|
203
|
+
"""
|
|
204
|
+
await async_(self._set)(key, value, expires_in)
|
|
205
|
+
|
|
206
|
+
def _delete(self, key: str) -> None:
|
|
207
|
+
"""Synchronous implementation of delete."""
|
|
208
|
+
sql = f"DELETE FROM {self._table_name} WHERE session_id = ?"
|
|
209
|
+
|
|
210
|
+
with self._config.provide_connection() as conn:
|
|
211
|
+
conn.execute(sql, (key,))
|
|
212
|
+
conn.commit()
|
|
213
|
+
|
|
214
|
+
async def delete(self, key: str) -> None:
|
|
215
|
+
"""Delete a session by key.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
key: Session ID to delete.
|
|
219
|
+
"""
|
|
220
|
+
await async_(self._delete)(key)
|
|
221
|
+
|
|
222
|
+
def _delete_all(self) -> None:
|
|
223
|
+
"""Synchronous implementation of delete_all."""
|
|
224
|
+
sql = f"DELETE FROM {self._table_name}"
|
|
225
|
+
|
|
226
|
+
with self._config.provide_connection() as conn:
|
|
227
|
+
conn.execute(sql)
|
|
228
|
+
conn.commit()
|
|
229
|
+
self._log_delete_all()
|
|
230
|
+
|
|
231
|
+
async def delete_all(self) -> None:
|
|
232
|
+
"""Delete all sessions from the store."""
|
|
233
|
+
await async_(self._delete_all)()
|
|
234
|
+
|
|
235
|
+
def _exists(self, key: str) -> bool:
|
|
236
|
+
"""Synchronous implementation of exists."""
|
|
237
|
+
sql = f"""
|
|
238
|
+
SELECT 1 FROM {self._table_name}
|
|
239
|
+
WHERE session_id = ?
|
|
240
|
+
AND (expires_at IS NULL OR julianday(expires_at) > julianday('now'))
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
with self._config.provide_connection() as conn:
|
|
244
|
+
cursor = conn.execute(sql, (key,))
|
|
245
|
+
result = cursor.fetchone()
|
|
246
|
+
return result is not None
|
|
247
|
+
|
|
248
|
+
async def exists(self, key: str) -> bool:
|
|
249
|
+
"""Check if a session key exists and is not expired.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
key: Session ID to check.
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
True if the session exists and is not expired.
|
|
256
|
+
"""
|
|
257
|
+
return await async_(self._exists)(key)
|
|
258
|
+
|
|
259
|
+
def _expires_in(self, key: str) -> "int | None":
|
|
260
|
+
"""Synchronous implementation of expires_in."""
|
|
261
|
+
sql = f"""
|
|
262
|
+
SELECT expires_at FROM {self._table_name}
|
|
263
|
+
WHERE session_id = ?
|
|
264
|
+
"""
|
|
265
|
+
|
|
266
|
+
with self._config.provide_connection() as conn:
|
|
267
|
+
cursor = conn.execute(sql, (key,))
|
|
268
|
+
row = cursor.fetchone()
|
|
269
|
+
|
|
270
|
+
if row is None or row[0] is None:
|
|
271
|
+
return None
|
|
272
|
+
|
|
273
|
+
expires_at_julian = row[0]
|
|
274
|
+
expires_at = self._julian_to_datetime(expires_at_julian)
|
|
275
|
+
|
|
276
|
+
if expires_at is None:
|
|
277
|
+
return None
|
|
278
|
+
|
|
279
|
+
now = datetime.now(timezone.utc)
|
|
280
|
+
|
|
281
|
+
if expires_at <= now:
|
|
282
|
+
return 0
|
|
283
|
+
|
|
284
|
+
delta = expires_at - now
|
|
285
|
+
return int(delta.total_seconds())
|
|
286
|
+
|
|
287
|
+
async def expires_in(self, key: str) -> "int | None":
|
|
288
|
+
"""Get the time in seconds until the session expires.
|
|
289
|
+
|
|
290
|
+
Args:
|
|
291
|
+
key: Session ID to check.
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
Seconds until expiration, or None if no expiry or key doesn't exist.
|
|
295
|
+
"""
|
|
296
|
+
return await async_(self._expires_in)(key)
|
|
297
|
+
|
|
298
|
+
def _delete_expired(self) -> int:
|
|
299
|
+
"""Synchronous implementation of delete_expired."""
|
|
300
|
+
sql = f"DELETE FROM {self._table_name} WHERE julianday(expires_at) <= julianday('now')"
|
|
301
|
+
|
|
302
|
+
with self._config.provide_connection() as conn:
|
|
303
|
+
cursor = conn.execute(sql)
|
|
304
|
+
conn.commit()
|
|
305
|
+
count = cursor.rowcount
|
|
306
|
+
if count > 0:
|
|
307
|
+
self._log_delete_expired(count)
|
|
308
|
+
return count
|
|
309
|
+
|
|
310
|
+
async def delete_expired(self) -> int:
|
|
311
|
+
"""Delete all expired sessions.
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
Number of sessions deleted.
|
|
315
|
+
"""
|
|
316
|
+
return await async_(self._delete_expired)()
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""SQLite database configuration with thread-local connections."""
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import sqlite3
|
|
5
|
+
import threading
|
|
6
|
+
import time
|
|
7
|
+
from contextlib import contextmanager
|
|
8
|
+
from typing import TYPE_CHECKING, Any, TypedDict, cast
|
|
9
|
+
|
|
10
|
+
from typing_extensions import NotRequired
|
|
11
|
+
|
|
12
|
+
from sqlspec.adapters.sqlite._typing import SqliteConnection
|
|
13
|
+
from sqlspec.utils.logging import get_logger
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Generator
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SqliteConnectionParams(TypedDict):
|
|
20
|
+
"""SQLite connection parameters."""
|
|
21
|
+
|
|
22
|
+
database: NotRequired[str]
|
|
23
|
+
timeout: NotRequired[float]
|
|
24
|
+
detect_types: NotRequired[int]
|
|
25
|
+
isolation_level: "NotRequired[str | None]"
|
|
26
|
+
check_same_thread: NotRequired[bool]
|
|
27
|
+
factory: "NotRequired[type[SqliteConnection] | None]"
|
|
28
|
+
cached_statements: NotRequired[int]
|
|
29
|
+
uri: NotRequired[bool]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
__all__ = ("SqliteConnectionPool",)
|
|
33
|
+
|
|
34
|
+
logger = get_logger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class SqliteConnectionPool:
|
|
38
|
+
"""Thread-local connection manager for SQLite.
|
|
39
|
+
|
|
40
|
+
SQLite connections aren't thread-safe, so we use thread-local storage
|
|
41
|
+
to ensure each thread has its own connection. This is simpler and more
|
|
42
|
+
efficient than a traditional pool for SQLite's constraints.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
__slots__ = (
|
|
46
|
+
"_connection_parameters",
|
|
47
|
+
"_enable_optimizations",
|
|
48
|
+
"_health_check_interval",
|
|
49
|
+
"_recycle_seconds",
|
|
50
|
+
"_thread_local",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
connection_parameters: "dict[str, Any]",
|
|
56
|
+
enable_optimizations: bool = True,
|
|
57
|
+
recycle_seconds: int = 86400,
|
|
58
|
+
health_check_interval: float = 30.0,
|
|
59
|
+
) -> None:
|
|
60
|
+
"""Initialize the thread-local connection manager.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
connection_parameters: SQLite connection parameters
|
|
64
|
+
enable_optimizations: Whether to apply performance PRAGMAs
|
|
65
|
+
recycle_seconds: Connection recycle time in seconds (default 24h)
|
|
66
|
+
health_check_interval: Seconds of idle time before running health check
|
|
67
|
+
"""
|
|
68
|
+
if "check_same_thread" not in connection_parameters:
|
|
69
|
+
connection_parameters = {**connection_parameters, "check_same_thread": False}
|
|
70
|
+
self._connection_parameters = connection_parameters
|
|
71
|
+
self._thread_local = threading.local()
|
|
72
|
+
self._enable_optimizations = enable_optimizations
|
|
73
|
+
self._recycle_seconds = recycle_seconds
|
|
74
|
+
self._health_check_interval = health_check_interval
|
|
75
|
+
|
|
76
|
+
def _create_connection(self) -> SqliteConnection:
|
|
77
|
+
"""Create a new SQLite connection with optimizations."""
|
|
78
|
+
connection = sqlite3.connect(**self._connection_parameters)
|
|
79
|
+
|
|
80
|
+
if self._enable_optimizations:
|
|
81
|
+
database = self._connection_parameters.get("database", ":memory:")
|
|
82
|
+
is_memory = database == ":memory:" or "mode=memory" in str(database)
|
|
83
|
+
|
|
84
|
+
if is_memory:
|
|
85
|
+
connection.execute("PRAGMA journal_mode = MEMORY")
|
|
86
|
+
connection.execute("PRAGMA synchronous = OFF")
|
|
87
|
+
connection.execute("PRAGMA temp_store = MEMORY")
|
|
88
|
+
else:
|
|
89
|
+
connection.execute("PRAGMA journal_mode = WAL")
|
|
90
|
+
connection.execute("PRAGMA synchronous = NORMAL")
|
|
91
|
+
connection.execute("PRAGMA busy_timeout = 5000")
|
|
92
|
+
|
|
93
|
+
connection.execute("PRAGMA foreign_keys = ON")
|
|
94
|
+
|
|
95
|
+
return connection # type: ignore[no-any-return]
|
|
96
|
+
|
|
97
|
+
def _is_connection_alive(self, connection: SqliteConnection) -> bool:
|
|
98
|
+
"""Check if a connection is still alive and usable.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
connection: Connection to check
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
True if connection is alive, False otherwise
|
|
105
|
+
"""
|
|
106
|
+
try:
|
|
107
|
+
connection.execute("SELECT 1")
|
|
108
|
+
except Exception:
|
|
109
|
+
return False
|
|
110
|
+
return True
|
|
111
|
+
|
|
112
|
+
def _get_thread_connection(self) -> SqliteConnection:
|
|
113
|
+
"""Get or create a connection for the current thread."""
|
|
114
|
+
thread_state = self._thread_local.__dict__
|
|
115
|
+
if "connection" not in thread_state:
|
|
116
|
+
self._thread_local.connection = self._create_connection()
|
|
117
|
+
self._thread_local.created_at = time.time()
|
|
118
|
+
self._thread_local.last_used = time.time()
|
|
119
|
+
return cast("SqliteConnection", self._thread_local.connection)
|
|
120
|
+
|
|
121
|
+
if self._recycle_seconds > 0 and time.time() - self._thread_local.created_at > self._recycle_seconds:
|
|
122
|
+
logger.debug("SQLite connection exceeded recycle time, recreating")
|
|
123
|
+
with contextlib.suppress(Exception):
|
|
124
|
+
self._thread_local.connection.close()
|
|
125
|
+
self._thread_local.connection = self._create_connection()
|
|
126
|
+
self._thread_local.created_at = time.time()
|
|
127
|
+
self._thread_local.last_used = time.time()
|
|
128
|
+
return cast("SqliteConnection", self._thread_local.connection)
|
|
129
|
+
|
|
130
|
+
idle_time = time.time() - thread_state.get("last_used", 0)
|
|
131
|
+
if idle_time > self._health_check_interval and not self._is_connection_alive(self._thread_local.connection):
|
|
132
|
+
logger.debug("SQLite connection failed health check after %.1fs idle, recreating", idle_time)
|
|
133
|
+
with contextlib.suppress(Exception):
|
|
134
|
+
self._thread_local.connection.close()
|
|
135
|
+
self._thread_local.connection = self._create_connection()
|
|
136
|
+
self._thread_local.created_at = time.time()
|
|
137
|
+
|
|
138
|
+
self._thread_local.last_used = time.time()
|
|
139
|
+
return cast("SqliteConnection", self._thread_local.connection)
|
|
140
|
+
|
|
141
|
+
def _close_thread_connection(self) -> None:
|
|
142
|
+
"""Close the connection for the current thread."""
|
|
143
|
+
thread_state = self._thread_local.__dict__
|
|
144
|
+
if "connection" in thread_state:
|
|
145
|
+
with contextlib.suppress(Exception):
|
|
146
|
+
self._thread_local.connection.close()
|
|
147
|
+
del self._thread_local.connection
|
|
148
|
+
if "created_at" in thread_state:
|
|
149
|
+
del self._thread_local.created_at
|
|
150
|
+
if "last_used" in thread_state:
|
|
151
|
+
del self._thread_local.last_used
|
|
152
|
+
|
|
153
|
+
@contextmanager
|
|
154
|
+
def get_connection(self) -> "Generator[SqliteConnection, None, None]":
|
|
155
|
+
"""Get a thread-local connection.
|
|
156
|
+
|
|
157
|
+
Yields:
|
|
158
|
+
SqliteConnection: A thread-local connection.
|
|
159
|
+
"""
|
|
160
|
+
connection = self._get_thread_connection()
|
|
161
|
+
try:
|
|
162
|
+
yield connection
|
|
163
|
+
finally:
|
|
164
|
+
with contextlib.suppress(Exception):
|
|
165
|
+
if connection.in_transaction:
|
|
166
|
+
connection.commit()
|
|
167
|
+
|
|
168
|
+
def close(self) -> None:
|
|
169
|
+
"""Close the thread-local connection if it exists."""
|
|
170
|
+
self._close_thread_connection()
|
|
171
|
+
|
|
172
|
+
def acquire(self) -> SqliteConnection:
|
|
173
|
+
"""Acquire a thread-local connection.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
SqliteConnection: A thread-local connection
|
|
177
|
+
"""
|
|
178
|
+
return self._get_thread_connection()
|
|
179
|
+
|
|
180
|
+
def release(self, connection: SqliteConnection) -> None:
|
|
181
|
+
"""Release a connection (no-op for thread-local connections).
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
connection: The connection to release (ignored)
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
def size(self) -> int:
|
|
188
|
+
"""Get pool size (always 1 for thread-local)."""
|
|
189
|
+
try:
|
|
190
|
+
_ = self._thread_local.connection
|
|
191
|
+
except AttributeError:
|
|
192
|
+
return 0
|
|
193
|
+
else:
|
|
194
|
+
return 1
|
|
195
|
+
|
|
196
|
+
def checked_out(self) -> int:
|
|
197
|
+
"""Get number of checked out connections (always 0)."""
|
|
198
|
+
return 0
|
|
Binary file
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""SQLite custom type handlers for optional JSON and type conversion support.
|
|
2
|
+
|
|
3
|
+
Provides registration functions for SQLite's adapter/converter system to enable
|
|
4
|
+
custom type handling. All handlers are optional and must be explicitly enabled
|
|
5
|
+
via SqliteDriverFeatures configuration.
|
|
6
|
+
|
|
7
|
+
All functions are designed for mypyc compilation using functools.partial
|
|
8
|
+
instead of lambdas for adapter registration.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import sqlite3
|
|
13
|
+
from functools import partial
|
|
14
|
+
from typing import TYPE_CHECKING, Any
|
|
15
|
+
|
|
16
|
+
from sqlspec.utils.logging import get_logger
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from collections.abc import Callable
|
|
20
|
+
|
|
21
|
+
__all__ = ("json_adapter", "json_converter", "register_type_handlers", "unregister_type_handlers")
|
|
22
|
+
|
|
23
|
+
logger = get_logger(__name__)
|
|
24
|
+
|
|
25
|
+
DEFAULT_JSON_TYPE = "JSON"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def json_adapter(value: Any, serializer: "Callable[[Any], str] | None" = None) -> str:
|
|
29
|
+
"""Convert Python dict/list to JSON string for SQLite storage.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
value: Python dict or list to serialize.
|
|
33
|
+
serializer: Optional JSON serializer callable. Defaults to standard json.dumps.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
JSON string representation.
|
|
37
|
+
"""
|
|
38
|
+
if serializer is None:
|
|
39
|
+
return json.dumps(value, ensure_ascii=False)
|
|
40
|
+
return serializer(value)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def json_converter(value: bytes, deserializer: "Callable[[str], Any] | None" = None) -> Any:
|
|
44
|
+
"""Convert JSON string from SQLite to Python dict/list.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
value: UTF-8 encoded JSON bytes from SQLite.
|
|
48
|
+
deserializer: Optional JSON deserializer callable. Defaults to standard json.loads.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Deserialized Python object (dict or list).
|
|
52
|
+
"""
|
|
53
|
+
if deserializer is None:
|
|
54
|
+
return json.loads(value.decode("utf-8"))
|
|
55
|
+
return deserializer(value.decode("utf-8"))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _make_json_adapter(serializer: "Callable[[Any], str] | None") -> "Callable[[Any], str]":
|
|
59
|
+
"""Create a JSON adapter function with bound serializer.
|
|
60
|
+
|
|
61
|
+
This is a module-level factory to avoid lambda closures which are
|
|
62
|
+
problematic for mypyc compilation.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
serializer: Optional JSON serializer callable.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Adapter function ready for sqlite3.register_adapter.
|
|
69
|
+
"""
|
|
70
|
+
return partial(json_adapter, serializer=serializer)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _make_json_converter(deserializer: "Callable[[str], Any] | None") -> "Callable[[bytes], Any]":
|
|
74
|
+
"""Create a JSON converter function with bound deserializer.
|
|
75
|
+
|
|
76
|
+
This is a module-level factory to avoid lambda closures which are
|
|
77
|
+
problematic for mypyc compilation.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
deserializer: Optional JSON deserializer callable.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Converter function ready for sqlite3.register_converter.
|
|
84
|
+
"""
|
|
85
|
+
return partial(json_converter, deserializer=deserializer)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def register_type_handlers(
|
|
89
|
+
json_serializer: "Callable[[Any], str] | None" = None, json_deserializer: "Callable[[str], Any] | None" = None
|
|
90
|
+
) -> None:
|
|
91
|
+
"""Register custom type adapters and converters with sqlite3 module.
|
|
92
|
+
|
|
93
|
+
This function registers handlers globally for the sqlite3 module. It should be
|
|
94
|
+
called once during application initialization if custom type handling is needed.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
json_serializer: Optional custom JSON serializer (e.g., orjson.dumps).
|
|
98
|
+
json_deserializer: Optional custom JSON deserializer (e.g., orjson.loads).
|
|
99
|
+
"""
|
|
100
|
+
dict_adapter = _make_json_adapter(json_serializer)
|
|
101
|
+
list_adapter = _make_json_adapter(json_serializer)
|
|
102
|
+
converter = _make_json_converter(json_deserializer)
|
|
103
|
+
|
|
104
|
+
sqlite3.register_adapter(dict, dict_adapter)
|
|
105
|
+
sqlite3.register_adapter(list, list_adapter)
|
|
106
|
+
sqlite3.register_converter(DEFAULT_JSON_TYPE, converter)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def unregister_type_handlers() -> None:
|
|
110
|
+
"""Unregister custom type handlers from sqlite3 module.
|
|
111
|
+
|
|
112
|
+
Note: sqlite3 module does not provide an official unregister API, so this
|
|
113
|
+
function is a no-op placeholder for API consistency with other adapters.
|
|
114
|
+
"""
|