立卡门 ①:有具名落点与复现的产品缺陷。finding 类别 a。reach: 公开入口实测一次。
动手的读者:分诊定级;service-analytics 属 domain:services,由本车道席位认领派发。
查重:mcp__github__search_issues 查 "analytics native sql ambiguous column name cube declares no join relationship path bare column qualify canJoin",17 条命中(含 closed),都不是本题。最近的几条:#21232(同族:读取方只看 cube.joins,但那是结构化 JSON 门)、#20933 / #20986(推断型 cube 上的关系路径)。
来源
#21232 的 dev 报告 5941198699(PR #21247,out_of_scope_findings[0])。实测在 b6e64185 上做,那里的 strategies/ 与 origin/main 逐字节相同;探针已删除。
reach:
POST /api/v1/analytics/query,原生 SQL 面。配置型 cube 建在 deal 上,它没有声明任何 join;维度是 note(基表列)和 owner.email(经 lookup owner,其目标对象也声明了 note 列)。
- SQLite:
500 DATABASE_ERROR(ambiguous column name: note);
- PostgreSQL 16.14:
500(42702,column reference "note" is ambiguous);
- 对照(ObjectQL 面):
200。
编译出的语句形如 SELECT note AS "note", "owner"."email" … FROM <deal> LEFT JOIN <person> "owner" … GROUP BY note, …:基表列没有限定表名,关系路径却照样 join 进来了。
落点(源码读)
packages/services/service-analytics/src/strategies/native-sql-strategy.ts 的 qualifyAndRegisterJoin:canJoin = !!cube?.joins && Object.keys(cube.joins).length > 0。只有 cube 声明了 join 时,基表裸列才被限定;而关系路径不论有没有声明,都经 hop 解析器 join 进来。这正是 #21232 那一族的问题:一个读取方只凭 cube.joins 做判断,与 hop-object.ts "不得各自解析 hop"的契约不符。
方向(供分诊参考,不是裁决)
基表列是否需要限定,按"本次查询实际 join 了什么"来判断(即同一个 hop 解析器的结果),不看 cube.joins 有没有声明。⛔ 不新写解析器。
Pins: 上面的配对在两个驱动上都返回 200,分组正确;已声明 join 的 cube 作对照;ObjectQL 面不变。
同文件的其他读取方(dev 的 Zone 2 普查,不在本卡)
native-sql-strategy.ts 里还有几处枚举 cube.joins 但不拆路径的地方::221 的 canHandle(联邦对象拒绝只问声明的 join 目标,可达性未测,记作 PR #21247 的 acceptance note),以及 :401 / :493 / :581(缺少 readScopedObjects 时的兜底)。
承接
本卡与 #21232(PR #21247)同包,文件面不交叉(native-sql-strategy.ts 对比 structured-json-dimension-door.ts)。按同包串行的规矩,在 PR #21247 落地后再认领。
Generated by Claude Code · domain:services seat 2 (#21118) · session_01DiCSbmJrkzNhuEAier4VoJ · https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ
立卡门 ①:有具名落点与复现的产品缺陷。
finding类别 a。reach:公开入口实测一次。动手的读者:分诊定级;
service-analytics属domain:services,由本车道席位认领派发。查重:
mcp__github__search_issues查 "analytics native sql ambiguous column name cube declares no join relationship path bare column qualify canJoin",17 条命中(含 closed),都不是本题。最近的几条:#21232(同族:读取方只看cube.joins,但那是结构化 JSON 门)、#20933 / #20986(推断型 cube 上的关系路径)。来源
#21232 的 dev 报告
5941198699(PR #21247,out_of_scope_findings[0])。实测在b6e64185上做,那里的strategies/与origin/main逐字节相同;探针已删除。reach:POST /api/v1/analytics/query,原生 SQL 面。配置型 cube 建在deal上,它没有声明任何 join;维度是note(基表列)和owner.email(经 lookupowner,其目标对象也声明了note列)。500 DATABASE_ERROR(ambiguous column name: note);500(42702,column reference "note" is ambiguous);200。编译出的语句形如
SELECT note AS "note", "owner"."email" … FROM <deal> LEFT JOIN <person> "owner" … GROUP BY note, …:基表列没有限定表名,关系路径却照样 join 进来了。落点(源码读)
packages/services/service-analytics/src/strategies/native-sql-strategy.ts的qualifyAndRegisterJoin:canJoin = !!cube?.joins && Object.keys(cube.joins).length > 0。只有 cube 声明了 join 时,基表裸列才被限定;而关系路径不论有没有声明,都经 hop 解析器 join 进来。这正是 #21232 那一族的问题:一个读取方只凭cube.joins做判断,与hop-object.ts"不得各自解析 hop"的契约不符。方向(供分诊参考,不是裁决)
基表列是否需要限定,按"本次查询实际 join 了什么"来判断(即同一个 hop 解析器的结果),不看
cube.joins有没有声明。⛔ 不新写解析器。Pins: 上面的配对在两个驱动上都返回
200,分组正确;已声明 join 的 cube 作对照;ObjectQL 面不变。同文件的其他读取方(dev 的 Zone 2 普查,不在本卡)
native-sql-strategy.ts里还有几处枚举cube.joins但不拆路径的地方::221的canHandle(联邦对象拒绝只问声明的 join 目标,可达性未测,记作 PR #21247 的 acceptance note),以及:401/:493/:581(缺少readScopedObjects时的兜底)。承接
本卡与 #21232(PR #21247)同包,文件面不交叉(
native-sql-strategy.ts对比structured-json-dimension-door.ts)。按同包串行的规矩,在 PR #21247 落地后再认领。Generated by Claude Code ·
domain:servicesseat 2 (#21118) ·session_01DiCSbmJrkzNhuEAier4VoJ· https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ