mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-01 04:47:03 +08:00
fix(database): migrate versioned schemas before create_all
This commit is contained in:
@@ -90,7 +90,7 @@ def _validate_migration_lineage(
|
||||
|
||||
|
||||
def prepare_database(*, before_alembic: Callable[[], None] | None = None) -> None:
|
||||
"""在建表或迁移前完成版本校验及可选备份。"""
|
||||
"""在建表或迁移前完成版本校验、可选备份与安全的结构升级。"""
|
||||
engine = get_engine()
|
||||
alembic_cfg = _build_alembic_config(engine)
|
||||
has_existing_database, current_heads, target_heads = _migration_state(
|
||||
@@ -101,6 +101,7 @@ def prepare_database(*, before_alembic: Callable[[], None] | None = None) -> Non
|
||||
has_existing_database
|
||||
and set(current_heads) != set(target_heads)
|
||||
)
|
||||
migrate_before_create = requires_migration and bool(current_heads)
|
||||
if (
|
||||
requires_migration
|
||||
and get_runtime_setting('DB_BACKUP_ENABLE')
|
||||
@@ -114,11 +115,17 @@ def prepare_database(*, before_alembic: Callable[[], None] | None = None) -> Non
|
||||
)
|
||||
build_database_governance().create_backup()
|
||||
|
||||
if migrate_before_create:
|
||||
# 已标记的旧结构必须先沿 Alembic 链升级;当前元数据可能包含依赖新列的外键,
|
||||
# 提前 create_all 会在 PostgreSQL 上因父表仍是旧结构而失败。
|
||||
update_db(alembic_cfg)
|
||||
|
||||
init_db()
|
||||
if before_alembic:
|
||||
# 首次初始化需要先建立用户表,再把管理员密码交给 Alembic 基础迁移消费。
|
||||
before_alembic()
|
||||
update_db(alembic_cfg)
|
||||
if not migrate_before_create:
|
||||
update_db(alembic_cfg)
|
||||
|
||||
|
||||
def verify_database_revision() -> None:
|
||||
|
||||
@@ -101,15 +101,40 @@ def test_prepare_database_creates_backup_before_schema_changes(monkeypatch) -> N
|
||||
|
||||
assert calls == [
|
||||
"backup",
|
||||
"alembic",
|
||||
"create_all",
|
||||
"before_alembic",
|
||||
"alembic",
|
||||
]
|
||||
assert logged_messages == [
|
||||
"数据库需要从版本 old 升级到 head,正在创建迁移前备份"
|
||||
]
|
||||
|
||||
|
||||
def test_prepare_database_keeps_create_all_first_for_unversioned_database(
|
||||
monkeypatch,
|
||||
) -> None:
|
||||
"""未标记旧库仍需先补齐基础表,再从 Alembic base 执行数据迁移。"""
|
||||
calls: list[str] = []
|
||||
monkeypatch.setattr(db_init, "get_engine", lambda: object())
|
||||
monkeypatch.setattr(db_init, "_build_alembic_config", lambda _engine: object())
|
||||
monkeypatch.setattr(
|
||||
db_init,
|
||||
"_migration_state",
|
||||
lambda *_: (True, (), ("head",)),
|
||||
)
|
||||
monkeypatch.setattr(db_init.settings, "DB_BACKUP_ENABLE", False)
|
||||
monkeypatch.setattr(db_init, "init_db", lambda: calls.append("create_all"))
|
||||
monkeypatch.setattr(
|
||||
db_init,
|
||||
"update_db",
|
||||
lambda _config: calls.append("alembic"),
|
||||
)
|
||||
|
||||
db_init.prepare_database(before_alembic=lambda: calls.append("before_alembic"))
|
||||
|
||||
assert calls == ["create_all", "before_alembic", "alembic"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("has_existing_database", "current_heads", "backup_enabled", "upgrade_enabled"),
|
||||
(
|
||||
|
||||
Reference in New Issue
Block a user