"""Schema 漂移检测 API。""" from typing import List from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import get_db from app.core.security import get_current_user, require_role from app.core.crypto import decrypt_password from app.models.user import User from app.models.instance import Instance from app.services.schema_drift_detector import SchemaDriftDetector router = APIRouter(prefix="/schema-drift", tags=["Schema 漂移检测"]) def _serialize_drift_report(report): return report.to_dict() if hasattr(report, "to_dict") else report @router.post("/instances/{instance_id}/capture") async def capture_schema( instance_id: int, database: str = "", db: AsyncSession = Depends(get_db), current_user: User = Depends(require_role("admin", "dba")), ): """捕获 Schema 快照并保存为基线。""" result = await db.execute(select(Instance).where(Instance.id == instance_id)) instance = result.scalar_one_or_none() if not instance: raise HTTPException(status_code=404, detail="数据源不存在") if not database: database = instance.database or "" detector = SchemaDriftDetector() instance.password = decrypt_password(instance.password) snapshot = await detector.capture_snapshot(instance, database) await detector.save_baseline(instance_id, database, snapshot) return { "message": "Schema 快照已捕获", "instance_id": instance_id, "database": database, "total_columns": len(snapshot), } @router.post("/instances/{instance_id}/check") async def check_drift( instance_id: int, database: str = "", db: AsyncSession = Depends(get_db), current_user: User = Depends(require_role("admin", "dba")), ): """检测 Schema 漂移。""" result = await db.execute(select(Instance).where(Instance.id == instance_id)) instance = result.scalar_one_or_none() if not instance: raise HTTPException(status_code=404, detail="数据源不存在") if not database: database = instance.database or "" detector = SchemaDriftDetector() instance.password = decrypt_password(instance.password) report = await detector.detect_drift(instance, database) return _serialize_drift_report(report) @router.get("/instances/{instance_id}/history") async def schema_history( instance_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(require_role("admin", "dba")), ): """获取 Schema 变更历史。""" # 简化实现,实际应从数据库查询 return { "instance_id": instance_id, "history": [], "message": "Schema 变更历史功能开发中,当前使用内存存储", }