Skip to content

Commit b269422

Browse files
[Variant] Check pending before VariantObject::insert (#7786)
# Rationale for this change A follow up from #7778, we should make sure to check for pending fields before calling `ObjectBuilder::insert`
1 parent d6c421c commit b269422

File tree

1 file changed

+76
-11
lines changed

1 file changed

+76
-11
lines changed

parquet-variant/src/builder.rs

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -597,29 +597,31 @@ impl<'a, 'b> ObjectBuilder<'a, 'b> {
597597
}
598598
}
599599

600+
fn check_pending_field(&mut self) {
601+
let Some((field_name, field_start)) = self.pending.as_ref() else {
602+
return;
603+
};
604+
605+
let field_id = self.metadata_builder.add_field_name(field_name);
606+
self.fields.insert(field_id, *field_start);
607+
608+
self.pending = None;
609+
}
610+
600611
/// Add a field with key and value to the object
601612
///
602613
/// Note: when inserting duplicate keys, the new value overwrites the previous mapping,
603614
/// but the old value remains in the buffer, resulting in a larger variant
604615
pub fn insert<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, key: &str, value: T) {
616+
self.check_pending_field();
617+
605618
let field_id = self.metadata_builder.add_field_name(key);
606619
let field_start = self.buffer.offset();
607620

608621
self.fields.insert(field_id, field_start);
609622
self.buffer.append_non_nested_value(value);
610623
}
611624

612-
fn check_pending_field(&mut self) {
613-
let Some((field_name, field_start)) = self.pending.as_ref() else {
614-
return;
615-
};
616-
617-
let field_id = self.metadata_builder.add_field_name(field_name);
618-
self.fields.insert(field_id, *field_start);
619-
620-
self.pending = None;
621-
}
622-
623625
/// Return a new [`ObjectBuilder`] to add a nested object with the specified
624626
/// key to the object.
625627
pub fn new_object(&mut self, key: &'b str) -> ObjectBuilder {
@@ -1364,4 +1366,67 @@ mod tests {
13641366
assert_eq!(items_list.get(0).unwrap(), Variant::from("apple"));
13651367
assert_eq!(items_list.get(1).unwrap(), Variant::from(false));
13661368
}
1369+
1370+
#[test]
1371+
fn test_nested_object_with_heterogeneous_fields() {
1372+
/*
1373+
{
1374+
"a": false,
1375+
"c": {
1376+
"b": "a"
1377+
}
1378+
"b": true,
1379+
}
1380+
*/
1381+
1382+
let mut builder = VariantBuilder::new();
1383+
{
1384+
let mut outer_object_builder = builder.new_object();
1385+
1386+
outer_object_builder.insert("a", false);
1387+
1388+
{
1389+
let mut inner_object_builder = outer_object_builder.new_object("c");
1390+
inner_object_builder.insert("b", "a");
1391+
inner_object_builder.finish();
1392+
}
1393+
1394+
outer_object_builder.insert("b", true);
1395+
1396+
outer_object_builder.finish();
1397+
}
1398+
1399+
let (metadata, value) = builder.finish();
1400+
1401+
// note, object fields are now sorted lexigraphically by field name
1402+
/*
1403+
{
1404+
"a": false,
1405+
"b": true,
1406+
"c": {
1407+
"b": "a"
1408+
}
1409+
}
1410+
*/
1411+
1412+
let variant = Variant::try_new(&metadata, &value).unwrap();
1413+
let outer_object = variant.as_object().unwrap();
1414+
1415+
assert_eq!(outer_object.len(), 3);
1416+
1417+
assert_eq!(outer_object.field_name(0).unwrap(), "a");
1418+
assert_eq!(outer_object.field(0).unwrap(), Variant::from(false));
1419+
1420+
assert_eq!(outer_object.field_name(2).unwrap(), "c");
1421+
1422+
let inner_object_variant = outer_object.field(2).unwrap();
1423+
let inner_object = inner_object_variant.as_object().unwrap();
1424+
1425+
assert_eq!(inner_object.len(), 1);
1426+
assert_eq!(inner_object.field_name(0).unwrap(), "b");
1427+
assert_eq!(inner_object.field(0).unwrap(), Variant::from("a"));
1428+
1429+
assert_eq!(outer_object.field_name(1).unwrap(), "b");
1430+
assert_eq!(outer_object.field(1).unwrap(), Variant::from(true));
1431+
}
13671432
}

0 commit comments

Comments
 (0)