MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / array_array_concat

Function array_array_concat

src/expr/src/scalar/func.rs:2846–2947  ·  view source on GitHub ↗
(
    a: Option<Array<'a>>,
    b: Option<Array<'a>>,
    temp_storage: &'a RowArena,
)

Source from the content-addressed store, hash-verified

2844 introduces_nulls = false
2845)]
2846fn array_array_concat<'a>(
2847 a: Option<Array<'a>>,
2848 b: Option<Array<'a>>,
2849 temp_storage: &'a RowArena,
2850) -> Result<Option<Array<'a>>, EvalError> {
2851 let Some(a_array) = a else {
2852 return Ok(b);
2853 };
2854 let Some(b_array) = b else {
2855 return Ok(a);
2856 };
2857
2858 let a_dims: Vec<ArrayDimension> = a_array.dims().into_iter().collect();
2859 let b_dims: Vec<ArrayDimension> = b_array.dims().into_iter().collect();
2860
2861 let a_ndims = a_dims.len();
2862 let b_ndims = b_dims.len();
2863
2864 // Per PostgreSQL, if either of the input arrays is zero dimensional,
2865 // the output is the other array, no matter their dimensions.
2866 if a_ndims == 0 {
2867 return Ok(b);
2868 } else if b_ndims == 0 {
2869 return Ok(a);
2870 }
2871
2872 // Postgres supports concatenating arrays of different dimensions,
2873 // as long as one of the arrays has the same type as an element of
2874 // the other array, i.e. `int[2][4] || int[4]` (or `int[4] || int[2][4]`)
2875 // works, because each element of `int[2][4]` is an `int[4]`.
2876 // This check is separate from the one below because Postgres gives a
2877 // specific error message if the number of dimensions differs by more
2878 // than one.
2879 // This cast is safe since MAX_ARRAY_DIMENSIONS is 6
2880 // Can be replaced by .abs_diff once it is stabilized
2881 // TODO(benesch): remove potentially dangerous usage of `as`.
2882 #[allow(clippy::as_conversions)]
2883 if (a_ndims as isize - b_ndims as isize).abs() > 1 {
2884 return Err(EvalError::IncompatibleArrayDimensions {
2885 dims: Some((a_ndims, b_ndims)),
2886 });
2887 }
2888
2889 let mut dims;
2890
2891 // After the checks above, we are certain that:
2892 // - neither array is zero dimensional nor empty
2893 // - both arrays have the same number of dimensions, or differ
2894 // at most by one.
2895 match a_ndims.cmp(&b_ndims) {
2896 // If both arrays have the same number of dimensions, validate
2897 // that their inner dimensions are the same and concatenate the
2898 // arrays.
2899 Ordering::Equal => {
2900 if &a_dims[1..] != &b_dims[1..] {
2901 return Err(EvalError::IncompatibleArrayDimensions { dims: None });
2902 }
2903 dims = vec![ArrayDimension {

Callers

nothing calls this directly

Calls 11

dimsMethod · 0.80
elementsMethod · 0.80
try_make_datumMethod · 0.80
try_push_arrayMethod · 0.80
unwrap_arrayMethod · 0.80
collectMethod · 0.45
into_iterMethod · 0.45
lenMethod · 0.45
cmpMethod · 0.45
extendMethod · 0.45
iterMethod · 0.45

Tested by

no test coverage detected