Files
geointel/artifacts/evidence/accuracy/P1/alembic-offline-upgrade.sql
T

501 lines
20 KiB
PL/PgSQL

-- command=python -m alembic upgrade head --sql
-- exit_code=0
-- captured_at=2026-08-01T18:37:24.0299035+02:00
BEGIN;
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Generating static SQL
INFO [alembic.runtime.migration] Will assume transactional DDL.
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
INFO [alembic.runtime.migration] Running upgrade -> 202601110001, Initial PostGIS schema for Sprint 1 foundation.
-- Running upgrade -> 202601110001
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS postgis_topology;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE projects (
id UUID NOT NULL,
name TEXT NOT NULL,
description TEXT,
region TEXT DEFAULT 'Kempen' NOT NULL,
status TEXT DEFAULT 'active' NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
PRIMARY KEY (id)
);
CREATE TABLE areas (
id UUID NOT NULL,
project_id UUID NOT NULL,
name TEXT NOT NULL,
geometry geometry(MULTIPOLYGON,4326) NOT NULL,
original_crs TEXT,
area_m2 FLOAT,
bbox geometry(POLYGON,4326),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
PRIMARY KEY (id),
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE
);
CREATE INDEX idx_areas_geometry ON areas USING gist (geometry);
CREATE INDEX idx_areas_bbox ON areas USING gist (bbox);
CREATE TABLE datasets (
id UUID NOT NULL,
project_id UUID NOT NULL,
area_id UUID,
name TEXT NOT NULL,
dataset_type TEXT NOT NULL,
source TEXT NOT NULL,
storage_path TEXT,
derived_from_dataset_id UUID,
crs TEXT,
bounds_json JSON,
resolution_json JSON,
bands_json JSON,
metadata_json JSON,
status TEXT DEFAULT 'created' NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
PRIMARY KEY (id),
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY(area_id) REFERENCES areas (id) ON DELETE SET NULL,
FOREIGN KEY(derived_from_dataset_id) REFERENCES datasets (id) ON DELETE SET NULL
);
CREATE TABLE dataset_versions (
id UUID NOT NULL,
dataset_id UUID NOT NULL,
version INTEGER DEFAULT '1' NOT NULL,
storage_path TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
PRIMARY KEY (id),
FOREIGN KEY(dataset_id) REFERENCES datasets (id) ON DELETE CASCADE
);
CREATE TABLE analysis_runs (
id UUID NOT NULL,
project_id UUID NOT NULL,
area_id UUID,
analysis_type TEXT NOT NULL,
status TEXT NOT NULL,
parameters_json JSON NOT NULL,
started_at TIMESTAMP WITH TIME ZONE,
finished_at TIMESTAMP WITH TIME ZONE,
error_message TEXT,
PRIMARY KEY (id),
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY(area_id) REFERENCES areas (id) ON DELETE SET NULL
);
CREATE TABLE exports (
id UUID NOT NULL,
project_id UUID NOT NULL,
analysis_run_id UUID,
export_type TEXT NOT NULL,
storage_path TEXT NOT NULL,
metadata_json JSON,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
PRIMARY KEY (id),
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY(analysis_run_id) REFERENCES analysis_runs (id) ON DELETE SET NULL
);
CREATE INDEX ix_areas_geometry ON areas USING gist (geometry);
CREATE INDEX ix_areas_project_id ON areas (project_id);
CREATE INDEX ix_datasets_project_id ON datasets (project_id);
INSERT INTO alembic_version (version_num) VALUES ('202601110001') RETURNING alembic_version.version_num;
INFO [alembic.runtime.migration] Running upgrade 202601110001 -> 202601120001, Add dataset storage metadata columns.
-- Running upgrade 202601110001 -> 202601120001
ALTER TABLE datasets ADD COLUMN original_filename TEXT;
ALTER TABLE datasets ADD COLUMN stored_filename TEXT;
ALTER TABLE datasets ADD COLUMN content_type TEXT;
ALTER TABLE datasets ADD COLUMN size_bytes INTEGER;
ALTER TABLE datasets ADD COLUMN checksum_sha256 TEXT;
ALTER TABLE datasets ALTER COLUMN status SET DEFAULT 'uploaded';
UPDATE alembic_version SET version_num='202601120001' WHERE alembic_version.version_num = '202601110001';
INFO [alembic.runtime.migration] Running upgrade 202601120001 -> 20260611212435, Add lightweight job table for sprint-3 async architecture foundation.
-- Running upgrade 202601120001 -> 20260611212435
CREATE TABLE jobs (
id UUID NOT NULL,
job_type TEXT NOT NULL,
status TEXT DEFAULT 'queued' NOT NULL,
project_id UUID NOT NULL,
dataset_id UUID,
input_dataset_id UUID,
output_dataset_id UUID,
parameters_json JSON NOT NULL,
result_json JSON,
error_message TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
started_at TIMESTAMP WITH TIME ZONE,
finished_at TIMESTAMP WITH TIME ZONE,
PRIMARY KEY (id),
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY(dataset_id) REFERENCES datasets (id) ON DELETE SET NULL,
FOREIGN KEY(input_dataset_id) REFERENCES datasets (id) ON DELETE SET NULL,
FOREIGN KEY(output_dataset_id) REFERENCES datasets (id) ON DELETE SET NULL
);
CREATE INDEX ix_jobs_project_id ON jobs (project_id);
CREATE INDEX ix_jobs_status ON jobs (status);
UPDATE alembic_version SET version_num='20260611212435' WHERE alembic_version.version_num = '202601120001';
INFO [alembic.runtime.migration] Running upgrade 20260611212435 -> 202606120001, Add dataset reference and provenance metadata columns.
-- Running upgrade 20260611212435 -> 202606120001
ALTER TABLE datasets ADD COLUMN dataset_role TEXT DEFAULT 'source' NOT NULL;
ALTER TABLE datasets ADD COLUMN source_name TEXT;
ALTER TABLE datasets ADD COLUMN reference_layer_name TEXT;
ALTER TABLE datasets ADD COLUMN source_metadata JSON;
ALTER TABLE datasets ADD COLUMN provenance_metadata JSON;
ALTER TABLE datasets ADD COLUMN imported_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL;
UPDATE alembic_version SET version_num='202606120001' WHERE alembic_version.version_num = '20260611212435';
INFO [alembic.runtime.migration] Running upgrade 202606120001 -> 202606120700, Add Sprint 7A vector feature and QA persistence foundation.
-- Running upgrade 202606120001 -> 202606120700
CREATE TABLE vector_features (
id UUID NOT NULL,
dataset_id UUID NOT NULL,
feature_class TEXT,
source_feature_id TEXT,
properties_json JSON,
geometry geometry(GEOMETRY,4326) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
PRIMARY KEY (id),
FOREIGN KEY(dataset_id) REFERENCES datasets (id) ON DELETE CASCADE
);
CREATE INDEX ix_vector_features_dataset_id ON vector_features (dataset_id);
CREATE INDEX ix_vector_features_geometry ON vector_features USING gist (geometry);
CREATE TABLE quality_checks (
id UUID NOT NULL,
project_id UUID NOT NULL,
job_id UUID,
analysis_run_id UUID,
candidate_dataset_id UUID,
reference_dataset_id UUID NOT NULL,
check_type TEXT NOT NULL,
status TEXT NOT NULL,
score FLOAT,
parameters_json JSON,
findings_json JSON,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
completed_at TIMESTAMP WITH TIME ZONE,
PRIMARY KEY (id),
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY(job_id) REFERENCES jobs (id) ON DELETE SET NULL,
FOREIGN KEY(analysis_run_id) REFERENCES analysis_runs (id) ON DELETE SET NULL,
FOREIGN KEY(candidate_dataset_id) REFERENCES datasets (id) ON DELETE SET NULL,
FOREIGN KEY(reference_dataset_id) REFERENCES datasets (id) ON DELETE CASCADE
);
CREATE INDEX ix_quality_checks_project_id ON quality_checks (project_id);
CREATE INDEX ix_quality_checks_reference_dataset_id ON quality_checks (reference_dataset_id);
CREATE INDEX ix_quality_checks_candidate_dataset_id ON quality_checks (candidate_dataset_id);
CREATE INDEX ix_quality_checks_analysis_run_id ON quality_checks (analysis_run_id);
CREATE TABLE metrics (
id UUID NOT NULL,
quality_check_id UUID,
analysis_run_id UUID,
metric_key TEXT NOT NULL,
metric_value FLOAT,
metric_unit TEXT,
label TEXT,
metadata_json JSON,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
PRIMARY KEY (id),
FOREIGN KEY(quality_check_id) REFERENCES quality_checks (id) ON DELETE CASCADE,
FOREIGN KEY(analysis_run_id) REFERENCES analysis_runs (id) ON DELETE SET NULL
);
CREATE INDEX ix_metrics_quality_check_id ON metrics (quality_check_id);
CREATE INDEX ix_metrics_analysis_run_id ON metrics (analysis_run_id);
UPDATE alembic_version SET version_num='202606120700' WHERE alembic_version.version_num = '202606120001';
INFO [alembic.runtime.migration] Running upgrade 202606120700 -> 202606120800, Add Sprint 8 detection foundation.
-- Running upgrade 202606120700 -> 202606120800
ALTER TABLE analysis_runs ADD COLUMN dataset_id UUID;
ALTER TABLE analysis_runs ADD FOREIGN KEY(dataset_id) REFERENCES datasets (id) ON DELETE SET NULL;
ALTER TABLE analysis_runs ADD COLUMN job_id UUID;
ALTER TABLE analysis_runs ADD FOREIGN KEY(job_id) REFERENCES jobs (id) ON DELETE SET NULL;
ALTER TABLE analysis_runs ADD COLUMN model_name VARCHAR(255);
ALTER TABLE analysis_runs ADD COLUMN model_version VARCHAR(120);
ALTER TABLE analysis_runs ADD COLUMN result_json JSON;
ALTER TABLE analysis_runs ADD COLUMN created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL;
CREATE TABLE detections (
id UUID NOT NULL,
project_id UUID NOT NULL,
dataset_id UUID,
analysis_run_id UUID,
job_id UUID,
model_name VARCHAR(255) NOT NULL,
model_version VARCHAR(120),
class_name VARCHAR(120) NOT NULL,
confidence FLOAT NOT NULL,
geometry geometry(GEOMETRY,4326) NOT NULL,
bbox_json JSON,
source_tile_path VARCHAR(500),
properties_json JSON,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY(dataset_id) REFERENCES datasets (id) ON DELETE SET NULL,
FOREIGN KEY(analysis_run_id) REFERENCES analysis_runs (id) ON DELETE SET NULL,
FOREIGN KEY(job_id) REFERENCES jobs (id) ON DELETE SET NULL
);
CREATE INDEX ix_detections_project_id ON detections (project_id);
CREATE INDEX ix_detections_dataset_id ON detections (dataset_id);
CREATE INDEX ix_detections_analysis_run_id ON detections (analysis_run_id);
CREATE INDEX ix_detections_class_name ON detections (class_name);
CREATE INDEX ix_detections_geometry ON detections USING gist (geometry);
UPDATE alembic_version SET version_num='202606120800' WHERE alembic_version.version_num = '202606120700';
INFO [alembic.runtime.migration] Running upgrade 202606120800 -> 202606120900, Add Sprint 9 segmentation foundation.
-- Running upgrade 202606120800 -> 202606120900
CREATE TABLE segmentations (
id UUID NOT NULL,
project_id UUID NOT NULL,
dataset_id UUID,
job_id UUID,
analysis_run_id UUID,
model_name VARCHAR(255) NOT NULL,
model_version VARCHAR(120),
class_name VARCHAR(120) NOT NULL,
confidence FLOAT,
geometry geometry(MULTIPOLYGON,4326) NOT NULL,
bbox_json JSON,
area_m2 FLOAT,
mask_path TEXT,
source_tile_path VARCHAR(500),
tile_index INTEGER,
properties_json JSON,
provenance_json JSON,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY(dataset_id) REFERENCES datasets (id) ON DELETE SET NULL,
FOREIGN KEY(job_id) REFERENCES jobs (id) ON DELETE SET NULL,
FOREIGN KEY(analysis_run_id) REFERENCES analysis_runs (id) ON DELETE SET NULL
);
CREATE INDEX ix_segmentations_project_id ON segmentations (project_id);
CREATE INDEX ix_segmentations_dataset_id ON segmentations (dataset_id);
CREATE INDEX ix_segmentations_analysis_run_id ON segmentations (analysis_run_id);
CREATE INDEX ix_segmentations_job_id ON segmentations (job_id);
CREATE INDEX ix_segmentations_class_name ON segmentations (class_name);
CREATE INDEX ix_segmentations_geometry ON segmentations USING gist (geometry);
UPDATE alembic_version SET version_num='202606120900' WHERE alembic_version.version_num = '202606120800';
INFO [alembic.runtime.migration] Running upgrade 202606120900 -> 202607140001, Add temporal dataset metadata and durable dataset-version provenance.
-- Running upgrade 202606120900 -> 202607140001
ALTER TABLE datasets ADD COLUMN temporal_series_key VARCHAR(255);
ALTER TABLE datasets ADD COLUMN observed_at TIMESTAMP WITH TIME ZONE;
ALTER TABLE datasets ADD COLUMN valid_from TIMESTAMP WITH TIME ZONE;
ALTER TABLE datasets ADD COLUMN valid_to TIMESTAMP WITH TIME ZONE;
ALTER TABLE datasets ADD COLUMN temporal_granularity VARCHAR(32);
ALTER TABLE datasets ADD COLUMN source_version VARCHAR(120);
ALTER TABLE dataset_versions ADD COLUMN source_version VARCHAR(120);
ALTER TABLE dataset_versions ADD COLUMN observed_at TIMESTAMP WITH TIME ZONE;
ALTER TABLE dataset_versions ADD COLUMN valid_from TIMESTAMP WITH TIME ZONE;
ALTER TABLE dataset_versions ADD COLUMN valid_to TIMESTAMP WITH TIME ZONE;
ALTER TABLE dataset_versions ADD COLUMN checksum_sha256 VARCHAR(64);
ALTER TABLE dataset_versions ADD COLUMN source_metadata JSON;
ALTER TABLE dataset_versions ADD COLUMN provenance_metadata JSON;
CREATE INDEX ix_datasets_project_temporal_series_observed ON datasets (project_id, temporal_series_key, observed_at);
CREATE UNIQUE INDEX ix_dataset_versions_dataset_version ON dataset_versions (dataset_id, version);
CREATE INDEX ix_vector_features_dataset_source_feature ON vector_features (dataset_id, source_feature_id);
ALTER TABLE datasets ADD CONSTRAINT ck_datasets_temporal_valid_range CHECK (valid_to IS NULL OR valid_from IS NULL OR valid_to >= valid_from);
ALTER TABLE dataset_versions ADD CONSTRAINT ck_dataset_versions_temporal_valid_range CHECK (valid_to IS NULL OR valid_from IS NULL OR valid_to >= valid_from);
UPDATE alembic_version SET version_num='202607140001' WHERE alembic_version.version_num = '202606120900';
INFO [alembic.runtime.migration] Running upgrade 202607140001 -> 202607150001, Add durable operator review decisions for detection QA evidence.
-- Running upgrade 202607140001 -> 202607150001
CREATE TABLE detection_reviews (
id UUID NOT NULL,
project_id UUID NOT NULL,
quality_check_id UUID NOT NULL,
analysis_run_id UUID,
evidence_role VARCHAR(32) NOT NULL,
evidence_feature_id VARCHAR(255) NOT NULL,
detection_id UUID,
reference_feature_id UUID,
decision VARCHAR(64) DEFAULT 'unreviewed' NOT NULL,
notes TEXT,
reviewed_by VARCHAR(120) DEFAULT 'operator' NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
PRIMARY KEY (id),
CONSTRAINT ck_detection_reviews_evidence_role CHECK (evidence_role IN ('false_positive', 'false_negative')),
CONSTRAINT ck_detection_reviews_decision CHECK (decision IN ('confirmed_model_false_positive', 'confirmed_model_false_negative', 'reference_gap_or_change', 'qa_alignment_mismatch', 'imagery_obscured_or_uncertain', 'uncertain', 'unreviewed')),
FOREIGN KEY(analysis_run_id) REFERENCES analysis_runs (id) ON DELETE SET NULL,
FOREIGN KEY(detection_id) REFERENCES detections (id) ON DELETE SET NULL,
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY(quality_check_id) REFERENCES quality_checks (id) ON DELETE CASCADE,
FOREIGN KEY(reference_feature_id) REFERENCES vector_features (id) ON DELETE SET NULL,
CONSTRAINT uq_detection_reviews_evidence UNIQUE (quality_check_id, evidence_role, evidence_feature_id)
);
CREATE INDEX ix_detection_reviews_project_id ON detection_reviews (project_id);
CREATE INDEX ix_detection_reviews_quality_check_id ON detection_reviews (quality_check_id);
CREATE INDEX ix_detection_reviews_analysis_run_id ON detection_reviews (analysis_run_id);
CREATE INDEX ix_detection_reviews_decision ON detection_reviews (decision);
UPDATE alembic_version SET version_num='202607150001' WHERE alembic_version.version_num = '202607140001';
INFO [alembic.runtime.migration] Running upgrade 202607150001 -> 202607160001, Index partitioned vector features by dataset and municipality.
-- Running upgrade 202607150001 -> 202607160001
CREATE INDEX ix_vector_features_dataset_municipality ON vector_features (dataset_id, (properties_json ->> 'municipality'));
UPDATE alembic_version SET version_num='202607160001' WHERE alembic_version.version_num = '202607150001';
INFO [alembic.runtime.migration] Running upgrade 202607160001 -> 202607260001, Add resumable AOI parent and partition operations.
-- Running upgrade 202607160001 -> 202607260001
CREATE TABLE aoi_operations (
id UUID NOT NULL,
project_id UUID NOT NULL,
area_id UUID,
parent_job_id UUID,
operation_type VARCHAR(128) NOT NULL,
status VARCHAR(32) NOT NULL,
geometry geometry(MULTIPOLYGON,4326) NOT NULL,
request_json JSON NOT NULL,
plan_json JSON NOT NULL,
result_json JSON,
error_message TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
started_at TIMESTAMP WITH TIME ZONE,
finished_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
PRIMARY KEY (id),
CONSTRAINT ck_aoi_operations_status CHECK (status IN ('queued', 'running', 'partial', 'success', 'failed', 'cancelled')),
FOREIGN KEY(project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY(area_id) REFERENCES areas (id) ON DELETE SET NULL,
FOREIGN KEY(parent_job_id) REFERENCES jobs (id) ON DELETE SET NULL
);
CREATE INDEX ix_aoi_operations_project_status ON aoi_operations (project_id, status);
CREATE INDEX ix_aoi_operations_geometry ON aoi_operations USING gist (geometry);
CREATE TABLE aoi_operation_partitions (
id UUID NOT NULL,
operation_id UUID NOT NULL,
child_job_id UUID,
partition_key VARCHAR(255) NOT NULL,
provider_key VARCHAR(120) NOT NULL,
product_key VARCHAR(120) NOT NULL,
ordinal INTEGER NOT NULL,
status VARCHAR(32) NOT NULL,
geometry geometry(MULTIPOLYGON,4326) NOT NULL,
attempt_count INTEGER DEFAULT '0' NOT NULL,
max_attempts INTEGER DEFAULT '3' NOT NULL,
checkpoint_json JSON,
result_json JSON,
error_message TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
started_at TIMESTAMP WITH TIME ZONE,
finished_at TIMESTAMP WITH TIME ZONE,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
PRIMARY KEY (id),
CONSTRAINT ck_aoi_operation_partitions_status CHECK (status IN ('queued', 'running', 'success', 'failed', 'skipped')),
CONSTRAINT uq_aoi_operation_partition_key UNIQUE (operation_id, partition_key),
FOREIGN KEY(operation_id) REFERENCES aoi_operations (id) ON DELETE CASCADE,
FOREIGN KEY(child_job_id) REFERENCES jobs (id) ON DELETE SET NULL
);
CREATE INDEX ix_aoi_operation_partitions_operation_status ON aoi_operation_partitions (operation_id, status);
CREATE INDEX ix_aoi_operation_partitions_geometry ON aoi_operation_partitions USING gist (geometry);
UPDATE alembic_version SET version_num='202607260001' WHERE alembic_version.version_num = '202607160001';
COMMIT;