Skip to content

analytics filter-normalizer:未映射的算子被静默丢弃 → 查询放宽到全表($between 已修,还剩四个) #4128

Description

@os-zhuang

#4081 的温度一致性矩阵补第六个消费者(NativeSQLStrategy)时发现的一类缺陷,$between 那一格已在该 PR 内修掉,但成因还在,这里单独立项。

成因

packages/services/service-analytics/src/strategies/filter-normalizer.ts 把 Mongo 风格的 where 拍平成内部管线形式,靠一张 MONGO_TO_CUBE_OP 映射表:

const cubeOp = MONGO_TO_CUBE_OP[opKey];
if (!cubeOp) continue;          // ← 未映射 = 谓词凭空消失

continue 掉一个谓词不是「不支持」,是把查询放宽。少一个 WHERE 条件的 SQL 依然合法,只是多返回行——所以它对断言 SQL 字符串的测试完全隐形,对用户表现为图表画出全部历史(#3650 的症状)。

normalizeAnalyticsFilters 同时被 NativeSQLStrategyObjectQLStrategy 使用,两条路径都受影响。

现状盘点

spec 的 FilterCondition 词汇(filter.zod.ts)对照映射表:

算子 状态
$eq $ne $gt $gte $lt $lte $in $nin $contains $notContains $exists ✅ 已映射
$between ✅ 已修(#4081 follow-up:下降为 gte+lte,畸形输入抛错)
$startsWith ❌ 静默丢弃
$endsWith ❌ 静默丢弃
$null ❌ 静默丢弃
$regex ❌ 静默丢弃
$and ✅ 递归拍平
$or / $not ⚠️ 有注释的刻意跳过——但同样是放宽,见下

四个 ❌ 都是作者可以合法写进 dashboard widget / dataset 过滤器的 spec 词汇($null 尤其常见:「未指派」「无关闭日期」这类看板)。今天它们不会报错、不会告警,只会多给行。

建议的方向

两步,第二步需要决策:

  1. 实现能实现的。 $startsWith / $endsWith / $regex 都能落到已有的 contains(LIKE)家族上;$null 落到已有的 set / notSetIS [NOT] NULL,两条策略都已支持)。这四个都不需要新概念,只是映射表缺项。

  2. 把兜底从 continue 改成 throw 这是 A filter with an operator outside VALID_AST_OPERATORS is silently dropped, not rejected — single-condition views return unfiltered results #3948 在 driver-memory 上已经做过的同一个决定(convertConditionToMongoreturn null 改为抛错,注释原文:「Returning no predicate would silently match every record」),也是 Prime Directive chore: version packages #10「declared ≠ enforced 要么实现要么报错,别假装覆盖」的直接应用。爆炸半径需要评估:改完之后,任何今天在用未映射算子的看板会从「悄悄画错」变成「明确报错」——方向正确,但属于行为变更,值得单独确认。

$or / $not 是第三档:注释写明「策略尚不支持递归 WHERE 构建,忽略以便部分查询仍能运行」。这条理由在 compileScopedFilterToSql(read-scope 已能编译完整的 $or 树,见 #3774 的一致性表)存在之后是否还成立,值得复查——如果能复用它,$or 就不必再被丢。注意 RLS read scope 走的是另一条路径,不受影响;受影响的是作者自己写的 where

复现

矩阵消费者本身就是复现器(packages/services/service-analytics/src/__tests__/native-sql-temporal-conformance.test.ts,真实 sql.js 引擎 + 断言行 id)。把 $between 换成上表任一 ❌ 算子,返回的就是全表。

关联

#4081(矩阵)、#4098(矩阵落地 + preview 侧同species 的 $between 缺陷)、#3650(窗口被丢弃画出全部历史)、#3948(driver-memory 同一决定的先例);ADR-0053 D-A3.1。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions