Skip to content

feat(index): add single-column btree global index build#454

Merged
JingsongLi merged 1 commit into
apache:mainfrom
QuakeWang:feat-btree-global-index
Jul 7, 2026
Merged

feat(index): add single-column btree global index build#454
JingsongLi merged 1 commit into
apache:mainfrom
QuakeWang:feat-btree-global-index

Conversation

@QuakeWang

Copy link
Copy Markdown
Member

Purpose

Rust already has BTree global index read support, scan integration, and row-id coverage semantics, but it did not have an entry point to build BTree global index files. This left the Rust read path unable to close the write/read lifecycle by itself.

Brief change log

  • Add a single-column BTree global index builder for data-evolution row-tracking append tables.
  • Plan index shards by contiguous global row-id ranges and reject missing first_row_id.
  • Write BTree index files under {table}/index/ with Java-compatible BTree/index manifest metadata.
  • Add Table::new_btree_global_index_build_builder().
  • Add CALL sys.create_global_index(..., index_type => 'btree') with unsupported handling for non-BTree types.
  • Add tests for shard planning, row-id gaps, missing row ids, overlap rejection, manifest metadata, SQL creation, and fast/full/detail scan behavior after appends.

Tests

  • cargo fmt --all -- --check
  • cargo clippy --all-targets --workspace --features fulltext,vortex,mosaic -- -D warnings
  • cargo test -p paimon btree
  • cargo test -p paimon table::global_index_scanner::tests --lib
  • cargo test -p paimon table::table_commit::tests::test_global_index --lib
  • cargo test -p paimon-datafusion --test procedures

API and Format

Adds a minimal Rust API and SQL procedure for BTree global index creation. The generated files use Java-compatible BTree/index manifest formats.

Documentation

@JingsongLi

Copy link
Copy Markdown
Contributor

I think there is a correctness issue for Binary/VarBinary BTree global indexes.

btree_global_index_build_builder.rs currently allows DataType::Binary(_) and DataType::VarBinary(_), but btree/key_serde.rs compares byte keys with Rust's default a.cmp(b), i.e. unsigned lexicographic order. This is inconsistent with Paimon's predicate semantics: spec/predicate.rs compares Datum::Bytes with Java signed-byte order via java_bytes_cmp.

For example, 0xff and 0x00 have different ordering under these two comparators. If the BTree index is written and range-pruned with unsigned byte order while predicates use Java signed-byte order, range queries can miss matching rows.

Could we either:

  1. reject Binary/VarBinary for BTree global indexes for now, or
  2. make the BTree byte comparator use the same Java signed-byte ordering as predicate evaluation?

A test with byte values like [0xff] and [0x00] would be useful to cover this.

Add a BTree global index builder for single-column data-evolution append tables. The builder plans row-id coverage conservatively, writes Java-compatible BTree/index manifest metadata, and exposes the minimal Rust API plus DataFusion create_global_index procedure.

Signed-off-by: QuakeWang <wangfuzheng0814@foxmail.com>
@QuakeWang QuakeWang force-pushed the feat-btree-global-index branch from 348adbc to 1c4a434 Compare July 6, 2026 05:17
@QuakeWang QuakeWang requested a review from JingsongLi July 6, 2026 05:44
@QuakeWang

Copy link
Copy Markdown
Member Author

I think there is a correctness issue for Binary/VarBinary BTree global indexes.

btree_global_index_build_builder.rs currently allows DataType::Binary(_) and DataType::VarBinary(_), but btree/key_serde.rs compares byte keys with Rust's default a.cmp(b), i.e. unsigned lexicographic order. This is inconsistent with Paimon's predicate semantics: spec/predicate.rs compares Datum::Bytes with Java signed-byte order via java_bytes_cmp.

For example, 0xff and 0x00 have different ordering under these two comparators. If the BTree index is written and range-pruned with unsigned byte order while predicates use Java signed-byte order, range queries can miss matching rows.

Could we either:

  1. reject Binary/VarBinary for BTree global indexes for now, or
  2. make the BTree byte comparator use the same Java signed-byte ordering as predicate evaluation?

A test with byte values like [0xff] and [0x00] would be useful to cover this.

@JingsongLi Thanks. I fixed this conservatively by rejecting Binary/VarBinary for BTree global index build for now, and added a regression test for that. Supporting these types should be handled separately with aligned byte comparator semantics.

@JingsongLi JingsongLi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@JingsongLi JingsongLi merged commit 41372de into apache:main Jul 7, 2026
12 checks passed
QuakeWang pushed a commit that referenced this pull request Jul 7, 2026
…471)

#454 predates #460's fallible with_projection and merged without a
rebase check; the unused Result fails clippy -D warnings on main and on
every open PR's merge CI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants