This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new 49c91b563a Replace `array_contains` with SQL array functions: 
`array_has`, `array_has_any`, `array_has_all` (#6990)
49c91b563a is described below

commit 49c91b563ad894b2f368690d85402895bdeaa73a
Author: Jay Zhan <[email protected]>
AuthorDate: Sun Jul 23 00:17:17 2023 +0800

    Replace `array_contains` with SQL array functions: `array_has`, 
`array_has_any`, `array_has_all` (#6990)
    
    * rename array_contains to array_has_all
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * array_has_all with columns done
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * add more tests
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * prepare array has any and array has
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * clippy
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * add proto only
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * add generated files
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * basic array_has done
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * add more tests
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * basic array_has done
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * array_has_all done
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * any and all are done
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * remove proto files
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * remove test
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * address comment
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * run doc command
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    * rerun command
    
    Signed-off-by: jayzhan211 <[email protected]>
    
    ---------
    
    Signed-off-by: jayzhan211 <[email protected]>
---
 .../core/tests/sqllogictests/test_files/array.slt  | 208 ++++++++++--
 datafusion/expr/src/built_in_function.rs           |  26 +-
 datafusion/expr/src/expr_fn.rs                     |  18 +-
 datafusion/physical-expr/src/array_expressions.rs  | 361 +++++++++++++++------
 datafusion/physical-expr/src/functions.rs          |  10 +-
 datafusion/proto/proto/datafusion.proto            |   4 +-
 datafusion/proto/src/generated/pbjson.rs           |  12 +-
 datafusion/proto/src/generated/prost.rs            |  12 +-
 datafusion/proto/src/logical_plan/from_proto.rs    |  26 +-
 datafusion/proto/src/logical_plan/to_proto.rs      |   4 +-
 docs/source/user-guide/expressions.md              |  38 ++-
 docs/source/user-guide/sql/scalar_functions.md     |  40 ++-
 12 files changed, 578 insertions(+), 181 deletions(-)

diff --git a/datafusion/core/tests/sqllogictests/test_files/array.slt 
b/datafusion/core/tests/sqllogictests/test_files/array.slt
index 6069ee0e93..9e117b6d05 100644
--- a/datafusion/core/tests/sqllogictests/test_files/array.slt
+++ b/datafusion/core/tests/sqllogictests/test_files/array.slt
@@ -86,6 +86,60 @@ AS VALUES
   (NULL, NULL, NULL, NULL)
 ;
 
+statement ok
+CREATE TABLE array_has_table_1D
+AS VALUES
+  (make_array(1, 2), 1, make_array(1,2,3), make_array(1,3), make_array(1,3,5), 
make_array(2,4,6,8,1,3,5)),
+  (make_array(3, 4, 5), 2, make_array(1,2,3,4), make_array(2,5), 
make_array(2,4,6), make_array(1,3,5))
+;
+
+statement ok
+CREATE TABLE array_has_table_1D_Float
+AS VALUES
+  (make_array(1.0, 2.0), 1.0, make_array(1.0,2.0,3.0), make_array(1.0,3.0), 
make_array(1.11), make_array(2.22, 3.33)),
+  (make_array(3.0, 4.0, 5.0), 2.0, make_array(1.0,2.0,3.0,4.0), 
make_array(2.0,5.0), make_array(2.22, 1.11), make_array(1.11, 3.33))
+;
+
+statement ok
+CREATE TABLE array_has_table_1D_Boolean
+AS VALUES
+  (make_array(true, true, true), false, make_array(true, true, false, true, 
false), make_array(true, false, true), make_array(false), make_array(true, 
false)),
+  (make_array(false, false, false), false, make_array(true, false, true), 
make_array(true, true), make_array(true, true), make_array(false,false,true))
+;
+
+statement ok
+CREATE TABLE array_has_table_1D_UTF8
+AS VALUES
+  (make_array('a', 'bc', 'def'), 'bc', make_array('datafusion', 'rust', 
'arrow'), make_array('rust', 'arrow'), make_array('rust', 'arrow', 'python'), 
make_array('data')),
+  (make_array('a', 'bc', 'def'), 'defg', make_array('datafusion', 'rust', 
'arrow'), make_array('datafusion', 'rust', 'arrow', 'python'), 
make_array('rust', 'arrow'), make_array('datafusion', 'rust', 'arrow'))
+;
+
+statement ok
+CREATE TABLE array_has_table_2D
+AS VALUES
+  (make_array([1,2]), make_array(1,3), make_array([1,2,3], [4,5], [6,7]), 
make_array([4,5], [6,7])),
+  (make_array([3,4], [5]), make_array(5), make_array([1,2,3,4], [5,6,7], 
[8,9,10]), make_array([1,2,3], [5,6,7], [8,9,10]))
+;
+
+statement ok
+CREATE TABLE array_has_table_2D_float
+AS VALUES
+  (make_array([1.0, 2.0, 3.0], [1.1, 2.2], [3.3]), make_array([1.1, 2.2], 
[3.3])),
+  (make_array([1.0, 2.0, 3.0], [1.1, 2.2], [3.3]), make_array([1.0], [1.1, 
2.2], [3.3]))
+;
+
+statement ok
+CREATE TABLE array_has_table_3D
+AS VALUES
+  (make_array([[1,2]]), make_array([1])),
+  (make_array([[1,2]]), make_array([1,2])),
+  (make_array([[1,2]]), make_array([1,2,3])),
+  (make_array([[1], [2]]), make_array([2])),
+  (make_array([[1], [2]]), make_array([1], [2])),
+  (make_array([[1], [2]], [[2], [3]]), make_array([1], [2], [3])),
+  (make_array([[1], [2]], [[2], [3]]), make_array([1], [2]))
+;
+
 statement ok
 CREATE TABLE arrays_values_without_nulls
 AS VALUES
@@ -1164,48 +1218,129 @@ NULL 1 1
 2 NULL 1
 2 1 NULL
 
-## array_contains
+## array_has/array_has_all/array_has_any
+
+query BBBBBBBBBBBB
+select array_has(make_array(1,2), 1),
+       array_has(make_array(1,2,NULL), 1),
+       array_has(make_array([2,3], [3,4]), make_array(2,3)),
+       array_has(make_array([[1], [2,3]], [[4,5], [6]]), make_array([1], 
[2,3])),
+       array_has(make_array([[1], [2,3]], [[4,5], [6]]), make_array([4,5], 
[6])),
+       array_has(make_array([[1], [2,3]], [[4,5], [6]]), make_array([1])),
+       array_has(make_array([[[1]]]), make_array([[1]])),
+       array_has(make_array([[[1]]], [[[1], [2]]]), make_array([[2]])),
+       array_has(make_array([[[1]]], [[[1], [2]]]), make_array([[1], [2]])),
+       list_has(make_array(1,2,3), 4),
+       array_contains(make_array(1,2,3), 3),
+       list_contains(make_array(1,2,3), 0)
+;
+----
+true true true true true false true false true false true false
 
-# array_contains scalar function #1
 query BBB
-select array_contains(make_array(1, 2, 3), make_array(1, 1, 2, 3)), 
array_contains([1, 2, 3], [1, 1, 2]), array_contains([1, 2, 3], [2, 1, 3, 1]);
+select array_has(column1, column2),
+       array_has_all(column3, column4),
+       array_has_any(column5, column6)
+from array_has_table_1D;
 ----
 true true true
+false false false
 
-# array_contains scalar function #2
-query BB
-select array_contains([[1, 2], [3, 4]], [[1, 2], [3, 4], [1, 3]]), 
array_contains([[[1], [2]], [[3], [4]]], [1, 2, 2, 3, 4]);
+query BBB
+select array_has(column1, column2),
+       array_has_all(column3, column4),
+       array_has_any(column5, column6)
+from array_has_table_1D_Float;
 ----
-true true
+true true false
+false false true
 
-# array_contains scalar function #3
 query BBB
-select array_contains(make_array(1, 2, 3), make_array(1, 2, 3, 4)), 
array_contains([1, 2, 3], [1, 1, 4]), array_contains([1, 2, 3], [2, 1, 3, 4]);
+select array_has(column1, column2),
+       array_has_all(column3, column4),
+       array_has_any(column5, column6)
+from array_has_table_1D_Boolean;
 ----
-false false false
+false true true
+true true true
 
-# array_contains scalar function #4
-query BB
-select array_contains([[1, 2], [3, 4]], [[1, 2], [3, 4], [1, 5]]), 
array_contains([[[1], [2]], [[3], [4]]], [1, 2, 2, 3, 5]);
+query BBB
+select array_has(column1, column2),
+       array_has_all(column3, column4),
+       array_has_any(column5, column6)
+from array_has_table_1D_UTF8;
 ----
-false false
+true true false
+false false true
 
-# array_contains scalar function #5
 query BB
-select array_contains([true, true, false, true, false], [true, false, false]), 
array_contains([true, false, true], [true, true]);
+select array_has(column1, column2),
+       array_has_all(column3, column4)
+from array_has_table_2D;
+----
+false true
+true false
+
+query B
+select array_has_all(column1, column2)
+from array_has_table_2D_float;
+----
+true
+false
+
+query B
+select array_has(column1, column2) from array_has_table_3D;
+----
+false
+true
+false
+false
+true
+false
+true
+
+query BBBB
+select array_has(column1, make_array(5, 6)),
+       array_has(column1, make_array(7, NULL)),
+       array_has(column2, 5.5),
+       array_has(column3, 'o')
+from arrays;
+----
+false false false true
+true false true false
+true false false true
+false true false false
+false false false false
+false false false false
+
+query BBBBBBBBBBBBB
+select array_has_all(make_array(1,2,3), make_array(1,3)),
+       array_has_all(make_array(1,2,3), make_array(1,4)),
+       array_has_all(make_array([1,2], [3,4]), make_array([1,2])),
+       array_has_all(make_array([1,2], [3,4]), make_array([1,3])),
+       array_has_all(make_array([1,2], [3,4]), make_array([1,2], [3,4], 
[5,6])),
+       array_has_all(make_array([[1,2,3]]), make_array([[1]])),
+       array_has_all(make_array([[1,2,3]]), make_array([[1,2,3]])),
+       array_has_any(make_array(1,2,3), make_array(1,10,100)),
+       array_has_any(make_array(1,2,3), make_array(10,100)),
+       array_has_any(make_array([1,2], [3,4]), make_array([1,10], [10,4])),
+       array_has_any(make_array([1,2], [3,4]), make_array([10,20], [3,4])),
+       array_has_any(make_array([[1,2,3]]), make_array([[1,2,3], [4,5,6]])),
+       array_has_any(make_array([[1,2,3]]), make_array([[1,2,3]], [[4,5,6]]))
+;
 ----
-true true
+true false true false false false true true false false true false true
 
-# array_contains scalar function #6
-query BB
-select array_contains(make_array(true, true, true), make_array(false, false)), 
array_contains([false, false, false], [true, true]);
+query BBBB
+select list_has_all(make_array(1,2,3), make_array(4,5,6)),
+       list_has_all(make_array(1,2,3), make_array(1,2)),
+       list_has_any(make_array(1,2,3), make_array(4,5,6)),
+        list_has_any(make_array(1,2,3), make_array(1,2,4))
+;
 ----
-false false
-
+false true false true
 
 ### Array operators tests
-
-
 ## array concatenate operator
 
 # array concatenate operator with scalars #1 (like array_concat scalar 
function)
@@ -1296,7 +1431,6 @@ select make_array(f0) from fixed_size_list_array
 [[1, 2], [3, 4]]
 
 
-
 ### Delete tables
 
 
@@ -1312,5 +1446,29 @@ drop table arrays;
 statement ok
 drop table arrays_values;
 
+statement ok
+drop table arrays_values_v2;
+
+statement ok
+drop table array_has_table_1D;
+
+statement ok
+drop table array_has_table_1D_Float;
+
+statement ok
+drop table array_has_table_1D_Boolean;
+
+statement ok
+drop table array_has_table_1D_UTF8;
+
+statement ok
+drop table array_has_table_2D;
+
+statement ok
+drop table array_has_table_2D_float;
+
+statement ok
+drop table array_has_table_3D;
+
 statement ok
 drop table arrays_values_without_nulls;
diff --git a/datafusion/expr/src/built_in_function.rs 
b/datafusion/expr/src/built_in_function.rs
index dded73c088..6914de686a 100644
--- a/datafusion/expr/src/built_in_function.rs
+++ b/datafusion/expr/src/built_in_function.rs
@@ -119,8 +119,12 @@ pub enum BuiltinScalarFunction {
     ArrayAppend,
     /// array_concat
     ArrayConcat,
-    /// array_contains
-    ArrayContains,
+    /// array_has
+    ArrayHas,
+    /// array_has_all
+    ArrayHasAll,
+    /// array_has_any
+    ArrayHasAny,
     /// array_dims
     ArrayDims,
     /// array_fill
@@ -330,7 +334,9 @@ impl BuiltinScalarFunction {
             BuiltinScalarFunction::Trunc => Volatility::Immutable,
             BuiltinScalarFunction::ArrayAppend => Volatility::Immutable,
             BuiltinScalarFunction::ArrayConcat => Volatility::Immutable,
-            BuiltinScalarFunction::ArrayContains => Volatility::Immutable,
+            BuiltinScalarFunction::ArrayHasAll => Volatility::Immutable,
+            BuiltinScalarFunction::ArrayHasAny => Volatility::Immutable,
+            BuiltinScalarFunction::ArrayHas => Volatility::Immutable,
             BuiltinScalarFunction::ArrayDims => Volatility::Immutable,
             BuiltinScalarFunction::ArrayFill => Volatility::Immutable,
             BuiltinScalarFunction::ArrayLength => Volatility::Immutable,
@@ -501,7 +507,9 @@ impl BuiltinScalarFunction {
 
                 Ok(expr_type)
             }
-            BuiltinScalarFunction::ArrayContains => Ok(Boolean),
+            BuiltinScalarFunction::ArrayHasAll
+            | BuiltinScalarFunction::ArrayHasAny
+            | BuiltinScalarFunction::ArrayHas => Ok(Boolean),
             BuiltinScalarFunction::ArrayDims => {
                 Ok(List(Arc::new(Field::new("item", UInt64, true))))
             }
@@ -808,7 +816,9 @@ impl BuiltinScalarFunction {
             BuiltinScalarFunction::ArrayConcat => {
                 Signature::variadic_any(self.volatility())
             }
-            BuiltinScalarFunction::ArrayContains => Signature::any(2, 
self.volatility()),
+            BuiltinScalarFunction::ArrayHasAll
+            | BuiltinScalarFunction::ArrayHasAny
+            | BuiltinScalarFunction::ArrayHas => Signature::any(2, 
self.volatility()),
             BuiltinScalarFunction::ArrayDims => Signature::any(1, 
self.volatility()),
             BuiltinScalarFunction::ArrayFill => Signature::any(2, 
self.volatility()),
             BuiltinScalarFunction::ArrayLength => {
@@ -1278,8 +1288,12 @@ fn aliases(func: &BuiltinScalarFunction) -> &'static 
[&'static str] {
         BuiltinScalarFunction::ArrayConcat => {
             &["array_concat", "array_cat", "list_concat", "list_cat"]
         }
-        BuiltinScalarFunction::ArrayContains => &["array_contains"],
         BuiltinScalarFunction::ArrayDims => &["array_dims", "list_dims"],
+        BuiltinScalarFunction::ArrayHasAll => &["array_has_all", 
"list_has_all"],
+        BuiltinScalarFunction::ArrayHasAny => &["array_has_any", 
"list_has_any"],
+        BuiltinScalarFunction::ArrayHas => {
+            &["array_has", "list_has", "array_contains", "list_contains"]
+        }
         BuiltinScalarFunction::ArrayFill => &["array_fill"],
         BuiltinScalarFunction::ArrayLength => &["array_length", "list_length"],
         BuiltinScalarFunction::ArrayNdims => &["array_ndims", "list_ndims"],
diff --git a/datafusion/expr/src/expr_fn.rs b/datafusion/expr/src/expr_fn.rs
index 30d9580c42..418aa8d8f8 100644
--- a/datafusion/expr/src/expr_fn.rs
+++ b/datafusion/expr/src/expr_fn.rs
@@ -536,10 +536,22 @@ scalar_expr!(
 );
 nary_scalar_expr!(ArrayConcat, array_concat, "concatenates arrays.");
 scalar_expr!(
-    ArrayContains,
-    array_contains,
+    ArrayHas,
+    array_has,
     first_array second_array,
-    "returns true, if each element of the second array appearing in the first 
array, otherwise false."
+"Returns true, if the element appears in the first array, otherwise false."
+);
+scalar_expr!(
+    ArrayHasAll,
+    array_has_all,
+    first_array second_array,
+"Returns true if each element of the second array appears in the first array; 
otherwise, it returns false."
+);
+scalar_expr!(
+    ArrayHasAny,
+    array_has_any,
+    first_array second_array,
+"Returns true if at least one element of the second array appears in the first 
array; otherwise, it returns false."
 );
 scalar_expr!(
     ArrayDims,
diff --git a/datafusion/physical-expr/src/array_expressions.rs 
b/datafusion/physical-expr/src/array_expressions.rs
index 47558ecc26..239b2a6a48 100644
--- a/datafusion/physical-expr/src/array_expressions.rs
+++ b/datafusion/physical-expr/src/array_expressions.rs
@@ -1375,69 +1375,275 @@ pub fn array_ndims(args: &[ArrayRef]) -> 
Result<ArrayRef> {
     Ok(Arc::new(result) as ArrayRef)
 }
 
-macro_rules! contains {
-    ($FIRST_ARRAY:expr, $SECOND_ARRAY:expr, $ARRAY_TYPE:ident) => {{
-        let first_array = downcast_arg!($FIRST_ARRAY, $ARRAY_TYPE);
-        let second_array = downcast_arg!($SECOND_ARRAY, $ARRAY_TYPE);
-        let mut res = true;
-        for x in second_array.values().iter().dedup() {
-            if !first_array.values().contains(x) {
-                res = false;
-                break;
+macro_rules! non_list_contains {
+    ($ARRAY:expr, $SUB_ARRAY:expr, $ARRAY_TYPE:ident) => {{
+        let sub_array = downcast_arg!($SUB_ARRAY, $ARRAY_TYPE);
+        let mut boolean_builder = BooleanArray::builder($ARRAY.len());
+
+        for (arr, elem) in $ARRAY.iter().zip(sub_array.iter()) {
+            if let (Some(arr), Some(elem)) = (arr, elem) {
+                let arr = downcast_arg!(arr, $ARRAY_TYPE);
+                let res = arr.iter().dedup().flatten().any(|x| x == elem);
+                boolean_builder.append_value(res);
             }
         }
+        Ok(Arc::new(boolean_builder.finish()))
+    }};
+}
+
+/// Array_has SQL function
+pub fn array_has(args: &[ArrayRef]) -> Result<ArrayRef> {
+    assert_eq!(args.len(), 2);
+
+    let array = args[0].as_list::<i32>();
+
+    match args[1].data_type() {
+        DataType::List(_) => {
+            let sub_array = args[1].as_list::<i32>();
+            let mut boolean_builder = BooleanArray::builder(array.len());
+
+            for (arr, elem) in array.iter().zip(sub_array.iter()) {
+                if let (Some(arr), Some(elem)) = (arr, elem) {
+                    let list_arr = arr.as_list::<i32>();
+                    let res = list_arr.iter().dedup().flatten().any(|x| *x == 
*elem);
+                    boolean_builder.append_value(res);
+                }
+            }
+            Ok(Arc::new(boolean_builder.finish()))
+        }
+
+        // Int64, Int32, Int16, Int8
+        // UInt64, UInt32, UInt16, UInt8
+        DataType::Int64 => {
+            non_list_contains!(array, args[1], Int64Array)
+        }
+        DataType::Int32 => {
+            non_list_contains!(array, args[1], Int32Array)
+        }
+        DataType::Int16 => {
+            non_list_contains!(array, args[1], Int16Array)
+        }
+        DataType::Int8 => {
+            non_list_contains!(array, args[1], Int8Array)
+        }
+        DataType::UInt64 => {
+            non_list_contains!(array, args[1], UInt64Array)
+        }
+        DataType::UInt32 => {
+            non_list_contains!(array, args[1], UInt32Array)
+        }
+        DataType::UInt16 => {
+            non_list_contains!(array, args[1], UInt16Array)
+        }
+        DataType::UInt8 => {
+            non_list_contains!(array, args[1], UInt8Array)
+        }
 
+        DataType::Float64 => {
+            non_list_contains!(array, args[1], Float64Array)
+        }
+        DataType::Float32 => {
+            non_list_contains!(array, args[1], Float32Array)
+        }
+        DataType::Utf8 => {
+            non_list_contains!(array, args[1], StringArray)
+        }
+        DataType::LargeUtf8 => {
+            non_list_contains!(array, args[1], LargeStringArray)
+        }
+        DataType::Boolean => {
+            non_list_contains!(array, args[1], BooleanArray)
+        }
+        data_type => Err(DataFusionError::NotImplemented(format!(
+            "Array_has is not implemented for '{data_type:?}'"
+        ))),
+    }
+}
+
+macro_rules! array_has_any_non_list_check {
+    ($ARRAY:expr, $SUB_ARRAY:expr, $ARRAY_TYPE:ident) => {{
+        let arr = downcast_arg!($ARRAY, $ARRAY_TYPE);
+        let sub_arr = downcast_arg!($SUB_ARRAY, $ARRAY_TYPE);
+
+        let mut res = false;
+        for elem in sub_arr.iter().dedup() {
+            if let Some(elem) = elem {
+                res |= arr.iter().dedup().flatten().any(|x| x == elem);
+            } else {
+                return Err(DataFusionError::Internal(format!(
+                    "array_has_any does not support Null type for element in 
sub_array"
+                )));
+            }
+        }
         res
     }};
 }
 
-/// Array_contains SQL function
-pub fn array_contains(args: &[ArrayRef]) -> Result<ArrayRef> {
-    fn concat_inner_lists(arg: ArrayRef) -> Result<ArrayRef> {
-        match arg.data_type() {
-            DataType::List(field) => match field.data_type() {
-                DataType::List(..) => {
-                    concat_inner_lists(array_concat(&[as_list_array(&arg)?
-                        .values()
-                        .clone()])?)
+/// Array_has_any SQL function
+pub fn array_has_any(args: &[ArrayRef]) -> Result<ArrayRef> {
+    assert_eq!(args.len(), 2);
+
+    let array = args[0].as_list::<i32>();
+    let sub_array = args[1].as_list::<i32>();
+
+    let mut boolean_builder = BooleanArray::builder(array.len());
+    for (arr, sub_arr) in array.iter().zip(sub_array.iter()) {
+        if let (Some(arr), Some(sub_arr)) = (arr, sub_arr) {
+            let res = match (arr.data_type(), sub_arr.data_type()) {
+                (DataType::List(_), DataType::List(_)) => {
+                    let arr = downcast_arg!(arr, ListArray);
+                    let sub_arr = downcast_arg!(sub_arr, ListArray);
+
+                    let mut res = false;
+                    for elem in sub_arr.iter().dedup().flatten() {
+                        res |= arr.iter().dedup().flatten().any(|x| *x == 
*elem);
+                    }
+                    res
                 }
-                _ => Ok(as_list_array(&arg)?.values().clone()),
-            },
-            data_type => Err(DataFusionError::NotImplemented(format!(
-                "Array is not type '{data_type:?}'."
-            ))),
+                // Int64, Int32, Int16, Int8
+                // UInt64, UInt32, UInt16, UInt8
+                (DataType::Int64, DataType::Int64) => {
+                    array_has_any_non_list_check!(arr, sub_arr, Int64Array)
+                }
+                (DataType::Int32, DataType::Int32) => {
+                    array_has_any_non_list_check!(arr, sub_arr, Int32Array)
+                }
+                (DataType::Int16, DataType::Int16) => {
+                    array_has_any_non_list_check!(arr, sub_arr, Int16Array)
+                }
+                (DataType::Int8, DataType::Int8) => {
+                    array_has_any_non_list_check!(arr, sub_arr, Int8Array)
+                }
+                (DataType::UInt64, DataType::UInt64) => {
+                    array_has_any_non_list_check!(arr, sub_arr, UInt64Array)
+                }
+                (DataType::UInt32, DataType::UInt32) => {
+                    array_has_any_non_list_check!(arr, sub_arr, UInt32Array)
+                }
+                (DataType::UInt16, DataType::UInt16) => {
+                    array_has_any_non_list_check!(arr, sub_arr, UInt16Array)
+                }
+                (DataType::UInt8, DataType::UInt8) => {
+                    array_has_any_non_list_check!(arr, sub_arr, UInt8Array)
+                }
+
+                (DataType::Float64, DataType::Float64) => {
+                    array_has_any_non_list_check!(arr, sub_arr, Float64Array)
+                }
+                (DataType::Float32, DataType::Float32) => {
+                    array_has_any_non_list_check!(arr, sub_arr, Float32Array)
+                }
+                (DataType::Boolean, DataType::Boolean) => {
+                    array_has_any_non_list_check!(arr, sub_arr, BooleanArray)
+                }
+                // Utf8, LargeUtf8
+                (DataType::Utf8, DataType::Utf8) => {
+                    array_has_any_non_list_check!(arr, sub_arr, StringArray)
+                }
+                (DataType::LargeUtf8, DataType::LargeUtf8) => {
+                    array_has_any_non_list_check!(arr, sub_arr, 
LargeStringArray)
+                }
+
+                (arr_type, sub_arr_type) => 
Err(DataFusionError::NotImplemented(format!(
+                    "Array_has_any is not implemented for '{arr_type:?}' and 
'{sub_arr_type:?}'",
+                )))?,
+            };
+            boolean_builder.append_value(res);
         }
     }
+    Ok(Arc::new(boolean_builder.finish()))
+}
 
-    let concat_first_array = concat_inner_lists(args[0].clone())?.clone();
-    let concat_second_array = concat_inner_lists(args[1].clone())?.clone();
+macro_rules! array_has_all_non_list_check {
+    ($ARRAY:expr, $SUB_ARRAY:expr, $ARRAY_TYPE:ident) => {{
+        let arr = downcast_arg!($ARRAY, $ARRAY_TYPE);
+        let sub_arr = downcast_arg!($SUB_ARRAY, $ARRAY_TYPE);
 
-    let res = match (concat_first_array.data_type(), 
concat_second_array.data_type()) {
-        (DataType::Utf8, DataType::Utf8) => contains!(concat_first_array, 
concat_second_array, StringArray),
-        (DataType::LargeUtf8, DataType::LargeUtf8) => 
contains!(concat_first_array, concat_second_array, LargeStringArray),
-        (DataType::Boolean, DataType::Boolean) => {
-            let first_array = downcast_arg!(concat_first_array, BooleanArray);
-            let second_array = downcast_arg!(concat_second_array, 
BooleanArray);
-            compute::bool_or(first_array) == compute::bool_or(second_array)
-        }
-        (DataType::Float32, DataType::Float32) => 
contains!(concat_first_array, concat_second_array, Float32Array),
-        (DataType::Float64, DataType::Float64) => 
contains!(concat_first_array, concat_second_array, Float64Array),
-        (DataType::Int8, DataType::Int8) => contains!(concat_first_array, 
concat_second_array, Int8Array),
-        (DataType::Int16, DataType::Int16) => contains!(concat_first_array, 
concat_second_array, Int16Array),
-        (DataType::Int32, DataType::Int32) => contains!(concat_first_array, 
concat_second_array, Int32Array),
-        (DataType::Int64, DataType::Int64) => contains!(concat_first_array, 
concat_second_array, Int64Array),
-        (DataType::UInt8, DataType::UInt8) => contains!(concat_first_array, 
concat_second_array, UInt8Array),
-        (DataType::UInt16, DataType::UInt16) => contains!(concat_first_array, 
concat_second_array, UInt16Array),
-        (DataType::UInt32, DataType::UInt32) => contains!(concat_first_array, 
concat_second_array, UInt32Array),
-        (DataType::UInt64, DataType::UInt64) => contains!(concat_first_array, 
concat_second_array, UInt64Array),
-        (first_array_data_type, second_array_data_type) => {
-            return Err(DataFusionError::NotImplemented(format!(
-                "Array_contains is not implemented for types 
'{first_array_data_type:?}' and '{second_array_data_type:?}'."
-            )))
+        let mut res = true;
+        for elem in sub_arr.iter().dedup() {
+            if let Some(elem) = elem {
+                res &= arr.iter().dedup().flatten().any(|x| x == elem);
+            } else {
+                return Err(DataFusionError::Internal(format!(
+                    "array_has_all does not support Null type for element in 
sub_array"
+                )));
+            }
         }
-    };
+        res
+    }};
+}
+
+/// Array_has_all SQL function
+pub fn array_has_all(args: &[ArrayRef]) -> Result<ArrayRef> {
+    assert_eq!(args.len(), 2);
+
+    let array = args[0].as_list::<i32>();
+    let sub_array = args[1].as_list::<i32>();
+
+    let mut boolean_builder = BooleanArray::builder(array.len());
+    for (arr, sub_arr) in array.iter().zip(sub_array.iter()) {
+        if let (Some(arr), Some(sub_arr)) = (arr, sub_arr) {
+            let res = match (arr.data_type(), sub_arr.data_type()) {
+                (DataType::List(_), DataType::List(_)) => {
+                    let arr = downcast_arg!(arr, ListArray);
+                    let sub_arr = downcast_arg!(sub_arr, ListArray);
+
+                    let mut res = true;
+                    for elem in sub_arr.iter().dedup().flatten() {
+                        res &= arr.iter().dedup().flatten().any(|x| *x == 
*elem);
+                    }
+                    res
+                }
+                // Int64, Int32, Int16, Int8
+                // UInt64, UInt32, UInt16, UInt8
+                (DataType::Int64, DataType::Int64) => {
+                    array_has_all_non_list_check!(arr, sub_arr, Int64Array)
+                }
+                (DataType::Int32, DataType::Int32) => {
+                    array_has_all_non_list_check!(arr, sub_arr, Int32Array)
+                }
+                (DataType::Int16, DataType::Int16) => {
+                    array_has_all_non_list_check!(arr, sub_arr, Int16Array)
+                }
+                (DataType::Int8, DataType::Int8) => {
+                    array_has_all_non_list_check!(arr, sub_arr, Int8Array)
+                }
+                (DataType::UInt64, DataType::UInt64) => {
+                    array_has_all_non_list_check!(arr, sub_arr, UInt64Array)
+                }
+                (DataType::UInt32, DataType::UInt32) => {
+                    array_has_all_non_list_check!(arr, sub_arr, UInt32Array)
+                }
+                (DataType::UInt16, DataType::UInt16) => {
+                    array_has_all_non_list_check!(arr, sub_arr, UInt16Array)
+                }
+                (DataType::UInt8, DataType::UInt8) => {
+                    array_has_all_non_list_check!(arr, sub_arr, UInt8Array)
+                }
 
-    Ok(Arc::new(BooleanArray::from(vec![res])))
+                (DataType::Float64, DataType::Float64) => {
+                    array_has_all_non_list_check!(arr, sub_arr, Float64Array)
+                }
+                (DataType::Float32, DataType::Float32) => {
+                    array_has_all_non_list_check!(arr, sub_arr, Float32Array)
+                }
+                (DataType::Boolean, DataType::Boolean) => {
+                    array_has_all_non_list_check!(arr, sub_arr, BooleanArray)
+                }
+                (DataType::Utf8, DataType::Utf8) => {
+                    array_has_all_non_list_check!(arr, sub_arr, StringArray)
+                }
+                (DataType::LargeUtf8, DataType::LargeUtf8) => {
+                    array_has_all_non_list_check!(arr, sub_arr, 
LargeStringArray)
+                }
+                (arr_type, sub_arr_type) => 
Err(DataFusionError::NotImplemented(format!(
+                    "Array_has_all is not implemented for '{arr_type:?}' and 
'{sub_arr_type:?}'",
+                )))?,
+            };
+            boolean_builder.append_value(res);
+        }
+    }
+    Ok(Arc::new(boolean_builder.finish()))
 }
 
 #[cfg(test)]
@@ -2070,63 +2276,6 @@ mod tests {
         assert_eq!(result, &UInt64Array::from_value(2, 1));
     }
 
-    #[test]
-    fn test_array_contains() {
-        // array_contains([1, 2, 3, 4], array_append([1, 2, 3, 4], 3)) = t
-        let first_array = return_array().into_array(1);
-        let second_array = array_append(&[
-            first_array.clone(),
-            Arc::new(Int64Array::from(vec![Some(3)])),
-        ])
-        .expect("failed to initialize function array_contains");
-
-        let arr = array_contains(&[first_array.clone(), second_array])
-            .expect("failed to initialize function array_contains");
-        let result = as_boolean_array(&arr);
-
-        assert_eq!(result, &BooleanArray::from(vec![true]));
-
-        // array_contains([1, 2, 3, 4], array_append([1, 2, 3, 4], 5)) = f
-        let second_array = array_append(&[
-            first_array.clone(),
-            Arc::new(Int64Array::from(vec![Some(5)])),
-        ])
-        .expect("failed to initialize function array_contains");
-
-        let arr = array_contains(&[first_array.clone(), second_array])
-            .expect("failed to initialize function array_contains");
-        let result = as_boolean_array(&arr);
-
-        assert_eq!(result, &BooleanArray::from(vec![false]));
-    }
-
-    #[test]
-    fn test_nested_array_contains() {
-        // array_contains([[1, 2, 3, 4], [5, 6, 7, 8]], array_append([1, 2, 3, 
4], 3)) = t
-        let first_array = return_nested_array().into_array(1);
-        let array = return_array().into_array(1);
-        let second_array =
-            array_append(&[array.clone(), 
Arc::new(Int64Array::from(vec![Some(3)]))])
-                .expect("failed to initialize function array_contains");
-
-        let arr = array_contains(&[first_array.clone(), second_array])
-            .expect("failed to initialize function array_contains");
-        let result = as_boolean_array(&arr);
-
-        assert_eq!(result, &BooleanArray::from(vec![true]));
-
-        // array_contains([[1, 2, 3, 4], [5, 6, 7, 8]], array_append([1, 2, 3, 
4], 9)) = f
-        let second_array =
-            array_append(&[array.clone(), 
Arc::new(Int64Array::from(vec![Some(9)]))])
-                .expect("failed to initialize function array_contains");
-
-        let arr = array_contains(&[first_array.clone(), second_array])
-            .expect("failed to initialize function array_contains");
-        let result = as_boolean_array(&arr);
-
-        assert_eq!(result, &BooleanArray::from(vec![false]));
-    }
-
     fn return_array() -> ColumnarValue {
         let args = [
             ColumnarValue::Scalar(ScalarValue::Int64(Some(1))),
diff --git a/datafusion/physical-expr/src/functions.rs 
b/datafusion/physical-expr/src/functions.rs
index 14279d7006..f48823bff5 100644
--- a/datafusion/physical-expr/src/functions.rs
+++ b/datafusion/physical-expr/src/functions.rs
@@ -416,8 +416,14 @@ pub fn create_physical_fun(
         BuiltinScalarFunction::ArrayConcat => {
             Arc::new(|args| 
make_scalar_function(array_expressions::array_concat)(args))
         }
-        BuiltinScalarFunction::ArrayContains => {
-            Arc::new(|args| 
make_scalar_function(array_expressions::array_contains)(args))
+        BuiltinScalarFunction::ArrayHasAll => {
+            Arc::new(|args| 
make_scalar_function(array_expressions::array_has_all)(args))
+        }
+        BuiltinScalarFunction::ArrayHasAny => {
+            Arc::new(|args| 
make_scalar_function(array_expressions::array_has_any)(args))
+        }
+        BuiltinScalarFunction::ArrayHas => {
+            Arc::new(|args| 
make_scalar_function(array_expressions::array_has)(args))
         }
         BuiltinScalarFunction::ArrayDims => {
             Arc::new(|args| 
make_scalar_function(array_expressions::array_dims)(args))
diff --git a/datafusion/proto/proto/datafusion.proto 
b/datafusion/proto/proto/datafusion.proto
index a1caa4c621..8192a403d3 100644
--- a/datafusion/proto/proto/datafusion.proto
+++ b/datafusion/proto/proto/datafusion.proto
@@ -563,10 +563,12 @@ enum ScalarFunction {
   ArrayToString = 97;
   Cardinality = 98;
   TrimArray = 99;
-  ArrayContains = 100;
   Encode = 101;
   Decode = 102;
   Cot = 103;
+  ArrayHas = 104;
+  ArrayHasAny = 105;
+  ArrayHasAll = 106;
 }
 
 message ScalarFunctionNode {
diff --git a/datafusion/proto/src/generated/pbjson.rs 
b/datafusion/proto/src/generated/pbjson.rs
index 4155a052cf..05bfbd089d 100644
--- a/datafusion/proto/src/generated/pbjson.rs
+++ b/datafusion/proto/src/generated/pbjson.rs
@@ -18064,10 +18064,12 @@ impl serde::Serialize for ScalarFunction {
             Self::ArrayToString => "ArrayToString",
             Self::Cardinality => "Cardinality",
             Self::TrimArray => "TrimArray",
-            Self::ArrayContains => "ArrayContains",
             Self::Encode => "Encode",
             Self::Decode => "Decode",
             Self::Cot => "Cot",
+            Self::ArrayHas => "ArrayHas",
+            Self::ArrayHasAny => "ArrayHasAny",
+            Self::ArrayHasAll => "ArrayHasAll",
         };
         serializer.serialize_str(variant)
     }
@@ -18179,10 +18181,12 @@ impl<'de> serde::Deserialize<'de> for ScalarFunction {
             "ArrayToString",
             "Cardinality",
             "TrimArray",
-            "ArrayContains",
             "Encode",
             "Decode",
             "Cot",
+            "ArrayHas",
+            "ArrayHasAny",
+            "ArrayHasAll",
         ];
 
         struct GeneratedVisitor;
@@ -18325,10 +18329,12 @@ impl<'de> serde::Deserialize<'de> for ScalarFunction {
                     "ArrayToString" => Ok(ScalarFunction::ArrayToString),
                     "Cardinality" => Ok(ScalarFunction::Cardinality),
                     "TrimArray" => Ok(ScalarFunction::TrimArray),
-                    "ArrayContains" => Ok(ScalarFunction::ArrayContains),
                     "Encode" => Ok(ScalarFunction::Encode),
                     "Decode" => Ok(ScalarFunction::Decode),
                     "Cot" => Ok(ScalarFunction::Cot),
+                    "ArrayHas" => Ok(ScalarFunction::ArrayHas),
+                    "ArrayHasAny" => Ok(ScalarFunction::ArrayHasAny),
+                    "ArrayHasAll" => Ok(ScalarFunction::ArrayHasAll),
                     _ => Err(serde::de::Error::unknown_variant(value, FIELDS)),
                 }
             }
diff --git a/datafusion/proto/src/generated/prost.rs 
b/datafusion/proto/src/generated/prost.rs
index af0703460a..f50754494d 100644
--- a/datafusion/proto/src/generated/prost.rs
+++ b/datafusion/proto/src/generated/prost.rs
@@ -2262,10 +2262,12 @@ pub enum ScalarFunction {
     ArrayToString = 97,
     Cardinality = 98,
     TrimArray = 99,
-    ArrayContains = 100,
     Encode = 101,
     Decode = 102,
     Cot = 103,
+    ArrayHas = 104,
+    ArrayHasAny = 105,
+    ArrayHasAll = 106,
 }
 impl ScalarFunction {
     /// String value of the enum field names used in the ProtoBuf definition.
@@ -2374,10 +2376,12 @@ impl ScalarFunction {
             ScalarFunction::ArrayToString => "ArrayToString",
             ScalarFunction::Cardinality => "Cardinality",
             ScalarFunction::TrimArray => "TrimArray",
-            ScalarFunction::ArrayContains => "ArrayContains",
             ScalarFunction::Encode => "Encode",
             ScalarFunction::Decode => "Decode",
             ScalarFunction::Cot => "Cot",
+            ScalarFunction::ArrayHas => "ArrayHas",
+            ScalarFunction::ArrayHasAny => "ArrayHasAny",
+            ScalarFunction::ArrayHasAll => "ArrayHasAll",
         }
     }
     /// Creates an enum from field names used in the ProtoBuf definition.
@@ -2483,10 +2487,12 @@ impl ScalarFunction {
             "ArrayToString" => Some(Self::ArrayToString),
             "Cardinality" => Some(Self::Cardinality),
             "TrimArray" => Some(Self::TrimArray),
-            "ArrayContains" => Some(Self::ArrayContains),
             "Encode" => Some(Self::Encode),
             "Decode" => Some(Self::Decode),
             "Cot" => Some(Self::Cot),
+            "ArrayHas" => Some(Self::ArrayHas),
+            "ArrayHasAny" => Some(Self::ArrayHasAny),
+            "ArrayHasAll" => Some(Self::ArrayHasAll),
             _ => None,
         }
     }
diff --git a/datafusion/proto/src/logical_plan/from_proto.rs 
b/datafusion/proto/src/logical_plan/from_proto.rs
index a3718090ed..674588692d 100644
--- a/datafusion/proto/src/logical_plan/from_proto.rs
+++ b/datafusion/proto/src/logical_plan/from_proto.rs
@@ -36,12 +36,12 @@ use datafusion_common::{
 };
 use datafusion_expr::expr::{Alias, Placeholder};
 use datafusion_expr::{
-    abs, acos, acosh, array, array_append, array_concat, array_contains, 
array_dims,
-    array_fill, array_length, array_ndims, array_position, array_positions,
-    array_prepend, array_remove, array_replace, array_to_string, ascii, asin, 
asinh,
-    atan, atan2, atanh, bit_length, btrim, cardinality, cbrt, ceil, 
character_length,
-    chr, coalesce, concat_expr, concat_ws_expr, cos, cosh, cot, current_date,
-    current_time, date_bin, date_part, date_trunc, degrees, digest, exp,
+    abs, acos, acosh, array, array_append, array_concat, array_dims, 
array_fill,
+    array_has, array_has_all, array_has_any, array_length, array_ndims, 
array_position,
+    array_positions, array_prepend, array_remove, array_replace, 
array_to_string, ascii,
+    asin, asinh, atan, atan2, atanh, bit_length, btrim, cardinality, cbrt, 
ceil,
+    character_length, chr, coalesce, concat_expr, concat_ws_expr, cos, cosh, 
cot,
+    current_date, current_time, date_bin, date_part, date_trunc, degrees, 
digest, exp,
     expr::{self, InList, Sort, WindowFunction},
     factorial, floor, from_unixtime, gcd, lcm, left, ln, log, log10, log2,
     logical_plan::{PlanType, StringifiedPlan},
@@ -451,7 +451,9 @@ impl From<&protobuf::ScalarFunction> for 
BuiltinScalarFunction {
             ScalarFunction::ToTimestamp => Self::ToTimestamp,
             ScalarFunction::ArrayAppend => Self::ArrayAppend,
             ScalarFunction::ArrayConcat => Self::ArrayConcat,
-            ScalarFunction::ArrayContains => Self::ArrayContains,
+            ScalarFunction::ArrayHasAll => Self::ArrayHasAll,
+            ScalarFunction::ArrayHasAny => Self::ArrayHasAny,
+            ScalarFunction::ArrayHas => Self::ArrayHas,
             ScalarFunction::ArrayDims => Self::ArrayDims,
             ScalarFunction::ArrayFill => Self::ArrayFill,
             ScalarFunction::ArrayLength => Self::ArrayLength,
@@ -1219,7 +1221,15 @@ pub fn parse_expr(
                         .map(|expr| parse_expr(expr, registry))
                         .collect::<Result<Vec<_>, _>>()?,
                 )),
-                ScalarFunction::ArrayContains => Ok(array_contains(
+                ScalarFunction::ArrayHasAll => Ok(array_has_all(
+                    parse_expr(&args[0], registry)?,
+                    parse_expr(&args[1], registry)?,
+                )),
+                ScalarFunction::ArrayHasAny => Ok(array_has_any(
+                    parse_expr(&args[0], registry)?,
+                    parse_expr(&args[1], registry)?,
+                )),
+                ScalarFunction::ArrayHas => Ok(array_has(
                     parse_expr(&args[0], registry)?,
                     parse_expr(&args[1], registry)?,
                 )),
diff --git a/datafusion/proto/src/logical_plan/to_proto.rs 
b/datafusion/proto/src/logical_plan/to_proto.rs
index e899eee6fe..072bc84d54 100644
--- a/datafusion/proto/src/logical_plan/to_proto.rs
+++ b/datafusion/proto/src/logical_plan/to_proto.rs
@@ -1382,7 +1382,9 @@ impl TryFrom<&BuiltinScalarFunction> for 
protobuf::ScalarFunction {
             BuiltinScalarFunction::ToTimestamp => Self::ToTimestamp,
             BuiltinScalarFunction::ArrayAppend => Self::ArrayAppend,
             BuiltinScalarFunction::ArrayConcat => Self::ArrayConcat,
-            BuiltinScalarFunction::ArrayContains => Self::ArrayContains,
+            BuiltinScalarFunction::ArrayHasAll => Self::ArrayHasAll,
+            BuiltinScalarFunction::ArrayHasAny => Self::ArrayHasAny,
+            BuiltinScalarFunction::ArrayHas => Self::ArrayHas,
             BuiltinScalarFunction::ArrayDims => Self::ArrayDims,
             BuiltinScalarFunction::ArrayFill => Self::ArrayFill,
             BuiltinScalarFunction::ArrayLength => Self::ArrayLength,
diff --git a/docs/source/user-guide/expressions.md 
b/docs/source/user-guide/expressions.md
index cf1e2f58af..14cf8dc2ac 100644
--- a/docs/source/user-guide/expressions.md
+++ b/docs/source/user-guide/expressions.md
@@ -179,24 +179,26 @@ Unlike to some databases the math functions in Datafusion 
works the same way as
 
 ## Array Expressions
 
-| Function                                  | Notes                            
                                                                              |
-| ----------------------------------------- | 
--------------------------------------------------------------------------------------------------------------
 |
-| array_append(array, element)              | Appends an element to the end of 
an array. `array_append([1, 2, 3], 4) -> [1, 2, 3, 4]`                        |
-| array_concat(array[, ..., array_n])       | Concatenates arrays. 
`array_concat([1, 2, 3], [4, 5, 6]) -> [1, 2, 3, 4, 5, 6]`                      
          |
-| array_contains(first_array, second_array) | Returns true, if each element of 
the second array appearing in the first array, otherwise false.               |
-| array_dims(array)                         | Returns an array of the array's 
dimensions. `array_dims([[1, 2, 3], [4, 5, 6]]) -> [2, 3]`                     |
-| array_fill(element, array)                | Returns an array filled with 
copies of the given value.                                                      
  |
-| array_length(array, dimension)            | Returns the length of the array 
dimension. `array_length([1, 2, 3, 4, 5]) -> 5`                                |
-| array_ndims(array)                        | Returns the number of dimensions 
of the array. `array_ndims([[1, 2, 3], [4, 5, 6]]) -> 2`                      |
-| array_position(array, element)            | Searches for an element in the 
array, returns first occurrence. `array_position([1, 2, 2, 3, 4], 2) -> 2`      
|
-| array_positions(array, element)           | Searches for an element in the 
array, returns all occurrences. `array_positions([1, 2, 2, 3, 4], 2) -> [2, 3]` 
|
-| array_prepend(array, element)             | Prepends an element to the 
beginning of an array. `array_prepend(1, [2, 3, 4]) -> [1, 2, 3, 4]`            
    |
-| array_remove(array, element)              | Removes all elements equal to 
the given value from the array.                                                 
 |
-| array_replace(array, from, to)            | Replaces a specified element 
with another specified element.                                                 
  |
-| array_to_string(array, delimeter)         | Converts each element to its 
text representation. `array_to_string([1, 2, 3, 4], ',') -> 1,2,3,4`            
  |
-| cardinality(array)                        | Returns the total number of 
elements in the array. `cardinality([[1, 2, 3], [4, 5, 6]]) -> 6`               
   |
-| make_array(value1, [value2 [, ...]])      | Returns an Arrow array using the 
specified input expressions. `make_array(1, 2, 3) -> [1, 2, 3]`               |
-| trim_array(array, n)                      | Removes the last n elements from 
the array.                                                                    |
+| Function                             | Notes                                 
                                                                         |
+| ------------------------------------ | 
--------------------------------------------------------------------------------------------------------------
 |
+| array_append(array, element)         | Appends an element to the end of an 
array. `array_append([1, 2, 3], 4) -> [1, 2, 3, 4]`                        |
+| array_concat(array[, ..., array_n])  | Concatenates arrays. 
`array_concat([1, 2, 3], [4, 5, 6]) -> [1, 2, 3, 4, 5, 6]`                      
          |
+| array_has(array, element)            | Returns true if the array contains 
the element `array_has([1,2,3], 1) -> true`                                 |
+| array_has_all(array, sub-array)      | Returns true if all elements of 
sub-array exist in array `array_has_all([1,2,3], [1,3]) -> true`               |
+| array_has_any(array, sub-array)      | Returns true if any elements exist in 
both arrays `array_has_any([1,2,3], [1,4]) -> true`                      |
+| array_dims(array)                    | Returns an array of the array's 
dimensions. `array_dims([[1, 2, 3], [4, 5, 6]]) -> [2, 3]`                     |
+| array_fill(element, array)           | Returns an array filled with copies 
of the given value.                                                        |
+| array_length(array, dimension)       | Returns the length of the array 
dimension. `array_length([1, 2, 3, 4, 5]) -> 5`                                |
+| array_ndims(array)                   | Returns the number of dimensions of 
the array. `array_ndims([[1, 2, 3], [4, 5, 6]]) -> 2`                      |
+| array_position(array, element)       | Searches for an element in the array, 
returns first occurrence. `array_position([1, 2, 2, 3, 4], 2) -> 2`      |
+| array_positions(array, element)      | Searches for an element in the array, 
returns all occurrences. `array_positions([1, 2, 2, 3, 4], 2) -> [2, 3]` |
+| array_prepend(array, element)        | Prepends an element to the beginning 
of an array. `array_prepend(1, [2, 3, 4]) -> [1, 2, 3, 4]`                |
+| array_remove(array, element)         | Removes all elements equal to the 
given value from the array.                                                  |
+| array_replace(array, from, to)       | Replaces a specified element with 
another specified element.                                                   |
+| array_to_string(array, delimeter)    | Converts each element to its text 
representation. `array_to_string([1, 2, 3, 4], ',') -> 1,2,3,4`              |
+| cardinality(array)                   | Returns the total number of elements 
in the array. `cardinality([[1, 2, 3], [4, 5, 6]]) -> 6`                  |
+| make_array(value1, [value2 [, ...]]) | Returns an Arrow array using the 
specified input expressions. `make_array(1, 2, 3) -> [1, 2, 3]`               |
+| trim_array(array, n)                 | Removes the last n elements from the 
array.                                                                    |
 
 ## Regular Expressions
 
diff --git a/docs/source/user-guide/sql/scalar_functions.md 
b/docs/source/user-guide/sql/scalar_functions.md
index 31b075821b..bcdd383252 100644
--- a/docs/source/user-guide/sql/scalar_functions.md
+++ b/docs/source/user-guide/sql/scalar_functions.md
@@ -1522,19 +1522,49 @@ array_concat(array[, ..., array_n])
 - list_cat
 - list_concat
 
-### `array_contains`
+### `array_has`
 
-Returns true, if each element of the second array appears in the first array, 
otherwise false.
+Returns true if the array contains the element
 
 ```
-array_contains(first_array, second_array)
+array_has(array, element)
 ```
 
 #### Arguments
 
-- **first_array**: Array expression.
+- **array**: Array expression.
+  Can be a constant, column, or function, and any combination of array 
operators.
+- **element**: Scalar or Array expression.
+  Can be a constant, column, or function, and any combination of array 
operators.
+
+### `array_has_all`
+
+Returns true if all elements of sub-array exist in array
+
+```
+array_has_all(array, sub-array)
+```
+
+#### Arguments
+
+- **array**: Array expression.
+  Can be a constant, column, or function, and any combination of array 
operators.
+- **sub-array**: Array expression.
+  Can be a constant, column, or function, and any combination of array 
operators.
+
+### `array_has_any`
+
+Returns true if any elements exist in both arrays
+
+```
+array_has_any(array, sub-array)
+```
+
+#### Arguments
+
+- **array**: Array expression.
   Can be a constant, column, or function, and any combination of array 
operators.
-- **second_array**: Array expression.
+- **sub-array**: Array expression.
   Can be a constant, column, or function, and any combination of array 
operators.
 
 ### `array_dims`

Reply via email to