"""add modbus_device and modbus_reading tables Revision ID: 20260622_09_modbus_tables Revises: 20260621_08_totp Create Date: 2026-06-22 00:00:00.000000 """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "20260622_09_modbus_tables" down_revision: Union[str, None] = "20260621_08_totp" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # modbus_device — deployment/configurable metadata for each polled device. op.create_table( "modbus_device", sa.Column("id", sa.Integer(), autoincrement=True, nullable=False), sa.Column("uuid", sa.String(length=36), nullable=False), sa.Column("friendly_name", sa.String(length=255), nullable=False), sa.Column("transport", sa.String(length=16), nullable=False), sa.Column("host", sa.String(length=255), nullable=False), sa.Column("port", sa.Integer(), nullable=False), sa.Column("unit_id", sa.Integer(), nullable=False), sa.Column("profile", sa.String(length=64), nullable=False), sa.Column("poll_interval_s", sa.Integer(), nullable=False), sa.Column("enabled", sa.Boolean(), nullable=False), sa.Column("last_poll_at", sa.DateTime(timezone=True), nullable=True), sa.Column("last_poll_ok", sa.Boolean(), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("uuid", name="uq_modbus_device_uuid"), ) # modbus_reading — generic telemetry, one row per device per poll cycle. op.create_table( "modbus_reading", sa.Column("id", sa.Integer(), autoincrement=True, nullable=False), sa.Column("device_id", sa.Integer(), nullable=False), sa.Column("recorded_at", sa.DateTime(timezone=True), nullable=False), sa.Column("payload", sa.JSON(), nullable=False), sa.ForeignKeyConstraint( ["device_id"], ["modbus_device.id"], ondelete="RESTRICT", ), sa.PrimaryKeyConstraint("id"), ) # Individual index on recorded_at (from the ORM-level index=True). op.create_index( "ix_modbus_reading_recorded_at", "modbus_reading", ["recorded_at"], unique=False, ) # Composite index for efficient time-range queries per device. op.create_index( "ix_modbus_reading_device_recorded", "modbus_reading", ["device_id", "recorded_at"], unique=False, ) def downgrade() -> None: # Drop the reading table first (it has a FK referencing modbus_device). op.drop_index("ix_modbus_reading_device_recorded", table_name="modbus_reading") op.drop_index("ix_modbus_reading_recorded_at", table_name="modbus_reading") op.drop_table("modbus_reading") # Drop the device table. op.drop_table("modbus_device")