From be08d6ebb5c9b69e80b377174558c200b8edec2d Mon Sep 17 00:00:00 2001 From: jxxghp Date: Tue, 19 Aug 2025 12:02:53 +0800 Subject: [PATCH] fix db --- database/versions/d58298a0879f_2_1_9.py | 125 ++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 database/versions/d58298a0879f_2_1_9.py diff --git a/database/versions/d58298a0879f_2_1_9.py b/database/versions/d58298a0879f_2_1_9.py new file mode 100644 index 00000000..a4064c5d --- /dev/null +++ b/database/versions/d58298a0879f_2_1_9.py @@ -0,0 +1,125 @@ +"""2.1.9 + +Revision ID: d58298a0879f +Revises: 4666ce24a443 +Create Date: 2025-08-19 11:56:39.652032 + +""" +import contextlib +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import sqlite + +from app.core.config import settings + +# revision identifiers, used by Alembic. +revision = 'd58298a0879f' +down_revision = '4666ce24a443' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + if settings.DB_TYPE.lower() == "postgresql": + # PostgreSQL序列修复:将SQLite的Sequence转换为PostgreSQL的Identity + fix_postgresql_sequences() + # ### end Alembic commands ### + + +def downgrade() -> None: + pass + + +def fix_postgresql_sequences(): + """ + 修复PostgreSQL数据库中的序列问题 + 将SQLite迁移过来的Sequence转换为PostgreSQL的Identity + """ + connection = op.get_bind() + + # 获取所有表名 + result = connection.execute(sa.text(""" + SELECT table_name + FROM information_schema.tables + WHERE table_schema = 'public' + AND table_type = 'BASE TABLE' + """)) + tables = [row[0] for row in result.fetchall()] + + print(f"发现 {len(tables)} 个表需要检查序列") + + for table_name in tables: + fix_table_sequence(connection, table_name) + + +def fix_table_sequence(connection, table_name): + """ + 修复单个表的序列 + """ + try: + # 检查表是否有id列 + result = connection.execute(sa.text(f""" + SELECT column_name, data_type, is_nullable, column_default + FROM information_schema.columns + WHERE table_name = '{table_name}' + AND column_name = 'id' + """)) + + id_column = result.fetchone() + if not id_column: + print(f"表 {table_name} 没有id列,跳过") + return + + column_name, data_type, is_nullable, column_default = id_column + + # 检查是否已经是Identity类型 + if column_default and 'GENERATED BY DEFAULT AS IDENTITY' in column_default: + print(f"表 {table_name} 的id列已经是Identity类型,跳过") + return + + # 检查是否有序列 + result = connection.execute(sa.text(f""" + SELECT sequence_name + FROM information_schema.sequences + WHERE sequence_name LIKE '{table_name}_id_seq' + """)) + + sequence_exists = result.fetchone() + + if sequence_exists: + print(f"表 {table_name} 存在序列,需要修复") + convert_to_identity(connection, table_name) + + except Exception as e: + print(f"修复表 {table_name} 序列时出错: {e}") + + +def convert_to_identity(connection, table_name): + """ + 将序列转换为Identity + """ + try: + # 获取当前序列的最大值 + result = connection.execute(sa.text(f""" + SELECT COALESCE(MAX(id), 0) + 1 as next_value + FROM {table_name} + """)) + next_value = result.fetchone()[0] + + # 删除旧的序列 + connection.execute(sa.text(f"DROP SEQUENCE IF EXISTS {table_name}_id_seq")) + + # 修改列定义,添加Identity + connection.execute(sa.text(f""" + ALTER TABLE {table_name} + ALTER COLUMN id SET DATA TYPE INTEGER, + ALTER COLUMN id SET DEFAULT NULL, + ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY (START WITH {next_value}) + """)) + + print(f"表 {table_name} 序列已转换为Identity,起始值为 {next_value}") + + except Exception as e: + print(f"转换表 {table_name} 序列时出错: {e}") + raise