Skip to content

analytics: where 里点名不存在的字段仍然一路到驱动 —— #4437(measure)/ #5520(dimension)之后,filter 面是同一个缺陷剩下的第三个 param #5669

Description

@os-zhuang

现象

ensureCube() 现在有两道源字段闸门 —— assertMeasureFields(#4437,param: 'measures')与 assertDimensionFields(#5520 / PR #5667,param: 'dimensions' | 'timeDimensions')。query.where 的字段名没有任何闸门:一个点名不存在字段的筛选条件被原样编译进 WHERE,由驱动答 no such column,调用方拿到 500(dataset 面还会拿到带整条语句的 message —— PR #5667 已把该路由的 5xx 信封收窄,所以泄漏这一半已闭,但分类这一半仍是 500)。

注意 inferCubeFromQuery 会把 where 的顶层键也铸成 dimension(analytics-service.tsquery.where 循环),所以从"cube 词汇表"角度看它和 dimension 是同一类成员;但闸门读的是 query.dimensions / query.timeDimensions 两个请求键,where 不在其中。

复现(测试双,ObjectQL aggregate 路,crm_account 有 id/name/phone/industry/annual_revenue)

POST /analytics/query {"cube":"crm_account","measures":["count"],"where":{"bogus_col":"x"}}

实测(PR #5667 开发期探针,同一 harness 下 dimension 侧已答 400):

生成 SQL: SELECT COUNT(*) AS "count" FROM "crm_account" WHERE bogus_col = $1
executeAggregate 收到调用 → 条件进了引擎,没有任何拒收

在真 SQLite 驱动上这就是 no such column: bogus_col,code/status 皆空,于是 REST 面落 5xx 兜底 —— 与 #5520 立单时 dimension 侧的形状完全一致。

期望

与 measure / dimension 两侧同形:构造 SQL 之前把 where 的字段名拿去和承载对象的字段核对,拒收用同一个信封(400 INVALID_FIELD + field/object/param: 'where')。数据面自 #4315/#4254 起就是这么答的(resolveQueryFields),所以同一个笔误在 /data/analytics 两条路上应当一个形状。

与既有单子的关系(已查重)

实现提示

闸门本体大概是 assertDimensionFields 的三档 stand-down 照抄(cube.sql 须为裸对象名、getObjectFieldNames 须作答、源须为裸列),难点在遍历 filter 树取字段键:要跳过 $and/$or/$not 等组合子与 $-前缀算子键,点号路径按关系穿越放行(同 dimension 闸门),并且要和 filter-normalizer 对同一棵树的读法保持一致,否则会出现"闸门看到的字段"与"真正进 SQL 的列"不是一回事。

严重度按 #5520 的口径估:无数字影响(出厂 metadata 由静态校验兜住),撞点是 Studio 预览、手写查询、外部 API 调用方 —— 他们拿到 500 而不是指名字段的 400。

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions