diff --git a/server/infrastructure/catalog_records/repositories.py b/server/infrastructure/catalog_records/repositories.py index ecab6631..e0030ac5 100644 --- a/server/infrastructure/catalog_records/repositories.py +++ b/server/infrastructure/catalog_records/repositories.py @@ -1,7 +1,7 @@ import datetime as dt from typing import TYPE_CHECKING, Optional -from sqlalchemy import Column, DateTime, ForeignKey, func, select +from sqlalchemy import Column, DateTime, func, select from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.exc import NoResultFound from sqlalchemy.orm import relationship @@ -20,13 +20,14 @@ class CatalogRecordModel(Base): __tablename__ = "catalog_record" id: ID = Column(UUID(as_uuid=True), primary_key=True) - dataset_id: ID = Column(UUID(as_uuid=True), ForeignKey("dataset.id")) + created_at: dt.datetime = Column( + DateTime(timezone=True), server_default=func.clock_timestamp(), nullable=False + ) + dataset: "DatasetModel" = relationship( "DatasetModel", back_populates="catalog_record", - ) - created_at: dt.datetime = Column( - DateTime(timezone=True), server_default=func.clock_timestamp(), nullable=False + cascade="delete", ) diff --git a/server/infrastructure/datasets/models.py b/server/infrastructure/datasets/models.py index e2adceca..137d3258 100644 --- a/server/infrastructure/datasets/models.py +++ b/server/infrastructure/datasets/models.py @@ -49,11 +49,15 @@ class DatasetModel(Base): id: uuid.UUID = Column(UUID(as_uuid=True), primary_key=True) + catalog_record_id: uuid.UUID = Column( + UUID(as_uuid=True), + ForeignKey("catalog_record.id", ondelete="CASCADE"), + nullable=False, + ) catalog_record: "CatalogRecordModel" = relationship( "CatalogRecordModel", back_populates="dataset", cascade="delete", - lazy="joined", uselist=False, ) diff --git a/server/infrastructure/datasets/repositories.py b/server/infrastructure/datasets/repositories.py index 69482456..2d82b401 100644 --- a/server/infrastructure/datasets/repositories.py +++ b/server/infrastructure/datasets/repositories.py @@ -2,7 +2,7 @@ from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy.orm import selectinload +from sqlalchemy.orm import contains_eager, selectinload from server.domain.common.pagination import Page from server.domain.common.types import ID @@ -48,8 +48,10 @@ async def _maybe_get_by_id( ) -> Optional[DatasetModel]: stmt = ( select(DatasetModel) + .join(DatasetModel.catalog_record) .where(DatasetModel.id == id) .options( + contains_eager(DatasetModel.catalog_record), selectinload(DatasetModel.formats), selectinload(DatasetModel.tags), ) diff --git a/server/migrations/versions/da164fd0fa6f_swap_dataset_catalog_record_fk.py b/server/migrations/versions/da164fd0fa6f_swap_dataset_catalog_record_fk.py new file mode 100644 index 00000000..78f60659 --- /dev/null +++ b/server/migrations/versions/da164fd0fa6f_swap_dataset_catalog_record_fk.py @@ -0,0 +1,74 @@ +"""swap-dataset-catalog_record-fk + +Revision ID: da164fd0fa6f +Revises: d9ea6ea6708f +Create Date: 2022-07-19 16:25:43.333190 + +""" +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = "da164fd0fa6f" +down_revision = "d9ea6ea6708f" +branch_labels = None +depends_on = None + + +def upgrade(): + # Drop old FK constraint. + op.drop_constraint( + "catalog_record_dataset_id_fkey", + "catalog_record", + type_="foreignkey", + ) + + # Add and fill new FK column and constraint. + op.add_column( + "dataset", + sa.Column("catalog_record_id", postgresql.UUID(as_uuid=True)), + ) + op.execute( + "UPDATE dataset SET catalog_record_id = catalog_record.id " + "FROM dataset AS d JOIN catalog_record ON d.id = catalog_record.dataset_id " + "WHERE d.id = dataset.id;" + ) + op.alter_column("dataset", "catalog_record_id", nullable=False) + op.create_foreign_key( + "dataset_catalog_record_id_fkey", + "dataset", + "catalog_record", + ["catalog_record_id"], + ["id"], + ondelete="CASCADE", + ) + + # Drop old FK column. + op.drop_column("catalog_record", "dataset_id") + + +def downgrade(): + # Drop new FK constraint. + op.drop_constraint("dataset_catalog_record_id_fkey", "dataset", type_="foreignkey") + + # Bring back and fill old FK column and constraint. + op.add_column( + "catalog_record", + sa.Column("dataset_id", postgresql.UUID(), autoincrement=False, nullable=True), + ) + op.execute( + "UPDATE catalog_record SET dataset_id = dataset.id " + "FROM catalog_record AS cr JOIN dataset ON cr.id = dataset.catalog_record_id " + "WHERE cr.id = catalog_record.id;" + ) + op.create_foreign_key( + "catalog_record_dataset_id_fkey", + "catalog_record", + "dataset", + ["dataset_id"], + ["id"], + ) + + # Drop new FK column. + op.drop_column("dataset", "catalog_record_id")