Initial commit
This commit is contained in:
65
core/db.py
Normal file
65
core/db.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""数据库访问层。
|
||||
|
||||
提供 run_query:读取 .sql 文件、剥离注释、参数化绑定执行、返回 list[dict]。
|
||||
所有报表查询必须走参数绑定,禁止字符串拼接 SQL(防注入)。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import create_engine, text
|
||||
from sqlalchemy.engine import Engine
|
||||
|
||||
from core.settings import settings
|
||||
|
||||
_engine: Engine | None = None
|
||||
|
||||
|
||||
def get_engine() -> Engine:
|
||||
"""惰性创建并缓存 SQLAlchemy engine。"""
|
||||
global _engine
|
||||
if _engine is None:
|
||||
_engine = create_engine(
|
||||
settings.database_url,
|
||||
pool_pre_ping=True,
|
||||
pool_recycle=1800,
|
||||
)
|
||||
return _engine
|
||||
|
||||
|
||||
def load_sql(sql_path: str | Path) -> str:
|
||||
"""读取 .sql 文件并剥离行级 `--` 注释,返回纯 SQL 文本。
|
||||
|
||||
支持 SQL 文件里自由书写中文注释(便于阅读与 AI 理解)。
|
||||
仅剥离以 `--` 开头的整行注释(行首可有空白),不处理行内注释,
|
||||
避免误删含 `--` 的字符串字面量。
|
||||
"""
|
||||
path = Path(sql_path)
|
||||
if not path.is_absolute():
|
||||
from core.settings import PROJECT_ROOT
|
||||
|
||||
path = PROJECT_ROOT / path
|
||||
raw = path.read_text(encoding="utf-8")
|
||||
lines = []
|
||||
for line in raw.splitlines():
|
||||
# 去掉行首空白后判断是否为注释行
|
||||
if re.match(r"\s*--", line):
|
||||
continue
|
||||
lines.append(line)
|
||||
return "\n".join(lines).strip()
|
||||
|
||||
|
||||
def run_query(sql_path: str | Path, params: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
"""执行参数化查询,返回 list[dict](每行一个 dict,键为列别名)。
|
||||
|
||||
:param sql_path: .sql 文件路径(相对项目根或绝对路径)。
|
||||
:param params: 绑定参数,键名对应 SQL 中的 :name 占位符。
|
||||
"""
|
||||
sql_text = load_sql(sql_path)
|
||||
engine = get_engine()
|
||||
with engine.connect() as conn:
|
||||
result = conn.execute(text(sql_text), params)
|
||||
cols = list(result.keys())
|
||||
return [dict(zip(cols, row)) for row in result.fetchall()]
|
||||
Reference in New Issue
Block a user