Fix: Migration 0102 checks table existence before adding owner_id

This commit is contained in:
Agent Zero
2026-08-04 00:18:06 +02:00
parent 40e9943e69
commit 51a2c44238
@@ -1,9 +1,12 @@
"""Add owner_id column to Phase 2 tables for row-level ownership. """Add owner_id column to Phase 2 tables for row-level ownership.
Adds nullable owner_id (FK users.id, ON DELETE SET NULL) to tables Adds nullable owner_id (FK -> users.id, ON DELETE SET NULL) to tables
that gained OwnedMixin in Phase 2. For tables that already have a that gained OwnedMixin in Phase 2. For tables that already have a
non-nullable user_id column, owner_id is backfilled from user_id. non-nullable user_id column, owner_id is backfilled from user_id.
Plugin tables may not exist yet at migration time (created by plugin
migrations separately), so we check existence before adding columns.
Revision ID: 0102 Revision ID: 0102
""" """
@@ -18,11 +21,11 @@ depends_on = None
# (table_name, has_user_id_to_backfill) # (table_name, has_user_id_to_backfill)
TABLES = [ TABLES = [
# Core models # Core models (always exist at this migration point)
("contact_folders", True), ("contact_folders", True),
("user_preferences", True), ("user_preferences", True),
("workspaces", False), ("workspaces", False),
# Plugin models # Plugin models (may not exist yet — created by plugin migrations)
("mcp_server_configs", False), ("mcp_server_configs", False),
("automation_agent_definitions", False), ("automation_agent_definitions", False),
("automation_definitions", False), ("automation_definitions", False),
@@ -38,8 +41,31 @@ TABLES = [
] ]
def _table_exists(conn, table_name: str) -> bool:
result = conn.execute(
sa.text("SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = :name)"),
{"name": table_name},
)
return result.scalar()
def upgrade() -> None: def upgrade() -> None:
for table_name, _has_user_id in TABLES: conn = op.get_bind()
for table_name, has_user_id in TABLES:
if not _table_exists(conn, table_name):
print(f"[0102] Skipping {table_name} — table does not exist yet")
continue
# Check if owner_id column already exists
col_exists = conn.execute(
sa.text(
"SELECT EXISTS (SELECT 1 FROM information_schema.columns "
"WHERE table_name = :name AND column_name = 'owner_id')"
),
{"name": table_name},
).scalar()
if col_exists:
print(f"[0102] Skipping {table_name} — owner_id already exists")
continue
op.add_column( op.add_column(
table_name, table_name,
sa.Column( sa.Column(
@@ -54,16 +80,19 @@ def upgrade() -> None:
table_name, table_name,
["owner_id"], ["owner_id"],
) )
# Backfill owner_id from user_id where available
for table_name, has_user_id in TABLES:
if has_user_id: if has_user_id:
op.execute( op.execute(
f"UPDATE {table_name} SET owner_id = user_id WHERE owner_id IS NULL;" f"UPDATE {table_name} SET owner_id = user_id WHERE owner_id IS NULL;"
) )
print(f"[0102] Added owner_id to {table_name} (backfilled from user_id)")
else:
print(f"[0102] Added owner_id to {table_name}")
def downgrade() -> None: def downgrade() -> None:
conn = op.get_bind()
for table_name, _ in TABLES: for table_name, _ in TABLES:
if not _table_exists(conn, table_name):
continue
op.drop_index(f"ix_{table_name}_owner_id", table_name=table_name) op.drop_index(f"ix_{table_name}_owner_id", table_name=table_name)
op.drop_column(table_name, "owner_id") op.drop_column(table_name, "owner_id")