This is an automated email from the ASF dual-hosted git repository. morningman pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-doris.git
The following commit(s) were added to refs/heads/master by this push: new 415b6b8086 [feature-wip](array-type) Support array type which doesn't contain null (#9809) 415b6b8086 is described below commit 415b6b8086b6fe8ff3b12c5c047f2fa4bcb07484 Author: Adonis Ling <adonis0...@gmail.com> AuthorDate: Sun Jun 12 23:35:28 2022 +0800 [feature-wip](array-type) Support array type which doesn't contain null (#9809) --- be/src/runtime/types.cpp | 6 + be/src/runtime/types.h | 7 +- be/src/vec/data_types/data_type_factory.cpp | 4 +- be/test/runtime/array_test.cpp | 212 ++++++++++++++++++++- fe/fe-core/src/main/cup/sql_parser.cup | 5 +- .../org/apache/doris/analysis/ArrayLiteral.java | 17 +- .../java/org/apache/doris/catalog/ArrayType.java | 50 +++-- .../main/java/org/apache/doris/catalog/Column.java | 5 +- .../java/org/apache/doris/catalog/ColumnType.java | 4 +- fe/fe-core/src/main/jflex/sql_scanner.flex | 1 + .../doris/analysis/RangePartitionPruneTest.java | 2 +- .../org/apache/doris/catalog/CreateTableTest.java | 5 + gensrc/proto/types.proto | 2 + gensrc/thrift/Types.thrift | 3 + 14 files changed, 283 insertions(+), 40 deletions(-) diff --git a/be/src/runtime/types.cpp b/be/src/runtime/types.cpp index b59d5186d2..58261a216b 100644 --- a/be/src/runtime/types.cpp +++ b/be/src/runtime/types.cpp @@ -49,6 +49,9 @@ TypeDescriptor::TypeDescriptor(const std::vector<TTypeNode>& types, int* idx) DCHECK(!node.__isset.scalar_type); DCHECK_LT(*idx, types.size() - 1); type = TYPE_ARRAY; + if (node.__isset.contains_null) { + contains_null = node.contains_null; + } ++(*idx); children.push_back(TypeDescriptor(types, idx)); break; @@ -165,6 +168,9 @@ TypeDescriptor::TypeDescriptor(const google::protobuf::RepeatedPtrField<PTypeNod } case TTypeNodeType::ARRAY: { type = TYPE_ARRAY; + if (node.has_contains_null()) { + contains_null = node.contains_null(); + } ++(*idx); children.push_back(TypeDescriptor(types, idx)); break; diff --git a/be/src/runtime/types.h b/be/src/runtime/types.h index b85fdb2dc2..2987064962 100644 --- a/be/src/runtime/types.h +++ b/be/src/runtime/types.h @@ -57,12 +57,15 @@ struct TypeDescriptor { /// The maximum precision representable by a 8-byte decimal (Decimal8Value) static const int MAX_DECIMAL8_PRECISION = 18; - /// Empty for scalar types + // Empty for scalar types std::vector<TypeDescriptor> children; - /// Only set if type == TYPE_STRUCT. The field name of each child. + // Only set if type == TYPE_STRUCT. The field name of each child. std::vector<std::string> field_names; + // Used for complex types only. + bool contains_null = true; + TypeDescriptor() : type(INVALID_TYPE), len(-1), precision(-1), scale(-1) {} // explicit TypeDescriptor(PrimitiveType type) : diff --git a/be/src/vec/data_types/data_type_factory.cpp b/be/src/vec/data_types/data_type_factory.cpp index 3658270ec7..43897e1f44 100644 --- a/be/src/vec/data_types/data_type_factory.cpp +++ b/be/src/vec/data_types/data_type_factory.cpp @@ -108,8 +108,8 @@ DataTypePtr DataTypeFactory::create_data_type(const TypeDescriptor& col_desc, bo break; case TYPE_ARRAY: DCHECK(col_desc.children.size() == 1); - nested = - std::make_shared<vectorized::DataTypeArray>(create_data_type(col_desc.children[0])); + nested = std::make_shared<vectorized::DataTypeArray>( + create_data_type(col_desc.children[0], col_desc.contains_null)); break; case INVALID_TYPE: default: diff --git a/be/test/runtime/array_test.cpp b/be/test/runtime/array_test.cpp index 2582a975f5..162157852d 100644 --- a/be/test/runtime/array_test.cpp +++ b/be/test/runtime/array_test.cpp @@ -52,9 +52,10 @@ namespace doris { template <typename... Ts> ColumnPB create_column_pb(const std::string& type, const Ts&... sub_column_types) { ColumnPB column; - column.set_type(type); + auto prefix = "NOT_NULL_"; + column.set_is_nullable(type.compare(0, strlen(prefix), prefix) != 0); + column.set_type(column.is_nullable() ? type : type.substr(strlen(prefix))); column.set_aggregation("NONE"); - column.set_is_nullable(true); if (type == "ARRAY") { column.set_length(OLAP_ARRAY_MAX_BYTES); } @@ -326,7 +327,7 @@ private: meta->set_encoding(item_encoding); } meta->set_compression(segment_v2::LZ4F); - meta->set_is_nullable(true); + meta->set_is_nullable(column.is_nullable()); for (uint32_t i = 0; i < column.get_subtype_count(); ++i) { init_column_meta<array_encoding, item_encoding>(meta->add_children_columns(), column_id, column.get_sub_column(i)); @@ -465,6 +466,36 @@ TEST_F(ArrayTest, TestBoolean) { test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, literal_arrays); } +TEST_F(ArrayTest, TestNotNullBoolean) { + // depth 1 + auto column_pb = create_column_pb("ARRAY", "NOT_NULL_BOOLEAN"); + std::vector<std::string> literal_arrays = { + "[]", + "[true, false, false]", + }; + test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, literal_arrays); + + // depth 2 + column_pb = create_column_pb("ARRAY", "ARRAY", "NOT_NULL_BOOLEAN"); + literal_arrays = { + "[]", + "[[]]", + "[[false, true, false]]", + "[[false, true, false], [true, false, true]]", + }; + test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, literal_arrays); + + // depth 3 + column_pb = create_column_pb("ARRAY", "ARRAY", "ARRAY", "NOT_NULL_BOOLEAN"); + literal_arrays = { + "[]", + "[[]]", + "[[[]]]", + "[[[]], [[false], [true, false]], [[false, true, false]]]", + }; + test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, literal_arrays); +} + void test_integer(const std::string& type, ArrayTest& test_suite) { // depth 1 auto column_pb = create_column_pb("ARRAY", type); @@ -512,6 +543,44 @@ TEST_F(ArrayTest, TestInteger) { test_integer("LARGEINT", *this); } +void test_not_null_integer(const std::string& type, ArrayTest& test_suite) { + // depth 1 + auto column_pb = create_column_pb("ARRAY", type); + std::vector<std::string> literal_arrays = { + "[]", + "[1, 2, 3]", + }; + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, + literal_arrays); + + // depth 2 + column_pb = create_column_pb("ARRAY", "ARRAY", type); + literal_arrays = { + "[]", + "[[]]", + "[[1, 2, 3]]", + "[[1, 2, 3], [4, 5, 6]]", + }; + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, + literal_arrays); + + // depth 3 + column_pb = create_column_pb("ARRAY", "ARRAY", "ARRAY", type); + literal_arrays = { + "[]", "[[]]", "[[[]]]", "[[[1, 2, 3]]]", "[[[]], [[1], [2, 3]], [[4, 5, 6]]]", + }; + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, + literal_arrays); +} + +TEST_F(ArrayTest, TestNotNullInteger) { + test_not_null_integer("NOT_NULL_TINYINT", *this); + test_not_null_integer("NOT_NULL_SMALLINT", *this); + test_not_null_integer("NOT_NULL_INT", *this); + test_not_null_integer("NOT_NULL_BIGINT", *this); + test_not_null_integer("NOT_NULL_LARGEINT", *this); +} + void test_float(const std::string& type, ArrayTest& test_suite) { // depth 1 auto column_pb = create_column_pb("ARRAY", type); @@ -555,6 +624,40 @@ TEST_F(ArrayTest, TestFloat) { test_float("DOUBLE", *this); } +void test_not_null_float(const std::string& type, ArrayTest& test_suite) { + // depth 1 + auto column_pb = create_column_pb("ARRAY", type); + std::vector<std::string> literal_arrays = { + "[]", + "[1.5, 2.5, 3.5]", + }; + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, + literal_arrays); + // depth 2 + column_pb = create_column_pb("ARRAY", "ARRAY", type); + literal_arrays = { + "[]", + "[[]]", + "[[1.5, 2.5, 3.5]]", + "[[1.5, 2.5, 3.5], [4.5, 5.5, 6.5]]", + }; + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, + literal_arrays); + + // depth 3 + column_pb = create_column_pb("ARRAY", "ARRAY", "ARRAY", type); + literal_arrays = { + "[]", "[[]]", "[[[]]]", "[[[1.5]]]", "[[[]], [[1.5], [2.5, 3.5]], [[4.5, 5.5, 6.5]]]", + }; + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, + literal_arrays); +} + +TEST_F(ArrayTest, TestNotNullFloat) { + test_not_null_float("NOT_NULL_FLOAT", *this); + test_not_null_float("NOT_NULL_DOUBLE", *this); +} + void test_string(const std::string& type, ArrayTest& test_suite) { // depth 1 auto column_pb = create_column_pb("ARRAY", type); @@ -590,6 +693,35 @@ TEST_F(ArrayTest, TestString) { test_string("STRING", *this); } +void test_not_null_string(const std::string& type, ArrayTest& test_suite) { + // depth 1 + auto column_pb = create_column_pb("ARRAY", type); + std::vector<std::string> literal_arrays = { + "[]", + "[\"a\", \"b\", \"c\"]", + }; + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::DICT_ENCODING>(column_pb, + literal_arrays); + + // more depths + column_pb = create_column_pb("ARRAY", "ARRAY", "ARRAY", type); + literal_arrays = { + "[]", + "[[]]", + "[[[]]]", + "[[[\"a\", \"b\", \"c\"]]]", + "[[[\"a\", \"c\"], [\"d\", \"e\", \"f\"]], [[\"g\"]]]", + }; + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::DICT_ENCODING>(column_pb, + literal_arrays); +} + +TEST_F(ArrayTest, TestNotNullString) { + test_not_null_string("NOT_NULL_CHAR", *this); + test_not_null_string("NOT_NULL_VARCHAR", *this); + test_not_null_string("NOT_NULL_STRING", *this); +} + void test_datetime(const std::string& type, ArrayTest& test_suite) { auto column_pb = create_column_pb("ARRAY", type); std::vector<std::string> literal_arrays; @@ -681,9 +813,83 @@ TEST_F(ArrayTest, TestDateTime) { test_datetime("DATETIME", *this); } +void test_not_null_datetime(const std::string& type, ArrayTest& test_suite) { + auto column_pb = create_column_pb("ARRAY", type); + std::vector<std::string> literal_arrays; + if (type == "DATE") { + literal_arrays = { + "[]", + "[\"2022-04-01\", \"2022-04-02\", \"2022-04-03\"]", + }; + } else { + literal_arrays = { + "[]", + "[\"2022-04-01 19:30:40\", \"2022-04-02 19:30:40 \", \"2022-04-03 19:30:40\"]", + }; + } + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, + literal_arrays); + // depth 2 + column_pb = create_column_pb("ARRAY", "ARRAY", type); + if (type == "DATE") { + literal_arrays = { + "[]", + "[[]]", + "[[\"2022-04-01\", \"2022-04-02\", \"2022-04-03\"], [\"2022-04-04\", " + "\"2022-04-05\", " + "\"2022-04-06\"]]", + }; + } else { + literal_arrays = { + "[]", + "[[]]", + "[[\"2022-04-01 19:30:40\", \"2022-04-02 19:30:40\", \"2022-04-03 19:30:40\"], " + "[\"2022-04-04 19:30:40\", " + "\"2022-04-05\", " + "\"2022-04-06\"]]", + }; + } + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, + literal_arrays); + + // depth 3 + column_pb = create_column_pb("ARRAY", "ARRAY", "ARRAY", type); + if (type == "DATE") { + literal_arrays = { + "[]", + "[[]]", + "[[[]]]", + "[[[\"2022-04-01\"]]]", + "[[[]], [[\"2022-04-01\"], [\"2022-04-02\", \"2022-04-03\"]], " + "[[\"2022-04-04\", " + "\"2022-04-05\", \"2022-04-06\"]]]", + }; + } else { + literal_arrays = { + "[]", + "[[]]", + "[[[]]]", + "[[[\"2022-04-01 19:30:40\"]]]", + "[[[]], [[\"2022-04-01 19:30:40\"], [\"2022-04-02 19:30:40\", \"2022-04-03 " + "19:30:40\"]], " + "[[\"2022-04-04 19:30:40\", " + "\"2022-04-05 19:30:40\", \"2022-04-06 19:30:40\"]]]", + }; + } + test_suite.test<segment_v2::DEFAULT_ENCODING, segment_v2::BIT_SHUFFLE>(column_pb, + literal_arrays); +} + +TEST_F(ArrayTest, TestNotNullDateTime) { + test_not_null_datetime("NOT_NULL_DATE", *this); + test_not_null_datetime("NOT_NULL_DATETIME", *this); +} + TEST_F(ArrayTest, TestDecimal) { test_integer("DECIMAL", *this); + test_not_null_integer("NOT_NULL_DECIMAL", *this); test_float("DECIMAL", *this); + test_not_null_float("NOT_NULL_DECIMAL", *this); } } // namespace doris diff --git a/fe/fe-core/src/main/cup/sql_parser.cup b/fe/fe-core/src/main/cup/sql_parser.cup index 2bdb818ed8..281c4c884f 100644 --- a/fe/fe-core/src/main/cup/sql_parser.cup +++ b/fe/fe-core/src/main/cup/sql_parser.cup @@ -276,7 +276,8 @@ terminal String KW_ADD, KW_ADMIN, KW_AFTER, KW_AGGREGATE, KW_ALIAS, KW_ALL, KW_A KW_UNCOMMITTED, KW_UNBOUNDED, KW_UNION, KW_UNIQUE, KW_UNLOCK, KW_UNSIGNED, KW_USE, KW_USER, KW_USING, KW_UNINSTALL, KW_VALUE, KW_VALUES, KW_VARCHAR, KW_VARIABLES, KW_VERBOSE, KW_VIEW, KW_WARNINGS, KW_WEEK, KW_WHEN, KW_WHITELIST, KW_WHERE, KW_WITH, KW_WORK, KW_WRITE, - KW_YEAR; + KW_YEAR, + KW_NOT_NULL; terminal COMMA, COLON, DOT, DOTDOTDOT, AT, STAR, LPAREN, RPAREN, SEMICOLON, LBRACKET, RBRACKET, DIVIDE, MOD, ADD, SUBTRACT; terminal BITAND, BITOR, BITXOR, BITNOT; @@ -4628,6 +4629,8 @@ type ::= {: RESULT = ScalarType.createVarcharType(-1); :} | KW_ARRAY LESSTHAN type:value_type GREATERTHAN {: RESULT = new ArrayType(value_type); :} + | KW_ARRAY LESSTHAN KW_NOT_NULL LPAREN type:value_type RPAREN GREATERTHAN + {: RESULT = new ArrayType(value_type, false); :} | KW_MAP LESSTHAN type:key_type COMMA type:value_type GREATERTHAN {: RESULT = new MapType(key_type,value_type); :} | KW_STRUCT LESSTHAN struct_field_list:fields GREATERTHAN diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ArrayLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ArrayLiteral.java index d9024de807..60be1f6001 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ArrayLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ArrayLiteral.java @@ -35,17 +35,22 @@ import java.util.List; public class ArrayLiteral extends LiteralExpr { public ArrayLiteral() { - this.type = new ArrayType(Type.NULL); + type = new ArrayType(Type.NULL, false); children = new ArrayList<>(); } public ArrayLiteral(LiteralExpr... v) { - if (v.length < 1) { - this.type = new ArrayType(Type.NULL); - return; + Type itemType = Type.NULL; + boolean containsNull = false; + for (LiteralExpr expr : v) { + if (itemType == Type.NULL || expr.type.getSlotSize() > itemType.getSlotSize()) { + itemType = expr.type; + } + if (expr.isNullable()) { + containsNull = true; + } } - - this.type = new ArrayType(v[0].type); + type = new ArrayType(itemType, containsNull); children = new ArrayList<>(v.length); children.addAll(Arrays.asList(v)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java index 028cb760fd..4748d4cad9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java @@ -37,22 +37,31 @@ public class ArrayType extends Type { @SerializedName(value = "itemType") private Type itemType; + @SerializedName(value = "containsNull") + private boolean containsNull; + public ArrayType() { - this.itemType = NULL; + itemType = NULL; + containsNull = false; } public ArrayType(Type itemType) { - this.itemType = itemType; + this(itemType, true); } - public void setItemType(Type itemType) { + public ArrayType(Type itemType, boolean containsNull) { this.itemType = itemType; + this.containsNull = containsNull; } public Type getItemType() { return itemType; } + public boolean getContainsNull() { + return containsNull; + } + @Override public PrimitiveType getPrimitiveType() { return PrimitiveType.ARRAY; @@ -69,32 +78,33 @@ public class ArrayType extends Type { } // Array(Null) is a virtual Array type, can match any Array(...) type - if (itemType.isNull()) { - return true; - } - if (((ArrayType) t).getItemType().isNull()) { + if (itemType.isNull() || ((ArrayType) t).getItemType().isNull()) { return true; } - - return itemType.matchesType(((ArrayType) t).itemType); + return itemType.matchesType(((ArrayType) t).itemType) + && ((ArrayType) t).containsNull == containsNull; } public static ArrayType create() { return new ArrayType(); } - public static ArrayType create(Type type) { - return new ArrayType(type); + public static ArrayType create(Type type, boolean containsNull) { + return new ArrayType(type, containsNull); } @Override public String toSql(int depth) { - return String.format("ARRAY<%s>", itemType.toSql(depth + 1)); + if (!containsNull) { + return "ARRAY<NOT_NULL(" + itemType.toSql(depth + 1) + ")>"; + } else { + return "ARRAY<" + itemType.toSql(depth + 1) + ">"; + } } @Override public int hashCode() { - return Objects.hash(itemType); + return Objects.hash(itemType, containsNull); } @Override @@ -103,10 +113,13 @@ public class ArrayType extends Type { return false; } ArrayType otherArrayType = (ArrayType) other; - return otherArrayType.itemType.equals(itemType); + return otherArrayType.itemType.equals(itemType) && otherArrayType.containsNull == containsNull; } public static boolean canCastTo(ArrayType type, ArrayType targetType) { + if (!targetType.containsNull && type.containsNull) { + return false; + } if (targetType.getItemType().isStringType() && type.getItemType().isStringType()) { return true; } @@ -119,6 +132,7 @@ public class ArrayType extends Type { container.types.add(node); Preconditions.checkNotNull(itemType); node.setType(TTypeNodeType.ARRAY); + node.setContainsNull(containsNull); itemType.toThrift(container); } @@ -130,8 +144,7 @@ public class ArrayType extends Type { } // Pass in the padding to make sure nested fields are aligned properly, // even if we then strip the top-level padding. - String structStr = itemType.prettyPrint(lpad); - structStr = structStr.substring(lpad); + String structStr = itemType.prettyPrint(lpad).substring(lpad); return String.format("%sARRAY<%s>", leftPadding, structStr); } @@ -162,10 +175,7 @@ public class ArrayType extends Type { @Override public boolean supportsTablePartitioning() { - if (!isSupported() || isComplexType()) { - return false; - } - return true; + return isSupported() && !isComplexType(); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java index 28e7a24303..7f75392090 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java @@ -166,10 +166,7 @@ public class Column implements Writable { public void createChildrenColumn(Type type, Column column) { if (type.isArrayType()) { Column c = new Column(COLUMN_ARRAY_CHILDREN, ((ArrayType) type).getItemType()); - // TODO We always set the item type in array nullable. - // We may provide an alternative to configure this property of - // the item type in array in future. - c.setIsAllowNull(true); + c.setIsAllowNull(((ArrayType) type).getContainsNull()); column.addChildrenColumn(c); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnType.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnType.java index 41575518b4..81bd0e3238 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ColumnType.java @@ -134,6 +134,7 @@ public abstract class ColumnType { ArrayType arrayType = (ArrayType) type; Text.writeString(out, arrayType.getPrimitiveType().name()); write(out, arrayType.getItemType()); + out.writeBoolean(arrayType.getContainsNull()); } } @@ -141,7 +142,8 @@ public abstract class ColumnType { PrimitiveType primitiveType = PrimitiveType.valueOf(Text.readString(in)); if (primitiveType == PrimitiveType.ARRAY) { Type itermType = read(in); - return ArrayType.create(itermType); + boolean containsNull = in.readBoolean(); + return ArrayType.create(itermType, containsNull); } else { int scale = in.readInt(); int precision = in.readInt(); diff --git a/fe/fe-core/src/main/jflex/sql_scanner.flex b/fe/fe-core/src/main/jflex/sql_scanner.flex index fceb550129..d57c6e8519 100644 --- a/fe/fe-core/src/main/jflex/sql_scanner.flex +++ b/fe/fe-core/src/main/jflex/sql_scanner.flex @@ -432,6 +432,7 @@ import org.apache.doris.qe.SqlModeHelper; keywordMap.put("year", new Integer(SqlParserSymbols.KW_YEAR)); keywordMap.put("||", new Integer(SqlParserSymbols.KW_PIPE)); keywordMap.put("current_timestamp", new Integer(SqlParserSymbols.KW_CURRENT_TIMESTAMP)); + keywordMap.put("not_null", new Integer(SqlParserSymbols.KW_NOT_NULL)); } // map from token id to token description diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/RangePartitionPruneTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/RangePartitionPruneTest.java index 52b52eb74f..fbc28fe6d5 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/RangePartitionPruneTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/RangePartitionPruneTest.java @@ -128,7 +128,7 @@ public class RangePartitionPruneTest extends PartitionPruneTestBase { addCase("select * from test.t1 where dt in (20211124, 20211126, 20211122)", "partitions=3/8", "partitions=3/8"); // is null addCase("select * from test.t1 where dt is null", "partitions=1/8", "partitions=1/8"); - addCase("select * from test.not_null where dt is null", "partitions=0/7", "partitions=0/7"); + addCase("select * from test.`not_null` where dt is null", "partitions=0/7", "partitions=0/7"); // not equal to addCase("select * from test.t1 where dt!=20211122", "partitions=8/8", "partitions=8/8"); diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableTest.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableTest.java index 71dd3e399d..17ddd906c0 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableTest.java @@ -539,5 +539,10 @@ public class CreateTableTest { createTable("create table test.table2(k1 INT, k2 Array<Array<int>>) duplicate key (k1) " + "distributed by hash(k1) buckets 1 properties('replication_num' = '1');"); }); + + ExceptionChecker.expectThrowsNoException(() -> { + createTable("create table test.table3(k1 INT, k2 Array<not_null(int)>) duplicate key (k1) " + + "distributed by hash(k1) buckets 1 properties('replication_num' = '1');"); + }); } } diff --git a/gensrc/proto/types.proto b/gensrc/proto/types.proto index a3ac3dc190..7a95288517 100644 --- a/gensrc/proto/types.proto +++ b/gensrc/proto/types.proto @@ -48,6 +48,8 @@ message PTypeNode { optional PScalarType scalar_type = 2; // only used for structs; has struct_fields.size() corresponding child types repeated PStructField struct_fields = 3; + // only used for complex types, such as array, map and etc. + optional bool contains_null = 4; }; // A flattened representation of a tree of column types obtained by depth-first diff --git a/gensrc/thrift/Types.thrift b/gensrc/thrift/Types.thrift index d75376443f..098307c98e 100644 --- a/gensrc/thrift/Types.thrift +++ b/gensrc/thrift/Types.thrift @@ -126,6 +126,9 @@ struct TTypeNode { // only used for structs; has struct_fields.size() corresponding child types 3: optional list<TStructField> struct_fields + + // only used for complex types, such as array, map and etc. + 4: optional bool contains_null } // A flattened representation of a tree of column types obtained by depth-first --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org