Files
Misaka_Company 4dc563cdd9 Initial commit
2026-07-30 14:17:18 +08:00

66 lines
2.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""数据库访问层。
提供 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()]