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

morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new e9848066c95 [FIX](type) fix matchExactType for complex type (#28233)
e9848066c95 is described below

commit e9848066c953d97aae9248b2ac22794ccd242d3c
Author: amory <wangqian...@selectdb.com>
AuthorDate: Thu Dec 21 11:49:05 2023 +0800

    [FIX](type) fix matchExactType for complex type (#28233)
    
    fe matchExactType function should call type.matchTypes for its own logic, 
do not switch case to do special logic otherwise we may meet core in be like 
this.
     ```
    F20231208 18:54:39.359673 680131 block.h:535] Check failed: 
_data_types[i]->is_nullable()  target type: 
Struct(l_info:Nullable(Array(Nullable(String)))) src type: 
Struct(col:Nullable(Array(Nullable(UInt8))))
    *** Check failure stack trace: ***
        @     0x5584e952b926  google::LogMessage::SendToLog()
        @     0x5584e9527ef0  google::LogMessage::Flush()
        @     0x5584e952c169  google::LogMessageFatal::~LogMessageFatal()
        @     0x5584cf17201e  doris::vectorized::MutableBlock::merge_impl<>()
        @     0x5584ceac4b1d  doris::vectorized::MutableBlock::merge<>()
        @     0x5584d4dd7de3  doris::vectorized::VUnionNode::get_next_const()
        @     0x5584d4dd9a45  doris::vectorized::VUnionNode::get_next()
        @     0x5584bce469bd  std::__invoke_impl<>()
        @     0x5584bce466d0  std::__invoke<>()
        @     0x5584bce465c7  
_ZNSt5_BindIFMN5doris8ExecNodeEFNS0_6StatusEPNS0_12RuntimeStateEPNS0_10vectorized5BlockEPbEPS1_St12_PlaceholderILi1EESC_ILi2EESC_ILi3EEEE6__callIS2_JOS4_OS7_OS8_EJLm0ELm1ELm2ELm3EEEET_OSt5tupleIJDpT0_EESt12_Index_tupleIJXspT1_EEE
        @     0x5584bce46358  std::_Bind<>::operator()<>()
        @     0x5584bce46208  std::__invoke_impl<>()
        @     0x5584bce46178  
_ZSt10__invoke_rIN5doris6StatusERSt5_BindIFMNS0_8ExecNodeEFS1_PNS0_12RuntimeStateEPNS0_10vectorized5BlockEPbEPS3_St12_PlaceholderILi1EESD_ILi2EESD_ILi3EEEEJS5_S8_S9_EENSt9enable_ifIX16is_invocable_r_vIT_T0_DpT1_EESL_E4typeEOSM_DpOSN_
        @     0x5584bce45c18  std::_Function_handler<>::_M_invoke()
        @     0x5584bce6412f  std::function<>::operator()()
        @     0x5584bce56382  doris::ExecNode::get_next_after_projects()
        @     0x5584bce26218  
doris::PlanFragmentExecutor::get_vectorized_internal()
        @     0x5584bce2431b  
doris::PlanFragmentExecutor::open_vectorized_internal()
        @     0x5584bce22a96  doris::PlanFragmentExecutor::open()
        @     0x5584bce27c9d  doris::PlanFragmentExecutor::execute()
        @     0x5584bcbdb3f8  doris::FragmentMgr::_exec_actual()
        @     0x5584bcbf982f  
doris::FragmentMgr::exec_plan_fragment()::$_0::operator()()
        @     0x5584bcbf9715  std::__invoke_impl<>()
        @     0x5584bcbf96b5  
_ZSt10__invoke_rIvRZN5doris11FragmentMgr18exec_plan_fragmentERKNS0_23TExecPlanFragmentParamsERKSt8functionIFvPNS0_12RuntimeStateEPNS0_6StatusEEEE3$_0JEENSt9enable_ifIX16is_invocable_r_vIT_T0_DpT1_EESH_E4typeEOSI_DpOSJ_
        @     0x5584bcbf942d  std::_Function_handler<>::_M_invoke()
        @     0x5584b9dfd883  std::function<>::operator()()
        @     0x5584bd6e3929  doris::FunctionRunnable::run()
        @     0x5584bd6cf8ce  doris::ThreadPool::dispatch_thread()
    ```
---
 .../java/org/apache/doris/catalog/ArrayType.java   |  8 +--
 .../java/org/apache/doris/catalog/MapType.java     |  8 ++-
 .../org/apache/doris/catalog/TemplateType.java     |  3 +-
 .../main/java/org/apache/doris/catalog/Type.java   | 17 +----
 .../apache/doris/analysis/FunctionCallExpr.java    |  8 +++
 .../org/apache/doris/analysis/IsNullPredicate.java | 17 +++--
 .../org/apache/doris/analysis/StructLiteral.java   |  7 +++
 .../java/org/apache/doris/catalog/FunctionSet.java | 42 ++++++++++---
 .../apache/doris/catalog/FunctionTypeDeducers.java | 34 ++++++++--
 gensrc/script/doris_builtins_functions.py          | 27 +++-----
 .../test_nested_types_insert_into_with_literal.out | 28 +++++++++
 ...st_nested_types_insert_into_with_literal.groovy | 73 ++++++++++++++++++++++
 12 files changed, 204 insertions(+), 68 deletions(-)

diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java
index 8edcfb51730..27f02c802cb 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/ArrayType.java
@@ -88,13 +88,11 @@ public class ArrayType extends Type {
             return false;
         }
 
-        // Array(Null) is a virtual Array type, can match any Array(...) type
-        if (itemType.isNull() || ((ArrayType) t).getItemType().isNull()) {
-            return true;
+        if (((ArrayType) t).getContainsNull() != getContainsNull()) {
+            return false;
         }
 
-        return itemType.matchesType(((ArrayType) t).itemType)
-                && (((ArrayType) t).containsNull || !containsNull);
+        return itemType.matchesType(((ArrayType) t).itemType);
     }
 
     @Override
diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java
index e6ab17c626b..1291a5f364e 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/MapType.java
@@ -126,9 +126,11 @@ public class MapType extends Type {
             return false;
         }
 
-        if ((keyType.isNull() || ((MapType) t).getKeyType().isNull())
-                && (valueType.isNull() || ((MapType) 
t).getKeyType().isNull())) {
-            return true;
+        if (((MapType) t).getIsKeyContainsNull() != getIsKeyContainsNull()) {
+            return false;
+        }
+        if (((MapType) t).getIsValueContainsNull() != 
getIsValueContainsNull()) {
+            return false;
         }
 
         return keyType.matchesType(((MapType) t).keyType)
diff --git 
a/fe/fe-common/src/main/java/org/apache/doris/catalog/TemplateType.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/TemplateType.java
index ba5ed62f9d0..3ba05614940 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/TemplateType.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/TemplateType.java
@@ -95,6 +95,7 @@ public class TemplateType extends Type {
         }
 
         if (specializedType != null
+                && !specializedType.isNull()
                 && !specificType.equals(specializedType)
                 && !specificType.matchesType(specializedType)
                 && !Type.isImplicitlyCastable(specificType, specializedType, 
true, enableDecimal256)
@@ -104,7 +105,7 @@ public class TemplateType extends Type {
                     name, specificType, specializedType));
         }
 
-        if (specializedType == null) {
+        if (specializedType == null || specializedType.isNull()) {
             specializedTypeMap.put(name, specificType);
         }
         return specializedTypeMap.get(name);
diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
index ab9b56c5aa5..a7e1660dd02 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
@@ -2241,6 +2241,7 @@ public abstract class Type {
     }
 
     public static boolean matchExactType(Type type1, Type type2, boolean 
ignorePrecision) {
+        // we should make type decide to match other for itself to impl 
matchesType instead of switch case types
         if (type1.matchesType(type2)) {
             if 
(PrimitiveType.typeWithPrecision.contains(type2.getPrimitiveType())) {
                 // For types which has precision and scale, we also need to 
check quality between precisions and scales
@@ -2253,22 +2254,6 @@ public abstract class Type {
                     return 
isSameDecimalTypeWithDifferentPrecision(((ScalarType) type2).decimalPrecision(),
                             ((ScalarType) type1).decimalPrecision());
                 }
-            } else if (type2.isArrayType()) {
-                // For types array, we also need to check contains null for 
case like
-                // cast(array<not_null(int)> as array<int>)
-                if (((ArrayType) type2).getContainsNull() != ((ArrayType) 
type1).getContainsNull()) {
-                    return false;
-                }
-                return matchExactType(((ArrayType) type2).getItemType(), 
((ArrayType) type1).getItemType());
-            } else if (type2.isMapType()) {
-                if (((MapType) type2).getIsKeyContainsNull() != ((MapType) 
type1).getIsKeyContainsNull()) {
-                    return false;
-                }
-                if (((MapType) type2).getIsValueContainsNull() != ((MapType) 
type1).getIsValueContainsNull()) {
-                    return false;
-                }
-                return matchExactType(((MapType) type2).getKeyType(), 
((MapType) type1).getKeyType())
-                    && matchExactType(((MapType) type2).getValueType(), 
((MapType) type1).getValueType());
             } else {
                 return true;
             }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
index c35b367f9bd..f38f984b717 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
@@ -1875,6 +1875,14 @@ public class FunctionCallExpr extends Expr {
                         && fnName.getFunction().equalsIgnoreCase("map")) {
                     ix = i % 2 == 0 ? 0 : 1;
                 }
+                // array_zip varargs special case array_zip(array1, array2, 
...)
+                // we only specialize array_zip with first array type, next 
type we same with custom type
+                if (i >= args.length && 
(fnName.getFunction().equalsIgnoreCase("array_zip"))) {
+                    if (argTypes[i].isNull()) {
+                        uncheckedCastChild(args[i - 1], i);
+                    }
+                    continue;
+                }
 
                 if (i == 0 && (fnName.getFunction().equalsIgnoreCase("char"))) 
{
                     continue;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/IsNullPredicate.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/IsNullPredicate.java
index c67ca1b0602..11a53ea5565 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IsNullPredicate.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IsNullPredicate.java
@@ -47,17 +47,14 @@ public class IsNullPredicate extends Predicate {
 
             
functionSet.addBuiltinBothScalaAndVectorized(ScalarFunction.createBuiltinOperator(IS_NOT_NULL,
                     null, Lists.newArrayList(t), Type.BOOLEAN, 
NullableMode.ALWAYS_NOT_NULLABLE));
+        }
+        // for array type
+        for (Type complexType : Lists.newArrayList(Type.ARRAY, Type.MAP, 
Type.GENERIC_STRUCT)) {
+            
functionSet.addBuiltinBothScalaAndVectorized(ScalarFunction.createBuiltinOperator(IS_NULL,
 null,
+                    Lists.newArrayList(complexType), Type.BOOLEAN, 
NullableMode.ALWAYS_NOT_NULLABLE));
 
-            // for array type
-            for (Type complexType : Lists.newArrayList(Type.ARRAY, Type.MAP, 
Type.GENERIC_STRUCT)) {
-                
functionSet.addBuiltinBothScalaAndVectorized(ScalarFunction.createBuiltinOperator(IS_NULL,
 null,
-                        Lists.newArrayList(complexType), Type.BOOLEAN, 
NullableMode.ALWAYS_NOT_NULLABLE));
-
-                
functionSet.addBuiltinBothScalaAndVectorized(ScalarFunction.createBuiltinOperator(IS_NOT_NULL,
-                        null, Lists.newArrayList(complexType), Type.BOOLEAN,
-                        NullableMode.ALWAYS_NOT_NULLABLE));
-            }
-
+            
functionSet.addBuiltinBothScalaAndVectorized(ScalarFunction.createBuiltinOperator(IS_NOT_NULL,
 null,
+                    Lists.newArrayList(complexType), Type.BOOLEAN, 
NullableMode.ALWAYS_NOT_NULLABLE));
         }
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/StructLiteral.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/StructLiteral.java
index effd5c7d61f..b459e312ece 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/StructLiteral.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/StructLiteral.java
@@ -23,6 +23,8 @@ import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.thrift.TExprNode;
 import org.apache.doris.thrift.TExprNodeType;
+import org.apache.doris.thrift.TTypeDesc;
+import org.apache.doris.thrift.TTypeNode;
 
 import com.google.common.base.Preconditions;
 import org.apache.commons.lang3.StringUtils;
@@ -106,6 +108,11 @@ public class StructLiteral extends LiteralExpr {
     @Override
     protected void toThrift(TExprNode msg) {
         msg.node_type = TExprNodeType.STRUCT_LITERAL;
+        ((StructType) type).getFields().forEach(v -> 
msg.setChildType(v.getType().getPrimitiveType().toThrift()));
+        TTypeDesc container = new TTypeDesc();
+        container.setTypes(new ArrayList<TTypeNode>());
+        type.toThrift(container);
+        msg.setType(container);
     }
 
     @Override
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java
index e5ae0d50284..c589cbbf505 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java
@@ -386,16 +386,31 @@ public class FunctionSet<T> {
                 throw new TypeException(templateFunction
                                 + " is not support for template since it's not 
a ScalarFunction");
             }
-            Type[] args = specializedFunction.getArgs();
+            ArrayList<Type> args = new ArrayList<>();
+            Collections.addAll(args, specializedFunction.getArgs());
             Map<String, Type> specializedTypeMap = Maps.newHashMap();
             boolean enableDecimal256 = SessionVariable.getEnableDecimal256();
-            for (int i = 0; i < args.length; i++) {
-                if (args[i].hasTemplateType()) {
+            int i = 0;
+            for (; i < args.size(); i++) {
+                if (args.get(i).hasTemplateType()) {
                     hasTemplateType = true;
-                    args[i] = 
args[i].specializeTemplateType(requestFunction.getArgs()[i], 
specializedTypeMap, false,
-                            enableDecimal256);
+                    // if args[i] is template type, and 
requestFunction.getArgs()[i] NULL_TYPE, we need call function
+                    // deduce to get the specific type
+                    Type deduceType = requestFunction.getArgs()[i];
+                    if (requestFunction.getArgs()[i].isNull()
+                            || (requestFunction.getArgs()[i] instanceof 
ArrayType
+                            && ((ArrayType) 
requestFunction.getArgs()[i]).getItemType().isNull())
+                            && 
FunctionTypeDeducers.DEDUCERS.containsKey(specializedFunction.functionName())) {
+                        deduceType = 
FunctionTypeDeducers.deduce(specializedFunction.functionName(), i, 
requestFunction.getArgs());
+                        args.set(i, 
args.get(i).specializeTemplateType(deduceType == null ? 
requestFunction.getArgs()[i]
+                                : deduceType, specializedTypeMap, false, 
enableDecimal256));
+                    } else {
+                        args.set(i, 
args.get(i).specializeTemplateType(requestFunction.getArgs()[i],
+                                specializedTypeMap, false, enableDecimal256));
+                    }
                 }
             }
+            specializedFunction.setArgs(args);
             if (specializedFunction.getReturnType().hasTemplateType()) {
                 hasTemplateType = true;
                 specializedFunction.setReturnType(
@@ -426,7 +441,7 @@ public class FunctionSet<T> {
                 newTypes[i] = inputType;
             }
         }
-        Type newRetType = 
FunctionTypeDeducers.deduce(inferenceFunction.functionName(), newTypes);
+        Type newRetType = 
FunctionTypeDeducers.deduce(inferenceFunction.functionName(), 0, newTypes);
         if (newRetType != null && inferenceFunction instanceof ScalarFunction) 
{
             ScalarFunction f = (ScalarFunction) inferenceFunction;
             return new ScalarFunction(f.getFunctionName(), 
Lists.newArrayList(newTypes), newRetType, f.hasVarArgs(),
@@ -448,7 +463,20 @@ public class FunctionSet<T> {
         final Type[] candicateArgTypes = candicate.getArgs();
         if (!(descArgTypes[0] instanceof ScalarType)
                 || !(candicateArgTypes[0] instanceof ScalarType)) {
-            if (candicateArgTypes[0] instanceof ArrayType || 
candicateArgTypes[0] instanceof MapType) {
+            if (candicateArgTypes[0] instanceof ArrayType) {
+                // match is exactly type. but for null type , with in 
array|map elem can not return true, because for
+                // be will make null_type to uint8
+                // so here meet null_type just make true as allowed, 
descArgTypes[0]).getItemType().isNull() is for
+                // empty literal like: []|{}
+                if (descArgTypes[0] instanceof ArrayType && ((ArrayType) 
descArgTypes[0]).getItemType().isNull()) {
+                    return true;
+                }
+                return descArgTypes[0].matchesType(candicateArgTypes[0]);
+            } else if (candicateArgTypes[0] instanceof MapType) {
+                if (descArgTypes[0] instanceof MapType && ((MapType) 
descArgTypes[0]).getKeyType().isNull()
+                        && ((MapType) 
descArgTypes[0]).getValueType().isNull()) {
+                    return true;
+                }
                 return descArgTypes[0].matchesType(candicateArgTypes[0]);
             }
             return false;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionTypeDeducers.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionTypeDeducers.java
index 80c78248ac2..34b1d1f768e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionTypeDeducers.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionTypeDeducers.java
@@ -23,26 +23,48 @@ import com.google.common.collect.Lists;
 import java.util.List;
 
 public class FunctionTypeDeducers {
-
     public interface TypeDeducer {
-        public Type deduce(Type[] args);
+        public Type deduce(int argIdx, Type[] args);
     }
 
     public static final ImmutableMap<String, TypeDeducer> DEDUCERS = 
ImmutableMap.<String, TypeDeducer>builder()
             .put("named_struct", new NamedStructDeducer())
             .put("struct_element", new StructElementDeducer())
+            .put("array_contains", new ArrayElemFuncDeducer())
+            .put("array_pushback", new ArrayElemFuncDeducer())
+            .put("element_at", new ArrayElemFuncDeducer())
             .build();
 
-    public static Type deduce(String fnName, Type[] args) {
+    public static Type deduce(String fnName, int argIdx, Type[] args) {
         if (DEDUCERS.containsKey(fnName)) {
-            return DEDUCERS.get(fnName).deduce(args);
+            return DEDUCERS.get(fnName).deduce(argIdx, args);
         }
         return null;
     }
 
+    public static class ArrayElemFuncDeducer implements TypeDeducer {
+        @Override
+        public Type deduce(int argIdx, Type[] args) {
+            if (args.length >= 2) {
+                if (argIdx == 0) {
+                    // first args should only to be array or null
+                    return args[0] instanceof ArrayType || args[0].isNull() ? 
new ArrayType(args[1]) : args[0];
+                } else if (args[0].isNull()) {
+                    // first arg is null, later element is not contains
+                    return args[argIdx];
+                } else if (Type.isImplicitlyCastable(args[argIdx], 
((ArrayType) args[0]).getItemType(), false, true)) {
+                    return args[argIdx];
+                } else {
+                    return null;
+                }
+            }
+            return null;
+        }
+    }
+
     public static class NamedStructDeducer implements TypeDeducer {
         @Override
-        public Type deduce(Type[] args) {
+        public Type deduce(int argIdx, Type[] args) {
             List<Type> evenArgs = Lists.newArrayList();
             for (int i = 0; i < args.length; i++) {
                 if ((i & 1) == 1) {
@@ -55,7 +77,7 @@ public class FunctionTypeDeducers {
 
     public static class StructElementDeducer implements TypeDeducer {
         @Override
-        public Type deduce(Type[] args) {
+        public Type deduce(int argIdx, Type[] args) {
             if (args[0] instanceof StructType) {
                 return Type.ANY_ELEMENT_TYPE;
             }
diff --git a/gensrc/script/doris_builtins_functions.py 
b/gensrc/script/doris_builtins_functions.py
index 91166a6dfb3..e756e238c09 100644
--- a/gensrc/script/doris_builtins_functions.py
+++ b/gensrc/script/doris_builtins_functions.py
@@ -165,24 +165,7 @@ visible_functions = {
         [['arrays_overlap'], 'BOOLEAN', ['ARRAY_VARCHAR', 'ARRAY_VARCHAR'], 
'ALWAYS_NULLABLE'],
         [['arrays_overlap'], 'BOOLEAN', ['ARRAY_STRING', 'ARRAY_STRING'], 
'ALWAYS_NULLABLE'],
 
-        [['array_contains'], 'BOOLEAN', ['ARRAY_BOOLEAN', 'BOOLEAN'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_TINYINT', 'TINYINT'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_SMALLINT', 'SMALLINT'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_INT', 'INT'], 'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_BIGINT', 'BIGINT'], 'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_LARGEINT', 'LARGEINT'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_DATETIME', 'DATETIME'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_DATE', 'DATE'], 'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_DATETIMEV2', 'DATETIMEV2'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_DATEV2', 'DATEV2'], 'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_FLOAT', 'FLOAT'], 'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_DOUBLE', 'DOUBLE'], 'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_DECIMALV2', 'DECIMALV2'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_DECIMAL32', 'DECIMAL32'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_DECIMAL64', 'DECIMAL64'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_DECIMAL128', 'DECIMAL128'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_VARCHAR', 'VARCHAR'], 
'CUSTOM'],
-        [['array_contains'], 'BOOLEAN', ['ARRAY_STRING', 'STRING'], 'CUSTOM'],
+        [['array_contains'], 'BOOLEAN', ['ARRAY<T>', 'T'], 'CUSTOM', ['T']],
 
         [['array_cum_sum'], 'ARRAY_BIGINT',     ['ARRAY_TINYINT'], ''],
         [['array_cum_sum'], 'ARRAY_BIGINT',     ['ARRAY_SMALLINT'], ''],
@@ -272,7 +255,7 @@ visible_functions = {
         [['array_position'], 'BIGINT', ['ARRAY_VARCHAR', 'VARCHAR'], 'CUSTOM'],
         [['array_position'], 'BIGINT', ['ARRAY_STRING', 'STRING'], 'CUSTOM'],
 
-        [['cardinality', 'size', 'array_size'], 'BIGINT', ['ARRAY'], ''],
+        [['cardinality', 'size', 'array_size'], 'BIGINT', ['ARRAY<T>'], '', 
['T']],
         [['array_distinct'], 'ARRAY_BOOLEAN',   ['ARRAY_BOOLEAN'], ''],
         [['array_distinct'], 'ARRAY_TINYINT',   ['ARRAY_TINYINT'], ''],
         [['array_distinct'], 'ARRAY_SMALLINT',  ['ARRAY_SMALLINT'], ''],
@@ -772,6 +755,7 @@ visible_functions = {
         [['array_pushfront'], 'ARRAY_VARCHAR',    ['ARRAY_VARCHAR', 
'VARCHAR'], 'ALWAYS_NULLABLE'],
         [['array_pushfront'], 'ARRAY_STRING',     ['ARRAY_STRING', 'STRING'], 
'ALWAYS_NULLABLE'],
 
+        [['array_pushback'], 'ARRAY<T>',    ['ARRAY<T>', 'T'], 
'ALWAYS_NULLABLE', ['T']],
         [['array_pushback'], 'ARRAY_BOOLEAN',    ['ARRAY_BOOLEAN', 'BOOLEAN'], 
'ALWAYS_NULLABLE'],
         [['array_pushback'], 'ARRAY_TINYINT',    ['ARRAY_TINYINT', 'TINYINT'], 
'ALWAYS_NULLABLE'],
         [['array_pushback'], 'ARRAY_SMALLINT',   ['ARRAY_SMALLINT', 
'SMALLINT'], 'ALWAYS_NULLABLE'],
@@ -833,7 +817,7 @@ visible_functions = {
         [['array_range'], 'ARRAY_INT', ['INT', 'INT'], 'ALWAYS_NULLABLE'],
         [['array_range'], 'ARRAY_INT', ['INT', 'INT', 'INT'], 
'ALWAYS_NULLABLE'],
 
-        [['array_zip'], 'ARRAY', ['ARRAY', '...'], ''],
+        [['array_zip'], 'ARRAY', ['ARRAY<T>', '...'], '', ['T']],
 
 
         # reverse function for string builtin
@@ -1469,6 +1453,9 @@ visible_functions = {
         [['nullif'], 'VARCHAR', ['VARCHAR', 'VARCHAR'], 'ALWAYS_NULLABLE'],
         [['nullif'], 'STRING', ['STRING', 'STRING'], 'ALWAYS_NULLABLE'],
 
+        [['is_null_pred'], "BOOLEAN", ['T', '...'], 'ALWAYS_NULLABLE', ['T']],
+        [['is_not_null_pred'], "BOOLEAN", ['T', '...'], 'ALWAYS_NULLABLE', 
['T']],
+
         [['ifnull', 'nvl'], 'BOOLEAN', ['BOOLEAN', 'BOOLEAN'], 'CUSTOM'],
         [['ifnull', 'nvl'], 'TINYINT', ['TINYINT', 'TINYINT'], 'CUSTOM'],
         [['ifnull', 'nvl'], 'SMALLINT', ['SMALLINT', 'SMALLINT'], 'CUSTOM'],
diff --git 
a/regression-test/data/datatype_p0/nested_types/query/test_nested_types_insert_into_with_literal.out
 
b/regression-test/data/datatype_p0/nested_types/query/test_nested_types_insert_into_with_literal.out
new file mode 100644
index 00000000000..74c8c2da0a8
--- /dev/null
+++ 
b/regression-test/data/datatype_p0/nested_types/query/test_nested_types_insert_into_with_literal.out
@@ -0,0 +1,28 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !sql --
+1      [[]]    [[]]    [[]]    [[]]    [[]]    [[]]    [[]]    [[]]    [[]]    
[[]]    [[]]    [[]]    [[]]    [[]]    [[]]    [[]]    [[]]
+
+-- !sql --
+1      [{}]    [{}]    [{}]    [{}]    [{}]    [{}]    [{}]    [{}]    [{}]    
[{}]    [{}]    [{}]    [{}]    [{}]    [{}]    [{}]    [{}]
+
+-- !sql --
+1      [{"col1": null, "col2": null, "col3": null, "col4": null, "col5": null, 
"col6": null, "col7": null, "col8": null, "col9": null, "col10": null, "col11": 
null, "col12": null, "col13": null, "col14": null, "col15": null, "col16": 
null, "col17": null}]        [{"col1": null, "col2": null, "col3": null, 
"col4": null, "col5": null, "col6": null, "col7": null, "col8": null, "col9": 
null, "col10": null, "col11": null, "col12": null, "col13": null, "col14": 
null, "col15": null, "col16": null, "col17": [...]
+
+-- !sql --
+1      {null:[]}       {null:[]}       {null:[]}       {null:[]}       
{null:[]}       {null:[]}       {null:[]}       {null:[]}       {null:[]}       
{null:[]}       {null:[]}       {null:[]}       {null:[]}       {null:[]}       
{null:[]}       {null:[]}       {null:[]}
+
+-- !sql --
+1      {null:{}}       {null:{}}       {null:{}}       {null:{}}       
{null:{}}       {null:{}}       {null:{}}       {null:{}}       {null:{}}       
{null:{}}       {null:{}}       {null:{}}       {null:{}}       {null:{}}       
{null:{}}       {null:{}}       {null:{}}
+
+-- !sql --
+1      {}      {}      {}      {}      {}      {}      {}      {}      {}      
{}      {}      {}      {}      {}      {}      {}      {}
+
+-- !sql --
+1      {"col_1": []}   {"col_2": []}   {"col_3": []}   {"col_4": []}   
{"col_5": []}   {"col_6": []}   {"col_7": []}   {"col_8": []}   {"col_9": []}   
{"col_10": []}  {"col_11": []}  {"col_12": []}  {"col_13": []}  {"col_14": []}  
{"col_15": []}  {"col_16": []}  {"col_17": []}
+
+-- !sql --
+1      {"col_1": {}}   {"col_2": {}}   {"col_3": {}}   {"col_4": {}}   
{"col_5": {}}   {"col_6": {}}   {"col_7": {}}   {"col_8": {}}   {"col_9": {}}   
{"col_10": {}}  {"col_11": {}}  {"col_12": {}}  {"col_13": {}}  {"col_14": {}}  
{"col_15": {}}  {"col_16": {}}  {"col_17": {}}
+
+-- !sql --
+1      {"col_1": {"col1": null, "col2": null, "col3": null, "col4": null, 
"col5": null, "col6": null, "col7": null, "col8": null, "col9": null, "col10": 
null, "col11": null, "col12": null, "col13": null, "col14": null, "col15": 
null, "col16": null, "col17": null}}       {"col_2": {"col1": null, "col2": 
null, "col3": null, "col4": null, "col5": null, "col6": null, "col7": null, 
"col8": null, "col9": null, "col10": null, "col11": null, "col12": null, 
"col13": null, "col14": null, "col15": null, "col1 [...]
+
diff --git 
a/regression-test/suites/datatype_p0/nested_types/query/test_nested_types_insert_into_with_literal.groovy
 
b/regression-test/suites/datatype_p0/nested_types/query/test_nested_types_insert_into_with_literal.groovy
new file mode 100644
index 00000000000..da3262858ae
--- /dev/null
+++ 
b/regression-test/suites/datatype_p0/nested_types/query/test_nested_types_insert_into_with_literal.groovy
@@ -0,0 +1,73 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+
+import com.google.common.collect.Lists
+import org.apache.commons.lang3.StringUtils
+import org.codehaus.groovy.runtime.IOGroovyMethods
+
+suite("test_nested_types_insert_into_with_literal", "p0") {
+    sql 'use regression_test_datatype_p0_nested_types'
+    // old planner does not support cast empty
+    sql 'set enable_nereids_planner=true'
+    sql 'set enable_fallback_to_original_planner=false'
+    sql """ADMIN SET FRONTEND CONFIG ('disable_nested_complex_type' = 
'false')"""
+
+    def table_names = [
+            "two_level_array_array_a",
+            "two_level_array_map_a",
+            "two_level_array_struct_a",
+
+            "two_level_map_array_a",
+            "two_level_map_map_a",
+            "two_level_map_struct_a",
+
+            "two_level_struct_array_a",
+            "two_level_struct_map_a",
+            "two_level_struct_struct_a"
+    ]
+
+    // notice : we do not suggest to use this literal {} to present empty 
struct, please use struct() instead
+    def null_literals = ["[[]]", "[{}]", "array(struct(null, null, null, null, 
null, null, null, null, null, null, null, null, null, null, null, null, null))",
+                        "{null:[]}", "{null:{}}", "{}",
+                        "struct([])", "struct({})", "struct(struct(null, null, 
null, null, null, null, null, null, null, null, null, null, null, null, null, 
null, null))"]
+
+    def colNameArr = ["c_bool", "c_tinyint", "c_smallint", "c_int", 
"c_bigint", "c_largeint", "c_float",
+                      "c_double", "c_decimal", "c_decimalv3", "c_date", 
"c_datetime", "c_datev2", "c_datetimev2",
+                      "c_char", "c_varchar", "c_string"]
+
+    // create tables
+    // (0,0) (0,1) (0,2) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2)
+    for (int i = 0; i < 3; ++i) {
+        for (int j = 0; j < 3; ++j) {
+            sql """ DROP TABLE IF EXISTS ${table_names[i*3+j]} """
+            String result = create_table_with_nested_type(2, [i, j], 
table_names[i*3+j])
+            sql result
+        }
+    }
+
+    // insert into empty literal
+    for (int i = 0; i < 9; ++i) {
+        String insertSql = "INSERT INTO ${table_names[i]} VALUES(1, "
+        for (int j = 0; j < colNameArr.size(); ++j) {
+            insertSql += "${null_literals[i]},"
+        }
+        insertSql = insertSql.substring(0, insertSql.length() - 1) + ")"
+        sql insertSql
+        qt_sql """ select * from ${table_names[i]} order by k1 """
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to