use crate::error::{SqlResult, SqlRuntimeError};
use crate::{ConcatSemigroup, Semigroup, Weight, some_function1, some_function2};
use dbsp::CmpFunc;
use itertools::Itertools;
use std::{collections::HashSet, fmt::Debug, hash::Hash, sync::Arc};
pub type Array<T> = Arc<Vec<T>>;
pub fn to_array<T>(data: Vec<T>) -> Array<T> {
Arc::new(data)
}
#[doc(hidden)]
pub fn to_arrayN<T>(data: Option<Vec<T>>) -> Option<Array<T>> {
data.map(|data| to_array(data))
}
#[doc(hidden)]
pub fn sort_to_array<F, G, T, D>(mut data: Vec<T>, _cmp: F, proj: G) -> Array<D>
where
F: CmpFunc<T>,
G: FnMut(T) -> D,
{
data.sort_unstable_by(|a, b| F::cmp(a, b));
Arc::new(data.into_iter().map(proj).collect::<Vec<D>>())
}
#[doc(hidden)]
pub fn sort_to_arrayN<F, G, T, D>(data: Option<Vec<T>>, cmp: F, proj: G) -> Option<Array<D>>
where
F: CmpFunc<T>,
G: FnMut(T) -> D,
{
data.map(|data| sort_to_array(data, cmp, proj))
}
pub fn to_vec<T>(data: Array<T>) -> Vec<T>
where
T: Clone,
{
Arc::unwrap_or_clone(data)
}
#[doc(hidden)]
impl<V> Semigroup<Vec<V>> for ConcatSemigroup<Vec<V>>
where
V: Clone + Ord,
{
#[doc(hidden)]
fn combine(left: &Vec<V>, right: &Vec<V>) -> Vec<V> {
left.iter().merge(right).cloned().collect()
}
}
#[doc(hidden)]
impl<V> Semigroup<Option<Vec<V>>> for ConcatSemigroup<Option<Vec<V>>>
where
V: Clone + Ord,
{
#[doc(hidden)]
fn combine(left: &Option<Vec<V>>, right: &Option<Vec<V>>) -> Option<Vec<V>> {
match (left, right) {
(None, _) => right.clone(),
(_, None) => left.clone(),
(Some(left), Some(right)) => Some(left.iter().merge(right).cloned().collect()),
}
}
}
#[doc(hidden)]
pub fn array_map__<T, S, F>(vec: Array<T>, f: F) -> Array<S>
where
F: Fn(&T) -> S,
{
(*vec).iter().map(f).collect::<Vec<S>>().into()
}
#[doc(hidden)]
pub fn array_mapN_<T, S, F>(vec: Option<Array<T>>, f: F) -> Option<Array<S>>
where
F: Fn(&T) -> S,
{
vec.as_ref().map(|vec| array_map__(vec.clone(), f))
}
#[doc(hidden)]
pub fn array_map_safe__<T, S, F>(vec: Array<T>, f: F) -> SqlResult<Option<Array<S>>>
where
F: Fn(&T) -> SqlResult<S>,
{
(*vec)
.iter()
.map(f)
.collect::<SqlResult<Vec<S>>>()
.map(|x| Some(x.into()))
}
#[doc(hidden)]
pub fn array_map_safeN_<T, S, F>(vec: Option<Array<T>>, f: F) -> SqlResult<Option<Array<S>>>
where
F: Fn(&T) -> SqlResult<S>,
{
match vec {
None => Err(SqlRuntimeError::from_strng("")),
Some(vec) => array_map_safe__(vec.clone(), f),
}
}
#[doc(hidden)]
pub fn element__<T>(array: Array<T>) -> Option<T>
where
T: Clone,
{
if array.len() <= 1 {
Arc::unwrap_or_clone(array).into_iter().next()
} else {
panic!("'ELEMENT()' called on array that does not have exactly 1 element");
}
}
#[doc(hidden)]
pub fn elementN_<T>(array: Option<Array<T>>) -> Option<T>
where
T: Clone,
{
let array = array?;
element__(array)
}
#[doc(hidden)]
pub fn element_N<T>(array: Array<Option<T>>) -> Option<T>
where
T: Clone,
{
if array.len() <= 1 {
Arc::unwrap_or_clone(array).into_iter().next().flatten()
} else {
panic!("'ELEMENT()' called on array that does not have exactly 1 element");
}
}
#[doc(hidden)]
pub fn elementNN<T>(array: Option<Array<Option<T>>>) -> Option<T>
where
T: Clone,
{
let array = array?;
element_N(array)
}
#[doc(hidden)]
pub fn cardinalityVec<T>(value: Array<T>) -> i32 {
value.len() as i32
}
#[doc(hidden)]
pub fn cardinalityVecN<T>(value: Option<Array<T>>) -> Option<i32> {
value.as_ref().map(|value| value.len() as i32)
}
#[doc(hidden)]
pub fn index___<T>(value: &Array<T>, index: isize) -> Option<T>
where
T: Clone,
{
let index: usize = index.try_into().ok()?;
value.get(index).cloned()
}
#[doc(hidden)]
pub fn index__N<T>(value: &Array<T>, index: Option<isize>) -> Option<T>
where
T: Clone,
{
let index = index?;
index___(value, index)
}
#[doc(hidden)]
pub fn index_N_<T>(value: &Array<Option<T>>, index: isize) -> Option<T>
where
T: Clone,
{
let index: usize = index.try_into().ok()?;
value.get(index)?.clone()
}
#[doc(hidden)]
pub fn index_NN<T>(value: &Array<Option<T>>, index: Option<isize>) -> Option<T>
where
T: Clone,
{
let index: usize = index?.try_into().ok()?;
value.get(index)?.clone()
}
#[doc(hidden)]
pub fn indexN__<T>(value: &Option<Array<T>>, index: isize) -> Option<T>
where
T: Clone,
{
index___(value.as_ref()?, index)
}
#[doc(hidden)]
pub fn indexN_N<T>(value: &Option<Array<T>>, index: Option<isize>) -> Option<T>
where
T: Clone,
{
index___(value.as_ref()?, index?)
}
#[doc(hidden)]
pub fn indexNN_<T>(value: &Option<Array<Option<T>>>, index: isize) -> Option<T>
where
T: Clone,
{
index_N_(value.as_ref()?, index)
}
#[doc(hidden)]
pub fn indexNNN<T>(value: &Option<Array<Option<T>>>, index: Option<isize>) -> Option<T>
where
T: Clone,
{
index_N_(value.as_ref()?, index?)
}
#[doc(hidden)]
pub fn array<T>() -> Array<T> {
vec![].into()
}
#[doc(hidden)]
pub fn limit<T>(vector: Array<T>, limit: usize) -> Array<T>
where
T: Clone,
{
let limit = std::cmp::min(limit, (*vector).len());
(**vector)[0..limit].to_vec().into()
}
#[doc(hidden)]
pub fn map<T, S, F>(vector: Array<T>, func: F) -> Array<S>
where
F: FnMut(&T) -> S,
{
(*vector).iter().map(func).collect::<Vec<S>>().into()
}
#[doc(hidden)]
pub fn array_append<T>(vector: Array<T>, value: T) -> Array<T>
where
T: Clone,
{
let mut result = Arc::unwrap_or_clone(vector);
result.push(value);
result.into()
}
#[doc(hidden)]
pub fn array_appendN<T>(vector: Option<Array<T>>, value: T) -> Option<Array<T>>
where
T: Clone,
{
Some(array_append(vector?, value))
}
#[doc(hidden)]
pub fn array_repeat__<T>(element: T, count: i32) -> Array<T>
where
T: Clone,
{
std::iter::repeat_n(element, usize::try_from(count).unwrap_or(0))
.collect::<Vec<T>>()
.into()
}
#[doc(hidden)]
pub fn array_repeatN_<T>(element: Option<T>, count: i32) -> Option<Array<Option<T>>>
where
T: Clone,
{
Some(array_repeat__(element, count))
}
#[doc(hidden)]
pub fn array_repeat_N<T>(element: T, count: Option<i32>) -> Option<Array<T>>
where
T: Clone,
{
Some(array_repeat__(element, count?))
}
#[doc(hidden)]
pub fn array_repeatNN<T>(element: Option<T>, count: Option<i32>) -> Option<Array<Option<T>>>
where
T: Clone,
{
Some(array_repeat__(element, count?))
}
#[doc(hidden)]
pub fn array_remove___<T>(vector: Array<T>, element: T) -> Array<T>
where
T: Eq + Clone,
{
let mut vec = Arc::unwrap_or_clone(vector);
vec.retain(|v| v != &element);
vec.into()
}
#[doc(hidden)]
pub fn array_removeN__<T>(vector: Option<Array<T>>, element: T) -> Option<Array<T>>
where
T: Eq + Clone,
{
let vector = vector?;
Some(array_remove___(vector, element))
}
#[doc(hidden)]
pub fn array_remove_N_<T>(vector: Array<Option<T>>, element: T) -> Array<Option<T>>
where
T: Eq + Clone,
{
array_remove___(vector, Some(element))
}
#[doc(hidden)]
pub fn array_removeNN_<T>(vector: Option<Array<Option<T>>>, element: T) -> Option<Array<Option<T>>>
where
T: Eq + Clone,
{
let vector = vector?;
Some(array_remove_N_(vector, element))
}
#[doc(hidden)]
pub fn array_remove_NN<T>(vector: Array<Option<T>>, element: Option<T>) -> Array<Option<T>>
where
T: Eq + Clone,
{
array_remove___(vector, element)
}
#[doc(hidden)]
pub fn array_removeNNN<T>(
vector: Option<Array<Option<T>>>,
element: Option<T>,
) -> Option<Array<Option<T>>>
where
T: Eq + Clone,
{
let vector = vector?;
Some(array_remove___(vector, element))
}
#[doc(hidden)]
pub fn array_remove__N<T>(vector: Array<T>, element: Option<T>) -> Array<T>
where
T: Eq + Clone,
{
match element {
None => vector,
Some(value) => array_remove___(vector, value),
}
}
#[doc(hidden)]
pub fn array_removeN_N<T>(vector: Option<Array<T>>, element: Option<T>) -> Option<Array<T>>
where
T: Eq + Clone,
{
let vector = vector?;
Some(array_remove__N(vector, element))
}
#[doc(hidden)]
pub fn array_position_<T>(vector: Array<T>, element: T) -> i64
where
T: Eq,
{
(*vector)
.iter()
.position(|x| *x == element)
.map(|v| v + 1)
.unwrap_or(0) as i64
}
pub fn array_positionN<T>(vector: Option<Array<T>>, element: T) -> Option<i64>
where
T: Eq,
{
let vector = vector?;
Some(array_position_(vector, element))
}
#[doc(hidden)]
pub fn array_reverse_<T>(vector: Array<T>) -> Array<T>
where
T: Clone,
{
let mut vector = Arc::unwrap_or_clone(vector);
vector.reverse();
Arc::new(vector)
}
some_function1!(array_reverse [T: Clone], Array<T>, Array<T>);
#[doc(hidden)]
pub fn sort_array<T>(vector: Array<T>, ascending: bool) -> Array<T>
where
T: Ord + Clone,
{
let mut data = Arc::unwrap_or_clone(vector);
if ascending {
data.sort()
} else {
data.sort_by(|a, b| b.cmp(a))
};
data.into()
}
#[doc(hidden)]
pub fn sort_arrayN<T>(vector: Option<Array<T>>, ascending: bool) -> Option<Array<T>>
where
T: Ord + Clone,
{
Some(sort_array(vector?, ascending))
}
#[doc(hidden)]
pub fn array_max__<T>(vector: Array<T>) -> Option<T>
where
T: Ord + Clone,
{
vector.iter().max().cloned()
}
#[doc(hidden)]
pub fn array_maxN_<T>(vector: Option<Array<T>>) -> Option<T>
where
T: Ord + Clone,
{
array_max__(vector?)
}
#[doc(hidden)]
pub fn array_max_N<T>(vector: Array<Option<T>>) -> Option<T>
where
T: Ord + Clone,
{
vector.iter().flatten().max().cloned()
}
#[doc(hidden)]
pub fn array_maxNN<T>(vector: Option<Array<Option<T>>>) -> Option<T>
where
T: Ord + Clone,
{
array_max_N(vector?)
}
#[doc(hidden)]
pub fn array_min__<T>(vector: Array<T>) -> Option<T>
where
T: Ord + Clone,
{
vector.iter().min().cloned()
}
#[doc(hidden)]
pub fn array_minN_<T>(vector: Option<Array<T>>) -> Option<T>
where
T: Ord + Clone,
{
array_min__(vector?)
}
#[doc(hidden)]
pub fn array_min_N<T>(vector: Array<Option<T>>) -> Option<T>
where
T: Ord + Clone,
{
vector.iter().flatten().min().cloned()
}
#[doc(hidden)]
pub fn array_minNN<T>(vector: Option<Array<Option<T>>>) -> Option<T>
where
T: Ord + Clone,
{
array_min_N(vector?)
}
#[doc(hidden)]
pub fn array_compact_<T>(vector: Array<Option<T>>) -> Array<T>
where
T: Clone,
{
(*vector)
.iter()
.flatten()
.cloned()
.collect::<Vec<T>>()
.into()
}
some_function1!(array_compact [T: Clone], Array<Option<T>>, Array<T>);
fn array_insert<T>(vector: Array<T>, value: T, index: usize) -> Array<T>
where
T: Clone,
{
match Arc::try_unwrap(vector) {
Ok(mut data) => {
data.insert(index, value);
data.into()
}
Err(vector) => {
let mut copy = Vec::with_capacity(vector.capacity().max(vector.len() + 1));
copy.extend_from_slice(&vector[..index]);
copy.push(value);
copy.extend_from_slice(&vector[index..]);
copy.into()
}
}
}
#[doc(hidden)]
pub fn array_prepend<T>(vector: Array<T>, value: T) -> Array<T>
where
T: Clone,
{
array_insert(vector, value, 0)
}
#[doc(hidden)]
pub fn array_prependN<T>(vector: Option<Array<T>>, value: T) -> Option<Array<T>>
where
T: Clone,
{
Some(array_prepend(vector?, value))
}
#[doc(hidden)]
pub fn array_contains_<T>(vector: Array<T>, element: T) -> bool
where
T: Eq,
{
vector.contains(&element)
}
#[doc(hidden)]
pub fn array_containsN<T>(vector: Option<Array<T>>, element: T) -> Option<bool>
where
T: Eq,
{
let vector = vector?;
Some(array_contains_(vector, element))
}
#[doc(hidden)]
pub fn array_distinct<T>(vector: Array<T>) -> Array<T>
where
T: Eq + Hash + Clone,
{
let mut hset: HashSet<&T> = HashSet::new();
let data = (*vector)
.iter()
.filter(|v| hset.insert(*v))
.cloned()
.collect::<Vec<T>>();
data.into()
}
#[doc(hidden)]
pub fn array_distinctN<T>(vector: Option<Array<T>>) -> Option<Array<T>>
where
T: Eq + Hash + Clone,
{
Some(array_distinct(vector?))
}
#[doc(hidden)]
pub fn sequence__(start: i32, end: i32) -> Array<i32> {
(start..=end).collect::<Vec<i32>>().into()
}
some_function2!(sequence, i32, i32, Array<i32>);
#[doc(hidden)]
pub fn arrays_overlap__<T>(first: Array<T>, second: Array<T>) -> bool
where
T: Eq + Hash,
{
if first.len() > second.len() {
return arrays_overlap__(second, first);
}
let (smaller, bigger) = (first, second);
if !smaller.is_empty() && !bigger.is_empty() {
let shset: HashSet<&T> = HashSet::from_iter((*smaller).iter());
for element in (*bigger).iter() {
if shset.contains(&element) {
return true;
}
}
}
false
}
some_function2!(arrays_overlap [T: Eq + Hash], Array<T>, Array<T>, bool);
#[doc(hidden)]
pub fn array_agg<T>(accumulator: &mut Vec<T>, value: T, weight: Weight, distinct: bool, keep: bool)
where
T: Clone,
{
if weight < 0 {
panic!("Negative weight {:?}", weight);
} else if weight > 0 && keep {
if !distinct {
for _ in 1..weight {
accumulator.push(value.clone())
}
}
accumulator.push(value)
}
}
#[doc(hidden)]
pub fn array_aggN<T>(
accumulator: &mut Option<Vec<T>>,
value: T,
weight: Weight,
distinct: bool,
keep: bool,
) where
T: Clone,
{
if let Some(accumulator) = accumulator.as_mut() {
array_agg(accumulator, value, weight, distinct, keep)
}
}
#[doc(hidden)]
pub fn array_agg_opt<T>(
accumulator: &mut Vec<Option<T>>,
value: Option<T>,
weight: Weight,
distinct: bool,
keep: bool,
ignore_nulls: bool,
) where
T: Clone,
{
if !ignore_nulls || value.is_some() {
array_agg(accumulator, value, weight, distinct, keep);
}
}
#[doc(hidden)]
pub fn array_agg_optN<T>(
accumulator: &mut Option<Vec<Option<T>>>,
value: Option<T>,
weight: Weight,
distinct: bool,
keep: bool,
ignore_nulls: bool,
) where
T: Clone,
{
if let Some(accumulator) = accumulator.as_mut() {
array_agg_opt(accumulator, value, weight, distinct, keep, ignore_nulls);
}
}
#[doc(hidden)]
pub fn array_concat__<T>(left: Array<T>, right: Array<T>) -> Array<T>
where
T: Clone,
{
match Arc::try_unwrap(left) {
Ok(mut left) => {
match Arc::try_unwrap(right) {
Ok(ref mut right) => left.append(right),
Err(right) => left.extend(right.iter().cloned()),
};
left.into()
}
Err(left) => {
let mut result = Vec::with_capacity(left.len() + right.len());
result.extend(left.iter().cloned());
result.extend(right.iter().cloned());
result.into()
}
}
}
some_function2!(array_concat [T: Clone], Array<T>, Array<T>, Array<T>);
fn to_set<T>(v: &[T]) -> HashSet<&T>
where
T: Eq + Clone + Hash + Ord,
{
v.iter().collect()
}
#[doc(hidden)]
pub fn array_except__<T>(left: Array<T>, right: Array<T>) -> Array<T>
where
T: Eq + Clone + Hash + Ord + Debug,
{
let left = to_set(&left);
let right = to_set(&right);
let result = left.difference(&right);
let mut result = result.copied().cloned().collect::<Vec<T>>();
result.sort();
result.into()
}
some_function2!(array_except [T: Eq + Clone + Hash + Ord + Debug], Array<T>, Array<T>, Array<T>);
#[doc(hidden)]
pub fn array_union__<T>(left: Array<T>, right: Array<T>) -> Array<T>
where
T: Eq + Clone + Hash + Ord,
{
let left = to_set(&left);
let right = to_set(&right);
let result = left.union(&right);
let mut result = result.copied().cloned().collect::<Vec<T>>();
result.sort();
result.into()
}
some_function2!(array_union [T: Eq + Clone + Hash + Ord], Array<T>, Array<T>, Array<T>);
#[doc(hidden)]
pub fn array_intersect__<T>(left: Array<T>, right: Array<T>) -> Array<T>
where
T: Eq + Clone + Hash + Ord,
{
let left = to_set(&left);
let right = to_set(&right);
let result = left.intersection(&right);
let mut result = result.copied().cloned().collect::<Vec<T>>();
result.sort();
result.into()
}
some_function2!(array_intersect [T: Eq + Clone + Hash + Ord], Array<T>, Array<T>, Array<T>);
#[doc(hidden)]
pub fn array_insert__N_<T>(array: Array<T>, pos: i32, value: Option<T>) -> Array<Option<T>>
where
T: Clone + Debug,
{
let array: Array<Option<T>> = array
.iter()
.map(|x| Some(x.clone()))
.collect::<Vec<Option<T>>>()
.into();
array_insert__NN(array, pos, value)
}
#[doc(hidden)]
pub fn array_insert_NN_<T>(
array: Array<T>,
pos: Option<i32>,
value: Option<T>,
) -> Option<Array<Option<T>>>
where
T: Clone + Debug,
{
let pos = pos?;
Some(array_insert__N_(array, pos, value))
}
#[doc(hidden)]
#[allow(clippy::needless_range_loop)]
pub fn array_insert__NN<T>(array: Array<Option<T>>, pos: i32, value: Option<T>) -> Array<Option<T>>
where
T: Clone + Debug,
{
const MAX_ARRAY_LENGTH: usize = (i32::MAX) as usize - 15;
let mut abs = num::abs(pos) as usize;
if pos == 0 {
panic!("Index of 0 for 'array_insert");
}
if abs > MAX_ARRAY_LENGTH {
panic!("Index {} too large for 'array_index'", pos);
}
let len = array.len();
if pos <= 0 {
if abs <= len {
abs = len - abs + 2;
} else {
let mut result: Vec<Option<T>> = Vec::with_capacity(abs + 1);
result.push(value);
for _index in 0..(abs - len - 1) {
result.push(None);
}
result.extend_from_slice(array.as_slice());
return result.into();
}
} else if abs > len {
let mut result = match Arc::try_unwrap(array) {
Ok(mut vec) => {
vec.reserve(abs - len);
vec
}
Err(array) => {
let mut result = Vec::<Option<T>>::with_capacity(abs + 1);
result.extend_from_slice(array.as_slice());
result
}
};
for _index in len..(abs - 1) {
result.push(None);
}
result.push(value);
return result.into();
}
array_insert(array, value, abs - 1)
}
#[doc(hidden)]
pub fn array_insert_NNN<T>(
array: Array<Option<T>>,
pos: Option<i32>,
value: Option<T>,
) -> Option<Array<Option<T>>>
where
T: Clone + Debug,
{
let pos = pos?;
Some(array_insert__NN(array, pos, value))
}
#[doc(hidden)]
pub fn array_insertN_N_<T>(
array: Option<Array<T>>,
pos: i32,
value: Option<T>,
) -> Option<Array<Option<T>>>
where
T: Clone + Debug,
{
let array = array?;
Some(array_insert__N_(array, pos, value))
}
#[doc(hidden)]
pub fn array_insertNNN_<T>(
array: Option<Array<T>>,
pos: Option<i32>,
value: Option<T>,
) -> Option<Array<Option<T>>>
where
T: Clone + Debug,
{
let array = array?;
let pos = pos?;
Some(array_insert__N_(array, pos, value))
}
#[doc(hidden)]
pub fn array_insertN_NN<T>(
array: Option<Array<Option<T>>>,
pos: i32,
value: Option<T>,
) -> Option<Array<Option<T>>>
where
T: Clone + Debug,
{
let array = array?;
Some(array_insert__NN(array, pos, value))
}
#[doc(hidden)]
pub fn array_insertNNNN<T>(
array: Option<Array<Option<T>>>,
pos: Option<i32>,
value: Option<T>,
) -> Option<Array<Option<T>>>
where
T: Clone + Debug,
{
let array = array?;
let pos = pos?;
Some(array_insert__NN(array, pos, value))
}
#[doc(hidden)]
pub fn array_exists__<T, F>(array: Array<T>, f: F) -> bool
where
F: Fn(&T) -> bool,
{
array.iter().any(f)
}
#[doc(hidden)]
pub fn array_existsN_<T, F>(array: Option<Array<T>>, f: F) -> Option<bool>
where
F: Fn(&T) -> bool,
{
let array = array?;
Some(array_exists__(array, f))
}
#[doc(hidden)]
pub fn array_exists_N<T, F>(array: Array<T>, f: F) -> Option<bool>
where
F: Fn(&T) -> Option<bool>,
{
let mut found_null = false;
for item in array.iter() {
match f(item) {
None => {
found_null = true;
continue;
}
Some(false) => continue,
Some(true) => return Some(true),
}
}
if found_null { None } else { Some(false) }
}
#[doc(hidden)]
pub fn array_existsNN<T, F>(array: Option<Array<T>>, f: F) -> Option<bool>
where
F: Fn(&T) -> Option<bool>,
{
let array = array?;
array_exists_N(array, f)
}
#[doc(hidden)]
pub fn transform_<T, S, F>(array: Array<T>, f: F) -> Array<S>
where
F: Fn(&T) -> S,
{
Arc::new(array.iter().map(f).collect())
}
#[doc(hidden)]
pub fn transformN<T, S, F>(array: Option<Array<T>>, f: F) -> Option<Array<S>>
where
F: Fn(&T) -> S,
{
let array = array?;
Some(transform_(array, f))
}