[ASTERIXDB-2044][COMP] Eliminate listify for complex group-by
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Fix EliminateSubplanWithInputCardinalityOneRule to handle recursive
subplans;
- Fix various places that assumes the nested plans inside a group-by
operator cannot be empty;
- Added regression tests.
Change-Id: Ida9aa8d89a89f90256e54c8c1806af9b4a162d21
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1946
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Yingyi Bu <buyingyi@gmail.com>
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/query-ASTERIXDB-810-2.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/query-ASTERIXDB-810-2.sqlpp
new file mode 100644
index 0000000..b6f6159
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/query-ASTERIXDB-810-2.sqlpp
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+/*
+ * Description : This test case is to verify the fix for issue810
+ * https://code.google.com/p/asterixdb/issues/detail?id=810
+ * Expected Res : SUCCESS
+ * Date : 16th Nov. 2014
+ */
+
+DROP DATAVERSE tpch IF EXISTS;
+CREATE dataverse tpch;
+
+USE tpch;
+
+
+CREATE TYPE LineItemType AS CLOSED {
+ l_orderkey : integer,
+ l_partkey : integer,
+ l_suppkey : integer,
+ l_linenumber : integer,
+ l_quantity : double,
+ l_extendedprice : double,
+ l_discount : double,
+ l_tax : double,
+ l_returnflag : string,
+ l_linestatus : string,
+ l_shipdate : string,
+ l_commitdate : string,
+ l_receiptdate : string,
+ l_shipinstruct : string,
+ l_shipmode : string,
+ l_comment : string
+}
+
+CREATE DATASET LineItem(LineItemType) PRIMARY KEY l_orderkey,l_linenumber;
+
+
+SELECT l_returnflag AS l_returnflag,
+ l_linestatus AS l_linestatus,
+ coll_count(cheap) AS count_cheaps,
+ coll_count(expensive) AS count_expensives
+FROM LineItem AS l
+/* +hash */
+GROUP BY l.l_returnflag AS l_returnflag,l.l_linestatus AS l_linestatus
+GROUP AS g
+LET cheap = (
+ SELECT ELEMENT g.l
+ FROM g
+ WHERE g.l.l_discount > 0.05
+),
+expensive = (
+ SELECT ELEMENT g.l
+ FROM g
+ WHERE g.l.l_discount <= 0.05
+)
+ORDER BY l_returnflag,l_linestatus
+;
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/query-ASTERIXDB-810.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/query-ASTERIXDB-810.sqlpp
new file mode 100644
index 0000000..451f163
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/query-ASTERIXDB-810.sqlpp
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+/*
+ * Description : This test case is to verify the fix for issue810
+ * https://code.google.com/p/asterixdb/issues/detail?id=810
+ * Expected Res : SUCCESS
+ * Date : 16th Nov. 2014
+ */
+
+DROP DATAVERSE tpch IF EXISTS;
+CREATE dataverse tpch;
+
+USE tpch;
+
+
+CREATE TYPE LineItemType AS CLOSED {
+ l_orderkey : integer,
+ l_partkey : integer,
+ l_suppkey : integer,
+ l_linenumber : integer,
+ l_quantity : double,
+ l_extendedprice : double,
+ l_discount : double,
+ l_tax : double,
+ l_returnflag : string,
+ l_linestatus : string,
+ l_shipdate : string,
+ l_commitdate : string,
+ l_receiptdate : string,
+ l_shipinstruct : string,
+ l_shipmode : string,
+ l_comment : string
+}
+
+CREATE DATASET LineItem(LineItemType) PRIMARY KEY l_orderkey,l_linenumber;
+
+
+SELECT l_returnflag AS l_returnflag,
+ l_linestatus AS l_linestatus,
+ coll_count(cheap) AS count_cheaps,
+ coll_count(expensive) AS count_expensives
+FROM LineItem AS l
+/* +hash */
+GROUP BY l.l_returnflag AS l_returnflag,l.l_linestatus AS l_linestatus
+GROUP AS g
+LET cheap = (
+ SELECT ELEMENT m
+ FROM (FROM g SELECT VALUE l) AS m
+ WHERE m.l_discount > 0.05
+),
+expensive = (
+ SELECT ELEMENT m
+ FROM (FROM g SELECT VALUE l) AS m
+ WHERE m.l_discount <= 0.05
+)
+ORDER BY l_returnflag,l_linestatus
+;
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-810-2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-810-2.plan
new file mode 100644
index 0000000..cad2fbb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-810-2.plan
@@ -0,0 +1,37 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$l_returnflag(ASC), $$l_linestatus(ASC) ] |PARTITIONED|
+ -- PRE_CLUSTERED_GROUP_BY[$$42, $$43] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$42(ASC), $$43(ASC)] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$42, $$43] |PARTITIONED|
+ -- PRE_CLUSTERED_GROUP_BY[$$30, $$31] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$30(ASC), $$31(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-810.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-810.plan
new file mode 100644
index 0000000..1c56f1c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/query-ASTERIXDB-810.plan
@@ -0,0 +1,39 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$l_returnflag(ASC), $$l_linestatus(ASC) ] |PARTITIONED|
+ -- PRE_CLUSTERED_GROUP_BY[$$42, $$43] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$42(ASC), $$43(ASC)] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$42, $$43] |PARTITIONED|
+ -- PRE_CLUSTERED_GROUP_BY[$$32, $$33] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$32(ASC), $$33(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-1.plan
index 1e60aed..f86825e 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-1.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-1.plan
@@ -27,15 +27,10 @@
-- AGGREGATE |LOCAL|
-- AGGREGATE |LOCAL|
-- STREAM_SELECT |UNPARTITIONED|
- -- UNNEST |UNPARTITIONED|
- -- SUBPLAN |UNPARTITIONED|
- {
- -- AGGREGATE |UNPARTITIONED|
- -- IN_MEMORY_STABLE_SORT [$$j(ASC)] |UNPARTITIONED|
- -- UNNEST |UNPARTITIONED|
- -- NESTED_TUPLE_SOURCE |UNPARTITIONED|
- }
- -- NESTED_TUPLE_SOURCE |UNPARTITIONED|
+ -- RUNNING_AGGREGATE |UNPARTITIONED|
+ -- IN_MEMORY_STABLE_SORT [$$j(ASC)] |UNPARTITIONED|
+ -- UNNEST |UNPARTITIONED|
+ -- NESTED_TUPLE_SOURCE |UNPARTITIONED|
}
-- ASSIGN |UNPARTITIONED|
-- EMPTY_TUPLE_SOURCE |UNPARTITIONED|
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/PreclusteredGroupByPOperator.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/PreclusteredGroupByPOperator.java
index a636d10..5a465f7 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/PreclusteredGroupByPOperator.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/PreclusteredGroupByPOperator.java
@@ -23,6 +23,7 @@
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.IHyracksJobBuilder;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
import org.apache.hyracks.algebricks.core.algebra.base.PhysicalOperatorTag;
@@ -70,7 +71,8 @@
AlgebricksPipeline[] subplans = compileSubplans(inputSchemas[0], gby, opSchema, context);
IAggregatorDescriptorFactory aggregatorFactory;
- if (gby.getNestedPlans().get(0).getRoots().get(0).getValue()
+ List<ILogicalPlan> nestedPlans = gby.getNestedPlans();
+ if (!nestedPlans.isEmpty() && nestedPlans.get(0).getRoots().get(0).getValue()
.getOperatorTag() == LogicalOperatorTag.RUNNINGAGGREGATE) {
aggregatorFactory = new NestedPlansRunningAggregatorFactory(subplans, keys, fdColumns);
} else {
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/typing/AbstractTypeEnvironment.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/typing/AbstractTypeEnvironment.java
index c4ff55b..f530820 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/typing/AbstractTypeEnvironment.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/typing/AbstractTypeEnvironment.java
@@ -52,11 +52,10 @@
@Override
public boolean substituteProducedVariable(LogicalVariable v1, LogicalVariable v2) throws AlgebricksException {
- Object t = varTypeMap.get(v1);
+ Object t = varTypeMap.remove(v1);
if (t == null) {
return false;
}
- varTypeMap.put(v1, null);
varTypeMap.put(v2, t);
return true;
}
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractIntroduceGroupByCombinerRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractIntroduceGroupByCombinerRule.java
index 4ef1cd5..e73f2a5 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractIntroduceGroupByCombinerRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/AbstractIntroduceGroupByCombinerRule.java
@@ -163,6 +163,11 @@
}
}
+ // Nothing is pushed.
+ if (bi.modifyGbyMap.isEmpty()) {
+ return null;
+ }
+
ArrayList<LogicalVariable> newOpGbyList = new ArrayList<LogicalVariable>();
ArrayList<LogicalVariable> replGbyList = new ArrayList<LogicalVariable>();
// Find maximal sequence of variable.
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushNestedOrderByUnderPreSortedGroupByRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushNestedOrderByUnderPreSortedGroupByRule.java
index bdab689..fc7b98e 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushNestedOrderByUnderPreSortedGroupByRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushNestedOrderByUnderPreSortedGroupByRule.java
@@ -64,6 +64,9 @@
return false;
}
GroupByOperator gby = (GroupByOperator) op;
+ if (gby.getNestedPlans().isEmpty()) {
+ return false;
+ }
ILogicalPlan plan = gby.getNestedPlans().get(0);
AbstractLogicalOperator op1 = (AbstractLogicalOperator) plan.getRoots().get(0).getValue();
if (op1.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/EliminateSubplanWithInputCardinalityOneRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/EliminateSubplanWithInputCardinalityOneRule.java
index 2cd857a..607ea1f 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/EliminateSubplanWithInputCardinalityOneRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/EliminateSubplanWithInputCardinalityOneRule.java
@@ -65,27 +65,39 @@
rootRef = opRef;
invoked = true;
}
+ return rewriteForOperator(rootRef, opRef, context);
+ }
+
+ private boolean rewriteForOperator(Mutable<ILogicalOperator> rootRef, Mutable<ILogicalOperator> opRef,
+ IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getInputs().size() <= 0) {
return false;
}
boolean changed = false;
- for (Mutable<ILogicalOperator> subplanRef : op.getInputs()) {
- AbstractLogicalOperator op1 = (AbstractLogicalOperator) subplanRef.getValue();
+
+ for (Mutable<ILogicalOperator> currentOpRef : op.getInputs()) {
+ AbstractLogicalOperator op1 = (AbstractLogicalOperator) currentOpRef.getValue();
if (op1.getOperatorTag() != LogicalOperatorTag.SUBPLAN) {
+ changed |= rewriteForOperator(rootRef, currentOpRef, context);
continue;
}
SubplanOperator subplan = (SubplanOperator) op1;
- Set<LogicalVariable> usedVarsUp = new ListSet<LogicalVariable>();
+ Set<LogicalVariable> usedVarsUp = new ListSet<>();
OperatorPropertiesUtil.getFreeVariablesInPath(rootRef.getValue(), subplan, usedVarsUp);
// TODO(buyingyi): figure out the rewriting for subplan operators with multiple subplans.
if (subplan.getNestedPlans().size() != 1) {
continue;
}
+ // Recursively rewrites the pipelines inside a nested subplan.
+ for (Mutable<ILogicalOperator> nestedRootRef : subplan.getNestedPlans().get(0).getRoots()) {
+ changed |= this.rewriteForOperator(nestedRootRef, nestedRootRef, context);
+ }
+
ILogicalOperator subplanInputOperator = subplan.getInputs().get(0).getValue();
- Set<LogicalVariable> subplanInputVars = new ListSet<LogicalVariable>();
+ Set<LogicalVariable> subplanInputVars = new ListSet<>();
VariableUtilities.getLiveVariables(subplanInputOperator, subplanInputVars);
int subplanInputVarSize = subplanInputVars.size();
subplanInputVars.removeAll(usedVarsUp);
@@ -93,31 +105,31 @@
if (subplanInputVars.size() < subplanInputVarSize) {
continue;
}
- Set<LogicalVariable> freeVars = new ListSet<LogicalVariable>();
+ Set<LogicalVariable> freeVars = new ListSet<>();
OperatorPropertiesUtil.getFreeVariablesInSubplans(subplan, freeVars);
boolean cardinalityOne = isCardinalityOne(subplan.getInputs().get(0), freeVars);
- if (cardinalityOne) {
- /** If the cardinality of freeVars in the subplan is one, the subplan can be removed. */
- ILogicalPlan plan = subplan.getNestedPlans().get(0);
-
- List<Mutable<ILogicalOperator>> rootRefs = plan.getRoots();
- // TODO(buyingyi): investigate the case of multi-root plans.
- if (rootRefs.size() != 1) {
- continue;
- }
-
- // Replaces all Nts' in the nested plan with the Subplan input operator or its deep copy.
- ILogicalOperator topOperator = rootRefs.get(0).getValue();
- ReplaceNtsWithSubplanInputOperatorVisitor visitor = new ReplaceNtsWithSubplanInputOperatorVisitor(
- context, subplan);
- ILogicalOperator newTopOperator = topOperator.accept(visitor, null);
- subplanRef.setValue(newTopOperator);
- OperatorManipulationUtil.computeTypeEnvironmentBottomUp(newTopOperator, context);
- changed = true;
- } else {
+ if (!cardinalityOne) {
continue;
}
+ /** If the cardinality of freeVars in the subplan is one, the subplan can be removed. */
+ ILogicalPlan plan = subplan.getNestedPlans().get(0);
+
+ List<Mutable<ILogicalOperator>> rootRefs = plan.getRoots();
+ // TODO(buyingyi): investigate the case of multi-root plans.
+ if (rootRefs.size() != 1) {
+ continue;
+ }
+
+ // Replaces all Nts' in the nested plan with the Subplan input operator or its deep copy.
+ ILogicalOperator topOperator = rootRefs.get(0).getValue();
+ ReplaceNtsWithSubplanInputOperatorVisitor visitor = new ReplaceNtsWithSubplanInputOperatorVisitor(context,
+ subplan);
+ ILogicalOperator newTopOperator = topOperator.accept(visitor, null);
+ currentOpRef.setValue(newTopOperator);
+ OperatorManipulationUtil.computeTypeEnvironmentBottomUp(newTopOperator, context);
+ changed = true;
}
+
return changed;
}
@@ -133,8 +145,8 @@
*/
private boolean isCardinalityOne(Mutable<ILogicalOperator> opRef, Set<LogicalVariable> freeVars)
throws AlgebricksException {
- Set<LogicalVariable> varsWithCardinalityOne = new ListSet<LogicalVariable>();
- Set<LogicalVariable> varsLiveAtUnnestAndJoin = new ListSet<LogicalVariable>();
+ Set<LogicalVariable> varsWithCardinalityOne = new ListSet<>();
+ Set<LogicalVariable> varsLiveAtUnnestAndJoin = new ListSet<>();
isCardinalityOne(opRef, freeVars, varsWithCardinalityOne, varsLiveAtUnnestAndJoin);
varsWithCardinalityOne.removeAll(varsLiveAtUnnestAndJoin);
return varsWithCardinalityOne.equals(freeVars);
@@ -158,7 +170,7 @@
Set<LogicalVariable> varsWithCardinalityOne, Set<LogicalVariable> varsLiveAtUnnestAndJoin)
throws AlgebricksException {
AbstractLogicalOperator operator = (AbstractLogicalOperator) opRef.getValue();
- List<LogicalVariable> liveVars = new ArrayList<LogicalVariable>();
+ List<LogicalVariable> liveVars = new ArrayList<>();
VariableUtilities.getLiveVariables(operator, liveVars);
if (OperatorPropertiesUtil.isCardinalityZeroOrOne(operator)) {
@@ -176,13 +188,6 @@
VariableUtilities.getLiveVariables(operator, varsLiveAtUnnestAndJoin);
}
}
-
- if (varsWithCardinalityOne.size() == freeVars.size()) {
- return;
- }
- for (Mutable<ILogicalOperator> childRef : operator.getInputs()) {
- isCardinalityOne(childRef, freeVars, varsWithCardinalityOne, varsLiveAtUnnestAndJoin);
- }
}
}