You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
#!/usr/bin/env python
|
|
# backend/scripts/migrate-sqlite-to-postgres.py — SQLite → Postgres 데이터 이관(행 수 일치 검증)
|
|
# 사용: SQLITE_URL=sqlite:////data/ari.db PG_URL=postgresql+psycopg://ari:pw@db/ari python -m scripts.migrate-sqlite-to-postgres
|
|
import os
|
|
import sys
|
|
|
|
from sqlmodel import Session, SQLModel, create_engine, select
|
|
|
|
# 모든 테이블 메타데이터 로드
|
|
import app.models # noqa: F401
|
|
|
|
|
|
def main() -> int:
|
|
src_url = os.environ.get("SQLITE_URL", "sqlite:////data/ari.db")
|
|
dst_url = os.environ["PG_URL"]
|
|
src = create_engine(src_url)
|
|
dst = create_engine(dst_url)
|
|
SQLModel.metadata.create_all(dst) # 대상 스키마 생성(또는 alembic upgrade head 선행)
|
|
|
|
mismatches = []
|
|
with Session(src) as s_src, Session(dst) as s_dst:
|
|
for table in SQLModel.metadata.sorted_tables:
|
|
model = _model_for(table.name)
|
|
if model is None:
|
|
continue
|
|
rows = s_src.exec(select(model)).all()
|
|
for r in rows:
|
|
s_dst.merge(model(**r.model_dump()))
|
|
s_dst.commit()
|
|
n_src = len(rows)
|
|
n_dst = len(s_dst.exec(select(model)).all())
|
|
print(f"{table.name}: src={n_src} dst={n_dst}")
|
|
if n_src != n_dst:
|
|
mismatches.append(table.name)
|
|
if mismatches:
|
|
print("행 수 불일치:", mismatches, file=sys.stderr)
|
|
return 1
|
|
print("이관 완료 — 행 수 일치")
|
|
return 0
|
|
|
|
|
|
def _model_for(tablename: str):
|
|
for cls in SQLModel.__subclasses__():
|
|
if getattr(cls, "__tablename__", None) == tablename:
|
|
return cls
|
|
return None
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|