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,731 @@
|
|
|
1
|
+
"""Base classes for SQLSpec migrations."""
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
import hashlib
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
|
|
8
|
+
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
|
|
11
|
+
from sqlspec.builder import CreateTable, Delete, Insert, Select, Update, sql
|
|
12
|
+
from sqlspec.loader import SQLFileLoader
|
|
13
|
+
from sqlspec.migrations.context import MigrationContext
|
|
14
|
+
from sqlspec.migrations.loaders import get_migration_loader
|
|
15
|
+
from sqlspec.migrations.templates import MigrationTemplateSettings, TemplateDescriptionHints, build_template_settings
|
|
16
|
+
from sqlspec.migrations.version import parse_version
|
|
17
|
+
from sqlspec.utils.logging import get_logger
|
|
18
|
+
from sqlspec.utils.module_loader import module_to_os_path
|
|
19
|
+
from sqlspec.utils.sync_tools import await_
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from sqlspec.config import DatabaseConfigProtocol
|
|
23
|
+
from sqlspec.observability import ObservabilityRuntime
|
|
24
|
+
|
|
25
|
+
__all__ = ("BaseMigrationCommands", "BaseMigrationRunner", "BaseMigrationTracker")
|
|
26
|
+
|
|
27
|
+
DriverT = TypeVar("DriverT")
|
|
28
|
+
ConfigT = TypeVar("ConfigT", bound="DatabaseConfigProtocol[Any, Any, Any]")
|
|
29
|
+
|
|
30
|
+
logger = get_logger("sqlspec.migrations.base")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class BaseMigrationTracker(ABC, Generic[DriverT]):
|
|
34
|
+
"""Base class for migration version tracking."""
|
|
35
|
+
|
|
36
|
+
__slots__ = ("version_table",)
|
|
37
|
+
|
|
38
|
+
def __init__(self, version_table_name: str = "ddl_migrations") -> None:
|
|
39
|
+
"""Initialize the migration tracker.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
version_table_name: Name of the table to track migrations.
|
|
43
|
+
"""
|
|
44
|
+
self.version_table = version_table_name
|
|
45
|
+
|
|
46
|
+
def _get_create_table_sql(self) -> CreateTable:
|
|
47
|
+
"""Get SQL builder for creating the tracking table.
|
|
48
|
+
|
|
49
|
+
Schema includes both legacy and new versioning columns:
|
|
50
|
+
- version_num: Migration version (sequential or timestamp format)
|
|
51
|
+
- version_type: Format indicator ('sequential' or 'timestamp')
|
|
52
|
+
- execution_sequence: Auto-incrementing application order
|
|
53
|
+
- description: Human-readable migration description
|
|
54
|
+
- applied_at: Timestamp when migration was applied
|
|
55
|
+
- execution_time_ms: Migration execution duration
|
|
56
|
+
- checksum: MD5 hash for content verification
|
|
57
|
+
- applied_by: User who applied the migration
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
SQL builder object for table creation.
|
|
61
|
+
"""
|
|
62
|
+
return (
|
|
63
|
+
sql
|
|
64
|
+
.create_table(self.version_table)
|
|
65
|
+
.if_not_exists()
|
|
66
|
+
.column("version_num", "VARCHAR(32)", primary_key=True)
|
|
67
|
+
.column("version_type", "VARCHAR(16)")
|
|
68
|
+
.column("execution_sequence", "INTEGER")
|
|
69
|
+
.column("description", "TEXT")
|
|
70
|
+
.column("applied_at", "TIMESTAMP", default="CURRENT_TIMESTAMP", not_null=True)
|
|
71
|
+
.column("execution_time_ms", "INTEGER")
|
|
72
|
+
.column("checksum", "VARCHAR(64)")
|
|
73
|
+
.column("applied_by", "VARCHAR(255)")
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def _get_current_version_sql(self) -> Select:
|
|
77
|
+
"""Get SQL builder for retrieving current version.
|
|
78
|
+
|
|
79
|
+
Uses execution_sequence to get the last applied migration,
|
|
80
|
+
which may differ from version_num order due to out-of-order migrations.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
SQL builder object for version query.
|
|
84
|
+
"""
|
|
85
|
+
return sql.select("version_num").from_(self.version_table).order_by("execution_sequence DESC").limit(1)
|
|
86
|
+
|
|
87
|
+
def _get_applied_migrations_sql(self) -> Select:
|
|
88
|
+
"""Get SQL builder for retrieving all applied migrations.
|
|
89
|
+
|
|
90
|
+
Orders by execution_sequence to show migrations in application order,
|
|
91
|
+
which preserves the actual execution history for out-of-order migrations.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
SQL builder object for migrations query.
|
|
95
|
+
"""
|
|
96
|
+
return sql.select("*").from_(self.version_table).order_by("execution_sequence")
|
|
97
|
+
|
|
98
|
+
def _get_next_execution_sequence_sql(self) -> Select:
|
|
99
|
+
"""Get SQL builder for retrieving next execution sequence.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
SQL builder object for sequence query.
|
|
103
|
+
"""
|
|
104
|
+
return sql.select("COALESCE(MAX(execution_sequence), 0) + 1 AS next_seq").from_(self.version_table)
|
|
105
|
+
|
|
106
|
+
def _get_record_migration_sql(
|
|
107
|
+
self,
|
|
108
|
+
version: str,
|
|
109
|
+
version_type: str,
|
|
110
|
+
execution_sequence: int,
|
|
111
|
+
description: str,
|
|
112
|
+
execution_time_ms: int,
|
|
113
|
+
checksum: str,
|
|
114
|
+
applied_by: str,
|
|
115
|
+
) -> Insert:
|
|
116
|
+
"""Get SQL builder for recording a migration.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
version: Version number of the migration.
|
|
120
|
+
version_type: Version format type ('sequential' or 'timestamp').
|
|
121
|
+
execution_sequence: Auto-incrementing application order.
|
|
122
|
+
description: Description of the migration.
|
|
123
|
+
execution_time_ms: Execution time in milliseconds.
|
|
124
|
+
checksum: MD5 checksum of the migration content.
|
|
125
|
+
applied_by: User who applied the migration.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
SQL builder object for insert.
|
|
129
|
+
"""
|
|
130
|
+
return (
|
|
131
|
+
sql
|
|
132
|
+
.insert(self.version_table)
|
|
133
|
+
.columns(
|
|
134
|
+
"version_num",
|
|
135
|
+
"version_type",
|
|
136
|
+
"execution_sequence",
|
|
137
|
+
"description",
|
|
138
|
+
"execution_time_ms",
|
|
139
|
+
"checksum",
|
|
140
|
+
"applied_by",
|
|
141
|
+
)
|
|
142
|
+
.values(version, version_type, execution_sequence, description, execution_time_ms, checksum, applied_by)
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def _get_remove_migration_sql(self, version: str) -> Delete:
|
|
146
|
+
"""Get SQL builder for removing a migration record.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
version: Version number to remove.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
SQL builder object for delete.
|
|
153
|
+
"""
|
|
154
|
+
return sql.delete().from_(self.version_table).where(sql.version_num == version)
|
|
155
|
+
|
|
156
|
+
def _get_update_version_sql(self, old_version: str, new_version: str, new_version_type: str) -> Update:
|
|
157
|
+
"""Get SQL builder for updating version record.
|
|
158
|
+
|
|
159
|
+
Updates version_num and version_type while preserving execution_sequence,
|
|
160
|
+
applied_at, and other metadata. Used during fix command to convert
|
|
161
|
+
timestamp versions to sequential format.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
old_version: Current version string.
|
|
165
|
+
new_version: New version string.
|
|
166
|
+
new_version_type: New version type ('sequential' or 'timestamp').
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
SQL builder object for update.
|
|
170
|
+
"""
|
|
171
|
+
return (
|
|
172
|
+
sql
|
|
173
|
+
.update(self.version_table)
|
|
174
|
+
.set("version_num", new_version)
|
|
175
|
+
.set("version_type", new_version_type)
|
|
176
|
+
.where(sql.version_num == old_version)
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
def _get_check_column_exists_sql(self) -> Select:
|
|
180
|
+
"""Get SQL to check what columns exist in the tracking table.
|
|
181
|
+
|
|
182
|
+
Returns a query that will fail gracefully if the table doesn't exist,
|
|
183
|
+
and returns column names if it does.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
SQL builder object for column check query.
|
|
187
|
+
"""
|
|
188
|
+
return sql.select("*").from_(self.version_table).limit(0)
|
|
189
|
+
|
|
190
|
+
def _get_add_missing_columns_sql(self, missing_columns: "set[str]") -> "list[str]":
|
|
191
|
+
"""Generate ALTER TABLE statements to add missing columns.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
missing_columns: Set of column names that need to be added.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
List of SQL statements to execute.
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
statements = []
|
|
201
|
+
target_create = self._get_create_table_sql()
|
|
202
|
+
|
|
203
|
+
column_definitions = {col.name.lower(): col for col in target_create.columns}
|
|
204
|
+
|
|
205
|
+
for col_name in sorted(missing_columns):
|
|
206
|
+
if col_name in column_definitions:
|
|
207
|
+
col_def = column_definitions[col_name]
|
|
208
|
+
alter = sql.alter_table(self.version_table).add_column(
|
|
209
|
+
name=col_def.name,
|
|
210
|
+
dtype=col_def.dtype,
|
|
211
|
+
default=col_def.default,
|
|
212
|
+
not_null=col_def.not_null,
|
|
213
|
+
unique=col_def.unique,
|
|
214
|
+
comment=col_def.comment,
|
|
215
|
+
)
|
|
216
|
+
statements.append(str(alter))
|
|
217
|
+
|
|
218
|
+
return statements
|
|
219
|
+
|
|
220
|
+
def _detect_missing_columns(self, existing_columns: "set[str]") -> "set[str]":
|
|
221
|
+
"""Detect which columns are missing from the current schema.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
existing_columns: Set of existing column names (may be uppercase/lowercase).
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
Set of missing column names (lowercase).
|
|
228
|
+
"""
|
|
229
|
+
target_create = self._get_create_table_sql()
|
|
230
|
+
target_columns = {col.name.lower() for col in target_create.columns}
|
|
231
|
+
existing_lower = {col.lower() for col in existing_columns}
|
|
232
|
+
return target_columns - existing_lower
|
|
233
|
+
|
|
234
|
+
@abstractmethod
|
|
235
|
+
def ensure_tracking_table(self, driver: DriverT) -> Any:
|
|
236
|
+
"""Create the migration tracking table if it doesn't exist.
|
|
237
|
+
|
|
238
|
+
Implementations should also check for and add any missing columns
|
|
239
|
+
to support schema migrations from older versions.
|
|
240
|
+
"""
|
|
241
|
+
...
|
|
242
|
+
|
|
243
|
+
@abstractmethod
|
|
244
|
+
def get_current_version(self, driver: DriverT) -> Any:
|
|
245
|
+
"""Get the latest applied migration version."""
|
|
246
|
+
...
|
|
247
|
+
|
|
248
|
+
@abstractmethod
|
|
249
|
+
def get_applied_migrations(self, driver: DriverT) -> Any:
|
|
250
|
+
"""Get all applied migrations in order."""
|
|
251
|
+
...
|
|
252
|
+
|
|
253
|
+
@abstractmethod
|
|
254
|
+
def record_migration(
|
|
255
|
+
self, driver: DriverT, version: str, description: str, execution_time_ms: int, checksum: str
|
|
256
|
+
) -> Any:
|
|
257
|
+
"""Record a successfully applied migration."""
|
|
258
|
+
...
|
|
259
|
+
|
|
260
|
+
@abstractmethod
|
|
261
|
+
def remove_migration(self, driver: DriverT, version: str) -> Any:
|
|
262
|
+
"""Remove a migration record."""
|
|
263
|
+
...
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class BaseMigrationRunner(ABC, Generic[DriverT]):
|
|
267
|
+
"""Base class for migration execution."""
|
|
268
|
+
|
|
269
|
+
extension_configs: "dict[str, dict[str, Any]]"
|
|
270
|
+
|
|
271
|
+
def __init__(
|
|
272
|
+
self,
|
|
273
|
+
migrations_path: Path,
|
|
274
|
+
extension_migrations: "dict[str, Path] | None" = None,
|
|
275
|
+
context: "Any | None" = None,
|
|
276
|
+
extension_configs: "dict[str, dict[str, Any]] | None" = None,
|
|
277
|
+
description_hints: "TemplateDescriptionHints | None" = None,
|
|
278
|
+
) -> None:
|
|
279
|
+
"""Initialize the migration runner.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
migrations_path: Path to the directory containing migration files.
|
|
283
|
+
extension_migrations: Optional mapping of extension names to their migration paths.
|
|
284
|
+
context: Optional migration context for Python migrations.
|
|
285
|
+
extension_configs: Optional mapping of extension names to their configurations.
|
|
286
|
+
description_hints: Preferred metadata keys for extracting human descriptions
|
|
287
|
+
from SQL comments and Python docstrings.
|
|
288
|
+
"""
|
|
289
|
+
self.migrations_path = migrations_path
|
|
290
|
+
self.extension_migrations = extension_migrations or {}
|
|
291
|
+
self.loader = SQLFileLoader()
|
|
292
|
+
self.project_root: Path | None = None
|
|
293
|
+
self.context = context
|
|
294
|
+
self.extension_configs = extension_configs or {}
|
|
295
|
+
self.description_hints = description_hints or TemplateDescriptionHints()
|
|
296
|
+
|
|
297
|
+
def _extract_version(self, filename: str) -> str | None:
|
|
298
|
+
"""Extract version from filename.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
filename: The migration filename.
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
The extracted version string or None.
|
|
305
|
+
"""
|
|
306
|
+
stem = Path(filename).stem
|
|
307
|
+
|
|
308
|
+
if stem.startswith("ext_"):
|
|
309
|
+
return stem
|
|
310
|
+
|
|
311
|
+
parts = stem.split("_", 1)
|
|
312
|
+
return parts[0].zfill(4) if parts and parts[0].isdigit() else None
|
|
313
|
+
|
|
314
|
+
def _calculate_checksum(self, content: str) -> str:
|
|
315
|
+
"""Calculate MD5 checksum of migration content.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
content: The migration file content.
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
MD5 checksum hex string.
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
return hashlib.md5(content.encode()).hexdigest() # noqa: S324
|
|
325
|
+
|
|
326
|
+
def _get_migration_files_sync(self) -> "list[tuple[str, Path]]":
|
|
327
|
+
"""Get all migration files sorted by version.
|
|
328
|
+
|
|
329
|
+
Uses version-aware sorting that handles both sequential and timestamp
|
|
330
|
+
formats correctly, with extension migrations sorted by extension name.
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
List of tuples containing (version, file_path).
|
|
334
|
+
"""
|
|
335
|
+
migrations = []
|
|
336
|
+
|
|
337
|
+
# Scan primary migration path
|
|
338
|
+
if self.migrations_path.exists():
|
|
339
|
+
for pattern in ("*.sql", "*.py"):
|
|
340
|
+
for file_path in self.migrations_path.glob(pattern):
|
|
341
|
+
if file_path.name.startswith("."):
|
|
342
|
+
continue
|
|
343
|
+
version = self._extract_version(file_path.name)
|
|
344
|
+
if version:
|
|
345
|
+
migrations.append((version, file_path))
|
|
346
|
+
|
|
347
|
+
# Scan extension migration paths
|
|
348
|
+
for ext_name, ext_path in self.extension_migrations.items():
|
|
349
|
+
if ext_path.exists():
|
|
350
|
+
for pattern in ("*.sql", "*.py"):
|
|
351
|
+
for file_path in ext_path.glob(pattern):
|
|
352
|
+
if file_path.name.startswith("."):
|
|
353
|
+
continue
|
|
354
|
+
# Prefix extension migrations to avoid version conflicts
|
|
355
|
+
version = self._extract_version(file_path.name)
|
|
356
|
+
if version:
|
|
357
|
+
# Use ext_ prefix to distinguish extension migrations
|
|
358
|
+
prefixed_version = f"ext_{ext_name}_{version}"
|
|
359
|
+
migrations.append((prefixed_version, file_path))
|
|
360
|
+
|
|
361
|
+
return sorted(migrations, key=_migration_sort_key)
|
|
362
|
+
|
|
363
|
+
def _load_migration_metadata(self, file_path: Path, version: "str | None" = None) -> "dict[str, Any]":
|
|
364
|
+
"""Load migration metadata from file.
|
|
365
|
+
|
|
366
|
+
Args:
|
|
367
|
+
file_path: Path to the migration file.
|
|
368
|
+
version: Optional pre-extracted version (preserves prefixes like ext_adk_0001).
|
|
369
|
+
|
|
370
|
+
Returns:
|
|
371
|
+
Migration metadata dictionary.
|
|
372
|
+
"""
|
|
373
|
+
if version is None:
|
|
374
|
+
version = self._extract_version(file_path.name)
|
|
375
|
+
|
|
376
|
+
context_to_use = self.context
|
|
377
|
+
|
|
378
|
+
for ext_name, ext_path in self.extension_migrations.items():
|
|
379
|
+
if file_path.parent == ext_path:
|
|
380
|
+
if ext_name in self.extension_configs and self.context:
|
|
381
|
+
context_to_use = MigrationContext(
|
|
382
|
+
dialect=self.context.dialect,
|
|
383
|
+
config=self.context.config,
|
|
384
|
+
driver=self.context.driver,
|
|
385
|
+
metadata=self.context.metadata.copy() if self.context.metadata else {},
|
|
386
|
+
extension_config=self.extension_configs[ext_name],
|
|
387
|
+
)
|
|
388
|
+
break
|
|
389
|
+
|
|
390
|
+
loader = get_migration_loader(file_path, self.migrations_path, self.project_root, context_to_use)
|
|
391
|
+
loader.validate_migration_file(file_path)
|
|
392
|
+
content = file_path.read_text(encoding="utf-8")
|
|
393
|
+
checksum = self._calculate_checksum(content)
|
|
394
|
+
description = self._extract_description(content, file_path)
|
|
395
|
+
if not description:
|
|
396
|
+
description = file_path.stem.split("_", 1)[1] if "_" in file_path.stem else ""
|
|
397
|
+
|
|
398
|
+
has_upgrade, has_downgrade = True, False
|
|
399
|
+
|
|
400
|
+
if file_path.suffix == ".sql":
|
|
401
|
+
up_query, down_query = f"migrate-{version}-up", f"migrate-{version}-down"
|
|
402
|
+
self.loader.clear_cache()
|
|
403
|
+
self.loader.load_sql(file_path)
|
|
404
|
+
has_upgrade, has_downgrade = self.loader.has_query(up_query), self.loader.has_query(down_query)
|
|
405
|
+
else:
|
|
406
|
+
try:
|
|
407
|
+
has_downgrade = bool(await_(loader.get_down_sql, raise_sync_error=False)(file_path))
|
|
408
|
+
except Exception:
|
|
409
|
+
has_downgrade = False
|
|
410
|
+
|
|
411
|
+
return {
|
|
412
|
+
"version": version,
|
|
413
|
+
"description": description,
|
|
414
|
+
"file_path": file_path,
|
|
415
|
+
"checksum": checksum,
|
|
416
|
+
"has_upgrade": has_upgrade,
|
|
417
|
+
"has_downgrade": has_downgrade,
|
|
418
|
+
"loader": loader,
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
def _extract_description(self, content: str, file_path: Path) -> str:
|
|
422
|
+
if file_path.suffix == ".sql":
|
|
423
|
+
return self._extract_sql_description(content)
|
|
424
|
+
if file_path.suffix == ".py":
|
|
425
|
+
return self._extract_python_description(content)
|
|
426
|
+
return ""
|
|
427
|
+
|
|
428
|
+
def _extract_sql_description(self, content: str) -> str:
|
|
429
|
+
keys = self.description_hints.sql_keys
|
|
430
|
+
for line in content.splitlines():
|
|
431
|
+
stripped = line.strip()
|
|
432
|
+
if not stripped:
|
|
433
|
+
continue
|
|
434
|
+
if stripped.startswith("--"):
|
|
435
|
+
body = stripped.lstrip("-").strip()
|
|
436
|
+
if not body:
|
|
437
|
+
continue
|
|
438
|
+
if ":" in body:
|
|
439
|
+
key, value = body.split(":", 1)
|
|
440
|
+
if key.strip() in keys:
|
|
441
|
+
return value.strip()
|
|
442
|
+
continue
|
|
443
|
+
break
|
|
444
|
+
return ""
|
|
445
|
+
|
|
446
|
+
def _extract_python_description(self, content: str) -> str:
|
|
447
|
+
try:
|
|
448
|
+
module = ast.parse(content)
|
|
449
|
+
except SyntaxError:
|
|
450
|
+
return ""
|
|
451
|
+
docstring = ast.get_docstring(module) or ""
|
|
452
|
+
keys = self.description_hints.python_keys
|
|
453
|
+
for line in docstring.splitlines():
|
|
454
|
+
stripped = line.strip()
|
|
455
|
+
if not stripped:
|
|
456
|
+
continue
|
|
457
|
+
if ":" in stripped:
|
|
458
|
+
key, value = stripped.split(":", 1)
|
|
459
|
+
if key.strip() in keys:
|
|
460
|
+
return value.strip()
|
|
461
|
+
return stripped
|
|
462
|
+
return ""
|
|
463
|
+
|
|
464
|
+
def _get_migration_sql(self, migration: "dict[str, Any]", direction: str) -> "list[str] | None":
|
|
465
|
+
"""Get migration SQL for given direction.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
migration: Migration metadata.
|
|
469
|
+
direction: Either 'up' or 'down'.
|
|
470
|
+
|
|
471
|
+
Returns:
|
|
472
|
+
SQL object for the migration.
|
|
473
|
+
"""
|
|
474
|
+
if not migration.get(f"has_{direction}grade"):
|
|
475
|
+
if direction == "down":
|
|
476
|
+
logger.warning("Migration %s has no downgrade query", migration["version"])
|
|
477
|
+
return None
|
|
478
|
+
msg = f"Migration {migration['version']} has no upgrade query"
|
|
479
|
+
raise ValueError(msg)
|
|
480
|
+
|
|
481
|
+
file_path, loader = migration["file_path"], migration["loader"]
|
|
482
|
+
|
|
483
|
+
try:
|
|
484
|
+
method = loader.get_up_sql if direction == "up" else loader.get_down_sql
|
|
485
|
+
sql_statements = await_(method, raise_sync_error=False)(file_path)
|
|
486
|
+
|
|
487
|
+
except Exception as e:
|
|
488
|
+
if direction == "down":
|
|
489
|
+
logger.warning("Failed to load downgrade for migration %s: %s", migration["version"], e)
|
|
490
|
+
return None
|
|
491
|
+
msg = f"Failed to load upgrade for migration {migration['version']}: {e}"
|
|
492
|
+
raise ValueError(msg) from e
|
|
493
|
+
else:
|
|
494
|
+
if sql_statements:
|
|
495
|
+
return cast("list[str]", sql_statements)
|
|
496
|
+
return None
|
|
497
|
+
|
|
498
|
+
@abstractmethod
|
|
499
|
+
def get_migration_files(self) -> Any:
|
|
500
|
+
"""Get all migration files sorted by version."""
|
|
501
|
+
...
|
|
502
|
+
|
|
503
|
+
@abstractmethod
|
|
504
|
+
def load_migration(self, file_path: Path) -> Any:
|
|
505
|
+
"""Load a migration file and extract its components."""
|
|
506
|
+
...
|
|
507
|
+
|
|
508
|
+
@abstractmethod
|
|
509
|
+
def execute_upgrade(self, driver: DriverT, migration: "dict[str, Any]") -> Any:
|
|
510
|
+
"""Execute an upgrade migration."""
|
|
511
|
+
...
|
|
512
|
+
|
|
513
|
+
@abstractmethod
|
|
514
|
+
def execute_downgrade(self, driver: DriverT, migration: "dict[str, Any]") -> Any:
|
|
515
|
+
"""Execute a downgrade migration."""
|
|
516
|
+
...
|
|
517
|
+
|
|
518
|
+
@abstractmethod
|
|
519
|
+
def load_all_migrations(self) -> Any:
|
|
520
|
+
"""Load all migrations into a single namespace for bulk operations."""
|
|
521
|
+
...
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
def _migration_sort_key(item: "tuple[str, Path]") -> Any:
|
|
525
|
+
return parse_version(item[0])
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
class BaseMigrationCommands(ABC, Generic[ConfigT, DriverT]):
|
|
529
|
+
"""Base class for migration commands."""
|
|
530
|
+
|
|
531
|
+
extension_configs: "dict[str, dict[str, Any]]"
|
|
532
|
+
|
|
533
|
+
def __init__(self, config: ConfigT) -> None:
|
|
534
|
+
"""Initialize migration commands.
|
|
535
|
+
|
|
536
|
+
Args:
|
|
537
|
+
config: The SQLSpec configuration.
|
|
538
|
+
"""
|
|
539
|
+
self.config = config
|
|
540
|
+
migration_config = cast("dict[str, Any]", self.config.migration_config) or {}
|
|
541
|
+
|
|
542
|
+
self.version_table = migration_config.get("version_table_name", "ddl_migrations")
|
|
543
|
+
self.migrations_path = Path(migration_config.get("script_location", "migrations"))
|
|
544
|
+
self.project_root = Path(migration_config["project_root"]) if "project_root" in migration_config else None
|
|
545
|
+
self.include_extensions = migration_config.get("include_extensions", [])
|
|
546
|
+
self.extension_configs = self._parse_extension_configs()
|
|
547
|
+
self._template_settings: MigrationTemplateSettings = build_template_settings(migration_config)
|
|
548
|
+
self._runtime: ObservabilityRuntime | None = self.config.get_observability_runtime()
|
|
549
|
+
self._last_command_error: Exception | None = None
|
|
550
|
+
self._last_command_metrics: dict[str, float] | None = None
|
|
551
|
+
|
|
552
|
+
def _parse_extension_configs(self) -> "dict[str, dict[str, Any]]":
|
|
553
|
+
"""Parse extension configurations from include_extensions.
|
|
554
|
+
|
|
555
|
+
Reads extension configuration from config.extension_config for each
|
|
556
|
+
extension listed in include_extensions.
|
|
557
|
+
|
|
558
|
+
Returns:
|
|
559
|
+
Dictionary mapping extension names to their configurations.
|
|
560
|
+
"""
|
|
561
|
+
configs = {}
|
|
562
|
+
|
|
563
|
+
for ext_config in self.include_extensions:
|
|
564
|
+
if not isinstance(ext_config, str):
|
|
565
|
+
logger.warning("Extension must be a string name, got: %s", ext_config)
|
|
566
|
+
continue
|
|
567
|
+
|
|
568
|
+
ext_name = ext_config
|
|
569
|
+
ext_options = cast("dict[str, Any]", self.config.extension_config).get(ext_name, {})
|
|
570
|
+
configs[ext_name] = ext_options
|
|
571
|
+
|
|
572
|
+
return configs
|
|
573
|
+
|
|
574
|
+
def _discover_extension_migrations(self) -> "dict[str, Path]":
|
|
575
|
+
"""Discover migration paths for configured extensions.
|
|
576
|
+
|
|
577
|
+
Returns:
|
|
578
|
+
Dictionary mapping extension names to their migration paths.
|
|
579
|
+
"""
|
|
580
|
+
|
|
581
|
+
extension_migrations = {}
|
|
582
|
+
|
|
583
|
+
for ext_name in self.extension_configs:
|
|
584
|
+
module_name = "sqlspec.extensions.litestar" if ext_name == "litestar" else f"sqlspec.extensions.{ext_name}"
|
|
585
|
+
|
|
586
|
+
try:
|
|
587
|
+
module_path = module_to_os_path(module_name)
|
|
588
|
+
migrations_dir = module_path / "migrations"
|
|
589
|
+
|
|
590
|
+
if migrations_dir.exists():
|
|
591
|
+
extension_migrations[ext_name] = migrations_dir
|
|
592
|
+
logger.debug("Found migrations for extension %s at %s", ext_name, migrations_dir)
|
|
593
|
+
else:
|
|
594
|
+
logger.warning("No migrations directory found for extension %s", ext_name)
|
|
595
|
+
except TypeError:
|
|
596
|
+
logger.warning("Extension %s not found", ext_name)
|
|
597
|
+
|
|
598
|
+
return extension_migrations
|
|
599
|
+
|
|
600
|
+
def _get_init_readme_content(self) -> str:
|
|
601
|
+
"""Get README content for migration directory initialization.
|
|
602
|
+
|
|
603
|
+
Returns:
|
|
604
|
+
README markdown content.
|
|
605
|
+
"""
|
|
606
|
+
return """# SQLSpec Migrations
|
|
607
|
+
|
|
608
|
+
This directory contains database migration files.
|
|
609
|
+
|
|
610
|
+
## File Format
|
|
611
|
+
|
|
612
|
+
Migration files use SQLFileLoader's named query syntax with versioned names:
|
|
613
|
+
|
|
614
|
+
```sql
|
|
615
|
+
-- name: migrate-20251011120000-up
|
|
616
|
+
CREATE TABLE example (
|
|
617
|
+
id INTEGER PRIMARY KEY,
|
|
618
|
+
name TEXT NOT NULL
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
-- name: migrate-20251011120000-down
|
|
622
|
+
DROP TABLE example;
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
## Naming Conventions
|
|
626
|
+
|
|
627
|
+
### File Names
|
|
628
|
+
|
|
629
|
+
Format: `{version}_{description}.sql`
|
|
630
|
+
|
|
631
|
+
- Version: Timestamp in YYYYMMDDHHmmss format (UTC)
|
|
632
|
+
- Description: Brief description using underscores
|
|
633
|
+
- Example: `20251011120000_create_users_table.sql`
|
|
634
|
+
|
|
635
|
+
### Query Names
|
|
636
|
+
|
|
637
|
+
- Upgrade: `migrate-{version}-up`
|
|
638
|
+
- Downgrade: `migrate-{version}-down`
|
|
639
|
+
|
|
640
|
+
## Version Format
|
|
641
|
+
|
|
642
|
+
Migrations use **timestamp-based versioning** (YYYYMMDDHHmmss):
|
|
643
|
+
|
|
644
|
+
- **Format**: 14-digit UTC timestamp
|
|
645
|
+
- **Example**: `20251011120000` (October 11, 2025 at 12:00:00 UTC)
|
|
646
|
+
- **Benefits**: Eliminates merge conflicts when multiple developers create migrations concurrently
|
|
647
|
+
|
|
648
|
+
### Creating Migrations
|
|
649
|
+
|
|
650
|
+
Use the CLI to generate timestamped migrations:
|
|
651
|
+
|
|
652
|
+
```bash
|
|
653
|
+
sqlspec create-migration "add user table"
|
|
654
|
+
# Creates: 20251011120000_add_user_table.sql
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
The timestamp is automatically generated in UTC timezone.
|
|
658
|
+
|
|
659
|
+
## Migration Execution
|
|
660
|
+
|
|
661
|
+
Migrations are applied in chronological order based on their timestamps.
|
|
662
|
+
The database tracks both version and execution order separately to handle
|
|
663
|
+
out-of-order migrations gracefully (e.g., from late-merging branches).
|
|
664
|
+
"""
|
|
665
|
+
|
|
666
|
+
def _get_init_init_content(self) -> str:
|
|
667
|
+
"""Get __init__.py content for migration directory initialization.
|
|
668
|
+
|
|
669
|
+
Returns:
|
|
670
|
+
Python module docstring content for the __init__.py file.
|
|
671
|
+
"""
|
|
672
|
+
return """Migrations.
|
|
673
|
+
"""
|
|
674
|
+
|
|
675
|
+
def init_directory(self, directory: str, package: bool = True) -> None:
|
|
676
|
+
"""Initialize migration directory structure.
|
|
677
|
+
|
|
678
|
+
Args:
|
|
679
|
+
directory: Directory to initialize migrations in.
|
|
680
|
+
package: Whether to create __init__.py file.
|
|
681
|
+
"""
|
|
682
|
+
console = Console()
|
|
683
|
+
|
|
684
|
+
migrations_dir = Path(directory)
|
|
685
|
+
migrations_dir.mkdir(parents=True, exist_ok=True)
|
|
686
|
+
|
|
687
|
+
if package:
|
|
688
|
+
init = migrations_dir / "__init__.py"
|
|
689
|
+
init.write_text(self._get_init_init_content())
|
|
690
|
+
|
|
691
|
+
readme = migrations_dir / "README.md"
|
|
692
|
+
readme.write_text(self._get_init_readme_content())
|
|
693
|
+
|
|
694
|
+
console.print(f"[green]Initialized migrations in {directory}[/]")
|
|
695
|
+
|
|
696
|
+
def _record_command_metric(self, name: str, value: float) -> None:
|
|
697
|
+
"""Accumulate per-command metrics for decorator flushing."""
|
|
698
|
+
|
|
699
|
+
if self._last_command_metrics is None:
|
|
700
|
+
self._last_command_metrics = {}
|
|
701
|
+
self._last_command_metrics[name] = self._last_command_metrics.get(name, 0.0) + value
|
|
702
|
+
|
|
703
|
+
@abstractmethod
|
|
704
|
+
def init(self, directory: str, package: bool = True) -> Any:
|
|
705
|
+
"""Initialize migration directory structure."""
|
|
706
|
+
...
|
|
707
|
+
|
|
708
|
+
@abstractmethod
|
|
709
|
+
def current(self, verbose: bool = False) -> Any:
|
|
710
|
+
"""Show current migration version."""
|
|
711
|
+
...
|
|
712
|
+
|
|
713
|
+
@abstractmethod
|
|
714
|
+
def upgrade(self, revision: str = "head") -> Any:
|
|
715
|
+
"""Upgrade to a target revision."""
|
|
716
|
+
...
|
|
717
|
+
|
|
718
|
+
@abstractmethod
|
|
719
|
+
def downgrade(self, revision: str = "-1") -> Any:
|
|
720
|
+
"""Downgrade to a target revision."""
|
|
721
|
+
...
|
|
722
|
+
|
|
723
|
+
@abstractmethod
|
|
724
|
+
def stamp(self, revision: str) -> Any:
|
|
725
|
+
"""Mark database as being at a specific revision without running migrations."""
|
|
726
|
+
...
|
|
727
|
+
|
|
728
|
+
@abstractmethod
|
|
729
|
+
def revision(self, message: str, file_type: str = "sql") -> Any:
|
|
730
|
+
"""Create a new migration file."""
|
|
731
|
+
...
|