Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの 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 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
88/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
java
領域
databases

調査の方向性

org.apache.paimon.fileindex.rangebitmap.RangeBitmap#isNull から開始し、cardinality <= 0 ブランチを調査します。5つの完全に NULL な値を使って、提供された Java API の再現を実行します。完了条件は、c IS NULL が5行すべてを返し、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日 10時間
マージ済み PR(30日)
478

環境構築

  • Dockerfile・Docker Compose ファイルなし
  • プルリクエストのテンプレートあり
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

apache/paimon のほかの issue

apache/paimon の issue をすべて見る

似ている issue

Java の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。