"""init schema Revision ID: 0001 Revises: Create Date: 2026-07-09 """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op from geoalchemy2 import Geography from sqlalchemy.dialects import postgresql revision: str = "0001" down_revision: Union[str, None] = None branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.execute("CREATE EXTENSION IF NOT EXISTS postgis") bind = op.get_bind() place_category = postgresql.ENUM( "building", "bridge", "monument", "park", "district", "skyscraper", "cathedral", "museum", "gate", "square", name="place_category", create_type=False, ) content_language = postgresql.ENUM("ru", "en", name="content_language", create_type=False) content_length = postgresql.ENUM("short", "medium", "long", name="content_length", create_type=False) place_category.create(bind, checkfirst=True) content_language.create(bind, checkfirst=True) content_length.create(bind, checkfirst=True) op.create_table( "cities", sa.Column("id", sa.Integer(), primary_key=True), sa.Column("slug", sa.String(64), nullable=False, unique=True), sa.Column("name_ru", sa.String(128), nullable=False), sa.Column("name_en", sa.String(128), nullable=False), sa.Column("country_code", sa.String(2), nullable=False, server_default="RU"), sa.Column( "center_point", Geography(geometry_type="POINT", srid=4326, spatial_index=False), nullable=True, ), sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False), ) op.create_table( "places", sa.Column("id", sa.Integer(), primary_key=True), sa.Column("city_id", sa.Integer(), sa.ForeignKey("cities.id", ondelete="CASCADE"), nullable=False), sa.Column("slug", sa.String(128), nullable=False, unique=True), sa.Column("category", place_category, nullable=False), sa.Column( "location", Geography(geometry_type="POINT", srid=4326, spatial_index=False), nullable=False, ), sa.Column("address", sa.String(256), nullable=True), sa.Column("district", sa.String(128), nullable=True), sa.Column("built_year", sa.String(128), nullable=True), sa.Column("architect_builder", sa.String(256), nullable=True), sa.Column("architectural_style", sa.String(128), nullable=True), sa.Column("notable_people", sa.Text(), nullable=True), sa.Column("is_active", sa.Boolean(), nullable=False, server_default=sa.true()), sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False), ) op.create_index("idx_places_location_gist", "places", ["location"], postgresql_using="gist") op.create_index("idx_places_city_id", "places", ["city_id"]) op.create_table( "place_content", sa.Column("id", sa.Integer(), primary_key=True), sa.Column("place_id", sa.Integer(), sa.ForeignKey("places.id", ondelete="CASCADE"), nullable=False), sa.Column("language", content_language, nullable=False), sa.Column("length", content_length, nullable=False), sa.Column("title", sa.String(256), nullable=False), sa.Column("body", sa.Text(), nullable=False), sa.UniqueConstraint("place_id", "language", "length", name="uq_place_content_variant"), ) op.create_index("idx_place_content_lookup", "place_content", ["place_id", "language", "length"]) def downgrade() -> None: op.drop_index("idx_place_content_lookup", table_name="place_content") op.drop_table("place_content") op.drop_index("idx_places_city_id", table_name="places") op.drop_index("idx_places_location_gist", table_name="places") op.drop_table("places") op.drop_table("cities") bind = op.get_bind() postgresql.ENUM(name="content_length").drop(bind, checkfirst=True) postgresql.ENUM(name="content_language").drop(bind, checkfirst=True) postgresql.ENUM(name="place_category").drop(bind, checkfirst=True) # Deliberately not dropping the postgis extension: the postgis/postgis base # image pre-installs postgis_topology/postgis_tiger_geocoder which depend on # it, and dropping a shared extension here is out of this migration's scope.