Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

MultiSet.consolidate merges keyed records whose keys or values differ only by number/string type

已关闭
#1,948 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
3/5
预计耗时
1-2 天
新手友好度
76/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
typescript
领域
databases

调研方向

Start in packages/db-ivm/src/utils.ts with getStringId, then locate the keyed consolidation path that builds compositeKey. Run the consolidation oracle and add the primitive key/value and join-tuple witnesses described in the issue, removing its exclusion; done means cross-type records remain distinct and a changeset is included for @tanstack/db-ivm.

由索引模型根据 Issue 内容生成。

描述

  • I've validated the bug against the latest version of DB packages (origin/main at b5d92ceb)

Describe the bug

MultiSet.consolidate() merges keyed records whose keys or primitive values differ only in type. A number and a string with the same text, such as 1 and "1", become one identity. Multiplicities for two different records are then summed together. A retraction of one record can erase an insert of a different record.

The keyed path builds a string identity. getStringId in packages/db-ivm/src/utils.ts encodes every primitive as `str_${String(value)}`, and consolidate joins the key the same way:

getStringId(value: any): string {
  if (value === null) return `null`
  if (value === undefined) return `undefined`
  if (typeof value !== `object`) return `str_${String(value)}`
  return `obj_${this.getId(value)}`
}
// ...
const compositeKey = key + `|` + valueId

So 1 and "1" both produce str_1, and the keys 1 and "1" both produce 1|.

To Reproduce

import { MultiSet } from '@tanstack/db-ivm'

new MultiSet<any>([[[1, 'v'], 1], [['1', 'v'], 1]]).consolidate().getInner()
// [[[1, 'v'], 2]]   expected two records, each with multiplicity 1

new MultiSet<any>([[['k', 1], 1], [['k', '1'], -1]]).consolidate().getInner()
// []   expected [[['k', 1], 1], [['k', '1'], -1]]

new MultiSet<any>([[['k', [1, null]], 1], [['k', ['1', null]], -1]]).consolidate().getInner()
// []   expected both records (join tuples have the same collision)

The unkeyed path is correct:

new MultiSet<any>([[1, 1], ['1', -1]]).consolidate().getInner()
// [[1, 1], ['1', -1]]

Expected behavior

Keyed consolidation should keep the identity rule it documents. Keys compare by value, and values compare by reference. A number and a string are different values, so records that differ only in that type must stay separate.

Scope

  • Object values are compared by reference and are not affected. The collision needs a primitive key or a primitive value, or a join tuple that holds a primitive.

  • In @tanstack/db, the collision needs one of these:

    • one collection with numeric and string keys that print the same, such as 1 and "1";
    • a keyed stream that carries primitive values.

    I have not traced which query shapes produce such a stream.

  • A code-weight change to MultiSet.consolidate is in progress. It keeps this behavior unchanged on purpose. Its consolidation oracle excludes these cross-type values from its grammar and links to this issue. A fix should remove that exclusion.

Suggested fix and test

  • Include the type in the primitive identity, for example `${typeof value}:${String(value)}`. Also encode the key with its type before the | join.
  • Remove the exclusion from the consolidation oracle, and add these cases as witnesses. Each case should fail before the fix and pass after it.
  • Add a changeset for @tanstack/db-ivm.
主要语言
TypeScript
星标
3.9k
派生
272
平均合并
1 天 1 小时
30 天内合并 PR
210

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

TanStack/db 的其他 Issue

查看 TanStack/db 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。