"""Add content_hash column to files table for SHA-256 dedup and integrity. Revision ID: 0038_dms_content_hash Revises: 0037_user_tenant_model Create Date: 2026-07-25 Changes: 1. Add content_hash (String(64), nullable) column to files table. """ from __future__ import annotations from typing import Union import sqlalchemy as sa from alembic import op # revision identifiers revision: str = "0038_dms_content_hash" down_revision: Union[str, None] = "0037_user_tenant_model" branch_labels: Union[str, None] = None depends_on: Union[str, None] = None def _column_exists(table: str, column: str) -> str: """Return SQL that checks if a column exists on a table.""" return ( f"SELECT 1 FROM information_schema.columns " f"WHERE table_name = '{table}' AND column_name = '{column}'" ) def upgrade() -> None: conn = op.get_bind() # Check if table exists first table_exists = conn.execute(sa.text("SELECT 1 FROM information_schema.tables WHERE table_name = 'files'")).fetchone() if table_exists is None: return result = conn.execute(sa.text(_column_exists("files", "content_hash"))).fetchone() if result is None: op.execute("ALTER TABLE files ADD COLUMN IF NOT EXISTS content_hash VARCHAR(64)") def downgrade() -> None: conn = op.get_bind() result = conn.execute(sa.text(_column_exists("files", "content_hash"))).fetchone() if result is not None: op.drop_column("files", "content_hash")