"""phase31 — device_registrations table (re-issue of phase30) phase30 used op.get_bind() + op.create_table() which is unreliable with Flask-Migrate and left the table uncreated even though alembic_version recorded phase30 as applied. This migration re-creates the table using the same raw-SQL pattern used by every other migration in this project. CREATE TABLE IF NOT EXISTS is idempotent — safe whether or not the table was partially created by the broken phase30. """ from alembic import op revision = 'phase31_device_registry' down_revision = 'phase30_device_registry' branch_labels = None depends_on = None def upgrade(): op.execute(""" CREATE TABLE IF NOT EXISTS device_registrations ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, device_id VARCHAR(64) NOT NULL, user_id INT NOT NULL, device_name VARCHAR(255) NOT NULL DEFAULT '', app_version VARCHAR(32) NOT NULL DEFAULT '', ios_version VARCHAR(32) NOT NULL DEFAULT '', registered_at DATETIME NOT NULL, last_seen_at DATETIME NOT NULL, CONSTRAINT uq_device_id UNIQUE (device_id), CONSTRAINT fk_device_reg_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 """) def downgrade(): op.execute("DROP TABLE IF EXISTS device_registrations")