cleanup: drop dead storage_objects.parent_object_id column + idx_storage_parent

parent_object_id was never written or read by any application code (verified
via repo-wide grep: only the baseline migration and the ORM model referenced
it). The orphan index idx_storage_parent likewise served nothing.

Tree structure is maintained entirely via the materialized path in
storage_objects.relative_path (LIKE-prefix queries in
backend/src/backend/scripts.py: list_workspace_tree, list_workspace_directories).
The column mislead a prior review into proposing an adjacency-list table —
removing it eliminates that temptation for the next reader.

Migration: migrations/versions/f7a8b9c0d1e2_drop_storage_parent.py
- Drops idx_storage_parent first, then parent_object_id (correct order on MySQL).
- MySQL 8.0 has no IF EXISTS on DROP INDEX / DROP COLUMN, so calls are unconditional.
- Updates the storage_objects TABLE COMMENT so the materialized-path warning
  reaches the DB, not just the ORM (Codex review finding).
- Downgrade restores both.

Model: common/src/common/db/models/storage.py
- Removes the dead Index entry and the dead column.
- Refreshes the table comment to flag the materialized-path contract.

Verified:
- alembic upgrade head: applied, head = f7a8b9c0d1e2
- SHOW INDEX / SHOW COLUMNS: 0 rows
- TABLE COMMENT updated in information_schema
- pytest backend/tests: 43 passed
This commit is contained in:
tao.chen
2026-08-21 10:16:41 +08:00
parent 3dc049f46e
commit 0ea6456ed1
2 changed files with 57 additions and 3 deletions
+1 -3
View File
@@ -20,7 +20,6 @@ class StorageObjects(Base):
Index("fk_storage_created_by", "created_by"),
Index("idx_storage_content_hash", "content_hash"),
Index("idx_storage_owner", "owner_user_id", "object_status"),
Index("idx_storage_parent", "parent_object_id"),
Index(
"idx_storage_workspace_path",
"workspace_id",
@@ -40,7 +39,7 @@ class StorageObjects(Base):
"object_key_hash_active",
unique=True,
),
{"comment": "Workspace 文件和 RustFS 对象的统一元数据"},
{"comment": "Workspace 文件和 RustFS 对象的统一元数据;目录树走 materialized path (relative_path),不要 join 邻接表列——已删除。"},
)
storage_object_id: Mapped[str] = mapped_column(CHAR(26), primary_key=True)
@@ -86,7 +85,6 @@ class StorageObjects(Base):
server_default=text("CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"),
)
owner_user_id: Mapped[str | None] = mapped_column(CHAR(26))
parent_object_id: Mapped[str | None] = mapped_column(CHAR(26))
relative_path: Mapped[str | None] = mapped_column(
String(1024), comment="Workspace 相对路径"
)
@@ -0,0 +1,56 @@
"""drop dead storage_objects.parent_object_id column and idx_storage_parent
Revision ID: f7a8b9c0d1e2
Revises: e1f2a3b4c5d6
Create Date: 2026-08-21
Removes a never-written column and its orphaned index. Tree structure is
maintained entirely via relative_path (materialized path); see
backend/src/backend/scripts.py (list_workspace_tree / list_workspace_directories).
MySQL 8.0 does not support DROP INDEX IF EXISTS / DROP COLUMN IF EXISTS,
so the calls below are unconditional.
"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision: str = "f7a8b9c0d1e2"
down_revision: str | Sequence[str] | None = "e1f2a3b4c5d6"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
"""Drop the dead index, then the dead column."""
op.drop_index("idx_storage_parent", table_name="storage_objects")
op.drop_column("storage_objects", "parent_object_id")
# Refresh the table comment so the warning reaches the DB, not just the ORM.
op.execute(
"ALTER TABLE storage_objects "
"COMMENT = 'Workspace 文件和 RustFS 对象的统一元数据;"
"目录树走 materialized path (relative_path),"
"不要 join 邻接表列——已删除。'"
)
def downgrade() -> None:
"""Recreate the column and index for rollback."""
op.add_column(
"storage_objects",
sa.Column("parent_object_id", mysql.CHAR(length=26), nullable=True),
)
op.create_index(
"idx_storage_parent",
"storage_objects",
["parent_object_id"],
unique=False,
)
op.execute(
"ALTER TABLE storage_objects "
"COMMENT = 'Workspace 文件和 RustFS 对象的统一元数据'"
)