use crate::{
array::{Array, BinaryArray, DictionaryArray, DictionaryKey, PrimitiveArray, Utf8Array},
compute::sort::SortOptions,
datatypes::PhysicalType,
error::*,
with_match_primitive_without_interval_type,
};
use super::{
fixed::FixedLengthEncoding,
interner::{Interned, OrderPreservingInterner},
null_sentinel, Rows,
};
pub fn compute_dictionary_mapping(
interner: &mut OrderPreservingInterner,
values: &Box<dyn Array>,
) -> Result<Vec<Option<Interned>>> {
Ok(match values.data_type().to_physical_type() {
PhysicalType::Primitive(primitive) => {
with_match_primitive_without_interval_type!(primitive, |$T| {
let values = values
.as_any()
.downcast_ref::<PrimitiveArray<$T>>()
.unwrap();
interner.intern(values.iter().map(|x| x.map(|x| x.encode())))
})
}
PhysicalType::Binary => {
let iter = values
.as_any()
.downcast_ref::<BinaryArray<i32>>()
.unwrap()
.iter();
interner.intern(iter)
}
PhysicalType::LargeBinary => {
let iter = values
.as_any()
.downcast_ref::<BinaryArray<i64>>()
.unwrap()
.iter();
interner.intern(iter)
}
PhysicalType::Utf8 => {
let iter = values
.as_any()
.downcast_ref::<Utf8Array<i32>>()
.unwrap()
.iter()
.map(|x| x.map(|x| x.as_bytes()));
interner.intern(iter)
}
PhysicalType::LargeUtf8 => {
let iter = values
.as_any()
.downcast_ref::<Utf8Array<i64>>()
.unwrap()
.iter()
.map(|x| x.map(|x| x.as_bytes()));
interner.intern(iter)
}
t => {
return Err(Error::NotYetImplemented(format!(
"dictionary value {t:?} is not supported"
)))
}
})
}
pub fn encode_dictionary<K: DictionaryKey>(
out: &mut Rows,
column: &DictionaryArray<K>,
normalized_keys: &[Option<&[u8]>],
opts: SortOptions,
) {
for (offset, k) in out.offsets.iter_mut().skip(1).zip(column.keys()) {
match k.and_then(|k| normalized_keys[unsafe { k.as_usize() }]) {
Some(normalized_key) => {
let end_offset = *offset + 1 + normalized_key.len();
out.buffer[*offset] = 1;
out.buffer[*offset + 1..end_offset].copy_from_slice(normalized_key);
if opts.descending {
out.buffer[*offset..end_offset]
.iter_mut()
.for_each(|v| *v = !*v)
}
*offset = end_offset;
}
None => {
out.buffer[*offset] = null_sentinel(opts);
*offset += 1;
}
}
}
}