This is an automated email from the ASF dual-hosted git repository. lihaopeng pushed a commit to branch branch-1.2-lts in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-1.2-lts by this push: new 2ebe5ef5cf [fix](fe)project should be done inside subquery (#18012) 2ebe5ef5cf is described below commit 2ebe5ef5cf6c19e065ea77db2469d1b75474b1ec Author: starocean999 <40539150+starocean...@users.noreply.github.com> AuthorDate: Wed Mar 22 10:41:56 2023 +0800 [fix](fe)project should be done inside subquery (#18012) --- .../org/apache/doris/analysis/SlotDescriptor.java | 6 ++- .../org/apache/doris/planner/JoinNodeBase.java | 12 ++--- .../apache/doris/planner/NestedLoopJoinNode.java | 4 +- .../java/org/apache/doris/planner/ScanNode.java | 56 ++++++++++++++++++++++ .../java/org/apache/doris/planner/SelectNode.java | 3 +- 5 files changed, 71 insertions(+), 10 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java index f4a67fe167..b68ea31778 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java @@ -80,7 +80,7 @@ public class SlotDescriptor { this.isMultiRef = false; } - SlotDescriptor(SlotId id, TupleDescriptor parent, SlotDescriptor src) { + public SlotDescriptor(SlotId id, TupleDescriptor parent, SlotDescriptor src) { this.id = id; this.parent = parent; this.byteOffset = src.byteOffset; @@ -154,6 +154,10 @@ public class SlotDescriptor { this.originType = column.getOriginType(); } + public void setSrcColumn(Column column) { + this.column = column; + } + public boolean isMaterialized() { return isMaterialized; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/JoinNodeBase.java b/fe/fe-core/src/main/java/org/apache/doris/planner/JoinNodeBase.java index 5d81033362..21ef809f31 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/JoinNodeBase.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/JoinNodeBase.java @@ -593,19 +593,19 @@ public abstract class JoinNodeBase extends PlanNode { Lists.newArrayList(vSrcToOutputSMap.getLhs())); List<Expr> newRhs = Lists.newArrayList(); boolean bSmapChanged = false; - for (Expr expr : smap.getRhs()) { - if (expr instanceof SlotRef) { - newRhs.add(expr); + for (Expr rhsExpr : smap.getRhs()) { + if (rhsExpr instanceof SlotRef || !rhsExpr.isBound(vOutputTupleDesc.getId())) { + newRhs.add(rhsExpr); } else { // we need do project in the join node // add a new slot for projection result and add the project expr to vSrcToOutputSMap SlotDescriptor slotDesc = analyzer.addSlotDescriptor(vOutputTupleDesc); - slotDesc.initFromExpr(expr); + slotDesc.initFromExpr(rhsExpr); slotDesc.setIsMaterialized(true); // the project expr is from smap, which use the slots of hash join node's output tuple // we need substitute it to make sure the project expr use slots from intermediate tuple - expr.substitute(tmpSmap); - vSrcToOutputSMap.getLhs().add(expr); + rhsExpr = rhsExpr.substitute(tmpSmap); + vSrcToOutputSMap.getLhs().add(rhsExpr); SlotRef slotRef = new SlotRef(slotDesc); vSrcToOutputSMap.getRhs().add(slotRef); newRhs.add(slotRef); diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/NestedLoopJoinNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/NestedLoopJoinNode.java index 4f4f0dfded..421c534860 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/NestedLoopJoinNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/NestedLoopJoinNode.java @@ -70,8 +70,8 @@ public class NestedLoopJoinNode extends JoinNodeBase { public NestedLoopJoinNode(PlanNodeId id, PlanNode outer, PlanNode inner, TableRef innerRef) { super(id, "NESTED LOOP JOIN", StatisticalType.NESTED_LOOP_JOIN_NODE, outer, inner, innerRef); - tupleIds.addAll(outer.getTupleIds()); - tupleIds.addAll(inner.getTupleIds()); + tupleIds.addAll(outer.getOutputTupleIds()); + tupleIds.addAll(inner.getOutputTupleIds()); } public boolean canParallelize() { diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java index ac368176ed..5862667a06 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java @@ -24,14 +24,17 @@ import org.apache.doris.analysis.Analyzer; import org.apache.doris.analysis.BinaryPredicate; import org.apache.doris.analysis.CompoundPredicate; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprSubstitutionMap; import org.apache.doris.analysis.InPredicate; import org.apache.doris.analysis.IsNullPredicate; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.NullLiteral; import org.apache.doris.analysis.PredicateUtils; import org.apache.doris.analysis.SlotDescriptor; +import org.apache.doris.analysis.SlotId; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.TupleDescriptor; +import org.apache.doris.analysis.TupleId; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.common.UserException; @@ -52,6 +55,7 @@ import org.apache.logging.log4j.Logger; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** * Representation of the common elements of all scan nodes. @@ -478,4 +482,56 @@ public abstract class ScanNode extends PlanNode { desc.getTable().getName()).add("keyRanges", "").addValue( super.debugString()).toString(); } + + public void setOutputSmap(ExprSubstitutionMap smap, Analyzer analyzer) { + outputSmap = smap; + if (smap.getRhs().stream().anyMatch(expr -> !(expr instanceof SlotRef))) { + if (outputTupleDesc == null) { + outputTupleDesc = analyzer.getDescTbl().createTupleDescriptor("OlapScanNode"); + } + if (projectList == null) { + projectList = Lists.newArrayList(); + } + // setOutputSmap may be called multiple times + // this happens if the olap table is in the most inner sub-query block in the cascades sub-queries + // create a tmpSmap for the later setOutputSmap call + ExprSubstitutionMap tmpSmap = new ExprSubstitutionMap( + Lists.newArrayList(outputTupleDesc.getSlots().stream().map(slot -> new SlotRef(slot)).collect( + Collectors.toList())), Lists.newArrayList(projectList)); + Set<SlotId> allOutputSlotIds = outputTupleDesc.getSlots().stream().map(slot -> slot.getId()) + .collect(Collectors.toSet()); + List<Expr> newRhs = Lists.newArrayList(); + List<Expr> rhs = smap.getRhs(); + for (int i = 0; i < smap.size(); ++i) { + Expr rhsExpr = rhs.get(i); + if (!(rhsExpr instanceof SlotRef) || !(allOutputSlotIds.contains(((SlotRef) rhsExpr).getSlotId()))) { + rhsExpr = rhsExpr.substitute(tmpSmap); + if (rhsExpr.isBound(desc.getId())) { + SlotDescriptor slotDesc = analyzer.addSlotDescriptor(outputTupleDesc); + slotDesc.initFromExpr(rhsExpr); + if (rhsExpr instanceof SlotRef) { + slotDesc.setSrcColumn(((SlotRef) rhsExpr).getColumn()); + } + slotDesc.setIsMaterialized(true); + slotDesc.materializeSrcExpr(); + projectList.add(rhsExpr); + newRhs.add(new SlotRef(slotDesc)); + allOutputSlotIds.add(slotDesc.getId()); + } else { + newRhs.add(rhs.get(i)); + } + } else { + newRhs.add(rhsExpr); + } + } + outputSmap.updateRhsExprs(newRhs); + } + } + + public List<TupleId> getOutputTupleIds() { + if (outputTupleDesc != null) { + return Lists.newArrayList(outputTupleDesc.getId()); + } + return tupleIds; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/SelectNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/SelectNode.java index 2baa6e6f13..6d78b5cb48 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/SelectNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SelectNode.java @@ -32,6 +32,7 @@ import org.apache.doris.thrift.TPlanNodeType; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.ArrayList; import java.util.List; /** @@ -41,7 +42,7 @@ public class SelectNode extends PlanNode { private static final Logger LOG = LogManager.getLogger(SelectNode.class); protected SelectNode(PlanNodeId id, PlanNode child, List<Expr> conjuncts) { - super(id, child.getTupleIds(), "SELECT", StatisticalType.SELECT_NODE); + super(id, new ArrayList<>(child.getOutputTupleIds()), "SELECT", StatisticalType.SELECT_NODE); addChild(child); this.tblRefIds = child.tblRefIds; this.nullableTupleIds = child.nullableTupleIds; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org