Skip to content

Commit 88ff2ba

Browse files
committed
Optimize exporting chuncked<dict> to Arrow Dict
Signed-off-by: Adam Gutglick <adam@spiraldb.com>
1 parent 2a54a2c commit 88ff2ba

1 file changed

Lines changed: 42 additions & 1 deletion

File tree

vortex-arrow/src/executor/dictionary.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@ use arrow_array::ArrayRef as ArrowArrayRef;
77
use arrow_array::DictionaryArray;
88
use arrow_array::PrimitiveArray;
99
use arrow_array::cast::AsArray;
10+
use arrow_array::new_empty_array;
1011
use arrow_array::new_null_array;
1112
use arrow_array::types::*;
1213
use arrow_schema::DataType;
1314
use vortex_array::ArrayRef;
1415
use vortex_array::ExecutionCtx;
1516
use vortex_array::IntoArray;
17+
use vortex_array::arrays::Chunked;
1618
use vortex_array::arrays::Constant;
1719
use vortex_array::arrays::ConstantArray;
1820
use vortex_array::arrays::Dict;
1921
use vortex_array::arrays::DictArray;
22+
use vortex_array::arrays::chunked::ChunkedArrayExt;
2023
use vortex_array::arrays::dict::DictArraySlotsExt;
2124
use vortex_array::matcher::Matcher;
2225
use vortex_error::VortexError;
@@ -32,7 +35,7 @@ impl Matcher for ArrowDictExportable {
3235
type Match<'a> = &'a ArrayRef;
3336

3437
fn try_match(array: &ArrayRef) -> Option<Self::Match<'_>> {
35-
(array.is::<Dict>() || array.is::<Constant>()).then_some(array)
38+
(array.is::<Dict>() || array.is::<Chunked>() || array.is::<Constant>()).then_some(array)
3639
}
3740
}
3841

@@ -52,6 +55,10 @@ pub(super) fn to_arrow_dictionary(
5255
Ok(constant) => return constant_to_dict(constant, codes_type, values_type, ctx),
5356
Err(array) => array,
5457
};
58+
let array = match array.try_downcast::<Chunked>() {
59+
Ok(chunked) => return chunked_to_dict(chunked, codes_type, values_type, ctx),
60+
Err(array) => array,
61+
};
5562

5663
// Otherwise, we should try and build a dictionary.
5764
// Arrow hides this functionality inside the cast module!
@@ -85,6 +92,40 @@ fn constant_to_dict(
8592
make_dict_array(codes_type, codes, values)
8693
}
8794

95+
/// Convert a chunked array to an Arrow dictionary array by exporting each chunk separately.
96+
fn chunked_to_dict(
97+
array: vortex_array::arrays::ChunkedArray,
98+
codes_type: &DataType,
99+
values_type: &DataType,
100+
ctx: &mut ExecutionCtx,
101+
) -> VortexResult<ArrowArrayRef> {
102+
let mut arrow_chunks = Vec::with_capacity(array.nchunks());
103+
for chunk in array.non_empty_chunks() {
104+
arrow_chunks.push(to_arrow_dictionary(
105+
chunk.clone(),
106+
codes_type,
107+
values_type,
108+
ctx,
109+
)?);
110+
}
111+
112+
if arrow_chunks.is_empty() {
113+
return Ok(new_empty_array(&DataType::Dictionary(
114+
Box::new(codes_type.clone()),
115+
Box::new(values_type.clone()),
116+
)));
117+
}
118+
if let [arrow_chunk] = arrow_chunks.as_slice() {
119+
return Ok(Arc::clone(arrow_chunk));
120+
}
121+
122+
let refs = arrow_chunks
123+
.iter()
124+
.map(|array| array.as_ref())
125+
.collect::<Vec<_>>();
126+
Ok(arrow_select::concat::concat(&refs)?)
127+
}
128+
88129
/// Convert a Vortex dictionary array to an Arrow dictionary array.
89130
fn dict_to_dict(
90131
array: DictArray,

0 commit comments

Comments
 (0)