Skip to content

objectui: buildPivot 的 cell key 用空格拼接 rowId 与 colId,维度值含空格时会静默串格 #5473

Description

@yinlianghui

实现 objectstack#5450(清理 DatasetWidget.tsx 里那个裸控制字节)时在相邻两行发现的,按 Prime Directive #10 单独开单,不在 5450 的 PR 里顺手改。

位置

packages/plugin-dashboard/src/DatasetWidget.tsx,buildPivot() 里:

const rid = rowDims.map((d) => String(row[d] ?? 'EMPTY')).join(SEP);   // SEP = U+0001
const cid = String(row[colDim] ?? 'EMPTY');
cellIndex.set(`${rid} ${cid}`, index);                                  // 注意:空格

行 id 内部用的是一个"维度值不可能包含"的字符(U+0001,objectstack#5450 已把它改成可读的转义写法,运行时值不变),但行 id 与列 id 之间用的是一个普通空格 —— 而维度值里含空格是再常见不过的事("New York"、"In Progress"、"Closed Won")。

后果

当两行满足 rid1 + 空格 + cid1 === rid2 + 空格 + cid2 时,cellIndex 的后写者覆盖先写者,透视表那一格显示的是另一行的度量值。举例(行维度 region,列维度 quarter):

region quarter cell key
A New York Q1 New York Q1
B New York Q1 New York Q1

两行落进同一个 key,cellIndex 只保留后者;drill-through 也是按这个 index 读 drillRawRows 的,所以钻取会一并钻到错的那行。

全程无报错、无警告 —— 只是格子里的数字不对。

触发面(如实说)

要求两个维度值恰好能在边界上"接得上",不是每天都撞;但维度值是任意用户数据,而且这是静默的数据正确性问题,不是渲染瑕疵。严重度请 triage 时按贵重口径判,我只按发现原样记。

为什么没在 objectstack#5450 里一起修

  • 那一单的文件面是四个控制字节 + KNOWN_OFFENDERS 基线,越界即停;
  • cell key 的字符串形态被现有测试直接钉着(expect(p.cellIndex.get('Open High')).toBe(0)),换编码要连同测试一起重写,属于另一个改动的完整范围。

建议方向

  • cell key 不再依赖"不可能出现的字符":JSON.stringify([rid, cid])(与 objectui#3388 对 include key、objectstack#5450 对告警去重 key 的处置同形),边界对任意维度值都无歧义;
  • 顺带把 buildPivot 的用例从"只有一个行维度"扩到多行维度 —— objectstack#5450 补的那条用例已经开了个头,在那之前分隔符从来没被任何用例跑到过(改成空串也照样全绿)。

发现来源:objectstack#5450 / PR objectui#3389。

Activity

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions