This is an automated email from the ASF dual-hosted git repository. zhangstar333 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 838e31146f0 [improve](fold) support complex type for constant folding (#32867) 838e31146f0 is described below commit 838e31146f095cc53d4b38a8ec7e078cbc7b226c Author: zhangstar333 <87313068+zhangstar...@users.noreply.github.com> AuthorDate: Thu Apr 11 23:40:50 2024 +0800 [improve](fold) support complex type for constant folding (#32867) --- be/src/runtime/fold_constant_executor.cpp | 61 ++-- .../java/org/apache/doris/catalog/ScalarType.java | 4 + .../java/org/apache/doris/analysis/CastExpr.java | 5 + .../java/org/apache/doris/analysis/MapLiteral.java | 2 +- .../expression/rules/FoldConstantRuleOnBE.java | 406 ++++++++++++++++++--- .../trees/expressions/literal/MapLiteral.java | 5 +- .../trees/expressions/literal/StructLiteral.java | 5 +- .../apache/doris/rewrite/FoldConstantsRule.java | 1 + .../org/apache/doris/analysis/MapLiteralTest.java | 12 +- .../apache/doris/analysis/StructLiteralTest.java | 4 +- .../nereids/trees/expressions/LiteralTest.java | 265 ++++++++++++++ gensrc/thrift/PaloInternalService.thrift | 1 + .../push_filter_inside_join.groovy | 1 + .../filter_push_down/push_filter_through.groovy | 1 + 14 files changed, 696 insertions(+), 77 deletions(-) diff --git a/be/src/runtime/fold_constant_executor.cpp b/be/src/runtime/fold_constant_executor.cpp index 69fe217da78..5ba384baf84 100644 --- a/be/src/runtime/fold_constant_executor.cpp +++ b/be/src/runtime/fold_constant_executor.cpp @@ -48,19 +48,20 @@ #include "util/runtime_profile.h" #include "util/uid_util.h" #include "vec/columns/column.h" +#include "vec/columns/column_array.h" #include "vec/columns/column_vector.h" #include "vec/columns/columns_number.h" #include "vec/common/string_ref.h" #include "vec/core/block.h" #include "vec/core/column_with_type_and_name.h" +#include "vec/core/field.h" +#include "vec/core/types.h" +#include "vec/data_types/data_type_array.h" #include "vec/data_types/data_type_number.h" #include "vec/exprs/vexpr.h" #include "vec/exprs/vexpr_context.h" #include "vec/runtime/vdatetime_value.h" -using std::string; -using std::map; - namespace doris { static std::unordered_set<PrimitiveType> PRIMITIVE_TYPE_SET { @@ -72,7 +73,7 @@ static std::unordered_set<PrimitiveType> PRIMITIVE_TYPE_SET { Status FoldConstantExecutor::fold_constant_vexpr(const TFoldConstantParams& params, PConstantExprResult* response) { const auto& expr_map = params.expr_map; - auto expr_result_map = response->mutable_expr_result_map(); + auto* expr_result_map = response->mutable_expr_result_map(); TQueryGlobals query_globals = params.query_globals; _query_id = params.query_id; @@ -107,31 +108,45 @@ Status FoldConstantExecutor::fold_constant_vexpr(const TFoldConstantParams& para string result; const auto& column_ptr = tmp_block.get_by_position(result_column).column; const auto& column_type = tmp_block.get_by_position(result_column).type; - if (column_ptr->is_null_at(0)) { - expr_result.set_success(false); - } else { + // 4 from fe: Config.be_exec_version maybe need remove after next version, now in 2.1 + if (_runtime_state->be_exec_version() >= 4 && params.__isset.is_nereids && + params.is_nereids) { + auto* p_type_desc = expr_result.mutable_type_desc(); + auto* p_values = expr_result.mutable_result_content(); + res_type.to_protobuf(p_type_desc); + auto datatype_serde = column_type->get_serde(); + RETURN_IF_ERROR(datatype_serde->write_column_to_pb( + *column_ptr->convert_to_full_column_if_const(), *p_values, 0, 1)); expr_result.set_success(true); - StringRef string_ref; - auto type = ctx->root()->type().type; - //eg: strcut, array, map VARIANT... will not impl get_data_at, so could use column->to_string() - if (PRIMITIVE_TYPE_SET.contains(type)) { - string_ref = column_ptr->get_data_at(0); + // after refactor, this field is useless, but it's required + expr_result.set_content("ERROR"); + expr_result.mutable_type()->set_type(t_type); + pexpr_result_map.mutable_map()->insert({n.first, expr_result}); + } else { + if (column_ptr->is_null_at(0)) { + expr_result.set_success(false); + } else { + expr_result.set_success(true); + StringRef string_ref; + auto type = ctx->root()->type().type; + //eg: strcut, array, map VARIANT... will not impl get_data_at, so could use column->to_string() + if (PRIMITIVE_TYPE_SET.contains(type)) { + string_ref = column_ptr->get_data_at(0); + } + RETURN_IF_ERROR(_get_result((void*)string_ref.data, string_ref.size, + ctx->root()->type(), column_ptr, column_type, + result)); } - RETURN_IF_ERROR(_get_result((void*)string_ref.data, string_ref.size, - ctx->root()->type(), column_ptr, column_type, result)); + expr_result.set_content(std::move(result)); + expr_result.mutable_type()->set_type(t_type); + expr_result.mutable_type()->set_scale(res_type.scale); + expr_result.mutable_type()->set_precision(res_type.precision); + expr_result.mutable_type()->set_len(res_type.len); + pexpr_result_map.mutable_map()->insert({n.first, expr_result}); } - - expr_result.set_content(std::move(result)); - expr_result.mutable_type()->set_type(t_type); - expr_result.mutable_type()->set_scale(res_type.scale); - expr_result.mutable_type()->set_precision(res_type.precision); - expr_result.mutable_type()->set_len(res_type.len); - pexpr_result_map.mutable_map()->insert({n.first, expr_result}); } expr_result_map->insert({m.first, pexpr_result_map}); } - //TODO: will be delete the debug log after find problem of timeout. - LOG(INFO) << "finish fold_query_id: " << query_id_string(); return Status::OK(); } diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/ScalarType.java b/fe/fe-common/src/main/java/org/apache/doris/catalog/ScalarType.java index 83072ad97f5..67346fc2160 100644 --- a/fe/fe-common/src/main/java/org/apache/doris/catalog/ScalarType.java +++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/ScalarType.java @@ -216,6 +216,10 @@ public class ScalarType extends Type { return DEFAULT_DECIMALV2; case LARGEINT: return LARGEINT; + case IPV4: + return IPV4; + case IPV6: + return IPV6; case ALL: return ALL; default: diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java index f069c1cd695..d2437fbd95c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java @@ -132,6 +132,11 @@ public class CastExpr extends Expr { if (type.isDecimalV2() && e.type.isDecimalV2()) { getChild(0).setType(type); } + // as the targetType have struct field name, if use the default name will be + // like col1,col2, col3... in struct, and the filed name is import in BE. + if (type.isStructType() && e.type.isStructType()) { + getChild(0).setType(type); + } analysisDone(); return; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/MapLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/MapLiteral.java index e55519101cf..633478f3f84 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/MapLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/MapLiteral.java @@ -188,7 +188,7 @@ public class MapLiteral extends LiteralExpr { // map key type do not support complex type throw new UnsupportedOperationException("Unsupport key type for MAP: " + children.get(i).getType()); } - list.add(children.get(i).getStringValueForArray() + list.add(getStringLiteralForComplexType(children.get(i)) + ":" + getStringLiteralForComplexType(children.get(i + 1))); } return "{" + StringUtils.join(list, ", ") + "}"; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java index 09e9bbe0b91..ac9d7c4427b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnBE.java @@ -22,7 +22,9 @@ import org.apache.doris.analysis.ExprId; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.ScalarType; +import org.apache.doris.common.Config; import org.apache.doris.common.IdGenerator; +import org.apache.doris.common.Pair; import org.apache.doris.common.UserException; import org.apache.doris.common.util.DebugUtil; import org.apache.doris.common.util.TimeUtils; @@ -33,18 +35,44 @@ import org.apache.doris.nereids.rules.expression.ExpressionPatternRuleFactory; import org.apache.doris.nereids.trees.expressions.Alias; import org.apache.doris.nereids.trees.expressions.Cast; import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.generator.TableGeneratingFunction; import org.apache.doris.nereids.trees.expressions.functions.scalar.Sleep; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Tokenize; +import org.apache.doris.nereids.trees.expressions.literal.ArrayLiteral; +import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; +import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral; +import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; +import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; +import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral; +import org.apache.doris.nereids.trees.expressions.literal.DecimalV3Literal; +import org.apache.doris.nereids.trees.expressions.literal.DoubleLiteral; +import org.apache.doris.nereids.trees.expressions.literal.FloatLiteral; +import org.apache.doris.nereids.trees.expressions.literal.IPv4Literal; +import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; +import org.apache.doris.nereids.trees.expressions.literal.JsonLiteral; +import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; +import org.apache.doris.nereids.trees.expressions.literal.MapLiteral; +import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.NumericLiteral; -import org.apache.doris.nereids.types.CharType; +import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; +import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; +import org.apache.doris.nereids.trees.expressions.literal.StructLiteral; +import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; +import org.apache.doris.nereids.types.ArrayType; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.DateTimeV2Type; -import org.apache.doris.nereids.types.DecimalV2Type; import org.apache.doris.nereids.types.DecimalV3Type; -import org.apache.doris.nereids.types.VarcharType; +import org.apache.doris.nereids.types.MapType; +import org.apache.doris.nereids.types.StructField; +import org.apache.doris.nereids.types.StructType; import org.apache.doris.proto.InternalService; import org.apache.doris.proto.InternalService.PConstantExprResult; import org.apache.doris.proto.Types.PScalarType; +import org.apache.doris.proto.Types.PStructField; +import org.apache.doris.proto.Types.PTypeDesc; +import org.apache.doris.proto.Types.PTypeNode; +import org.apache.doris.proto.Types.PValues; import org.apache.doris.qe.ConnectContext; import org.apache.doris.rpc.BackendServiceProxy; import org.apache.doris.system.Backend; @@ -55,12 +83,18 @@ import org.apache.doris.thrift.TPrimitiveType; import org.apache.doris.thrift.TQueryGlobals; import org.apache.doris.thrift.TQueryOptions; -import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; +import com.google.common.net.InetAddresses; +import com.google.protobuf.ByteString; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.Inet4Address; +import java.time.DateTimeException; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; @@ -68,7 +102,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -84,8 +117,8 @@ public class FoldConstantRuleOnBE implements ExpressionPatternRuleFactory { public List<ExpressionPatternMatcher<? extends Expression>> buildRules() { return ImmutableList.of( root(Expression.class) - .whenCtx(FoldConstantRuleOnBE::isEnableFoldByBe) - .thenApply(FoldConstantRuleOnBE::foldByBE) + .whenCtx(FoldConstantRuleOnBE::isEnableFoldByBe) + .thenApply(FoldConstantRuleOnBE::foldByBE) ); } @@ -156,12 +189,23 @@ public class FoldConstantRuleOnBE implements ExpressionPatternRuleFactory { return; } // eg: avg_state(1) return is agg function serialize data - if (expr.getDataType().isAggStateType()) { + // and some type can't find a literal to represent. + // time type: need add a time literal in nereids + // IPv6 type: need get a library to output the compressed address format + if (expr.getDataType().isAggStateType() || expr.getDataType().isObjectType() + || expr.getDataType().isVariantType() || expr.getDataType().isTimeLikeType() + || expr.getDataType().isIPv6Type()) { return; } - if (skipSleepFunction(expr)) { + if (skipSleepFunction(expr) || (expr instanceof TableGeneratingFunction)) { return; } + // Tokenize function want check the second child literal must be string type + // and properties format, it's a little special, + // maybe check in checkLegalityBeforeTypeCoercion function? + if (expr instanceof Tokenize) { + expr.checkLegalityAfterRewrite(); + } String id = idGenerator.getNextId().toString(); constMap.put(id, expr); Expr staleExpr; @@ -219,14 +263,14 @@ public class FoldConstantRuleOnBE implements ExpressionPatternRuleFactory { TQueryOptions tQueryOptions = new TQueryOptions(); tQueryOptions.setRepeatMaxNum(context.getSessionVariable().repeatMaxNum); + tQueryOptions.setBeExecVersion(Config.be_exec_version); TFoldConstantParams tParams = new TFoldConstantParams(paramMap, queryGlobals); tParams.setVecExec(true); tParams.setQueryOptions(tQueryOptions); tParams.setQueryId(context.queryId()); + tParams.setIsNereids(true); - // TODO: will be delete the debug log after find problem of timeout. - LOG.info("fold query {} ", DebugUtil.printId(context.queryId())); Future<PConstantExprResult> future = BackendServiceProxy.getInstance().foldConstantExpr(brpcAddress, tParams); PConstantExprResult result = future.get(5, TimeUnit.SECONDS); @@ -234,42 +278,18 @@ public class FoldConstantRuleOnBE implements ExpressionPatternRuleFactory { if (result.getStatus().getStatusCode() == 0) { for (Entry<String, InternalService.PExprResultMap> e : result.getExprResultMapMap().entrySet()) { for (Entry<String, InternalService.PExprResult> e1 : e.getValue().getMapMap().entrySet()) { - PScalarType pScalarType = e1.getValue().getType(); - TPrimitiveType tPrimitiveType = TPrimitiveType.findByValue(pScalarType.getType()); - PrimitiveType primitiveType = PrimitiveType.fromThrift(Objects.requireNonNull(tPrimitiveType)); Expression ret; if (e1.getValue().getSuccess()) { - DataType type; - if (PrimitiveType.ARRAY == primitiveType - || PrimitiveType.MAP == primitiveType - || PrimitiveType.STRUCT == primitiveType - || PrimitiveType.AGG_STATE == primitiveType) { + PTypeDesc pTypeDesc = e1.getValue().getTypeDesc(); + DataType type = convertToNereidsType(pTypeDesc.getTypesList(), 0).key(); + PValues resultContent = e1.getValue().getResultContent(); + List<Literal> resultExpression = getResultExpression(type, resultContent); + if (resultExpression.isEmpty()) { ret = constMap.get(e1.getKey()); + LOG.debug("Be constant folding convert {} to {} failed query_id: {}", e1.getKey(), ret, + DebugUtil.printId(context.queryId())); } else { - if (primitiveType == PrimitiveType.CHAR) { - Preconditions.checkState(pScalarType.hasLen(), - "be return char type without len"); - type = CharType.createCharType(pScalarType.getLen()); - } else if (primitiveType == PrimitiveType.VARCHAR) { - Preconditions.checkState(pScalarType.hasLen(), - "be return varchar type without len"); - type = VarcharType.createVarcharType(pScalarType.getLen()); - } else if (primitiveType == PrimitiveType.DECIMALV2) { - type = DecimalV2Type.createDecimalV2Type( - pScalarType.getPrecision(), pScalarType.getScale()); - } else if (primitiveType == PrimitiveType.DATETIMEV2) { - type = DateTimeV2Type.of(pScalarType.getScale()); - } else if (primitiveType == PrimitiveType.DECIMAL32 - || primitiveType == PrimitiveType.DECIMAL64 - || primitiveType == PrimitiveType.DECIMAL128 - || primitiveType == PrimitiveType.DECIMAL256) { - type = DecimalV3Type.createDecimalV3TypeLooseCheck( - pScalarType.getPrecision(), pScalarType.getScale()); - } else { - type = DataType.fromCatalogType(ScalarType.createType( - PrimitiveType.fromThrift(tPrimitiveType))); - } - ret = Literal.of(e1.getValue().getContent()).castTo(type); + ret = resultExpression.get(0); } } else { ret = constMap.get(e1.getKey()); @@ -291,4 +311,304 @@ public class FoldConstantRuleOnBE implements ExpressionPatternRuleFactory { } return resultMap; } + + /** + * convert PValues which from BE to Expression of nereids + */ + public static List<Literal> getResultExpression(DataType type, PValues resultContent) { + List<Literal> res = new ArrayList<>(); + if (type.isNullType()) { + int num = resultContent.getNullMapCount(); + for (int i = 0; i < num; ++i) { + Literal literal = new NullLiteral(type); + res.add(literal); + } + } else if (type.isBooleanType()) { + int num = resultContent.getUint32ValueCount(); + for (int i = 0; i < num; ++i) { + Literal literal = BooleanLiteral.of(resultContent.getUint32Value(i) == 1); + res.add(literal); + } + } else if (type.isTinyIntType()) { + int num = resultContent.getInt32ValueCount(); + for (int i = 0; i < num; ++i) { + Literal literal = new TinyIntLiteral((byte) resultContent.getInt32Value(i)); + res.add(literal); + } + } else if (type.isSmallIntType()) { + int num = resultContent.getInt32ValueCount(); + for (int i = 0; i < num; ++i) { + Literal literal = new SmallIntLiteral((short) resultContent.getInt32Value(i)); + res.add(literal); + } + } else if (type.isIntegerType()) { + int num = resultContent.getInt32ValueCount(); + for (int i = 0; i < num; ++i) { + Literal literal = new IntegerLiteral(resultContent.getInt32Value(i)); + res.add(literal); + } + } else if (type.isBigIntType()) { + int num = resultContent.getInt64ValueCount(); + for (int i = 0; i < num; ++i) { + Literal literal = new BigIntLiteral(resultContent.getInt64Value(i)); + res.add(literal); + } + } else if (type.isLargeIntType()) { + int num = resultContent.getBytesValueCount(); + for (int i = 0; i < num; ++i) { + ByteString bytesValue = resultContent.getBytesValue(i); + byte[] bytes = convertByteOrder(bytesValue.toByteArray()); + BigInteger convertedBigInteger = new BigInteger(bytes); + Literal literal = new LargeIntLiteral(convertedBigInteger); + res.add(literal); + } + } else if (type.isFloatType()) { + int num = resultContent.getFloatValueCount(); + for (int i = 0; i < num; ++i) { + float value = resultContent.getFloatValue(i); + Literal literal = null; + if (Float.isNaN(value)) { + literal = new NullLiteral(type); + } else { + literal = new FloatLiteral(value); + } + res.add(literal); + } + } else if (type.isDoubleType()) { + int num = resultContent.getDoubleValueCount(); + for (int i = 0; i < num; ++i) { + double value = resultContent.getDoubleValue(i); + Literal literal = null; + if (Double.isNaN(value)) { + literal = new NullLiteral(type); + } else { + literal = new DoubleLiteral(value); + } + res.add(literal); + } + } else if (type.isDecimalV2Type()) { + int num = resultContent.getBytesValueCount(); + for (int i = 0; i < num; ++i) { + ByteString bytesValue = resultContent.getBytesValue(i); + byte[] bytes = convertByteOrder(bytesValue.toByteArray()); + BigInteger value = new BigInteger(bytes); + BigDecimal bigDecimal = new BigDecimal(value, 9); // decimalv2 scale always 9 + Literal literal = new DecimalLiteral(bigDecimal); + res.add(literal); + } + } else if (type.isDecimalV3Type()) { + int num = resultContent.getBytesValueCount(); + DecimalV3Type decimalV3Type = (DecimalV3Type) type; + for (int i = 0; i < num; ++i) { + ByteString bytesValue = resultContent.getBytesValue(i); + byte[] bytes = convertByteOrder(bytesValue.toByteArray()); + BigInteger value = new BigInteger(bytes); + BigDecimal bigDecimal = new BigDecimal(value, decimalV3Type.getScale()); + Literal literal = new DecimalV3Literal(decimalV3Type, bigDecimal); + res.add(literal); + } + } else if (type.isDateTimeV2Type()) { + int num = resultContent.getUint64ValueCount(); + for (int i = 0; i < num; ++i) { + long uint64Value = resultContent.getUint64Value(i); + LocalDateTime dateTimeV2 = convertToJavaDateTimeV2(uint64Value); + Literal literal = new DateTimeV2Literal((DateTimeV2Type) type, dateTimeV2.getYear(), + dateTimeV2.getMonthValue(), dateTimeV2.getDayOfMonth(), dateTimeV2.getHour(), + dateTimeV2.getMinute(), dateTimeV2.getSecond(), dateTimeV2.getNano() / 1000); + res.add(literal); + } + } else if (type.isDateV2Type()) { + int num = resultContent.getUint32ValueCount(); + for (int i = 0; i < num; ++i) { + int uint32Value = resultContent.getUint32Value(i); + LocalDate localDate = convertToJavaDateV2(uint32Value); + DateV2Literal dateV2Literal = new DateV2Literal(localDate.getYear(), localDate.getMonthValue(), + localDate.getDayOfMonth()); + res.add(dateV2Literal); + } + } else if (type.isIPv4Type()) { + int num = resultContent.getUint32ValueCount(); + for (int i = 0; i < num; ++i) { + Inet4Address inet4Address = InetAddresses.fromInteger(resultContent.getUint32Value(i)); + IPv4Literal iPv4Literal = new IPv4Literal(inet4Address.getHostAddress()); + res.add(iPv4Literal); + } + } else if (type.isJsonType()) { + int num = resultContent.getStringValueCount(); + for (int i = 0; i < num; ++i) { + String stringValue = resultContent.getStringValue(i); + // maybe need handle NULL_IN_CSV_FOR_ORDINARY_TYPE = "\\N"; + JsonLiteral jsonLiteral = new JsonLiteral(stringValue); + res.add(jsonLiteral); + } + } else if (type.isStringLikeType()) { + int num = resultContent.getStringValueCount(); + for (int i = 0; i < num; ++i) { + Literal literal = new StringLiteral(resultContent.getStringValue(i)); + res.add(literal); + } + } else if (type.isArrayType()) { + ArrayType arrayType = (ArrayType) type; + int childCount = resultContent.getChildElementCount(); + List<Literal> allLiterals = new ArrayList<>(); + for (int i = 0; i < childCount; ++i) { + allLiterals.addAll(getResultExpression(arrayType.getItemType(), + resultContent.getChildElement(i))); + } + int offsetCount = resultContent.getChildOffsetCount(); + if (offsetCount == 1) { + ArrayLiteral arrayLiteral = new ArrayLiteral(allLiterals, arrayType); + res.add(arrayLiteral); + } else { + for (int i = 0; i < offsetCount; ++i) { + List<Literal> childLiteral = new ArrayList<>(); + int startOffset = (int) ((i == 0) ? 0 : resultContent.getChildOffset(i - 1)); + int endOffset = (int) resultContent.getChildOffset(i); + for (int off = startOffset; off < endOffset; ++off) { + childLiteral.add(allLiterals.get(off)); + } + ArrayLiteral arrayLiteral = new ArrayLiteral(childLiteral, arrayType); + res.add(arrayLiteral); + } + } + } else if (type.isMapType()) { + MapType mapType = (MapType) type; + int childCount = resultContent.getChildElementCount(); + List<Literal> allKeys = new ArrayList<>(); + List<Literal> allValues = new ArrayList<>(); + for (int i = 0; i < childCount; i = i + 2) { + allKeys.addAll(getResultExpression(mapType.getKeyType(), + resultContent.getChildElement(i))); + allValues.addAll(getResultExpression(mapType.getValueType(), + resultContent.getChildElement(i + 1))); + } + int offsetCount = resultContent.getChildOffsetCount(); + if (offsetCount == 1) { + MapLiteral mapLiteral = new MapLiteral(allKeys, allValues, mapType); + res.add(mapLiteral); + } else { + for (int i = 0; i < offsetCount; ++i) { + List<Literal> keyLiteral = new ArrayList<>(); + List<Literal> valueLiteral = new ArrayList<>(); + int startOffset = (int) ((i == 0) ? 0 : resultContent.getChildOffset(i - 1)); + int endOffset = (int) resultContent.getChildOffset(i); + for (int off = startOffset; off < endOffset; ++off) { + keyLiteral.add(allKeys.get(off)); + valueLiteral.add(allValues.get(off)); + } + MapLiteral mapLiteral = new MapLiteral(keyLiteral, valueLiteral, mapType); + res.add(mapLiteral); + } + } + } else if (type.isStructType()) { + StructType structType = (StructType) type; + int childCount = resultContent.getChildElementCount(); + List<List<Literal>> allFields = new ArrayList<>(); + for (int i = 0; i < childCount; ++i) { + allFields.add(getResultExpression(structType.getFields().get(i).getDataType(), + resultContent.getChildElement(i))); + } + for (int i = 0; i < allFields.get(0).size(); ++i) { + List<Literal> fields = new ArrayList<>(); + for (int child = 0; child < childCount; ++child) { + fields.add(allFields.get(child).get(i)); + } + StructLiteral structLiteral = new StructLiteral(fields, structType); + res.add(structLiteral); + } + } else { + LOG.warn("the type: {} is not support, should implement it", type.toString()); + } + if (resultContent.hasHasNull()) { + for (int i = 0; i < resultContent.getNullMapCount(); ++i) { + if (resultContent.getNullMap(i)) { + res.set(i, new NullLiteral(type)); + } + } + } + return res; + } + + private static Pair<DataType, Integer> convertToNereidsType(List<PTypeNode> typeNodes, int start) { + PScalarType pScalarType = typeNodes.get(start).getScalarType(); + boolean containsNull = typeNodes.get(start).getContainsNull(); + TPrimitiveType tPrimitiveType = TPrimitiveType.findByValue(pScalarType.getType()); + DataType type; + int parsedNodes; + if (tPrimitiveType == TPrimitiveType.ARRAY) { + Pair<DataType, Integer> itemType = convertToNereidsType(typeNodes, start + 1); + type = ArrayType.of(itemType.key(), containsNull); + parsedNodes = 1 + itemType.value(); + } else if (tPrimitiveType == TPrimitiveType.MAP) { + Pair<DataType, Integer> keyType = convertToNereidsType(typeNodes, start + 1); + Pair<DataType, Integer> valueType = convertToNereidsType(typeNodes, start + 1 + keyType.value()); + type = MapType.of(keyType.key(), valueType.key()); + parsedNodes = 1 + keyType.value() + valueType.value(); + } else if (tPrimitiveType == TPrimitiveType.STRUCT) { + parsedNodes = 1; + ArrayList<StructField> fields = new ArrayList<>(); + for (int i = 0; i < typeNodes.get(start).getStructFieldsCount(); ++i) { + Pair<DataType, Integer> fieldType = convertToNereidsType(typeNodes, start + parsedNodes); + PStructField structField = typeNodes.get(start).getStructFields(i); + fields.add(new StructField(structField.getName(), fieldType.key(), + structField.getContainsNull(), + structField.getComment() == null ? "" : structField.getComment())); + parsedNodes += fieldType.value(); + } + type = new StructType(fields); + } else if (tPrimitiveType == TPrimitiveType.DECIMALV2) { + type = DataType.fromCatalogType(ScalarType.createDecimalType(PrimitiveType.fromThrift(tPrimitiveType), + pScalarType.getPrecision(), pScalarType.getScale())); + parsedNodes = 1; + } else { + type = DataType.fromCatalogType(ScalarType.createType(PrimitiveType.fromThrift(tPrimitiveType), + pScalarType.getLen(), pScalarType.getPrecision(), pScalarType.getScale())); + parsedNodes = 1; + } + return Pair.of(type, parsedNodes); + } + + private static LocalDateTime convertToJavaDateTimeV2(long time) { + int year = (int) (time >> 46); + int yearMonth = (int) (time >> 42); + int yearMonthDay = (int) (time >> 37); + + int month = (yearMonth & 0XF); + int day = (yearMonthDay & 0X1F); + + int hour = (int) ((time >> 32) & 0X1F); + int minute = (int) ((time >> 26) & 0X3F); + int second = (int) ((time >> 20) & 0X3F); + int microsecond = (int) (time & 0XFFFFF); + + try { + return LocalDateTime.of(year, month, day, hour, minute, second, microsecond * 1000); + } catch (DateTimeException e) { + return null; + } + } + + private static LocalDate convertToJavaDateV2(int date) { + int year = date >> 9; + int month = (date >> 5) & 0XF; + int day = date & 0X1F; + try { + return LocalDate.of(year, month, day); + } catch (DateTimeException e) { + return null; + } + } + + /** + * Change the order of the bytes, Because JVM is Big-Endian , x86 is Little-Endian. + */ + private static byte[] convertByteOrder(byte[] bytes) { + int length = bytes.length; + for (int i = 0; i < length / 2; ++i) { + byte temp = bytes[i]; + bytes[i] = bytes[length - 1 - i]; + bytes[length - 1 - i] = temp; + } + return bytes; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MapLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MapLiteral.java index 7dab827509b..c57bd3a0487 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MapLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/MapLiteral.java @@ -48,7 +48,10 @@ public class MapLiteral extends Literal { this(keys, values, computeDataType(keys, values)); } - private MapLiteral(List<Literal> keys, List<Literal> values, DataType dataType) { + /** + * create MAP Literal with keys, values and datatype + */ + public MapLiteral(List<Literal> keys, List<Literal> values, DataType dataType) { super(dataType); this.keys = ImmutableList.copyOf(Objects.requireNonNull(keys, "keys should not be null")); this.values = ImmutableList.copyOf(Objects.requireNonNull(values, "values should not be null")); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StructLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StructLiteral.java index 2fd2186f496..3a46f1f5b83 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StructLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/StructLiteral.java @@ -49,7 +49,10 @@ public class StructLiteral extends Literal { this(fields, computeDataType(fields)); } - private StructLiteral(List<Literal> fields, DataType dataType) { + /** + * create Struct Literal with fields and datatype + */ + public StructLiteral(List<Literal> fields, DataType dataType) { super(dataType); this.fields = ImmutableList.copyOf(Objects.requireNonNull(fields, "fields should not be null")); Preconditions.checkArgument(dataType instanceof StructType, diff --git a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java index 3ef20a5651d..dd37c2fc7b1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java +++ b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java @@ -384,6 +384,7 @@ public class FoldConstantsRule implements ExprRewriteRule { tParams.setVecExec(true); tParams.setQueryOptions(tQueryOptions); tParams.setQueryId(context.queryId()); + tParams.setIsNereids(false); Future<InternalService.PConstantExprResult> future = BackendServiceProxy.getInstance().foldConstantExpr(brpcAddress, tParams); diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/MapLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/MapLiteralTest.java index 700c54253e4..61e77dbc907 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/MapLiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/MapLiteralTest.java @@ -116,26 +116,26 @@ public class MapLiteralTest { @Test public void testGetStringInFe() throws AnalysisException { MapLiteral mapLiteral1 = new MapLiteral(intLiteral1, floatLiteral); - Assert.assertEquals("{\"1\":2.15}", mapLiteral1.getStringValueInFe()); + Assert.assertEquals("{1:2.15}", mapLiteral1.getStringValueInFe()); MapLiteral mapLiteral11 = new MapLiteral(intLiteral1, floatLiteral1); - Assert.assertEquals("{\"1\":\"11:22:33\"}", mapLiteral11.getStringValueInFe()); + Assert.assertEquals("{1:\"11:22:33\"}", mapLiteral11.getStringValueInFe()); MapLiteral mapLiteral2 = new MapLiteral(boolLiteral, stringLiteral); - Assert.assertEquals("{\"1\":\"shortstring\"}", mapLiteral2.getStringValueInFe()); + Assert.assertEquals("{1:\"shortstring\"}", mapLiteral2.getStringValueInFe()); MapLiteral mapLiteral3 = new MapLiteral(largeIntLiteral, dateLiteral); - Assert.assertEquals("{\"1000000000000000000000\":\"2022-10-10\"}", mapLiteral3.getStringValueInFe()); + Assert.assertEquals("{1000000000000000000000:\"2022-10-10\"}", mapLiteral3.getStringValueInFe()); MapLiteral mapLiteral4 = new MapLiteral(floatLiteral1, nullLiteral); Assert.assertEquals("{\"11:22:33\":null}", mapLiteral4.getStringValueInFe()); MapLiteral mapLiteral5 = new MapLiteral(datetimeLiteral, dateLiteral); Assert.assertEquals("{\"2022-10-10 12:10:10\":\"2022-10-10\"}", mapLiteral5.getStringValueInFe()); MapLiteral mapLiteral6 = new MapLiteral(decimalLiteral1, decimalLiteral2); - Assert.assertEquals("{\"1.0\":2}", mapLiteral6.getStringValueInFe()); + Assert.assertEquals("{1.0:2}", mapLiteral6.getStringValueInFe()); MapLiteral mapLiteral7 = new MapLiteral(); Assert.assertEquals("{}", mapLiteral7.getStringValueInFe()); MapLiteral mapLiteral8 = new MapLiteral(nullLiteral, intLiteral1); Assert.assertEquals("{null:1}", mapLiteral8.getStringValueInFe()); MapLiteral mapLiteral9 = new MapLiteral(intLiteral1, nullLiteral); - Assert.assertEquals("{\"1\":null}", mapLiteral9.getStringValueInFe()); + Assert.assertEquals("{1:null}", mapLiteral9.getStringValueInFe()); MapLiteral mapLiteral10 = new MapLiteral(intLiteral1, arrayLiteral); Assert.assertEquals("{\"1\":[\"1\", \"2.15\"]}", mapLiteral10.getStringValueForArray()); diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/StructLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/StructLiteralTest.java index b7f2577ad63..c48ad5d5785 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/StructLiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/StructLiteralTest.java @@ -86,9 +86,9 @@ public class StructLiteralTest { stringLiteral, largeIntLiteral, decimalLiteral1, decimalLiteral2, dateLiteral, datetimeLiteral); Assert.assertEquals("{\"col1\": 1, \"col2\": 2.15, \"col3\": \"11:22:33\", \"col4\": 1, \"col5\": " + "\"shortstring\", \"col6\": 1000000000000000000000, \"col7\": 1.0, \"col8\": 2, \"col9\": \"2022-10-10\", \"col10\": \"2022-10-10 12:10:10\"}", - structLiteral1.getStringValueInFe()); + structLiteral1.getStringValueInFe()); StructLiteral structLiteral2 = new StructLiteral(arrayLiteral, mapLiteral, structLiteral); - Assert.assertEquals("{\"col1\": [1.0, 2.15], \"col2\": {\"1\":2.15}, \"col3\": " + Assert.assertEquals("{\"col1\": [1.0, 2.15], \"col2\": {1:2.15}, \"col3\": " + "{\"col1\": 1, \"col2\": 2.15, \"col3\": 1.0, \"col4\": \"2022-10-10\"}}", structLiteral2.getStringValueInFe()); StructLiteral structLiteral3 = new StructLiteral(); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/LiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/LiteralTest.java index 842846bbd1b..fcb64ff0bfa 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/LiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/LiteralTest.java @@ -17,15 +17,29 @@ package org.apache.doris.nereids.trees.expressions; +import org.apache.doris.nereids.trees.expressions.literal.ArrayLiteral; import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral; import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; +import org.apache.doris.nereids.types.ArrayType; +import org.apache.doris.nereids.types.DataType; +import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.StructField; +import org.apache.doris.nereids.types.StructType; +import org.apache.doris.proto.Types.PGenericType; +import org.apache.doris.proto.Types.PGenericType.TypeId; +import org.apache.doris.proto.Types.PValues; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + class LiteralTest { @Test @@ -42,4 +56,255 @@ class LiteralTest { Assertions.assertTrue(Literal.of(1) instanceof IntegerLiteral); Assertions.assertTrue(Literal.of(false) instanceof BooleanLiteral); } + + @Test + public void testGetResultExpressionArrayInt() { + int num = 10; + Integer[] elementsArray = new Integer[num]; + for (int i = 0; i < elementsArray.length; ++i) { + elementsArray[i] = i; + } + DataType arrayType = ArrayType.of(IntegerType.INSTANCE, true); + PGenericType.Builder childTypeBuilder = PGenericType.newBuilder(); + childTypeBuilder.setId(TypeId.INT32); + PGenericType.Builder typeBuilder = PGenericType.newBuilder(); + typeBuilder.setId(TypeId.LIST); + + PValues.Builder childBuilder = PValues.newBuilder(); + PValues.Builder resultContentBuilder = PValues.newBuilder(); + for (int value : elementsArray) { + childBuilder.addInt32Value(value); + } + childBuilder.setType(childTypeBuilder.build()); + PValues childValues = childBuilder.build(); + resultContentBuilder.setType(typeBuilder.build()); + resultContentBuilder.addChildElement(childValues); + resultContentBuilder.addChildOffset(10); + PValues resultContent = resultContentBuilder.build(); + List<Literal> resultExpression + = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE.getResultExpression(arrayType, + resultContent); + Assertions.assertTrue(resultExpression.get(0).isLiteral()); + } + + @Test + public void testGetResultExpressionArrayArrayInt() { + int num = 10; + Integer[] elementsArray = new Integer[num]; + for (int i = 0; i < elementsArray.length; ++i) { + elementsArray[i] = i; + } + DataType nestedArrayType = ArrayType.of(IntegerType.INSTANCE, true); + DataType outArrayType = ArrayType.of(nestedArrayType, true); + PGenericType.Builder childTypeBuilder = PGenericType.newBuilder(); + childTypeBuilder.setId(TypeId.INT32); + PGenericType.Builder typeBuilder = PGenericType.newBuilder(); + typeBuilder.setId(TypeId.LIST); + PGenericType.Builder outTypeBuilder = PGenericType.newBuilder(); + outTypeBuilder.setId(TypeId.LIST); + + PValues.Builder childBuilder = PValues.newBuilder(); + PValues.Builder nestedContentBuilder = PValues.newBuilder(); + PValues.Builder outContentBuilder = PValues.newBuilder(); + for (int value : elementsArray) { + childBuilder.addInt32Value(value); + } + childBuilder.setType(childTypeBuilder.build()); + PValues childValues = childBuilder.build(); + nestedContentBuilder.setType(typeBuilder.build()); + nestedContentBuilder.addChildElement(childValues); + nestedContentBuilder.addChildOffset(10); + PValues nestedResultContent = nestedContentBuilder.build(); + outContentBuilder.setType(outTypeBuilder.build()); + outContentBuilder.addChildElement(nestedResultContent); + outContentBuilder.addChildOffset(1); + PValues resultContent = outContentBuilder.build(); + List<Literal> resultExpression + = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE.getResultExpression(outArrayType, + resultContent); + // [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] + Assertions.assertTrue(resultExpression.get(0) instanceof ArrayLiteral); + System.out.println(resultExpression.get(0).toString()); + } + + @Test + public void testGetResultExpressionArrayArrayInt2() { + int num = 10; + Integer[] elementsArray = new Integer[num]; + for (int i = 0; i < elementsArray.length; ++i) { + elementsArray[i] = i; + } + DataType nestedArrayType = ArrayType.of(IntegerType.INSTANCE, true); + DataType outArrayType = ArrayType.of(nestedArrayType, true); + PGenericType.Builder childTypeBuilder = PGenericType.newBuilder(); + childTypeBuilder.setId(TypeId.INT32); + PGenericType.Builder typeBuilder = PGenericType.newBuilder(); + typeBuilder.setId(TypeId.LIST); + PGenericType.Builder outTypeBuilder = PGenericType.newBuilder(); + outTypeBuilder.setId(TypeId.LIST); + + PValues.Builder childBuilder1 = PValues.newBuilder(); + PValues.Builder childBuilder2 = PValues.newBuilder(); + PValues.Builder nestedContentBuilder = PValues.newBuilder(); + PValues.Builder outContentBuilder = PValues.newBuilder(); + for (int i = 0; i < elementsArray.length; i = i + 2) { + childBuilder1.addInt32Value(elementsArray[i]); + childBuilder2.addInt32Value(elementsArray[i + 1]); + } + childBuilder1.setType(childTypeBuilder.build()); + childBuilder2.setType(childTypeBuilder.build()); + PValues childValues1 = childBuilder1.build(); + PValues childValues2 = childBuilder2.build(); + nestedContentBuilder.setType(typeBuilder.build()); + nestedContentBuilder.addChildElement(childValues1); + nestedContentBuilder.addChildElement(childValues2); + nestedContentBuilder.addChildOffset(5); + nestedContentBuilder.addChildOffset(10); + PValues nestedResultContent = nestedContentBuilder.build(); + outContentBuilder.setType(outTypeBuilder.build()); + outContentBuilder.addChildElement(nestedResultContent); + outContentBuilder.addChildOffset(2); + PValues resultContent = outContentBuilder.build(); + List<Literal> resultExpression + = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE.getResultExpression(outArrayType, + resultContent); + // [[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]] + Assertions.assertTrue(resultExpression.get(0) instanceof ArrayLiteral); + System.out.println(resultExpression.get(0).toString()); + } + + @Test + public void testGetResultExpressionArrayNull() { + int num = 10; + Integer[] elementsArray = new Integer[num]; + Boolean[] nullMap = new Boolean[num]; + for (int i = 0; i < elementsArray.length; ++i) { + elementsArray[i] = i; + nullMap[i] = (i % 2 == 1); + } + DataType arrayType = ArrayType.of(IntegerType.INSTANCE, true); + PGenericType.Builder childTypeBuilder = PGenericType.newBuilder(); + childTypeBuilder.setId(TypeId.INT32); + PGenericType.Builder typeBuilder = PGenericType.newBuilder(); + typeBuilder.setId(TypeId.LIST); + + PValues.Builder childBuilder = PValues.newBuilder(); + PValues.Builder resultContentBuilder = PValues.newBuilder(); + for (int value : elementsArray) { + childBuilder.addInt32Value(value); + } + childBuilder.setType(childTypeBuilder.build()); + childBuilder.setHasNull(true); + childBuilder.addAllNullMap(Arrays.asList(nullMap)); + PValues childValues = childBuilder.build(); + resultContentBuilder.setType(typeBuilder.build()); + resultContentBuilder.addChildElement(childValues); + resultContentBuilder.addChildOffset(10); + PValues resultContent = resultContentBuilder.build(); + List<Literal> resultExpression + = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE.getResultExpression(arrayType, + resultContent); + // [0, NULL, 2, NULL, 4, NULL, 6, NULL, 8, NULL] + Assertions.assertTrue(resultExpression.get(0).isLiteral()); + System.out.println(resultExpression.get(0).toString()); + } + + @Test + public void testGetResultExpressionStruct() { + int num = 10; + Integer[] elementsArray = new Integer[num]; + for (int i = 0; i < elementsArray.length; ++i) { + elementsArray[i] = i; + } + List<StructField> typeFields = new ArrayList<>(); + typeFields.add(new StructField("col1", IntegerType.INSTANCE, true, "comment1")); + typeFields.add(new StructField("col2", StringType.INSTANCE, true, "comment1")); + + DataType structType = new StructType(typeFields); + PGenericType.Builder childTypeBuilder1 = PGenericType.newBuilder(); + childTypeBuilder1.setId(TypeId.INT32); + PGenericType.Builder childTypeBuilder2 = PGenericType.newBuilder(); + childTypeBuilder2.setId(TypeId.STRING); + PGenericType.Builder typeBuilder = PGenericType.newBuilder(); + typeBuilder.setId(TypeId.STRUCT); + + PValues.Builder childBuilder1 = PValues.newBuilder(); + PValues.Builder childBuilder2 = PValues.newBuilder(); + PValues.Builder resultContentBuilder = PValues.newBuilder(); + for (int i = 0; i < elementsArray.length; i = i + 2) { + childBuilder1.addInt32Value(elementsArray[i]); + childBuilder2.addStringValue("str" + (i + 1)); + } + childBuilder1.setType(childTypeBuilder1.build()); + childBuilder2.setType(childTypeBuilder2.build()); + PValues childValues1 = childBuilder1.build(); + PValues childValues2 = childBuilder2.build(); + + resultContentBuilder.setType(typeBuilder.build()); + resultContentBuilder.addChildElement(childValues1); + resultContentBuilder.addChildElement(childValues2); + PValues resultContent = resultContentBuilder.build(); + List<Literal> resultExpression + = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE.getResultExpression(structType, + resultContent); + Assertions.assertTrue(resultExpression.get(0).isLiteral()); + // STRUCT('col1':0,'col2':'str1') + System.out.println(resultExpression.get(0).toString()); + } + + @Test + public void testGetResultExpressionStructArray() { + int num = 10; + Integer[] elementsArray = new Integer[num]; + for (int i = 0; i < elementsArray.length; ++i) { + elementsArray[i] = i; + } + List<StructField> typeFields = new ArrayList<>(); + typeFields.add(new StructField("col1", ArrayType.of(IntegerType.INSTANCE), true, "comment1")); + typeFields.add(new StructField("col2", ArrayType.of(StringType.INSTANCE), true, "comment1")); + + DataType structType = new StructType(typeFields); + PGenericType.Builder childTypeBuilder1 = PGenericType.newBuilder(); + childTypeBuilder1.setId(TypeId.INT32); + PGenericType.Builder childTypeBuilder2 = PGenericType.newBuilder(); + childTypeBuilder2.setId(TypeId.STRING); + PGenericType.Builder childTypeBuilder3 = PGenericType.newBuilder(); + childTypeBuilder3.setId(TypeId.LIST); + PGenericType.Builder typeBuilder = PGenericType.newBuilder(); + typeBuilder.setId(TypeId.STRUCT); + + PValues.Builder childBuilder1 = PValues.newBuilder(); + PValues.Builder childBuilder2 = PValues.newBuilder(); + PValues.Builder arrayChildBuilder1 = PValues.newBuilder(); + PValues.Builder arrayChildBuilder2 = PValues.newBuilder(); + PValues.Builder resultContentBuilder = PValues.newBuilder(); + for (int i = 0; i < elementsArray.length; i = i + 2) { + childBuilder1.addInt32Value(elementsArray[i]); + childBuilder2.addStringValue("str" + (i + 1)); + } + childBuilder1.setType(childTypeBuilder1.build()); + childBuilder2.setType(childTypeBuilder2.build()); + arrayChildBuilder1.setType(childTypeBuilder3.build()); + arrayChildBuilder2.setType(childTypeBuilder3.build()); + + PValues childValues1 = childBuilder1.build(); + PValues childValues2 = childBuilder2.build(); + arrayChildBuilder1.addChildElement(childValues1); + arrayChildBuilder1.addChildOffset(5); + arrayChildBuilder2.addChildElement(childValues2); + arrayChildBuilder2.addChildOffset(5); + PValues arrayChildValues1 = arrayChildBuilder1.build(); + PValues arrayChildValues2 = arrayChildBuilder2.build(); + + resultContentBuilder.setType(typeBuilder.build()); + resultContentBuilder.addChildElement(arrayChildValues1); + resultContentBuilder.addChildElement(arrayChildValues2); + PValues resultContent = resultContentBuilder.build(); + List<Literal> resultExpression + = org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnBE.getResultExpression(structType, + resultContent); + Assertions.assertTrue(resultExpression.get(0).isLiteral()); + // STRUCT('col1':[0, 2, 4, 6, 8],'col2':['str1', 'str3', 'str5', 'str7', 'str9']) + System.out.println(resultExpression.get(0).toString()); + } } diff --git a/gensrc/thrift/PaloInternalService.thrift b/gensrc/thrift/PaloInternalService.thrift index 97bd7f5552e..b71ddfa21a3 100644 --- a/gensrc/thrift/PaloInternalService.thrift +++ b/gensrc/thrift/PaloInternalService.thrift @@ -548,6 +548,7 @@ struct TFoldConstantParams { 3: optional bool vec_exec 4: optional TQueryOptions query_options 5: optional Types.TUniqueId query_id + 6: optional bool is_nereids } // TransmitData diff --git a/regression-test/suites/nereids_rules_p0/filter_push_down/push_filter_inside_join.groovy b/regression-test/suites/nereids_rules_p0/filter_push_down/push_filter_inside_join.groovy index 97fdc1c0b4f..cd8ed1a25a0 100644 --- a/regression-test/suites/nereids_rules_p0/filter_push_down/push_filter_inside_join.groovy +++ b/regression-test/suites/nereids_rules_p0/filter_push_down/push_filter_inside_join.groovy @@ -23,6 +23,7 @@ suite("push_filter_inside_join") { sql "SET ignore_shape_nodes='PhysicalDistribute,PhysicalProject'" sql "SET disable_join_reorder=true" sql 'set be_number_for_test=3' + sql "set enable_fold_constant_by_be=false"//plan shape will be different // Push down > condition to cross join qt_pushdown_cross_join""" diff --git a/regression-test/suites/nereids_rules_p0/filter_push_down/push_filter_through.groovy b/regression-test/suites/nereids_rules_p0/filter_push_down/push_filter_through.groovy index 16c06b8edd9..d084d3240da 100644 --- a/regression-test/suites/nereids_rules_p0/filter_push_down/push_filter_through.groovy +++ b/regression-test/suites/nereids_rules_p0/filter_push_down/push_filter_through.groovy @@ -24,6 +24,7 @@ suite("push_filter_through") { sql 'set be_number_for_test=3' sql "SET ignore_shape_nodes='PhysicalDistribute, PhysicalProject'" sql "set enable_fold_nondeterministic_fn=false" + sql "set enable_fold_constant_by_be=false"//plan shape will be different // push filter through alias qt_filter_project_alias""" --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org