Skip to main content

ArrowColumnWriter

Struct ArrowColumnWriter 

Source
pub struct ArrowColumnWriter {
    writer: ArrowColumnWriterImpl,
    chunk: Arc<Mutex<ArrowColumnChunkData>>,
    distinct_values_seen: Option<HashSet<u64>>,
}
Expand description

Encodes ArrowLeafColumn to ArrowColumnChunk

ArrowColumnWriter instances can be created using an ArrowRowGroupWriterFactory;

Note: This is a low-level interface for applications that require fine-grained control of encoding (e.g. encoding using multiple threads), see ArrowWriter for a higher-level interface

§Example: Encoding two Arrow Array’s in Parallel

// The arrow schema
let schema = Arc::new(Schema::new(vec![
    Field::new("i32", DataType::Int32, false),
    Field::new("f32", DataType::Float32, false),
]));

// Compute the parquet schema
let props = Arc::new(WriterProperties::default());
let parquet_schema = ArrowSchemaConverter::new()
  .with_coerce_types(props.coerce_types())
  .convert(&schema)
  .unwrap();

// Create parquet writer
let root_schema = parquet_schema.root_schema_ptr();
// write to memory in the example, but this could be a File
let mut out = Vec::with_capacity(1024);
let mut writer = SerializedFileWriter::new(&mut out, root_schema, props.clone())
  .unwrap();

// Create a factory for building Arrow column writers
let row_group_factory = ArrowRowGroupWriterFactory::new(&writer, Arc::clone(&schema));
// Create column writers for the 0th row group
let col_writers = row_group_factory.create_column_writers(0).unwrap();

// Spawn a worker thread for each column
//
// Note: This is for demonstration purposes, a thread-pool e.g. rayon or tokio, would be better.
// The `map` produces an iterator of type `tuple of (thread handle, send channel)`.
let mut workers: Vec<_> = col_writers
    .into_iter()
    .map(|mut col_writer| {
        let (send, recv) = std::sync::mpsc::channel::<ArrowLeafColumn>();
        let handle = std::thread::spawn(move || {
            // receive Arrays to encode via the channel
            for col in recv {
                col_writer.write(&col)?;
            }
            // once the input is complete, close the writer
            // to return the newly created ArrowColumnChunk
            col_writer.close()
        });
        (handle, send)
    })
    .collect();

// Start row group
let mut row_group_writer: SerializedRowGroupWriter<'_, _> = writer
  .next_row_group()
  .unwrap();

// Create some example input columns to encode
let to_write = vec![
    Arc::new(Int32Array::from_iter_values([1, 2, 3])) as _,
    Arc::new(Float32Array::from_iter_values([1., 45., -1.])) as _,
];

// Send the input columns to the workers
let mut worker_iter = workers.iter_mut();
for (arr, field) in to_write.iter().zip(&schema.fields) {
    for leaves in compute_leaves(field, arr).unwrap() {
        worker_iter.next().unwrap().1.send(leaves).unwrap();
    }
}

// Wait for the workers to complete encoding, and append
// the resulting column chunks to the row group (and the file)
for (handle, send) in workers {
    drop(send); // Drop send side to signal termination
    // wait for the worker to send the completed chunk
    let chunk: ArrowColumnChunk = handle.join().unwrap().unwrap();
    chunk.append_to_row_group(&mut row_group_writer).unwrap();
}
// Close the row group which writes to the underlying file
row_group_writer.close().unwrap();

let metadata = writer.close().unwrap();
assert_eq!(metadata.file_metadata().num_rows(), 3);

Fields§

§writer: ArrowColumnWriterImpl§chunk: Arc<Mutex<ArrowColumnChunkData>>§distinct_values_seen: Option<HashSet<u64>>

Non-null value hashes accumulated across all writes for this column’s row group. None when tracking is disabled via WriterProperties::write_row_group_number_distinct_values.

Implementations§

Source§

impl ArrowColumnWriter

Source

pub fn write(&mut self, col: &ArrowLeafColumn) -> Result<()>

Write an ArrowLeafColumn

Source

fn write_with_chunker( &mut self, col: &ArrowLeafColumn, chunker: &mut ContentDefinedChunker, ) -> Result<()>

Write with content-defined chunking, inserting page flushes at chunk boundaries.

Source

fn write_internal(&mut self, levels: &ArrayLevels) -> Result<()>

Source

pub fn close(self) -> Result<ArrowColumnChunk>

Close this column returning the written ArrowColumnChunk

§Errors

Returns an error if the column could not be finalised, or if another thread panicked while holding the column chunk. The caller cannot cause either.

Source

pub fn memory_size(&self) -> usize

Returns the estimated total memory usage by the writer.

This Self::get_estimated_total_bytes this is an estimate of the current memory usage and not it’s anticipated encoded size.

This includes:

  1. Data buffered in encoded form
  2. Data buffered in un-encoded form (e.g. usize dictionary keys)

This value should be greater than or equal to Self::get_estimated_total_bytes

Source

pub fn get_estimated_total_bytes(&self) -> usize

Returns the estimated total encoded bytes for this column writer.

This includes:

  1. Data buffered in encoded form
  2. An estimate of how large the data buffered in un-encoded form would be once encoded

This value should be less than or equal to Self::memory_size

Trait Implementations§

Source§

impl Debug for ArrowColumnWriter

Source§

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

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
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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.

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

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

Source§

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.
§

impl<T> Ungil for T
where T: Send,