"""老库补列:create_all 只会建新表,不会给已存在的表加字段。 模型新增可空字段后(如定制项目的验收时间 / 开票 / 回款),启动时自动 `ALTER TABLE ... ADD COLUMN` 补齐,不需要手写迁移脚本。 用法:在 `Base.metadata.create_all()` 之后调用 `ensure_columns(engine, Base.metadata)`。 """ from __future__ import annotations from sqlalchemy import inspect, text from sqlalchemy.engine import Engine from sqlalchemy.sql.schema import MetaData def ensure_columns(engine: Engine, metadata: MetaData) -> list[str]: """给已存在的表补上模型里新增的可空字段,返回补过的列名(表.列)。""" insp = inspect(engine) added: list[str] = [] for table in metadata.tables.values(): if not insp.has_table(table.name): continue # 表还不存在 → create_all 会按最新模型建,这里不用管 existing = {c["name"] for c in insp.get_columns(table.name)} for col in table.columns: if col.name in existing: continue if not col.nullable: print(f"[warn] 跳过高字段 {table.name}.{col.name}:新增列需允许为空") continue ddl = col.type.compile(engine.dialect) with engine.begin() as conn: conn.execute(text(f"ALTER TABLE {table.name} ADD COLUMN {col.name} {ddl} NULL")) added.append(f"{table.name}.{col.name}") return added