All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m39s
- 新增店铺角色管理 API 和数据模型 - 实现角色继承和权限检查逻辑 - 添加流程测试框架和集成测试 - 更新权限服务和账号管理逻辑 - 添加数据库迁移脚本 - 归档 OpenSpec 变更文档 Ultraworked with Sisyphus
70 lines
2.0 KiB
Python
70 lines
2.0 KiB
Python
import logging
|
|
from typing import Any, List, Optional
|
|
|
|
import psycopg2
|
|
from psycopg2.extras import RealDictCursor
|
|
|
|
from config.settings import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Database:
|
|
_instance: Optional['Database'] = None
|
|
_conn = None
|
|
|
|
def __new__(cls):
|
|
if cls._instance is None:
|
|
cls._instance = super().__new__(cls)
|
|
cls._instance._connect()
|
|
return cls._instance
|
|
|
|
def _connect(self):
|
|
config = settings.db_config
|
|
self._conn = psycopg2.connect(
|
|
host=config["host"],
|
|
port=config["port"],
|
|
database=config["database"],
|
|
user=config["user"],
|
|
password=config["password"],
|
|
cursor_factory=RealDictCursor,
|
|
)
|
|
self._conn.autocommit = True
|
|
logger.info(f"数据库连接成功: {config['host']}:{config['port']}/{config['database']}")
|
|
|
|
def query(self, sql: str, params: tuple = ()) -> List[dict]:
|
|
with self._conn.cursor() as cur:
|
|
cur.execute(sql, params)
|
|
return cur.fetchall()
|
|
|
|
def query_one(self, sql: str, params: tuple = ()) -> Optional[dict]:
|
|
rows = self.query(sql, params)
|
|
return rows[0] if rows else None
|
|
|
|
def scalar(self, sql: str, params: tuple = ()) -> Any:
|
|
with self._conn.cursor() as cur:
|
|
cur.execute(sql, params)
|
|
row = cur.fetchone()
|
|
if row:
|
|
return list(row.values())[0]
|
|
return None
|
|
|
|
def execute(self, sql: str, params: tuple = ()) -> int:
|
|
with self._conn.cursor() as cur:
|
|
cur.execute(sql, params)
|
|
return cur.rowcount
|
|
|
|
def execute_many(self, sql: str, params_list: List[tuple]) -> int:
|
|
with self._conn.cursor() as cur:
|
|
cur.executemany(sql, params_list)
|
|
return cur.rowcount
|
|
|
|
def close(self):
|
|
if self._conn:
|
|
self._conn.close()
|
|
logger.info("数据库连接已关闭")
|
|
|
|
|
|
def get_db() -> Database:
|
|
return Database()
|