chore(docker): 增加升级数据库脚本
This commit is contained in:
@@ -218,6 +218,120 @@ def update_table_structure(init_table, niushop_columns):
|
||||
|
||||
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():
|
||||
# 文件路径
|
||||
@@ -240,9 +354,17 @@ def main():
|
||||
init_tables = extract_init_table_structures(init_content)
|
||||
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("正在比较表结构差异...")
|
||||
upgrade_statements = []
|
||||
structure_upgrade_statements = []
|
||||
updated_init_content = init_content
|
||||
|
||||
# 遍历init.sql中的所有表
|
||||
@@ -278,29 +400,49 @@ def main():
|
||||
# 提取列名(带反引号)
|
||||
col_name_in_def = col['definition'].split(' ')[0]
|
||||
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中的表结构
|
||||
new_create_sql = update_table_structure(init_table, niushop_cols)
|
||||
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("正在写入升级脚本...")
|
||||
with open(upgrade_file, 'w', encoding='utf-8') as f:
|
||||
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")
|
||||
|
||||
for stmt in upgrade_statements:
|
||||
f.write(f"{stmt}\n")
|
||||
# 写入表结构升级语句
|
||||
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")
|
||||
|
||||
# 更新init.sql文件
|
||||
print("正在更新init.sql文件...")
|
||||
with open(init_file, 'w', encoding='utf-8') as f:
|
||||
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}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user