""" PostgreSQL Project Repository 实现 """ from typing import List, Optional import psycopg2 from psycopg2.extras import RealDictCursor from packages.domain.entities import Project from packages.ports.project_repository import ProjectRepository class PostgresProjectRepository(ProjectRepository): """Project 仓储 PostgreSQL 实现""" def __init__(self, connection_string: str): self.connection_string = connection_string def _get_connection(self): """获取数据库连接(使用连接池)""" from packages.adapters.postgres.connection_pool import PooledConnection return PooledConnection() def save(self, project: Project) -> None: """保存项目""" conn = self._get_connection() try: with conn.cursor() as cur: cur.execute( """ INSERT INTO projects ( id, workspace_id, name, description, status, created_by, created_at, updated_at ) VALUES ( %(id)s, %(workspace_id)s, %(name)s, %(description)s, %(status)s, %(created_by)s, %(created_at)s, %(updated_at)s ) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, description = EXCLUDED.description, status = EXCLUDED.status, updated_at = EXCLUDED.updated_at """, { "id": project.id, "workspace_id": project.workspace_id, "name": project.name, "description": project.description, "status": project.status, "created_by": project.created_by, "created_at": project.created_at, "updated_at": project.updated_at, }, ) conn.commit() finally: conn.close() def find_by_id(self, project_id: str) -> Optional[Project]: """根据 ID 查找项目""" conn = self._get_connection() try: with conn.cursor() as cur: cur.execute("SELECT * FROM projects WHERE id = %s", (project_id,)) row = cur.fetchone() return self._row_to_project(row) if row else None finally: conn.close() def find_by_workspace(self, workspace_id: str) -> List[Project]: """根据 workspace 查找所有项目""" conn = self._get_connection() try: with conn.cursor() as cur: cur.execute( "SELECT * FROM projects WHERE workspace_id = %s ORDER BY created_at DESC", (workspace_id,), ) rows = cur.fetchall() return [self._row_to_project(row) for row in rows] finally: conn.close() def find_by_creator(self, user_id: str) -> List[Project]: """根据创建者查找项目""" conn = self._get_connection() try: with conn.cursor() as cur: cur.execute( "SELECT * FROM projects WHERE created_by = %s ORDER BY created_at DESC", (user_id,), ) rows = cur.fetchall() return [self._row_to_project(row) for row in rows] finally: conn.close() def count_by_workspace(self, workspace_id: str) -> int: """统计 workspace 的项目数量""" conn = self._get_connection() try: with conn.cursor() as cur: cur.execute( "SELECT COUNT(*) FROM projects WHERE workspace_id = %s", (workspace_id,), ) return cur.fetchone()["count"] finally: conn.close() def delete(self, project_id: str) -> bool: """删除项目""" conn = self._get_connection() try: with conn.cursor() as cur: cur.execute("DELETE FROM projects WHERE id = %s", (project_id,)) deleted = cur.rowcount > 0 conn.commit() return deleted finally: conn.close() def _row_to_project(self, row: dict) -> Project: """将数据库行转换为 Project 对象""" return Project( id=row["id"], workspace_id=row["workspace_id"], name=row["name"], description=row["description"], status=row["status"], created_by=row["created_by"], created_at=row["created_at"], updated_at=row["updated_at"], )