Skip to content

Commit 690dc35

Browse files
committed
truncate metadata when drop object builder
1 parent 2b1edde commit 690dc35

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

parquet-variant/src/builder.rs

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,21 @@ impl ParentState<'_> {
584584
| ParentState::List { buffer, .. } => buffer.offset(),
585585
}
586586
}
587+
588+
// return the current index of the undelying metadata buffer at the time of calling this method.
589+
fn metadata_current_offset(&self) -> usize {
590+
match self {
591+
ParentState::Variant {
592+
metadata_builder, ..
593+
}
594+
| ParentState::Object {
595+
metadata_builder, ..
596+
}
597+
| ParentState::List {
598+
metadata_builder, ..
599+
} => metadata_builder.metadata_buffer.len(),
600+
}
601+
}
587602
}
588603

589604
/// Top level builder for [`Variant`] values
@@ -1065,6 +1080,9 @@ pub struct ObjectBuilder<'a> {
10651080
fields: IndexMap<u32, usize>, // (field_id, offset)
10661081
/// the starting offset in the parent's buffer where this object starts
10671082
object_start_offset: usize,
1083+
/// the starting offset in the parent's metadata buffer where this object starts
1084+
/// used to truncate the written fields in `drop` if the current object has not been finished
1085+
object_meta_start_offset: usize,
10681086
/// whether the object has been finished, the written content of the current object
10691087
/// will be truncated in `drop` if `has_been_finished` is false
10701088
has_been_finished: bool,
@@ -1076,11 +1094,13 @@ pub struct ObjectBuilder<'a> {
10761094
impl<'a> ObjectBuilder<'a> {
10771095
fn new(parent_state: ParentState<'a>, validate_unique_fields: bool) -> Self {
10781096
let start_offset = parent_state.buffer_current_offset();
1097+
let meta_start_offset = parent_state.metadata_current_offset();
10791098
Self {
10801099
parent_state,
10811100
fields: IndexMap::new(),
10821101
object_start_offset: start_offset,
10831102
has_been_finished: false,
1103+
object_meta_start_offset: meta_start_offset,
10841104
validate_unique_fields,
10851105
duplicate_fields: HashSet::new(),
10861106
}
@@ -1269,6 +1289,11 @@ impl Drop for ObjectBuilder<'_> {
12691289
.buffer()
12701290
.inner_mut()
12711291
.truncate(self.object_start_offset);
1292+
1293+
self.parent_state
1294+
.metadata_builder()
1295+
.field_names
1296+
.truncate(self.object_meta_start_offset);
12721297
}
12731298
}
12741299
}
@@ -2542,8 +2567,7 @@ mod tests {
25422567
// The original builder should be unchanged
25432568
let (metadata, value) = builder.finish();
25442569
let metadata = VariantMetadata::try_new(&metadata).unwrap();
2545-
assert_eq!(metadata.len(), 1);
2546-
assert_eq!(&metadata[0], "name"); // not rolled back
2570+
assert!(metadata.is_empty()); // rolled back
25472571

25482572
let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
25492573
assert_eq!(variant, Variant::Int8(42));
@@ -2617,8 +2641,7 @@ mod tests {
26172641
list_builder.finish();
26182642
let (metadata, value) = builder.finish();
26192643
let metadata = VariantMetadata::try_new(&metadata).unwrap();
2620-
assert_eq!(metadata.len(), 1);
2621-
assert_eq!(&metadata[0], "name"); // not rolled back
2644+
assert!(metadata.is_empty());
26222645

26232646
let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
26242647
let list = variant.as_list().unwrap();
@@ -2646,8 +2669,8 @@ mod tests {
26462669
// Only the second attempt should appear in the final variant
26472670
let (metadata, value) = builder.finish();
26482671
let metadata = VariantMetadata::try_new(&metadata).unwrap();
2649-
assert_eq!(metadata.len(), 1);
2650-
assert_eq!(&metadata[0], "name"); // not rolled back
2672+
assert_eq!(metadata.len(), 1); // rolled back
2673+
assert_eq!(&metadata[0], "name");
26512674

26522675
let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
26532676
assert_eq!(variant, Variant::Int8(2));
@@ -2700,9 +2723,7 @@ mod tests {
27002723
// Only the second attempt should appear in the final variant
27012724
let (metadata, value) = builder.finish();
27022725
let metadata = VariantMetadata::try_new(&metadata).unwrap();
2703-
assert_eq!(metadata.len(), 2);
2704-
assert_eq!(&metadata[0], "first");
2705-
assert_eq!(&metadata[1], "nested"); // not rolled back
2726+
assert!(metadata.is_empty()); // rolled back
27062727

27072728
let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
27082729
assert_eq!(variant, Variant::Int8(2));
@@ -2725,15 +2746,12 @@ mod tests {
27252746
object_builder.finish().unwrap();
27262747
let (metadata, value) = builder.finish();
27272748
let metadata = VariantMetadata::try_new(&metadata).unwrap();
2728-
assert_eq!(metadata.len(), 3);
2729-
assert_eq!(&metadata[0], "first");
2730-
assert_eq!(&metadata[1], "name"); // not rolled back
2731-
assert_eq!(&metadata[2], "second");
2749+
assert_eq!(metadata.len(), 1); // the fields of nested_object_builder has been rolled back
2750+
assert_eq!(&metadata[0], "second");
27322751

27332752
let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
27342753
let obj = variant.as_object().unwrap();
2735-
assert_eq!(obj.len(), 2);
2736-
assert_eq!(obj.get("first"), Some(Variant::Int8(1)));
2754+
assert_eq!(obj.len(), 1);
27372755
assert_eq!(obj.get("second"), Some(Variant::Int8(2)));
27382756
}
27392757

@@ -2756,10 +2774,7 @@ mod tests {
27562774
// Only the second attempt should appear in the final variant
27572775
let (metadata, value) = builder.finish();
27582776
let metadata = VariantMetadata::try_new(&metadata).unwrap();
2759-
assert_eq!(metadata.len(), 3);
2760-
assert_eq!(&metadata[0], "first"); // not rolled back
2761-
assert_eq!(&metadata[1], "name"); // not rolled back
2762-
assert_eq!(&metadata[2], "nested"); // not rolled back
2777+
assert_eq!(metadata.len(), 0); // rolled back
27632778

27642779
let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
27652780
assert_eq!(variant, Variant::Int8(2));

0 commit comments

Comments
 (0)