"""add discovery metadata to worlds and create world_visits Revision ID: 0003_add_discovery_metadata Revises: 0002_add_date_of_birth_to_users Create Date: 2025-01-02 00:00:00.000000 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision: str = "0003_add_discovery_metadata" down_revision: Union[str, None] = "0002_add_date_of_birth_to_users" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: """Add discovery metadata columns to worlds and create world_visits.""" # Add discovery metadata columns to worlds. op.add_column( "worlds", sa.Column("category", sa.String(length=100), nullable=True), ) op.add_column( "worlds", sa.Column( "tags", postgresql.ARRAY(sa.String()), nullable=True, server_default="{}", ), ) op.add_column( "worlds", sa.Column("play_count", sa.Integer(), nullable=False, server_default="0"), ) op.add_column( "worlds", sa.Column("last_played_at", sa.DateTime(timezone=True), nullable=True), ) # B-tree index on category, GIN index on tags. op.create_index( "ix_worlds_category", "worlds", ["category"], unique=False, ) op.create_index( "ix_worlds_tags", "worlds", ["tags"], unique=False, postgresql_using="gin", ) # Create world_visits table. op.create_table( "world_visits", sa.Column("id", sa.Integer(), primary_key=True), sa.Column("world_id", sa.Integer(), nullable=False), sa.Column("user_id", sa.Integer(), nullable=True), sa.Column("anonymous_token", sa.String(length=255), nullable=True), sa.Column( "visited_at", sa.DateTime(timezone=True), server_default=sa.func.now(), ), sa.ForeignKeyConstraint( ["world_id"], ["worlds.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint( ["user_id"], ["users.id"], ondelete="CASCADE" ), ) op.create_index( op.f("ix_world_visits_id"), "world_visits", ["id"], unique=False ) op.create_index( "ix_world_visits_world_id_visited_at", "world_visits", ["world_id", "visited_at"], unique=False, ) def downgrade() -> None: """Drop world_visits and discovery metadata columns from worlds.""" op.drop_index( "ix_world_visits_world_id_visited_at", table_name="world_visits" ) op.drop_index(op.f("ix_world_visits_id"), table_name="world_visits") op.drop_table("world_visits") op.drop_index("ix_worlds_tags", table_name="worlds") op.drop_index("ix_worlds_category", table_name="worlds") op.drop_column("worlds", "last_played_at") op.drop_column("worlds", "play_count") op.drop_column("worlds", "tags") op.drop_column("worlds", "category")