Merge pull request #1069 from CREDO23/fix/zero-cache

[Fix] Make migration 109 idempotent
This commit is contained in:
Rohan Verma 2026-04-01 02:19:53 -07:00 committed by GitHub
commit b1631cd6f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -11,6 +11,7 @@ index to correctly handle NULL parent_id at root level.
from collections.abc import Sequence
import sqlalchemy as sa
from sqlalchemy import inspect
from alembic import op
@ -21,67 +22,76 @@ depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
op.create_table(
"folders",
sa.Column("id", sa.Integer(), primary_key=True, index=True),
sa.Column("name", sa.String(255), nullable=False, index=True),
sa.Column("position", sa.String(50), nullable=False, index=True),
sa.Column(
"parent_id",
sa.Integer(),
sa.ForeignKey("folders.id", ondelete="CASCADE"),
nullable=True,
index=True,
),
sa.Column(
"search_space_id",
sa.Integer(),
sa.ForeignKey("searchspaces.id", ondelete="CASCADE"),
nullable=False,
index=True,
),
sa.Column(
"created_by_id",
sa.Uuid(),
sa.ForeignKey("user.id", ondelete="SET NULL"),
nullable=True,
index=True,
),
sa.Column(
"created_at",
sa.TIMESTAMP(timezone=True),
nullable=False,
server_default=sa.func.now(),
),
sa.Column(
"updated_at",
sa.TIMESTAMP(timezone=True),
nullable=False,
server_default=sa.func.now(),
),
)
conn = op.get_bind()
inspector = inspect(conn)
existing_tables = inspector.get_table_names()
if "folders" not in existing_tables:
op.create_table(
"folders",
sa.Column("id", sa.Integer(), primary_key=True, index=True),
sa.Column("name", sa.String(255), nullable=False, index=True),
sa.Column("position", sa.String(50), nullable=False, index=True),
sa.Column(
"parent_id",
sa.Integer(),
sa.ForeignKey("folders.id", ondelete="CASCADE"),
nullable=True,
index=True,
),
sa.Column(
"search_space_id",
sa.Integer(),
sa.ForeignKey("searchspaces.id", ondelete="CASCADE"),
nullable=False,
index=True,
),
sa.Column(
"created_by_id",
sa.Uuid(),
sa.ForeignKey("user.id", ondelete="SET NULL"),
nullable=True,
index=True,
),
sa.Column(
"created_at",
sa.TIMESTAMP(timezone=True),
nullable=False,
server_default=sa.func.now(),
),
sa.Column(
"updated_at",
sa.TIMESTAMP(timezone=True),
nullable=False,
server_default=sa.func.now(),
),
)
# Expression-based unique index: COALESCE(parent_id, 0) handles NULL correctly.
# PostgreSQL treats NULL != NULL in regular unique constraints, so a standard
# UniqueConstraint(search_space_id, parent_id, name) would allow duplicate
# folder names at the root level.
op.execute(
"""
CREATE UNIQUE INDEX uq_folder_space_parent_name
ON folders (search_space_id, COALESCE(parent_id, 0), name);
"""
)
existing_indexes = [idx["name"] for idx in inspector.get_indexes("folders")]
if "uq_folder_space_parent_name" not in existing_indexes:
op.execute(
"""
CREATE UNIQUE INDEX uq_folder_space_parent_name
ON folders (search_space_id, COALESCE(parent_id, 0), name);
"""
)
op.add_column(
"documents",
sa.Column(
"folder_id",
sa.Integer(),
sa.ForeignKey("folders.id", ondelete="SET NULL"),
nullable=True,
index=True,
),
)
existing_columns = [col["name"] for col in inspector.get_columns("documents")]
if "folder_id" not in existing_columns:
op.add_column(
"documents",
sa.Column(
"folder_id",
sa.Integer(),
sa.ForeignKey("folders.id", ondelete="SET NULL"),
nullable=True,
index=True,
),
)
def downgrade() -> None: