94 Zeilen
3.4 KiB
Python
94 Zeilen
3.4 KiB
Python
from abc import ABC, abstractmethod
|
|
from typing import Optional, List, Dict, Any
|
|
import psycopg2
|
|
from psycopg2.extras import RealDictCursor
|
|
from contextlib import contextmanager
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class BaseRepository(ABC):
|
|
"""Base repository with common database operations"""
|
|
|
|
def __init__(self, db_url: str):
|
|
self.db_url = db_url
|
|
|
|
@contextmanager
|
|
def get_db_connection(self):
|
|
"""Get database connection with automatic cleanup"""
|
|
conn = None
|
|
try:
|
|
conn = psycopg2.connect(self.db_url)
|
|
yield conn
|
|
except Exception as e:
|
|
if conn:
|
|
conn.rollback()
|
|
logger.error(f"Database error: {e}")
|
|
raise
|
|
finally:
|
|
if conn:
|
|
conn.close()
|
|
|
|
@contextmanager
|
|
def get_db_cursor(self, conn):
|
|
"""Get database cursor with dict results"""
|
|
cursor = None
|
|
try:
|
|
cursor = conn.cursor(cursor_factory=RealDictCursor)
|
|
yield cursor
|
|
finally:
|
|
if cursor:
|
|
cursor.close()
|
|
|
|
def execute_query(self, query: str, params: tuple = None) -> List[Dict[str, Any]]:
|
|
"""Execute SELECT query and return results"""
|
|
with self.get_db_connection() as conn:
|
|
with self.get_db_cursor(conn) as cursor:
|
|
cursor.execute(query, params)
|
|
return cursor.fetchall()
|
|
|
|
def execute_one(self, query: str, params: tuple = None) -> Optional[Dict[str, Any]]:
|
|
"""Execute query and return single result"""
|
|
with self.get_db_connection() as conn:
|
|
with self.get_db_cursor(conn) as cursor:
|
|
cursor.execute(query, params)
|
|
return cursor.fetchone()
|
|
|
|
def execute_insert(self, query: str, params: tuple = None) -> Optional[str]:
|
|
"""Execute INSERT query and return ID"""
|
|
with self.get_db_connection() as conn:
|
|
with self.get_db_cursor(conn) as cursor:
|
|
cursor.execute(query + " RETURNING id", params)
|
|
result = cursor.fetchone()
|
|
conn.commit()
|
|
return result['id'] if result else None
|
|
|
|
def execute_update(self, query: str, params: tuple = None) -> int:
|
|
"""Execute UPDATE query and return affected rows"""
|
|
with self.get_db_connection() as conn:
|
|
with self.get_db_cursor(conn) as cursor:
|
|
cursor.execute(query, params)
|
|
affected = cursor.rowcount
|
|
conn.commit()
|
|
return affected
|
|
|
|
def execute_delete(self, query: str, params: tuple = None) -> int:
|
|
"""Execute DELETE query and return affected rows"""
|
|
with self.get_db_connection() as conn:
|
|
with self.get_db_cursor(conn) as cursor:
|
|
cursor.execute(query, params)
|
|
affected = cursor.rowcount
|
|
conn.commit()
|
|
return affected
|
|
|
|
def execute_batch(self, queries: List[tuple]) -> None:
|
|
"""Execute multiple queries in a transaction"""
|
|
with self.get_db_connection() as conn:
|
|
with self.get_db_cursor(conn) as cursor:
|
|
try:
|
|
for query, params in queries:
|
|
cursor.execute(query, params)
|
|
conn.commit()
|
|
except Exception as e:
|
|
conn.rollback()
|
|
raise |