112 lines
3.6 KiB
Python
112 lines
3.6 KiB
Python
"""add feishu outbox reply hash
|
|
|
|
Revision ID: add_feishu_outbox_reply_hash
|
|
Revises: add_ai_pmo_simulation_field
|
|
Create Date: 2026-03-10
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
revision = "add_feishu_outbox_reply_hash"
|
|
down_revision = "add_ai_pmo_simulation_field"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def _table_exists(bind, table_name: str) -> bool:
|
|
return sa.inspect(bind).has_table(table_name)
|
|
|
|
|
|
def _column_exists(bind, table_name: str, column_name: str) -> bool:
|
|
inspector = sa.inspect(bind)
|
|
if not inspector.has_table(table_name):
|
|
return False
|
|
return any(col.get("name") == column_name for col in inspector.get_columns(table_name))
|
|
|
|
|
|
def _index_exists(bind, table_name: str, index_name: str) -> bool:
|
|
inspector = sa.inspect(bind)
|
|
if not inspector.has_table(table_name):
|
|
return False
|
|
return any(idx.get("name") == index_name for idx in inspector.get_indexes(table_name))
|
|
|
|
|
|
def _create_index_if_not_exists(
|
|
bind,
|
|
*,
|
|
index_name: str,
|
|
table_name: str,
|
|
columns: list[str],
|
|
unique: bool = False,
|
|
postgresql_where: Any = None,
|
|
sqlite_where: Any = None,
|
|
) -> None:
|
|
if _index_exists(bind, table_name, index_name):
|
|
return
|
|
kwargs: dict[str, Any] = {}
|
|
if postgresql_where is not None:
|
|
kwargs["postgresql_where"] = postgresql_where
|
|
if sqlite_where is not None:
|
|
kwargs["sqlite_where"] = sqlite_where
|
|
op.create_index(index_name, table_name, columns, unique=unique, **kwargs)
|
|
|
|
|
|
def _drop_index_if_exists(bind, table_name: str, index_name: str) -> None:
|
|
if _index_exists(bind, table_name, index_name):
|
|
op.drop_index(index_name, table_name=table_name)
|
|
|
|
|
|
def upgrade() -> None:
|
|
bind = op.get_bind()
|
|
if not _table_exists(bind, "feishu_reply_outbox"):
|
|
return
|
|
|
|
if not _column_exists(bind, "feishu_reply_outbox", "source_message_id"):
|
|
op.add_column("feishu_reply_outbox", sa.Column("source_message_id", sa.String(length=128), nullable=True))
|
|
if not _column_exists(bind, "feishu_reply_outbox", "reply_hash"):
|
|
op.add_column("feishu_reply_outbox", sa.Column("reply_hash", sa.String(length=32), nullable=True))
|
|
|
|
_create_index_if_not_exists(
|
|
bind,
|
|
index_name="ix_feishu_reply_outbox_source_message_id",
|
|
table_name="feishu_reply_outbox",
|
|
columns=["source_message_id"],
|
|
)
|
|
_create_index_if_not_exists(
|
|
bind,
|
|
index_name="ix_feishu_reply_outbox_reply_hash",
|
|
table_name="feishu_reply_outbox",
|
|
columns=["reply_hash"],
|
|
)
|
|
sent_where = sa.text("status = 'sent' AND reply_hash IS NOT NULL")
|
|
_create_index_if_not_exists(
|
|
bind,
|
|
index_name="uq_feishu_reply_outbox_sent_reply_hash",
|
|
table_name="feishu_reply_outbox",
|
|
columns=["tenant_id", "reply_hash"],
|
|
unique=True,
|
|
postgresql_where=sent_where,
|
|
sqlite_where=sent_where,
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
bind = op.get_bind()
|
|
if not _table_exists(bind, "feishu_reply_outbox"):
|
|
return
|
|
|
|
_drop_index_if_exists(bind, "feishu_reply_outbox", "uq_feishu_reply_outbox_sent_reply_hash")
|
|
_drop_index_if_exists(bind, "feishu_reply_outbox", "ix_feishu_reply_outbox_reply_hash")
|
|
_drop_index_if_exists(bind, "feishu_reply_outbox", "ix_feishu_reply_outbox_source_message_id")
|
|
|
|
if _column_exists(bind, "feishu_reply_outbox", "reply_hash"):
|
|
op.drop_column("feishu_reply_outbox", "reply_hash")
|
|
if _column_exists(bind, "feishu_reply_outbox", "source_message_id"):
|
|
op.drop_column("feishu_reply_outbox", "source_message_id")
|