76 lines
3.6 KiB
Python
76 lines
3.6 KiB
Python
|
|
"""Replace saved dataset inputs with editable preparations and independent snapshots."""
|
||
|
|
|
||
|
|
import sqlalchemy as sa
|
||
|
|
from alembic import op
|
||
|
|
|
||
|
|
revision = "0015"
|
||
|
|
down_revision = "0014"
|
||
|
|
branch_labels = None
|
||
|
|
depends_on = None
|
||
|
|
|
||
|
|
|
||
|
|
def upgrade():
|
||
|
|
op.drop_table("template_inputs")
|
||
|
|
op.add_column("catalog_batches", sa.Column("job_id", sa.String(36), nullable=True))
|
||
|
|
op.add_column("catalog_batches", sa.Column("offset", sa.Integer(), nullable=False, server_default="0"))
|
||
|
|
op.execute("UPDATE catalog_batches SET job_id = id")
|
||
|
|
# Preserve unfinished catalog pagination; only legacy research inputs are discarded.
|
||
|
|
jobs = sa.table("sync_jobs", sa.column("id"), sa.column("checkpoint", sa.JSON()))
|
||
|
|
batches = sa.table("catalog_batches", sa.column("id"), sa.column("offset", sa.Integer()))
|
||
|
|
for job_id, checkpoint in op.get_bind().execute(sa.select(jobs.c.id, jobs.c.checkpoint)):
|
||
|
|
offset = (checkpoint or {}).get("offset", 0)
|
||
|
|
if type(offset) is int and offset >= 0:
|
||
|
|
op.get_bind().execute(batches.update().where(batches.c.id == job_id).values(offset=offset))
|
||
|
|
names = {"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s"}
|
||
|
|
fk = next(
|
||
|
|
f
|
||
|
|
for f in sa.inspect(op.get_bind()).get_foreign_keys("catalog_batches")
|
||
|
|
if f["constrained_columns"] == ["id"]
|
||
|
|
)
|
||
|
|
with op.batch_alter_table("catalog_batches", naming_convention=names) as batch:
|
||
|
|
batch.drop_constraint(fk["name"] or "fk_catalog_batches_id_sync_jobs", type_="foreignkey")
|
||
|
|
batch.alter_column("job_id", existing_type=sa.String(36), nullable=False)
|
||
|
|
batch.create_foreign_key("fk_catalog_batches_job", "sync_jobs", ["job_id"], ["id"])
|
||
|
|
batch.create_index("ix_catalog_batches_job_id", ["job_id"])
|
||
|
|
op.create_table(
|
||
|
|
"data_preparations",
|
||
|
|
sa.Column("id", sa.String(36), primary_key=True),
|
||
|
|
sa.Column("name", sa.String(200), nullable=False),
|
||
|
|
sa.Column("note", sa.Text(), nullable=False),
|
||
|
|
sa.Column("scope_key", sa.String(200), nullable=False),
|
||
|
|
sa.Column("scope", sa.JSON(), nullable=False),
|
||
|
|
sa.Column("version", sa.Integer(), nullable=False),
|
||
|
|
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
||
|
|
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
|
||
|
|
)
|
||
|
|
op.create_index("ix_data_preparations_scope_key", "data_preparations", ["scope_key"])
|
||
|
|
op.create_table(
|
||
|
|
"preparation_fields",
|
||
|
|
sa.Column(
|
||
|
|
"preparation_id",
|
||
|
|
sa.String(36),
|
||
|
|
sa.ForeignKey("data_preparations.id", ondelete="CASCADE"),
|
||
|
|
primary_key=True,
|
||
|
|
),
|
||
|
|
sa.Column("field_id", sa.String(200), primary_key=True),
|
||
|
|
sa.Column("dataset_id", sa.String(200), nullable=False),
|
||
|
|
sa.Column("content", sa.JSON(), nullable=False),
|
||
|
|
)
|
||
|
|
op.create_index("ix_preparation_fields_dataset_id", "preparation_fields", ["dataset_id"])
|
||
|
|
op.create_table(
|
||
|
|
"research_input_snapshots",
|
||
|
|
sa.Column("id", sa.String(36), primary_key=True),
|
||
|
|
sa.Column("preparation_id", sa.String(36), nullable=False),
|
||
|
|
sa.Column("preparation_version", sa.Integer(), nullable=False),
|
||
|
|
sa.Column("content", sa.JSON(), nullable=False),
|
||
|
|
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
||
|
|
sa.UniqueConstraint("preparation_id", "preparation_version"),
|
||
|
|
)
|
||
|
|
op.create_index(
|
||
|
|
"ix_research_input_snapshots_preparation_id", "research_input_snapshots", ["preparation_id"]
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def downgrade():
|
||
|
|
raise RuntimeError("旧输入模型已移除;回退请恢复升级前数据库备份")
|