diff --git a/database/base.py b/database/base.py index fa249ae..d2e1241 100644 --- a/database/base.py +++ b/database/base.py @@ -1,10 +1,10 @@ import uuid from datetime import datetime -from typing import Dict, List, Optional +from typing import Any, Dict, List, Optional from geoalchemy2 import Geometry from shapely.geometry import MultiLineString, MultiPoint, MultiPolygon -from sqlalchemy import ForeignKey +from sqlalchemy import ForeignKey, Index from sqlalchemy.dialects.postgresql import JSONB, NUMRANGE, UUID, Range from sqlalchemy.orm import ( DeclarativeBase, @@ -56,7 +56,7 @@ class VersionedBase(Base): """ __abstract__ = True - __table_args__ = {"schema": "hame"} + __table_args__: Any = {"schema": "hame"} # Go figure. We have to *explicitly state* id is a mapped column, because id will # have to be defined inside all the subclasses for relationship remote_side @@ -152,11 +152,24 @@ class PlanObjectBase(PlanBase): __abstract__ = True + @declared_attr.directive + @classmethod + def __table_args__(cls): + return ( + Index( + f"ix_{cls.__tablename__}_plan_id_ordering", + "plan_id", + "ordering", + unique=True, + ), + PlanBase.__table_args__, + ) + description: Mapped[language_str] source_data_object: Mapped[str] = mapped_column(nullable=True) height_range: Mapped[numeric_range] height_unit: Mapped[str] = mapped_column(nullable=True) - ordering: Mapped[Optional[int]] = mapped_column(index=True) + ordering: Mapped[Optional[int]] type_of_underground_id: Mapped[uuid.UUID] = mapped_column( ForeignKey("codes.type_of_underground.id", name="type_of_underground_id_fkey"), index=True, diff --git a/database/migrations/versions/2024_12_02_1351-09f44e0e7110_ordering_index_fixes.py b/database/migrations/versions/2024_12_02_1351-09f44e0e7110_ordering_index_fixes.py new file mode 100644 index 0000000..4b2fd71 --- /dev/null +++ b/database/migrations/versions/2024_12_02_1351-09f44e0e7110_ordering_index_fixes.py @@ -0,0 +1,206 @@ +"""ordering index fixes + +Revision ID: 09f44e0e7110 +Revises: 4e3c0868ea98 +Create Date: 2024-12-02 13:51:55.645788 + +""" +from typing import Sequence, Union + +import geoalchemy2 +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "09f44e0e7110" +down_revision: Union[str, None] = "4e3c0868ea98" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index( + "ix_hame_land_use_area_ordering", + table_name="land_use_area", + schema="hame", + ) + op.create_index( + "ix_land_use_area_plan_id_ordering", + "land_use_area", + ["plan_id", "ordering"], + unique=True, + schema="hame", + ) + op.drop_index( + "ix_hame_land_use_point_ordering", + table_name="land_use_point", + schema="hame", + ) + op.create_index( + "ix_land_use_point_plan_id_ordering", + "land_use_point", + ["plan_id", "ordering"], + unique=True, + schema="hame", + ) + op.drop_index("ix_hame_line_ordering", table_name="line", schema="hame") + op.create_index( + "ix_line_plan_id_ordering", + "line", + ["plan_id", "ordering"], + unique=True, + schema="hame", + ) + op.drop_index("ix_hame_other_area_ordering", table_name="other_area", schema="hame") + op.create_index( + "ix_other_area_plan_id_ordering", + "other_area", + ["plan_id", "ordering"], + unique=True, + schema="hame", + ) + op.drop_index( + "ix_hame_other_point_ordering", table_name="other_point", schema="hame" + ) + op.create_index( + "ix_other_point_plan_id_ordering", + "other_point", + ["plan_id", "ordering"], + unique=True, + schema="hame", + ) + op.drop_index( + "ix_hame_plan_proposition_ordering", + table_name="plan_proposition", + schema="hame", + ) + op.create_index( + "ix_plan_proposition_plan_regulation_group_id_ordering", + "plan_proposition", + ["plan_regulation_group_id", "ordering"], + unique=False, + schema="hame", + ) + op.drop_index( + "ix_hame_plan_regulation_ordering", + table_name="plan_regulation", + schema="hame", + ) + op.create_index( + "ix_plan_regulation_plan_regulation_group_id_ordering", + "plan_regulation", + ["plan_regulation_group_id", "ordering"], + unique=True, + schema="hame", + ) + op.drop_index( + "ix_hame_plan_regulation_group_ordering", + table_name="plan_regulation_group", + schema="hame", + ) + op.create_index( + "ix_plan_regulation_group_plan_id_ordering", + "plan_regulation_group", + ["plan_id", "ordering"], + unique=False, + schema="hame", + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index( + "ix_plan_regulation_group_plan_id_ordering", + table_name="plan_regulation_group", + schema="hame", + ) + op.create_index( + "ix_hame_plan_regulation_group_ordering", + "plan_regulation_group", + ["ordering"], + unique=False, + schema="hame", + ) + op.drop_index( + "ix_plan_regulation_plan_regulation_group_id_ordering", + table_name="plan_regulation", + schema="hame", + ) + op.create_index( + "ix_hame_plan_regulation_ordering", + "plan_regulation", + ["ordering"], + unique=False, + schema="hame", + ) + op.drop_index( + "ix_plan_proposition_plan_regulation_group_id_ordering", + table_name="plan_proposition", + schema="hame", + ) + op.create_index( + "ix_hame_plan_proposition_ordering", + "plan_proposition", + ["ordering"], + unique=False, + schema="hame", + ) + op.drop_index( + "ix_other_point_plan_id_ordering", + table_name="other_point", + schema="hame", + ) + op.create_index( + "ix_hame_other_point_ordering", + "other_point", + ["ordering"], + unique=False, + schema="hame", + ) + op.drop_index( + "ix_other_area_plan_id_ordering", + table_name="other_area", + schema="hame", + ) + op.create_index( + "ix_hame_other_area_ordering", + "other_area", + ["ordering"], + unique=False, + schema="hame", + ) + op.drop_index("ix_line_plan_id_ordering", table_name="line", schema="hame") + op.create_index( + "ix_hame_line_ordering", + "line", + ["ordering"], + unique=False, + schema="hame", + ) + op.drop_index( + "ix_land_use_point_plan_id_ordering", + table_name="land_use_point", + schema="hame", + ) + op.create_index( + "ix_hame_land_use_point_ordering", + "land_use_point", + ["ordering"], + unique=False, + schema="hame", + ) + op.drop_index( + "ix_land_use_area_plan_id_ordering", + table_name="land_use_area", + schema="hame", + ) + op.create_index( + "ix_hame_land_use_area_ordering", + "land_use_area", + ["ordering"], + unique=False, + schema="hame", + ) + # ### end Alembic commands ### diff --git a/database/models.py b/database/models.py index 99f5fe9..86e7d6b 100644 --- a/database/models.py +++ b/database/models.py @@ -15,7 +15,7 @@ unique_str, ) from shapely.geometry import MultiLineString, MultiPoint, MultiPolygon -from sqlalchemy import Column, ForeignKey, Table, Uuid +from sqlalchemy import Column, ForeignKey, Index, Table, Uuid from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql import func @@ -193,6 +193,10 @@ class PlanRegulationGroup(VersionedBase): """ __tablename__ = "plan_regulation_group" + __table_args__ = ( + Index("ix_plan_regulation_group_plan_id_ordering", "plan_id", "ordering"), + VersionedBase.__table_args__, + ) short_name: Mapped[unique_str] name: Mapped[language_str] @@ -209,7 +213,7 @@ class PlanRegulationGroup(VersionedBase): ) plan: Mapped["Plan"] = relationship() - ordering: Mapped[Optional[int]] = mapped_column(index=True) + ordering: Mapped[Optional[int]] # värikoodi? type_of_plan_regulation_group_id: Mapped[uuid.UUID] = mapped_column( @@ -292,6 +296,15 @@ class PlanRegulation(PlanBase): """ __tablename__ = "plan_regulation" + __table_args__ = ( + Index( + "ix_plan_regulation_plan_regulation_group_id_ordering", + "plan_regulation_group_id", + "ordering", + unique=True, + ), + PlanBase.__table_args__, + ) plan_regulation_group_id: Mapped[uuid.UUID] = mapped_column( ForeignKey( @@ -446,7 +459,7 @@ class PlanRegulation(PlanBase): unit: Mapped[str] = mapped_column(nullable=True) text_value: Mapped[language_str] numeric_value: Mapped[float] = mapped_column(nullable=True) - ordering: Mapped[Optional[int]] = mapped_column(index=True) + ordering: Mapped[Optional[int]] class PlanProposition(PlanBase): @@ -455,6 +468,14 @@ class PlanProposition(PlanBase): """ __tablename__ = "plan_proposition" + __table_args__ = ( + Index( + "ix_plan_proposition_plan_regulation_group_id_ordering", + "plan_regulation_group_id", + "ordering", + ), + PlanBase.__table_args__, + ) plan_regulation_group_id: Mapped[uuid.UUID] = mapped_column( ForeignKey( @@ -471,7 +492,7 @@ class PlanProposition(PlanBase): # Let's load all the codes for objects joined. plan_theme = relationship("PlanTheme", backref="plan_propositions", lazy="joined") text_value: Mapped[language_str] - ordering: Mapped[Optional[int]] = mapped_column(index=True) + ordering: Mapped[Optional[int]] class SourceData(VersionedBase):