github-actions[bot] commented on code in PR #61165: URL: https://github.com/apache/doris/pull/61165#discussion_r2909670422
########## fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToThriftVisitor.java: ########## @@ -0,0 +1,799 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.analysis; + +import org.apache.doris.analysis.ArithmeticExpr.Operator; +import org.apache.doris.catalog.ArrayType; +import org.apache.doris.catalog.ScalarType; +import org.apache.doris.catalog.StructType; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.ErrorCode; +import org.apache.doris.common.ErrorReport; +import org.apache.doris.nereids.trees.expressions.functions.scalar.SearchDslParser; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.thrift.TBoolLiteral; +import org.apache.doris.thrift.TCaseExpr; +import org.apache.doris.thrift.TColumnRef; +import org.apache.doris.thrift.TDateLiteral; +import org.apache.doris.thrift.TDecimalLiteral; +import org.apache.doris.thrift.TExpr; +import org.apache.doris.thrift.TExprNode; +import org.apache.doris.thrift.TExprNodeType; +import org.apache.doris.thrift.TExprOpcode; +import org.apache.doris.thrift.TFloatLiteral; +import org.apache.doris.thrift.TIPv4Literal; +import org.apache.doris.thrift.TIPv6Literal; +import org.apache.doris.thrift.TInPredicate; +import org.apache.doris.thrift.TInfoFunc; +import org.apache.doris.thrift.TIntLiteral; +import org.apache.doris.thrift.TJsonLiteral; +import org.apache.doris.thrift.TLargeIntLiteral; +import org.apache.doris.thrift.TMatchPredicate; +import org.apache.doris.thrift.TSearchClause; +import org.apache.doris.thrift.TSearchFieldBinding; +import org.apache.doris.thrift.TSearchOccur; +import org.apache.doris.thrift.TSearchParam; +import org.apache.doris.thrift.TSlotRef; +import org.apache.doris.thrift.TStringLiteral; +import org.apache.doris.thrift.TTimeV2Literal; +import org.apache.doris.thrift.TTypeDesc; +import org.apache.doris.thrift.TTypeNode; +import org.apache.doris.thrift.TVarBinaryLiteral; + +import com.google.common.collect.Lists; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Visitor that converts any {@link Expr} node into its Thrift {@link TExprNode} + * representation. Replaces the per-subclass {@code toThrift(TExprNode)} methods. + * + * <p>Usage: {@code ExprToThriftVisitor.treeToThrift(expr)} or + * {@code expr.accept(ExprToThriftVisitor.INSTANCE, texprNode)}. + */ +public class ExprToThriftVisitor extends ExprVisitor<Void, TExprNode> { + private static final Logger LOG = LogManager.getLogger(ExprToThriftVisitor.class); + + public static final ExprToThriftVisitor INSTANCE = new ExprToThriftVisitor(); + + protected ExprToThriftVisitor() { + } + + // ----------------------------------------------------------------------- + // Static utility methods (moved from Expr.java) + // ----------------------------------------------------------------------- + + public static TExpr treeToThrift(Expr expr) { + TExpr result = new TExpr(); + treeToThriftHelper(expr, result, INSTANCE); + return result; + } + + public static List<TExpr> treesToThrift(List<? extends Expr> exprs) { + List<TExpr> result = Lists.newArrayList(); + for (Expr expr : exprs) { + result.add(treeToThrift(expr)); + } + return result; + } + + /** + * Append a flattened version of {@code expr} (including all children) + * to {@code container}, using the given visitor for per-node conversion. + */ + public static void treeToThriftHelper(Expr expr, TExpr container, + ExprVisitor<Void, TExprNode> visitor) { + // CastExpr no-op: skip the cast and serialize the child directly + if (expr instanceof CastExpr && ((CastExpr) expr).isNoOp()) { + treeToThriftHelper(expr.getChild(0), container, visitor); + return; + } + + TExprNode msg = new TExprNode(); + msg.type = expr.getType().toThrift(); + msg.num_children = expr.getChildren().size(); + if (expr.getFn() != null) { + msg.setFn(expr.getFn().toThrift( + expr.getType(), expr.collectChildReturnTypes(), expr.collectChildReturnNullables())); + if (expr.getFn().hasVarArgs()) { + msg.setVarargStartIdx(expr.getFn().getNumArgs() - 1); + } + } + msg.output_scale = -1; + msg.setIsNullable(expr.isNullable()); + + expr.accept(visitor, msg); + container.addToNodes(msg); + + for (Expr child : expr.getChildren()) { + treeToThriftHelper(child, container, visitor); + } + } + + @Override + public Void visit(Expr expr, TExprNode msg) { + throw new UnsupportedOperationException( + "ExprToThriftVisitor does not support Expr type: " + expr.getClass().getSimpleName()); + } + + // ----------------------------------------------------------------------- + // Literals + // ----------------------------------------------------------------------- + + @Override + public Void visitBoolLiteral(BoolLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.BOOL_LITERAL; + msg.bool_literal = new TBoolLiteral(expr.getValue()); + return null; + } + + @Override + public Void visitStringLiteral(StringLiteral expr, TExprNode msg) { + if (expr.getValue() == null) { + msg.node_type = TExprNodeType.NULL_LITERAL; + } else { + msg.string_literal = new TStringLiteral(expr.getValue()); + msg.node_type = TExprNodeType.STRING_LITERAL; + } + return null; + } + + @Override + public Void visitIntLiteral(IntLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.INT_LITERAL; + msg.int_literal = new TIntLiteral(expr.getValue()); + return null; + } + + @Override + public Void visitLargeIntLiteral(LargeIntLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.LARGE_INT_LITERAL; + msg.large_int_literal = new TLargeIntLiteral(expr.getStringValue()); + return null; + } + + @Override + public Void visitFloatLiteral(FloatLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.FLOAT_LITERAL; + msg.float_literal = new TFloatLiteral(expr.getValue()); + return null; + } + + @Override + public Void visitDecimalLiteral(DecimalLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.DECIMAL_LITERAL; + msg.decimal_literal = new TDecimalLiteral(expr.getStringValue()); + return null; + } + + @Override + public Void visitDateLiteral(DateLiteral expr, TExprNode msg) { + if (expr.getType().isDatetimeV2() || expr.getType().isTimeStampTz()) { + expr.roundFloor(((ScalarType) expr.getType()).getScalarScale()); + } + msg.node_type = TExprNodeType.DATE_LITERAL; + msg.date_literal = new TDateLiteral(expr.getStringValue()); + try { + expr.checkValueValid(); + } catch (AnalysisException e) { + LOG.warn("meet invalid value when plan to translate " + expr.toString() + " to thrift node"); + } + return null; + } + + @Override + public Void visitTimeV2Literal(TimeV2Literal expr, TExprNode msg) { + msg.node_type = TExprNodeType.TIMEV2_LITERAL; + msg.timev2_literal = new TTimeV2Literal(expr.getValue()); + return null; + } + + @Override + public Void visitNullLiteral(NullLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.NULL_LITERAL; + return null; + } + + @Override + public Void visitMaxLiteral(MaxLiteral expr, TExprNode msg) { + // TODO: complete this type + return null; Review Comment: nit (pre-existing): `visitMaxLiteral` returns without setting `msg.node_type`, leaving the `TExprNode` in an invalid state. The old `MaxLiteral.toThrift()` had the same TODO. Since this is a new file, might be worth adding a `DORIS_CHECK` or at minimum a more prominent TODO that this will cause a Thrift serialization error if MaxLiteral is ever actually serialized. ########## fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToThriftVisitor.java: ########## @@ -0,0 +1,799 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.analysis; + +import org.apache.doris.analysis.ArithmeticExpr.Operator; +import org.apache.doris.catalog.ArrayType; +import org.apache.doris.catalog.ScalarType; +import org.apache.doris.catalog.StructType; +import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.ErrorCode; +import org.apache.doris.common.ErrorReport; +import org.apache.doris.nereids.trees.expressions.functions.scalar.SearchDslParser; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.thrift.TBoolLiteral; +import org.apache.doris.thrift.TCaseExpr; +import org.apache.doris.thrift.TColumnRef; +import org.apache.doris.thrift.TDateLiteral; +import org.apache.doris.thrift.TDecimalLiteral; +import org.apache.doris.thrift.TExpr; +import org.apache.doris.thrift.TExprNode; +import org.apache.doris.thrift.TExprNodeType; +import org.apache.doris.thrift.TExprOpcode; +import org.apache.doris.thrift.TFloatLiteral; +import org.apache.doris.thrift.TIPv4Literal; +import org.apache.doris.thrift.TIPv6Literal; +import org.apache.doris.thrift.TInPredicate; +import org.apache.doris.thrift.TInfoFunc; +import org.apache.doris.thrift.TIntLiteral; +import org.apache.doris.thrift.TJsonLiteral; +import org.apache.doris.thrift.TLargeIntLiteral; +import org.apache.doris.thrift.TMatchPredicate; +import org.apache.doris.thrift.TSearchClause; +import org.apache.doris.thrift.TSearchFieldBinding; +import org.apache.doris.thrift.TSearchOccur; +import org.apache.doris.thrift.TSearchParam; +import org.apache.doris.thrift.TSlotRef; +import org.apache.doris.thrift.TStringLiteral; +import org.apache.doris.thrift.TTimeV2Literal; +import org.apache.doris.thrift.TTypeDesc; +import org.apache.doris.thrift.TTypeNode; +import org.apache.doris.thrift.TVarBinaryLiteral; + +import com.google.common.collect.Lists; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Visitor that converts any {@link Expr} node into its Thrift {@link TExprNode} + * representation. Replaces the per-subclass {@code toThrift(TExprNode)} methods. + * + * <p>Usage: {@code ExprToThriftVisitor.treeToThrift(expr)} or + * {@code expr.accept(ExprToThriftVisitor.INSTANCE, texprNode)}. + */ +public class ExprToThriftVisitor extends ExprVisitor<Void, TExprNode> { + private static final Logger LOG = LogManager.getLogger(ExprToThriftVisitor.class); + + public static final ExprToThriftVisitor INSTANCE = new ExprToThriftVisitor(); + + protected ExprToThriftVisitor() { + } + + // ----------------------------------------------------------------------- + // Static utility methods (moved from Expr.java) + // ----------------------------------------------------------------------- + + public static TExpr treeToThrift(Expr expr) { + TExpr result = new TExpr(); + treeToThriftHelper(expr, result, INSTANCE); + return result; + } + + public static List<TExpr> treesToThrift(List<? extends Expr> exprs) { + List<TExpr> result = Lists.newArrayList(); + for (Expr expr : exprs) { + result.add(treeToThrift(expr)); + } + return result; + } + + /** + * Append a flattened version of {@code expr} (including all children) + * to {@code container}, using the given visitor for per-node conversion. + */ + public static void treeToThriftHelper(Expr expr, TExpr container, + ExprVisitor<Void, TExprNode> visitor) { + // CastExpr no-op: skip the cast and serialize the child directly + if (expr instanceof CastExpr && ((CastExpr) expr).isNoOp()) { + treeToThriftHelper(expr.getChild(0), container, visitor); + return; + } + + TExprNode msg = new TExprNode(); + msg.type = expr.getType().toThrift(); + msg.num_children = expr.getChildren().size(); + if (expr.getFn() != null) { + msg.setFn(expr.getFn().toThrift( + expr.getType(), expr.collectChildReturnTypes(), expr.collectChildReturnNullables())); + if (expr.getFn().hasVarArgs()) { + msg.setVarargStartIdx(expr.getFn().getNumArgs() - 1); + } + } + msg.output_scale = -1; + msg.setIsNullable(expr.isNullable()); + + expr.accept(visitor, msg); + container.addToNodes(msg); + + for (Expr child : expr.getChildren()) { + treeToThriftHelper(child, container, visitor); + } + } + + @Override + public Void visit(Expr expr, TExprNode msg) { + throw new UnsupportedOperationException( + "ExprToThriftVisitor does not support Expr type: " + expr.getClass().getSimpleName()); + } + + // ----------------------------------------------------------------------- + // Literals + // ----------------------------------------------------------------------- + + @Override + public Void visitBoolLiteral(BoolLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.BOOL_LITERAL; + msg.bool_literal = new TBoolLiteral(expr.getValue()); + return null; + } + + @Override + public Void visitStringLiteral(StringLiteral expr, TExprNode msg) { + if (expr.getValue() == null) { + msg.node_type = TExprNodeType.NULL_LITERAL; + } else { + msg.string_literal = new TStringLiteral(expr.getValue()); + msg.node_type = TExprNodeType.STRING_LITERAL; + } + return null; + } + + @Override + public Void visitIntLiteral(IntLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.INT_LITERAL; + msg.int_literal = new TIntLiteral(expr.getValue()); + return null; + } + + @Override + public Void visitLargeIntLiteral(LargeIntLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.LARGE_INT_LITERAL; + msg.large_int_literal = new TLargeIntLiteral(expr.getStringValue()); + return null; + } + + @Override + public Void visitFloatLiteral(FloatLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.FLOAT_LITERAL; + msg.float_literal = new TFloatLiteral(expr.getValue()); + return null; + } + + @Override + public Void visitDecimalLiteral(DecimalLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.DECIMAL_LITERAL; + msg.decimal_literal = new TDecimalLiteral(expr.getStringValue()); + return null; + } + + @Override + public Void visitDateLiteral(DateLiteral expr, TExprNode msg) { + if (expr.getType().isDatetimeV2() || expr.getType().isTimeStampTz()) { + expr.roundFloor(((ScalarType) expr.getType()).getScalarScale()); + } + msg.node_type = TExprNodeType.DATE_LITERAL; + msg.date_literal = new TDateLiteral(expr.getStringValue()); + try { + expr.checkValueValid(); + } catch (AnalysisException e) { + LOG.warn("meet invalid value when plan to translate " + expr.toString() + " to thrift node"); + } + return null; + } + + @Override + public Void visitTimeV2Literal(TimeV2Literal expr, TExprNode msg) { + msg.node_type = TExprNodeType.TIMEV2_LITERAL; + msg.timev2_literal = new TTimeV2Literal(expr.getValue()); + return null; + } + + @Override + public Void visitNullLiteral(NullLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.NULL_LITERAL; + return null; + } + + @Override + public Void visitMaxLiteral(MaxLiteral expr, TExprNode msg) { + // TODO: complete this type + return null; + } + + @Override + public Void visitJsonLiteral(JsonLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.JSON_LITERAL; + msg.json_literal = new TJsonLiteral(expr.getUnescapedValue()); + return null; + } + + @Override + public Void visitIPv4Literal(IPv4Literal expr, TExprNode msg) { + msg.node_type = TExprNodeType.IPV4_LITERAL; + msg.ipv4_literal = new TIPv4Literal(expr.getValue()); + return null; + } + + @Override + public Void visitIPv6Literal(IPv6Literal expr, TExprNode msg) { + msg.node_type = TExprNodeType.IPV6_LITERAL; + msg.ipv6_literal = new TIPv6Literal(expr.getValue()); + return null; + } + + @Override + public Void visitVarBinaryLiteral(VarBinaryLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.VARBINARY_LITERAL; + msg.varbinary_literal = new TVarBinaryLiteral(ByteBuffer.wrap(expr.getValue())); + return null; + } + + @Override + public Void visitArrayLiteral(ArrayLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.ARRAY_LITERAL; + msg.setChildType(((ArrayType) expr.getType()).getItemType().getPrimitiveType().toThrift()); + return null; + } + + @Override + public Void visitMapLiteral(MapLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.MAP_LITERAL; + TTypeDesc container = new TTypeDesc(); + container.setTypes(new ArrayList<TTypeNode>()); + expr.getType().toThrift(container); + msg.setType(container); + return null; + } + + @Override + public Void visitStructLiteral(StructLiteral expr, TExprNode msg) { + msg.node_type = TExprNodeType.STRUCT_LITERAL; + ((StructType) expr.getType()).getFields() + .forEach(v -> msg.setChildType(v.getType().getPrimitiveType().toThrift())); + TTypeDesc container = new TTypeDesc(); + container.setTypes(new ArrayList<TTypeNode>()); + expr.getType().toThrift(container); + msg.setType(container); + return null; + } + + @Override + public Void visitPlaceHolderExpr(PlaceHolderExpr expr, TExprNode msg) { + expr.getLiteral().accept(this, msg); + return null; + } + + // ----------------------------------------------------------------------- + // Reference / slot expressions + // ----------------------------------------------------------------------- + + @Override + public Void visitSlotRef(SlotRef expr, TExprNode msg) { + msg.node_type = TExprNodeType.SLOT_REF; + msg.slot_ref = new TSlotRef(expr.getDesc().getId().asInt(), expr.getDesc().getParent().getId().asInt()); + msg.slot_ref.setColUniqueId(expr.getDesc().getUniqueId()); + msg.slot_ref.setIsVirtualSlot(expr.getDesc().getVirtualColumn() != null); + msg.setLabel(expr.getLabel()); + return null; + } + + @Override + public Void visitColumnRefExpr(ColumnRefExpr expr, TExprNode msg) { + msg.node_type = TExprNodeType.COLUMN_REF; + TColumnRef columnRef = new TColumnRef(); + columnRef.setColumnId(expr.getColumnId()); + columnRef.setColumnName(expr.getName()); + msg.column_ref = columnRef; + return null; + } + + @Override + public Void visitInformationFunction(InformationFunction expr, TExprNode msg) { + msg.node_type = TExprNodeType.INFO_FUNC; + msg.info_func = new TInfoFunc(Long.parseLong(expr.getIntValue()), expr.getStrValue()); + return null; + } + + @Override + public Void visitEncryptKeyRef(EncryptKeyRef expr, TExprNode msg) { + // no operation + return null; + } + + @Override + public Void visitVariableExpr(VariableExpr expr, TExprNode msg) { + switch (expr.getType().getPrimitiveType()) { + case BOOLEAN: + msg.node_type = TExprNodeType.BOOL_LITERAL; + msg.bool_literal = new TBoolLiteral(expr.getBoolValue()); + break; + case TINYINT: + case SMALLINT: + case INT: + case BIGINT: + msg.node_type = TExprNodeType.INT_LITERAL; + msg.int_literal = new TIntLiteral(expr.getIntValue()); + break; + case FLOAT: + case DOUBLE: + msg.node_type = TExprNodeType.FLOAT_LITERAL; + msg.float_literal = new TFloatLiteral(expr.getFloatValue()); + break; + default: + if (expr.getStrValue() == null) { + msg.node_type = TExprNodeType.NULL_LITERAL; + } else { + msg.node_type = TExprNodeType.STRING_LITERAL; + msg.string_literal = new TStringLiteral(expr.getStrValue()); + } + } + return null; + } + + // ----------------------------------------------------------------------- + // Predicates + // ----------------------------------------------------------------------- + + @Override + public Void visitBinaryPredicate(BinaryPredicate expr, TExprNode msg) { + msg.node_type = TExprNodeType.BINARY_PRED; + msg.setOpcode(toThriftOpcode(expr.getOp())); + msg.setChildType(expr.getChild(0).getType().getPrimitiveType().toThrift()); + return null; + } + + @Override + public Void visitIsNullPredicate(IsNullPredicate expr, TExprNode msg) { + msg.node_type = TExprNodeType.FUNCTION_CALL; + return null; + } + + @Override + public Void visitCompoundPredicate(CompoundPredicate expr, TExprNode msg) { + msg.node_type = TExprNodeType.COMPOUND_PRED; + msg.setOpcode(toThriftOpcode(expr.getOp())); + return null; + } + + @Override + public Void visitInPredicate(InPredicate expr, TExprNode msg) { + msg.in_predicate = new TInPredicate(expr.isNotIn()); + msg.node_type = TExprNodeType.IN_PRED; + msg.setOpcode(toThriftOpcode(expr)); + return null; + } + + @Override + public Void visitLikePredicate(LikePredicate expr, TExprNode msg) { + msg.node_type = TExprNodeType.FUNCTION_CALL; + return null; + } + + @Override + public Void visitMatchPredicate(MatchPredicate expr, TExprNode msg) { + msg.node_type = TExprNodeType.MATCH_PRED; + msg.setOpcode(toThriftOpcode(expr.getOp())); + msg.match_predicate = new TMatchPredicate( + expr.getInvertedIndexParser(), expr.getInvertedIndexParserMode()); + msg.match_predicate.setCharFilterMap(expr.getInvertedIndexCharFilter()); + msg.match_predicate.setParserLowercase(expr.getInvertedIndexParserLowercase()); + msg.match_predicate.setParserStopwords(expr.getInvertedIndexParserStopwords()); + msg.match_predicate.setAnalyzerName(expr.getInvertedIndexAnalyzerName()); + return null; + } + + @Override + public Void visitBetweenPredicate(BetweenPredicate expr, TExprNode msg) { + throw new IllegalStateException( + "BetweenPredicate needs to be rewritten into a CompoundPredicate."); + } + + @Override + public Void visitSearchPredicate(SearchPredicate expr, TExprNode msg) { + msg.node_type = TExprNodeType.SEARCH_EXPR; + msg.setSearchParam(buildSearchThriftParam(expr)); + + LOG.info("SearchPredicate.toThrift: dsl='{}', num_children_in_base={}, children_size={}", + expr.getDslString(), msg.num_children, expr.getChildren().size()); Review Comment: nit (pre-existing): These `LOG.info` calls fire on **every query** that uses search predicates. This was the same in the old `SearchPredicate.toThrift()`, but since we're doing a clean extraction, this would be a good opportunity to downgrade them to `LOG.debug` (or guard with `if (LOG.isDebugEnabled())`). Same applies to the LOG.info calls in `buildSearchThriftParam()` below (lines ~650-668). Not a blocker for this PR since it's a faithful migration of existing behavior. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
