Skip to content

Commit b6bce65

Browse files
author
Vova Kolmakov
committed
fixed by review note
1 parent 35c27d4 commit b6bce65

3 files changed

Lines changed: 92 additions & 9 deletions

File tree

rust/lance-core/src/datatypes/field.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,17 +1023,22 @@ impl Field {
10231023
///
10241024
/// Call this after modifying `field.metadata` directly (e.g., via UpdateConfig)
10251025
/// to keep structured fields like `unenforced_primary_key_position` in sync.
1026-
pub fn sync_embedded_metadata(&mut self) {
1027-
self.unenforced_primary_key_position = self
1028-
.metadata
1029-
.get(LANCE_UNENFORCED_PRIMARY_KEY_POSITION)
1030-
.and_then(|s| s.parse::<u32>().ok())
1031-
.or_else(|| {
1026+
pub fn sync_embedded_metadata(&mut self) -> Result<()> {
1027+
self.unenforced_primary_key_position =
1028+
if let Some(s) = self.metadata.get(LANCE_UNENFORCED_PRIMARY_KEY_POSITION) {
1029+
Some(s.parse::<u32>().map_err(|e| {
1030+
Error::invalid_input(format!(
1031+
"Invalid value '{}' for {}: {}",
1032+
s, LANCE_UNENFORCED_PRIMARY_KEY_POSITION, e
1033+
))
1034+
})?)
1035+
} else {
10321036
self.metadata
10331037
.get(LANCE_UNENFORCED_PRIMARY_KEY)
10341038
.filter(|s| matches!(s.to_lowercase().as_str(), "true" | "1" | "yes"))
10351039
.map(|_| 0)
1036-
});
1040+
};
1041+
Ok(())
10371042
}
10381043
}
10391044

@@ -1153,7 +1158,7 @@ impl TryFrom<&ArrowField> for Field {
11531158
dictionary: None,
11541159
unenforced_primary_key_position: None,
11551160
};
1156-
result.sync_embedded_metadata();
1161+
result.sync_embedded_metadata()?;
11571162
Ok(result)
11581163
}
11591164
}
@@ -1840,4 +1845,25 @@ mod tests {
18401845
.unwrap();
18411846
assert_eq!(unloaded_projected, unloaded);
18421847
}
1848+
1849+
#[test]
1850+
fn test_try_from_arrow_field_invalid_pk_position_returns_error() {
1851+
let arrow_field =
1852+
ArrowField::new("id", DataType::Int32, false).with_metadata(HashMap::from([(
1853+
LANCE_UNENFORCED_PRIMARY_KEY_POSITION.to_string(),
1854+
"not_a_number".to_string(),
1855+
)]));
1856+
1857+
let result = Field::try_from(&arrow_field);
1858+
assert!(
1859+
result.is_err(),
1860+
"Invalid pk position should fail in TryFrom"
1861+
);
1862+
let err_msg = result.unwrap_err().to_string();
1863+
assert!(
1864+
err_msg.contains("not_a_number"),
1865+
"Error should include the invalid value: {}",
1866+
err_msg
1867+
);
1868+
}
18431869
}

rust/lance/src/dataset/metadata.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,4 +838,61 @@ mod tests {
838838
]
839839
);
840840
}
841+
842+
#[tokio::test]
843+
async fn test_update_field_metadata_invalid_pk_position_returns_error() {
844+
let mut dataset = test_dataset_for_pk().await;
845+
846+
let result = dataset
847+
.update_field_metadata()
848+
.update(
849+
"id",
850+
[("lance-schema:unenforced-primary-key:position", "abc")],
851+
)
852+
.unwrap()
853+
.await;
854+
855+
assert!(result.is_err(), "Non-numeric position should return error");
856+
assert!(matches!(result.unwrap_err(), Error::InvalidInput { .. }));
857+
}
858+
859+
#[tokio::test]
860+
async fn test_update_field_metadata_negative_pk_position_returns_error() {
861+
let mut dataset = test_dataset_for_pk().await;
862+
863+
let result = dataset
864+
.update_field_metadata()
865+
.update(
866+
"id",
867+
[("lance-schema:unenforced-primary-key:position", "-1")],
868+
)
869+
.unwrap()
870+
.await;
871+
872+
assert!(result.is_err(), "Negative position should return error");
873+
assert!(matches!(result.unwrap_err(), Error::InvalidInput { .. }));
874+
}
875+
876+
#[tokio::test]
877+
async fn test_update_field_metadata_overflow_pk_position_returns_error() {
878+
let mut dataset = test_dataset_for_pk().await;
879+
880+
let result = dataset
881+
.update_field_metadata()
882+
.update(
883+
"id",
884+
[(
885+
"lance-schema:unenforced-primary-key:position",
886+
"99999999999",
887+
)],
888+
)
889+
.unwrap()
890+
.await;
891+
892+
assert!(
893+
result.is_err(),
894+
"Overflowing u32 position should return error"
895+
);
896+
assert!(matches!(result.unwrap_err(), Error::InvalidInput { .. }));
897+
}
841898
}

rust/lance/src/dataset/transaction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2327,7 +2327,7 @@ impl Transaction {
23272327
for (field_id, field_metadata_update) in field_metadata_updates {
23282328
if let Some(field) = manifest.schema.field_by_id_mut(*field_id) {
23292329
apply_update_map(&mut field.metadata, field_metadata_update);
2330-
field.sync_embedded_metadata();
2330+
field.sync_embedded_metadata()?;
23312331
} else {
23322332
return Err(Error::invalid_input_source(
23332333
format!("Field with id {} does not exist", field_id).into(),

0 commit comments

Comments
 (0)