Skip to content

Commit cec24a0

Browse files
authored
[Variant] Caller provides ParentState to ValueBuilder methods (apache#8189)
# Which issue does this PR close? - Closes apache#8188 # Rationale for this change Today, `ValueBuilder::[try_]append_variant` unconditionally creates and uses a `ParentState::Variant`, but that is incorrect when the caller is a `ListBuilder` or `ObjectBuilder`. Rework the API so that the caller passes their parent state, thus ensuring proper rollback in all situations. This is also a building block that will eventually let us simplify `VariantArrayBuilder` to use a `ValueBuilder` directly, instead of a `VariantBuilder`. # What changes are included in this PR? Several methods become associated functions. # Are these changes tested? Existing unit tests cover this refactor. # Are there any user-facing changes? No
1 parent d5701d2 commit cec24a0

File tree

1 file changed

+81
-112
lines changed

1 file changed

+81
-112
lines changed

parquet-variant/src/builder.rs

Lines changed: 81 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,8 @@ impl ValueBuilder {
251251
self.append_slice(value.as_bytes());
252252
}
253253

254-
fn append_object(&mut self, metadata_builder: &mut MetadataBuilder, obj: VariantObject) {
255-
let mut object_builder = self.new_object(metadata_builder);
254+
fn append_object(state: ParentState<'_>, obj: VariantObject) {
255+
let mut object_builder = ObjectBuilder::new(state, false);
256256

257257
for (field_name, value) in obj.iter() {
258258
object_builder.insert(field_name, value);
@@ -261,37 +261,27 @@ impl ValueBuilder {
261261
object_builder.finish().unwrap();
262262
}
263263

264-
fn try_append_object(
265-
&mut self,
266-
metadata_builder: &mut MetadataBuilder,
267-
obj: VariantObject,
268-
) -> Result<(), ArrowError> {
269-
let mut object_builder = self.new_object(metadata_builder);
264+
fn try_append_object(state: ParentState<'_>, obj: VariantObject) -> Result<(), ArrowError> {
265+
let mut object_builder = ObjectBuilder::new(state, false);
270266

271267
for res in obj.iter_try() {
272268
let (field_name, value) = res?;
273269
object_builder.try_insert(field_name, value)?;
274270
}
275271

276-
object_builder.finish()?;
277-
278-
Ok(())
272+
object_builder.finish()
279273
}
280274

281-
fn append_list(&mut self, metadata_builder: &mut MetadataBuilder, list: VariantList) {
282-
let mut list_builder = self.new_list(metadata_builder);
275+
fn append_list(state: ParentState<'_>, list: VariantList) {
276+
let mut list_builder = ListBuilder::new(state, false);
283277
for value in list.iter() {
284278
list_builder.append_value(value);
285279
}
286280
list_builder.finish();
287281
}
288282

289-
fn try_append_list(
290-
&mut self,
291-
metadata_builder: &mut MetadataBuilder,
292-
list: VariantList,
293-
) -> Result<(), ArrowError> {
294-
let mut list_builder = self.new_list(metadata_builder);
283+
fn try_append_list(state: ParentState<'_>, list: VariantList) -> Result<(), ArrowError> {
284+
let mut list_builder = ListBuilder::new(state, false);
295285
for res in list.iter_try() {
296286
let value = res?;
297287
list_builder.try_append_value(value)?;
@@ -306,93 +296,80 @@ impl ValueBuilder {
306296
self.0.len()
307297
}
308298

309-
fn new_object<'a>(
310-
&'a mut self,
311-
metadata_builder: &'a mut MetadataBuilder,
312-
) -> ObjectBuilder<'a> {
313-
let parent_state = ParentState::variant(self, metadata_builder);
314-
let validate_unique_fields = false;
315-
ObjectBuilder::new(parent_state, validate_unique_fields)
316-
}
317-
318-
fn new_list<'a>(&'a mut self, metadata_builder: &'a mut MetadataBuilder) -> ListBuilder<'a> {
319-
let parent_state = ParentState::variant(self, metadata_builder);
320-
let validate_unique_fields = false;
321-
ListBuilder::new(parent_state, validate_unique_fields)
322-
}
323-
324299
/// Appends a variant to the builder.
325300
///
326301
/// # Panics
327302
///
328303
/// This method will panic if the variant contains duplicate field names in objects
329304
/// when validation is enabled. For a fallible version, use [`ValueBuilder::try_append_variant`]
330-
fn append_variant<'m, 'd>(
331-
&mut self,
332-
variant: Variant<'m, 'd>,
333-
metadata_builder: &mut MetadataBuilder,
334-
) {
305+
fn append_variant(mut state: ParentState<'_>, variant: Variant<'_, '_>) {
306+
let builder = state.value_builder();
335307
match variant {
336-
Variant::Null => self.append_null(),
337-
Variant::BooleanTrue => self.append_bool(true),
338-
Variant::BooleanFalse => self.append_bool(false),
339-
Variant::Int8(v) => self.append_int8(v),
340-
Variant::Int16(v) => self.append_int16(v),
341-
Variant::Int32(v) => self.append_int32(v),
342-
Variant::Int64(v) => self.append_int64(v),
343-
Variant::Date(v) => self.append_date(v),
344-
Variant::TimestampMicros(v) => self.append_timestamp_micros(v),
345-
Variant::TimestampNtzMicros(v) => self.append_timestamp_ntz_micros(v),
346-
Variant::TimestampNanos(v) => self.append_timestamp_nanos(v),
347-
Variant::TimestampNtzNanos(v) => self.append_timestamp_ntz_nanos(v),
348-
Variant::Decimal4(decimal4) => self.append_decimal4(decimal4),
349-
Variant::Decimal8(decimal8) => self.append_decimal8(decimal8),
350-
Variant::Decimal16(decimal16) => self.append_decimal16(decimal16),
351-
Variant::Float(v) => self.append_float(v),
352-
Variant::Double(v) => self.append_double(v),
353-
Variant::Binary(v) => self.append_binary(v),
354-
Variant::String(s) => self.append_string(s),
355-
Variant::ShortString(s) => self.append_short_string(s),
356-
Variant::Uuid(v) => self.append_uuid(v),
357-
Variant::Object(obj) => self.append_object(metadata_builder, obj),
358-
Variant::List(list) => self.append_list(metadata_builder, list),
359-
Variant::Time(v) => self.append_time_micros(v),
308+
Variant::Null => builder.append_null(),
309+
Variant::BooleanTrue => builder.append_bool(true),
310+
Variant::BooleanFalse => builder.append_bool(false),
311+
Variant::Int8(v) => builder.append_int8(v),
312+
Variant::Int16(v) => builder.append_int16(v),
313+
Variant::Int32(v) => builder.append_int32(v),
314+
Variant::Int64(v) => builder.append_int64(v),
315+
Variant::Date(v) => builder.append_date(v),
316+
Variant::Time(v) => builder.append_time_micros(v),
317+
Variant::TimestampMicros(v) => builder.append_timestamp_micros(v),
318+
Variant::TimestampNtzMicros(v) => builder.append_timestamp_ntz_micros(v),
319+
Variant::TimestampNanos(v) => builder.append_timestamp_nanos(v),
320+
Variant::TimestampNtzNanos(v) => builder.append_timestamp_ntz_nanos(v),
321+
Variant::Decimal4(decimal4) => builder.append_decimal4(decimal4),
322+
Variant::Decimal8(decimal8) => builder.append_decimal8(decimal8),
323+
Variant::Decimal16(decimal16) => builder.append_decimal16(decimal16),
324+
Variant::Float(v) => builder.append_float(v),
325+
Variant::Double(v) => builder.append_double(v),
326+
Variant::Binary(v) => builder.append_binary(v),
327+
Variant::String(s) => builder.append_string(s),
328+
Variant::ShortString(s) => builder.append_short_string(s),
329+
Variant::Uuid(v) => builder.append_uuid(v),
330+
Variant::Object(obj) => return Self::append_object(state, obj),
331+
Variant::List(list) => return Self::append_list(state, list),
360332
}
333+
state.finish();
361334
}
362335

363-
/// Appends a variant to the builder
364-
fn try_append_variant<'m, 'd>(
365-
&mut self,
366-
variant: Variant<'m, 'd>,
367-
metadata_builder: &mut MetadataBuilder,
336+
/// Tries to append a variant to the provided [`ParentState`] instance.
337+
///
338+
/// The attempt fails if the variant contains duplicate field names in objects when validation
339+
/// is enabled.
340+
pub fn try_append_variant(
341+
mut state: ParentState<'_>,
342+
variant: Variant<'_, '_>,
368343
) -> Result<(), ArrowError> {
344+
let builder = state.value_builder();
369345
match variant {
370-
Variant::Null => self.append_null(),
371-
Variant::BooleanTrue => self.append_bool(true),
372-
Variant::BooleanFalse => self.append_bool(false),
373-
Variant::Int8(v) => self.append_int8(v),
374-
Variant::Int16(v) => self.append_int16(v),
375-
Variant::Int32(v) => self.append_int32(v),
376-
Variant::Int64(v) => self.append_int64(v),
377-
Variant::Date(v) => self.append_date(v),
378-
Variant::TimestampMicros(v) => self.append_timestamp_micros(v),
379-
Variant::TimestampNtzMicros(v) => self.append_timestamp_ntz_micros(v),
380-
Variant::TimestampNanos(v) => self.append_timestamp_nanos(v),
381-
Variant::TimestampNtzNanos(v) => self.append_timestamp_ntz_nanos(v),
382-
Variant::Decimal4(decimal4) => self.append_decimal4(decimal4),
383-
Variant::Decimal8(decimal8) => self.append_decimal8(decimal8),
384-
Variant::Decimal16(decimal16) => self.append_decimal16(decimal16),
385-
Variant::Float(v) => self.append_float(v),
386-
Variant::Double(v) => self.append_double(v),
387-
Variant::Binary(v) => self.append_binary(v),
388-
Variant::Uuid(v) => self.append_uuid(v),
389-
Variant::String(s) => self.append_string(s),
390-
Variant::ShortString(s) => self.append_short_string(s),
391-
Variant::Object(obj) => self.try_append_object(metadata_builder, obj)?,
392-
Variant::List(list) => self.try_append_list(metadata_builder, list)?,
393-
Variant::Time(v) => self.append_time_micros(v),
346+
Variant::Null => builder.append_null(),
347+
Variant::BooleanTrue => builder.append_bool(true),
348+
Variant::BooleanFalse => builder.append_bool(false),
349+
Variant::Int8(v) => builder.append_int8(v),
350+
Variant::Int16(v) => builder.append_int16(v),
351+
Variant::Int32(v) => builder.append_int32(v),
352+
Variant::Int64(v) => builder.append_int64(v),
353+
Variant::Date(v) => builder.append_date(v),
354+
Variant::Time(v) => builder.append_time_micros(v),
355+
Variant::TimestampMicros(v) => builder.append_timestamp_micros(v),
356+
Variant::TimestampNtzMicros(v) => builder.append_timestamp_ntz_micros(v),
357+
Variant::TimestampNanos(v) => builder.append_timestamp_nanos(v),
358+
Variant::TimestampNtzNanos(v) => builder.append_timestamp_ntz_nanos(v),
359+
Variant::Decimal4(decimal4) => builder.append_decimal4(decimal4),
360+
Variant::Decimal8(decimal8) => builder.append_decimal8(decimal8),
361+
Variant::Decimal16(decimal16) => builder.append_decimal16(decimal16),
362+
Variant::Float(v) => builder.append_float(v),
363+
Variant::Double(v) => builder.append_double(v),
364+
Variant::Binary(v) => builder.append_binary(v),
365+
Variant::String(s) => builder.append_string(s),
366+
Variant::ShortString(s) => builder.append_short_string(s),
367+
Variant::Uuid(v) => builder.append_uuid(v),
368+
Variant::Object(obj) => return Self::try_append_object(state, obj),
369+
Variant::List(list) => return Self::try_append_list(state, list),
394370
}
395371

372+
state.finish();
396373
Ok(())
397374
}
398375

@@ -1224,21 +1201,17 @@ impl VariantBuilder {
12241201
/// builder.append_value(42i8);
12251202
/// ```
12261203
pub fn append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, value: T) {
1227-
let variant = value.into();
1228-
self.value_builder
1229-
.append_variant(variant, &mut self.metadata_builder);
1204+
let state = ParentState::variant(&mut self.value_builder, &mut self.metadata_builder);
1205+
ValueBuilder::append_variant(state, value.into())
12301206
}
12311207

12321208
/// Append a value to the builder.
12331209
pub fn try_append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(
12341210
&mut self,
12351211
value: T,
12361212
) -> Result<(), ArrowError> {
1237-
let variant = value.into();
1238-
self.value_builder
1239-
.try_append_variant(variant, &mut self.metadata_builder)?;
1240-
1241-
Ok(())
1213+
let state = ParentState::variant(&mut self.value_builder, &mut self.metadata_builder);
1214+
ValueBuilder::try_append_variant(state, value.into())
12421215
}
12431216

12441217
/// Finish the builder and return the metadata and value buffers.
@@ -1326,19 +1299,17 @@ impl<'a> ListBuilder<'a> {
13261299
/// This method will panic if the variant contains duplicate field names in objects
13271300
/// when validation is enabled. For a fallible version, use [`ListBuilder::try_append_value`].
13281301
pub fn append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, value: T) {
1329-
self.try_append_value(value).unwrap();
1302+
let (state, _) = self.parent_state();
1303+
ValueBuilder::append_variant(state, value.into())
13301304
}
13311305

13321306
/// Appends a new primitive value to this list
13331307
pub fn try_append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(
13341308
&mut self,
13351309
value: T,
13361310
) -> Result<(), ArrowError> {
1337-
let (mut state, _) = self.parent_state();
1338-
let (value_builder, metadata_builder) = state.value_and_metadata_builders();
1339-
value_builder.try_append_variant(value.into(), metadata_builder)?;
1340-
state.finish();
1341-
Ok(())
1311+
let (state, _) = self.parent_state();
1312+
ValueBuilder::try_append_variant(state, value.into())
13421313
}
13431314

13441315
/// Builder-style API for appending a value to the list and returning self to enable method chaining.
@@ -1436,7 +1407,8 @@ impl<'a> ObjectBuilder<'a> {
14361407
/// This method will panic if the variant contains duplicate field names in objects
14371408
/// when validation is enabled. For a fallible version, use [`ObjectBuilder::try_insert`]
14381409
pub fn insert<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, key: &str, value: T) {
1439-
self.try_insert(key, value).unwrap();
1410+
let (state, _) = self.parent_state(key).unwrap();
1411+
ValueBuilder::append_variant(state, value.into())
14401412
}
14411413

14421414
/// Add a field with key and value to the object
@@ -1453,11 +1425,8 @@ impl<'a> ObjectBuilder<'a> {
14531425
key: &str,
14541426
value: T,
14551427
) -> Result<(), ArrowError> {
1456-
let (mut state, _) = self.parent_state(key)?;
1457-
let (value_builder, metadata_builder) = state.value_and_metadata_builders();
1458-
value_builder.try_append_variant(value.into(), metadata_builder)?;
1459-
state.finish();
1460-
Ok(())
1428+
let (state, _) = self.parent_state(key)?;
1429+
ValueBuilder::try_append_variant(state, value.into())
14611430
}
14621431

14631432
/// Builder style API for adding a field with key and value to the object

0 commit comments

Comments
 (0)