feat: align IndexConfig fields with lance-namespace IndexContent

Add `type_url` and `index_version` to `IndexConfig` so the field set
mirrors the lance-namespace `IndexContent` contract
(lance-format/lance-namespace#348), keeping client and server on the same
shape.

- `type_url`: from `IndexDescription::type_url`
- `index_version`: from the first segment's index version

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Will Jones
2026-06-04 15:05:28 -07:00
parent a6cfbc9606
commit fe22f8cf43
3 changed files with 30 additions and 9 deletions

View File

@@ -371,6 +371,10 @@ pub struct IndexConfig {
/// This is the UUID of the first segment. `None` if it could not be
/// determined (e.g. for remote tables, which do not yet surface this).
pub index_uuid: Option<String>,
/// The protobuf type URL, a precise type identifier for the index.
///
/// `None` if unavailable (e.g. for remote tables).
pub type_url: Option<String>,
/// When the index was created, taken as the minimum creation time across
/// all segments.
///
@@ -387,15 +391,19 @@ pub struct IndexConfig {
/// `None` if size information is unavailable, such as for indices created
/// before file sizes were tracked, or for remote tables.
pub size_bytes: Option<u64>,
/// The number of segments that make up the index.
///
/// `None` if unavailable (e.g. for remote tables).
pub num_segments: Option<u32>,
/// The on-disk index format version, taken from the first segment.
///
/// `None` if unavailable (e.g. for remote tables).
pub index_version: Option<i32>,
/// Index-type-specific details, serialized as JSON.
///
/// The shape of this JSON varies by index type. `None` if the details
/// could not be produced (e.g. no plugin available) or for remote tables.
pub index_details: Option<String>,
/// The number of segments that make up the index.
///
/// `None` if unavailable (e.g. for remote tables).
pub num_segments: Option<u32>,
}
#[skip_serializing_none]

View File

@@ -2049,13 +2049,15 @@ impl<S: HttpSend> BaseTable for RemoteTable<S> {
index_type: stats.index_type,
columns,
// These are left None until the server response wires
// them through. See https://github.com/lancedb/lancedb/issues/3492
// them through. See https://github.com/lancedb/lancedb/issues/3494
index_uuid: None,
type_url: None,
created_at: None,
num_indexed_rows: None,
size_bytes: None,
index_details: None,
num_segments: None,
index_version: None,
index_details: None,
})),
Ok(None) => Ok(None), // The index must have been deleted since we listed it.
Err(e) => Err(e),
@@ -3953,22 +3955,26 @@ mod tests {
index_type: IndexType::IvfPq,
columns: vec!["vector".into()],
index_uuid: None,
type_url: None,
created_at: None,
num_indexed_rows: None,
size_bytes: None,
index_details: None,
num_segments: None,
index_version: None,
index_details: None,
},
IndexConfig {
name: "my_idx".into(),
index_type: IndexType::LabelList,
columns: vec!["metadata.`my.column`".into()],
index_uuid: None,
type_url: None,
created_at: None,
num_indexed_rows: None,
size_bytes: None,
index_details: None,
num_segments: None,
index_version: None,
index_details: None,
},
];
assert_eq!(indices, expected);

View File

@@ -2930,17 +2930,20 @@ impl BaseTable for NativeTable {
let segments = idx_desc.segments();
let index_uuid = segments.first().map(|seg| seg.uuid.to_string());
let created_at = segments.iter().filter_map(|seg| seg.created_at).min();
let index_version = segments.first().map(|seg| seg.index_version);
Some(IndexConfig {
name: idx_desc.name().to_string(),
index_type,
columns,
index_uuid,
type_url: Some(idx_desc.type_url().to_string()),
created_at,
num_indexed_rows: Some(idx_desc.rows_indexed()),
size_bytes: idx_desc.total_size_bytes(),
index_details: idx_desc.details().ok(),
num_segments: Some(segments.len() as u32),
index_version,
index_details: idx_desc.details().ok(),
})
})
.collect();
@@ -3405,10 +3408,12 @@ mod tests {
assert_eq!(index.index_type, crate::index::IndexType::IvfPq);
assert_eq!(index.columns, vec!["embeddings".to_string()]);
assert!(index.index_uuid.is_some());
assert!(index.type_url.is_some());
assert_eq!(index.num_segments, Some(1));
assert_eq!(index.num_indexed_rows, Some(512));
assert!(index.created_at.is_some());
assert!(index.size_bytes.is_some());
assert!(index.index_version.is_some());
assert!(index.index_details.is_some());
assert_eq!(table.count_rows(None).await.unwrap(), 512);
assert_eq!(table.name(), "test");
@@ -3762,10 +3767,12 @@ mod tests {
// The richer metadata surfaced from describe_indices should be populated.
assert!(index.index_uuid.is_some());
assert!(index.type_url.is_some());
assert_eq!(index.num_segments, Some(1));
assert_eq!(index.num_indexed_rows, Some(1));
assert!(index.created_at.is_some());
assert!(index.size_bytes.is_some());
assert!(index.index_version.is_some());
assert!(index.index_details.is_some());
let indices = table.as_native().unwrap().load_indices().await.unwrap();