"""one row per vision execution, and camera as an input method The vision surroundings do not go on `measurements`: statistics and the export read that table on every pass. And it would be wrong modelling anyway - one acquisition produces N quotes, and image, overlay, device and engine version are the same for all of them. Revision ID: 012_vision_results Revises: 011_vision_graph Create Date: 2026-08-16 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa revision: str = '012_vision_results' down_revision: Union[str, None] = '011_vision_graph' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None OLD_METHODS = ('usb_caliper', 'manual') NEW_METHODS = ('usb_caliper', 'manual', 'camera') def upgrade() -> None: op.create_table( 'vision_results', sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True), sa.Column('task_id', sa.Integer(), sa.ForeignKey('recipe_tasks.id'), nullable=False, index=True), sa.Column('image_path', sa.String(length=500), nullable=True), sa.Column('overlay_path', sa.String(length=500), nullable=True), sa.Column('engine_version', sa.String(length=64), nullable=False), sa.Column('executed_on', sa.Enum('server', 'station', name='vision_executed_on_enum'), nullable=False), sa.Column('station_id', sa.Integer(), sa.ForeignKey('stations.id'), nullable=True), sa.Column('device_code', sa.String(length=100), nullable=True), sa.Column('calibration_snapshot', sa.JSON(), nullable=True), sa.Column('graph_snapshot', sa.JSON(), nullable=False), sa.Column('duration_ms', sa.Integer(), nullable=True), sa.Column('executed_at', sa.DateTime(), nullable=False, server_default=sa.func.now()), mysql_engine='InnoDB', mysql_charset='utf8mb4', ) with op.batch_alter_table('measurements') as batch: batch.alter_column( 'input_method', existing_type=sa.Enum(*OLD_METHODS, name='input_method_enum'), type_=sa.Enum(*NEW_METHODS, name='input_method_enum'), existing_nullable=False, ) batch.add_column( sa.Column('vision_result_id', sa.Integer(), nullable=True) ) batch.create_foreign_key( 'fk_measurements_vision_result', 'vision_results', ['vision_result_id'], ['id'], ) def downgrade() -> None: with op.batch_alter_table('measurements') as batch: batch.drop_constraint('fk_measurements_vision_result', type_='foreignkey') batch.drop_column('vision_result_id') batch.alter_column( 'input_method', existing_type=sa.Enum(*NEW_METHODS, name='input_method_enum'), type_=sa.Enum(*OLD_METHODS, name='input_method_enum'), existing_nullable=False, ) op.drop_table('vision_results')