You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2020/03/02 11:34:52 UTC
[incubator-doris] branch master updated: [SetOperation] Change set
operation from random shuffle to hash shuffle (#3015)
This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git
The following commit(s) were added to refs/heads/master by this push:
new 54aa0ed [SetOperation] Change set operation from random shuffle to hash shuffle (#3015)
54aa0ed is described below
commit 54aa0ed26b909518f907e762fbebc6e836e9b440
Author: yangzhg <78...@qq.com>
AuthorDate: Mon Mar 2 19:34:41 2020 +0800
[SetOperation] Change set operation from random shuffle to hash shuffle (#3015)
use hash shuffle instead of random shuffle in set operation, prepare for intersect and except operation
---
.../apache/doris/analysis/SetOperationStmt.java | 4 +-
.../apache/doris/planner/DistributedPlanner.java | 3 +-
.../org/apache/doris/planner/HashJoinNode.java | 2 +-
.../org/apache/doris/planner/SetOperationNode.java | 10 +-
.../apache/doris/planner/SingleNodePlanner.java | 48 +-
.../java/org/apache/doris/planner/PlannerTest.java | 1890 +-------------------
6 files changed, 73 insertions(+), 1884 deletions(-)
diff --git a/fe/src/main/java/org/apache/doris/analysis/SetOperationStmt.java b/fe/src/main/java/org/apache/doris/analysis/SetOperationStmt.java
index 29def10..1a24fca 100644
--- a/fe/src/main/java/org/apache/doris/analysis/SetOperationStmt.java
+++ b/fe/src/main/java/org/apache/doris/analysis/SetOperationStmt.java
@@ -649,7 +649,9 @@ public class SetOperationStmt extends QueryStmt {
if (isAnalyzed()) {
return;
}
- if (qualifier_ == Qualifier.ALL && operation != Operation.UNION) {
+ // Oracle and ms-SQLServer do not support INTERSECT ALL and EXCEPT ALL, postgres support it,
+ // but it is very ambiguous
+ if (qualifier_ == Qualifier.ALL && (operation == Operation.EXCEPT || operation == Operation.INTERSECT)) {
throw new AnalysisException("INTERSECT and EXCEPT does not support ALL qualifier.");
}
analyzer = new Analyzer(parent);
diff --git a/fe/src/main/java/org/apache/doris/planner/DistributedPlanner.java b/fe/src/main/java/org/apache/doris/planner/DistributedPlanner.java
index c3adbe1..9c3bce3 100644
--- a/fe/src/main/java/org/apache/doris/planner/DistributedPlanner.java
+++ b/fe/src/main/java/org/apache/doris/planner/DistributedPlanner.java
@@ -671,7 +671,8 @@ public class DistributedPlanner {
setOperationNode.addChild(null);
// Connect the unpartitioned child fragments to SetOperationNode via a random exchange.
connectChildFragment(setOperationNode, i, setOperationFragment, childFragment);
- childFragment.setOutputPartition(DataPartition.RANDOM);
+ childFragment.setOutputPartition(
+ DataPartition.hashPartitioned(setOperationNode.getMaterializedResultExprLists_().get(i)));
}
setOperationNode.init(ctx_.getRootAnalyzer());
return setOperationFragment;
diff --git a/fe/src/main/java/org/apache/doris/planner/HashJoinNode.java b/fe/src/main/java/org/apache/doris/planner/HashJoinNode.java
index 64bd9d4..04a69c7 100644
--- a/fe/src/main/java/org/apache/doris/planner/HashJoinNode.java
+++ b/fe/src/main/java/org/apache/doris/planner/HashJoinNode.java
@@ -277,7 +277,7 @@ public class HashJoinNode extends PlanNode {
output.append(detailPrefix + "colocate: " + isColocate + (isColocate? "" : ", reason: " + colocateReason) + "\n");
for (BinaryPredicate eqJoinPredicate : eqJoinConjuncts) {
- output.append(eqJoinPredicate.toSql() + "\n");
+ output.append(detailPrefix).append("equal join conjunct: ").append(eqJoinPredicate.toSql() + "\n");
}
if (!otherJoinConjuncts.isEmpty()) {
output.append(detailPrefix + "other join predicates: ").append(
diff --git a/fe/src/main/java/org/apache/doris/planner/SetOperationNode.java b/fe/src/main/java/org/apache/doris/planner/SetOperationNode.java
index a6623cd..cb92707 100644
--- a/fe/src/main/java/org/apache/doris/planner/SetOperationNode.java
+++ b/fe/src/main/java/org/apache/doris/planner/SetOperationNode.java
@@ -54,7 +54,7 @@ import com.google.common.collect.Lists;
public abstract class SetOperationNode extends PlanNode {
private final static Logger LOG = LoggerFactory.getLogger(SetOperationNode.class);
- // List of set operation result exprs of the originating UnionStmt. Used for
+ // List of set operation result exprs of the originating SetOperationStmt. Used for
// determining passthrough-compatibility of children.
protected List<Expr> setOpResultExprs_;
@@ -114,6 +114,14 @@ public abstract class SetOperationNode extends PlanNode {
resultExprLists_.add(resultExprs);
}
+ public List<List<Expr>> getMaterializedResultExprLists_() {
+ return materializedResultExprLists_;
+ }
+
+ public List<List<Expr>> getMaterializedConstExprLists_() {
+ return materializedConstExprLists_;
+ }
+
@Override
public void computeStats(Analyzer analyzer) {
super.computeStats(analyzer);
diff --git a/fe/src/main/java/org/apache/doris/planner/SingleNodePlanner.java b/fe/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
index ca88171..1ebe7bb 100644
--- a/fe/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
+++ b/fe/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
@@ -1584,6 +1584,11 @@ public class SingleNodePlanner {
// If it is a union or other same operation, there are only two possibilities,
// one is the root node, and the other is a distinct node in front, so the setOperationDistinctPlan will
// be aggregate node, if this is a mixed operation
+ // e.g. :
+ // a union b -> setOperationDistinctPlan == null
+ // a union b union all c -> setOperationDistinctPlan == null -> setOperationDistinctPlan == AggregationNode
+ // a union all b except c -> setOperationDistinctPlan == null -> setOperationDistinctPlan == UnionNode
+ // a union b except c -> setOperationDistinctPlan == null -> setOperationDistinctPlan == AggregationNode
if (setOperationDistinctPlan != null && setOperationDistinctPlan instanceof SetOperationNode) {
Preconditions.checkState(!setOperationDistinctPlan.getClass().equals(setOpNode.getClass()));
setOpNode.addChild(setOperationDistinctPlan, setOperationStmt.getResultExprs());
@@ -1591,7 +1596,8 @@ public class SingleNodePlanner {
Preconditions.checkState(setOperationStmt.hasDistinctOps());
Preconditions.checkState(setOperationDistinctPlan instanceof AggregationNode);
setOpNode.addChild(setOperationDistinctPlan,
- setOperationStmt.getDistinctAggInfo().getGroupingExprs()); }
+ setOperationStmt.getDistinctAggInfo().getGroupingExprs());
+ }
setOpNode.init(analyzer);
return setOpNode;
}
@@ -1701,9 +1707,11 @@ public class SingleNodePlanner {
return result;
}
- // create partial plan for example: a union b intersect c
- // first partial plan is a union b as a result d,
+ // create the partial plan, or example: a union b intersect c
+ // the first partial plan is a union b as a result d,
// the second partial plan d intersect c
+ // notice that when query is a union b the union operation is in right-hand child(b),
+ // while the left-hand child(a)'s operation is null
private PlanNode createPartialSetOperationPlan(Analyzer analyzer, SetOperationStmt setOperationStmt,
List<SetOperationStmt.SetOperand> setOperands,
PlanNode setOperationDistinctPlan, long defaultOrderByLimit)
@@ -1712,6 +1720,7 @@ public class SingleNodePlanner {
boolean hasAllOps = false;
List<SetOperationStmt.SetOperand> allOps = new ArrayList<>();
List<SetOperationStmt.SetOperand> distinctOps = new ArrayList<>();
+ SetOperationStmt.Operation operation = null;
for (SetOperationStmt.SetOperand op: setOperands) {
if (op.getQualifier() == SetOperationStmt.Qualifier.DISTINCT) {
hasDistinctOps = true;
@@ -1721,19 +1730,30 @@ public class SingleNodePlanner {
hasAllOps = true;
allOps.add(op);
}
+ if (operation == null || operation == op.getOperation()) {
+ operation = op.getOperation();
+ } else {
+ operation = null;
+ }
}
- // create DISTINCT tree
- if (hasDistinctOps) {
+ Preconditions.checkNotNull(operation, "invalid operation.");
+ if (operation == SetOperationStmt.Operation.INTERSECT || operation == SetOperationStmt.Operation.EXCEPT) {
setOperationDistinctPlan = createSetOperationPlan(
- analyzer, setOperationStmt, distinctOps, setOperationDistinctPlan, defaultOrderByLimit);
- setOperationDistinctPlan = new AggregationNode(ctx_.getNextNodeId(), setOperationDistinctPlan,
- setOperationStmt.getDistinctAggInfo());
- setOperationDistinctPlan.init(analyzer);
- }
- // create ALL tree
- if (hasAllOps) {
- setOperationDistinctPlan = createSetOperationPlan(analyzer, setOperationStmt, allOps,
- setOperationDistinctPlan, defaultOrderByLimit);
+ analyzer, setOperationStmt, setOperands, setOperationDistinctPlan, defaultOrderByLimit);
+ } else {
+ // create DISTINCT tree
+ if (hasDistinctOps) {
+ setOperationDistinctPlan = createSetOperationPlan(
+ analyzer, setOperationStmt, distinctOps, setOperationDistinctPlan, defaultOrderByLimit);
+ setOperationDistinctPlan = new AggregationNode(ctx_.getNextNodeId(), setOperationDistinctPlan,
+ setOperationStmt.getDistinctAggInfo());
+ setOperationDistinctPlan.init(analyzer);
+ }
+ // create ALL tree
+ if (hasAllOps) {
+ setOperationDistinctPlan = createSetOperationPlan(analyzer, setOperationStmt, allOps,
+ setOperationDistinctPlan, defaultOrderByLimit);
+ }
}
return setOperationDistinctPlan;
}
diff --git a/fe/src/test/java/org/apache/doris/planner/PlannerTest.java b/fe/src/test/java/org/apache/doris/planner/PlannerTest.java
index 663133c..56a2e6f 100644
--- a/fe/src/test/java/org/apache/doris/planner/PlannerTest.java
+++ b/fe/src/test/java/org/apache/doris/planner/PlannerTest.java
@@ -17,6 +17,7 @@
package org.apache.doris.planner;
+import org.apache.commons.lang3.StringUtils;
import org.apache.doris.analysis.CreateDbStmt;
import org.apache.doris.analysis.CreateTableStmt;
import org.apache.doris.catalog.Catalog;
@@ -64,100 +65,12 @@ public class PlannerTest {
+ " db1.tbl1 b\n"
+ " on (a.k1 = b.k1)\n"
+ "where b.k1 = 'a'";
- String plan1 = "PLAN FRAGMENT 0\n" +
- " OUTPUT EXPRS:<slot 4> | <slot 5> | `b`.`k1` | `b`.`k2` | `b`.`k3` | `b`.`k4`\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " RESULT SINK\n" +
- "\n" +
- " 4:HASH JOIN\n" +
- " | join op: INNER JOIN (BROADCAST)\n" +
- " | hash predicates:\n" +
- " | colocate: false, reason: Node type not match\n" +
- "(<slot 4> = `b`.`k1`)\n" +
- " | tuple ids: 2 4 \n" +
- " | \n" +
- " |----7:EXCHANGE\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " 0:UNION\n" +
- " | child exprs: \n" +
- " | `k1` | `k2`\n" +
- " | `k1` | `k2`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " |----6:EXCHANGE\n" +
- " | tuple ids: 1 \n" +
- " | \n" +
- " 5:EXCHANGE\n" +
- " tuple ids: 0 \n" +
- "\n" +
- "PLAN FRAGMENT 1\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 07\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 3:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: null\n" +
- " PREDICATES: `b`.`k1` = 'a'\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 2\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 06\n" +
- " RANDOM\n" +
- "\n" +
- " 2:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 3\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 05\n" +
- " RANDOM\n" +
- "\n" +
- " 1:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 0 \n";
StmtExecutor stmtExecutor1 = new StmtExecutor(ctx, sql1);
stmtExecutor1.execute();
Planner planner1 = stmtExecutor1.planner();
List<PlanFragment> fragments1 = planner1.getFragments();
- Assert.assertEquals(plan1, planner1.getExplainString(fragments1, TExplainLevel.VERBOSE));
+ String plan1 = planner1.getExplainString(fragments1, TExplainLevel.VERBOSE);
+ Assert.assertEquals(1, StringUtils.countMatches(plan1, "UNION"));
String sql2 = "explain select * from db1.tbl1 where k1='a' and k4=1\n"
+ "union distinct\n"
+ " (select * from db1.tbl1 where k1='b' and k4=2\n"
@@ -177,351 +90,13 @@ public class PlannerTest {
+ " union all\n"
+ " (select * from db1.tbl1 where k1='b' and k4=5)\n"
+ " order by 3 limit 3)";
-
- String plan2 = "PLAN FRAGMENT 0\n" +
- " OUTPUT EXPRS:<slot 60> | <slot 61> | <slot 62> | <slot 63>\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " RESULT SINK\n" +
- "\n" +
- " 30:EXCHANGE\n" +
- " tuple ids: 15 \n" +
- "\n" +
- "PLAN FRAGMENT 1\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 30\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 9:UNION\n" +
- " | child exprs: \n" +
- " | <slot 60> | <slot 61> | <slot 62> | <slot 63>\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | <slot 57> | <slot 58> | <slot 56> | <slot 59>\n" +
- " | pass-through-operands: 26,27,28\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " |----27:EXCHANGE\n" +
- " | tuple ids: 8 \n" +
- " | \n" +
- " |----28:EXCHANGE\n" +
- " | tuple ids: 9 \n" +
- " | \n" +
- " |----29:EXCHANGE\n" +
- " | limit: 3\n" +
- " | tuple ids: 14 \n" +
- " | \n" +
- " 26:EXCHANGE\n" +
- " tuple ids: 15 \n" +
- "\n" +
- "PLAN FRAGMENT 2\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 29\n" +
- " RANDOM\n" +
- "\n" +
- " 25:MERGING-EXCHANGE\n" +
- " limit: 3\n" +
- " tuple ids: 14 \n" +
- "\n" +
- "PLAN FRAGMENT 3\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 25\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 15:TOP-N\n" +
- " | order by: <slot 56> ASC\n" +
- " | offset: 0\n" +
- " | limit: 3\n" +
- " | tuple ids: 14 \n" +
- " | \n" +
- " 12:UNION\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 13 \n" +
- " | \n" +
- " |----24:EXCHANGE\n" +
- " | tuple ids: 12 \n" +
- " | \n" +
- " 23:EXCHANGE\n" +
- " tuple ids: 11 \n" +
- "\n" +
- "PLAN FRAGMENT 4\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 24\n" +
- " RANDOM\n" +
- "\n" +
- " 14:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 5\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 12 \n" +
- "\n" +
- "PLAN FRAGMENT 5\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 23\n" +
- " RANDOM\n" +
- "\n" +
- " 13:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 3\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 11 \n" +
- "\n" +
- "PLAN FRAGMENT 6\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 28\n" +
- " RANDOM\n" +
- "\n" +
- " 11:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 4\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 9 \n" +
- "\n" +
- "PLAN FRAGMENT 7\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 27\n" +
- " RANDOM\n" +
- "\n" +
- " 10:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 3\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 8 \n" +
- "\n" +
- "PLAN FRAGMENT 8\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 26\n" +
- " RANDOM\n" +
- "\n" +
- " 8:AGGREGATE (update finalize)\n" +
- " | group by: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 0:UNION\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | <slot 29> | <slot 30> | <slot 28> | <slot 31>\n" +
- " | pass-through-operands: 19,20,21\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " |----20:EXCHANGE\n" +
- " | tuple ids: 1 \n" +
- " | \n" +
- " |----21:EXCHANGE\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " |----22:EXCHANGE\n" +
- " | limit: 3\n" +
- " | tuple ids: 7 \n" +
- " | \n" +
- " 19:EXCHANGE\n" +
- " tuple ids: 0 \n" +
- "\n" +
- "PLAN FRAGMENT 9\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 22\n" +
- " RANDOM\n" +
- "\n" +
- " 18:MERGING-EXCHANGE\n" +
- " limit: 3\n" +
- " tuple ids: 7 \n" +
- "\n" +
- "PLAN FRAGMENT 10\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 18\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 7:TOP-N\n" +
- " | order by: <slot 28> ASC\n" +
- " | offset: 0\n" +
- " | limit: 3\n" +
- " | tuple ids: 7 \n" +
- " | \n" +
- " 4:UNION\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 6 \n" +
- " | \n" +
- " |----17:EXCHANGE\n" +
- " | tuple ids: 5 \n" +
- " | \n" +
- " 16:EXCHANGE\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 11\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 17\n" +
- " RANDOM\n" +
- "\n" +
- " 6:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 3\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 5 \n" +
- "\n" +
- "PLAN FRAGMENT 12\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 16\n" +
- " RANDOM\n" +
- "\n" +
- " 5:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 13\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 21\n" +
- " RANDOM\n" +
- "\n" +
- " 3:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 2 \n" +
- "\n" +
- "PLAN FRAGMENT 14\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 20\n" +
- " RANDOM\n" +
- "\n" +
- " 2:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 15\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 19\n" +
- " RANDOM\n" +
- "\n" +
- " 1:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 1\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 0 \n";
StmtExecutor stmtExecutor2 = new StmtExecutor(ctx, sql2);
stmtExecutor2.execute();
Planner planner2 = stmtExecutor2.planner();
List<PlanFragment> fragments2 = planner2.getFragments();
- Assert.assertEquals(plan2, planner2.getExplainString(fragments2, TExplainLevel.VERBOSE));
+ String plan2 = planner2.getExplainString(fragments2, TExplainLevel.VERBOSE);
+ Assert.assertEquals(4, StringUtils.countMatches(plan2, "UNION"));
+
// intersect
String sql3 = "explain select * from\n"
+ " (select k1, k2 from db1.tbl1\n"
@@ -531,104 +106,12 @@ public class PlannerTest {
+ " db1.tbl1 b\n"
+ " on (a.k1 = b.k1)\n"
+ "where b.k1 = 'a'";
- String plan3 = "PLAN FRAGMENT 0\n" +
- " OUTPUT EXPRS:<slot 4> | <slot 5> | `b`.`k1` | `b`.`k2` | `b`.`k3` | `b`.`k4`\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " RESULT SINK\n" +
- "\n" +
- " 5:HASH JOIN\n" +
- " | join op: INNER JOIN (BROADCAST)\n" +
- " | hash predicates:\n" +
- " | colocate: false, reason: Node type not match\n" +
- "(<slot 4> = `b`.`k1`)\n" +
- " | tuple ids: 2 4 \n" +
- " | \n" +
- " |----8:EXCHANGE\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " 3:AGGREGATE (update finalize)\n" +
- " | group by: <slot 4>, <slot 5>\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " 0:INTERSECT\n" +
- " | child exprs: \n" +
- " | `k1` | `k2`\n" +
- " | `k1` | `k2`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " |----7:EXCHANGE\n" +
- " | tuple ids: 1 \n" +
- " | \n" +
- " 6:EXCHANGE\n" +
- " tuple ids: 0 \n" +
- "\n" +
- "PLAN FRAGMENT 1\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 08\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 4:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: null\n" +
- " PREDICATES: `b`.`k1` = 'a'\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 2\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 07\n" +
- " RANDOM\n" +
- "\n" +
- " 2:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 3\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 06\n" +
- " RANDOM\n" +
- "\n" +
- " 1:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 0 \n";
StmtExecutor stmtExecutor3 = new StmtExecutor(ctx, sql3);
stmtExecutor3.execute();
Planner planner3 = stmtExecutor3.planner();
List<PlanFragment> fragments3 = planner3.getFragments();
- Assert.assertEquals(plan3, planner3.getExplainString(fragments3, TExplainLevel.VERBOSE));
+ String plan3 = planner3.getExplainString(fragments3, TExplainLevel.VERBOSE);
+ Assert.assertEquals(1, StringUtils.countMatches(plan3, "INTERSECT"));
String sql4 = "explain select * from db1.tbl1 where k1='a' and k4=1\n"
+ "intersect distinct\n"
+ " (select * from db1.tbl1 where k1='b' and k4=2\n"
@@ -649,357 +132,12 @@ public class PlannerTest {
+ " (select * from db1.tbl1 where k1='b' and k4=5)\n"
+ " order by 3 limit 3)";
- String plan4 = "PLAN FRAGMENT 0\n" +
- " OUTPUT EXPRS:<slot 60> | <slot 61> | <slot 62> | <slot 63>\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " RESULT SINK\n" +
- "\n" +
- " 32:EXCHANGE\n" +
- " tuple ids: 15 \n" +
- "\n" +
- "PLAN FRAGMENT 1\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: HASH_PARTITIONED: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 32\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 31:AGGREGATE (merge finalize)\n" +
- " | group by: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 30:EXCHANGE\n" +
- " tuple ids: 15 \n" +
- "\n" +
- "PLAN FRAGMENT 2\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 30\n" +
- " HASH_PARTITIONED: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- "\n" +
- " 16:AGGREGATE (update serialize)\n" +
- " | STREAMING\n" +
- " | group by: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 0:INTERSECT\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | <slot 29> | <slot 30> | <slot 28> | <slot 31>\n" +
- " | <slot 57> | <slot 58> | <slot 56> | <slot 59>\n" +
- " | pass-through-operands: 23,24,25,27,28\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " |----24:EXCHANGE\n" +
- " | tuple ids: 1 \n" +
- " | \n" +
- " |----25:EXCHANGE\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " |----27:EXCHANGE\n" +
- " | tuple ids: 8 \n" +
- " | \n" +
- " |----28:EXCHANGE\n" +
- " | tuple ids: 9 \n" +
- " | \n" +
- " |----26:EXCHANGE\n" +
- " | limit: 3\n" +
- " | tuple ids: 7 \n" +
- " | \n" +
- " |----29:EXCHANGE\n" +
- " | limit: 3\n" +
- " | tuple ids: 14 \n" +
- " | \n" +
- " 23:EXCHANGE\n" +
- " tuple ids: 0 \n" +
- "\n" +
- "PLAN FRAGMENT 3\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 29\n" +
- " RANDOM\n" +
- "\n" +
- " 22:MERGING-EXCHANGE\n" +
- " limit: 3\n" +
- " tuple ids: 14 \n" +
- "\n" +
- "PLAN FRAGMENT 4\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 22\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 15:TOP-N\n" +
- " | order by: <slot 56> ASC\n" +
- " | offset: 0\n" +
- " | limit: 3\n" +
- " | tuple ids: 14 \n" +
- " | \n" +
- " 14:AGGREGATE (update finalize)\n" +
- " | group by: <slot 52>, <slot 53>, <slot 54>, <slot 55>\n" +
- " | tuple ids: 13 \n" +
- " | \n" +
- " 11:INTERSECT\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 13 \n" +
- " | \n" +
- " |----21:EXCHANGE\n" +
- " | tuple ids: 12 \n" +
- " | \n" +
- " 20:EXCHANGE\n" +
- " tuple ids: 11 \n" +
- "\n" +
- "PLAN FRAGMENT 5\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 21\n" +
- " RANDOM\n" +
- "\n" +
- " 13:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 5\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 12 \n" +
- "\n" +
- "PLAN FRAGMENT 6\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 20\n" +
- " RANDOM\n" +
- "\n" +
- " 12:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 3\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 11 \n" +
- "\n" +
- "PLAN FRAGMENT 7\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 28\n" +
- " RANDOM\n" +
- "\n" +
- " 10:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 4\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 9 \n" +
- "\n" +
- "PLAN FRAGMENT 8\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 27\n" +
- " RANDOM\n" +
- "\n" +
- " 9:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 3\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 8 \n" +
- "\n" +
- "PLAN FRAGMENT 9\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 26\n" +
- " RANDOM\n" +
- "\n" +
- " 19:MERGING-EXCHANGE\n" +
- " limit: 3\n" +
- " tuple ids: 7 \n" +
- "\n" +
- "PLAN FRAGMENT 10\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 19\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 8:TOP-N\n" +
- " | order by: <slot 28> ASC\n" +
- " | offset: 0\n" +
- " | limit: 3\n" +
- " | tuple ids: 7 \n" +
- " | \n" +
- " 7:AGGREGATE (update finalize)\n" +
- " | group by: <slot 24>, <slot 25>, <slot 26>, <slot 27>\n" +
- " | tuple ids: 6 \n" +
- " | \n" +
- " 4:INTERSECT\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 6 \n" +
- " | \n" +
- " |----18:EXCHANGE\n" +
- " | tuple ids: 5 \n" +
- " | \n" +
- " 17:EXCHANGE\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 11\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 18\n" +
- " RANDOM\n" +
- "\n" +
- " 6:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 3\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 5 \n" +
- "\n" +
- "PLAN FRAGMENT 12\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 17\n" +
- " RANDOM\n" +
- "\n" +
- " 5:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 13\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 25\n" +
- " RANDOM\n" +
- "\n" +
- " 3:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 2 \n" +
- "\n" +
- "PLAN FRAGMENT 14\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 24\n" +
- " RANDOM\n" +
- "\n" +
- " 2:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 15\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 23\n" +
- " RANDOM\n" +
- "\n" +
- " 1:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 1\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 0 \n";
StmtExecutor stmtExecutor4 = new StmtExecutor(ctx, sql4);
stmtExecutor4.execute();
Planner planner4 = stmtExecutor4.planner();
List<PlanFragment> fragments4 = planner4.getFragments();
- Assert.assertEquals(plan4, planner4.getExplainString(fragments4, TExplainLevel.VERBOSE));
+ String plan4 = planner4.getExplainString(fragments4, TExplainLevel.VERBOSE);
+ Assert.assertEquals(3, StringUtils.countMatches(plan4, "INTERSECT"));
// except
String sql5 = "explain select * from\n"
@@ -1010,104 +148,12 @@ public class PlannerTest {
+ " db1.tbl1 b\n"
+ " on (a.k1 = b.k1)\n"
+ "where b.k1 = 'a'";
- String plan5 = "PLAN FRAGMENT 0\n" +
- " OUTPUT EXPRS:<slot 4> | <slot 5> | `b`.`k1` | `b`.`k2` | `b`.`k3` | `b`.`k4`\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " RESULT SINK\n" +
- "\n" +
- " 5:HASH JOIN\n" +
- " | join op: INNER JOIN (BROADCAST)\n" +
- " | hash predicates:\n" +
- " | colocate: false, reason: Node type not match\n" +
- "(<slot 4> = `b`.`k1`)\n" +
- " | tuple ids: 2 4 \n" +
- " | \n" +
- " |----8:EXCHANGE\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " 3:AGGREGATE (update finalize)\n" +
- " | group by: <slot 4>, <slot 5>\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " 0:EXCEPT\n" +
- " | child exprs: \n" +
- " | `k1` | `k2`\n" +
- " | `k1` | `k2`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " |----7:EXCHANGE\n" +
- " | tuple ids: 1 \n" +
- " | \n" +
- " 6:EXCHANGE\n" +
- " tuple ids: 0 \n" +
- "\n" +
- "PLAN FRAGMENT 1\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 08\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 4:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: null\n" +
- " PREDICATES: `b`.`k1` = 'a'\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 2\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 07\n" +
- " RANDOM\n" +
- "\n" +
- " 2:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 3\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 06\n" +
- " RANDOM\n" +
- "\n" +
- " 1:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 0 \n";
StmtExecutor stmtExecutor5 = new StmtExecutor(ctx, sql5);
stmtExecutor5.execute();
Planner planner5 = stmtExecutor5.planner();
List<PlanFragment> fragments5 = planner5.getFragments();
- Assert.assertEquals(plan5, planner5.getExplainString(fragments5, TExplainLevel.VERBOSE));
+ String plan5 = planner5.getExplainString(fragments5, TExplainLevel.VERBOSE);
+ Assert.assertEquals(1, StringUtils.countMatches(plan5, "EXCEPT"));
String sql6 = "select * from db1.tbl1 where k1='a' and k4=1\n"
+ "except\n"
@@ -1117,143 +163,12 @@ public class PlannerTest {
+ "except distinct\n"
+ "(select * from db1.tbl1 where k1='a' and k4=2)\n"
+ "order by 3 limit 3";
- String plan6 = "PLAN FRAGMENT 0\n" +
- " OUTPUT EXPRS:<slot 21> | <slot 22> | <slot 20> | <slot 23>\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " RESULT SINK\n" +
- "\n" +
- " 11:MERGING-EXCHANGE\n" +
- " limit: 3\n" +
- " tuple ids: 5 \n" +
- "\n" +
- "PLAN FRAGMENT 1\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 11\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 6:TOP-N\n" +
- " | order by: <slot 20> ASC\n" +
- " | offset: 0\n" +
- " | limit: 3\n" +
- " | tuple ids: 5 \n" +
- " | \n" +
- " 5:AGGREGATE (update finalize)\n" +
- " | group by: <slot 16>, <slot 17>, <slot 18>, <slot 19>\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " 0:EXCEPT\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " |----8:EXCHANGE\n" +
- " | tuple ids: 1 \n" +
- " | \n" +
- " |----9:EXCHANGE\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " |----10:EXCHANGE\n" +
- " | tuple ids: 3 \n" +
- " | \n" +
- " 7:EXCHANGE\n" +
- " tuple ids: 0 \n" +
- "\n" +
- "PLAN FRAGMENT 2\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 10\n" +
- " RANDOM\n" +
- "\n" +
- " 4:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 3 \n" +
- "\n" +
- "PLAN FRAGMENT 3\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 09\n" +
- " RANDOM\n" +
- "\n" +
- " 3:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 2 \n" +
- "\n" +
- "PLAN FRAGMENT 4\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 08\n" +
- " RANDOM\n" +
- "\n" +
- " 2:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 1\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 5\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 07\n" +
- " RANDOM\n" +
- "\n" +
- " 1:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 1\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 0 \n";
StmtExecutor stmtExecutor6 = new StmtExecutor(ctx, sql6);
stmtExecutor6.execute();
Planner planner6 = stmtExecutor6.planner();
List<PlanFragment> fragments6 = planner6.getFragments();
- Assert.assertEquals(plan6, planner6.getExplainString(fragments6, TExplainLevel.VERBOSE));
+ String plan6 = planner6.getExplainString(fragments6, TExplainLevel.VERBOSE);
+ Assert.assertEquals(1, StringUtils.countMatches(plan6, "EXCEPT"));
String sql7 = "select * from db1.tbl1 where k1='a' and k4=1\n"
+ "except distinct\n"
@@ -1263,143 +178,12 @@ public class PlannerTest {
+ "except\n"
+ "(select * from db1.tbl1 where k1='a' and k4=2)\n"
+ "order by 3 limit 3";
- String plan7 = "PLAN FRAGMENT 0\n" +
- " OUTPUT EXPRS:<slot 21> | <slot 22> | <slot 20> | <slot 23>\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " RESULT SINK\n" +
- "\n" +
- " 11:MERGING-EXCHANGE\n" +
- " limit: 3\n" +
- " tuple ids: 5 \n" +
- "\n" +
- "PLAN FRAGMENT 1\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 11\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 6:TOP-N\n" +
- " | order by: <slot 20> ASC\n" +
- " | offset: 0\n" +
- " | limit: 3\n" +
- " | tuple ids: 5 \n" +
- " | \n" +
- " 5:AGGREGATE (update finalize)\n" +
- " | group by: <slot 16>, <slot 17>, <slot 18>, <slot 19>\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " 0:EXCEPT\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " |----8:EXCHANGE\n" +
- " | tuple ids: 1 \n" +
- " | \n" +
- " |----9:EXCHANGE\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " |----10:EXCHANGE\n" +
- " | tuple ids: 3 \n" +
- " | \n" +
- " 7:EXCHANGE\n" +
- " tuple ids: 0 \n" +
- "\n" +
- "PLAN FRAGMENT 2\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 10\n" +
- " RANDOM\n" +
- "\n" +
- " 4:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 3 \n" +
- "\n" +
- "PLAN FRAGMENT 3\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 09\n" +
- " RANDOM\n" +
- "\n" +
- " 3:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 2 \n" +
- "\n" +
- "PLAN FRAGMENT 4\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 08\n" +
- " RANDOM\n" +
- "\n" +
- " 2:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 1\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 5\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 07\n" +
- " RANDOM\n" +
- "\n" +
- " 1:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 1\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 0 \n";
StmtExecutor stmtExecutor7 = new StmtExecutor(ctx, sql7);
stmtExecutor7.execute();
Planner planner7 = stmtExecutor7.planner();
List<PlanFragment> fragments7 = planner7.getFragments();
- Assert.assertEquals(plan7, planner7.getExplainString(fragments7, TExplainLevel.VERBOSE));
+ String plan7 = planner7.getExplainString(fragments7, TExplainLevel.VERBOSE);
+ Assert.assertEquals(1, StringUtils.countMatches(plan7, "EXCEPT"));
// mixed
String sql8 = "select * from db1.tbl1 where k1='a' and k4=1\n"
@@ -1410,185 +194,14 @@ public class PlannerTest {
+ "intersect\n"
+ "(select * from db1.tbl1 where k1='a' and k4=2)\n"
+ "order by 3 limit 3";
- String plan8 = "PLAN FRAGMENT 0\n" +
- " OUTPUT EXPRS:<slot 21> | <slot 22> | <slot 20> | <slot 23>\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " RESULT SINK\n" +
- "\n" +
- " 17:MERGING-EXCHANGE\n" +
- " limit: 3\n" +
- " tuple ids: 5 \n" +
- "\n" +
- "PLAN FRAGMENT 1\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 17\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 10:TOP-N\n" +
- " | order by: <slot 20> ASC\n" +
- " | offset: 0\n" +
- " | limit: 3\n" +
- " | tuple ids: 5 \n" +
- " | \n" +
- " 9:AGGREGATE (update finalize)\n" +
- " | group by: <slot 16>, <slot 17>, <slot 18>, <slot 19>\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " 7:INTERSECT\n" +
- " | child exprs: \n" +
- " | <slot 16> | <slot 17> | <slot 18> | <slot 19>\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " |----16:EXCHANGE\n" +
- " | tuple ids: 3 \n" +
- " | \n" +
- " 15:EXCHANGE\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 2\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 16\n" +
- " RANDOM\n" +
- "\n" +
- " 8:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 3 \n" +
- "\n" +
- "PLAN FRAGMENT 3\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 15\n" +
- " RANDOM\n" +
- "\n" +
- " 6:AGGREGATE (update finalize)\n" +
- " | group by: <slot 16>, <slot 17>, <slot 18>, <slot 19>\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " 4:EXCEPT\n" +
- " | child exprs: \n" +
- " | <slot 16> | <slot 17> | <slot 18> | <slot 19>\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " |----14:EXCHANGE\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " 13:EXCHANGE\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 4\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 14\n" +
- " RANDOM\n" +
- "\n" +
- " 5:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 2 \n" +
- "\n" +
- "PLAN FRAGMENT 5\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 13\n" +
- " RANDOM\n" +
- "\n" +
- " 3:AGGREGATE (update finalize)\n" +
- " | group by: <slot 16>, <slot 17>, <slot 18>, <slot 19>\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " 0:UNION\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 4 \n" +
- " | \n" +
- " |----12:EXCHANGE\n" +
- " | tuple ids: 1 \n" +
- " | \n" +
- " 11:EXCHANGE\n" +
- " tuple ids: 0 \n" +
- "\n" +
- "PLAN FRAGMENT 6\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 12\n" +
- " RANDOM\n" +
- "\n" +
- " 2:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 1\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 7\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 11\n" +
- " RANDOM\n" +
- "\n" +
- " 1:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 1\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 0 \n";
StmtExecutor stmtExecutor8 = new StmtExecutor(ctx, sql8);
stmtExecutor8.execute();
Planner planner8 = stmtExecutor8.planner();
List<PlanFragment> fragments8 = planner8.getFragments();
- Assert.assertEquals(plan8, planner8.getExplainString(fragments8, TExplainLevel.VERBOSE));
+ String plan8 = planner8.getExplainString(fragments8, TExplainLevel.VERBOSE);
+ Assert.assertEquals(1, StringUtils.countMatches(plan8, "UNION"));
+ Assert.assertEquals(1, StringUtils.countMatches(plan8, "INTERSECT"));
+ Assert.assertEquals(1, StringUtils.countMatches(plan8, "EXCEPT"));
String sql9 = "explain select * from db1.tbl1 where k1='a' and k4=1\n"
+ "intersect distinct\n"
@@ -1610,469 +223,14 @@ public class PlannerTest {
+ " (select * from db1.tbl1 where k1='b' and k4=5)\n"
+ " order by 3 limit 3)";
- String plan9 = "PLAN FRAGMENT 0\n" +
- " OUTPUT EXPRS:<slot 60> | <slot 61> | <slot 62> | <slot 63>\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " RESULT SINK\n" +
- "\n" +
- " 47:EXCHANGE\n" +
- " tuple ids: 15 \n" +
- "\n" +
- "PLAN FRAGMENT 1\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: HASH_PARTITIONED: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 47\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 46:AGGREGATE (merge finalize)\n" +
- " | group by: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 45:EXCHANGE\n" +
- " tuple ids: 15 \n" +
- "\n" +
- "PLAN FRAGMENT 2\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 45\n" +
- " HASH_PARTITIONED: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- "\n" +
- " 23:AGGREGATE (update serialize)\n" +
- " | STREAMING\n" +
- " | group by: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 17:EXCEPT\n" +
- " | child exprs: \n" +
- " | <slot 60> | <slot 61> | <slot 62> | <slot 63>\n" +
- " | <slot 57> | <slot 58> | <slot 56> | <slot 59>\n" +
- " | pass-through-operands: 43\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " |----44:EXCHANGE\n" +
- " | limit: 3\n" +
- " | tuple ids: 14 \n" +
- " | \n" +
- " 43:EXCHANGE\n" +
- " tuple ids: 15 \n" +
- "\n" +
- "PLAN FRAGMENT 3\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 44\n" +
- " RANDOM\n" +
- "\n" +
- " 42:MERGING-EXCHANGE\n" +
- " limit: 3\n" +
- " tuple ids: 14 \n" +
- "\n" +
- "PLAN FRAGMENT 4\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 42\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 22:TOP-N\n" +
- " | order by: <slot 56> ASC\n" +
- " | offset: 0\n" +
- " | limit: 3\n" +
- " | tuple ids: 14 \n" +
- " | \n" +
- " 21:AGGREGATE (update finalize)\n" +
- " | group by: <slot 52>, <slot 53>, <slot 54>, <slot 55>\n" +
- " | tuple ids: 13 \n" +
- " | \n" +
- " 18:INTERSECT\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 13 \n" +
- " | \n" +
- " |----41:EXCHANGE\n" +
- " | tuple ids: 12 \n" +
- " | \n" +
- " 40:EXCHANGE\n" +
- " tuple ids: 11 \n" +
- "\n" +
- "PLAN FRAGMENT 5\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 41\n" +
- " RANDOM\n" +
- "\n" +
- " 20:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 5\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 12 \n" +
- "\n" +
- "PLAN FRAGMENT 6\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 40\n" +
- " RANDOM\n" +
- "\n" +
- " 19:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 3\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 11 \n" +
- "\n" +
- "PLAN FRAGMENT 7\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: HASH_PARTITIONED: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 43\n" +
- " RANDOM\n" +
- "\n" +
- " 39:AGGREGATE (merge finalize)\n" +
- " | group by: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 38:EXCHANGE\n" +
- " tuple ids: 15 \n" +
- "\n" +
- "PLAN FRAGMENT 8\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 38\n" +
- " HASH_PARTITIONED: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- "\n" +
- " 16:AGGREGATE (update serialize)\n" +
- " | STREAMING\n" +
- " | group by: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 11:UNION\n" +
- " | child exprs: \n" +
- " | <slot 40> | <slot 41> | <slot 42> | <slot 43>\n" +
- " | <slot 60> | <slot 61> | <slot 62> | <slot 63>\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " |----37:EXCHANGE\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 36:EXCHANGE\n" +
- " tuple ids: 10 \n" +
- "\n" +
- "PLAN FRAGMENT 9\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: HASH_PARTITIONED: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 37\n" +
- " RANDOM\n" +
- "\n" +
- " 35:AGGREGATE (merge finalize)\n" +
- " | group by: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 34:EXCHANGE\n" +
- " tuple ids: 15 \n" +
- "\n" +
- "PLAN FRAGMENT 10\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 34\n" +
- " HASH_PARTITIONED: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- "\n" +
- " 10:AGGREGATE (update serialize)\n" +
- " | STREAMING\n" +
- " | group by: <slot 60>, <slot 61>, <slot 62>, <slot 63>\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " 0:INTERSECT\n" +
- " | child exprs: \n" +
- " | <slot 12> | <slot 13> | <slot 14> | <slot 15>\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | <slot 29> | <slot 30> | <slot 28> | <slot 31>\n" +
- " | pass-through-operands: 31,32\n" +
- " | tuple ids: 15 \n" +
- " | \n" +
- " |----32:EXCHANGE\n" +
- " | tuple ids: 0 \n" +
- " | \n" +
- " |----33:EXCHANGE\n" +
- " | limit: 3\n" +
- " | tuple ids: 7 \n" +
- " | \n" +
- " 31:EXCHANGE\n" +
- " tuple ids: 3 \n" +
- "\n" +
- "PLAN FRAGMENT 11\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: UNPARTITIONED\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 33\n" +
- " RANDOM\n" +
- "\n" +
- " 30:MERGING-EXCHANGE\n" +
- " limit: 3\n" +
- " tuple ids: 7 \n" +
- "\n" +
- "PLAN FRAGMENT 12\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 30\n" +
- " UNPARTITIONED\n" +
- "\n" +
- " 9:TOP-N\n" +
- " | order by: <slot 28> ASC\n" +
- " | offset: 0\n" +
- " | limit: 3\n" +
- " | tuple ids: 7 \n" +
- " | \n" +
- " 8:AGGREGATE (update finalize)\n" +
- " | group by: <slot 24>, <slot 25>, <slot 26>, <slot 27>\n" +
- " | tuple ids: 6 \n" +
- " | \n" +
- " 5:EXCEPT\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 6 \n" +
- " | \n" +
- " |----29:EXCHANGE\n" +
- " | tuple ids: 5 \n" +
- " | \n" +
- " 28:EXCHANGE\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 13\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 29\n" +
- " RANDOM\n" +
- "\n" +
- " 7:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 3\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 5 \n" +
- "\n" +
- "PLAN FRAGMENT 14\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 28\n" +
- " RANDOM\n" +
- "\n" +
- " 6:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 4 \n" +
- "\n" +
- "PLAN FRAGMENT 15\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 32\n" +
- " RANDOM\n" +
- "\n" +
- " 1:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'a', `k4` = 1\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 0 \n" +
- "\n" +
- "PLAN FRAGMENT 16\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 31\n" +
- " RANDOM\n" +
- "\n" +
- " 2:UNION\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 3 \n" +
- " | \n" +
- " |----27:EXCHANGE\n" +
- " | tuple ids: 2 \n" +
- " | \n" +
- " 26:EXCHANGE\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 17\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 27\n" +
- " RANDOM\n" +
- "\n" +
- " 4:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 2 \n" +
- "\n" +
- "PLAN FRAGMENT 18\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 26\n" +
- " RANDOM\n" +
- "\n" +
- " 3:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 2\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 1 \n" +
- "\n" +
- "PLAN FRAGMENT 19\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 36\n" +
- " RANDOM\n" +
- "\n" +
- " 15:AGGREGATE (update finalize)\n" +
- " | group by: <slot 40>, <slot 41>, <slot 42>, <slot 43>\n" +
- " | tuple ids: 10 \n" +
- " | \n" +
- " 12:INTERSECT\n" +
- " | child exprs: \n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | `default_cluster:db1.tbl1`.`k1` | `default_cluster:db1.tbl1`.`k2` | `default_cluster:db1.tbl1`.`k3` | `default_cluster:db1.tbl1`.`k4`\n" +
- " | pass-through-operands: all\n" +
- " | tuple ids: 10 \n" +
- " | \n" +
- " |----25:EXCHANGE\n" +
- " | tuple ids: 9 \n" +
- " | \n" +
- " 24:EXCHANGE\n" +
- " tuple ids: 8 \n" +
- "\n" +
- "PLAN FRAGMENT 20\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 25\n" +
- " RANDOM\n" +
- "\n" +
- " 14:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 4\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 9 \n" +
- "\n" +
- "PLAN FRAGMENT 21\n" +
- " OUTPUT EXPRS:\n" +
- " PARTITION: RANDOM\n" +
- "\n" +
- " STREAM DATA SINK\n" +
- " EXCHANGE ID: 24\n" +
- " RANDOM\n" +
- "\n" +
- " 13:OlapScanNode\n" +
- " TABLE: tbl1\n" +
- " PREAGGREGATION: OFF. Reason: No AggregateInfo\n" +
- " PREDICATES: `k1` = 'b', `k4` = 3\n" +
- " partitions=0/1\n" +
- " rollup: null\n" +
- " tabletRatio=0/0\n" +
- " tabletList=\n" +
- " cardinality=-1\n" +
- " avgRowSize=0.0\n" +
- " numNodes=0\n" +
- " tuple ids: 8 \n";
StmtExecutor stmtExecutor9 = new StmtExecutor(ctx, sql9);
stmtExecutor9.execute();
Planner planner9 = stmtExecutor9.planner();
List<PlanFragment> fragments9 = planner9.getFragments();
- Assert.assertEquals(plan9, planner9.getExplainString(fragments9, TExplainLevel.VERBOSE));
+ String plan9 = planner9.getExplainString(fragments9, TExplainLevel.VERBOSE);
+ Assert.assertEquals(2, StringUtils.countMatches(plan9, "UNION"));
+ Assert.assertEquals(3, StringUtils.countMatches(plan9, "INTERSECT"));
+ Assert.assertEquals(2, StringUtils.countMatches(plan9, "EXCEPT"));
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org