diff --git a/be/src/vec/functions/array/function_array_element.h b/be/src/vec/functions/array/function_array_element.h index 094802f886..9b84a274a9 100644 --- a/be/src/vec/functions/array/function_array_element.h +++ b/be/src/vec/functions/array/function_array_element.h @@ -43,20 +43,24 @@ public: bool is_variadic() const override { return false; } + bool use_default_implementation_for_nulls() const override { return false; } + size_t get_number_of_arguments() const override { return 2; } DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { - DCHECK(is_array(arguments[0]) || is_map(arguments[0])) + DataTypePtr arg_0 = remove_nullable(arguments[0]); + DCHECK(is_array(arg_0) || is_map(arg_0)) << "first argument for function: " << name - << " should be DataTypeArray or DataTypeMap"; - if (is_array(arguments[0])) { - DCHECK(is_integer(arguments[1])) << "second argument for function: " << name - << " should be Integer for array element"; + << " should be DataTypeArray or DataTypeMap, but it is " << arg_0->get_name(); + if (is_array(arg_0)) { + DCHECK(is_integer(remove_nullable(arguments[1]))) + << "second argument for function: " << name + << " should be Integer for array element"; return make_nullable( - check_and_get_data_type(arguments[0].get())->get_nested_type()); - } else if (is_map(arguments[0])) { + check_and_get_data_type(arg_0.get())->get_nested_type()); + } else if (is_map(arg_0)) { return make_nullable( - check_and_get_data_type(arguments[0].get())->get_value_type()); + check_and_get_data_type(arg_0.get())->get_value_type()); } else { LOG(ERROR) << "element_at only support array and map so far."; return nullptr; @@ -83,7 +87,7 @@ public: if (args[0].column->is_column_map()) { res_column = _execute_map(args, input_rows_count, src_null_map, dst_null_map); } else { - res_column = _execute_non_nullable(args, input_rows_count, src_null_map, dst_null_map); + res_column = _execute_nullable(args, input_rows_count, src_null_map, dst_null_map); } if (!res_column) { return Status::RuntimeError("unsupported types for function {}({}, {})", get_name(), @@ -98,15 +102,9 @@ public: private: //=========================== map element===========================// ColumnPtr _get_mapped_idx(const ColumnArray& column, const ColumnWithTypeAndName& argument) { - auto right_column = argument.column->convert_to_full_column_if_const(); + auto right_column = make_nullable(argument.column->convert_to_full_column_if_const()); const ColumnArray::Offsets64& offsets = column.get_offsets(); - ColumnPtr nested_ptr = nullptr; - if (is_column_nullable(column.get_data())) { - nested_ptr = reinterpret_cast(column.get_data()) - .get_nested_column_ptr(); - } else { - nested_ptr = column.get_data_ptr(); - } + ColumnPtr nested_ptr = make_nullable(column.get_data_ptr()); size_t rows = offsets.size(); // prepare return data auto matched_indices = ColumnVector::create(); @@ -245,7 +243,8 @@ private: if (rows <= 0) { return nullptr; } - + if (key_arr->is_nullable()) { + } ColumnPtr matched_indices = _get_mapped_idx(*key_arr, arguments[1]); if (!matched_indices) { return nullptr; @@ -254,12 +253,11 @@ private: ColumnWithTypeAndName indices(matched_indices, indices_type, "indices"); ColumnWithTypeAndName data(val_arr, val_type, "value"); ColumnsWithTypeAndName args = {data, indices}; - return _execute_non_nullable(args, input_rows_count, src_null_map, dst_null_map); + return _execute_nullable(args, input_rows_count, src_null_map, dst_null_map); } - ColumnPtr _execute_non_nullable(const ColumnsWithTypeAndName& arguments, - size_t input_rows_count, const UInt8* src_null_map, - UInt8* dst_null_map) { + ColumnPtr _execute_nullable(const ColumnsWithTypeAndName& arguments, size_t input_rows_count, + const UInt8* src_null_map, UInt8* dst_null_map) { // check array nested column type and get data auto left_column = arguments[0].column->convert_to_full_column_if_const(); const auto& array_column = reinterpret_cast(*left_column); @@ -277,67 +275,60 @@ private: } ColumnPtr res = nullptr; + // because we impl use_default_implementation_for_nulls + // we should handle array index column by-self, and array index should not be nullable. + auto idx_col = remove_nullable(arguments[1].column); if (nested_column->is_date_type()) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (nested_column->is_datetime_type()) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + *idx_col, nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_number(offsets, *nested_column, src_null_map, - *arguments[1].column, nested_null_map, - dst_null_map); + res = _execute_number(offsets, *nested_column, src_null_map, *idx_col, + nested_null_map, dst_null_map); } else if (check_column(*nested_column)) { - res = _execute_string(offsets, *nested_column, src_null_map, *arguments[1].column, - nested_null_map, dst_null_map); + res = _execute_string(offsets, *nested_column, src_null_map, *idx_col, nested_null_map, + dst_null_map); } return res; diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/StructType.java b/fe/fe-common/src/main/java/org/apache/doris/catalog/StructType.java index fa8624a955..a037b77de9 100644 --- a/fe/fe-common/src/main/java/org/apache/doris/catalog/StructType.java +++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/StructType.java @@ -175,11 +175,14 @@ public class StructType extends Type { } StructType other = (StructType) t; - if (fields.size() != other.getFields().size()) { - // Temp to make NullPredict from fe send to be - return other.getFields().size() == 1 && Objects.equals(other.getFields().get(0).name, "null_pred"); + // Temp to make NullPredict from fe send to be + if (other.getFields().size() == 1 && Objects.equals(other.getFields().get(0).name, + Type.GENERIC_STRUCT.getFields().get(0).name)) { + return true; + } + if (fields.size() != other.getFields().size()) { + return false; } - for (int i = 0; i < fields.size(); i++) { if (!fields.get(i).matchesField(((StructType) t).getFields().get(i))) { return false; 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 8c1f1200b4..5e794b27e0 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 @@ -107,6 +107,8 @@ public abstract class Type { public static final ScalarType ALL = new ScalarType(PrimitiveType.ALL); public static final MapType MAP = new MapType(); public static final ArrayType ARRAY = ArrayType.create(); + public static final StructType GENERIC_STRUCT = new StructType(Lists.newArrayList( + new StructField("generic_struct", new ScalarType(PrimitiveType.NULL_TYPE)))); public static final StructType STRUCT = new StructType(); public static final VariantType VARIANT = new VariantType(); 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 976722fc21..1edca054dd 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 @@ -699,7 +699,7 @@ public class FunctionCallExpr extends Expr { } for (Expr child : children) { - if (child.type.isOnlyMetricType()) { + if (child.type.isOnlyMetricType() && !child.type.isComplexType()) { throw new AnalysisException(Type.OnlyMetricTypeErrorMsg); } } 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 64367c56ce..545bfc5185 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 @@ -24,8 +24,6 @@ import org.apache.doris.catalog.Function; import org.apache.doris.catalog.Function.NullableMode; import org.apache.doris.catalog.FunctionSet; import org.apache.doris.catalog.ScalarFunction; -import org.apache.doris.catalog.StructField; -import org.apache.doris.catalog.StructType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.thrift.TExprNode; @@ -62,7 +60,7 @@ public class IsNullPredicate extends Predicate { isNotNullSymbol, Lists.newArrayList(t), Type.BOOLEAN, NullableMode.ALWAYS_NOT_NULLABLE)); // for array type - for (Type complexType : Lists.newArrayList(Type.ARRAY, Type.MAP)) { + for (Type complexType : Lists.newArrayList(Type.ARRAY, Type.MAP, Type.GENERIC_STRUCT)) { functionSet.addBuiltinBothScalaAndVectorized(ScalarFunction.createBuiltinOperator(IS_NULL, isNullSymbol, Lists.newArrayList(complexType), Type.BOOLEAN, NullableMode.ALWAYS_NOT_NULLABLE)); @@ -71,12 +69,6 @@ public class IsNullPredicate extends Predicate { NullableMode.ALWAYS_NOT_NULLABLE)); } - Type nullStruct = new StructType(Lists.newArrayList(new StructField("null_pred", Type.NULL))); - functionSet.addBuiltinBothScalaAndVectorized(ScalarFunction.createBuiltinOperator(IS_NULL, isNullSymbol, - Lists.newArrayList(nullStruct), Type.BOOLEAN, NullableMode.ALWAYS_NOT_NULLABLE)); - - functionSet.addBuiltinBothScalaAndVectorized(ScalarFunction.createBuiltinOperator(IS_NOT_NULL, - isNotNullSymbol, Lists.newArrayList(nullStruct), Type.BOOLEAN, NullableMode.ALWAYS_NOT_NULLABLE)); } } 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 ffb11b6015..6475f3e3ec 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 @@ -1564,6 +1564,27 @@ public class FunctionSet { prefix + "17count_star_removeEPN9doris_udf15FunctionContextEPNS1_9BigIntValE", null, false, true, true, true)); + // count(array/map/struct) + for (Type complexType : Lists.newArrayList(Type.ARRAY, Type.MAP, Type.GENERIC_STRUCT)) { + addBuiltin(AggregateFunction.createBuiltin(FunctionSet.COUNT, + Lists.newArrayList(complexType), Type.BIGINT, Type.BIGINT, + prefix + "18init_zero_not_nullIN9doris_udf9BigIntValEEEvPNS2_15FunctionContextEPT_", + prefix + "12count_updateEPN9doris_udf15FunctionContextERKNS1_6AnyValEPNS1_9BigIntValE", + prefix + "11count_mergeEPN9doris_udf15FunctionContextERKNS1_9BigIntValEPS4_", + null, null, + prefix + "12count_removeEPN9doris_udf15FunctionContextERKNS1_6AnyValEPNS1_9BigIntValE", + null, false, true, true, true)); + + addBuiltin(AggregateFunction.createBuiltin(FunctionSet.COUNT, + Lists.newArrayList(complexType), Type.BIGINT, Type.BIGINT, + prefix + "18init_zero_not_nullIN9doris_udf9BigIntValEEEvPNS2_15FunctionContextEPT_", + prefix + "12count_updateEPN9doris_udf15FunctionContextERKNS1_6AnyValEPNS1_9BigIntValE", + prefix + "11count_mergeEPN9doris_udf15FunctionContextERKNS1_9BigIntValEPS4_", + null, null, + prefix + "12count_removeEPN9doris_udf15FunctionContextERKNS1_6AnyValEPNS1_9BigIntValE", + null, false, true, true, true)); + } + // windowFunnel addBuiltin(AggregateFunction.createBuiltin(FunctionSet.WINDOW_FUNNEL, Lists.newArrayList(Type.BIGINT, Type.STRING, Type.DATETIME, Type.BOOLEAN), diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/IsNullPredicateWithComplexTypeTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/IsNullPredicateWithComplexTypeTest.java index c40de1e643..6897b1ec82 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/IsNullPredicateWithComplexTypeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/IsNullPredicateWithComplexTypeTest.java @@ -20,6 +20,7 @@ package org.apache.doris.analysis; import org.apache.doris.common.Config; import org.apache.doris.utframe.TestWithFeService; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class IsNullPredicateWithComplexTypeTest extends TestWithFeService { @@ -53,8 +54,19 @@ public class IsNullPredicateWithComplexTypeTest extends TestWithFeService { String testStructIsNUll = "select * from test.complex where s is null"; String testMapIsNUll = "select * from test.complex where m is null"; String testArrayIsNUll = "select * from test.complex where a is null"; - assertSQLPlanOrErrorMsgContains(testStructIsNUll, ""); - assertSQLPlanOrErrorMsgContains(testMapIsNUll, ""); - assertSQLPlanOrErrorMsgContains(testArrayIsNUll, ""); + Assertions.assertNotNull(getSQLPlanner(testStructIsNUll)); + Assertions.assertNotNull(getSQLPlanner(testMapIsNUll)); + Assertions.assertNotNull(getSQLPlanner(testArrayIsNUll)); } + + @Test + public void testCount() throws Exception { + String testStructIsNUll = "select count(s) from test.complex"; + String testMapIsNUll = "select count(m) from test.complex"; + String testArrayIsNUll = "select count(a) from test.complex"; + Assertions.assertNotNull(getSQLPlanner(testStructIsNUll)); + Assertions.assertNotNull(getSQLPlanner(testMapIsNUll)); + Assertions.assertNotNull(getSQLPlanner(testArrayIsNUll)); + } + } diff --git a/regression-test/data/export/test_map_export.out b/regression-test/data/export/test_map_export.out index bf3df19431..9b46ae9dfb 100644 --- a/regression-test/data/export/test_map_export.out +++ b/regression-test/data/export/test_map_export.out @@ -5,3 +5,7 @@ 3 {" 33,amory ":2, " bet ":20, " cler ":26} 4 {"k3":23, null:20, "k4":null} 5 {null:null} + +-- !select_count -- +4 + diff --git a/regression-test/data/load/insert/test_array_insert_into_select.out b/regression-test/data/load/insert/test_array_insert_into_select.out index 2dcf990314..594d8881e3 100644 --- a/regression-test/data/load/insert/test_array_insert_into_select.out +++ b/regression-test/data/load/insert/test_array_insert_into_select.out @@ -5,9 +5,15 @@ 2 [{"a":"1","b":"2"}] 3 [] +-- !select_string -- +4 + -- !select_array -- 0 \N 1 ['{"a":"1","b":"2","c":"3",}', '{"a":"1","b":"2"}'] 2 \N 3 [] +-- !select_array -- +2 + diff --git a/regression-test/data/load/insert/test_array_string_insert.out b/regression-test/data/load/insert/test_array_string_insert.out index bec55ae658..4d5875f533 100644 --- a/regression-test/data/load/insert/test_array_string_insert.out +++ b/regression-test/data/load/insert/test_array_string_insert.out @@ -5,3 +5,6 @@ 6 \N ['4'] [[123], [222]] 7 \N ['4'] [[12345, NULL], [222]] +-- !select_count -- +1 4 2 + diff --git a/regression-test/data/load/insert/test_insert_nested_array.out b/regression-test/data/load/insert/test_insert_nested_array.out index e40e3d26c8..0a59a905cf 100644 --- a/regression-test/data/load/insert/test_insert_nested_array.out +++ b/regression-test/data/load/insert/test_insert_nested_array.out @@ -13,6 +13,9 @@ 6 [[1, 2, NULL], NULL, [4, NULL, 6], NULL, [NULL, 8, 9]] 6 [[1, 2, NULL], NULL, [4, NULL, 6], NULL, [NULL, 8, 9]] +-- !select -- +12 + -- !select -- 1 [] 1 [] @@ -27,6 +30,9 @@ 6 [[[NULL]], [[1], [2, 3]], [[4, 5, 6], NULL, NULL]] 6 [[[NULL]], [[1], [2, 3]], [[4, 5, 6], NULL, NULL]] +-- !select -- +12 + -- !select -- 1 [] 1 [] 1 [] 1 [] diff --git a/regression-test/data/load/insert/test_map_dml.out b/regression-test/data/load/insert/test_map_dml.out index 4ce856d254..fd032152a2 100644 --- a/regression-test/data/load/insert/test_map_dml.out +++ b/regression-test/data/load/insert/test_map_dml.out @@ -3,5 +3,12 @@ 1 {" amory ":6, "happy":38} 6 {"amory":6, "is":38, "cl":0} +-- !select_count -- +2 + -- !select -- 100 {1:"1", 2:"2", 3:"3"} {32767:"32767", 32768:"32768", 32769:"32769"} [65534, 65535, 65536] {2022-07-13:1} {2022-07-13 12:30:00:"2022-07-13 12:30:00"} {0.33:33, 0.67:67} + +-- !select -- +1 1 1 1 1 1 + diff --git a/regression-test/data/load_p0/broker_load/test_array_load.out b/regression-test/data/load_p0/broker_load/test_array_load.out index aac06e46ed..89b7f6c012 100644 --- a/regression-test/data/load_p0/broker_load/test_array_load.out +++ b/regression-test/data/load_p0/broker_load/test_array_load.out @@ -7,6 +7,9 @@ 5 [NULL, NULL] [32767, 32768, NULL] [65534, NULL, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01] [1991-01-01 00:00:00] [0.33, 0.67] [3.1415926, 0.878787878] [1, 1.2, 1.3] 100 [1, 2, 3] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c'] ['hello', 'world'] [2022-07-13] [2022-07-13 12:30:00] [0.33, 0.67] [3.1415926, 0.878787878] [4, 5.5, 6.67] +-- !select_count -- +6 6 + -- !select -- 1 [1, 2, 3, 4, 5] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01] [1991-01-01 00:00:00] [0.333333, 0.676767] [3.1415926, 0.878787878] [1, 1.2, 1.3] 2 [6, 7, 8, 9, 10] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01] [1991-01-01 00:00:00] [0.333333, 0.676767] [3.1415926, 0.878787878] [1, 1.2, 1.3] @@ -16,6 +19,9 @@ 6 [NULL, NULL, 0, 0] [32767, 32768, NULL] [65534, NULL, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello,,,', 'world][]'] [1991-01-01] [1991-01-01 00:00:00] [0.33, 0.67] [3.1415926, 0.878787878] [0, 0] 100 [1, 2, 3] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c'] ['hello', 'world'] [2022-07-13] [2022-07-13 12:30:00] [0.33, 0.67] [3.1415926, 0.878787878] [4, 5.5, 6.67] +-- !select_count -- +7 7 + -- !select -- 1 [1, 2, 3, 4, 5] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01, 1992-02-02, 1993-03-03] [1991-01-01 00:00:00] [0.33, 0.67] [3.1415926, 0.878787878] [1, 1.2, 1.3] 2 [1, 2, 3, 4, 5] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01, 1992-02-02, 1993-03-03] \N \N \N [1, NULL, 1.3] @@ -24,6 +30,9 @@ 5 \N \N \N \N \N \N \N \N \N \N 100 [1, 2, 3] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c'] ['hello', 'world'] [2022-07-13] [2022-07-13 12:30:00] [0.33, 0.67] [3.1415926, 0.878787878] [4, 5.5, 6.67] +-- !select_count -- +6 3 + -- !select -- 1 [1, 2, 3, 4, 5] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01] [1991-01-01 00:00:00] [0.33, 0.67] [3.1415926, 0.878787878] [1, 1.2, 1.3] 2 [6, 7, 8, 9, 10] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01] [1991-01-01 00:00:00] [0.33, 0.67] [3.1415926, 0.878787878] [1, 1.2, 1.3] @@ -32,6 +41,9 @@ 5 [NULL, NULL] [32767, 32768, NULL] [65534, NULL, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01] [1991-01-01 00:00:00] [0.33, 0.67] [3.1415926, 0.878787878] [1, 1.2, 1.3] 100 [1, 2, 3] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c'] ['hello', 'world'] [2022-07-13] [2022-07-13 12:30:00] [0.33, 0.67] [3.1415926, 0.878787878] [4, 5.5, 6.67] +-- !select_count -- +6 6 + -- !select -- 1 [1, 2, 3, 4, 5] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01] [1991-01-01 00:00:00] [0.333333, 0.676767] [3.1415926, 0.878787878] [1, 1.2, 1.3] 2 [6, 7, 8, 9, 10] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01] [1991-01-01 00:00:00] [0.333333, 0.676767] [3.1415926, 0.878787878] [1, 1.2, 1.3] @@ -41,6 +53,9 @@ 6 [NULL, NULL, 0, 0] [32767, 32768, NULL] [65534, NULL, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello,,,', 'world][]'] [1991-01-01] [1991-01-01 00:00:00] [0.33, 0.67] [3.1415926, 0.878787878] [0, 0] 100 [1, 2, 3] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c'] ['hello', 'world'] [2022-07-13] [2022-07-13 12:30:00] [0.33, 0.67] [3.1415926, 0.878787878] [4, 5.5, 6.67] +-- !select_count -- +7 7 + -- !select -- 1 [1, 2, 3, 4, 5] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01, 1992-02-02, 1993-03-03] [1991-01-01 00:00:00] [0.33, 0.67] [3.1415926, 0.878787878] [1, 1.2, 1.3] 2 [1, 2, 3, 4, 5] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c', 'd', 'e'] ['hello', 'world'] [1991-01-01, 1992-02-02, 1993-03-03] \N \N \N [1, NULL, 1.3] @@ -49,3 +64,6 @@ 5 \N \N \N \N \N \N \N \N \N \N 100 [1, 2, 3] [32767, 32768, 32769] [65534, 65535, 65536] ['a', 'b', 'c'] ['hello', 'world'] [2022-07-13] [2022-07-13 12:30:00] [0.33, 0.67] [3.1415926, 0.878787878] [4, 5.5, 6.67] +-- !select_count -- +6 3 + diff --git a/regression-test/data/load_p0/stream_load/test_map_load_and_compaction.out b/regression-test/data/load_p0/stream_load/test_map_load_and_compaction.out index df2b8a05db..b4348cb553 100644 --- a/regression-test/data/load_p0/stream_load/test_map_load_and_compaction.out +++ b/regression-test/data/load_p0/stream_load/test_map_load_and_compaction.out @@ -2,3 +2,6 @@ -- !select -- 20317 +-- !select -- +20317 + diff --git a/regression-test/data/load_p0/stream_load/test_map_load_and_function.out b/regression-test/data/load_p0/stream_load/test_map_load_and_function.out index 70f7d3c7d1..c02d5efe7a 100644 --- a/regression-test/data/load_p0/stream_load/test_map_load_and_function.out +++ b/regression-test/data/load_p0/stream_load/test_map_load_and_function.out @@ -305,7 +305,7 @@ k22 9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N 10 {} \N 11 \N \N -12 {"k3":23, null:20, "k4":null} 20 +12 {"k3":23, null:20, "k4":null} \N 13 {"null":1} \N 15 {"":2, "k2":0} 2 16 {null:null} \N @@ -324,7 +324,7 @@ k22 9 {" 1,amy ":2, " k2 ":90, " k7 ":33} \N 10 {} \N 11 \N \N -12 {"k3":23, null:20, "k4":null} \N +12 {"k3":23, null:20, "k4":null} 20 13 {"null":1} \N 15 {"":2, "k2":0} \N 16 {null:null} \N @@ -1047,3 +1047,6 @@ false -- !select_m5 -- 1 100 200 \N +-- !select_count -- +1 1 1 1 1 + diff --git a/regression-test/data/query_p0/show/test_map_show_create.out b/regression-test/data/query_p0/show/test_map_show_create.out index 78b706ca7d..774a1d9020 100644 --- a/regression-test/data/query_p0/show/test_map_show_create.out +++ b/regression-test/data/query_p0/show/test_map_show_create.out @@ -2,3 +2,6 @@ -- !select -- test_map_show_create CREATE TABLE `test_map_show_create` (\n `k1` int(11) NULL,\n `k2` MAP NULL,\n `k3` MAP NULL,\n `k4` MAP NULL,\n `k5` MAP NULL,\n `k6` MAP NULL\n) ENGINE=OLAP\nDUPLICATE KEY(`k1`)\nCOMMENT 'OLAP'\nDISTRIBUTED BY HASH(`k1`) BUCKETS 1\nPROPERTIES (\n"replication_allocation" = "tag.location.default: 1",\n"in_memory" = "false",\n"storage_format" = "V2",\n"light_schema_change" = "true",\n"disable_auto_compaction" = "false"\n); +-- !select -- +1 1 1 1 1 + diff --git a/regression-test/data/query_p0/show/test_struct_show_create.out b/regression-test/data/query_p0/show/test_struct_show_create.out index e06f2ba5dd..1dd95c010c 100644 --- a/regression-test/data/query_p0/show/test_struct_show_create.out +++ b/regression-test/data/query_p0/show/test_struct_show_create.out @@ -1,4 +1,7 @@ -- This file is automatically generated. You should know what you did if you want to edit this +-- !select_count -- +1 1 1 1 1 1 1 1 1 1 + -- !select -- test_struct_show_create CREATE TABLE `test_struct_show_create` (\n `k1` int(11) NULL,\n `k2` STRUCT NOT NULL,\n `k3` STRUCT NOT NULL,\n `k4` STRUCT NOT NULL,\n `k5` STRUCT NOT NULL,\n `k6` STRUCT NULL,\n `k7` STRUCT NOT NULL,\n `k8` STRUCT NOT NULL,\n `k9` STRUCT NOT NULL,\n `k10` STRUCT NOT NULL,\n `k11` STRUCT NULL\n) ENGINE=OLAP\nDUPLICATE KEY(`k1`)\nCOMMENT 'OLAP'\nDISTRIBUTED BY HASH(`k1`) BUCKETS 1\nPROPERTIES (\n"replication_allocation" = "tag.location.default: 1",\n"in_memory" = "false",\n"storage_format" = "V2",\n"light_schema_change" = "true",\n"disable_auto_compaction" = "false"\n); diff --git a/regression-test/suites/export/test_map_export.groovy b/regression-test/suites/export/test_map_export.groovy index a1fa469f43..362e512491 100644 --- a/regression-test/suites/export/test_map_export.groovy +++ b/regression-test/suites/export/test_map_export.groovy @@ -75,6 +75,7 @@ suite("test_map_export", "export") { // check result qt_select """ SELECT * FROM ${testTable} ORDER BY id; """ + qt_select_count """SELECT COUNT(m) FROM ${testTable}""" def outFilePath = """${context.file.parent}/test_map_export""" logger.info("test_map_export the outFilePath=" + outFilePath) diff --git a/regression-test/suites/load/insert/test_array_insert_into_select.groovy b/regression-test/suites/load/insert/test_array_insert_into_select.groovy index f171ae3220..554f188af0 100644 --- a/regression-test/suites/load/insert/test_array_insert_into_select.groovy +++ b/regression-test/suites/load/insert/test_array_insert_into_select.groovy @@ -41,6 +41,7 @@ suite("test_array_insert_into_select", "load") { // check data in tstring qt_select_string "SELECT * FROM tstring ORDER BY id" + qt_select_string "SELECT count(data) FROM tstring" // create table with array @@ -62,4 +63,5 @@ suite("test_array_insert_into_select", "load") { // check data in tarray qt_select_array "SELECT * FROM tarray ORDER BY id" + qt_select_array "SELECT count(data) FROM tarray" } diff --git a/regression-test/suites/load/insert/test_array_string_insert.groovy b/regression-test/suites/load/insert/test_array_string_insert.groovy index c98f1ac80a..23acc72242 100644 --- a/regression-test/suites/load/insert/test_array_string_insert.groovy +++ b/regression-test/suites/load/insert/test_array_string_insert.groovy @@ -73,6 +73,7 @@ suite("test_array_string_insert", "load") { // select the table and check whether the data is correct qt_select "select * from ${testTable} order by k1" + qt_select_count "select count(k2), count(k3), count(k4) from ${testTable}" } test_insert_array_string(); diff --git a/regression-test/suites/load/insert/test_insert_nested_array.groovy b/regression-test/suites/load/insert/test_insert_nested_array.groovy index e3291d7831..2291b6c652 100644 --- a/regression-test/suites/load/insert/test_insert_nested_array.groovy +++ b/regression-test/suites/load/insert/test_insert_nested_array.groovy @@ -44,6 +44,7 @@ suite("test_insert_nested_array", "load") { (6, [[1, 2, null], null, [4, null, 6], null, [null, 8, 9]]) """ qt_select "select * from ${tableName} order by `key`" + qt_select "select count(value) from ${tableName}" } def test_nested_array_3_depths = { @@ -74,6 +75,7 @@ suite("test_insert_nested_array", "load") { (6, [[[null]], [[1], [2, 3]], [[4, 5, 6], null, null]]) """ qt_select "select * from ${tableName} order by `key`" + qt_select "select count(value) from ${tableName}" qt_select "select * from ${tableName} as t1 right join ${tableName} as t2 on t1.`key` = t2.`key` order by t1.`key`" } diff --git a/regression-test/suites/load/insert/test_map_dml.groovy b/regression-test/suites/load/insert/test_map_dml.groovy index 438bd0b496..5f626fe833 100644 --- a/regression-test/suites/load/insert/test_map_dml.groovy +++ b/regression-test/suites/load/insert/test_map_dml.groovy @@ -95,6 +95,7 @@ suite("test_map_dml", "load") { // select the table and check whether the data is correct qt_select "SELECT * FROM ${testTable} ORDER BY k1" + qt_select_count "SELECT COUNT(k1) FROM ${testTable}" } finally { try_sql("DROP TABLE IF EXISTS ${testTable}") @@ -107,6 +108,7 @@ suite("test_map_dml", "load") { create_test_table01.call(testTable) // select the table and check whether the data is correct qt_select "SELECT * FROM ${testTable01} ORDER BY k1" + qt_select "SELECT COUNT(k2), COUNT(k3), COUNT(k4),COUNT(k5),COUNT(k6), COUNT(k7) FROM ${testTable01}" } finally { try_sql("DROP TABLE IF EXISTS ${testTable01}") diff --git a/regression-test/suites/load_p0/broker_load/test_array_load.groovy b/regression-test/suites/load_p0/broker_load/test_array_load.groovy index 9634b29a4e..2697d08db2 100644 --- a/regression-test/suites/load_p0/broker_load/test_array_load.groovy +++ b/regression-test/suites/load_p0/broker_load/test_array_load.groovy @@ -191,7 +191,8 @@ suite("test_array_load", "load_p0") { def check_data_correct = {table_name -> sql "sync" // select the table and check whether the data is correct - qt_select "select * from ${table_name} order by k1" + qt_select "select * from ${table_name} order by k1" + qt_select_count "select count(3), count(k6) from ${table_name}" } try { diff --git a/regression-test/suites/load_p0/stream_load/test_map_load_and_compaction.groovy b/regression-test/suites/load_p0/stream_load/test_map_load_and_compaction.groovy index ae4778d511..c8b0a98570 100644 --- a/regression-test/suites/load_p0/stream_load/test_map_load_and_compaction.groovy +++ b/regression-test/suites/load_p0/stream_load/test_map_load_and_compaction.groovy @@ -97,6 +97,7 @@ suite("test_map_load_and_compaction", "p0") { // check result qt_select "SELECT count(*) FROM ${testTable};" + qt_select "SELECT count(actor) FROM ${testTable};" // check here 2 rowsets //TabletId,ReplicaId,BackendId,SchemaHash,Version,LstSuccessVersion,LstFailedVersion,LstFailedTime,LocalDataSize,RemoteDataSize,RowCount,State,LstConsistencyCheckTime,CheckVersion,VersionCount,PathHash,MetaUrl,CompactionStatus diff --git a/regression-test/suites/load_p0/stream_load/test_map_load_and_function.groovy b/regression-test/suites/load_p0/stream_load/test_map_load_and_function.groovy index 362be32602..5d0a187d09 100644 --- a/regression-test/suites/load_p0/stream_load/test_map_load_and_function.groovy +++ b/regression-test/suites/load_p0/stream_load/test_map_load_and_function.groovy @@ -183,4 +183,5 @@ suite("test_map_load_and_function", "p0") { qt_select_m3 "SELECT id, m3['k1'], m3['k2'], m3['nokey'] FROM ${testTable} ORDER BY id" qt_select_m4 "SELECT id, m4[100], m4[200], m4[300] FROM ${testTable} ORDER BY id" qt_select_m5 "SELECT id, m5[10000], m5[20000], m5[30000] FROM ${testTable} ORDER BY id" + qt_select_count "SELECT COUNT(m1), COUNT(m2), COUNT(m3), COUNT(m4), COUNT(m5) FROM ${testTable}" } diff --git a/regression-test/suites/query_p0/show/test_map_show_create.groovy b/regression-test/suites/query_p0/show/test_map_show_create.groovy index 463cb2babc..01776b7c80 100644 --- a/regression-test/suites/query_p0/show/test_map_show_create.groovy +++ b/regression-test/suites/query_p0/show/test_map_show_create.groovy @@ -62,6 +62,7 @@ suite("test_map_show_create", "query") { create_test_table.call(testTable) qt_select "SHOW CREATE TABLE ${testTable}" + qt_select "select count(k2), count(k3), count(k4), count(k5), count(k6) from ${testTable}" } finally { try_sql("DROP TABLE IF EXISTS ${testTable}") } diff --git a/regression-test/suites/query_p0/show/test_struct_show_create.groovy b/regression-test/suites/query_p0/show/test_struct_show_create.groovy index e73359b663..ae21c4ed45 100644 --- a/regression-test/suites/query_p0/show/test_struct_show_create.groovy +++ b/regression-test/suites/query_p0/show/test_struct_show_create.groovy @@ -71,7 +71,7 @@ suite("test_struct_show_create", "query") { try { sql "DROP TABLE IF EXISTS ${testTable}" create_test_table.call(testTable) - + qt_select_count "select count(k2), count(k3), count(k4), count(k5), count(6), count(k7), count(k8), count(k9), count(k10), count(11) from ${testTable}" qt_select "show create table ${testTable}" } finally { try_sql("DROP TABLE IF EXISTS ${testTable}")