chore(docker): 增加升级数据库脚本
This commit is contained in:
@@ -218,6 +218,120 @@ def update_table_structure(init_table, niushop_columns):
|
|||||||
|
|
||||||
return new_create_sql
|
return new_create_sql
|
||||||
|
|
||||||
|
# 提取INSERT语句
|
||||||
|
def extract_insert_statements(sql_content):
|
||||||
|
"""从SQL文件中提取INSERT语句,包括完整的列名和值"""
|
||||||
|
insert_statements = {}
|
||||||
|
|
||||||
|
# 匹配所有INSERT语句,使用更可靠的方式处理
|
||||||
|
# 先分割SQL文件为多个语句
|
||||||
|
statements = sql_content.split(';')
|
||||||
|
|
||||||
|
for stmt in statements:
|
||||||
|
stmt = stmt.strip()
|
||||||
|
if not stmt:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 检查是否是INSERT语句
|
||||||
|
if stmt.upper().startswith('INSERT INTO'):
|
||||||
|
try:
|
||||||
|
# 提取表名
|
||||||
|
table_name_start = stmt.find('INSERT INTO') + len('INSERT INTO')
|
||||||
|
table_name_end = stmt.find('(')
|
||||||
|
table_name_part = stmt[table_name_start:table_name_end].strip()
|
||||||
|
# 去掉反引号
|
||||||
|
table_name = table_name_part.strip('`')
|
||||||
|
|
||||||
|
# 提取列名
|
||||||
|
columns_start = table_name_end + 1
|
||||||
|
columns_end = stmt.find(')', columns_start)
|
||||||
|
columns_str = stmt[columns_start:columns_end].strip()
|
||||||
|
|
||||||
|
# 提取VALUES部分
|
||||||
|
values_start = stmt.find('VALUES') + len('VALUES')
|
||||||
|
values_part = stmt[values_start:].strip()
|
||||||
|
|
||||||
|
# 处理VALUES部分,提取所有括号对
|
||||||
|
values = []
|
||||||
|
bracket_count = 0
|
||||||
|
current_value = ''
|
||||||
|
in_quotes = False
|
||||||
|
quote_char = ''
|
||||||
|
|
||||||
|
for char in values_part:
|
||||||
|
if char in ('"', "'") and (not current_value or current_value[-1] != '\\'):
|
||||||
|
if not in_quotes:
|
||||||
|
in_quotes = True
|
||||||
|
quote_char = char
|
||||||
|
elif char == quote_char:
|
||||||
|
in_quotes = False
|
||||||
|
|
||||||
|
if char == '(' and not in_quotes:
|
||||||
|
bracket_count += 1
|
||||||
|
current_value = '('
|
||||||
|
elif char == ')' and not in_quotes:
|
||||||
|
bracket_count -= 1
|
||||||
|
current_value += ')'
|
||||||
|
if bracket_count == 0:
|
||||||
|
# 去掉括号
|
||||||
|
value_content = current_value[1:-1].strip()
|
||||||
|
if value_content:
|
||||||
|
values.append(value_content)
|
||||||
|
current_value = ''
|
||||||
|
elif bracket_count > 0:
|
||||||
|
current_value += char
|
||||||
|
|
||||||
|
if table_name not in insert_statements:
|
||||||
|
insert_statements[table_name] = {
|
||||||
|
'columns': columns_str,
|
||||||
|
'values': []
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_statements[table_name]['values'].extend(values)
|
||||||
|
except Exception as e:
|
||||||
|
# 跳过格式不正确的INSERT语句
|
||||||
|
continue
|
||||||
|
|
||||||
|
return insert_statements
|
||||||
|
|
||||||
|
# 比较数据差异,生成数据升级语句
|
||||||
|
def generate_data_upgrade_statements(niushop_inserts, init_inserts, table_mapping):
|
||||||
|
"""生成数据升级语句"""
|
||||||
|
upgrade_statements = []
|
||||||
|
|
||||||
|
for niushop_table, niushop_insert_info in niushop_inserts.items():
|
||||||
|
# 检查init.sql中是否有对应的表
|
||||||
|
if niushop_table in table_mapping:
|
||||||
|
init_table = table_mapping[niushop_table]
|
||||||
|
|
||||||
|
# 获取niushop_database.sql中的列名和值
|
||||||
|
columns_str = niushop_insert_info.get('columns', '')
|
||||||
|
niushop_values = niushop_insert_info.get('values', [])
|
||||||
|
|
||||||
|
# 获取init.sql中对应表的数据
|
||||||
|
init_insert_info = init_inserts.get(init_table, {})
|
||||||
|
init_values = init_insert_info.get('values', [])
|
||||||
|
|
||||||
|
# 生成缺失数据的INSERT语句
|
||||||
|
for niushop_value in niushop_values:
|
||||||
|
# 过滤掉无效的VALUES(如包含列名的VALUES)
|
||||||
|
if 'store_name' in niushop_value and 'site_id' in niushop_value:
|
||||||
|
continue
|
||||||
|
# 过滤掉太短的值,可能是解析错误
|
||||||
|
if len(niushop_value) < 5:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if niushop_value not in init_values:
|
||||||
|
# 构建完整的INSERT语句,包含列名
|
||||||
|
if columns_str:
|
||||||
|
insert_stmt = f"INSERT INTO `{init_table}` ({columns_str}) VALUES ({niushop_value});"
|
||||||
|
else:
|
||||||
|
# 如果没有列名,使用简化的INSERT语句
|
||||||
|
insert_stmt = f"INSERT INTO `{init_table}` VALUES ({niushop_value});"
|
||||||
|
upgrade_statements.append(insert_stmt)
|
||||||
|
|
||||||
|
return upgrade_statements
|
||||||
|
|
||||||
# 主函数
|
# 主函数
|
||||||
def main():
|
def main():
|
||||||
# 文件路径
|
# 文件路径
|
||||||
@@ -240,9 +354,17 @@ def main():
|
|||||||
init_tables = extract_init_table_structures(init_content)
|
init_tables = extract_init_table_structures(init_content)
|
||||||
print(f"从init.sql提取到 {len(init_tables)} 个表结构")
|
print(f"从init.sql提取到 {len(init_tables)} 个表结构")
|
||||||
|
|
||||||
|
# 创建表名映射(niushop_table -> init_table)
|
||||||
|
table_mapping = {}
|
||||||
|
for init_table_name, init_table in init_tables.items():
|
||||||
|
original_table_name = init_table_name
|
||||||
|
if original_table_name.startswith('lucky_'):
|
||||||
|
original_table_name = original_table_name[6:] # 去掉lucky_前缀
|
||||||
|
table_mapping[original_table_name] = init_table_name
|
||||||
|
|
||||||
# 比较表结构差异,生成更新
|
# 比较表结构差异,生成更新
|
||||||
print("正在比较表结构差异...")
|
print("正在比较表结构差异...")
|
||||||
upgrade_statements = []
|
structure_upgrade_statements = []
|
||||||
updated_init_content = init_content
|
updated_init_content = init_content
|
||||||
|
|
||||||
# 遍历init.sql中的所有表
|
# 遍历init.sql中的所有表
|
||||||
@@ -278,21 +400,39 @@ def main():
|
|||||||
# 提取列名(带反引号)
|
# 提取列名(带反引号)
|
||||||
col_name_in_def = col['definition'].split(' ')[0]
|
col_name_in_def = col['definition'].split(' ')[0]
|
||||||
alter_stmt = f"ALTER TABLE `{init_table_name}` ADD COLUMN {col['definition']};"
|
alter_stmt = f"ALTER TABLE `{init_table_name}` ADD COLUMN {col['definition']};"
|
||||||
upgrade_statements.append(alter_stmt)
|
structure_upgrade_statements.append(alter_stmt)
|
||||||
|
|
||||||
# 更新init.sql中的表结构
|
# 更新init.sql中的表结构
|
||||||
new_create_sql = update_table_structure(init_table, niushop_cols)
|
new_create_sql = update_table_structure(init_table, niushop_cols)
|
||||||
updated_init_content = updated_init_content.replace(init_table['full_sql'], new_create_sql)
|
updated_init_content = updated_init_content.replace(init_table['full_sql'], new_create_sql)
|
||||||
|
|
||||||
|
# 提取INSERT语句,生成数据升级
|
||||||
|
print("正在提取INSERT语句...")
|
||||||
|
niushop_inserts = extract_insert_statements(niushop_content)
|
||||||
|
init_inserts = extract_insert_statements(init_content)
|
||||||
|
|
||||||
|
print("正在生成数据升级语句...")
|
||||||
|
data_upgrade_statements = generate_data_upgrade_statements(niushop_inserts, init_inserts, table_mapping)
|
||||||
|
|
||||||
# 写入升级脚本
|
# 写入升级脚本
|
||||||
print("正在写入升级脚本...")
|
print("正在写入升级脚本...")
|
||||||
with open(upgrade_file, 'w', encoding='utf-8') as f:
|
with open(upgrade_file, 'w', encoding='utf-8') as f:
|
||||||
f.write("-- 数据库升级脚本\n")
|
f.write("-- 数据库升级脚本\n")
|
||||||
f.write("-- 生成时间: 自动生成\n")
|
f.write("-- 生成时间: 自动生成\n")
|
||||||
f.write("-- 描述: 根据niushop_database.sql更新init.sql的表结构\n\n")
|
f.write("-- 描述: 根据niushop_database.sql更新init.sql的表结构和数据\n\n")
|
||||||
f.write("USE shop_mallnew;\n\n")
|
f.write("USE shop_mallnew;\n\n")
|
||||||
|
|
||||||
for stmt in upgrade_statements:
|
# 写入表结构升级语句
|
||||||
|
if structure_upgrade_statements:
|
||||||
|
f.write("-- 表结构升级语句\n")
|
||||||
|
for stmt in structure_upgrade_statements:
|
||||||
|
f.write(f"{stmt}\n")
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
|
# 写入数据升级语句
|
||||||
|
if data_upgrade_statements:
|
||||||
|
f.write("-- 数据升级语句\n")
|
||||||
|
for stmt in data_upgrade_statements:
|
||||||
f.write(f"{stmt}\n")
|
f.write(f"{stmt}\n")
|
||||||
|
|
||||||
# 更新init.sql文件
|
# 更新init.sql文件
|
||||||
@@ -300,7 +440,9 @@ def main():
|
|||||||
with open(init_file, 'w', encoding='utf-8') as f:
|
with open(init_file, 'w', encoding='utf-8') as f:
|
||||||
f.write(updated_init_content)
|
f.write(updated_init_content)
|
||||||
|
|
||||||
print(f"升级脚本已生成,共 {len(upgrade_statements)} 条ALTER语句")
|
total_statements = len(structure_upgrade_statements) + len(data_upgrade_statements)
|
||||||
|
print(f"升级脚本已生成,共 {total_statements} 条语句")
|
||||||
|
print(f"其中表结构升级语句 {len(structure_upgrade_statements)} 条,数据升级语句 {len(data_upgrade_statements)} 条")
|
||||||
print(f"升级脚本路径: {upgrade_file}")
|
print(f"升级脚本路径: {upgrade_file}")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
19
upgrade.sql
19
upgrade.sql
@@ -1,6 +1,6 @@
|
|||||||
-- 数据库升级脚本
|
-- 数据库升级脚本
|
||||||
-- 生成时间: 自动生成
|
-- 生成时间: 自动生成
|
||||||
-- 描述: 根据niushop_database.sql更新init.sql的表结构
|
-- 描述: 根据niushop_database.sql更新init.sql的表结构和数据
|
||||||
|
|
||||||
USE shop_mallnew;
|
USE shop_mallnew;
|
||||||
|
|
||||||
@@ -55,12 +55,11 @@ ALTER TABLE `lucky_user` ADD COLUMN `create_uid` int NOT NULL DEFAULT '0' COMMEN
|
|||||||
|
|
||||||
-- 数据升级语句
|
-- 数据升级语句
|
||||||
USE shop_mallnew;
|
USE shop_mallnew;
|
||||||
|
INSERT INTO `lucky_cashier_auth_group` (`group_name`, `menu_array`, `keyword`, `site_id`, `desc`) VALUES ('门店管理员', '', 'admin', 1, '');
|
||||||
INSERT INTO `lucky_cashier_auth_group` VALUES ('门店管理员', '', 'admin', 1, '');
|
INSERT INTO `lucky_cashier_auth_group` (`group_name`, `menu_array`, `keyword`, `site_id`, `desc`) VALUES ('收银员', 'cashier,billing,buycard,recharge', '', 1, '');
|
||||||
INSERT INTO `lucky_cashier_auth_group` VALUES ('收银员', 'cashier,billing,buycard,recharge', '', 1, '');
|
INSERT INTO `lucky_cashier_auth_group` (`group_name`, `menu_array`, `keyword`, `site_id`, `desc`) VALUES ('核销员', 'verify_manage,verify_index,verify_record,verify_code_info,verify', '', 1, '');
|
||||||
INSERT INTO `lucky_cashier_auth_group` VALUES ('核销员', 'verify_manage,verify_index,verify_record,verify_code_info,verify', '', 1, '');
|
INSERT INTO `lucky_store` (`store_name`,`site_id`,`status`,`stock_type`,`is_default`) VALUES ('默认总店',1,1,'store', 1);
|
||||||
INSERT INTO `lucky_store` VALUES ('默认总店',1,1,'store', 1);
|
INSERT INTO `lucky_cron` (`type`, `period`, `period_type`, `name`, `event`, `execute_time`, `relate_id`, `create_time`) VALUES (2, 2, 0, '店铺统计更新(按时)', 'CronStatShopHour', 1700447491, 0, 0);
|
||||||
INSERT INTO `lucky_cron` VALUES (2, 2, 0, '店铺统计更新(按时)', 'CronStatShopHour', 1700447491, 0, 0);
|
INSERT INTO `lucky_cron` (`type`, `period`, `period_type`, `name`, `event`, `execute_time`, `relate_id`, `create_time`) VALUES (2, 2, 0, '门店统计更新(按时)', 'CronStatStoreHour', 1700447491, 0, 0);
|
||||||
INSERT INTO `lucky_cron` VALUES (2, 2, 0, '门店统计更新(按时)', 'CronStatStoreHour', 1700447491, 0, 0);
|
INSERT INTO `lucky_cron` (`type`, `period`, `period_type`, `name`, `event`, `execute_time`, `relate_id`, `create_time`) VALUES (2, 2, 0, '店铺统计更新(按日)', 'CronStatShop', 1700447491, 0, 0);
|
||||||
INSERT INTO `lucky_cron` VALUES (2, 2, 0, '店铺统计更新(按日)', 'CronStatShop', 1700447491, 0, 0);
|
INSERT INTO `lucky_cron` (`type`, `period`, `period_type`, `name`, `event`, `execute_time`, `relate_id`, `create_time`) VALUES (2, 2, 0, '门店统计更新(按日)', 'CronStatStore', 1700447491, 0, 0);
|
||||||
INSERT INTO `lucky_cron` VALUES (2, 2, 0, '门店统计更新(按日)', 'CronStatStore', 1700447491, 0, 0);
|
|
||||||
|
|||||||
Reference in New Issue
Block a user