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
sqlspec/cli.py
ADDED
|
@@ -0,0 +1,911 @@
|
|
|
1
|
+
# ruff: noqa: C901
|
|
2
|
+
import sys
|
|
3
|
+
from collections.abc import Callable, Sequence
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
6
|
+
|
|
7
|
+
import rich_click as click
|
|
8
|
+
from click.core import ParameterSource
|
|
9
|
+
from rich import get_console
|
|
10
|
+
from rich.prompt import Confirm, Prompt
|
|
11
|
+
from rich.table import Table
|
|
12
|
+
|
|
13
|
+
from sqlspec.config import AsyncDatabaseConfig, SyncDatabaseConfig
|
|
14
|
+
from sqlspec.exceptions import ConfigResolverError
|
|
15
|
+
from sqlspec.utils.config_tools import discover_config_from_pyproject, resolve_config_sync
|
|
16
|
+
from sqlspec.utils.module_loader import import_string
|
|
17
|
+
from sqlspec.utils.sync_tools import run_
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from rich_click import Group
|
|
21
|
+
|
|
22
|
+
from sqlspec.extensions.adk.memory.store import BaseAsyncADKMemoryStore, BaseSyncADKMemoryStore
|
|
23
|
+
from sqlspec.migrations.commands import AsyncMigrationCommands, SyncMigrationCommands
|
|
24
|
+
|
|
25
|
+
__all__ = ("add_migration_commands", "get_sqlspec_group")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _safe_group_command(
|
|
29
|
+
group: "Group", *, aliases: "list[str] | None" = None, **kwargs: Any
|
|
30
|
+
) -> "Callable[[Callable[..., Any]], Callable[..., Any]]":
|
|
31
|
+
if aliases is None:
|
|
32
|
+
return group.command(**kwargs)
|
|
33
|
+
try:
|
|
34
|
+
return group.command(aliases=aliases, **kwargs)
|
|
35
|
+
except TypeError:
|
|
36
|
+
return group.command(**kwargs)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def get_sqlspec_group() -> "Group":
|
|
40
|
+
"""Get the SQLSpec CLI group.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
The SQLSpec CLI group.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
@click.group(name="sqlspec")
|
|
47
|
+
@click.option(
|
|
48
|
+
"--config",
|
|
49
|
+
help="Dotted path to SQLSpec config(s) or callable function (env: SQLSPEC_CONFIG)",
|
|
50
|
+
required=False,
|
|
51
|
+
default=None,
|
|
52
|
+
type=str,
|
|
53
|
+
envvar="SQLSPEC_CONFIG",
|
|
54
|
+
)
|
|
55
|
+
@click.option(
|
|
56
|
+
"--validate-config", is_flag=True, default=False, help="Validate configuration before executing migrations"
|
|
57
|
+
)
|
|
58
|
+
@click.pass_context
|
|
59
|
+
def sqlspec_group(ctx: "click.Context", config: str | None, validate_config: bool) -> None:
|
|
60
|
+
"""SQLSpec CLI commands.
|
|
61
|
+
|
|
62
|
+
Configuration resolution prefers CLI flag, SQLSPEC_CONFIG env var, and finally the [tool.sqlspec] section.
|
|
63
|
+
Comma-separated paths are split, deduplicated by bind key, and loaded from the current working directory so local modules can be imported.
|
|
64
|
+
When --validate-config is used we report each config's async capability.
|
|
65
|
+
"""
|
|
66
|
+
console = get_console()
|
|
67
|
+
ctx.ensure_object(dict)
|
|
68
|
+
|
|
69
|
+
if config is None:
|
|
70
|
+
config = discover_config_from_pyproject()
|
|
71
|
+
if config:
|
|
72
|
+
console.print("[dim]Using config from pyproject.toml[/]")
|
|
73
|
+
|
|
74
|
+
if config is None:
|
|
75
|
+
console.print("[red]Error: No SQLSpec config found.[/]")
|
|
76
|
+
console.print("\nSpecify config using one of:")
|
|
77
|
+
console.print(" 1. CLI flag: sqlspec --config myapp.config:get_configs <command>")
|
|
78
|
+
console.print(" 2. Environment var: export SQLSPEC_CONFIG=myapp.config:get_configs")
|
|
79
|
+
console.print(" 3. pyproject.toml: [tool.sqlspec]")
|
|
80
|
+
console.print(' config = "myapp.config:get_configs"')
|
|
81
|
+
ctx.exit(1)
|
|
82
|
+
|
|
83
|
+
cwd = str(Path.cwd())
|
|
84
|
+
cwd_added = False
|
|
85
|
+
if cwd not in sys.path:
|
|
86
|
+
sys.path.insert(0, cwd)
|
|
87
|
+
cwd_added = True
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
all_configs: list[AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]] = []
|
|
91
|
+
for config_path in config.split(","):
|
|
92
|
+
config_path = config_path.strip()
|
|
93
|
+
if not config_path:
|
|
94
|
+
continue
|
|
95
|
+
config_result = resolve_config_sync(config_path)
|
|
96
|
+
if isinstance(config_result, Sequence) and not isinstance(config_result, str):
|
|
97
|
+
all_configs.extend(config_result)
|
|
98
|
+
else:
|
|
99
|
+
all_configs.append(config_result) # pyright: ignore
|
|
100
|
+
|
|
101
|
+
configs_by_key: dict[
|
|
102
|
+
str | None, AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]
|
|
103
|
+
] = {}
|
|
104
|
+
for cfg in all_configs:
|
|
105
|
+
configs_by_key[cfg.bind_key] = cfg
|
|
106
|
+
|
|
107
|
+
ctx.obj["configs"] = list(configs_by_key.values())
|
|
108
|
+
|
|
109
|
+
if not ctx.obj["configs"]:
|
|
110
|
+
console.print("[red]Error: No valid configs found after resolution.[/]")
|
|
111
|
+
console.print("\nEnsure your config path returns valid config instance(s).")
|
|
112
|
+
ctx.exit(1)
|
|
113
|
+
|
|
114
|
+
ctx.obj["validate_config"] = validate_config
|
|
115
|
+
|
|
116
|
+
if validate_config:
|
|
117
|
+
console.print(f"[green]✓[/] Successfully loaded {len(ctx.obj['configs'])} config(s)")
|
|
118
|
+
for i, cfg in enumerate(ctx.obj["configs"]):
|
|
119
|
+
config_name = cfg.bind_key or f"config-{i}"
|
|
120
|
+
config_type = type(cfg).__name__
|
|
121
|
+
is_async = cfg.is_async
|
|
122
|
+
execution_hint = "[dim cyan](async-capable)[/]" if is_async else "[dim](sync)[/]"
|
|
123
|
+
console.print(f" [dim]•[/] {config_name}: {config_type} {execution_hint}")
|
|
124
|
+
|
|
125
|
+
except (ImportError, ConfigResolverError) as e:
|
|
126
|
+
console.print(f"[red]Error loading config: {e}[/]")
|
|
127
|
+
ctx.exit(1)
|
|
128
|
+
finally:
|
|
129
|
+
if cwd_added and cwd in sys.path and sys.path[0] == cwd:
|
|
130
|
+
sys.path.remove(cwd)
|
|
131
|
+
|
|
132
|
+
return sqlspec_group
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _ensure_click_context() -> "click.Context":
|
|
136
|
+
"""Return the active Click context, raising if missing (for type-checkers)."""
|
|
137
|
+
|
|
138
|
+
context = click.get_current_context()
|
|
139
|
+
if context is None: # pragma: no cover - click guarantees context in commands
|
|
140
|
+
msg = "SQLSpec CLI commands require an active Click context"
|
|
141
|
+
raise RuntimeError(msg)
|
|
142
|
+
return cast("click.Context", context)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def add_migration_commands(database_group: "Group | None" = None) -> "Group":
|
|
146
|
+
"""Add migration commands to the database group.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
database_group: The database group to add the commands to.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
The database group with the migration commands added.
|
|
153
|
+
"""
|
|
154
|
+
console = get_console()
|
|
155
|
+
|
|
156
|
+
if database_group is None:
|
|
157
|
+
database_group = get_sqlspec_group()
|
|
158
|
+
|
|
159
|
+
bind_key_option = click.option(
|
|
160
|
+
"--bind-key", help="Specify which SQLSpec config to use by bind key", type=str, default=None
|
|
161
|
+
)
|
|
162
|
+
verbose_option = click.option("--verbose", help="Enable verbose output.", type=bool, default=False, is_flag=True)
|
|
163
|
+
no_prompt_option = click.option(
|
|
164
|
+
"--no-prompt",
|
|
165
|
+
help="Do not prompt for confirmation before executing the command.",
|
|
166
|
+
type=bool,
|
|
167
|
+
default=False,
|
|
168
|
+
required=False,
|
|
169
|
+
show_default=True,
|
|
170
|
+
is_flag=True,
|
|
171
|
+
)
|
|
172
|
+
include_option = click.option(
|
|
173
|
+
"--include", multiple=True, help="Include only specific configurations (can be used multiple times)"
|
|
174
|
+
)
|
|
175
|
+
exclude_option = click.option(
|
|
176
|
+
"--exclude", multiple=True, help="Exclude specific configurations (can be used multiple times)"
|
|
177
|
+
)
|
|
178
|
+
dry_run_option = click.option(
|
|
179
|
+
"--dry-run", is_flag=True, default=False, help="Show what would be executed without making changes"
|
|
180
|
+
)
|
|
181
|
+
execution_mode_option = click.option(
|
|
182
|
+
"--execution-mode",
|
|
183
|
+
type=click.Choice(["auto", "sync", "async"]),
|
|
184
|
+
default="auto",
|
|
185
|
+
help="Force execution mode (auto-detects by default)",
|
|
186
|
+
)
|
|
187
|
+
no_auto_sync_option = click.option(
|
|
188
|
+
"--no-auto-sync",
|
|
189
|
+
is_flag=True,
|
|
190
|
+
default=False,
|
|
191
|
+
help="Disable automatic version reconciliation when migrations have been renamed",
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
def get_config_by_bind_key(
|
|
195
|
+
ctx: "click.Context", bind_key: str | None
|
|
196
|
+
) -> "AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]":
|
|
197
|
+
"""Get the SQLSpec config for the specified bind key.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
ctx: The click context.
|
|
201
|
+
bind_key: The bind key to get the config for.
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
The SQLSpec config for the specified bind key.
|
|
205
|
+
"""
|
|
206
|
+
configs = ctx.obj["configs"]
|
|
207
|
+
if bind_key is None:
|
|
208
|
+
config = configs[0]
|
|
209
|
+
else:
|
|
210
|
+
config = None
|
|
211
|
+
for cfg in configs:
|
|
212
|
+
config_name = cfg.bind_key
|
|
213
|
+
if config_name == bind_key:
|
|
214
|
+
config = cfg
|
|
215
|
+
break
|
|
216
|
+
|
|
217
|
+
if config is None:
|
|
218
|
+
console.print(f"[red]No config found for bind key: {bind_key}[/]")
|
|
219
|
+
sys.exit(1)
|
|
220
|
+
|
|
221
|
+
return cast("AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]", config)
|
|
222
|
+
|
|
223
|
+
def _get_adk_configs(
|
|
224
|
+
ctx: "click.Context", bind_key: str | None
|
|
225
|
+
) -> "list[AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]]":
|
|
226
|
+
if bind_key is not None:
|
|
227
|
+
return [get_config_by_bind_key(ctx, bind_key)]
|
|
228
|
+
|
|
229
|
+
configs = ctx.obj["configs"]
|
|
230
|
+
return [cfg for cfg in configs if "adk" in cfg.extension_config]
|
|
231
|
+
|
|
232
|
+
def _get_memory_store_class(
|
|
233
|
+
config: "AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]",
|
|
234
|
+
) -> "type[BaseAsyncADKMemoryStore[Any] | BaseSyncADKMemoryStore[Any]] | None":
|
|
235
|
+
config_module = type(config).__module__
|
|
236
|
+
config_name = type(config).__name__
|
|
237
|
+
|
|
238
|
+
if not config_module.startswith("sqlspec.adapters."):
|
|
239
|
+
return None
|
|
240
|
+
|
|
241
|
+
adapter_name = config_module.split(".")[2]
|
|
242
|
+
store_class_name = config_name.replace("Config", "ADKMemoryStore")
|
|
243
|
+
store_path = f"sqlspec.adapters.{adapter_name}.adk.store.{store_class_name}"
|
|
244
|
+
|
|
245
|
+
try:
|
|
246
|
+
return cast("type[BaseAsyncADKMemoryStore[Any] | BaseSyncADKMemoryStore[Any]]", import_string(store_path))
|
|
247
|
+
except ImportError:
|
|
248
|
+
return None
|
|
249
|
+
|
|
250
|
+
def _is_adk_memory_enabled(
|
|
251
|
+
config: "AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]",
|
|
252
|
+
) -> bool:
|
|
253
|
+
adk_config = cast("dict[str, Any]", config.extension_config.get("adk", {}))
|
|
254
|
+
return bool(adk_config.get("enable_memory", True))
|
|
255
|
+
|
|
256
|
+
async def _cleanup_memory_entries_async(store: "BaseAsyncADKMemoryStore[Any]", days: int) -> int:
|
|
257
|
+
return await store.delete_entries_older_than(days)
|
|
258
|
+
|
|
259
|
+
async def _verify_memory_table_async(config: "AsyncDatabaseConfig[Any, Any, Any]", sql: str) -> None:
|
|
260
|
+
async with config.provide_session() as driver:
|
|
261
|
+
await driver.execute(sql)
|
|
262
|
+
|
|
263
|
+
def get_configs_with_migrations(
|
|
264
|
+
ctx: "click.Context", enabled_only: bool = False
|
|
265
|
+
) -> "list[tuple[str, AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]]]":
|
|
266
|
+
"""Get all configurations that have migrations enabled.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
ctx: The click context.
|
|
270
|
+
enabled_only: If True, only return configs with enabled=True.
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
List of tuples (config_name, config) for configs with migrations enabled.
|
|
274
|
+
"""
|
|
275
|
+
configs: list[AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]] = ctx.obj["configs"]
|
|
276
|
+
migration_configs: list[tuple[str, AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]]] = []
|
|
277
|
+
|
|
278
|
+
for config in configs:
|
|
279
|
+
migration_config = config.migration_config
|
|
280
|
+
if migration_config:
|
|
281
|
+
enabled = migration_config.get("enabled", True)
|
|
282
|
+
if not enabled_only or enabled:
|
|
283
|
+
config_name = config.bind_key or str(type(config).__name__)
|
|
284
|
+
migration_configs.append((config_name, config))
|
|
285
|
+
|
|
286
|
+
return migration_configs
|
|
287
|
+
|
|
288
|
+
def filter_configs(
|
|
289
|
+
configs: "list[tuple[str, Any]]", include: "tuple[str, ...]", exclude: "tuple[str, ...]"
|
|
290
|
+
) -> "list[tuple[str, Any]]":
|
|
291
|
+
"""Filter configuration list based on include/exclude criteria.
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
configs: List of (config_name, config) tuples.
|
|
295
|
+
include: Config names to include (empty means include all).
|
|
296
|
+
exclude: Config names to exclude.
|
|
297
|
+
|
|
298
|
+
Returns:
|
|
299
|
+
Filtered list of configurations.
|
|
300
|
+
"""
|
|
301
|
+
filtered = configs
|
|
302
|
+
if include:
|
|
303
|
+
filtered = [(name, config) for name, config in filtered if name in include]
|
|
304
|
+
if exclude:
|
|
305
|
+
filtered = [(name, config) for name, config in filtered if name not in exclude]
|
|
306
|
+
return filtered
|
|
307
|
+
|
|
308
|
+
def _execute_for_config(
|
|
309
|
+
config: "AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]",
|
|
310
|
+
sync_fn: "Callable[[], Any]",
|
|
311
|
+
async_fn: "Callable[[], Any]",
|
|
312
|
+
) -> Any:
|
|
313
|
+
"""Execute a migration command with appropriate sync/async handling.
|
|
314
|
+
|
|
315
|
+
For sync configs, executes the sync function directly without an event loop.
|
|
316
|
+
For async configs, wraps the async function in run_() to execute with event loop.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
config: The database configuration.
|
|
320
|
+
sync_fn: Function to call for sync configs (should call sync migration methods).
|
|
321
|
+
async_fn: Async function to call for async configs (should await async migration methods).
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
The result of the executed function.
|
|
325
|
+
"""
|
|
326
|
+
if config.is_async:
|
|
327
|
+
return run_(async_fn)()
|
|
328
|
+
return sync_fn()
|
|
329
|
+
|
|
330
|
+
def _partition_configs_by_async(
|
|
331
|
+
configs: "list[tuple[str, Any]]",
|
|
332
|
+
) -> "tuple[list[tuple[str, Any]], list[tuple[str, Any]]]":
|
|
333
|
+
"""Partition configs into sync and async groups.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
configs: List of (config_name, config) tuples.
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
Tuple of (sync_configs, async_configs).
|
|
340
|
+
"""
|
|
341
|
+
sync_configs = [(name, cfg) for name, cfg in configs if not cfg.is_async]
|
|
342
|
+
async_configs = [(name, cfg) for name, cfg in configs if cfg.is_async]
|
|
343
|
+
return sync_configs, async_configs
|
|
344
|
+
|
|
345
|
+
def process_multiple_configs(
|
|
346
|
+
ctx: "click.Context",
|
|
347
|
+
bind_key: str | None,
|
|
348
|
+
include: "tuple[str, ...]",
|
|
349
|
+
exclude: "tuple[str, ...]",
|
|
350
|
+
dry_run: bool,
|
|
351
|
+
operation_name: str,
|
|
352
|
+
) -> "list[tuple[str, Any]] | None":
|
|
353
|
+
"""Process configuration selection for multi-config operations.
|
|
354
|
+
|
|
355
|
+
Requests targeting a single bind key or with only one available config run in single-config mode.
|
|
356
|
+
Enabled configs are used unless include/exclude widen the set, and dry runs simply list the configs that would execute.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
ctx: Click context.
|
|
360
|
+
bind_key: Specific bind key to target.
|
|
361
|
+
include: Config names to include.
|
|
362
|
+
exclude: Config names to exclude.
|
|
363
|
+
dry_run: Whether this is a dry run.
|
|
364
|
+
operation_name: Name of the operation for display.
|
|
365
|
+
|
|
366
|
+
Returns:
|
|
367
|
+
List of (config_name, config) tuples to process, or None for single config mode.
|
|
368
|
+
"""
|
|
369
|
+
if bind_key and not include and not exclude:
|
|
370
|
+
return None
|
|
371
|
+
|
|
372
|
+
enabled_only = not include and not exclude
|
|
373
|
+
migration_configs = get_configs_with_migrations(ctx, enabled_only=enabled_only)
|
|
374
|
+
|
|
375
|
+
if len(migration_configs) <= 1 and not include and not exclude:
|
|
376
|
+
return None
|
|
377
|
+
|
|
378
|
+
configs_to_process = filter_configs(migration_configs, include, exclude)
|
|
379
|
+
|
|
380
|
+
if not configs_to_process:
|
|
381
|
+
console.print("[yellow]No configurations match the specified criteria.[/]")
|
|
382
|
+
return []
|
|
383
|
+
|
|
384
|
+
if dry_run:
|
|
385
|
+
console.print(f"[blue]Dry run: Would {operation_name} {len(configs_to_process)} configuration(s)[/]")
|
|
386
|
+
for config_name, _ in configs_to_process:
|
|
387
|
+
console.print(f" • {config_name}")
|
|
388
|
+
return []
|
|
389
|
+
|
|
390
|
+
return configs_to_process
|
|
391
|
+
|
|
392
|
+
@database_group.command(name="show-current-revision", help="Shows the current revision for the database.")
|
|
393
|
+
@bind_key_option
|
|
394
|
+
@verbose_option
|
|
395
|
+
@include_option
|
|
396
|
+
@exclude_option
|
|
397
|
+
def show_database_revision( # pyright: ignore[reportUnusedFunction]
|
|
398
|
+
bind_key: str | None, verbose: bool, include: "tuple[str, ...]", exclude: "tuple[str, ...]"
|
|
399
|
+
) -> None:
|
|
400
|
+
"""Show current database revision.
|
|
401
|
+
|
|
402
|
+
Supports multi-config execution by partitioning selected configs into sync and async groups before dispatching them separately.
|
|
403
|
+
"""
|
|
404
|
+
from sqlspec.migrations.commands import create_migration_commands
|
|
405
|
+
|
|
406
|
+
ctx = _ensure_click_context()
|
|
407
|
+
|
|
408
|
+
def _show_for_config(config: Any) -> None:
|
|
409
|
+
"""Show current revision for a single config with sync/async dispatch."""
|
|
410
|
+
migration_commands: SyncMigrationCommands[Any] | AsyncMigrationCommands[Any] = create_migration_commands(
|
|
411
|
+
config=config
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
def sync_show() -> None:
|
|
415
|
+
migration_commands.current(verbose=verbose)
|
|
416
|
+
|
|
417
|
+
async def async_show() -> None:
|
|
418
|
+
await cast("AsyncMigrationCommands[Any]", migration_commands).current(verbose=verbose)
|
|
419
|
+
|
|
420
|
+
_execute_for_config(config, sync_show, async_show)
|
|
421
|
+
|
|
422
|
+
configs_to_process = process_multiple_configs(
|
|
423
|
+
ctx, bind_key, include, exclude, dry_run=False, operation_name="show current revision"
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
if configs_to_process is not None:
|
|
427
|
+
if not configs_to_process:
|
|
428
|
+
return
|
|
429
|
+
|
|
430
|
+
console.rule("[yellow]Listing current revisions for all configurations[/]", align="left")
|
|
431
|
+
|
|
432
|
+
sync_configs, async_configs = _partition_configs_by_async(configs_to_process)
|
|
433
|
+
|
|
434
|
+
for config_name, config in sync_configs:
|
|
435
|
+
console.print(f"\n[blue]Configuration: {config_name}[/]")
|
|
436
|
+
try:
|
|
437
|
+
_show_for_config(config)
|
|
438
|
+
except Exception as e:
|
|
439
|
+
console.print(f"[red]✗ Failed to get current revision for {config_name}: {e}[/]")
|
|
440
|
+
|
|
441
|
+
if async_configs:
|
|
442
|
+
|
|
443
|
+
async def _run_async_configs() -> None:
|
|
444
|
+
for config_name, config in async_configs:
|
|
445
|
+
console.print(f"\n[blue]Configuration: {config_name}[/]")
|
|
446
|
+
try:
|
|
447
|
+
migration_commands: AsyncMigrationCommands[Any] = cast(
|
|
448
|
+
"AsyncMigrationCommands[Any]", create_migration_commands(config=config)
|
|
449
|
+
)
|
|
450
|
+
await migration_commands.current(verbose=verbose)
|
|
451
|
+
except Exception as e:
|
|
452
|
+
console.print(f"[red]✗ Failed to get current revision for {config_name}: {e}[/]")
|
|
453
|
+
|
|
454
|
+
run_(_run_async_configs)()
|
|
455
|
+
else:
|
|
456
|
+
console.rule("[yellow]Listing current revision[/]", align="left")
|
|
457
|
+
sqlspec_config = get_config_by_bind_key(ctx, bind_key)
|
|
458
|
+
_show_for_config(sqlspec_config)
|
|
459
|
+
|
|
460
|
+
@database_group.command(name="downgrade", help="Downgrade database to a specific revision.")
|
|
461
|
+
@bind_key_option
|
|
462
|
+
@no_prompt_option
|
|
463
|
+
@include_option
|
|
464
|
+
@exclude_option
|
|
465
|
+
@dry_run_option
|
|
466
|
+
@click.argument("revision", type=str, default="-1")
|
|
467
|
+
def downgrade_database( # pyright: ignore[reportUnusedFunction]
|
|
468
|
+
bind_key: str | None,
|
|
469
|
+
revision: str,
|
|
470
|
+
no_prompt: bool,
|
|
471
|
+
include: "tuple[str, ...]",
|
|
472
|
+
exclude: "tuple[str, ...]",
|
|
473
|
+
dry_run: bool,
|
|
474
|
+
) -> None:
|
|
475
|
+
"""Downgrade the database to the latest revision."""
|
|
476
|
+
|
|
477
|
+
from sqlspec.migrations.commands import create_migration_commands
|
|
478
|
+
|
|
479
|
+
ctx = _ensure_click_context()
|
|
480
|
+
|
|
481
|
+
def _downgrade_for_config(config: Any) -> None:
|
|
482
|
+
"""Downgrade a single config with sync/async dispatch."""
|
|
483
|
+
migration_commands: SyncMigrationCommands[Any] | AsyncMigrationCommands[Any] = create_migration_commands(
|
|
484
|
+
config=config
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
def sync_downgrade() -> None:
|
|
488
|
+
migration_commands.downgrade(revision=revision, dry_run=dry_run)
|
|
489
|
+
|
|
490
|
+
async def async_downgrade() -> None:
|
|
491
|
+
await cast("AsyncMigrationCommands[Any]", migration_commands).downgrade(
|
|
492
|
+
revision=revision, dry_run=dry_run
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
_execute_for_config(config, sync_downgrade, async_downgrade)
|
|
496
|
+
|
|
497
|
+
configs_to_process = process_multiple_configs(
|
|
498
|
+
ctx, bind_key, include, exclude, dry_run=dry_run, operation_name=f"downgrade to {revision}"
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
if configs_to_process is not None:
|
|
502
|
+
if not configs_to_process:
|
|
503
|
+
return
|
|
504
|
+
|
|
505
|
+
if not no_prompt and not Confirm.ask(
|
|
506
|
+
f"[bold]Are you sure you want to downgrade {len(configs_to_process)} configuration(s) to revision {revision}?[/]"
|
|
507
|
+
):
|
|
508
|
+
console.print("[yellow]Operation cancelled.[/]")
|
|
509
|
+
return
|
|
510
|
+
|
|
511
|
+
console.rule("[yellow]Starting multi-configuration downgrade process[/]", align="left")
|
|
512
|
+
|
|
513
|
+
sync_configs, async_configs = _partition_configs_by_async(configs_to_process)
|
|
514
|
+
|
|
515
|
+
for config_name, config in sync_configs:
|
|
516
|
+
console.print(f"[blue]Downgrading configuration: {config_name}[/]")
|
|
517
|
+
try:
|
|
518
|
+
_downgrade_for_config(config)
|
|
519
|
+
console.print(f"[green]✓ Successfully downgraded: {config_name}[/]")
|
|
520
|
+
except Exception as e:
|
|
521
|
+
console.print(f"[red]✗ Failed to downgrade {config_name}: {e}[/]")
|
|
522
|
+
|
|
523
|
+
if async_configs:
|
|
524
|
+
|
|
525
|
+
async def _run_async_configs() -> None:
|
|
526
|
+
for config_name, config in async_configs:
|
|
527
|
+
console.print(f"[blue]Downgrading configuration: {config_name}[/]")
|
|
528
|
+
try:
|
|
529
|
+
migration_commands: AsyncMigrationCommands[Any] = cast(
|
|
530
|
+
"AsyncMigrationCommands[Any]", create_migration_commands(config=config)
|
|
531
|
+
)
|
|
532
|
+
await migration_commands.downgrade(revision=revision, dry_run=dry_run)
|
|
533
|
+
console.print(f"[green]✓ Successfully downgraded: {config_name}[/]")
|
|
534
|
+
except Exception as e:
|
|
535
|
+
console.print(f"[red]✗ Failed to downgrade {config_name}: {e}[/]")
|
|
536
|
+
|
|
537
|
+
run_(_run_async_configs)()
|
|
538
|
+
else:
|
|
539
|
+
console.rule("[yellow]Starting database downgrade process[/]", align="left")
|
|
540
|
+
input_confirmed = (
|
|
541
|
+
True
|
|
542
|
+
if no_prompt
|
|
543
|
+
else Confirm.ask(f"Are you sure you want to downgrade the database to the `{revision}` revision?")
|
|
544
|
+
)
|
|
545
|
+
if input_confirmed:
|
|
546
|
+
sqlspec_config = get_config_by_bind_key(ctx, bind_key)
|
|
547
|
+
_downgrade_for_config(sqlspec_config)
|
|
548
|
+
|
|
549
|
+
@database_group.command(name="upgrade", help="Upgrade database to a specific revision.")
|
|
550
|
+
@bind_key_option
|
|
551
|
+
@no_prompt_option
|
|
552
|
+
@include_option
|
|
553
|
+
@exclude_option
|
|
554
|
+
@dry_run_option
|
|
555
|
+
@execution_mode_option
|
|
556
|
+
@no_auto_sync_option
|
|
557
|
+
@click.argument("revision", type=str, default="head")
|
|
558
|
+
def upgrade_database( # pyright: ignore[reportUnusedFunction]
|
|
559
|
+
bind_key: str | None,
|
|
560
|
+
revision: str,
|
|
561
|
+
no_prompt: bool,
|
|
562
|
+
include: "tuple[str, ...]",
|
|
563
|
+
exclude: "tuple[str, ...]",
|
|
564
|
+
dry_run: bool,
|
|
565
|
+
execution_mode: str,
|
|
566
|
+
no_auto_sync: bool,
|
|
567
|
+
) -> None:
|
|
568
|
+
"""Upgrade the database to the latest revision.
|
|
569
|
+
|
|
570
|
+
Non-automatic execution modes are surfaced in the console, and multi-config flows reuse ``process_multiple_configs`` to split sync/async executions while honoring dry-run and auto-sync flags.
|
|
571
|
+
"""
|
|
572
|
+
from sqlspec.migrations.commands import create_migration_commands
|
|
573
|
+
|
|
574
|
+
ctx = _ensure_click_context()
|
|
575
|
+
if execution_mode != "auto":
|
|
576
|
+
console.print(f"[dim]Execution mode: {execution_mode}[/]")
|
|
577
|
+
|
|
578
|
+
def _upgrade_for_config(config: Any) -> None:
|
|
579
|
+
"""Upgrade a single config with sync/async dispatch."""
|
|
580
|
+
migration_commands: SyncMigrationCommands[Any] | AsyncMigrationCommands[Any] = create_migration_commands(
|
|
581
|
+
config=config
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
def sync_upgrade() -> None:
|
|
585
|
+
migration_commands.upgrade(revision=revision, auto_sync=not no_auto_sync, dry_run=dry_run)
|
|
586
|
+
|
|
587
|
+
async def async_upgrade() -> None:
|
|
588
|
+
await cast("AsyncMigrationCommands[Any]", migration_commands).upgrade(
|
|
589
|
+
revision=revision, auto_sync=not no_auto_sync, dry_run=dry_run
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
_execute_for_config(config, sync_upgrade, async_upgrade)
|
|
593
|
+
|
|
594
|
+
configs_to_process = process_multiple_configs(
|
|
595
|
+
ctx, bind_key, include, exclude, dry_run, operation_name=f"upgrade to {revision}"
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
if configs_to_process is not None:
|
|
599
|
+
if not configs_to_process:
|
|
600
|
+
return
|
|
601
|
+
|
|
602
|
+
if not no_prompt and not Confirm.ask(
|
|
603
|
+
f"[bold]Are you sure you want to upgrade {len(configs_to_process)} configuration(s) to revision {revision}?[/]"
|
|
604
|
+
):
|
|
605
|
+
console.print("[yellow]Operation cancelled.[/]")
|
|
606
|
+
return
|
|
607
|
+
|
|
608
|
+
console.rule("[yellow]Starting multi-configuration upgrade process[/]", align="left")
|
|
609
|
+
|
|
610
|
+
sync_configs, async_configs = _partition_configs_by_async(configs_to_process)
|
|
611
|
+
|
|
612
|
+
for config_name, config in sync_configs:
|
|
613
|
+
console.print(f"[blue]Upgrading configuration: {config_name}[/]")
|
|
614
|
+
try:
|
|
615
|
+
_upgrade_for_config(config)
|
|
616
|
+
console.print(f"[green]✓ Successfully upgraded: {config_name}[/]")
|
|
617
|
+
except Exception as e:
|
|
618
|
+
console.print(f"[red]✗ Failed to upgrade {config_name}: {e}[/]")
|
|
619
|
+
|
|
620
|
+
if async_configs:
|
|
621
|
+
|
|
622
|
+
async def _run_async_configs() -> None:
|
|
623
|
+
for config_name, config in async_configs:
|
|
624
|
+
console.print(f"[blue]Upgrading configuration: {config_name}[/]")
|
|
625
|
+
try:
|
|
626
|
+
migration_commands: AsyncMigrationCommands[Any] = cast(
|
|
627
|
+
"AsyncMigrationCommands[Any]", create_migration_commands(config=config)
|
|
628
|
+
)
|
|
629
|
+
await migration_commands.upgrade(
|
|
630
|
+
revision=revision, auto_sync=not no_auto_sync, dry_run=dry_run
|
|
631
|
+
)
|
|
632
|
+
console.print(f"[green]✓ Successfully upgraded: {config_name}[/]")
|
|
633
|
+
except Exception as e:
|
|
634
|
+
console.print(f"[red]✗ Failed to upgrade {config_name}: {e}[/]")
|
|
635
|
+
|
|
636
|
+
run_(_run_async_configs)()
|
|
637
|
+
else:
|
|
638
|
+
console.rule("[yellow]Starting database upgrade process[/]", align="left")
|
|
639
|
+
input_confirmed = (
|
|
640
|
+
True
|
|
641
|
+
if no_prompt
|
|
642
|
+
else Confirm.ask(f"[bold]Are you sure you want migrate the database to the `{revision}` revision?[/]")
|
|
643
|
+
)
|
|
644
|
+
if input_confirmed:
|
|
645
|
+
sqlspec_config = get_config_by_bind_key(ctx, bind_key)
|
|
646
|
+
_upgrade_for_config(sqlspec_config)
|
|
647
|
+
|
|
648
|
+
@database_group.command(help="Stamp the revision table with the given revision")
|
|
649
|
+
@click.argument("revision", type=str)
|
|
650
|
+
@bind_key_option
|
|
651
|
+
def stamp(bind_key: str | None, revision: str) -> None: # pyright: ignore[reportUnusedFunction]
|
|
652
|
+
"""Stamp the revision table with the given revision."""
|
|
653
|
+
from sqlspec.migrations.commands import create_migration_commands
|
|
654
|
+
|
|
655
|
+
ctx = _ensure_click_context()
|
|
656
|
+
|
|
657
|
+
sqlspec_config = get_config_by_bind_key(ctx, bind_key)
|
|
658
|
+
migration_commands = create_migration_commands(config=sqlspec_config)
|
|
659
|
+
|
|
660
|
+
def sync_stamp() -> None:
|
|
661
|
+
migration_commands.stamp(revision=revision)
|
|
662
|
+
|
|
663
|
+
async def async_stamp() -> None:
|
|
664
|
+
await cast("AsyncMigrationCommands[Any]", migration_commands).stamp(revision=revision)
|
|
665
|
+
|
|
666
|
+
_execute_for_config(sqlspec_config, sync_stamp, async_stamp)
|
|
667
|
+
|
|
668
|
+
@database_group.command(name="init", help="Initialize migrations for the project.")
|
|
669
|
+
@bind_key_option
|
|
670
|
+
@click.argument("directory", default=None, required=False)
|
|
671
|
+
@click.option("--package", is_flag=True, default=True, help="Create `__init__.py` for created folder")
|
|
672
|
+
@no_prompt_option
|
|
673
|
+
def init_sqlspec( # pyright: ignore[reportUnusedFunction]
|
|
674
|
+
bind_key: str | None, directory: str | None, package: bool, no_prompt: bool
|
|
675
|
+
) -> None:
|
|
676
|
+
"""Initialize the database migrations.
|
|
677
|
+
|
|
678
|
+
Sync configs are handled inline while async configs run via a single ``run_`` call so migrations stay in sync.
|
|
679
|
+
"""
|
|
680
|
+
from sqlspec.migrations.commands import create_migration_commands
|
|
681
|
+
|
|
682
|
+
ctx = _ensure_click_context()
|
|
683
|
+
|
|
684
|
+
console.rule("[yellow]Initializing database migrations.", align="left")
|
|
685
|
+
input_confirmed = (
|
|
686
|
+
True if no_prompt else Confirm.ask("[bold]Are you sure you want initialize migrations for the project?[/]")
|
|
687
|
+
)
|
|
688
|
+
if not input_confirmed:
|
|
689
|
+
return
|
|
690
|
+
|
|
691
|
+
configs = [get_config_by_bind_key(ctx, bind_key)] if bind_key is not None else ctx.obj["configs"]
|
|
692
|
+
|
|
693
|
+
sync_configs = [cfg for cfg in configs if not cfg.is_async]
|
|
694
|
+
async_configs = [cfg for cfg in configs if cfg.is_async]
|
|
695
|
+
|
|
696
|
+
for config in sync_configs:
|
|
697
|
+
migration_config_dict = config.migration_config or {}
|
|
698
|
+
target_directory = (
|
|
699
|
+
str(migration_config_dict.get("script_location", "migrations")) if directory is None else directory
|
|
700
|
+
)
|
|
701
|
+
migration_commands = create_migration_commands(config=config)
|
|
702
|
+
migration_commands.init(directory=target_directory, package=package)
|
|
703
|
+
|
|
704
|
+
if async_configs:
|
|
705
|
+
|
|
706
|
+
async def _init_async_configs() -> None:
|
|
707
|
+
for config in async_configs:
|
|
708
|
+
migration_config_dict = config.migration_config or {}
|
|
709
|
+
target_directory = (
|
|
710
|
+
str(migration_config_dict.get("script_location", "migrations"))
|
|
711
|
+
if directory is None
|
|
712
|
+
else directory
|
|
713
|
+
)
|
|
714
|
+
migration_commands: AsyncMigrationCommands[Any] = cast(
|
|
715
|
+
"AsyncMigrationCommands[Any]", create_migration_commands(config=config)
|
|
716
|
+
)
|
|
717
|
+
await migration_commands.init(directory=target_directory, package=package)
|
|
718
|
+
|
|
719
|
+
run_(_init_async_configs)()
|
|
720
|
+
|
|
721
|
+
@_safe_group_command(
|
|
722
|
+
database_group, name="create-migration", help="Create a new migration revision.", aliases=["make-migration"]
|
|
723
|
+
)
|
|
724
|
+
@bind_key_option
|
|
725
|
+
@click.option("-m", "--message", default=None, help="Revision message")
|
|
726
|
+
@click.option(
|
|
727
|
+
"--format",
|
|
728
|
+
"--file-type",
|
|
729
|
+
"file_format",
|
|
730
|
+
type=click.Choice(["sql", "py"]),
|
|
731
|
+
default=None,
|
|
732
|
+
help="File format for the generated migration (defaults to template profile)",
|
|
733
|
+
)
|
|
734
|
+
@no_prompt_option
|
|
735
|
+
def create_revision( # pyright: ignore[reportUnusedFunction]
|
|
736
|
+
bind_key: str | None, message: str | None, file_format: str | None, no_prompt: bool
|
|
737
|
+
) -> None:
|
|
738
|
+
"""Create a new database revision."""
|
|
739
|
+
from sqlspec.migrations.commands import create_migration_commands
|
|
740
|
+
|
|
741
|
+
ctx = _ensure_click_context()
|
|
742
|
+
|
|
743
|
+
console.rule("[yellow]Creating new migration revision[/]", align="left")
|
|
744
|
+
message_text = message
|
|
745
|
+
if message_text is None:
|
|
746
|
+
message_text = (
|
|
747
|
+
"new migration" if no_prompt else Prompt.ask("Please enter a message describing this revision")
|
|
748
|
+
)
|
|
749
|
+
|
|
750
|
+
sqlspec_config = get_config_by_bind_key(ctx, bind_key)
|
|
751
|
+
param_source = ctx.get_parameter_source("file_format")
|
|
752
|
+
effective_format = None if param_source is ParameterSource.DEFAULT else file_format
|
|
753
|
+
migration_commands = create_migration_commands(config=sqlspec_config)
|
|
754
|
+
|
|
755
|
+
def sync_revision() -> None:
|
|
756
|
+
migration_commands.revision(message=message_text, file_type=effective_format)
|
|
757
|
+
|
|
758
|
+
async def async_revision() -> None:
|
|
759
|
+
await cast("AsyncMigrationCommands[Any]", migration_commands).revision(
|
|
760
|
+
message=message_text, file_type=effective_format
|
|
761
|
+
)
|
|
762
|
+
|
|
763
|
+
_execute_for_config(sqlspec_config, sync_revision, async_revision)
|
|
764
|
+
|
|
765
|
+
@database_group.command(name="fix", help="Convert timestamp migrations to sequential format.")
|
|
766
|
+
@bind_key_option
|
|
767
|
+
@dry_run_option
|
|
768
|
+
@click.option("--yes", is_flag=True, help="Skip confirmation prompt")
|
|
769
|
+
@click.option("--no-database", is_flag=True, help="Skip database record updates")
|
|
770
|
+
def fix_migrations( # pyright: ignore[reportUnusedFunction]
|
|
771
|
+
bind_key: str | None, dry_run: bool, yes: bool, no_database: bool
|
|
772
|
+
) -> None:
|
|
773
|
+
"""Convert timestamp migrations to sequential format."""
|
|
774
|
+
from sqlspec.migrations.commands import create_migration_commands
|
|
775
|
+
|
|
776
|
+
ctx = _ensure_click_context()
|
|
777
|
+
|
|
778
|
+
console.rule("[yellow]Migration Fix Command[/]", align="left")
|
|
779
|
+
sqlspec_config = get_config_by_bind_key(ctx, bind_key)
|
|
780
|
+
migration_commands = create_migration_commands(config=sqlspec_config)
|
|
781
|
+
|
|
782
|
+
def sync_fix() -> None:
|
|
783
|
+
migration_commands.fix(dry_run=dry_run, update_database=not no_database, yes=yes)
|
|
784
|
+
|
|
785
|
+
async def async_fix() -> None:
|
|
786
|
+
await cast("AsyncMigrationCommands[Any]", migration_commands).fix(
|
|
787
|
+
dry_run=dry_run, update_database=not no_database, yes=yes
|
|
788
|
+
)
|
|
789
|
+
|
|
790
|
+
_execute_for_config(sqlspec_config, sync_fix, async_fix)
|
|
791
|
+
|
|
792
|
+
@database_group.command(name="show-config", help="Show all configurations with migrations enabled.")
|
|
793
|
+
@bind_key_option
|
|
794
|
+
def show_config(bind_key: str | None = None) -> None: # pyright: ignore[reportUnusedFunction]
|
|
795
|
+
"""Show and display all configurations with migrations enabled.
|
|
796
|
+
|
|
797
|
+
Providing a bind key validates that config while still iterating the original config list to remain compatible with existing callers.
|
|
798
|
+
"""
|
|
799
|
+
ctx = _ensure_click_context()
|
|
800
|
+
|
|
801
|
+
if bind_key is not None:
|
|
802
|
+
get_config_by_bind_key(ctx, bind_key)
|
|
803
|
+
all_configs: list[AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]] = ctx.obj[
|
|
804
|
+
"configs"
|
|
805
|
+
]
|
|
806
|
+
migration_configs: list[
|
|
807
|
+
tuple[str, AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]]
|
|
808
|
+
] = []
|
|
809
|
+
for cfg in all_configs:
|
|
810
|
+
config_name = cfg.bind_key
|
|
811
|
+
if config_name == bind_key and cfg.migration_config:
|
|
812
|
+
migration_configs.append((config_name, cfg)) # pyright: ignore[reportArgumentType]
|
|
813
|
+
else:
|
|
814
|
+
migration_configs = get_configs_with_migrations(ctx)
|
|
815
|
+
|
|
816
|
+
if not migration_configs:
|
|
817
|
+
console.print("[yellow]No configurations with migrations detected.[/]")
|
|
818
|
+
return
|
|
819
|
+
|
|
820
|
+
table = Table(title="Migration Configurations")
|
|
821
|
+
table.add_column("Configuration Name", style="cyan")
|
|
822
|
+
table.add_column("Migration Path", style="blue")
|
|
823
|
+
table.add_column("Status", style="green")
|
|
824
|
+
|
|
825
|
+
for config_name, config in migration_configs:
|
|
826
|
+
migration_config_dict = config.migration_config or {}
|
|
827
|
+
script_location = migration_config_dict.get("script_location", "migrations")
|
|
828
|
+
table.add_row(config_name, str(script_location), "Migration Enabled")
|
|
829
|
+
|
|
830
|
+
console.print(table)
|
|
831
|
+
console.print(f"[blue]Found {len(migration_configs)} configuration(s) with migrations enabled.[/]")
|
|
832
|
+
|
|
833
|
+
@database_group.group(name="adk", help="ADK extension commands")
|
|
834
|
+
def adk_group() -> None: # pyright: ignore[reportUnusedFunction]
|
|
835
|
+
"""ADK extension commands."""
|
|
836
|
+
|
|
837
|
+
@adk_group.group(name="memory", help="ADK memory store commands")
|
|
838
|
+
def adk_memory_group() -> None: # pyright: ignore[reportUnusedFunction]
|
|
839
|
+
"""ADK memory store commands."""
|
|
840
|
+
|
|
841
|
+
@adk_memory_group.command(name="cleanup", help="Delete memory entries older than N days")
|
|
842
|
+
@bind_key_option
|
|
843
|
+
@click.option("--days", type=int, required=True, help="Delete entries older than this many days")
|
|
844
|
+
def cleanup_memory(bind_key: str | None, days: int) -> None: # pyright: ignore[reportUnusedFunction]
|
|
845
|
+
"""Cleanup memory entries older than N days."""
|
|
846
|
+
ctx = _ensure_click_context()
|
|
847
|
+
configs = _get_adk_configs(ctx, bind_key)
|
|
848
|
+
|
|
849
|
+
if not configs:
|
|
850
|
+
console.print("[yellow]No ADK configurations found.[/]")
|
|
851
|
+
return
|
|
852
|
+
|
|
853
|
+
for cfg in configs:
|
|
854
|
+
config_name = cfg.bind_key or "default"
|
|
855
|
+
if not _is_adk_memory_enabled(cfg):
|
|
856
|
+
console.print(f"[yellow]Memory disabled for {config_name}; skipping.[/]")
|
|
857
|
+
continue
|
|
858
|
+
|
|
859
|
+
store_class = _get_memory_store_class(cfg)
|
|
860
|
+
if store_class is None:
|
|
861
|
+
console.print(f"[yellow]No memory store found for {config_name}; skipping.[/]")
|
|
862
|
+
continue
|
|
863
|
+
|
|
864
|
+
if isinstance(cfg, AsyncDatabaseConfig):
|
|
865
|
+
async_store = cast("BaseAsyncADKMemoryStore[Any]", store_class(cfg))
|
|
866
|
+
deleted = run_(_cleanup_memory_entries_async)(async_store, days)
|
|
867
|
+
console.print(f"[green]✓[/] {config_name}: deleted {deleted} memory entries older than {days} days")
|
|
868
|
+
continue
|
|
869
|
+
sync_store = cast("BaseSyncADKMemoryStore[Any]", store_class(cfg))
|
|
870
|
+
deleted = sync_store.delete_entries_older_than(days)
|
|
871
|
+
console.print(f"[green]✓[/] {config_name}: deleted {deleted} memory entries older than {days} days")
|
|
872
|
+
|
|
873
|
+
@adk_memory_group.command(name="verify", help="Verify memory table exists and is reachable")
|
|
874
|
+
@bind_key_option
|
|
875
|
+
def verify_memory(bind_key: str | None) -> None: # pyright: ignore[reportUnusedFunction]
|
|
876
|
+
"""Verify memory tables are reachable for configured adapters."""
|
|
877
|
+
ctx = _ensure_click_context()
|
|
878
|
+
configs = _get_adk_configs(ctx, bind_key)
|
|
879
|
+
|
|
880
|
+
if not configs:
|
|
881
|
+
console.print("[yellow]No ADK configurations found.[/]")
|
|
882
|
+
return
|
|
883
|
+
|
|
884
|
+
for cfg in configs:
|
|
885
|
+
config_name = cfg.bind_key or "default"
|
|
886
|
+
if not _is_adk_memory_enabled(cfg):
|
|
887
|
+
console.print(f"[yellow]Memory disabled for {config_name}; skipping.[/]")
|
|
888
|
+
continue
|
|
889
|
+
|
|
890
|
+
store_class = _get_memory_store_class(cfg)
|
|
891
|
+
if store_class is None:
|
|
892
|
+
console.print(f"[yellow]No memory store found for {config_name}; skipping.[/]")
|
|
893
|
+
continue
|
|
894
|
+
|
|
895
|
+
try:
|
|
896
|
+
if isinstance(cfg, AsyncDatabaseConfig):
|
|
897
|
+
async_cfg: AsyncDatabaseConfig[Any, Any, Any] = cfg
|
|
898
|
+
async_store = cast("BaseAsyncADKMemoryStore[Any]", store_class(async_cfg))
|
|
899
|
+
sql = f"SELECT 1 FROM {async_store.memory_table} WHERE 1 = 0"
|
|
900
|
+
run_(_verify_memory_table_async)(async_cfg, sql)
|
|
901
|
+
console.print(f"[green]✓[/] {config_name}: memory table reachable")
|
|
902
|
+
continue
|
|
903
|
+
sync_store = cast("BaseSyncADKMemoryStore[Any]", store_class(cfg))
|
|
904
|
+
sql = f"SELECT 1 FROM {sync_store.memory_table} WHERE 1 = 0"
|
|
905
|
+
with cfg.provide_session() as driver:
|
|
906
|
+
driver.execute(sql)
|
|
907
|
+
console.print(f"[green]✓[/] {config_name}: memory table reachable")
|
|
908
|
+
except Exception as exc:
|
|
909
|
+
console.print(f"[red]✗[/] {config_name}: {exc}")
|
|
910
|
+
|
|
911
|
+
return database_group
|