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 22a13b6  fix(table): align pk-vector source meta with Java (#531)
22a13b6 is described below

commit 22a13b676280ad18ec4af7a492867dbbf58c9ba4
Author: Junrui Lee <[email protected]>
AuthorDate: Fri Jul 17 08:35:20 2026 +0800

    fix(table): align pk-vector source meta with Java (#531)
---
 crates/paimon/src/spec/pk_vector_source.rs        |  78 ++++++++++----
 crates/paimon/src/table/pk_vector_orchestrator.rs |   1 +
 crates/paimon/src/table/pk_vector_scan.rs         | 124 ++++++++++++++++++++--
 crates/paimon/src/table/vector_search_builder.rs  |  12 +--
 crates/paimon/src/vindex/pkvector/ann.rs          |  19 ++--
 crates/paimon/src/vindex/pkvector/bucket.rs       |   1 +
 crates/paimon/tests/pk_vector_baseline_test.rs    |  13 ++-
 7 files changed, 203 insertions(+), 45 deletions(-)

diff --git a/crates/paimon/src/spec/pk_vector_source.rs 
b/crates/paimon/src/spec/pk_vector_source.rs
index 2c859e0..802cbf7 100644
--- a/crates/paimon/src/spec/pk_vector_source.rs
+++ b/crates/paimon/src/spec/pk_vector_source.rs
@@ -76,15 +76,28 @@ impl PkVectorSourceFile {
 /// Mirrors Java `org.apache.paimon.index.pkvector.PkVectorSourceMeta`.
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct PkVectorSourceMeta {
+    data_level: i32,
     source_files: Vec<PkVectorSourceFile>,
 }
 
 impl PkVectorSourceMeta {
-    pub fn new(source_files: Vec<PkVectorSourceFile>) -> crate::Result<Self> {
+    pub fn new(data_level: i32, source_files: Vec<PkVectorSourceFile>) -> 
crate::Result<Self> {
+        if data_level <= 0 {
+            return Err(data_invalid(format!(
+                "source meta data level must be positive: {data_level}"
+            )));
+        }
         if source_files.is_empty() {
             return Err(data_invalid("a vector index must reference source 
files"));
         }
-        Ok(Self { source_files })
+        Ok(Self {
+            data_level,
+            source_files,
+        })
+    }
+
+    pub fn data_level(&self) -> i32 {
+        self.data_level
     }
 
     pub fn source_files(&self) -> &[PkVectorSourceFile] {
@@ -136,6 +149,12 @@ impl PkVectorSourceMeta {
                 "unsupported vector source version: {version}"
             )));
         }
+        let data_level = cursor.read_i32_be()?;
+        if data_level <= 0 {
+            return Err(data_invalid(format!(
+                "source meta data level must be positive: {data_level}"
+            )));
+        }
         let count = cursor.read_i32_be()?;
         if count <= 0 {
             return Err(data_invalid("a vector index must reference source 
files"));
@@ -152,7 +171,7 @@ impl PkVectorSourceMeta {
                 "unexpected trailing bytes in vector source metadata",
             ));
         }
-        Self::new(source_files)
+        Self::new(data_level, source_files)
     }
 }
 
@@ -270,9 +289,10 @@ mod tests {
         out
     }
 
-    fn frame(files: &[(&str, i64)]) -> Vec<u8> {
+    fn frame(data_level: i32, files: &[(&str, i64)]) -> Vec<u8> {
         let mut out = Vec::new();
         out.extend_from_slice(&1i32.to_be_bytes()); // version
+        out.extend_from_slice(&data_level.to_be_bytes());
         out.extend_from_slice(&(files.len() as i32).to_be_bytes());
         for (name, rows) in files {
             out.extend_from_slice(&java_write_utf(name));
@@ -319,8 +339,9 @@ mod tests {
 
     #[test]
     fn deserialize_single_source_file() {
-        let bytes = frame(&[("data-abc.parquet", 100)]);
+        let bytes = frame(1, &[("data-abc.parquet", 100)]);
         let meta = PkVectorSourceMeta::deserialize(&bytes).unwrap();
+        assert_eq!(meta.data_level(), 1);
         assert_eq!(meta.source_files().len(), 1);
         assert_eq!(meta.source_files()[0].file_name(), "data-abc.parquet");
         assert_eq!(meta.source_files()[0].row_count(), 100);
@@ -328,54 +349,67 @@ mod tests {
 
     #[test]
     fn deserialize_multi_source_files() {
-        let bytes = frame(&[("f0", 3), ("f1", 5)]);
+        let bytes = frame(2, &[("f0", 3), ("f1", 5)]);
         let meta = PkVectorSourceMeta::deserialize(&bytes).unwrap();
+        assert_eq!(meta.data_level(), 2);
         assert_eq!(meta.source_files().len(), 2);
         assert_eq!(meta.source_files()[1].row_count(), 5);
     }
 
     #[test]
     fn deserialize_rejects_bad_version() {
-        let mut bytes = frame(&[("f0", 1)]);
+        let mut bytes = frame(1, &[("f0", 1)]);
         bytes[0..4].copy_from_slice(&2i32.to_be_bytes());
         assert!(PkVectorSourceMeta::deserialize(&bytes).is_err());
     }
 
+    #[test]
+    fn deserialize_rejects_zero_or_negative_data_level() {
+        assert!(PkVectorSourceMeta::deserialize(&frame(0, &[("f0", 
1)])).is_err());
+        assert!(PkVectorSourceMeta::deserialize(&frame(-1, &[("f0", 
1)])).is_err());
+    }
+
     #[test]
     fn deserialize_rejects_zero_count() {
         let mut out = Vec::new();
         out.extend_from_slice(&1i32.to_be_bytes());
+        out.extend_from_slice(&1i32.to_be_bytes());
         out.extend_from_slice(&0i32.to_be_bytes());
         assert!(PkVectorSourceMeta::deserialize(&out).is_err());
     }
 
     #[test]
     fn deserialize_rejects_trailing_bytes() {
-        let mut bytes = frame(&[("f0", 1)]);
+        let mut bytes = frame(1, &[("f0", 1)]);
         bytes.push(0xFF);
         assert!(PkVectorSourceMeta::deserialize(&bytes).is_err());
     }
 
     #[test]
     fn deserialize_rejects_truncated_input() {
-        let bytes = frame(&[("f0", 1)]);
+        let bytes = frame(1, &[("f0", 1)]);
         assert!(PkVectorSourceMeta::deserialize(&bytes[..bytes.len() - 
2]).is_err());
     }
 
     #[test]
     fn deserialize_rejects_negative_row_count() {
-        let bytes = frame(&[("f0", -1)]);
+        let bytes = frame(1, &[("f0", -1)]);
         assert!(PkVectorSourceMeta::deserialize(&bytes).is_err());
     }
 
     #[test]
     fn new_rejects_empty() {
-        assert!(PkVectorSourceMeta::new(Vec::new()).is_err());
+        assert!(PkVectorSourceMeta::new(1, Vec::new()).is_err());
+        assert!(PkVectorSourceMeta::new(
+            0,
+            vec![PkVectorSourceFile::new("f0".to_string(), 1).unwrap()]
+        )
+        .is_err());
     }
 
     #[test]
     fn resolve_single_file() {
-        let meta = PkVectorSourceMeta::deserialize(&frame(&[("f0", 
3)])).unwrap();
+        let meta = PkVectorSourceMeta::deserialize(&frame(1, &[("f0", 
3)])).unwrap();
         assert_eq!(meta.resolve(0).unwrap(), ("f0".to_string(), 0));
         assert_eq!(meta.resolve(2).unwrap(), ("f0".to_string(), 2));
     }
@@ -383,7 +417,7 @@ mod tests {
     #[test]
     fn resolve_multi_file_prefix_sum_boundaries() {
         // f0 owns ordinals 0..=2, f1 owns 3..=7.
-        let meta = PkVectorSourceMeta::deserialize(&frame(&[("f0", 3), ("f1", 
5)])).unwrap();
+        let meta = PkVectorSourceMeta::deserialize(&frame(1, &[("f0", 3), 
("f1", 5)])).unwrap();
         assert_eq!(meta.resolve(2).unwrap(), ("f0".to_string(), 2)); // last 
of f0
         assert_eq!(meta.resolve(3).unwrap(), ("f1".to_string(), 0)); // first 
of f1
         assert_eq!(meta.resolve(7).unwrap(), ("f1".to_string(), 4)); // last 
of f1
@@ -391,13 +425,13 @@ mod tests {
 
     #[test]
     fn resolve_rejects_negative_ordinal() {
-        let meta = PkVectorSourceMeta::deserialize(&frame(&[("f0", 
3)])).unwrap();
+        let meta = PkVectorSourceMeta::deserialize(&frame(1, &[("f0", 
3)])).unwrap();
         assert!(meta.resolve(-1).is_err());
     }
 
     #[test]
     fn resolve_rejects_ordinal_at_or_past_total() {
-        let meta = PkVectorSourceMeta::deserialize(&frame(&[("f0", 
3)])).unwrap();
+        let meta = PkVectorSourceMeta::deserialize(&frame(1, &[("f0", 
3)])).unwrap();
         assert!(meta.resolve(3).is_err()); // total == 3, valid range 0..=2
     }
 
@@ -422,9 +456,10 @@ mod tests {
             index_field_id: 0,
             extra_field_ids: None,
             index_meta: None,
-            source_meta: Some(frame(&[("f0", 3)])),
+            source_meta: Some(frame(1, &[("f0", 3)])),
         };
         let parsed = 
PkVectorSourceMeta::from_global_index_meta(&meta).unwrap();
+        assert_eq!(parsed.data_level(), 1);
         assert_eq!(parsed.source_files()[0].file_name(), "f0");
     }
 
@@ -432,10 +467,13 @@ mod tests {
     fn resolve_rejects_row_count_overflow() {
         // Two individually-valid row counts whose prefix sum overflows i64.
         // Resolving past the first file forces the checked_add on the second.
-        let meta = PkVectorSourceMeta::new(vec![
-            PkVectorSourceFile::new("f0".to_string(), i64::MAX).unwrap(),
-            PkVectorSourceFile::new("f1".to_string(), 1).unwrap(),
-        ])
+        let meta = PkVectorSourceMeta::new(
+            1,
+            vec![
+                PkVectorSourceFile::new("f0".to_string(), i64::MAX).unwrap(),
+                PkVectorSourceFile::new("f1".to_string(), 1).unwrap(),
+            ],
+        )
         .unwrap();
         assert!(meta.resolve(i64::MAX).is_err());
     }
diff --git a/crates/paimon/src/table/pk_vector_orchestrator.rs 
b/crates/paimon/src/table/pk_vector_orchestrator.rs
index 66a7543..59ee64c 100644
--- a/crates/paimon/src/table/pk_vector_orchestrator.rs
+++ b/crates/paimon/src/table/pk_vector_orchestrator.rs
@@ -764,6 +764,7 @@ mod e2e_tests {
     fn ann_segment(sources: &[(&str, i64)]) -> BucketAnnSegment {
         BucketAnnSegment::for_test(
             PkVectorSourceMeta::new(
+                1,
                 sources
                     .iter()
                     .map(|(n, r)| PkVectorSourceFile::new((*n).to_string(), 
*r).unwrap())
diff --git a/crates/paimon/src/table/pk_vector_scan.rs 
b/crates/paimon/src/table/pk_vector_scan.rs
index d5547e5..a8219fd 100644
--- a/crates/paimon/src/table/pk_vector_scan.rs
+++ b/crates/paimon/src/table/pk_vector_scan.rs
@@ -23,7 +23,8 @@
 use std::collections::{BTreeMap, HashSet};
 
 use crate::spec::{
-    BinaryRow, DataFileMeta, FileKind, GlobalIndexMeta, IndexManifest, 
PkVectorSourceMeta,
+    BinaryRow, DataFileMeta, FileKind, GlobalIndexMeta, IndexManifest, 
PkVectorSourceFile,
+    PkVectorSourceMeta,
 };
 use crate::table::pk_vector_orchestrator::PkVectorSearchSplit;
 use crate::table::source::{DataSplit, DataSplitBuilder, DeletionFile};
@@ -46,6 +47,56 @@ fn should_read_pk_index_source(file: &DataFileMeta) -> bool {
     matches!(file.file_source, Some(src) if src == FILE_SOURCE_COMPACT) && 
file.level > 0
 }
 
+fn source_files_unique(files: &[PkVectorSourceFile]) -> bool {
+    let mut seen = HashSet::new();
+    files.iter().all(|file| seen.insert(file.file_name()))
+}
+
+fn current_ann_segments(
+    active_data_files: &[DataFileMeta],
+    ann_segments: Vec<BucketAnnSegment>,
+) -> crate::Result<Vec<BucketAnnSegment>> {
+    let mut sources_by_level: BTreeMap<i32, Vec<PkVectorSourceFile>> = 
BTreeMap::new();
+    for file in active_data_files {
+        if should_read_pk_index_source(file) {
+            sources_by_level
+                .entry(file.level)
+                .or_default()
+                .push(PkVectorSourceFile::new(
+                    file.file_name.clone(),
+                    file.row_count,
+                )?);
+        }
+    }
+    for sources in sources_by_level.values_mut() {
+        sources.sort_by(|a, b| a.file_name().cmp(b.file_name()));
+    }
+
+    let mut segments_by_level: BTreeMap<i32, Vec<BucketAnnSegment>> = 
BTreeMap::new();
+    for segment in ann_segments {
+        let source_meta = &segment.source_meta;
+        let Some(desired) = sources_by_level.get(&source_meta.data_level()) 
else {
+            continue;
+        };
+        if source_files_unique(source_meta.source_files())
+            && desired.as_slice() == source_meta.source_files()
+        {
+            segments_by_level
+                .entry(source_meta.data_level())
+                .or_default()
+                .push(segment);
+        }
+    }
+
+    let mut current = Vec::new();
+    for mut level_segments in segments_by_level.into_values() {
+        if level_segments.len() == 1 {
+            current.push(level_segments.remove(0));
+        }
+    }
+    Ok(current)
+}
+
 /// Combines one bucket's data splits into a single split, keeping data files 
and
 /// deletion files in strict parallel order and rejecting duplicate file names.
 struct BucketAccumulator {
@@ -284,8 +335,11 @@ fn plan_from_inputs(
     // Phase C: assemble one split per bucket that has data.
     let mut out = Vec::new();
     for (key, acc) in accum_by_bucket {
-        let ann_segments = segments_by_bucket.remove(&key).unwrap_or_default();
         let data_split = acc.build()?;
+        let ann_segments = current_ann_segments(
+            data_split.data_files(),
+            segments_by_bucket.remove(&key).unwrap_or_default(),
+        )?;
         let active_files: Vec<BucketActiveFile> = data_split
             .data_files()
             .iter()
@@ -369,9 +423,10 @@ mod tests {
     /// Build a `_SOURCE_META` blob the way `PkVectorSourceMeta::deserialize`
     /// expects it. There is no public serializer, so we mirror the frame used 
by
     /// `pk_vector_source.rs`'s own round-trip tests.
-    fn source_meta_bytes(files: &[(&str, i64)]) -> Vec<u8> {
+    fn source_meta_bytes(data_level: i32, files: &[(&str, i64)]) -> Vec<u8> {
         let mut out = Vec::new();
         out.extend_from_slice(&1i32.to_be_bytes()); // version
+        out.extend_from_slice(&data_level.to_be_bytes());
         out.extend_from_slice(&(files.len() as i32).to_be_bytes());
         for (name, rows) in files {
             out.extend_from_slice(&java_write_utf(name));
@@ -380,14 +435,32 @@ mod tests {
         out
     }
 
-    fn gim(field_id: i32, source_files: &[(&str, i64)]) -> GlobalIndexMeta {
+    fn gim(field_id: i32, data_level: i32, source_files: &[(&str, i64)]) -> 
GlobalIndexMeta {
         GlobalIndexMeta {
             row_range_start: 0,
             row_range_end: 0,
             index_field_id: field_id,
             extra_field_ids: None,
             index_meta: Some(vec![1, 2, 3]),
-            source_meta: Some(source_meta_bytes(source_files)),
+            source_meta: Some(source_meta_bytes(data_level, source_files)),
+        }
+    }
+
+    fn ann_segment(data_level: i32, path: &str, source_files: &[(&str, i64)]) 
-> BucketAnnSegment {
+        BucketAnnSegment {
+            source_meta: PkVectorSourceMeta::new(
+                data_level,
+                source_files
+                    .iter()
+                    .map(|(name, rows)| {
+                        PkVectorSourceFile::new((*name).to_string(), 
*rows).unwrap()
+                    })
+                    .collect(),
+            )
+            .unwrap(),
+            path: path.to_string(),
+            file_size: 1,
+            index_meta: Vec::new(),
         }
     }
 
@@ -397,7 +470,7 @@ mod tests {
         let entries = vec![(
             BinaryRow::new(0),
             0,
-            gim(2, &[("d0", 3)]),
+            gim(2, 5, &[("d0", 3)]),
             "idx/seg0".to_string(),
             10u64,
             "seg0".to_string(),
@@ -411,7 +484,7 @@ mod tests {
         let entries = vec![(
             BinaryRow::new(0),
             0,
-            gim(2, &[("d0", 3)]),
+            gim(2, 5, &[("d0", 3)]),
             "idx/seg0".to_string(),
             10u64,
             "seg0".to_string(),
@@ -436,6 +509,43 @@ mod tests {
         assert_eq!(splits[0].active_files[0].file_name, "d0");
     }
 
+    #[test]
+    fn current_segments_require_exact_level_source_set() {
+        let active = vec![
+            dfm("b", 2, 5, Some(1)),
+            dfm("a", 1, 5, Some(1)),
+            dfm("c", 3, 6, Some(1)),
+        ];
+        let current = current_ann_segments(
+            &active,
+            vec![
+                // Matches level 5 after active files are sorted by file name.
+                ann_segment(5, "current-l5", &[("a", 1), ("b", 2)]),
+                // Wrong level for the same source files -> stale.
+                ann_segment(4, "wrong-level", &[("a", 1), ("b", 2)]),
+                // Incomplete level 6 coverage -> stale.
+                ann_segment(6, "partial-l6", &[("c", 2)]),
+            ],
+        )
+        .unwrap();
+        assert_eq!(current.len(), 1);
+        assert_eq!(current[0].path, "current-l5");
+    }
+
+    #[test]
+    fn current_segments_drop_all_when_level_has_multiple_matches() {
+        let active = vec![dfm("a", 1, 5, Some(1))];
+        let current = current_ann_segments(
+            &active,
+            vec![
+                ann_segment(5, "first", &[("a", 1)]),
+                ann_segment(5, "second", &[("a", 1)]),
+            ],
+        )
+        .unwrap();
+        assert!(current.is_empty());
+    }
+
     #[test]
     fn rejects_data_split_with_wrong_snapshot() {
         let data = DataSplitBuilder::new()
diff --git a/crates/paimon/src/table/vector_search_builder.rs 
b/crates/paimon/src/table/vector_search_builder.rs
index 97f8b2e..122af04 100644
--- a/crates/paimon/src/table/vector_search_builder.rs
+++ b/crates/paimon/src/table/vector_search_builder.rs
@@ -2653,13 +2653,11 @@ mod tests {
     /// A `PkVectorSearchSplit` carrying a single ANN segment addressed by 
`path`.
     fn pk_split_with_segment(path: &str) -> PkVectorSearchSplit {
         let mut split = pk_search_split(0, vec![pk_data_file("file-a", 3, 
Some(0))]);
-        let source_meta =
-            
crate::spec::PkVectorSourceMeta::new(vec![crate::spec::PkVectorSourceFile::new(
-                "file-a".to_string(),
-                3,
-            )
-            .unwrap()])
-            .unwrap();
+        let source_meta = crate::spec::PkVectorSourceMeta::new(
+            1,
+            vec![crate::spec::PkVectorSourceFile::new("file-a".to_string(), 
3).unwrap()],
+        )
+        .unwrap();
         let mut segment = BucketAnnSegment::for_test(source_meta);
         segment.path = path.to_string();
         split.ann_segments = vec![segment];
diff --git a/crates/paimon/src/vindex/pkvector/ann.rs 
b/crates/paimon/src/vindex/pkvector/ann.rs
index 0d1559b..aad463f 100644
--- a/crates/paimon/src/vindex/pkvector/ann.rs
+++ b/crates/paimon/src/vindex/pkvector/ann.rs
@@ -221,7 +221,7 @@ mod tests {
             .iter()
             .map(|(name, rows)| PkVectorSourceFile::new((*name).to_string(), 
*rows).unwrap())
             .collect();
-        PkVectorSourceMeta::new(files).unwrap()
+        PkVectorSourceMeta::new(1, files).unwrap()
     }
 
     fn dv(deleted: &[u32]) -> Arc<DeletionVector> {
@@ -379,10 +379,13 @@ mod tests {
         );
         let segment = BucketAnnSegment::for_test({
             use crate::spec::{PkVectorSourceFile, PkVectorSourceMeta};
-            PkVectorSourceMeta::new(vec![
-                PkVectorSourceFile::new("f0".into(), 3).unwrap(),
-                PkVectorSourceFile::new("f1".into(), 5).unwrap(),
-            ])
+            PkVectorSourceMeta::new(
+                1,
+                vec![
+                    PkVectorSourceFile::new("f0".into(), 3).unwrap(),
+                    PkVectorSourceFile::new("f1".into(), 5).unwrap(),
+                ],
+            )
             .unwrap()
         });
         let mut dvs = HashMap::new();
@@ -416,7 +419,8 @@ mod tests {
         );
         let segment = BucketAnnSegment::for_test({
             use crate::spec::{PkVectorSourceFile, PkVectorSourceMeta};
-            PkVectorSourceMeta::new(vec![PkVectorSourceFile::new("f0".into(), 
1).unwrap()]).unwrap()
+            PkVectorSourceMeta::new(1, 
vec![PkVectorSourceFile::new("f0".into(), 1).unwrap()])
+                .unwrap()
         });
         let err = searcher
             .search(
@@ -440,7 +444,8 @@ mod tests {
         );
         let segment = BucketAnnSegment::for_test({
             use crate::spec::{PkVectorSourceFile, PkVectorSourceMeta};
-            PkVectorSourceMeta::new(vec![PkVectorSourceFile::new("f0".into(), 
1).unwrap()]).unwrap()
+            PkVectorSourceMeta::new(1, 
vec![PkVectorSourceFile::new("f0".into(), 1).unwrap()])
+                .unwrap()
         });
         let results = searcher
             .search(
diff --git a/crates/paimon/src/vindex/pkvector/bucket.rs 
b/crates/paimon/src/vindex/pkvector/bucket.rs
index 337e922..fcd7d1f 100644
--- a/crates/paimon/src/vindex/pkvector/bucket.rs
+++ b/crates/paimon/src/vindex/pkvector/bucket.rs
@@ -289,6 +289,7 @@ mod tests {
 
     fn meta(files: &[(&str, i64)]) -> PkVectorSourceMeta {
         PkVectorSourceMeta::new(
+            1,
             files
                 .iter()
                 .map(|(n, r)| PkVectorSourceFile::new((*n).into(), 
*r).unwrap())
diff --git a/crates/paimon/tests/pk_vector_baseline_test.rs 
b/crates/paimon/tests/pk_vector_baseline_test.rs
index 1cb0399..e1e3177 100644
--- a/crates/paimon/tests/pk_vector_baseline_test.rs
+++ b/crates/paimon/tests/pk_vector_baseline_test.rs
@@ -196,11 +196,13 @@ fn java_write_utf(s: &str) -> Vec<u8> {
 
 /// Assemble the `_SOURCE_META` frame the way Java `PkVectorSourceMeta` writes 
it
 /// and `PkVectorSourceMeta::deserialize` expects: `i32-BE version=1`, `i32-BE
-/// count`, then per source file a `writeUTF` name and an `i64-BE` row count. 
No
-/// trailing bytes. Source files are listed in global ordinal order.
-fn source_meta_bytes(files: &[(&str, i64)]) -> Vec<u8> {
+/// data_level`, `i32-BE count`, then per source file a `writeUTF` name and an
+/// `i64-BE` row count. No trailing bytes. Source files are listed in global
+/// ordinal order.
+fn source_meta_bytes(data_level: i32, files: &[(&str, i64)]) -> Vec<u8> {
     let mut out = Vec::new();
     out.extend_from_slice(&1i32.to_be_bytes()); // version
+    out.extend_from_slice(&data_level.to_be_bytes());
     out.extend_from_slice(&(files.len() as i32).to_be_bytes());
     for (name, rows) in files {
         out.extend_from_slice(&java_write_utf(name));
@@ -396,7 +398,10 @@ async fn build_table(
             row_range_end: row_count - 1,
             index_field_id: vector_field_id,
             extra_field_ids: None,
-            source_meta: Some(source_meta_bytes(&[(&data_file_name, 
row_count)])),
+            source_meta: Some(source_meta_bytes(
+                indexed_meta.level,
+                &[(&data_file_name, row_count)],
+            )),
             index_meta: None,
         }),
     };

Reply via email to