""" Database change model for tracking database schema and data modifications. Tracks database changes including schema modifications, data updates, index creation, optimizations, and cleanup operations with backup tracking. """ from datetime import datetime from typing import TYPE_CHECKING, Optional from sqlalchemy import BigInteger, Boolean, CHAR, CheckConstraint, ForeignKey, Index, String, Text, TIMESTAMP from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.sql import func from .base import Base, UUIDMixin if TYPE_CHECKING: from .infrastructure import Infrastructure from .session import Session from .work_item import WorkItem class DatabaseChange(Base, UUIDMixin): """ Database change model for tracking database modifications. Records all database schema and data changes including DDL operations, data modifications, index management, optimizations, and cleanup tasks. Tracks affected rows, backup status, and freed space for audit and rollback purposes. Attributes: work_item_id: Foreign key to work_items table (required) session_id: Foreign key to sessions table (required) database_name: Name of the database that was modified infrastructure_id: Foreign key to infrastructure table change_type: Type of database change sql_executed: SQL statements that were executed rows_affected: Number of rows affected by the change size_freed_bytes: Bytes freed by cleanup operations backup_taken: Whether a backup was taken before the change backup_location: Path or identifier of the backup created_at: When the change was made work_item: Relationship to WorkItem model session: Relationship to Session model infrastructure: Relationship to Infrastructure model """ __tablename__ = "database_changes" # Foreign keys work_item_id: Mapped[str] = mapped_column( CHAR(36), ForeignKey("work_items.id", ondelete="CASCADE"), nullable=False, doc="Foreign key to work_items table (required)" ) session_id: Mapped[str] = mapped_column( CHAR(36), ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False, doc="Foreign key to sessions table (required)" ) database_name: Mapped[str] = mapped_column( String(255), nullable=False, doc="Name of the database that was modified" ) infrastructure_id: Mapped[Optional[str]] = mapped_column( CHAR(36), ForeignKey("infrastructure.id", ondelete="SET NULL"), doc="Foreign key to infrastructure table" ) # Change details change_type: Mapped[Optional[str]] = mapped_column( String(50), doc="Type of change: schema, data, index, optimization, cleanup, migration" ) sql_executed: Mapped[Optional[str]] = mapped_column( Text, doc="SQL statements that were executed" ) rows_affected: Mapped[Optional[int]] = mapped_column( BigInteger, doc="Number of rows affected by the change" ) size_freed_bytes: Mapped[Optional[int]] = mapped_column( BigInteger, doc="Bytes freed by cleanup operations" ) # Backup tracking backup_taken: Mapped[bool] = mapped_column( Boolean, default=False, server_default="0", nullable=False, doc="Whether a backup was taken before the change" ) backup_location: Mapped[Optional[str]] = mapped_column( String(500), doc="Path or identifier of the backup" ) # Timestamp created_at: Mapped[datetime] = mapped_column( TIMESTAMP, nullable=False, server_default=func.now(), doc="When the change was made" ) # Relationships work_item: Mapped["WorkItem"] = relationship( "WorkItem", back_populates="database_changes", doc="Relationship to WorkItem model" ) session: Mapped["Session"] = relationship( "Session", back_populates="database_changes", doc="Relationship to Session model" ) infrastructure: Mapped[Optional["Infrastructure"]] = relationship( "Infrastructure", back_populates="database_changes", doc="Relationship to Infrastructure model" ) # Constraints and indexes __table_args__ = ( CheckConstraint( "change_type IN ('schema', 'data', 'index', 'optimization', 'cleanup', 'migration')", name="ck_database_changes_type" ), Index("idx_db_changes_work_item", "work_item_id"), Index("idx_db_changes_database", "database_name"), ) def __repr__(self) -> str: """String representation of the database change.""" return f""