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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]