You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by bu...@apache.org on 2016/02/23 03:01:13 UTC

[3/3] incubator-asterixdb git commit: ASTERIXDB-1205: fix union queries.

ASTERIXDB-1205: fix union queries.

Fixed the AqlExpressionToPlanTranslator for union expression;
Eliminate shared operator references in translated logical plans;
Removed IntroduceUnionRule;
Fixed tuple source for SQL++ join clause;
Added regression tests.

Change-Id: Ib79a899ec4b35ece6f8f9f59b80126fed0c48851
Reviewed-on: https://asterix-gerrit.ics.uci.edu/629
Reviewed-by: Till Westmann <ti...@apache.org>
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>


Project: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/commit/1e7760c3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/tree/1e7760c3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/diff/1e7760c3

Branch: refs/heads/master
Commit: 1e7760c307a8be58f3e770401252b0d1cb9ef82a
Parents: 770f377
Author: Yingyi Bu <yi...@couchbase.com>
Authored: Mon Feb 22 16:25:42 2016 -0800
Committer: Yingyi Bu <bu...@gmail.com>
Committed: Mon Feb 22 17:55:32 2016 -0800

----------------------------------------------------------------------
 .../asterix/optimizer/base/RuleCollections.java |   9 +-
 .../asterix/optimizer/rules/FuzzyJoinRule.java  |   2 +-
 .../optimizer/rules/IntroduceUnionRule.java     | 127 ---------
 .../rules/am/InvertedIndexAccessMethod.java     |   6 +-
 .../subplan/InlineAllNtsInSubplanVisitor.java   |   6 +-
 .../AqlExpressionToPlanTranslator.java          |  68 +++--
 .../LangExpressionToPlanTranslator.java         | 117 +++++++-
 .../SqlppExpressionToPlanTranslator.java        |  24 +-
 .../asterix/translator/TranslationContext.java  |  26 +-
 .../queries/union/query-ASTERIXDB-1047.aql      |  40 +++
 .../queries/union/query-ASTERIXDB-1205-2.aql    |  28 ++
 .../queries/union/query-ASTERIXDB-1205-3.aql    |  25 ++
 .../queries/union/query-ASTERIXDB-1205-4.aql    |  30 +++
 .../queries/union/query-ASTERIXDB-1205.aql      |  29 ++
 .../optimizerts/queries/union/union_dataset.aql |  35 +++
 .../queries/union/union_dataset2.aql            |  33 +++
 .../queries/union/union_dataset3.aql            |  35 +++
 .../optimizerts/queries/union/union_query.aql   |  41 +++
 .../results/q05_local_supplier_volume.plan      |  10 +-
 .../optimizerts/results/q08_group_by.plan       |  12 +-
 .../optimizerts/results/q09_group_by.plan       |   6 +-
 .../optimizerts/results/query-issue562.plan     |  74 +++---
 .../split-materialization-above-join.plan       | 264 ++++++++++---------
 .../results/union/query-ASTERIXDB-1047.plan     |  19 ++
 .../results/union/query-ASTERIXDB-1205-2.plan   |  19 ++
 .../results/union/query-ASTERIXDB-1205-3.plan   |  15 ++
 .../results/union/query-ASTERIXDB-1205-4.plan   |  27 ++
 .../results/union/query-ASTERIXDB-1205.plan     |  19 ++
 .../results/union/union_dataset.plan            |  21 ++
 .../results/union/union_dataset2.plan           |  17 ++
 .../results/union/union_dataset3.plan           |  21 ++
 .../optimizerts/results/union/union_query.plan  |  19 ++
 .../query-ASTERIXDB-1047.1.ddl.aql              |  33 +++
 .../query-ASTERIXDB-1047.2.update.aql           |  24 ++
 .../query-ASTERIXDB-1047.3.query.aql            |  31 +++
 .../query-ASTERIXDB-1205.1.ddl.aql              |  19 ++
 .../query-ASTERIXDB-1205.2.update.aql           |  18 ++
 .../query-ASTERIXDB-1205.3.query.aql            |  28 ++
 .../query-ASTERIXDB-1205.1.ddl.aql              |  19 ++
 .../query-ASTERIXDB-1205.2.update.aql           |  18 ++
 .../query-ASTERIXDB-1205.3.query.aql            |  30 +++
 .../query-ASTERIXDB-1205.1.ddl.aql              |  19 ++
 .../query-ASTERIXDB-1205.2.update.aql           |  18 ++
 .../query-ASTERIXDB-1205.3.query.aql            |  29 ++
 .../query-ASTERIXDB-300.1.ddl.aql               |  19 ++
 .../query-ASTERIXDB-300.2.update.aql            |  18 ++
 .../query-ASTERIXDB-300.3.query.aql             |  35 +++
 .../queries/union/union/union.3.query.aql       |   2 +-
 .../queries/union/union2/union.1.ddl.aql        |  29 ++
 .../queries/union/union2/union.2.update.aql     |  22 ++
 .../queries/union/union2/union.3.query.aql      |  22 ++
 .../custord/join_q_04/join_q_04.1.ddl.sqlpp     |   1 +
 .../custord/join_q_05/join_q_05.1.ddl.sqlpp     |  61 +++++
 .../custord/join_q_05/join_q_05.2.update.sqlpp  |  20 ++
 .../custord/join_q_05/join_q_05.3.query.sqlpp   |  31 +++
 .../custord/join_q_06/join_q_06.1.ddl.sqlpp     |  47 ++++
 .../custord/join_q_06/join_q_06.2.update.sqlpp  |  20 ++
 .../custord/join_q_06/join_q_06.3.query.sqlpp   |  30 +++
 .../custord/join_q_07/join_q_07.1.ddl.sqlpp     |  47 ++++
 .../custord/join_q_07/join_q_07.2.update.sqlpp  |  20 ++
 .../custord/join_q_07/join_q_07.3.query.sqlpp   |  35 +++
 .../results/custord/join_q_06/join_q_06.1.adm   |   1 +
 .../query-ASTERIXDB-1047.1.adm                  |   3 +
 .../query-ASTERIXDB-1205-2.1.adm                |   5 +
 .../query-ASTERIXDB-1205-3.1.adm                |   7 +
 .../query-ASTERIXDB-1205.1.adm                  |   5 +
 .../query-ASTERIXDB-300.1.adm                   |   1 +
 .../runtimets/results/union/union/union.1.adm   |  18 +-
 .../runtimets/results/union/union2/union2.1.adm |  20 ++
 .../custord/join_q_04/join_q_04.1.ast           |  36 +++
 .../src/test/resources/runtimets/testsuite.xml  |  30 +++
 .../resources/runtimets/testsuite_sqlpp.xml     |  16 ++
 .../om/functions/AsterixBuiltinFunctions.java   |   3 -
 73 files changed, 1738 insertions(+), 376 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
index ae0b2f6..ad5283a 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
@@ -48,7 +48,6 @@ import org.apache.asterix.optimizer.rules.IntroduceRandomPartitioningFeedComputa
 import org.apache.asterix.optimizer.rules.IntroduceRapidFrameFlushProjectAssignRule;
 import org.apache.asterix.optimizer.rules.IntroduceSecondaryIndexInsertDeleteRule;
 import org.apache.asterix.optimizer.rules.IntroduceStaticTypeCastForInsertRule;
-import org.apache.asterix.optimizer.rules.IntroduceUnionRule;
 import org.apache.asterix.optimizer.rules.IntroduceUnnestForCollectionToSequenceRule;
 import org.apache.asterix.optimizer.rules.LoadRecordFieldsRule;
 import org.apache.asterix.optimizer.rules.NestGroupByRule;
@@ -78,7 +77,6 @@ import org.apache.asterix.optimizer.rules.temporal.TranslateIntervalExpressionRu
 import org.apache.hyracks.algebricks.core.rewriter.base.HeuristicOptimizer;
 import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 import org.apache.hyracks.algebricks.rewriter.rules.BreakSelectIntoConjunctsRule;
-import org.apache.hyracks.algebricks.rewriter.rules.ComplexJoinInferenceRule;
 import org.apache.hyracks.algebricks.rewriter.rules.ComplexUnnestToProductRule;
 import org.apache.hyracks.algebricks.rewriter.rules.ConsolidateAssignsRule;
 import org.apache.hyracks.algebricks.rewriter.rules.ConsolidateSelectsRule;
@@ -110,6 +108,7 @@ import org.apache.hyracks.algebricks.rewriter.rules.PushSortDownRule;
 import org.apache.hyracks.algebricks.rewriter.rules.PushSubplanWithAggregateDownThroughProductRule;
 import org.apache.hyracks.algebricks.rewriter.rules.PushUnnestDownThroughUnionRule;
 import org.apache.hyracks.algebricks.rewriter.rules.ReinferAllTypesRule;
+import org.apache.hyracks.algebricks.rewriter.rules.RemoveCartesianProductWithEmptyBranchRule;
 import org.apache.hyracks.algebricks.rewriter.rules.RemoveRedundantGroupByDecorVars;
 import org.apache.hyracks.algebricks.rewriter.rules.RemoveRedundantVariablesRule;
 import org.apache.hyracks.algebricks.rewriter.rules.RemoveUnnecessarySortMergeExchange;
@@ -183,7 +182,6 @@ public final class RuleCollections {
         condPushDownAndJoinInference.add(new CancelUnnestWithNestedListifyRule());
         condPushDownAndJoinInference.add(new SimpleUnnestToProductRule());
         condPushDownAndJoinInference.add(new ComplexUnnestToProductRule());
-        condPushDownAndJoinInference.add(new ComplexJoinInferenceRule());
         condPushDownAndJoinInference.add(new DisjunctivePredicateToJoinRule());
         condPushDownAndJoinInference.add(new PushSelectIntoJoinRule());
         condPushDownAndJoinInference.add(new IntroJoinInsideSubplanRule());
@@ -222,7 +220,6 @@ public final class RuleCollections {
         fieldLoads.add(new ConstantFoldingRule());
         fieldLoads.add(new RemoveRedundantSelectRule());
         fieldLoads.add(new FeedScanCollectionToUnnest());
-        fieldLoads.add(new ComplexJoinInferenceRule());
         fieldLoads.add(new InlineSubplanInputForNestedTupleSourceRule());
         return fieldLoads;
     }
@@ -244,8 +241,7 @@ public final class RuleCollections {
         consolidation.add(new CountVarToCountOneRule());
         consolidation.add(new RemoveUnusedAssignAndAggregateRule());
         consolidation.add(new RemoveRedundantGroupByDecorVars());
-        //unionRule => PushUnnestDownUnion => RemoveRedundantListifyRule cause these rules are correlated
-        consolidation.add(new IntroduceUnionRule());
+        //PushUnnestDownUnion => RemoveRedundantListifyRule cause these rules are correlated
         consolidation.add(new PushUnnestDownThroughUnionRule());
         consolidation.add(new RemoveRedundantListifyRule());
         return consolidation;
@@ -274,6 +270,7 @@ public final class RuleCollections {
         planCleanupRules.add(new IntroduceDynamicTypeCastRule());
         planCleanupRules.add(new IntroduceDynamicTypeCastForExternalFunctionRule());
         planCleanupRules.add(new RemoveUnusedAssignAndAggregateRule());
+        planCleanupRules.add(new RemoveCartesianProductWithEmptyBranchRule());
         return planCleanupRules;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
index 99a418e..427eda7 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
@@ -266,7 +266,7 @@ public class FuzzyJoinRule implements IAlgebraicRewriteRule {
         context.setVarCounter(counter.get());
 
         LogicalOperatorDeepCopyWithNewVariablesVisitor deepCopyVisitor = new LogicalOperatorDeepCopyWithNewVariablesVisitor(
-                context);
+                context, context);
 
         translator.addOperatorToMetaScope(new Identifier("#LEFT"), leftInputOp);
         translator.addVariableToMetaScope(new Identifier("$$LEFT"), leftInputVar);

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceUnionRule.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceUnionRule.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceUnionRule.java
deleted file mode 100644
index 51d04a6..0000000
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceUnionRule.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.asterix.optimizer.rules;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang3.mutable.Mutable;
-
-import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.utils.Triple;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
-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.expressions.AbstractFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
-import org.apache.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil;
-import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
-
-/**
- * @author kereno, ecarm002, ildar.absalyamov
- *         Generates a union operator and puts it instead of "assign <- [function-call: asterix:union]"
- *         Before rule:
- *         ============
- *         assign [var] <- [asterix:union(left_branch, right_branch)]
- *         join (TRUE)
- *         left_branch
- *         right_branch
- *         After rule:
- *         ============
- *         union (left_branch, right_branch, result_var)
- *         left_branch
- *         right_branch
- */
-public class IntroduceUnionRule implements IAlgebraicRewriteRule {
-
-    @Override
-    public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) {
-        return false;
-    }
-
-    @Override
-    public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
-            throws AlgebricksException {
-
-        if (!opRef.getValue().getOperatorTag().equals(LogicalOperatorTag.ASSIGN)) {
-            return false;
-        }
-
-        AssignOperator assignUnion = (AssignOperator) opRef.getValue();
-
-        if (assignUnion.getExpressions().get(0).getValue().getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL)
-            return false;
-
-        AbstractFunctionCallExpression u = (AbstractFunctionCallExpression) assignUnion.getExpressions().get(0)
-                .getValue();
-        if (!AsterixBuiltinFunctions.UNION.equals(u.getFunctionIdentifier())) {
-            return false;
-        }
-
-        //Retrieving the logical variables for the union from the two aggregates which are inputs to the join
-        Mutable<ILogicalOperator> join = assignUnion.getInputs().get(0);
-
-        LogicalOperatorTag tag1 = join.getValue().getOperatorTag();
-        if (tag1 != LogicalOperatorTag.INNERJOIN && tag1 != LogicalOperatorTag.LEFTOUTERJOIN) {
-            return false;
-        }
-        AbstractBinaryJoinOperator join1 = (AbstractBinaryJoinOperator) join.getValue();
-        ILogicalExpression cond1 = join1.getCondition().getValue();
-        // don't try to push a product down
-        if (!OperatorPropertiesUtil.isAlwaysTrueCond(cond1)) {
-            return false;
-        }
-
-        List<Mutable<ILogicalOperator>> joinInputs = join.getValue().getInputs();
-
-        Mutable<ILogicalOperator> left_branch = joinInputs.get(0);
-        Mutable<ILogicalOperator> right_branch = joinInputs.get(1);
-
-        List<LogicalVariable> input1Var = new ArrayList<LogicalVariable>();
-        VariableUtilities.getProducedVariables(left_branch.getValue(), input1Var);
-
-        List<LogicalVariable> input2Var = new ArrayList<LogicalVariable>();
-        VariableUtilities.getProducedVariables(right_branch.getValue(), input2Var);
-
-        List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> varMap = new ArrayList<Triple<LogicalVariable, LogicalVariable, LogicalVariable>>(
-                1);
-        Triple<LogicalVariable, LogicalVariable, LogicalVariable> triple = new Triple<LogicalVariable, LogicalVariable, LogicalVariable>(
-                input1Var.get(0), input2Var.get(0), assignUnion.getVariables().get(0));
-        varMap.add(triple);
-        UnionAllOperator unionOp = new UnionAllOperator(varMap);
-
-        unionOp.getInputs().add(left_branch);
-        unionOp.getInputs().add(right_branch);
-
-        context.computeAndSetTypeEnvironmentForOperator(unionOp);
-
-        opRef.setValue(unionOp);
-
-        return true;
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
index d8e4c6a..824fe7a 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
@@ -610,13 +610,13 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
 
         // Create first copy.
         LogicalOperatorDeepCopyWithNewVariablesVisitor firstDeepCopyVisitor = new LogicalOperatorDeepCopyWithNewVariablesVisitor(
-                context, newProbeSubTreeVarMap);
+                context, context, newProbeSubTreeVarMap);
         ILogicalOperator newProbeSubTree = firstDeepCopyVisitor.deepCopy(probeSubTree.root);
         inferTypes(newProbeSubTree, context);
         Mutable<ILogicalOperator> newProbeSubTreeRootRef = new MutableObject<ILogicalOperator>(newProbeSubTree);
         // Create second copy.
         LogicalOperatorDeepCopyWithNewVariablesVisitor secondDeepCopyVisitor = new LogicalOperatorDeepCopyWithNewVariablesVisitor(
-                context, joinInputSubTreeVarMap);
+                context, context, joinInputSubTreeVarMap);
         ILogicalOperator joinInputSubTree = secondDeepCopyVisitor.deepCopy(probeSubTree.root);
         inferTypes(joinInputSubTree, context);
         probeSubTree.rootRef.setValue(joinInputSubTree);
@@ -694,7 +694,7 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
 
         // Copy the scan subtree in indexSubTree.
         LogicalOperatorDeepCopyWithNewVariablesVisitor deepCopyVisitor = new LogicalOperatorDeepCopyWithNewVariablesVisitor(
-                context);
+                context, context);
         ILogicalOperator scanSubTree = deepCopyVisitor.deepCopy(indexSubTree.root);
 
         Map<LogicalVariable, LogicalVariable> copyVarMap = deepCopyVisitor.getInputToOutputVariableMapping();

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/InlineAllNtsInSubplanVisitor.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/InlineAllNtsInSubplanVisitor.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/InlineAllNtsInSubplanVisitor.java
index b3e07e5..beebe0f 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/InlineAllNtsInSubplanVisitor.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/InlineAllNtsInSubplanVisitor.java
@@ -402,7 +402,7 @@ class InlineAllNtsInSubplanVisitor implements IQueryOperatorVisitor<ILogicalOper
             return op;
         }
         LogicalOperatorDeepCopyWithNewVariablesVisitor deepCopyVisitor = new LogicalOperatorDeepCopyWithNewVariablesVisitor(
-                context);
+                context, context);
         ILogicalOperator copiedInputOperator = deepCopyVisitor.deepCopy(subplanInputOperator);
 
         // Updates the primary key info in the copied plan segment.
@@ -668,9 +668,7 @@ class InlineAllNtsInSubplanVisitor implements IQueryOperatorVisitor<ILogicalOper
 
     private void subtituteVariables(ILogicalOperator op) throws AlgebricksException {
         VariableUtilities.substituteVariables(op, subplanInputVarToCurrentVarMap, context);
-        for (Pair<LogicalVariable, LogicalVariable> pair : varMapIntroducedByRewriting) {
-            VariableUtilities.substituteVariables(op, pair.first, pair.second, context);
-        }
+        VariableUtilities.substituteVariables(op, varMapIntroducedByRewriting, context);
     }
 
     private void updateInputToOutputVarMapping(LogicalVariable oldVar, LogicalVariable newVar, boolean inNts) {

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java b/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
index 097edbd..48c9a7f 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.translator;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
@@ -41,17 +42,17 @@ import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.commons.lang3.mutable.MutableObject;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.common.utils.Triple;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistinctOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
 
 /**
@@ -133,7 +134,7 @@ class AqlExpressionToPlanTranslator extends LangExpressionToPlanTranslator imple
             result = produceFlworPlan(noFlworClause, isTop, resOpRef, rRes.second);
         }
         if (!isTop) {
-            context.existSubplan();
+            context.exitSubplan();
         }
 
         return result;
@@ -163,22 +164,53 @@ class AqlExpressionToPlanTranslator extends LangExpressionToPlanTranslator imple
     @Override
     public Pair<ILogicalOperator, LogicalVariable> visit(UnionExpr unionExpr, Mutable<ILogicalOperator> tupSource)
             throws AsterixException {
-        //Translate the AQL union into an assign [var] <- [function-call: asterix:union, Args:[..]]
-        //The rule "IntroduceUnionRule" will translates this assign operator into the UnionAll operator.
-        Mutable<ILogicalOperator> ts = tupSource;
-        LogicalVariable assignedVar = context.newVar();
-        List<Mutable<ILogicalExpression>> inputVars = new ArrayList<Mutable<ILogicalExpression>>();
+        List<Mutable<ILogicalOperator>> inputOpRefsToUnion = new ArrayList<>();
+        List<LogicalVariable> vars = new ArrayList<>();
         for (Expression e : unionExpr.getExprs()) {
-            Pair<ILogicalOperator, LogicalVariable> op_var = e.accept(this, ts);
-            ts = new MutableObject<ILogicalOperator>(op_var.first);
-            VariableReferenceExpression var = new VariableReferenceExpression(op_var.second);
-            inputVars.add(new MutableObject<ILogicalExpression>(var));
+            // Visits the expression of one branch.
+            Pair<ILogicalOperator, LogicalVariable> opAndVar = e.accept(this, tupSource);
+
+            // Creates an unnest operator.
+            LogicalVariable unnestVar = context.newVar();
+            List<Mutable<ILogicalExpression>> args = new ArrayList<>();
+            args.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(opAndVar.second)));
+            UnnestOperator unnestOp = new UnnestOperator(unnestVar,
+                    new MutableObject<ILogicalExpression>(new UnnestingFunctionCallExpression(
+                            FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SCAN_COLLECTION), args)));
+            unnestOp.getInputs().add(new MutableObject<ILogicalOperator>(opAndVar.first));
+            inputOpRefsToUnion.add(new MutableObject<ILogicalOperator>(unnestOp));
+            vars.add(unnestVar);
         }
-        AbstractFunctionCallExpression union = new ScalarFunctionCallExpression(
-                FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.UNION), inputVars);
-        AssignOperator a = new AssignOperator(assignedVar, new MutableObject<ILogicalExpression>(union));
-        a.getInputs().add(ts);
-        return new Pair<ILogicalOperator, LogicalVariable>(a, assignedVar);
+
+        // Creates a tree of binary union-all operators.
+        UnionAllOperator topUnionAllOp = null;
+        LogicalVariable topUnionVar = null;
+        Iterator<Mutable<ILogicalOperator>> inputOpRefIterator = inputOpRefsToUnion.iterator();
+        Mutable<ILogicalOperator> leftInputBranch = inputOpRefIterator.next();
+        Iterator<LogicalVariable> inputVarIterator = vars.iterator();
+        LogicalVariable leftInputVar = inputVarIterator.next();
+
+        while (inputOpRefIterator.hasNext()) {
+            // Generates the variable triple <leftVar, rightVar, outputVar> .
+            topUnionVar = context.newVar();
+            Triple<LogicalVariable, LogicalVariable, LogicalVariable> varTriple = new Triple<>(leftInputVar,
+                    inputVarIterator.next(), topUnionVar);
+            List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> varTriples = new ArrayList<>();
+            varTriples.add(varTriple);
+
+            // Creates a binary union-all operator.
+            topUnionAllOp = new UnionAllOperator(varTriples);
+            topUnionAllOp.getInputs().add(leftInputBranch);
+            topUnionAllOp.getInputs().add(inputOpRefIterator.next());
+
+            // Re-assigns leftInputBranch and leftInputVar.
+            leftInputBranch = new MutableObject<ILogicalOperator>(topUnionAllOp);
+            leftInputVar = topUnionVar;
+        }
+
+        Pair<ILogicalOperator, LogicalVariable> result = aggListifyForSubquery(topUnionVar,
+                new MutableObject<ILogicalOperator>(topUnionAllOp), false);
+        return result;
     }
 
     private Pair<ILogicalOperator, LogicalVariable> produceFlworPlan(boolean noForClause, boolean isTop,

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index a1a6d4b..dd4d6db 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -21,8 +21,12 @@ package org.apache.asterix.translator;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
@@ -112,6 +116,7 @@ import org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFun
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
@@ -129,6 +134,8 @@ import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperat
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SinkOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.LogicalOperatorDeepCopyWithNewVariablesVisitor;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
 import org.apache.hyracks.algebricks.core.algebra.properties.LocalOrderProperty;
 import org.apache.hyracks.algebricks.core.algebra.properties.OrderColumn;
@@ -403,6 +410,7 @@ class LangExpressionToPlanTranslator
         }
         globalPlanRoots.add(new MutableObject<ILogicalOperator>(topOp));
         ILogicalPlan plan = new ALogicalPlanImpl(globalPlanRoots);
+        eliminateSharedOperatorReferenceForPlan(plan);
         return plan;
     }
 
@@ -721,7 +729,7 @@ class LangExpressionToPlanTranslator
         SelectOperator sel1 = new SelectOperator(
                 new MutableObject<ILogicalExpression>(new VariableReferenceExpression(varCond)), false, null);
         sel1.getInputs().add(new MutableObject<ILogicalOperator>(pThen.first));
-        context.existSubplan();
+        context.exitSubplan();
 
         context.enterSubplan();
         Pair<ILogicalOperator, LogicalVariable> pElse = ifexpr.getElseExpr().accept(this, nestedSource);
@@ -730,7 +738,7 @@ class LangExpressionToPlanTranslator
                 new MutableObject<ILogicalExpression>(new VariableReferenceExpression(varCond)));
         SelectOperator sel2 = new SelectOperator(new MutableObject<ILogicalExpression>(notVarCond), false, null);
         sel2.getInputs().add(new MutableObject<ILogicalOperator>(pElse.first));
-        context.existSubplan();
+        context.exitSubplan();
 
         ILogicalPlan p1 = new ALogicalPlanImpl(new MutableObject<ILogicalOperator>(sel1));
         sp.getNestedPlans().add(p1);
@@ -1228,7 +1236,7 @@ class LangExpressionToPlanTranslator
         return k == Kind.LITERAL_EXPRESSION || k == Kind.LIST_CONSTRUCTOR_EXPRESSION
                 || k == Kind.RECORD_CONSTRUCTOR_EXPRESSION || k == Kind.VARIABLE_EXPRESSION || k == Kind.CALL_EXPRESSION
                 || k == Kind.OP_EXPRESSION || k == Kind.FIELD_ACCESSOR_EXPRESSION || k == Kind.INDEX_ACCESSOR_EXPRESSION
-                || k == Kind.UNARY_EXPRESSION || k == Kind.UNION_EXPRESSION;
+                || k == Kind.UNARY_EXPRESSION;
     }
 
     protected <T> List<T> mkSingletonArrayList(T item) {
@@ -1238,11 +1246,12 @@ class LangExpressionToPlanTranslator
     }
 
     protected ILogicalExpression makeUnnestExpression(ILogicalExpression expr) {
+        List<Mutable<ILogicalExpression>> argRefs = new ArrayList<>();
+        argRefs.add(new MutableObject<ILogicalExpression>(expr));
         switch (expr.getExpressionTag()) {
             case VARIABLE: {
                 return new UnnestingFunctionCallExpression(
-                        FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SCAN_COLLECTION),
-                        new MutableObject<ILogicalExpression>(expr));
+                        FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SCAN_COLLECTION), argRefs);
             }
             case FUNCTION_CALL: {
                 AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) expr;
@@ -1250,8 +1259,7 @@ class LangExpressionToPlanTranslator
                     return expr;
                 } else {
                     return new UnnestingFunctionCallExpression(
-                            FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SCAN_COLLECTION),
-                            new MutableObject<ILogicalExpression>(expr));
+                            FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SCAN_COLLECTION), argRefs);
                 }
             }
             default: {
@@ -1277,4 +1285,99 @@ class LangExpressionToPlanTranslator
         return false;
     }
 
+    /**
+     * Eliminate shared operator references in a query plan.
+     * Deep copy a new query plan subtree whenever there is a shared operator reference.
+     *
+     * @param plan,
+     *            the query plan.
+     * @throws AsterixException
+     */
+    private void eliminateSharedOperatorReferenceForPlan(ILogicalPlan plan) throws AsterixException {
+        for (Mutable<ILogicalOperator> opRef : plan.getRoots()) {
+            Set<Mutable<ILogicalOperator>> opRefSet = new HashSet<>();
+            eliminateSharedOperatorReference(opRef, opRefSet);
+        }
+    }
+
+    /**
+     * Eliminate shared operator references in a query plan rooted at <code>currentOpRef.getValue()</code>.
+     * Deep copy a new query plan subtree whenever there is a shared operator reference.
+     *
+     * @param currentOpRef,
+     *            the operator reference to consider
+     * @param opRefSet,
+     *            the set storing seen operator references so far.
+     * @return a mapping that maps old variables to new variables, for the ancestors of
+     *         <code>currentOpRef</code> to replace variables properly.
+     * @throws AsterixException
+     */
+    private Map<LogicalVariable, LogicalVariable> eliminateSharedOperatorReference(
+            Mutable<ILogicalOperator> currentOpRef, Set<Mutable<ILogicalOperator>> opRefSet) throws AsterixException {
+        try {
+            opRefSet.add(currentOpRef);
+            AbstractLogicalOperator currentOperator = (AbstractLogicalOperator) currentOpRef.getValue();
+
+            // Recursively eliminates shared references in nested plans.
+            if (currentOperator.hasNestedPlans()) {
+                // Since a nested plan tree itself can never be shared with another nested plan tree in
+                // another operator, the operation called in the if block does not need to replace
+                // any variables further for <code>currentOpRef.getValue()</code> nor its ancestor.
+                AbstractOperatorWithNestedPlans opWithNestedPlan = (AbstractOperatorWithNestedPlans) currentOperator;
+                for (ILogicalPlan plan : opWithNestedPlan.getNestedPlans()) {
+                    for (Mutable<ILogicalOperator> rootRef : plan.getRoots()) {
+                        Set<Mutable<ILogicalOperator>> nestedOpRefSet = new HashSet<>();
+                        eliminateSharedOperatorReference(rootRef, nestedOpRefSet);
+                    }
+                }
+            }
+
+            int childIndex = 0;
+            Map<LogicalVariable, LogicalVariable> varMap = new HashMap<>();
+            for (Mutable<ILogicalOperator> childRef : currentOperator.getInputs()) {
+                if (opRefSet.contains(childRef)) {
+                    // There is a shared operator reference in the query plan.
+                    // Deep copies the child plan.
+                    LogicalOperatorDeepCopyWithNewVariablesVisitor visitor = new LogicalOperatorDeepCopyWithNewVariablesVisitor(
+                            context, null);
+                    ILogicalOperator newChild = childRef.getValue().accept(visitor, null);
+                    Map<LogicalVariable, LogicalVariable> cloneVarMap = visitor.getInputToOutputVariableMapping();
+
+                    // Substitute variables according to the deep copy which generates new variables.
+                    VariableUtilities.substituteVariables(currentOperator, cloneVarMap, null);
+                    varMap.putAll(cloneVarMap);
+
+                    // Sets the new child.
+                    childRef = new MutableObject<ILogicalOperator>(newChild);
+                    currentOperator.getInputs().set(childIndex, childRef);
+                }
+
+                // Recursively eliminate shared operator reference for the operator subtree,
+                // even if it is a deep copy of some other one.
+                Map<LogicalVariable, LogicalVariable> childVarMap = eliminateSharedOperatorReference(childRef,
+                        opRefSet);
+                // Substitute variables according to the new subtree.
+                VariableUtilities.substituteVariables(currentOperator, childVarMap, null);
+
+                // Updates mapping like <$a, $b> in varMap to <$a, $c>, where there is a mapping <$b, $c>
+                // in childVarMap.
+                for (Map.Entry<LogicalVariable, LogicalVariable> entry : varMap.entrySet()) {
+                    LogicalVariable newVar = childVarMap.get(entry.getValue());
+                    if (newVar != null) {
+                        entry.setValue(newVar);
+                    }
+                }
+                varMap.putAll(childVarMap);
+                ++childIndex;
+            }
+
+            // Only retain live variables for parent operators to substitute variables.
+            Set<LogicalVariable> liveVars = new HashSet<>();
+            VariableUtilities.getLiveVariables(currentOperator, liveVars);
+            varMap.values().retainAll(liveVars);
+            return varMap;
+        } catch (AlgebricksException e) {
+            throw new AsterixException(e);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java b/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index a708cf6..b3d6bea 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -20,9 +20,11 @@ package org.apache.asterix.translator;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Stack;
 
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
 import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Clause.ClauseType;
 import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.clause.LetClause;
@@ -72,7 +74,6 @@ import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBina
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistinctOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.OuterUnnestOperator;
@@ -92,6 +93,7 @@ import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
  */
 class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator implements ILangExpressionToPlanTranslator,
         ISqlppVisitor<Pair<ILogicalOperator, LogicalVariable>, Mutable<ILogicalOperator>> {
+    private Stack<Mutable<ILogicalOperator>> uncorrelatedLeftBranchStack = new Stack<Mutable<ILogicalOperator>>();
 
     public SqlppExpressionToPlanTranslator(AqlMetadataProvider metadataProvider, int currentVarCounter)
             throws AlgebricksException {
@@ -145,7 +147,7 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
         Pair<ILogicalOperator, LogicalVariable> result = produceSelectPlan(selectExpression.isSubquery(), currentOpRef,
                 select.second);
         if (selectExpression.isSubquery()) {
-            context.existSubplan();
+            context.exitSubplan();
         }
         return result;
     }
@@ -230,7 +232,14 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
         Mutable<ILogicalOperator> topOpRef = new MutableObject<ILogicalOperator>(unnestOp);
         if (fromTerm.hasCorrelateClauses()) {
             for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
-                topOpRef = new MutableObject<ILogicalOperator>(correlateClause.accept(this, topOpRef).first);
+                if (correlateClause.getClauseType() == ClauseType.UNNEST_CLAUSE) {
+                    // Correlation is allowed.
+                    topOpRef = new MutableObject<ILogicalOperator>(correlateClause.accept(this, topOpRef).first);
+                } else {
+                    // Correlation is dis-allowed.
+                    uncorrelatedLeftBranchStack.push(topOpRef);
+                    topOpRef = new MutableObject<ILogicalOperator>(correlateClause.accept(this, tupSource).first);
+                }
             }
         }
         return new Pair<ILogicalOperator, LogicalVariable>(topOpRef.getValue(), fromVar);
@@ -239,12 +248,13 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
     @Override
     public Pair<ILogicalOperator, LogicalVariable> visit(JoinClause joinClause, Mutable<ILogicalOperator> inputRef)
             throws AsterixException {
+        Mutable<ILogicalOperator> leftInputRef = uncorrelatedLeftBranchStack.pop();
         if (joinClause.getJoinType() == JoinType.INNER) {
             Pair<ILogicalOperator, LogicalVariable> rightBranch = generateUnnestForBinaryCorrelateRightBranch(
-                    joinClause, new MutableObject<ILogicalOperator>(new EmptyTupleSourceOperator()));
+                    joinClause, inputRef);
             // A join operator with condition TRUE.
             AbstractBinaryJoinOperator joinOperator = new InnerJoinOperator(
-                    new MutableObject<ILogicalExpression>(ConstantExpression.TRUE), inputRef,
+                    new MutableObject<ILogicalExpression>(ConstantExpression.TRUE), leftInputRef,
                     new MutableObject<ILogicalOperator>(rightBranch.first));
             Mutable<ILogicalOperator> joinOpRef = new MutableObject<ILogicalOperator>(joinOperator);
 
@@ -260,7 +270,7 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
             SubplanOperator subplanOp = new SubplanOperator();
             Mutable<ILogicalOperator> ntsRef = new MutableObject<ILogicalOperator>(
                     new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(subplanOp)));
-            subplanOp.getInputs().add(inputRef);
+            subplanOp.getInputs().add(leftInputRef);
 
             // Enters the translation for a subplan.
             context.enterSubplan();
@@ -322,7 +332,7 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
             aggOp.getInputs().add(new MutableObject<ILogicalOperator>(currentTopOp));
 
             // Exits the translation of a subplan.
-            context.existSubplan();
+            context.exitSubplan();
 
             // Sets the nested subplan of the subplan operator.
             ILogicalPlan subplan = new ALogicalPlanImpl(new MutableObject<ILogicalOperator>(aggOp));

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-algebra/src/main/java/org/apache/asterix/translator/TranslationContext.java
----------------------------------------------------------------------
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/translator/TranslationContext.java b/asterix-algebra/src/main/java/org/apache/asterix/translator/TranslationContext.java
index 84a01b5..71de5ac 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/translator/TranslationContext.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/translator/TranslationContext.java
@@ -24,9 +24,10 @@ import java.util.Stack;
 
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.hyracks.algebricks.core.algebra.base.Counter;
+import org.apache.hyracks.algebricks.core.algebra.base.IVariableContext;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
 
-public final class TranslationContext {
+public final class TranslationContext implements IVariableContext {
 
     private Counter varCounter;
 
@@ -39,10 +40,24 @@ public final class TranslationContext {
         this.varCounter = varCounter;
     }
 
+    @Override
     public int getVarCounter() {
         return varCounter.get();
     }
 
+    @Override
+    public LogicalVariable newVar() {
+        varCounter.inc();
+        LogicalVariable var = new LogicalVariable(varCounter.get());
+        currentVarMap.put(varCounter.get(), var);
+        return var;
+    }
+
+    @Override
+    public void setVarCounter(int count) {
+        varCounter.set(count);
+    }
+
     public boolean isTopFlwor() {
         return topFlwor;
     }
@@ -73,13 +88,6 @@ public final class TranslationContext {
         currentVarMap.put(v.getVar().getId(), var);
     }
 
-    public LogicalVariable newVar() {
-        varCounter.inc();
-        LogicalVariable var = new LogicalVariable(varCounter.get());
-        currentVarMap.put(varCounter.get(), var);
-        return var;
-    }
-
     /**
      * Within a subplan, an unbounded variable can be rebound in
      * the group-by operator. But the rebinding only exists
@@ -96,7 +104,7 @@ public final class TranslationContext {
     /***
      * This method marks that the translation exits a subplan.
      */
-    public void existSubplan() {
+    public void exitSubplan() {
         if (!stack.isEmpty()) {
             currentVarMap = stack.pop();
         }

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1047.aql
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1047.aql b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1047.aql
new file mode 100644
index 0000000..4210fc3
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1047.aql
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+/**
+ * This query is to verify the fix of ASTERIXDB-1047.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type DBLPType as open {
+  id: int64,
+  dblpid: string,
+  title: string,
+  authors: string,
+  misc: string
+}
+
+create dataset DBLP(DBLPType) primary key id;
+
+
+(for $d in dataset DBLP where $d.id = 1 return $d)
+  union
+(for $d in dataset DBLP where $d.authors = "Alfred V. Aho John E. Hopcroft Jeffrey D. Ullman" return $d);

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-2.aql
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-2.aql b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-2.aql
new file mode 100644
index 0000000..82d1430
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-2.aql
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+/**
+ * This query is to verify the fix of ASTERIXDB-1205.
+ */
+
+let $aa := [{"fa":1, "fb":1}, {"fa":2, "fb":1}]
+let $bb := [{"fa":1, "fb":0}, {"fa":1, "fb":1}, {"fa":3, "fb":1}]
+
+for $tt in ($aa union $bb)
+order by $tt.fa, $tt.fb
+return $tt;

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-3.aql
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-3.aql b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-3.aql
new file mode 100644
index 0000000..2ab92dc
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-3.aql
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+/**
+ * This query is to verify the fix of ASTERIXDB-1205.
+ */
+
+let $aa := [{"fa":1, "fb":1}, {"fa":2, "fb":1}]
+let $bb := [{"fa":1, "fb":0}, {"fa":1, "fb":1}, {"fa":3, "fb":1}]
+return $aa union $bb;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-4.aql
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-4.aql b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-4.aql
new file mode 100644
index 0000000..48f7c2a
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205-4.aql
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+/**
+ * This query is to verify the fix of ASTERIXDB-1205.
+ */
+
+let $aa := [{"fa":1, "fb":1}, {"fa":2, "fb":1}]
+let $bb := [{"fa":1, "fb":0}, {"fa":1, "fb":1}, {"fa":3, "fb":1}]
+let $dd := [{"fa":4, "fb":5}, {"fa":6, "fb":7}]
+let $ccc := $aa union $bb union $dd
+
+for $tt in $ccc
+order by $tt.fa, $tt.fb
+return $tt;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205.aql
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205.aql b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205.aql
new file mode 100644
index 0000000..763aba1
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/union/query-ASTERIXDB-1205.aql
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+/**
+ * This query is to verify the fix of ASTERIXDB-1205.
+ */
+
+let $aa := [{"fa":1, "fb":1}, {"fa":2, "fb":1}]
+let $bb := [{"fa":1, "fb":0}, {"fa":1, "fb":1}, {"fa":3, "fb":1}]
+let $ccc := $aa union $bb
+
+for $tt in $ccc
+order by $tt.fa, $tt.fb
+return $tt;

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset.aql
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset.aql b/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset.aql
new file mode 100644
index 0000000..7a55ee5
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset.aql
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+drop dataverse TinySocial if exists;
+create dataverse TinySocial;
+use dataverse TinySocial;
+
+create type FacebookUserType as open {
+        id: int
+}
+
+create dataset FacebookUsers(FacebookUserType)
+primary key id;
+
+create dataset FacebookUsers2(FacebookUserType)
+primary key id;
+
+
+let $c := dataset("FacebookUsers") union dataset("FacebookUsers2")
+for $res in $c order by $res.id return $res

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset2.aql
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset2.aql b/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset2.aql
new file mode 100644
index 0000000..049652f
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset2.aql
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+drop dataverse TinySocial if exists;
+create dataverse TinySocial;
+use dataverse TinySocial;
+
+create type FacebookUserType as open {
+        id: int
+}
+
+create dataset FacebookUsers(FacebookUserType)
+primary key id;
+
+create dataset FacebookUsers2(FacebookUserType)
+primary key id;
+
+dataset("FacebookUsers") union dataset("FacebookUsers2");

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset3.aql
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset3.aql b/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset3.aql
new file mode 100644
index 0000000..edb429f
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/union/union_dataset3.aql
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+drop dataverse TinySocial if exists;
+create dataverse TinySocial;
+use dataverse TinySocial;
+
+create type FacebookUserType as open {
+        id: int
+}
+
+create dataset FacebookUsers(FacebookUserType)
+primary key id;
+
+create dataset FacebookUsers2(FacebookUserType)
+primary key id;
+
+
+for $res in (dataset("FacebookUsers") union dataset("FacebookUsers2"))
+order by $res.id return $res

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/queries/union/union_query.aql
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/queries/union/union_query.aql b/asterix-app/src/test/resources/optimizerts/queries/union/union_query.aql
new file mode 100644
index 0000000..3e6ebaf
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/union/union_query.aql
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+drop dataverse TinySocial if exists;
+create dataverse TinySocial;
+use dataverse TinySocial;
+
+create type FacebookUserType as open {
+        id: int
+}
+
+create type FacebookMessageType as open {
+        message-id: int
+}
+
+create dataset FacebookUsers(FacebookUserType)
+primary key id;
+
+create dataset FacebookMessages(FacebookMessageType)
+primary key message-id;
+
+let $t1 := for $t in dataset FacebookUsers return $t.id
+let $t2 := for $s in dataset FacebookMessages return $s.message-id
+let $c := $t1 union $t2
+for $res in $c distinct by $res order by $res return $res

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/results/q05_local_supplier_volume.plan
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/results/q05_local_supplier_volume.plan b/asterix-app/src/test/resources/optimizerts/results/q05_local_supplier_volume.plan
index 1f99eee..9d17ca8 100644
--- a/asterix-app/src/test/resources/optimizerts/results/q05_local_supplier_volume.plan
+++ b/asterix-app/src/test/resources/optimizerts/results/q05_local_supplier_volume.plan
@@ -2,8 +2,8 @@
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
-        -- SORT_MERGE_EXCHANGE [$$100(DESC) ]  |PARTITIONED|
-          -- STABLE_SORT [$$100(DESC)]  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$89(DESC) ]  |PARTITIONED|
+          -- STABLE_SORT [$$89(DESC)]  |PARTITIONED|
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
               -- EXTERNAL_GROUP_BY[$$119]  |PARTITIONED|
                       {
@@ -19,7 +19,7 @@
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                       -- STREAM_PROJECT  |PARTITIONED|
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          -- HYBRID_HASH_JOIN [$$81, $$98][$$115, $$88]  |PARTITIONED|
+                          -- HYBRID_HASH_JOIN [$$94, $$81][$$88, $$115]  |PARTITIONED|
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                               -- STREAM_PROJECT  |PARTITIONED|
                                 -- ASSIGN  |PARTITIONED|
@@ -66,8 +66,8 @@
                                                     -- HASH_PARTITION_EXCHANGE [$$86]  |PARTITIONED|
                                                       -- STREAM_PROJECT  |PARTITIONED|
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          -- HYBRID_HASH_JOIN [$$89][$$87]  |PARTITIONED|
-                                                            -- HASH_PARTITION_EXCHANGE [$$89]  |PARTITIONED|
+                                                          -- HYBRID_HASH_JOIN [$$90][$$87]  |PARTITIONED|
+                                                            -- HASH_PARTITION_EXCHANGE [$$90]  |PARTITIONED|
                                                               -- STREAM_PROJECT  |PARTITIONED|
                                                                 -- ASSIGN  |PARTITIONED|
                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/results/q08_group_by.plan
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/results/q08_group_by.plan b/asterix-app/src/test/resources/optimizerts/results/q08_group_by.plan
index 601091e..1aca471 100644
--- a/asterix-app/src/test/resources/optimizerts/results/q08_group_by.plan
+++ b/asterix-app/src/test/resources/optimizerts/results/q08_group_by.plan
@@ -31,8 +31,8 @@
                               -- HASH_PARTITION_EXCHANGE [$$81]  |PARTITIONED|
                                 -- STREAM_PROJECT  |PARTITIONED|
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    -- HYBRID_HASH_JOIN [$$92][$$82]  |PARTITIONED|
-                                      -- HASH_PARTITION_EXCHANGE [$$92]  |PARTITIONED|
+                                    -- HYBRID_HASH_JOIN [$$94][$$82]  |PARTITIONED|
+                                      -- HASH_PARTITION_EXCHANGE [$$94]  |PARTITIONED|
                                         -- STREAM_SELECT  |PARTITIONED|
                                           -- STREAM_PROJECT  |PARTITIONED|
                                             -- ASSIGN  |PARTITIONED|
@@ -43,8 +43,8 @@
                                       -- HASH_PARTITION_EXCHANGE [$$82]  |PARTITIONED|
                                         -- STREAM_PROJECT  |PARTITIONED|
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            -- HYBRID_HASH_JOIN [$$89][$$83]  |PARTITIONED|
-                                              -- HASH_PARTITION_EXCHANGE [$$89]  |PARTITIONED|
+                                            -- HYBRID_HASH_JOIN [$$91][$$83]  |PARTITIONED|
+                                              -- HASH_PARTITION_EXCHANGE [$$91]  |PARTITIONED|
                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                   -- ASSIGN  |PARTITIONED|
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -54,8 +54,8 @@
                                               -- HASH_PARTITION_EXCHANGE [$$83]  |PARTITIONED|
                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    -- HYBRID_HASH_JOIN [$$87][$$84]  |PARTITIONED|
-                                                      -- HASH_PARTITION_EXCHANGE [$$87]  |PARTITIONED|
+                                                    -- HYBRID_HASH_JOIN [$$89][$$84]  |PARTITIONED|
+                                                      -- HASH_PARTITION_EXCHANGE [$$89]  |PARTITIONED|
                                                         -- STREAM_PROJECT  |PARTITIONED|
                                                           -- ASSIGN  |PARTITIONED|
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/results/q09_group_by.plan
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/results/q09_group_by.plan b/asterix-app/src/test/resources/optimizerts/results/q09_group_by.plan
index fc2abd2..9f48723 100644
--- a/asterix-app/src/test/resources/optimizerts/results/q09_group_by.plan
+++ b/asterix-app/src/test/resources/optimizerts/results/q09_group_by.plan
@@ -15,7 +15,7 @@
               -- HASH_PARTITION_EXCHANGE [$$84]  |PARTITIONED|
                 -- STREAM_PROJECT  |PARTITIONED|
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                    -- HYBRID_HASH_JOIN [$$64, $$63][$$69, $$84]  |PARTITIONED|
+                    -- HYBRID_HASH_JOIN [$$63, $$64][$$84, $$69]  |PARTITIONED|
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                         -- STREAM_PROJECT  |PARTITIONED|
                           -- ASSIGN  |PARTITIONED|
@@ -30,8 +30,8 @@
                               -- HASH_PARTITION_EXCHANGE [$$65]  |PARTITIONED|
                                 -- STREAM_PROJECT  |PARTITIONED|
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    -- HYBRID_HASH_JOIN [$$77][$$66]  |PARTITIONED|
-                                      -- HASH_PARTITION_EXCHANGE [$$77]  |PARTITIONED|
+                                    -- HYBRID_HASH_JOIN [$$72][$$66]  |PARTITIONED|
+                                      -- HASH_PARTITION_EXCHANGE [$$72]  |PARTITIONED|
                                         -- STREAM_PROJECT  |PARTITIONED|
                                           -- ASSIGN  |PARTITIONED|
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/1e7760c3/asterix-app/src/test/resources/optimizerts/results/query-issue562.plan
----------------------------------------------------------------------
diff --git a/asterix-app/src/test/resources/optimizerts/results/query-issue562.plan b/asterix-app/src/test/resources/optimizerts/results/query-issue562.plan
index 5062719..28625aa 100644
--- a/asterix-app/src/test/resources/optimizerts/results/query-issue562.plan
+++ b/asterix-app/src/test/resources/optimizerts/results/query-issue562.plan
@@ -3,12 +3,12 @@
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
         -- SORT_MERGE_EXCHANGE [$$7(ASC) ]  |PARTITIONED|
-          -- PRE_CLUSTERED_GROUP_BY[$$89]  |PARTITIONED|
+          -- PRE_CLUSTERED_GROUP_BY[$$86]  |PARTITIONED|
                   {
                     -- AGGREGATE  |LOCAL|
                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                   }
-            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$89(ASC)] HASH:[$$89]  |PARTITIONED|
+            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$86(ASC)] HASH:[$$86]  |PARTITIONED|
               -- SORT_GROUP_BY[$$59]  |PARTITIONED|
                       {
                         -- AGGREGATE  |LOCAL|
@@ -21,46 +21,48 @@
                         -- STREAM_SELECT  |PARTITIONED|
                           -- STREAM_PROJECT  |PARTITIONED|
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- PRE_CLUSTERED_GROUP_BY[$$86]  |PARTITIONED|
+                              -- SORT_GROUP_BY[$$83]  |PARTITIONED|
                                       {
                                         -- AGGREGATE  |LOCAL|
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                       }
-                                -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$86(ASC)] HASH:[$$86]  |PARTITIONED|
-                                  -- PRE_CLUSTERED_GROUP_BY[$$62]  |PARTITIONED|
-                                          {
-                                            -- AGGREGATE  |LOCAL|
-                                              -- STREAM_SELECT  |LOCAL|
-                                                -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                          }
+                                -- HASH_PARTITION_EXCHANGE [$$83]  |PARTITIONED|
+                                  -- STREAM_PROJECT  |PARTITIONED|
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      -- STABLE_SORT [$$62(ASC)]  |PARTITIONED|
+                                      -- PRE_CLUSTERED_GROUP_BY[$$65, $$11, $$62]  |PARTITIONED|
+                                              {
+                                                -- AGGREGATE  |LOCAL|
+                                                  -- STREAM_SELECT  |LOCAL|
+                                                    -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                              }
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- STREAM_PROJECT  |PARTITIONED|
+                                          -- STABLE_SORT [$$65(ASC), $$65(ASC), $$62(ASC)]  |PARTITIONED|
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              -- HYBRID_HASH_JOIN [$$67][$$68]  |PARTITIONED|
-                                                -- HASH_PARTITION_EXCHANGE [$$67]  |PARTITIONED|
-                                                  -- ASSIGN  |PARTITIONED|
-                                                    -- STREAM_PROJECT  |PARTITIONED|
-                                                      -- ASSIGN  |PARTITIONED|
-                                                        -- STREAM_PROJECT  |PARTITIONED|
-                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            -- HYBRID_HASH_JOIN [$$83][$$82]  |PARTITIONED|
-                                                              -- HASH_PARTITION_EXCHANGE [$$83]  |PARTITIONED|
-                                                                -- UNNEST  |UNPARTITIONED|
-                                                                  -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
-                                                              -- HASH_PARTITION_EXCHANGE [$$82]  |PARTITIONED|
-                                                                -- ASSIGN  |PARTITIONED|
-                                                                  -- STREAM_PROJECT  |PARTITIONED|
+                                              -- STABLE_SORT [$$65(ASC), $$65(ASC), $$62(ASC)]  |PARTITIONED|
+                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                  -- STREAM_PROJECT  |PARTITIONED|
+                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                      -- HYBRID_HASH_JOIN [$$68][$$69]  |PARTITIONED|
+                                                        -- HASH_PARTITION_EXCHANGE [$$68]  |PARTITIONED|
+                                                          -- ASSIGN  |PARTITIONED|
+                                                            -- ASSIGN  |PARTITIONED|
+                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                -- HYBRID_HASH_JOIN [$$65][$$11]  |PARTITIONED|
+                                                                  -- HASH_PARTITION_EXCHANGE [$$65]  |PARTITIONED|
+                                                                    -- UNNEST  |UNPARTITIONED|
+                                                                      -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
+                                                                  -- HASH_PARTITION_EXCHANGE [$$11]  |PARTITIONED|
                                                                     -- ASSIGN  |PARTITIONED|
-                                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                      -- STREAM_PROJECT  |PARTITIONED|
+                                                                        -- ASSIGN  |PARTITIONED|
                                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                -- HASH_PARTITION_EXCHANGE [$$68]  |PARTITIONED|
-                                                  -- ASSIGN  |PARTITIONED|
-                                                    -- STREAM_PROJECT  |PARTITIONED|
-                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        -- DATASOURCE_SCAN  |PARTITIONED|
-                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                                            -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                        -- HASH_PARTITION_EXCHANGE [$$69]  |PARTITIONED|
+                                                          -- ASSIGN  |PARTITIONED|
+                                                            -- STREAM_PROJECT  |PARTITIONED|
+                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|