This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-1.2-lts
in repository https://gitbox.apache.org/repos/asf/doris.git

commit bb9925e0e2ecf833a0674a054c3c9cf644613957
Author: yiguolei <[email protected]>
AuthorDate: Fri Jul 7 17:16:51 2023 +0800

    f
---
 .../apache/doris/analysis/ExprSubstitutionMap.java | 28 +++++++----
 .../org/apache/doris/planner/JoinNodeBase.java     | 58 ++++++++++++----------
 2 files changed, 51 insertions(+), 35 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprSubstitutionMap.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprSubstitutionMap.java
index 65f9d2f8e0..b8008fde77 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprSubstitutionMap.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprSubstitutionMap.java
@@ -33,11 +33,15 @@ import java.util.Objects;
 
 /**
  * Map of expression substitutions: lhs[i] gets substituted with rhs[i].
- * To support expression substitution across query blocks, rhs exprs must 
already be
- * analyzed when added to this map. Otherwise, analysis of a SlotRef may fail 
after
- * substitution, e.g., because the table it refers to is in a different query 
block
+ * To support expression substitution across query blocks, rhs exprs must
+ * already be
+ * analyzed when added to this map. Otherwise, analysis of a SlotRef may fail
+ * after
+ * substitution, e.g., because the table it refers to is in a different query
+ * block
  * that is not visible.
- * See Expr.substitute() and related functions for details on the actual 
substitution.
+ * See Expr.substitute() and related functions for details on the actual
+ * substitution.
  */
 public final class ExprSubstitutionMap {
     private static final Logger LOG = 
LogManager.getLogger(ExprSubstitutionMap.class);
@@ -62,7 +66,8 @@ public final class ExprSubstitutionMap {
     }
 
     /**
-     * Add an expr mapping. The rhsExpr must be analyzed to support correct 
substitution
+     * Add an expr mapping. The rhsExpr must be analyzed to support correct
+     * substitution
      * across query blocks. It is not required that the lhsExpr is analyzed.
      */
     public void put(Expr lhsExpr, Expr rhsExpr) {
@@ -132,7 +137,7 @@ public final class ExprSubstitutionMap {
     }
 
     /**
-     * Return a map  which is equivalent to applying f followed by g,
+     * Return a map which is equivalent to applying f followed by g,
      * i.e., g(f()).
      * Always returns a non-null map.
      */
@@ -208,7 +213,8 @@ public final class ExprSubstitutionMap {
 
     /**
      * Returns the replace of two substitution maps.
-     * f [A.id, B.id] [A.age, B.age] [A.name, B.name] g [A.id, C.id] [B.age, 
C.age] [A.address, C.address]
+     * f [A.id, B.id] [A.age, B.age] [A.name, B.name] g [A.id, C.id] [B.age, 
C.age]
+     * [A.address, C.address]
      * return: [A.id, C,id] [A.age, C.age] [A.name, B.name] [A.address, 
C.address]
      */
     public static ExprSubstitutionMap composeAndReplace(ExprSubstitutionMap f, 
ExprSubstitutionMap g, Analyzer analyzer)
@@ -304,11 +310,13 @@ public final class ExprSubstitutionMap {
     }
 
     /**
-     * Verifies the internal state of this smap: Checks that the lhs_ has no 
duplicates,
+     * Verifies the internal state of this smap: Checks that the lhs_ has no
+     * duplicates,
      * and that all rhs exprs are analyzed.
      */
     private void verify() {
-        // This method is very very time consuming, especially when planning 
large complex query.
+        // This method is very very time consuming, especially when planning 
large
+        // complex query.
         // So disable it by default.
         if (LOG.isDebugEnabled()) {
             for (int i = 0; i < lhs.size(); ++i) {
@@ -340,7 +348,7 @@ public final class ExprSubstitutionMap {
         Preconditions.checkState(lhs.size() == rhs.size(), "lhs and rhs must 
be same size");
         for (int i = 0; i < rhs.size(); i++) {
             if (rhs.get(i) instanceof SlotRef) {
-                ((SlotRef) 
rhs.get(i)).getDesc().setIsNullable(lhs.get(i).isNullable());
+                ((SlotRef) 
rhs.get(i)).getDesc().setIsNullable(lhs.get(i).isNullable() || ((SlotRef) 
rhs.get(i)).getDesc().getIsNullable());
             }
         }
     }
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 19921125e3..bdf5c0f161 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
@@ -158,21 +158,22 @@ public abstract class JoinNodeBase extends PlanNode {
         int leftNullableNumber = 0;
         int rightNullableNumber = 0;
         if (copyLeft) {
-            //cross join do not have OutputTblRefIds
+            // cross join do not have OutputTblRefIds
             List<TupleId> srcTupleIds = getChild(0) instanceof JoinNodeBase ? 
getChild(0).getOutputTupleIds()
                     : getChild(0).getOutputTblRefIds();
             for (TupleDescriptor leftTupleDesc : 
analyzer.getDescTbl().getTupleDesc(srcTupleIds)) {
-                // if the child is cross join node, the only way to get the 
correct nullable info of its output slots
+                // if the child is cross join node, the only way to get the 
correct nullable
+                // info of its output slots
                 // is to check if the output tuple ids are outer joined or not.
                 // then pass this nullable info to hash join node will be 
correct.
-                boolean needSetToNullable =
-                        getChild(0) instanceof JoinNodeBase && 
analyzer.isOuterJoined(leftTupleDesc.getId());
+                boolean needSetToNullable = getChild(0) instanceof JoinNodeBase
+                        && analyzer.isOuterJoined(leftTupleDesc.getId());
                 for (SlotDescriptor leftSlotDesc : leftTupleDesc.getSlots()) {
                     if (!isMaterializedByChild(leftSlotDesc, 
getChild(0).getOutputSmap())) {
                         continue;
                     }
-                    SlotDescriptor outputSlotDesc =
-                            
analyzer.getDescTbl().copySlotDescriptor(vOutputTupleDesc, leftSlotDesc);
+                    SlotDescriptor outputSlotDesc = 
analyzer.getDescTbl().copySlotDescriptor(vOutputTupleDesc,
+                            leftSlotDesc);
                     if (leftNullable) {
                         outputSlotDesc.setIsNullable(true);
                         leftNullableNumber++;
@@ -188,14 +189,14 @@ public abstract class JoinNodeBase extends PlanNode {
             List<TupleId> srcTupleIds = getChild(1) instanceof JoinNodeBase ? 
getChild(1).getOutputTupleIds()
                     : getChild(1).getOutputTblRefIds();
             for (TupleDescriptor rightTupleDesc : 
analyzer.getDescTbl().getTupleDesc(srcTupleIds)) {
-                boolean needSetToNullable =
-                        getChild(1) instanceof JoinNodeBase && 
analyzer.isOuterJoined(rightTupleDesc.getId());
+                boolean needSetToNullable = getChild(1) instanceof JoinNodeBase
+                        && analyzer.isOuterJoined(rightTupleDesc.getId());
                 for (SlotDescriptor rightSlotDesc : rightTupleDesc.getSlots()) 
{
                     if (!isMaterializedByChild(rightSlotDesc, 
getChild(1).getOutputSmap())) {
                         continue;
                     }
-                    SlotDescriptor outputSlotDesc =
-                            
analyzer.getDescTbl().copySlotDescriptor(vOutputTupleDesc, rightSlotDesc);
+                    SlotDescriptor outputSlotDesc = 
analyzer.getDescTbl().copySlotDescriptor(vOutputTupleDesc,
+                            rightSlotDesc);
                     if (rightNullable) {
                         outputSlotDesc.setIsNullable(true);
                         rightNullableNumber++;
@@ -211,8 +212,7 @@ public abstract class JoinNodeBase extends PlanNode {
         // add mark slot if needed
         if (isMarkJoin() && analyzer.needPopUpMarkTuple(innerRef)) {
             SlotDescriptor markSlot = 
analyzer.getMarkTuple(innerRef).getSlots().get(0);
-            SlotDescriptor outputSlotDesc =
-                    analyzer.getDescTbl().copySlotDescriptor(vOutputTupleDesc, 
markSlot);
+            SlotDescriptor outputSlotDesc = 
analyzer.getDescTbl().copySlotDescriptor(vOutputTupleDesc, markSlot);
             srcTblRefToOutputTupleSmap.put(new SlotRef(markSlot), new 
SlotRef(outputSlotDesc));
         }
 
@@ -313,8 +313,10 @@ public abstract class JoinNodeBase extends PlanNode {
             }
         }
 
-        // be may be possible to output correct row number without any column 
data in future
-        // but for now, in order to have correct output row number, should 
keep at least one slot.
+        // be may be possible to output correct row number without any column 
data in
+        // future
+        // but for now, in order to have correct output row number, should 
keep at least
+        // one slot.
         // use first materialized slot if outputSlotIds is empty.
         if (outputSlotIds.isEmpty() && firstMaterializedSlotId != null) {
             outputSlotIds.add(firstMaterializedSlotId);
@@ -359,7 +361,8 @@ public abstract class JoinNodeBase extends PlanNode {
         vIntermediateTupleDescList = new ArrayList<>();
         vIntermediateTupleDescList.add(vIntermediateLeftTupleDesc);
         vIntermediateTupleDescList.add(vIntermediateRightTupleDesc);
-        // if join type is MARK, add mark tuple to intermediate tuple. mark 
slot will be generated after join.
+        // if join type is MARK, add mark tuple to intermediate tuple. mark 
slot will be
+        // generated after join.
         if (isMarkJoin()) {
             TupleDescriptor markTuple = analyzer.getMarkTuple(innerRef);
             if (markTuple != null) {
@@ -395,8 +398,8 @@ public abstract class JoinNodeBase extends PlanNode {
             for (TupleDescriptor tupleDescriptor : analyzer.getDescTbl()
                     .getTupleDesc(getChild(0).getOutputTupleIds())) {
                 for (SlotDescriptor slotDescriptor : 
tupleDescriptor.getMaterializedSlots()) {
-                    SlotDescriptor intermediateSlotDesc =
-                            
analyzer.getDescTbl().copySlotDescriptor(vIntermediateLeftTupleDesc, 
slotDescriptor);
+                    SlotDescriptor intermediateSlotDesc = analyzer.getDescTbl()
+                            .copySlotDescriptor(vIntermediateLeftTupleDesc, 
slotDescriptor);
                     if (leftNullable) {
                         intermediateSlotDesc.setIsNullable(true);
                     }
@@ -411,8 +414,8 @@ public abstract class JoinNodeBase extends PlanNode {
             for (TupleDescriptor tupleDescriptor : analyzer.getDescTbl()
                     .getTupleDesc(getChild(1).getOutputTupleIds())) {
                 for (SlotDescriptor slotDescriptor : 
tupleDescriptor.getMaterializedSlots()) {
-                    SlotDescriptor intermediateSlotDesc =
-                            
analyzer.getDescTbl().copySlotDescriptor(vIntermediateRightTupleDesc, 
slotDescriptor);
+                    SlotDescriptor intermediateSlotDesc = analyzer.getDescTbl()
+                            .copySlotDescriptor(vIntermediateRightTupleDesc, 
slotDescriptor);
                     if (rightNullable) {
                         intermediateSlotDesc.setIsNullable(true);
                     }
@@ -423,7 +426,8 @@ public abstract class JoinNodeBase extends PlanNode {
         vIntermediateRightTupleDesc.computeMemLayout();
         // 3. replace srcExpr by intermediate tuple
         Preconditions.checkState(vSrcToOutputSMap != null);
-        // Set `preserveRootTypes` to true because we should keep the 
consistent for types. See Issue-11314.
+        // Set `preserveRootTypes` to true because we should keep the 
consistent for
+        // types. See Issue-11314.
         vSrcToOutputSMap.substituteLhs(originToIntermediateSmap, analyzer, 
true);
         // 4. replace other conjuncts and conjuncts
         computeOtherConjuncts(analyzer, originToIntermediateSmap);
@@ -438,7 +442,7 @@ public abstract class JoinNodeBase extends PlanNode {
         List<Expr> exprs = vSrcToOutputSMap.getLhs();
         ArrayList<SlotDescriptor> slots = vOutputTupleDesc.getSlots();
         for (int i = 0; i < slots.size(); i++) {
-            slots.get(i).setIsNullable(exprs.get(i).isNullable());
+            slots.get(i).setIsNullable(exprs.get(i).isNullable() || 
slots.get(i).getIsNullable());
         }
         vSrcToOutputSMap.reCalculateNullableInfoForSlotInRhs();
     }
@@ -509,7 +513,8 @@ public abstract class JoinNodeBase extends PlanNode {
     /**
      * If parent wants to get join node tupleids,
      * it will call this function instead of read properties directly.
-     * The reason is that the tuple id of vOutputTupleDesc the real output 
tuple id for join node.
+     * The reason is that the tuple id of vOutputTupleDesc the real output 
tuple id
+     * for join node.
      * <p>
      * If you read the properties of @tupleids directly instead of this 
function,
      * it reads the input id of the current node.
@@ -606,12 +611,15 @@ public abstract class JoinNodeBase extends PlanNode {
                 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
+                // add a new slot for projection result and add the project 
expr to
+                // vSrcToOutputSMap
                 SlotDescriptor slotDesc = 
analyzer.addSlotDescriptor(vOutputTupleDesc);
                 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
+                // 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
                 rhsExpr = rhsExpr.substitute(tmpSmap);
                 vSrcToOutputSMap.getLhs().add(rhsExpr);
                 SlotRef slotRef = new SlotRef(slotDesc);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to