DEBUG.WIKI
晚安云;香港 CN2 ¥15/月
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →

打印 SQLAlchemy 聚合语句时报 use_function_name 缺参,先区分编译方言

SQLAlchemy 2.1 的 aggregate_strings 曾在 str(stmt) 中触发 TypeError。2.1.4 修复了字符串展示,但不支持的默认方言仍可能抛 CompileError;诊断 SQL 应使用真实目标方言。

查询语句还没交给数据库,调试时执行 str(stmt) 就报:

TypeError: SQLCompiler.visit_aggregate_strings_func() missing
1 required keyword-only argument: 'use_function_name'

如果语句含 func.aggregate_strings(),应核对 SQLAlchemy 2.1 的默认编译路径。这个错误可以发生在日志或异常消息构造中;它本身不能证明目标数据库执行了错误 SQL。

同一表达式会按方言生成不同函数

下面是说明问题的查询,不需要连接数据库:

from sqlalchemy import column, func, select, table

t = table("items", column("label"))
stmt = select(func.aggregate_strings(t.c.label, ","))
print(str(stmt))

aggregate_strings() 是跨后端表达式,SQLite、PostgreSQL 等有各自的编译实现。在受影响的 2.1 路径中,普通默认编译器调用这个函数时,没有提供内部所需的 use_function_name,于是产生 Python 缺参错误。

SQLAlchemy 2.1.4 的正式变更包含这项修复,2.1.5 也包含它。更新到适合项目且包含修复的版本后,str(stmt) 的展示路径不应再出现该缺参异常。

想看目标数据库 SQL,显式选择它的方言

例如目标是 PostgreSQL,诊断时可使用:

from sqlalchemy.dialects import postgresql

compiled = stmt.compile(dialect=postgresql.dialect())
print(compiled)

这沿用上一段定义的 stmt,只做编译,不执行查询。应用里已有 Engine 时,也可以按 stmt.compile(engine) 选择实际 Engine 的方言。输出参数应遵守现有日志脱敏规则,不要为了直观看到值而把外部输入拼接进 SQL。

显式 stmt.compile() 与 str(stmt) 在修复后也不保证完全相同。2.1.4 的修复让字符串展示使用适当的展示编译器;普通默认方言或未实现该函数的第三方方言,则会明确抛 CompileError,说明该方言不支持 aggregate_strings。这不再是漏传参数,但也不是“所有后端已支持此函数”。

第三方方言需要按它真正支持的聚合函数实现编译,不能给私有方法随手补一个默认名称,再假定数据库能执行那个名称。

复查时分别检查原来的日志入口、实际目标方言编译及有代表性数据的查询结果。字符串能打印,只完成了展示环节;分隔符、NULL 处理、顺序需求和数据库支持范围仍应按原来的查询契约确认。