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

[Bug] range-bitmap file index: IS NULL returns only the first and last row when a column is entirely NULL in a file

未关闭 适合新手
#10,332 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

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

调研方向

从 org.apache.paimon.fileindex.rangebitmap.RangeBitmap#isNull 开始,检查 cardinality <= 0 分支。使用五个完全为 NULL 的值运行提供的 Java API 复现;完成条件是 c IS NULL 返回全部五行,并为 range-bitmap 情况提供回归覆盖。

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

描述

bug
Search before asking
  • I searched in the issues and found nothing similar.
Paimon version

2.0.0 (paimon-bundle-2.0.0)

Compute Engine

None — reproduced with the Java API (ReadBuilder.withFilter), local filesystem catalog, Java 21.

Minimal reproduce step

Create an append table with a range-bitmap file index on c, write 5 rows where c is NULL in every row, then read with c IS NULL:

Identifier id = Identifier.create("db", "t_isnull");
catalog.createTable(
    id,
    Schema.newBuilder()
        .column("id", DataTypes.INT())
        .column("c", DataTypes.INT())
        .option("file-index.range-bitmap.columns", "c")
        .build(),
    false);
Table table = catalog.getTable(id);
List<GenericRow> rows = new ArrayList<>();
for (int i = 0; i < 5; i++) {
  rows.add(GenericRow.of(i, null));
}
write(table, rows);

Predicate isNull = new PredicateBuilder(table.rowType()).isNull(1);
System.out.println(count(table, isNull));   // prints 2
System.out.println(count(table, null));     // prints 5

Helper methods:

static void write(Table table, List<GenericRow> rows) throws Exception {
  BatchWriteBuilder builder = table.newBatchWriteBuilder();
  try (BatchTableWrite write = builder.newWrite();
      BatchTableCommit commit = builder.newCommit()) {
    for (GenericRow row : rows) write.write(row);
    commit.commit(write.prepareCommit());
  }
}

static long count(Table table, Predicate filter) throws Exception {
  ReadBuilder builder = table.newReadBuilder();
  if (filter != null) builder = builder.withFilter(filter);
  long[] count = new long[1];
  try (RecordReader<InternalRow> reader =
      builder.newRead().createReader(builder.newScan().plan())) {
    reader.forEachRemaining(row -> count[0]++);
  }
  return count[0];
}

The same table with file-index.bitmap.columns or file-index.bsi.columns instead of range-bitmap returns 5.

What doesn't meet your expectations?

c IS NULL returns 2 rows; all 5 rows match. The rows returned are the first and the last row of the file; every row in between is dropped.

The same table with file-index.bitmap.columns or file-index.bsi.columns instead of range-bitmap returns 5.

Anything else?

Root cause is in org.apache.paimon.fileindex.rangebitmap.RangeBitmap#isNull. When the column has no non-null value in the file (cardinality <= 0), it returns:

RoaringBitmap32.bitmapOf(0, rid - 1)

bitmapOf(int...) takes a list of positions, so this is the two-element set {0, rid - 1}, not the range [0, rid). Any file with three or more rows where the indexed column is entirely NULL loses its middle rows for IS NULL.

Suggested fix: return the full range, e.g. RoaringBitmap32.bitmapOfRange(0, rid). isNotNull on the same reader is correct (it returns an empty bitmap for such a file), so the complement of isNotNull over [0, rid) gives the right answer too.

Are you willing to submit a PR?
  • I'm willing to submit a PR!
主要语言
Java
星标
3.4k
派生
1.4k
平均合并
1 天 12 小时
30 天内合并 PR
473

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 有 Pull Request 模板
  • 没有贡献指南

从这里开始

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

apache/paimon 的其他 Issue

查看 apache/paimon 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 发到你的邮箱

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