Files
call-center/scripts/migrate_core_db.py
T

82 lines
2.3 KiB
Python

from __future__ import annotations
from pathlib import Path
import sys
from sqlalchemy.exc import OperationalError, ProgrammingError
from sqlalchemy import text
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from services.shared.db import engine
from services.shared.schema_migrations import (
MIGRATIONS_DIR,
applied_migration_versions,
database_backend_name,
ensure_schema_migrations_table,
list_migration_files,
)
def _split_statements(sql: str) -> list[str]:
chunks = []
for part in sql.split(";"):
stmt = part.strip()
if stmt:
chunks.append(stmt)
return chunks
def _apply_file(path: Path) -> None:
# Some checked-in SQL files may contain a UTF-8 BOM; accept them for both
# local SQLite runs and Postgres migration jobs.
statements = _split_statements(path.read_text(encoding="utf-8-sig"))
with engine.begin() as conn:
for stmt in statements:
try:
conn.execute(text(stmt))
except (OperationalError, ProgrammingError) as exc:
message = str(exc).lower()
duplicate_markers = [
"duplicate column name",
"already exists",
"duplicate key value violates unique constraint",
]
if any(marker in message for marker in duplicate_markers):
continue
raise
conn.execute(
text("INSERT INTO schema_migrations(version, applied_at) VALUES (:v, CURRENT_TIMESTAMP)"),
{"v": path.name},
)
def main() -> None:
files = list_migration_files()
if not files:
raise RuntimeError(f"No migration files found for dialect in {MIGRATIONS_DIR}")
ensure_schema_migrations_table()
applied = applied_migration_versions()
applied_now = []
for file_path in files:
if file_path.name in applied:
continue
_apply_file(file_path)
applied_now.append(file_path.name)
print(f"Dialect: {database_backend_name()}")
if applied_now:
print("Applied migrations:")
for m in applied_now:
print(f"- {m}")
else:
print("No new migrations to apply")
if __name__ == "__main__":
main()