This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-rust.git
The following commit(s) were added to refs/heads/main by this push:
new 75c9ee01 fix(spec): widen index-manifest row count to i64 (#751)
75c9ee01 is described below
commit 75c9ee01081e5ee1987c883e234109fba12a05bc
Author: Junrui Lee <[email protected]>
AuthorDate: Thu Aug 27 15:44:54 2026 +0800
fix(spec): widen index-manifest row count to i64 (#751)
---
bindings/c/src/tests.rs | 2 +-
.../datafusion/src/system_tables/table_indexes.rs | 2 +-
.../datafusion/tests/dynamic_bucket_tables.rs | 5 +--
.../integrations/datafusion/tests/system_tables.rs | 5 +--
.../src/spec/avro/index_manifest_entry_decode.rs | 4 +--
crates/paimon/src/spec/index_file_meta.rs | 2 +-
crates/paimon/src/spec/index_manifest.rs | 34 +++++++++++++++++--
crates/paimon/src/table/data_evolution_writer.rs | 2 +-
.../paimon/src/table/full_text_search_builder.rs | 2 +-
.../paimon/src/table/global_index_drop_builder.rs | 2 +-
crates/paimon/src/table/hybrid_search_builder.rs | 4 +--
.../paimon/src/table/lumina_index_build_builder.rs | 38 +++++++++++++---------
.../paimon/src/table/pk_full_text_bucket_search.rs | 2 +-
.../paimon/src/table/pk_full_text_bucket_state.rs | 4 +--
crates/paimon/src/table/pk_full_text_read.rs | 2 +-
crates/paimon/src/table/pk_full_text_scan.rs | 4 +--
.../src/table/sorted_global_index_build_builder.rs | 38 +++++++++++++++-------
crates/paimon/src/table/table_commit.rs | 2 +-
crates/paimon/src/table/vector_search_builder.rs | 2 +-
.../paimon/src/table/vindex_index_build_builder.rs | 9 +++--
crates/paimon/tests/pk_vector_baseline_test.rs | 4 +--
crates/paimon/tests/pk_vector_batch_test.rs | 2 +-
22 files changed, 107 insertions(+), 64 deletions(-)
diff --git a/bindings/c/src/tests.rs b/bindings/c/src/tests.rs
index e7da4306..37fa0c91 100644
--- a/bindings/c/src/tests.rs
+++ b/bindings/c/src/tests.rs
@@ -2459,7 +2459,7 @@ fn build_pk_vector_table(path: &str, vectors: &[[f32;
PK_DIM]]) -> Table {
index_type: INDEX_TYPE.to_string(),
file_name: index_file_name,
file_size: i64::try_from(index_file_size).unwrap(),
- row_count: i32::try_from(row_count).unwrap(),
+ row_count,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: 0,
diff --git a/crates/integrations/datafusion/src/system_tables/table_indexes.rs
b/crates/integrations/datafusion/src/system_tables/table_indexes.rs
index c1c900ee..cff4796a 100644
--- a/crates/integrations/datafusion/src/system_tables/table_indexes.rs
+++ b/crates/integrations/datafusion/src/system_tables/table_indexes.rs
@@ -132,7 +132,7 @@ impl TableProvider for TableIndexesTable {
index_types.push(index_file.index_type.as_str());
file_names.push(index_file.file_name.as_str());
file_sizes.push(index_file.file_size);
- row_counts.push(i64::from(index_file.row_count));
+ row_counts.push(index_file.row_count);
append_dv_ranges(
&mut dv_ranges,
index_file
diff --git a/crates/integrations/datafusion/tests/dynamic_bucket_tables.rs
b/crates/integrations/datafusion/tests/dynamic_bucket_tables.rs
index 34aea68f..186b7894 100644
--- a/crates/integrations/datafusion/tests/dynamic_bucket_tables.rs
+++ b/crates/integrations/datafusion/tests/dynamic_bucket_tables.rs
@@ -1000,10 +1000,7 @@ async fn
test_pk_dynamic_bucket_partitioned_insert_overwrite() {
}
// Total hash count: partition 'b' had 2 keys, partition 'a' now has 1 key
- let total_hashes: i64 = entries_after
- .iter()
- .map(|e| e.index_file.row_count as i64)
- .sum();
+ let total_hashes: i64 = entries_after.iter().map(|e|
e.index_file.row_count).sum();
assert_eq!(
total_hashes, 3,
"Total hash entries should be 3 (2 from 'b' + 1 from 'a'), got
{total_hashes}"
diff --git a/crates/integrations/datafusion/tests/system_tables.rs
b/crates/integrations/datafusion/tests/system_tables.rs
index 267f3c97..582d6ef1 100644
--- a/crates/integrations/datafusion/tests/system_tables.rs
+++ b/crates/integrations/datafusion/tests/system_tables.rs
@@ -287,10 +287,7 @@ async fn test_table_indexes_system_table() {
assert_eq!(index_types.value(row), expected.index_file.index_type);
assert_eq!(file_names.value(row), expected.index_file.file_name);
assert_eq!(file_sizes.value(row), expected.index_file.file_size);
- assert_eq!(
- row_counts.value(row),
- i64::from(expected.index_file.row_count)
- );
+ assert_eq!(row_counts.value(row), expected.index_file.row_count);
assert_eq!(
dv_ranges.is_null(row),
expected.index_file.deletion_vectors_ranges.is_none()
diff --git a/crates/paimon/src/spec/avro/index_manifest_entry_decode.rs
b/crates/paimon/src/spec/avro/index_manifest_entry_decode.rs
index efdd960f..38bf0c71 100644
--- a/crates/paimon/src/spec/avro/index_manifest_entry_decode.rs
+++ b/crates/paimon/src/spec/avro/index_manifest_entry_decode.rs
@@ -36,7 +36,7 @@ impl AvroRecordDecode for IndexManifestEntry {
let mut index_type: Option<String> = None;
let mut file_name: Option<String> = None;
let mut file_size: Option<i64> = None;
- let mut row_count: Option<i32> = None;
+ let mut row_count: Option<i64> = None;
let mut deletion_vectors_ranges: Option<IndexMap<String,
DeletionVectorMeta>> = None;
let mut global_index_meta: Option<GlobalIndexMeta> = None;
@@ -61,7 +61,7 @@ impl AvroRecordDecode for IndexManifestEntry {
"_INDEX_TYPE" => index_type = Some(read_string_field(cursor,
field.nullable)?),
"_FILE_NAME" => file_name = Some(read_string_field(cursor,
field.nullable)?),
"_FILE_SIZE" => file_size = Some(read_long_field(cursor,
field.nullable)?),
- "_ROW_COUNT" => row_count = Some(read_long_field(cursor,
field.nullable)? as i32),
+ "_ROW_COUNT" => row_count = Some(read_long_field(cursor,
field.nullable)?),
"_DELETIONS_VECTORS_RANGES" | "_DELETION_VECTORS_RANGES" => {
deletion_vectors_ranges =
decode_nullable_dv_ranges(cursor, field.nullable)?;
}
diff --git a/crates/paimon/src/spec/index_file_meta.rs
b/crates/paimon/src/spec/index_file_meta.rs
index d6e6e80e..3b1b2f56 100644
--- a/crates/paimon/src/spec/index_file_meta.rs
+++ b/crates/paimon/src/spec/index_file_meta.rs
@@ -66,7 +66,7 @@ pub struct IndexFileMeta {
pub file_size: i64,
#[serde(rename = "_ROW_COUNT")]
- pub row_count: i32,
+ pub row_count: i64,
// use Indexmap to ensure the order of deletion_vectors_ranges is
consistent.
#[serde(
diff --git a/crates/paimon/src/spec/index_manifest.rs
b/crates/paimon/src/spec/index_manifest.rs
index 5160b61e..24cac0f2 100644
--- a/crates/paimon/src/spec/index_manifest.rs
+++ b/crates/paimon/src/spec/index_manifest.rs
@@ -27,9 +27,8 @@ use crate::Result;
///
/// Must match the serde layout of `IndexManifestEntry`.
///
-/// Note: `_FILE_SIZE` is an Avro `long` and Rust `i64`, matching Java Paimon's
-/// schema. `_ROW_COUNT` remains an Avro `long` for Java compatibility while
-/// the Rust `IndexFileMeta` field is still `i32`.
+/// Note: `_FILE_SIZE` and `_ROW_COUNT` are Avro `long`s and Rust `i64`s,
+/// matching Java Paimon's schema.
pub const INDEX_MANIFEST_ENTRY_SCHEMA: &str = r#"{
"type": "record",
"name": "org.apache.paimon.avro.generated.record",
@@ -370,6 +369,35 @@ mod tests {
assert_eq!(decoded, vec![entry]);
}
+ #[test]
+ fn row_count_above_i32_max_round_trips_through_index_manifest() {
+ // _ROW_COUNT is an Avro `long`; a source-backed index over a large
data
+ // file can exceed i32::MAX. The decoder must not truncate it.
+ let row_count = i64::from(i32::MAX) + 100;
+ let entry: IndexManifestEntry =
serde_json::from_value(serde_json::json!({
+ "_VERSION": 1,
+ "_KIND": 0,
+ "_PARTITION": [0, 0, 0, 0],
+ "_BUCKET": 0,
+ "_INDEX_TYPE": "TEST",
+ "_FILE_NAME": "index",
+ "_FILE_SIZE": 42,
+ "_ROW_COUNT": row_count
+ }))
+ .unwrap();
+
+ let bytes = crate::spec::to_avro_bytes_with_compression(
+ INDEX_MANIFEST_ENTRY_SCHEMA,
+ std::slice::from_ref(&entry),
+ crate::spec::DEFAULT_AVRO_COMPRESSION,
+ )
+ .unwrap();
+
+ let decoded = IndexManifest::read_from_bytes(&bytes).unwrap();
+ assert_eq!(decoded[0].index_file.row_count, row_count);
+ assert_eq!(decoded, vec![entry]);
+ }
+
#[test]
fn legacy_five_field_global_index_decodes_without_source_meta() {
// 5-field _GLOBAL_INDEX schema (pre-#8549): no _SOURCE_META.
Identical to
diff --git a/crates/paimon/src/table/data_evolution_writer.rs
b/crates/paimon/src/table/data_evolution_writer.rs
index d8b66e86..1736626c 100644
--- a/crates/paimon/src/table/data_evolution_writer.rs
+++ b/crates/paimon/src/table/data_evolution_writer.rs
@@ -713,7 +713,7 @@ impl DataEvolutionDeleteWriter {
index_type: DELETION_VECTORS_INDEX_TYPE.to_string(),
file_name,
file_size,
- row_count,
+ row_count: i64::from(row_count),
deletion_vectors_ranges: Some(ranges),
global_index_meta: None,
})
diff --git a/crates/paimon/src/table/full_text_search_builder.rs
b/crates/paimon/src/table/full_text_search_builder.rs
index 532cd0f3..81beacc2 100644
--- a/crates/paimon/src/table/full_text_search_builder.rs
+++ b/crates/paimon/src/table/full_text_search_builder.rs
@@ -1270,7 +1270,7 @@ mod tests {
index_type: FULL_TEXT_INDEX_TYPE.to_string(),
file_name: name.to_string(),
file_size: 0,
- row_count: i32::try_from(end - start + 1).unwrap(),
+ row_count: end - start + 1,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: start,
diff --git a/crates/paimon/src/table/global_index_drop_builder.rs
b/crates/paimon/src/table/global_index_drop_builder.rs
index 6bc70e72..505139fe 100644
--- a/crates/paimon/src/table/global_index_drop_builder.rs
+++ b/crates/paimon/src/table/global_index_drop_builder.rs
@@ -259,7 +259,7 @@ mod tests {
index_type: index_type.to_string(),
file_name: name.to_string(),
file_size: 128,
- row_count: (row_range_end - row_range_start + 1) as i32,
+ row_count: (row_range_end - row_range_start + 1),
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start,
diff --git a/crates/paimon/src/table/hybrid_search_builder.rs
b/crates/paimon/src/table/hybrid_search_builder.rs
index 3f5006cb..5068dc80 100644
--- a/crates/paimon/src/table/hybrid_search_builder.rs
+++ b/crates/paimon/src/table/hybrid_search_builder.rs
@@ -1385,7 +1385,7 @@ mod pk_hybrid_tests {
index_type: VECTOR_INDEX_TYPE.to_string(),
file_name: vector_index_name,
file_size: i64::try_from(vector_index_size).unwrap(),
- row_count: i32::try_from(row_count).unwrap(),
+ row_count,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: 0,
@@ -1418,7 +1418,7 @@ mod pk_hybrid_tests {
index_type: PK_FULL_TEXT_INDEX_TYPE.to_string(),
file_name: ft_index_name,
file_size: 1,
- row_count: i32::try_from(row_count).unwrap(),
+ row_count,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: 0,
diff --git a/crates/paimon/src/table/lumina_index_build_builder.rs
b/crates/paimon/src/table/lumina_index_build_builder.rs
index 7bed2cc3..d340c97e 100644
--- a/crates/paimon/src/table/lumina_index_build_builder.rs
+++ b/crates/paimon/src/table/lumina_index_build_builder.rs
@@ -200,7 +200,15 @@ impl<'a> LuminaIndexBuildBuilder<'a> {
index_meta: Vec<u8>,
) -> Result<IndexFileMeta> {
let row_count = checked_row_count(shard.row_range_start,
shard.row_range_end)?;
- validate_vector_buffer(vectors, row_count, dimension)?;
+ // The native Lumina builder counts rows in an i32; the manifest keeps
the
+ // full width.
+ let native_row_count = i32::try_from(row_count).map_err(|_|
Error::DataInvalid {
+ message: format!(
+ "Lumina shard row count {row_count} exceeds what the native
builder accepts"
+ ),
+ source: None,
+ })?;
+ validate_vector_buffer(vectors, native_row_count, dimension)?;
let ids = (0..row_count as u64).collect::<Vec<_>>();
let native_options =
LuminaIndexMeta::deserialize(&index_meta)?.options().clone();
@@ -208,8 +216,8 @@ impl<'a> LuminaIndexBuildBuilder<'a> {
let temp_file = TempFileGuard::new(temp_path.clone());
let temp_path_str = temp_path.to_string_lossy().to_string();
let builder = LuminaBuilder::create(&native_options)?;
- builder.pretrain(vectors, row_count, dimension)?;
- builder.insert(vectors, &ids, row_count, dimension)?;
+ builder.pretrain(vectors, native_row_count, dimension)?;
+ builder.insert(vectors, &ids, native_row_count, dimension)?;
builder.dump(&temp_path_str)?;
let file_name = format!("lumina-global-index-{}.index",
uuid::Uuid::new_v4());
@@ -596,10 +604,7 @@ async fn extract_vectors(
index_column,
dimension,
shard.row_range_start,
- i64::from(checked_row_count(
- shard.row_range_start,
- shard.row_range_end,
- )?),
+ checked_row_count(shard.row_range_start, shard.row_range_end)?,
)
}
@@ -751,19 +756,22 @@ fn checked_i64(value: u64, context: &str) -> Result<i64> {
})
}
-fn checked_row_count(row_range_start: i64, row_range_end: i64) -> Result<i32> {
+fn checked_row_count(row_range_start: i64, row_range_end: i64) -> Result<i64> {
if row_range_end < row_range_start {
return Err(Error::DataInvalid {
message: format!("Invalid Lumina row range [{row_range_start},
{row_range_end}]"),
source: None,
});
}
- i32::try_from(row_range_end - row_range_start + 1).map_err(|_|
Error::DataInvalid {
- message: format!(
- "Lumina row count is too large for Rust IndexFileMeta:
[{row_range_start}, {row_range_end}]"
- ),
- source: None,
- })
+ row_range_end
+ .checked_sub(row_range_start)
+ .and_then(|span| span.checked_add(1))
+ .ok_or_else(|| Error::DataInvalid {
+ message: format!(
+ "Row count overflows for row range [{row_range_start},
{row_range_end}]"
+ ),
+ source: None,
+ })
}
fn validate_vector_buffer(vectors: &[f32], row_count: i32, dimension: i32) ->
Result<()> {
@@ -1701,7 +1709,7 @@ mod tests {
index_type: LUMINA_IDENTIFIER.to_string(),
file_name: format!("lumina-synthetic-{start}-{end}.index"),
file_size: 1,
- row_count: (end - start + 1) as i32,
+ row_count: (end - start + 1),
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: start,
diff --git a/crates/paimon/src/table/pk_full_text_bucket_search.rs
b/crates/paimon/src/table/pk_full_text_bucket_search.rs
index d774e237..ecb2ba23 100644
--- a/crates/paimon/src/table/pk_full_text_bucket_search.rs
+++ b/crates/paimon/src/table/pk_full_text_bucket_search.rs
@@ -369,7 +369,7 @@ mod tests {
index_type: PK_FULL_TEXT_INDEX_TYPE.into(),
file_name: file_name.into(),
file_size: 1,
- row_count: total as i32,
+ row_count: total,
deletion_vectors_ranges: None,
global_index_meta: Some(gim(7, frame(level, files))),
}
diff --git a/crates/paimon/src/table/pk_full_text_bucket_state.rs
b/crates/paimon/src/table/pk_full_text_bucket_state.rs
index 48ad4b21..c32cf6e4 100644
--- a/crates/paimon/src/table/pk_full_text_bucket_state.rs
+++ b/crates/paimon/src/table/pk_full_text_bucket_state.rs
@@ -66,7 +66,7 @@ fn payload_matches_source(
None => return false, // overflow → stale
}
}
- i64::from(payload.row_count) == total
+ payload.row_count == total
&& global_meta.row_range_start == 0
&& global_meta.row_range_end == total - 1
}
@@ -297,7 +297,7 @@ mod tests {
fn payload(
file_name: &str,
index_type: &str,
- row_count: i32,
+ row_count: i64,
global_index_meta: Option<GlobalIndexMeta>,
) -> IndexFileMeta {
IndexFileMeta {
diff --git a/crates/paimon/src/table/pk_full_text_read.rs
b/crates/paimon/src/table/pk_full_text_read.rs
index 63b58f84..d5eed2fc 100644
--- a/crates/paimon/src/table/pk_full_text_read.rs
+++ b/crates/paimon/src/table/pk_full_text_read.rs
@@ -684,7 +684,7 @@ mod read_tests {
index_type: PK_FULL_TEXT_INDEX_TYPE.into(),
file_name: file_name.into(),
file_size: 1,
- row_count: total as i32,
+ row_count: total,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: 0,
diff --git a/crates/paimon/src/table/pk_full_text_scan.rs
b/crates/paimon/src/table/pk_full_text_scan.rs
index 5a677655..2ffe0b49 100644
--- a/crates/paimon/src/table/pk_full_text_scan.rs
+++ b/crates/paimon/src/table/pk_full_text_scan.rs
@@ -508,7 +508,7 @@ mod tests {
fn payload(
file_name: &str,
index_type: &str,
- row_count: i32,
+ row_count: i64,
global_index_meta: Option<GlobalIndexMeta>,
) -> IndexFileMeta {
IndexFileMeta {
@@ -526,7 +526,7 @@ mod tests {
payload(
file_name,
PK_FULL_TEXT_INDEX_TYPE,
- total as i32,
+ total,
Some(gim(7, 0, total - 1, Some(frame(level, files)))),
)
}
diff --git a/crates/paimon/src/table/sorted_global_index_build_builder.rs
b/crates/paimon/src/table/sorted_global_index_build_builder.rs
index 94fc3165..de72364b 100644
--- a/crates/paimon/src/table/sorted_global_index_build_builder.rs
+++ b/crates/paimon/src/table/sorted_global_index_build_builder.rs
@@ -715,10 +715,7 @@ async fn extract_index_rows(
read_builder.with_projection(&[index_column, ROW_ID_FIELD_NAME])?;
let read = read_builder.new_read()?;
let batches = read.to_arrow(&splits)?.try_collect::<Vec<_>>().await?;
- let expected_row_count = i64::from(checked_row_count(
- shard.row_range_start,
- shard.row_range_end,
- )?);
+ let expected_row_count = checked_row_count(shard.row_range_start,
shard.row_range_end)?;
if index_type == MULTIVALUE_GLOBAL_INDEX_TYPE {
let DataType::Array(array_type) = index_field.data_type() else {
unreachable!("multivalue field was validated before extraction")
@@ -1017,7 +1014,7 @@ fn checked_i64(value: u64, context: &str) -> Result<i64> {
})
}
-fn checked_row_count(row_range_start: i64, row_range_end: i64) -> Result<i32> {
+fn checked_row_count(row_range_start: i64, row_range_end: i64) -> Result<i64> {
if row_range_end < row_range_start {
return Err(Error::DataInvalid {
message: format!(
@@ -1026,12 +1023,15 @@ fn checked_row_count(row_range_start: i64,
row_range_end: i64) -> Result<i32> {
source: None,
});
}
- i32::try_from(row_range_end - row_range_start + 1).map_err(|_|
Error::DataInvalid {
- message: format!(
- "Sorted global index row count is too large for Rust
IndexFileMeta: [{row_range_start}, {row_range_end}]"
- ),
- source: None,
- })
+ row_range_end
+ .checked_sub(row_range_start)
+ .and_then(|span| span.checked_add(1))
+ .ok_or_else(|| Error::DataInvalid {
+ message: format!(
+ "Row count overflows for row range [{row_range_start},
{row_range_end}]"
+ ),
+ source: None,
+ })
}
fn ranges_overlap(left_start: i64, left_end: i64, right_start: i64, right_end:
i64) -> bool {
@@ -1040,6 +1040,20 @@ fn ranges_overlap(left_start: i64, left_end: i64,
right_start: i64, right_end: i
#[cfg(test)]
mod tests {
+
+ /// A row range wider than `i32::MAX` yields the full count instead of
being
+ /// rejected, and an inverted or overflowing range is still an error.
+ #[test]
+ fn checked_row_count_spans_beyond_i32() {
+ let start = 0;
+ let end = i64::from(i32::MAX) + 10;
+ assert_eq!(
+ super::checked_row_count(start, end).unwrap(),
+ i64::from(i32::MAX) + 11
+ );
+ assert!(super::checked_row_count(5, 4).is_err());
+ assert!(super::checked_row_count(i64::MIN, i64::MAX).is_err());
+ }
use super::*;
use crate::btree::BTreeIndexMeta;
use crate::catalog::Identifier;
@@ -3105,7 +3119,7 @@ mod tests {
index_type: BTREE_GLOBAL_INDEX_TYPE.to_string(),
file_name: "btree-synthetic-hole.index".to_string(),
file_size: 1,
- row_count: (hole_end - hole_start + 1) as i32,
+ row_count: (hole_end - hole_start + 1),
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: hole_start,
diff --git a/crates/paimon/src/table/table_commit.rs
b/crates/paimon/src/table/table_commit.rs
index 96749512..6e5d78c3 100644
--- a/crates/paimon/src/table/table_commit.rs
+++ b/crates/paimon/src/table/table_commit.rs
@@ -3288,7 +3288,7 @@ mod tests {
index_type: "lumina".to_string(),
file_name: name.to_string(),
file_size: 128,
- row_count: (row_range_end - row_range_start + 1) as i32,
+ row_count: (row_range_end - row_range_start + 1),
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start,
diff --git a/crates/paimon/src/table/vector_search_builder.rs
b/crates/paimon/src/table/vector_search_builder.rs
index 9867c582..aa1fdc6d 100644
--- a/crates/paimon/src/table/vector_search_builder.rs
+++ b/crates/paimon/src/table/vector_search_builder.rs
@@ -5701,7 +5701,7 @@ mod tests {
index_type: IVF_FLAT_IDENTIFIER.to_string(),
file_name: index_file_name,
file_size: i64::try_from(index_file_size).unwrap(),
- row_count: i32::try_from(row_count).unwrap(),
+ row_count,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: 0,
diff --git a/crates/paimon/src/table/vindex_index_build_builder.rs
b/crates/paimon/src/table/vindex_index_build_builder.rs
index 881c6308..b0680fe7 100644
--- a/crates/paimon/src/table/vindex_index_build_builder.rs
+++ b/crates/paimon/src/table/vindex_index_build_builder.rs
@@ -1203,7 +1203,7 @@ fn checked_i64(value: u64, context: &str) -> Result<i64> {
})
}
-fn checked_row_count(row_range_start: i64, row_range_end: i64) -> Result<i32> {
+fn checked_row_count(row_range_start: i64, row_range_end: i64) -> Result<i64> {
if row_range_end < row_range_start {
return Err(Error::DataInvalid {
message: format!("Invalid vindex row range [{row_range_start},
{row_range_end}]"),
@@ -1213,10 +1213,9 @@ fn checked_row_count(row_range_start: i64,
row_range_end: i64) -> Result<i32> {
row_range_end
.checked_sub(row_range_start)
.and_then(|count| count.checked_add(1))
- .and_then(|count| i32::try_from(count).ok())
.ok_or_else(|| Error::DataInvalid {
message: format!(
- "vindex row count is too large for Rust IndexFileMeta:
[{row_range_start}, {row_range_end}]"
+ "Row count overflows for row range [{row_range_start},
{row_range_end}]"
),
source: None,
})
@@ -1624,7 +1623,7 @@ mod tests {
index_type: IVF_FLAT_IDENTIFIER.to_string(),
file_name:
format!("vector-ivf-flat-synthetic-{start}-{end}.index"),
file_size: 1,
- row_count: (end - start + 1) as i32,
+ row_count: end - start + 1,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: start,
@@ -1895,7 +1894,7 @@ mod tests {
index_type: "lumina".to_string(),
file_name: "lumina-synthetic-0.index".to_string(),
file_size: 1,
- row_count: (coverage[0].to() - coverage[0].from() + 1) as i32,
+ row_count: (coverage[0].to() - coverage[0].from() + 1) as i64,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: coverage[0].from(),
diff --git a/crates/paimon/tests/pk_vector_baseline_test.rs
b/crates/paimon/tests/pk_vector_baseline_test.rs
index 058e499f..a5c4e90b 100644
--- a/crates/paimon/tests/pk_vector_baseline_test.rs
+++ b/crates/paimon/tests/pk_vector_baseline_test.rs
@@ -424,7 +424,7 @@ async fn build_table_with_first_row_id(
index_type: INDEX_TYPE.to_string(),
file_name: index_file_name,
file_size: i64::try_from(index_file_size).unwrap(),
- row_count: i32::try_from(row_count).unwrap(),
+ row_count,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: 0,
@@ -1271,7 +1271,7 @@ async fn
pk_vector_refine_factor_matches_exact_ground_truth() {
index_type: INDEX_TYPE.to_string(),
file_name: index_file_name,
file_size: i64::try_from(index_file_size).unwrap(),
- row_count: i32::try_from(row_count).unwrap(),
+ row_count,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: 0,
diff --git a/crates/paimon/tests/pk_vector_batch_test.rs
b/crates/paimon/tests/pk_vector_batch_test.rs
index 235d82d8..87e4ca59 100644
--- a/crates/paimon/tests/pk_vector_batch_test.rs
+++ b/crates/paimon/tests/pk_vector_batch_test.rs
@@ -285,7 +285,7 @@ async fn build_table(vectors: &[[f32; DIM]]) ->
(tempfile::TempDir, Table) {
index_type: INDEX_TYPE.to_string(),
file_name: index_file_name,
file_size: i64::try_from(index_file_size).unwrap(),
- row_count: i32::try_from(row_count).unwrap(),
+ row_count,
deletion_vectors_ranges: None,
global_index_meta: Some(GlobalIndexMeta {
row_range_start: 0,