71a3e5b4db2a_update_scan_status_enum.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. """update_scan_status_enum
  2. Revision ID: 71a3e5b4db2a
  3. Revises: faceebd6a580
  4. Create Date: 2025-06-08 16:29:38.093854
  5. """
  6. from typing import Sequence, Union
  7. from alembic import op
  8. import sqlalchemy as sa
  9. from sqlalchemy.dialects import postgresql
  10. # revision identifiers, used by Alembic.
  11. revision: str = '71a3e5b4db2a'
  12. down_revision: Union[str, None] = 'faceebd6a580'
  13. branch_labels: Union[str, Sequence[str], None] = None
  14. depends_on: Union[str, Sequence[str], None] = None
  15. def upgrade() -> None:
  16. """Upgrade schema."""
  17. # Create the enum type first using raw SQL to ensure it exists
  18. op.execute("CREATE TYPE transformstatus AS ENUM ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')")
  19. # Add new columns
  20. op.add_column('scans', sa.Column('started_at', sa.DateTime(), nullable=True))
  21. op.add_column('scans', sa.Column('completed_at', sa.DateTime(), nullable=True))
  22. op.add_column('scans', sa.Column('error', sa.Text(), nullable=True))
  23. op.add_column('scans', sa.Column('details', sa.JSON(), nullable=True))
  24. # Add new status column with enum type
  25. op.add_column('scans', sa.Column('status_new', postgresql.ENUM('PENDING', 'RUNNING', 'COMPLETED', 'FAILED', name='transformstatus'), nullable=True))
  26. # Copy data from old status to new status with proper casting
  27. op.execute("""
  28. UPDATE scans
  29. SET status_new = CASE
  30. WHEN status = 'PENDING' THEN 'PENDING'::transformstatus
  31. WHEN status = 'RUNNING' THEN 'RUNNING'::transformstatus
  32. WHEN status = 'COMPLETED' THEN 'COMPLETED'::transformstatus
  33. WHEN status = 'FAILED' THEN 'FAILED'::transformstatus
  34. ELSE 'PENDING'::transformstatus
  35. END
  36. """)
  37. # Make the new status column not nullable
  38. op.alter_column('scans', 'status_new', nullable=False)
  39. # Drop the old status column
  40. op.drop_column('scans', 'status')
  41. # Rename the new status column
  42. op.alter_column('scans', 'status_new', new_column_name='status')
  43. # Update other columns
  44. op.alter_column('scans', 'sketch_id',
  45. existing_type=sa.UUID(),
  46. nullable=False)
  47. op.drop_index('idx_scans_sketch_id', table_name='scans')
  48. op.drop_constraint('scans_sketch_id_fkey', 'scans', type_='foreignkey')
  49. op.create_foreign_key(None, 'scans', 'sketches', ['sketch_id'], ['id'])
  50. op.drop_column('scans', 'values')
  51. op.drop_column('scans', 'results')
  52. op.drop_column('scans', 'created_at')
  53. def downgrade() -> None:
  54. """Downgrade schema."""
  55. # Add back old columns
  56. op.add_column('scans', sa.Column('created_at', postgresql.TIMESTAMP(timezone=True), server_default=sa.text('now()'), autoincrement=False, nullable=True))
  57. op.add_column('scans', sa.Column('results', postgresql.JSON(astext_type=sa.Text()), autoincrement=False, nullable=True))
  58. op.add_column('scans', sa.Column('values', postgresql.ARRAY(sa.TEXT()), autoincrement=False, nullable=True))
  59. # Add new VARCHAR status column
  60. op.add_column('scans', sa.Column('status_old', sa.String(), nullable=True))
  61. # Copy data from enum status to VARCHAR status
  62. op.execute("UPDATE scans SET status_old = status::VARCHAR")
  63. # Make the new status column not nullable
  64. op.alter_column('scans', 'status_old', nullable=False)
  65. # Drop the enum status column
  66. op.drop_column('scans', 'status')
  67. # Rename the new status column
  68. op.alter_column('scans', 'status_old', new_column_name='status')
  69. # Update other columns
  70. op.drop_constraint(None, 'scans', type_='foreignkey')
  71. op.create_foreign_key('scans_sketch_id_fkey', 'scans', 'sketches', ['sketch_id'], ['id'], onupdate='CASCADE', ondelete='CASCADE')
  72. op.create_index('idx_scans_sketch_id', 'scans', ['sketch_id'], unique=False)
  73. op.alter_column('scans', 'sketch_id',
  74. existing_type=sa.UUID(),
  75. nullable=True)
  76. op.drop_column('scans', 'details')
  77. op.drop_column('scans', 'error')
  78. op.drop_column('scans', 'completed_at')
  79. op.drop_column('scans', 'started_at')
  80. # Drop the enum type
  81. op.execute("DROP TYPE transformstatus")