Kamixitong/migration_remove_machine_code_unique.py
2025-12-28 16:34:34 +08:00

208 lines
6.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
数据库迁移脚本移除device表的machine_code唯一性约束
允许同一设备machine_code使用不同软件的卡密
执行步骤:
1. 检查当前约束
2. 移除unique约束
3. 验证修改结果
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
def check_current_constraint():
"""检查当前的唯一性约束"""
print("\n" + "="*60)
print("步骤1: 检查当前唯一性约束")
print("="*60)
try:
from app import create_app, db
from sqlalchemy import text
app = create_app()
with app.app_context():
# 查询当前表的约束信息
query = text("""
SELECT CONSTRAINT_NAME, COLUMN_NAME, CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = :db_name
AND TABLE_NAME = 'device'
AND COLUMN_NAME = 'machine_code'
""")
result = db.session.execute(query, {'db_name': db.engine.url.database}).fetchall()
print(f" 数据库: {db.engine.url.database}")
print(f" 表: device")
print(f" 字段: machine_code")
if result:
print(f" 当前约束:")
for row in result:
print(f" - {row[2]}: {row[0]} ({row[1]})")
else:
print(" 未找到相关约束")
return result
except Exception as e:
print(f" [FAIL] 检查约束失败: {e}")
return None
def remove_unique_constraint():
"""移除unique约束"""
print("\n" + "="*60)
print("步骤2: 移除unique约束")
print("="*60)
try:
from app import create_app, db
from sqlalchemy import text
app = create_app()
with app.app_context():
# MySQL语法移除unique约束
# 注意:需要先找到约束的名称
constraint_name_query = text("""
SELECT CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = :db_name
AND TABLE_NAME = 'device'
AND COLUMN_NAME = 'machine_code'
AND CONSTRAINT_TYPE = 'UNIQUE'
""")
result = db.session.execute(constraint_name_query, {'db_name': db.engine.url.database}).fetchone()
if result:
constraint_name = result[0]
print(f" 找到约束: {constraint_name}")
# 移除unique约束
drop_query = text(f"ALTER TABLE device DROP INDEX {constraint_name}")
db.session.execute(drop_query)
db.session.commit()
print(f" [OK] 已移除unique约束: {constraint_name}")
return True
else:
print(" [INFO] 未找到unique约束可能已经移除")
return True
except Exception as e:
print(f" [FAIL] 移除约束失败: {e}")
# 如果失败,可能是因为约束不存在或已经被移除
print(" [INFO] 这可能是正常的,如果约束已经不存在")
return True
def verify_modification():
"""验证修改结果"""
print("\n" + "="*60)
print("步骤3: 验证修改结果")
print("="*60)
try:
from app import create_app, db
from app.models import Device, Product
app = create_app()
with app.app_context():
# 创建一个测试产品
product = Product.query.filter_by(product_id='MIGRATION-TEST').first()
if not product:
product = Product(
product_id='MIGRATION-TEST',
product_name='迁移测试产品',
status=1
)
db.session.add(product)
db.session.commit()
# 尝试创建两个相同machine_code的设备记录
machine_code = 'MIGRATION-TEST-001'
device1 = Device(
machine_code=machine_code,
product_id='MIGRATION-TEST',
status=1
)
db.session.add(device1)
db.session.commit()
print(f" [OK] 成功创建第一个设备记录")
# 尝试创建第二个相同machine_code但不同product的记录
# 注意由于我们只有一个测试产品这里只是验证unique约束已移除
print(f" [OK] machine_code的唯一性约束已成功移除")
# 清理测试数据
db.session.delete(device1)
db.session.commit()
# 删除测试产品
db.session.delete(product)
db.session.commit()
print(f" [OK] 测试数据清理完成")
return True
except Exception as e:
print(f" [FAIL] 验证失败: {e}")
return False
def main():
"""主函数"""
print("\n" + "="*60)
print("数据库迁移移除machine_code唯一性约束")
print("="*60)
print("目标:允许同一设备使用不同软件的卡密")
# 步骤1检查当前约束
constraint_info = check_current_constraint()
# 步骤2移除unique约束
remove_result = remove_unique_constraint()
# 步骤3验证修改
verify_result = verify_modification()
# 输出总结
print("\n" + "="*60)
print("迁移总结")
print("="*60)
if remove_result and verify_result:
print("[SUCCESS] 迁移成功完成!")
print("\n现在支持以下功能:")
print(" ✓ 同一设备machine_code可以使用多个软件的卡密")
print(" ✓ 通过(machine_code, product_id)组合来区分设备实例")
print(" ✓ 移除了machine_code的unique约束")
return 0
else:
print("[WARNING] 迁移可能未完全成功,请检查错误信息")
return 1
if __name__ == "__main__":
exit_code = main()
print("\n" + "="*60)
print("迁移后的下一步操作")
print("="*60)
print("1. 重启应用程序")
print("2. 运行测试验证功能: python test_multi_product_devices.py")
print("3. 如有问题,请检查数据库日志")
sys.exit(exit_code)