GeoIntel release gates / Compile, test, contracts and builds (push) Successful in 1m49s
GeoIntel release gates / Python and npm vulnerability policy (push) Successful in 21s
GeoIntel release gates / Production AI image, SBOM and container scan (push) Successful in 5m39s
GeoIntel release gates / Deploy exact gated revision to Unraid (push) Failing after 58m43s
109 lines
5.4 KiB
Python
109 lines
5.4 KiB
Python
"""Initial PostGIS schema for Sprint 1 foundation."""
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from geoalchemy2 import Geometry
|
|
|
|
revision = "202601110001"
|
|
down_revision = None
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.execute("CREATE EXTENSION IF NOT EXISTS postgis")
|
|
op.execute("CREATE EXTENSION IF NOT EXISTS postgis_topology")
|
|
op.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"')
|
|
|
|
op.create_table(
|
|
"projects",
|
|
sa.Column("id", sa.UUID(as_uuid=True), primary_key=True),
|
|
sa.Column("name", sa.Text(), nullable=False),
|
|
sa.Column("description", sa.Text(), nullable=True),
|
|
sa.Column("region", sa.Text(), nullable=False, server_default="Kempen"),
|
|
sa.Column("status", sa.Text(), nullable=False, server_default="active"),
|
|
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()")),
|
|
sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()")),
|
|
)
|
|
|
|
op.create_table(
|
|
"areas",
|
|
sa.Column("id", sa.UUID(as_uuid=True), primary_key=True),
|
|
sa.Column("project_id", sa.UUID(as_uuid=True), sa.ForeignKey("projects.id", ondelete="CASCADE"), nullable=False),
|
|
sa.Column("name", sa.Text(), nullable=False),
|
|
sa.Column("geometry", Geometry("MULTIPOLYGON", srid=4326), nullable=False),
|
|
sa.Column("original_crs", sa.Text(), nullable=True),
|
|
sa.Column("area_m2", sa.Float(), nullable=True),
|
|
sa.Column("bbox", Geometry("POLYGON", srid=4326), nullable=True),
|
|
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()")),
|
|
)
|
|
|
|
op.create_table(
|
|
"datasets",
|
|
sa.Column("id", sa.UUID(as_uuid=True), primary_key=True),
|
|
sa.Column("project_id", sa.UUID(as_uuid=True), sa.ForeignKey("projects.id", ondelete="CASCADE"), nullable=False),
|
|
sa.Column("area_id", sa.UUID(as_uuid=True), sa.ForeignKey("areas.id", ondelete="SET NULL"), nullable=True),
|
|
sa.Column("name", sa.Text(), nullable=False),
|
|
sa.Column("dataset_type", sa.Text(), nullable=False),
|
|
sa.Column("source", sa.Text(), nullable=False),
|
|
sa.Column("storage_path", sa.Text(), nullable=True),
|
|
sa.Column("derived_from_dataset_id", sa.UUID(as_uuid=True), sa.ForeignKey("datasets.id", ondelete="SET NULL"), nullable=True),
|
|
sa.Column("crs", sa.Text(), nullable=True),
|
|
sa.Column("bounds_json", sa.JSON(), nullable=True),
|
|
sa.Column("resolution_json", sa.JSON(), nullable=True),
|
|
sa.Column("bands_json", sa.JSON(), nullable=True),
|
|
sa.Column("metadata_json", sa.JSON(), nullable=True),
|
|
sa.Column("status", sa.Text(), nullable=False, server_default="created"),
|
|
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()")),
|
|
sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()")),
|
|
)
|
|
|
|
op.create_table(
|
|
"dataset_versions",
|
|
sa.Column("id", sa.UUID(as_uuid=True), primary_key=True),
|
|
sa.Column("dataset_id", sa.UUID(as_uuid=True), sa.ForeignKey("datasets.id", ondelete="CASCADE"), nullable=False),
|
|
sa.Column("version", sa.Integer(), nullable=False, server_default="1"),
|
|
sa.Column("storage_path", sa.Text(), nullable=True),
|
|
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()")),
|
|
)
|
|
|
|
op.create_table(
|
|
"analysis_runs",
|
|
sa.Column("id", sa.UUID(as_uuid=True), primary_key=True),
|
|
sa.Column("project_id", sa.UUID(as_uuid=True), sa.ForeignKey("projects.id", ondelete="CASCADE"), nullable=False),
|
|
sa.Column("area_id", sa.UUID(as_uuid=True), sa.ForeignKey("areas.id", ondelete="SET NULL"), nullable=True),
|
|
sa.Column("analysis_type", sa.Text(), nullable=False),
|
|
sa.Column("status", sa.Text(), nullable=False),
|
|
sa.Column("parameters_json", sa.JSON(), nullable=False),
|
|
sa.Column("started_at", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column("finished_at", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column("error_message", sa.Text(), nullable=True),
|
|
)
|
|
|
|
op.create_table(
|
|
"exports",
|
|
sa.Column("id", sa.UUID(as_uuid=True), primary_key=True),
|
|
sa.Column("project_id", sa.UUID(as_uuid=True), sa.ForeignKey("projects.id", ondelete="CASCADE"), nullable=False),
|
|
sa.Column("analysis_run_id", sa.UUID(as_uuid=True), sa.ForeignKey("analysis_runs.id", ondelete="SET NULL"), nullable=True),
|
|
sa.Column("export_type", sa.Text(), nullable=False),
|
|
sa.Column("storage_path", sa.Text(), nullable=False),
|
|
sa.Column("metadata_json", sa.JSON(), nullable=True),
|
|
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("NOW()")),
|
|
)
|
|
|
|
op.create_index("ix_areas_geometry", "areas", ["geometry"], postgresql_using="gist")
|
|
op.create_index("ix_areas_project_id", "areas", ["project_id"])
|
|
op.create_index("ix_datasets_project_id", "datasets", ["project_id"])
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_datasets_project_id", table_name="datasets")
|
|
op.drop_index("ix_areas_project_id", table_name="areas")
|
|
op.drop_index("ix_areas_geometry", table_name="areas", postgresql_using="gist")
|
|
op.drop_table("exports")
|
|
op.drop_table("analysis_runs")
|
|
op.drop_table("dataset_versions")
|
|
op.drop_table("datasets")
|
|
op.drop_table("areas")
|
|
op.drop_table("projects")
|