| 1 | """Widen case template text columns to TEXT |
| 2 | |
| 3 | Revision ID: 03508fb56a48 |
| 4 | Revises: 6ba5c2887ec5 |
| 5 | Create Date: 2026-04-26 19:30:00.000000 |
| 6 | |
| 7 | The previous autogenerate (6ba5c2887ec5) materialized several free-form |
| 8 | text columns as VARCHAR(255) because SQLModel's ``sa_column=Text`` form |
| 9 | isn't picked up cleanly by alembic's type inference. This migration |
| 10 | widens them to TEXT so analysts can paste multi-paragraph guidelines |
| 11 | and log snippets / command output without truncation. |
| 12 | |
| 13 | Affected columns: |
| 14 | - incident_management_case_template.description |
| 15 | - incident_management_case_template_task.description |
| 16 | - incident_management_case_template_task.guidelines |
| 17 | - incident_management_case_task.description |
| 18 | - incident_management_case_task.guidelines |
| 19 | - incident_management_case_task.evidence_comment |
| 20 | |
| 21 | Non-destructive: the tables are introduced empty in 6ba5c2887ec5, so |
| 22 | no data is at risk. |
| 23 | """ |
| 24 | |
| 25 | from typing import Sequence |
| 26 | from typing import Union |
| 27 | |
| 28 | import sqlalchemy as sa |
| 29 | |
| 30 | from alembic import op |
| 31 | |
| 32 | # revision identifiers, used by Alembic. |
| 33 | revision: str = "03508fb56a48" |
| 34 | down_revision: Union[str, None] = "6ba5c2887ec5" |
| 35 | branch_labels: Union[str, Sequence[str], None] = None |
| 36 | depends_on: Union[str, Sequence[str], None] = None |
| 37 | |
| 38 | |
| 39 | # (table_name, column_name, nullable) — every column should be widened to TEXT. |
| 40 | _WIDEN_COLUMNS = [ |
| 41 | ("incident_management_case_template", "description", True), |
| 42 | ("incident_management_case_template_task", "description", True), |
| 43 | ("incident_management_case_template_task", "guidelines", True), |
| 44 | ("incident_management_case_task", "description", True), |
| 45 | ("incident_management_case_task", "guidelines", True), |
| 46 | ("incident_management_case_task", "evidence_comment", True), |
| 47 | ] |
| 48 | |
| 49 | |
| 50 | def upgrade() -> None: |
| 51 | for table, column, nullable in _WIDEN_COLUMNS: |
| 52 | op.alter_column( |
| 53 | table, |
| 54 | column, |
| 55 | existing_type=sa.String(length=255), |
| 56 | type_=sa.Text(), |
| 57 | existing_nullable=nullable, |
| 58 | ) |
| 59 | |
| 60 | |
| 61 | def downgrade() -> None: |
| 62 | # Reverses the widening. Will fail if any row contains a value longer |
| 63 | # than 255 characters; that's intentional — losing data on downgrade |
| 64 | # would be worse than refusing to run. |
| 65 | for table, column, nullable in _WIDEN_COLUMNS: |
| 66 | op.alter_column( |
| 67 | table, |
| 68 | column, |
| 69 | existing_type=sa.Text(), |
| 70 | type_=sa.String(length=255), |
| 71 | existing_nullable=nullable, |
| 72 | ) |