Fix migrations 0004 and 0005 to be fully idempotent
The Dockerfile runs `alembic stamp --purge base && alembic upgrade head` on every restart, so all migrations re-run against an existing database. Migration 0004 used `op.add_column()` which fails on re-run with "column already exists". Migration 0005 used `op.create_table()` which would fail similarly. Both now use raw SQL with idempotency guards: - 0004: `DO $$ BEGIN ALTER TABLE ADD COLUMN ... EXCEPTION WHEN duplicate_column` + `IF EXISTS` check before touching the tasks table - 0005: `CREATE TABLE IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS` Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,54 +15,35 @@ depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
"conversations",
|
||||
sa.Column("id", sa.Integer(), primary_key=True),
|
||||
sa.Column("title", sa.Text(), nullable=False, server_default=""),
|
||||
sa.Column("model", sa.Text(), nullable=False, server_default=""),
|
||||
sa.Column(
|
||||
"created_at",
|
||||
sa.DateTime(timezone=True),
|
||||
server_default=sa.func.now(),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column(
|
||||
"updated_at",
|
||||
sa.DateTime(timezone=True),
|
||||
server_default=sa.func.now(),
|
||||
nullable=False,
|
||||
),
|
||||
)
|
||||
conn = op.get_bind()
|
||||
|
||||
op.create_table(
|
||||
"messages",
|
||||
sa.Column("id", sa.Integer(), primary_key=True),
|
||||
sa.Column(
|
||||
"conversation_id",
|
||||
sa.Integer(),
|
||||
sa.ForeignKey("conversations.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column("role", sa.Text(), nullable=False),
|
||||
sa.Column("content", sa.Text(), nullable=False, server_default=""),
|
||||
sa.Column(
|
||||
"context_note_id",
|
||||
sa.Integer(),
|
||||
sa.ForeignKey("notes.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column(
|
||||
"created_at",
|
||||
sa.DateTime(timezone=True),
|
||||
server_default=sa.func.now(),
|
||||
nullable=False,
|
||||
),
|
||||
)
|
||||
conn.execute(sa.text("""
|
||||
CREATE TABLE IF NOT EXISTS conversations (
|
||||
id SERIAL PRIMARY KEY,
|
||||
title TEXT NOT NULL DEFAULT '',
|
||||
model TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
)
|
||||
"""))
|
||||
|
||||
op.create_index("ix_messages_conversation_id", "messages", ["conversation_id"])
|
||||
conn.execute(sa.text("""
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id SERIAL PRIMARY KEY,
|
||||
conversation_id INTEGER NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
|
||||
role TEXT NOT NULL,
|
||||
content TEXT NOT NULL DEFAULT '',
|
||||
context_note_id INTEGER REFERENCES notes(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
)
|
||||
"""))
|
||||
|
||||
conn.execute(sa.text(
|
||||
"CREATE INDEX IF NOT EXISTS ix_messages_conversation_id ON messages (conversation_id)"
|
||||
))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index("ix_messages_conversation_id", table_name="messages")
|
||||
op.drop_table("messages")
|
||||
op.drop_table("conversations")
|
||||
op.execute("DROP INDEX IF EXISTS ix_messages_conversation_id")
|
||||
op.execute("DROP TABLE IF EXISTS messages")
|
||||
op.execute("DROP TABLE IF EXISTS conversations")
|
||||
|
||||
Reference in New Issue
Block a user