Struct datafusion::common::arrow::array::builder::StructBuilder

source ·
pub struct StructBuilder { /* private fields */ }
Expand description

Builder for StructArray

Note that callers should make sure that methods of all the child field builders are properly called to maintain the consistency of the data structure.

Handling arrays with complex layouts, such as List<Struct<List<Struct>>>, in Rust can be challenging due to its strong typing system. To construct a collection builder (ListBuilder, LargeListBuilder, or MapBuilder) using make_builder, multiple calls are required. This complexity arises from the recursive approach utilized by StructBuilder::from_fields.

Initially, StructBuilder::from_fields invokes make_builder, which returns a Box<dyn ArrayBuilder>. To obtain the specific collection builder, one must first use StructBuilder::field_builder to get a Collection<[Box<dyn ArrayBuilder>]>. Subsequently, the values() result from this operation can be downcast to the desired builder type.

For example, when working with ListBuilder, you would first call StructBuilder::field_builder::<ListBuilder<Box<dyn ArrayBuilder>>> and then downcast the Box<dyn ArrayBuilder> to the specific StructBuilder you need.

For a practical example see the code below:

   use arrow_array::builder::{ArrayBuilder, ListBuilder, StringBuilder, StructBuilder};
   use arrow_schema::{DataType, Field, Fields};
   use std::sync::Arc;

   // This is an example column that has a List<Struct<List<Struct>>> layout
   let mut example_col = ListBuilder::new(StructBuilder::from_fields(
       vec![Field::new(
           "value_list",
           DataType::List(Arc::new(Field::new(
               "item",
               DataType::Struct(Fields::from(vec![
                   Field::new("key", DataType::Utf8, true),
                   Field::new("value", DataType::Utf8, true),
               ])), //In this example we are trying to get to this builder and insert key/value pairs
               true,
           ))),
           true,
       )],
       0,
   ));

  // We can obtain the StructBuilder without issues, because example_col was created with StructBuilder
  let col_struct_builder: &mut StructBuilder = example_col.values();

  // We can't obtain the ListBuilder<StructBuilder> with the expected generic types, because under the hood
  // the StructBuilder was returned as a Box<dyn ArrayBuilder> and passed as such to the ListBuilder constructor
   
  // This panics in runtime, even though we know that the builder is a ListBuilder<StructBuilder>.
  // let sb = col_struct_builder
  //     .field_builder::<ListBuilder<StructBuilder>>(0)
  //     .as_mut()
  //     .unwrap();

  //To keep in line with Rust's strong typing, we fetch a ListBuilder<Box<dyn ArrayBuilder>> from the column StructBuilder first...
  let mut list_builder_option =
      col_struct_builder.field_builder::<ListBuilder<Box<dyn ArrayBuilder>>>(0);

  let list_builder = list_builder_option.as_mut().unwrap();

  // ... and then downcast the key/value pair values to a StructBuilder
  let struct_builder = list_builder
      .values()
      .as_any_mut()
      .downcast_mut::<StructBuilder>()
      .unwrap();

  // We can now append values to the StructBuilder
  let key_builder = struct_builder.field_builder::<StringBuilder>(0).unwrap();
  key_builder.append_value("my key");

  let value_builder = struct_builder.field_builder::<StringBuilder>(1).unwrap();
  value_builder.append_value("my value");

  struct_builder.append(true);
  list_builder.append(true);
  col_struct_builder.append(true);
  example_col.append(true);

  let array = example_col.finish();

  println!("My array: {:?}", array);

Implementations§

source§

impl StructBuilder

source

pub fn new( fields: impl Into<Fields>, field_builders: Vec<Box<dyn ArrayBuilder>>, ) -> StructBuilder

Creates a new StructBuilder

source

pub fn from_fields(fields: impl Into<Fields>, capacity: usize) -> StructBuilder

Creates a new StructBuilder from Fields and capacity

source

pub fn field_builder<T>(&mut self, i: usize) -> Option<&mut T>
where T: ArrayBuilder,

Returns a mutable reference to the child field builder at index i. Result will be None if the input type T provided doesn’t match the actual field builder’s type.

source

pub fn num_fields(&self) -> usize

Returns the number of fields for the struct this builder is building.

source

pub fn append(&mut self, is_valid: bool)

Appends an element (either null or non-null) to the struct. The actual elements should be appended for each child sub-array in a consistent way.

source

pub fn append_null(&mut self)

Appends a null element to the struct.

source

pub fn finish(&mut self) -> StructArray

Builds the StructArray and reset this builder.

source

pub fn finish_cloned(&self) -> StructArray

Builds the StructArray without resetting the builder.

source

pub fn validity_slice(&self) -> Option<&[u8]>

Returns the current null buffer as a slice

Trait Implementations§

source§

impl ArrayBuilder for StructBuilder

source§

fn len(&self) -> usize

Returns the number of array slots in the builder.

Note that this always return the first child field builder’s length, and it is the caller’s responsibility to maintain the consistency that all the child field builder should have the equal number of elements.

source§

fn finish(&mut self) -> Arc<dyn Array>

Builds the array.

source§

fn finish_cloned(&self) -> Arc<dyn Array>

Builds the array without resetting the builder.

source§

fn as_any(&self) -> &(dyn Any + 'static)

Returns the builder as a non-mutable Any reference.

This is most useful when one wants to call non-mutable APIs on a specific builder type. In this case, one can first cast this into a Any, and then use downcast_ref to get a reference on the specific builder.

source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Returns the builder as a mutable Any reference.

This is most useful when one wants to call mutable APIs on a specific builder type. In this case, one can first cast this into a Any, and then use downcast_mut to get a reference on the specific builder.

source§

fn into_box_any(self: Box<StructBuilder>) -> Box<dyn Any>

Returns the boxed builder as a box of Any.

source§

fn is_empty(&self) -> bool

Returns whether number of array slots is zero
source§

impl Debug for StructBuilder

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V