"""Pin allocation recompute to a day-local TiDB index range. Revision ID: 458 Revises: 457 Create Date: 2026-08-10 ``cmdb.cost.nightly_recompute_allocation`` previously walked cost facts with a global id cursor plus a 90-day date predicate. Production TiDB cancelled that query with error 8176 when it crossed a large block of out-of-window history. The service now scans one accounting day at a time; this index makes each ``date = :day AND id > :cursor`` page a narrow ordered range instead of a historical-table scan. The guard keeps the migration safe for already-repaired environments and the TiDB DDL is online. """ from __future__ import annotations import sqlalchemy as sa from alembic import op revision = "458" down_revision = "457" branch_labels = None depends_on = None _TABLE = "cmdb_cost_facts" _INDEX = "ix_facts_date_id" def _index_exists(bind, table: str, index: str) -> bool: return bind.execute( sa.text( "SELECT 1 FROM information_schema.STATISTICS " "WHERE TABLE_SCHEMA = DATABASE() " " AND TABLE_NAME = :t AND INDEX_NAME = :i LIMIT 1" ), {"t": table, "i": index}, ).scalar() is not None def upgrade() -> None: bind = op.get_bind() if not _index_exists(bind, _TABLE, _INDEX): op.create_index(_INDEX, _TABLE, ["date", "id"]) def downgrade() -> None: bind = op.get_bind() if _index_exists(bind, _TABLE, _INDEX): op.drop_index(_INDEX, table_name=_TABLE)