MCPcopy Create free account
hub / github.com/apache/datafusion / build_map_array

Function build_map_array

datafusion/functions-nested/src/map.rs:567–670  ·  view source on GitHub ↗

Common logic to build a MapArray from decomposed list arrays

(
    keys: &[ArrayRef],
    values: &[ArrayRef],
    keys_data_type: &DataType,
    values_data_type: &DataType,
    original_len: usize,
    nulls_bitmap: Option<arrow::buffer::NullBuffer>,
)

Source from the content-addressed store, hash-verified

565
566/// Common logic to build a MapArray from decomposed list arrays
567fn build_map_array(
568 keys: &[ArrayRef],
569 values: &[ArrayRef],
570 keys_data_type: &DataType,
571 values_data_type: &DataType,
572 original_len: usize,
573 nulls_bitmap: Option<arrow::buffer::NullBuffer>,
574) -> Result<ColumnarValue> {
575 if keys.len() != values.len() {
576 return exec_err!("map requires key and value lists to have the same length");
577 }
578
579 let mut key_array_vec = vec![];
580 let mut value_array_vec = vec![];
581 for (k, v) in keys.iter().zip(values.iter()) {
582 key_array_vec.push(k.as_ref());
583 value_array_vec.push(v.as_ref());
584 }
585
586 // Build offset buffer that accounts for NULL maps
587 // For each row, if it's NULL, the offset stays the same (empty range)
588 // If it's not NULL, the offset advances by the number of entries in that map
589 // NOTE: MapArray always requires i32 offsets, regardless of input list type
590 let mut running_offset = 0i32;
591 let mut offset_buffer = vec![running_offset];
592 let mut non_null_idx = 0;
593 for i in 0..original_len {
594 let is_null = nulls_bitmap.as_ref().is_some_and(|nulls| nulls.is_null(i));
595 if !is_null {
596 let entry_count = keys[non_null_idx].len();
597 // Validate that we won't overflow i32 when converting from potentially i64 offsets
598 let entry_count_i32 = i32::try_from(entry_count).map_err(|_| {
599 datafusion_common::DataFusionError::Execution(format!(
600 "Map offset overflow: entry count {entry_count} at index {i} exceeds i32::MAX",
601 ))
602 })?;
603 running_offset =
604 running_offset.checked_add(entry_count_i32).ok_or_else(|| {
605 datafusion_common::DataFusionError::Execution(format!(
606 "Map offset overflow: cumulative offset exceeds i32::MAX at index {i}",
607 ))
608 })?;
609 non_null_idx += 1;
610 }
611 offset_buffer.push(running_offset);
612 }
613
614 // concatenate all the arrays
615 // If key_array_vec is empty, it means all maps were NULL (list elements were NULL).
616 // In this case, we need to create empty arrays with the correct data type.
617 let (flattened_keys, flattened_values) = if key_array_vec.is_empty() {
618 // All maps are NULL - create empty arrays
619 // We need to infer the data type from the original keys/values arrays
620 let key_type = get_element_type(keys_data_type)?;
621 let value_type = get_element_type(values_data_type)?;
622
623 (
624 arrow::array::new_empty_array(key_type),

Callers 2

make_map_array_internalFunction · 0.85

Calls 15

newFunction · 0.85
null_countMethod · 0.80
get_element_typeFunction · 0.70
concatFunction · 0.50
StructClass · 0.50
MapEnum · 0.50
lenMethod · 0.45
iterMethod · 0.45
pushMethod · 0.45
as_refMethod · 0.45
is_nullMethod · 0.45
is_emptyMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…