"""把 SQLite 控制面库迁移到 Postgres 的命令行入口。 用法(Postgres 连接参数只走 CLOUD_DB_* 环境变量,本脚本 不接受、不打印任何密码或密钥): CLOUD_DB_HOST=... CLOUD_DB_PORT=5432 CLOUD_DB_NAME=... \ CLOUD_DB_USER=... CLOUD_DB_PASSWORD=... \ python3 -m cloud.migrate_sqlite_to_postgres --sqlite 输出:每张表本次插入的行数(第二次跑应全为 0,即幂等, 不重复插)。驱动缺失时明确报错,绝不静默回落到 SQLite; 目标库须事先存在(本脚本不建库,建库见 cloud/README.md)。 """ import argparse import sys from cloud.migrations import ( migrate_sqlite_to_postgres, migration_coverage, ) def main(argv=None): parser = argparse.ArgumentParser( description="Migrate a SQLite control-plane DB to Postgres.") parser.add_argument("--sqlite", required=True, help="source SQLite file path") args = parser.parse_args(argv) result = migrate_sqlite_to_postgres(args.sqlite) total = 0 for table, count in result.items(): print("%s: %d" % (table, count)) total += count print("total inserted: %d" % total) # 覆盖报告:只含表名,不含行内容与任何密钥。missing 非空 # 即清单与 schema 对齐回归;unmigrated 是目标库无此表、 # 本迁移无法迁移的表,须另行处理,不能读成“已迁完”。 coverage = migration_coverage() if coverage["missing_from_migration"]: print("WARNING missing_from_migration: %s" % ", ".join(coverage["missing_from_migration"])) print("unmigrated (no PG schema, NOT migrated): %s" % ", ".join(coverage["unmigrated_no_pg_schema"])) print("skipped by design: %s" % ", ".join(coverage["skipped_by_design"])) return 0 if __name__ == "__main__": sys.exit(main())