feat(db): update SQL init script and Alembic migration for compatibility

Update data-annotation-init.sql and Alembic migration to support both new and old deployments:

SQL Initialization Script (data-annotation-init.sql):
- Add file_version column to t_dm_annotation_results table
- Add Alembic version table creation and version insertion
- New deployments using this script will have latest schema and Alembic version marked

Alembic Migration (20250205_0001_add_file_version.py):
- Add column_exists() helper function to detect if column already exists
- Add compatibility check in upgrade(): skip if column exists (new SQL init)
- Add informative print messages for deployment clarity
- Enhanced docstrings explaining compatibility strategy

Deployment Scenarios:
1. New deployment with latest SQL script: Schema created with file_version, Alembic marked as applied
2. Old deployment upgrade: Alembic detects missing column and adds it

This ensures backward compatibility while supporting fresh installs with complete schema.
This commit is contained in:
2026-02-05 21:17:17 +08:00
parent f5cb265667
commit 48cf49d064
2 changed files with 58 additions and 1 deletions

View File

@@ -4,10 +4,16 @@ Revision ID: 20250205_0001
Revises:
Create Date: 2025-02-05 00:00:00.000000
说明:
- 此迁移脚本用于升级旧版本数据库(使用 2025-02-05 之前的 SQL 脚本初始化)
- 如果使用最新的 data-annotation-init.sql 初始化,此脚本会自动跳过
(因为 alembic_version 表已包含此版本记录)
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -17,14 +23,45 @@ branch_labels = None
depends_on = None
def column_exists(table_name: str, column_name: str) -> bool:
"""检查表中是否已存在指定列"""
conn = op.get_bind()
inspector = inspect(conn)
columns = [col['name'] for col in inspector.get_columns(table_name)]
return column_name in columns
def upgrade() -> None:
"""
升级:添加 file_version 字段到 t_dm_annotation_results 表
兼容性处理:
- 如果字段已存在(使用最新 SQL 脚本初始化),则跳过
- 如果字段不存在(旧版本数据库),则添加字段
"""
if column_exists("t_dm_annotation_results", "file_version"):
# 字段已存在,说明使用的是最新 SQL 初始化脚本
# Alembic 会自动记录版本,无需重复添加字段
print("字段 file_version 已存在,跳过添加操作(使用最新 SQL 脚本初始化)")
return
# 字段不存在,添加字段(旧版本数据库升级)
op.add_column(
"t_dm_annotation_results",
sa.Column(
"file_version", sa.BigInteger(), nullable=True, comment="标注时的文件版本号"
),
)
print("成功添加 file_version 字段到 t_dm_annotation_results 表")
def downgrade() -> None:
op.drop_column("t_dm_annotation_results", "file_version")
"""
回滚:删除 file_version 字段
注意:如果使用的是最新 SQL 脚本初始化,回滚此迁移不会删除字段
因为字段是初始结构的一部分
"""
if column_exists("t_dm_annotation_results", "file_version"):
op.drop_column("t_dm_annotation_results", "file_version")
print("成功删除 file_version 字段")

View File

@@ -66,6 +66,7 @@ CREATE TABLE IF NOT EXISTS t_dm_annotation_results (
file_id VARCHAR(36) NOT NULL COMMENT '文件ID',
annotation JSON NOT NULL COMMENT 'Label Studio annotation 原始JSON',
annotation_status VARCHAR(32) NOT NULL DEFAULT 'ANNOTATED' COMMENT '标注状态: ANNOTATED/NO_ANNOTATION/NOT_APPLICABLE',
file_version BIGINT NULL COMMENT '标注时的文件版本号',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
UNIQUE KEY uk_project_file (project_id, file_id),
@@ -1466,8 +1467,27 @@ INSERT INTO t_dm_annotation_templates (
'1.0.0'
);
-- =============================================
-- Alembic 版本控制表(标记数据库已应用最新迁移)
-- 说明:如果使用此脚本初始化数据库,则不需要再运行 Alembic 升级
-- =============================================
-- 创建 alembic_version 表(如果不存在)
CREATE TABLE IF NOT EXISTS alembic_version (
version_num VARCHAR(32) NOT NULL PRIMARY KEY
) COMMENT='Alembic 迁移版本记录表';
-- 清除现有版本记录(避免重复插入错误)
DELETE FROM alembic_version;
-- 插入当前最新版本(与 alembic/versions/20250205_0001_add_file_version.py 对应)
INSERT INTO alembic_version (version_num) VALUES ('20250205_0001');
-- =============================================
-- 完成提示
-- =============================================
SELECT CONCAT('成功插入 ', COUNT(*), ' 个内置标注模板') AS result
FROM t_dm_annotation_templates WHERE built_in = 1;
SELECT CONCAT('数据库已初始化至 Alembic 版本: ', version_num) AS alembic_status
FROM alembic_version;