Dmitry Lychagin has uploaded a new change for review.

  https://asterix-gerrit.ics.uci.edu/2169

Change subject: [ASTERIXDB-2170][SQL] Fix resolution order of implicit field 
access
......................................................................

[ASTERIXDB-2170][SQL] Fix resolution order of implicit field access

- user model changes: yes
- storage format changes: no
- interface changes: no

Details:
- Resolve field access to the nearest variable in scope
  instead of raising compile-time error
- Cleanup group variable handling in GroupBy clause,
  no longer use ‘with’ map for it
- Fix ByNameToByIndexFieldAccessRule to use type environment
  of its input operator when analyzing its expression
- Fix ExternalGroupByPOperator to use input schema of its
  aggregate function when generating runtime for that function

Change-Id: I69b1c5422017ceaa74a0cd83085c910292b00418
---
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushAggregateIntoNestedSubplanRule.java
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ResolveVariableRule.java
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
M 
asterixdb/asterix-app/src/test/resources/optimizerts/results/tpcds/query-ASTERIXDB-1581.plan
M 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/custord/join_q_09/join_q_09.2.query.sqlpp
M 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/conflict-fields-dataset/conflict-fields-dataset.3.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.1.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.2.update.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.3.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/custord/join_q_09/join_q_09.1.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/resolution/conflict-fields-dataset/conflict-fields-dataset.1.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/resolution/order_1/order_1.3.adm
M asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
M asterixdb/asterix-lang-common/pom.xml
M 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/context/Scope.java
M 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/OperatorExpr.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
M asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
M asterixdb/pom.xml
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/ExternalGroupByPOperator.java
26 files changed, 271 insertions(+), 185 deletions(-)


  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/69/2169/1

diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
index b3b0ad7..1ace6fa 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
@@ -87,7 +87,7 @@
             return changed;
         }
         changed |= extractFirstArg(fce, op, context);
-        IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op);
+        IVariableTypeEnvironment env = 
context.getOutputTypeEnvironment(op.getInputs().get(0).getValue());
         IAType t = (IAType) env.getType(fce.getArguments().get(0).getValue());
         changed |= rewriteFieldAccess(exprRef, fce, getActualType(t));
         return changed;
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushAggregateIntoNestedSubplanRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushAggregateIntoNestedSubplanRule.java
index 2b98762..d69dd3b 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushAggregateIntoNestedSubplanRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushAggregateIntoNestedSubplanRule.java
@@ -421,47 +421,47 @@
             AggregateOperator nspAgg = (AggregateOperator) 
nspAggRef.getValue();
             Mutable<ILogicalOperator> nspAggChildRef = 
nspAgg.getInputs().get(0);
             LogicalVariable listifyVar = findListifiedVariable(nspAgg, 
varFromNestedAgg);
-            if (listifyVar == null) {
-                    continue;
-            }
-            OperatorManipulationUtil.substituteVarRec(aggInSubplanOp, 
unnestVar, listifyVar, true, context);
-            nspAgg.getVariables().addAll(aggInSubplanOp.getVariables());
-            nspAgg.getExpressions().addAll(aggInSubplanOp.getExpressions());
-            for (LogicalVariable v : aggInSubplanOp.getVariables()) {
-                nspWithAgg.put(v, nspOp);
-                nspAggVars.put(v, 0);
-                nspAggVarToPlanIndex.put(v, i);
-            }
+            if (listifyVar != null) {
+                OperatorManipulationUtil.substituteVarRec(aggInSubplanOp, 
unnestVar, listifyVar, true, context);
+                nspAgg.getVariables().addAll(aggInSubplanOp.getVariables());
+                
nspAgg.getExpressions().addAll(aggInSubplanOp.getExpressions());
+                for (LogicalVariable v : aggInSubplanOp.getVariables()) {
+                    nspWithAgg.put(v, nspOp);
+                    nspAggVars.put(v, 0);
+                    nspAggVarToPlanIndex.put(v, i);
+                }
 
-            Mutable<ILogicalOperator> opRef1InSubplan = 
aggInSubplanOp.getInputs().get(0);
-            if (!opRef1InSubplan.getValue().getInputs().isEmpty()) {
-                Mutable<ILogicalOperator> opRef2InSubplan = 
opRef1InSubplan.getValue().getInputs().get(0);
-                AbstractLogicalOperator op2InSubplan = 
(AbstractLogicalOperator) opRef2InSubplan.getValue();
-                if (op2InSubplan.getOperatorTag() != 
LogicalOperatorTag.NESTEDTUPLESOURCE) {
-                    List<Mutable<ILogicalOperator>> nspInpList = 
nspAgg.getInputs();
-                    nspInpList.clear();
-                    nspInpList.add(opRef1InSubplan);
-                    while (true) {
-                        opRef2InSubplan = 
opRef1InSubplan.getValue().getInputs().get(0);
-                        op2InSubplan = (AbstractLogicalOperator) 
opRef2InSubplan.getValue();
-                        if (op2InSubplan.getOperatorTag() == 
LogicalOperatorTag.UNNEST) {
-                            List<Mutable<ILogicalOperator>> opInpList = 
opRef1InSubplan.getValue().getInputs();
-                            opInpList.clear();
-                            opInpList.add(nspAggChildRef);
-                            break;
-                        }
-                        opRef1InSubplan = opRef2InSubplan;
-                        if (opRef1InSubplan.getValue().getInputs().isEmpty()) {
-                            throw new IllegalStateException(
+                Mutable<ILogicalOperator> opRef1InSubplan = 
aggInSubplanOp.getInputs().get(0);
+                if (!opRef1InSubplan.getValue().getInputs().isEmpty()) {
+                    Mutable<ILogicalOperator> opRef2InSubplan = 
opRef1InSubplan.getValue().getInputs().get(0);
+                    AbstractLogicalOperator op2InSubplan = 
(AbstractLogicalOperator) opRef2InSubplan.getValue();
+                    if (op2InSubplan.getOperatorTag() != 
LogicalOperatorTag.NESTEDTUPLESOURCE) {
+                        List<Mutable<ILogicalOperator>> nspInpList = 
nspAgg.getInputs();
+                        nspInpList.clear();
+                        nspInpList.add(opRef1InSubplan);
+                        while (true) {
+                            opRef2InSubplan = 
opRef1InSubplan.getValue().getInputs().get(0);
+                            op2InSubplan = (AbstractLogicalOperator) 
opRef2InSubplan.getValue();
+                            if (op2InSubplan.getOperatorTag() == 
LogicalOperatorTag.UNNEST) {
+                                List<Mutable<ILogicalOperator>> opInpList = 
opRef1InSubplan.getValue().getInputs();
+                                opInpList.clear();
+                                opInpList.add(nspAggChildRef);
+                                break;
+                            }
+                            opRef1InSubplan = opRef2InSubplan;
+                            if 
(opRef1InSubplan.getValue().getInputs().isEmpty()) {
+                                throw new IllegalStateException(
                                         "PushAggregateIntoNestedSubplanRule: 
could not find UNNEST.");
+                            }
                         }
                     }
                 }
+                subplanOpRef.setValue(subplan.getInputs().get(0).getValue());
+                OperatorPropertiesUtil.typeOpRec(nspAggRef, context);
+                return true;
             }
-            subplanOpRef.setValue(subplan.getInputs().get(0).getValue());
-            OperatorPropertiesUtil.typeOpRec(nspAggRef, context);
         }
-        return true;
+        return false;
     }
 
     private LogicalVariable findListifiedVariable(AggregateOperator nspAgg, 
LogicalVariable varFromNestedAgg) {
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ResolveVariableRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ResolveVariableRule.java
index 2d7695f..f851e91 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ResolveVariableRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ResolveVariableRule.java
@@ -21,7 +21,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -154,13 +154,7 @@
 
         // The resolution order: 1. field-access 2. datasets (standalone-name 
or fully-qualified)
         if (numVarCandidates > 0) {
-            if (numVarCandidates == 1) {
-                resolveAsFieldAccess(funcRef, 
varAccessCandidates.iterator().next());
-            } else {
-                // More than one possibilities.
-                throw new AlgebricksException(
-                        "Cannot resolve ambiguous alias reference for 
undefined identifier " + unresolvedVarName);
-            }
+            resolveAsFieldAccess(funcRef, 
varAccessCandidates.iterator().next());
         } else if (hasMatchedDataset) {
             // Rewrites the "resolve" function to a "dataset" function and 
only keep the dataset name argument.
             
func.setFunctionInfo(FunctionUtil.getFunctionInfo(BuiltinFunctions.DATASET));
@@ -205,22 +199,22 @@
     }
 
     // Finds all candidate fully qualified expression/field-access paths.
-    private Set<Pair<ILogicalExpression, List<String>>> 
findCandidatePaths(ILogicalOperator op,
-            Collection<ILogicalExpression> referenceExprs, String 
unresolvedVarName, IOptimizationContext context)
+    private LinkedHashSet<Pair<ILogicalExpression, List<String>>> 
findCandidatePaths(ILogicalOperator op,
+            List<ILogicalExpression> referenceExprs, String unresolvedVarName, 
IOptimizationContext context)
             throws AlgebricksException {
-        Set<Pair<ILogicalExpression, List<String>>> candidates = new 
HashSet<>();
+        LinkedHashSet<Pair<ILogicalExpression, List<String>>> candidates = new 
LinkedHashSet<>();
         IVariableTypeEnvironment env = 
context.getOutputTypeEnvironment(op.getInputs().get(0).getValue());
         for (ILogicalExpression referenceExpr : referenceExprs) {
             IAType type = (IAType) env.getType(referenceExpr);
-            candidates.addAll(findCandidatePathsForExpr(unresolvedVarName, 
type, referenceExpr, new ArrayList<>()));
+            findCandidatePathsForExpr(unresolvedVarName, type, referenceExpr, 
new ArrayList<>(), candidates);
         }
         return candidates;
     }
 
     // Recursively finds candidate paths under an expression.
-    private Set<Pair<ILogicalExpression, List<String>>> 
findCandidatePathsForExpr(String unresolvedVarName,
-            IAType pathType, ILogicalExpression expr, List<String> parentPath) 
throws AlgebricksException {
-        Set<Pair<ILogicalExpression, List<String>>> varAccessCandidates = new 
HashSet<>();
+    private void findCandidatePathsForExpr(String unresolvedVarName, IAType 
pathType, ILogicalExpression expr,
+            List<String> parentPath, Set<Pair<ILogicalExpression, 
List<String>>> outCandidates)
+            throws AlgebricksException {
         IAType type = pathType;
         if (type.getTypeTag() == ATypeTag.UNION) {
             type = ((AUnionType) type).getActualType();
@@ -229,7 +223,7 @@
         if (tag == ATypeTag.ANY) {
             List<String> path = new ArrayList<>(parentPath);
             path.add(unresolvedVarName);
-            varAccessCandidates.add(new Pair<>(expr, path));
+            outCandidates.add(new Pair<>(expr, path));
         }
         if (tag == ATypeTag.OBJECT) {
             ARecordType recordType = (ARecordType) type;
@@ -237,7 +231,7 @@
                 // If the field name is possible.
                 List<String> path = new ArrayList<>(parentPath);
                 path.add(unresolvedVarName);
-                varAccessCandidates.add(new Pair<>(expr, path));
+                outCandidates.add(new Pair<>(expr, path));
             } else {
                 // Recursively identified possible paths.
                 String[] fieldNames = recordType.getFieldNames();
@@ -245,12 +239,10 @@
                 for (int index = 0; index < fieldNames.length; ++index) {
                     List<String> path = new ArrayList<>(parentPath);
                     path.add(fieldNames[index]);
-                    
varAccessCandidates.addAll(findCandidatePathsForExpr(unresolvedVarName, 
fieldTypes[index], expr,
-                            path));
+                    findCandidatePathsForExpr(unresolvedVarName, 
fieldTypes[index], expr, path, outCandidates);
                 }
             }
         }
-        return varAccessCandidates;
     }
 
     // Try to resolve the expression like resolve("x").foo as x.foo.
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index 719824b..57d729d 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -794,6 +794,8 @@
     public Pair<ILogicalOperator, LogicalVariable> visit(GroupbyClause gc, 
Mutable<ILogicalOperator> tupSource)
             throws CompilationException {
         Mutable<ILogicalOperator> topOp = tupSource;
+
+        LogicalVariable groupRecordVar = null;
         if (gc.hasGroupVar()) {
             List<Pair<Expression, Identifier>> groupFieldList = 
gc.getGroupFieldList();
             List<Mutable<ILogicalExpression>> groupRecordConstructorArgList = 
new ArrayList<>();
@@ -805,13 +807,14 @@
                 ILogicalExpression groupFieldExpr = 
langExprToAlgExpression(groupField.first, topOp).first;
                 groupRecordConstructorArgList.add(new 
MutableObject<>(groupFieldExpr));
             }
-            LogicalVariable groupVar = 
context.newVarFromExpression(gc.getGroupVar());
-            AssignOperator groupVarAssignOp = new AssignOperator(groupVar,
-                    new MutableObject<>(new ScalarFunctionCallExpression(
-                            
FunctionUtil.getFunctionInfo(BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR),
-                            groupRecordConstructorArgList)));
-            groupVarAssignOp.getInputs().add(topOp);
-            topOp = new MutableObject<>(groupVarAssignOp);
+            MutableObject<ILogicalExpression> groupRecordConstr = new 
MutableObject<>(new ScalarFunctionCallExpression(
+                    
FunctionUtil.getFunctionInfo(BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR),
+                    groupRecordConstructorArgList));
+
+            groupRecordVar = context.newVar();
+            AssignOperator groupRecordVarAssignOp = new 
AssignOperator(groupRecordVar, groupRecordConstr);
+            groupRecordVarAssignOp.getInputs().add(topOp);
+            topOp = new MutableObject<>(groupRecordVarAssignOp);
         }
 
         GroupByOperator gOp = new GroupByOperator();
@@ -831,30 +834,46 @@
         }
 
         gOp.getInputs().add(topOp);
-        for (Entry<Expression, VariableExpr> entry : 
gc.getWithVarMap().entrySet()) {
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> listifyInput = 
langExprToAlgExpression(entry.getKey(),
+
+        if (gc.hasGroupVar()) {
+            VariableExpr groupVar = gc.getGroupVar();
+            LogicalVariable groupLogicalVar = context.newVar();
+            ILogicalPlan nestedPlan = 
createNestedPlanWithAggregate(groupLogicalVar,
+                    BuiltinFunctions.LISTIFY, new 
VariableReferenceExpression(groupRecordVar),
                     new MutableObject<>(new NestedTupleSourceOperator(new 
MutableObject<>(gOp))));
-            List<Mutable<ILogicalExpression>> flArgs = new ArrayList<>(1);
-            flArgs.add(new MutableObject<>(listifyInput.first));
-            AggregateFunctionCallExpression fListify =
-                    
BuiltinFunctions.makeAggregateFunctionExpression(BuiltinFunctions.LISTIFY, 
flArgs);
-            LogicalVariable aggVar = context.newVar();
-            AggregateOperator agg = new 
AggregateOperator(mkSingletonArrayList(aggVar),
-                    mkSingletonArrayList(new MutableObject<>(fListify)));
-
-            agg.getInputs().add(listifyInput.second);
-
-            ILogicalPlan plan = new ALogicalPlanImpl(new MutableObject<>(agg));
-            gOp.getNestedPlans().add(plan);
-            // Hide the variable that was part of the "with", replacing it with
-            // the one bound by the aggregation op.
-            context.setVar(entry.getValue(), aggVar);
+            gOp.getNestedPlans().add(nestedPlan);
+            context.setVar(groupVar, groupLogicalVar);
         }
+
+        if (gc.hasWithMap()) {
+            for (Entry<Expression, VariableExpr> entry : 
gc.getWithVarMap().entrySet()) {
+                VariableExpr withVar = entry.getValue();
+                Expression withExpr = entry.getKey();
+                Pair<ILogicalExpression, Mutable<ILogicalOperator>> 
listifyInput = langExprToAlgExpression(withExpr,
+                        new MutableObject<>(new NestedTupleSourceOperator(new 
MutableObject<>(gOp))));
+                LogicalVariable withLogicalVar = context.newVar();
+                ILogicalPlan nestedPlan = 
createNestedPlanWithAggregate(withLogicalVar,
+                        BuiltinFunctions.LISTIFY, listifyInput.first, 
listifyInput.second);
+                gOp.getNestedPlans().add(nestedPlan);
+                context.setVar(withVar, withLogicalVar);
+            }
+        }
+
         gOp.setGroupAll(gc.isGroupAll());
         gOp.getAnnotations().put(OperatorAnnotations.USE_HASH_GROUP_BY, 
gc.hasHashGroupByHint());
         return new Pair<>(gOp, null);
     }
 
+    private ILogicalPlan createNestedPlanWithAggregate(LogicalVariable 
aggOutputVar, FunctionIdentifier aggFunc,
+            ILogicalExpression aggFnInput, Mutable<ILogicalOperator> 
aggOpInput) {
+        AggregateFunctionCallExpression aggFnCall = 
BuiltinFunctions.makeAggregateFunctionExpression(aggFunc,
+                mkSingletonArrayList(new MutableObject<>(aggFnInput)));
+        AggregateOperator aggOp = new 
AggregateOperator(mkSingletonArrayList(aggOutputVar),
+                mkSingletonArrayList(new MutableObject<>(aggFnCall)));
+        aggOp.getInputs().add(aggOpInput);
+        return new ALogicalPlanImpl(new MutableObject<>(aggOp));
+    }
+
     @Override
     public Pair<ILogicalOperator, LogicalVariable> visit(IfExpr ifexpr, 
Mutable<ILogicalOperator> tupSource)
             throws CompilationException {
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index c17b55b..57f2253 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -662,9 +662,12 @@
         for (GbyVariableExpressionPair pair : groupbyClause.getGbyPairList()) {
             fieldBindings.add(getFieldBinding(pair.getVar()));
         }
-        if (groupbyClause.hasWithMap() && groupbyClause.hasGroupVar()) {
-            // Makes sure that we add the re-mapped group variable which 
refers to a collection.
-            
fieldBindings.add(getFieldBinding(groupbyClause.getWithVarMap().get(groupbyClause.getGroupVar())));
+        if (groupbyClause.hasGroupVar()) {
+            fieldBindings.add(getFieldBinding(groupbyClause.getGroupVar()));
+        }
+        if (groupbyClause.hasWithMap()) {
+            // no WITH in SQL++
+            throw new 
IllegalStateException(groupbyClause.getWithVarMap().values().toString());
         }
         return fieldBindings;
     }
diff --git 
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpcds/query-ASTERIXDB-1581.plan
 
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpcds/query-ASTERIXDB-1581.plan
index 14b31eb..753ae20 100644
--- 
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpcds/query-ASTERIXDB-1581.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpcds/query-ASTERIXDB-1581.plan
@@ -32,7 +32,7 @@
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                   -- HYBRID_HASH_JOIN [$$92][$$93]  
|PARTITIONED|
                                     -- HASH_PARTITION_EXCHANGE [$$92]  
|PARTITIONED|
-                                      -- PRE_CLUSTERED_GROUP_BY[$$32]  
|PARTITIONED|
+                                      -- PRE_CLUSTERED_GROUP_BY[$$30]  
|PARTITIONED|
                                               {
                                                 -- AGGREGATE  |LOCAL|
                                                   -- AGGREGATE  |LOCAL|
@@ -42,11 +42,11 @@
                                                           -- 
NESTED_TUPLE_SOURCE  |LOCAL|
                                               }
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          -- STABLE_SORT [$$32(ASC)]  
|PARTITIONED|
+                                          -- STABLE_SORT [$$30(ASC)]  
|PARTITIONED|
                                             -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
                                               -- STREAM_PROJECT  |PARTITIONED|
                                                 -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
-                                                  -- HYBRID_HASH_JOIN 
[$$32][$$85]  |PARTITIONED|
+                                                  -- HYBRID_HASH_JOIN 
[$$30][$$85]  |PARTITIONED|
                                                     -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
                                                       -- STREAM_PROJECT  
|PARTITIONED|
                                                         -- ASSIGN  
|PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/custord/join_q_09/join_q_09.2.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/custord/join_q_09/join_q_09.2.query.sqlpp
index 49aa67f..32071ee 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/custord/join_q_09/join_q_09.2.query.sqlpp
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/custord/join_q_09/join_q_09.2.query.sqlpp
@@ -17,10 +17,10 @@
  * under the License.
  */
 
-/** This query is a negative test for ambiguous alias reference. */
+/** This query is a test for ambiguous alias reference. */
 
 SELECT c.name AS cust_name,
-       age AS cust_age,
+       age AS age,
        o.total AS order_total,
        [o.oid,o.cid] AS orderList
 FROM test.Customers c, test.Orders o
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/conflict-fields-dataset/conflict-fields-dataset.3.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/conflict-fields-dataset/conflict-fields-dataset.3.query.sqlpp
index 2645ddc..6560931 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/conflict-fields-dataset/conflict-fields-dataset.3.query.sqlpp
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/conflict-fields-dataset/conflict-fields-dataset.3.query.sqlpp
@@ -21,4 +21,5 @@
 
 select *
 from samptable s1, samptable s2
-where samptable > 0;
+where samptable > 0
+order by s1.id
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.1.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.1.ddl.sqlpp
new file mode 100644
index 0000000..d6231cf
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.1.ddl.sqlpp
@@ -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 test if exists;
+create dataverse test;
+use test;
+
+create type partType as closed {
+  pid: bigint
+};
+
+create type orderType as closed {
+  oid: bigint,
+  pid: bigint
+};
+
+create dataset parts(partType) primary key pid;
+
+create dataset orders(orderType) primary key oid;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.2.update.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.2.update.sqlpp
new file mode 100644
index 0000000..3e5e1d1
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.2.update.sqlpp
@@ -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.
+ */
+
+use test;
+
+insert into parts ({'pid': 0});
+insert into parts ({'pid': 1});
+
+insert into orders ({'oid' : 100, 'pid': 0});
+insert into orders ({'oid' : 101, 'pid': 1});
+insert into orders ({'oid' : 102, 'pid': 99});
+insert into orders ({'oid' : 103, 'pid': 1});
+insert into orders ({'oid' : 104, 'pid': 0});
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.3.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.3.query.sqlpp
new file mode 100644
index 0000000..01ed3a5
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/resolution/order_1/order_1.3.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+use test;
+
+select value oid from orders
+where pid in (select value pid from parts)
+order by oid
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/custord/join_q_09/join_q_09.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/custord/join_q_09/join_q_09.1.adm
new file mode 100644
index 0000000..9c8f2ee
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/custord/join_q_09/join_q_09.1.adm
@@ -0,0 +1,3 @@
+{ "cust_name": "Jodi Alex", "order_total": 7.206, "orderList": [ 1, 5 ] }
+{ "cust_name": "Jodi Rotruck", "order_total": 14.2326, "orderList": [ 10, 775 
] }
+{ "cust_name": "Jodi Rotruck", "order_total": 97.20656, "orderList": [ 1000, 
775 ] }
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/resolution/conflict-fields-dataset/conflict-fields-dataset.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/resolution/conflict-fields-dataset/conflict-fields-dataset.1.adm
new file mode 100644
index 0000000..86f600b
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/resolution/conflict-fields-dataset/conflict-fields-dataset.1.adm
@@ -0,0 +1,2 @@
+{ "s1": { "id": 0 }, "s2": { "id": 1, "samptable": 1 } }
+{ "s1": { "id": 1, "samptable": 1 }, "s2": { "id": 1, "samptable": 1 } }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/resolution/order_1/order_1.3.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/resolution/order_1/order_1.3.adm
new file mode 100644
index 0000000..c9e3657
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/resolution/order_1/order_1.3.adm
@@ -0,0 +1,4 @@
+100
+101
+103
+104
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml 
b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 484e395..db69cf7 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -1493,8 +1493,7 @@
     </test-case>
     <test-case FilePath="custord">
       <compilation-unit name="join_q_09">
-        <output-dir compare="Text">join_q_01</output-dir>
-        <expected-error>Cannot resolve ambiguous alias reference for undefined 
identifier age</expected-error>
+        <output-dir compare="Text">join_q_09</output-dir>
       </compilation-unit>
     </test-case>
     <test-case FilePath="custord">
@@ -5389,8 +5388,7 @@
     </test-case>
     <test-case FilePath="resolution">
       <compilation-unit name="conflict-fields-dataset">
-        <output-dir compare="Text">conflict-field-dataset</output-dir>
-        <expected-error>Cannot resolve ambiguous alias reference for undefined 
identifier samptable</expected-error>
+        <output-dir compare="Text">conflict-fields-dataset</output-dir>
       </compilation-unit>
     </test-case>
     <test-case FilePath="resolution">
@@ -5401,6 +5399,11 @@
     <test-case FilePath="resolution">
       <compilation-unit name="fullyqualified2">
         <output-dir compare="Text">fullyqualified2</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="resolution">
+      <compilation-unit name="order_1">
+        <output-dir compare="Text">order_1</output-dir>
       </compilation-unit>
     </test-case>
   </test-group>
@@ -6437,7 +6440,6 @@
     <test-case FilePath="subquery">
       <compilation-unit name="query-ASTERIXDB-1574-3">
         <output-dir compare="Text">query-ASTERIXDB-1574</output-dir>
-        <expected-error>Cannot resolve ambiguous alias reference for undefined 
identifier</expected-error>
       </compilation-unit>
     </test-case>
     <test-case FilePath="subquery">
diff --git a/asterixdb/asterix-lang-common/pom.xml 
b/asterixdb/asterix-lang-common/pom.xml
index b6c6e7a..6572cc0 100644
--- a/asterixdb/asterix-lang-common/pom.xml
+++ b/asterixdb/asterix-lang-common/pom.xml
@@ -91,6 +91,10 @@
       <artifactId>commons-lang</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-collections4</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.hyracks</groupId>
       <artifactId>algebricks-core</artifactId>
     </dependency>
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/context/Scope.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/context/Scope.java
index ad277d3..92a101d 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/context/Scope.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/context/Scope.java
@@ -18,40 +18,39 @@
  */
 package org.apache.asterix.lang.common.context;
 
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.ArrayList;
 import java.util.Iterator;
-import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.Set;
 
 import org.apache.asterix.common.functions.FunctionSignature;
-import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.parser.ScopeChecker;
-import org.apache.asterix.lang.common.rewrites.VariableSubstitutionEnvironment;
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.commons.collections4.iterators.ReverseListIterator;
 
 public final class Scope {
-    private Scope parent;
-    private Map<String, Identifier> symbols = new HashMap<String, 
Identifier>();
-    private Map<String, Expression> varExprMap = new HashMap<String, 
Expression>();
-    private FunctionSignatures functionSignatures = null;
     private final ScopeChecker scopeChecker;
-    private boolean maskParentScope = false;
-
-    public Scope(ScopeChecker scopeChecker, Scope parent) {
-        this.scopeChecker = scopeChecker;
-        this.parent = parent;
-    }
+    private final Scope parent;
+    private final LinkedHashMap<String, Identifier> symbols;
+    private final boolean maskParentScope;
+    private FunctionSignatures functionSignatures;
 
     public Scope(ScopeChecker scopeChecker) {
         this(scopeChecker, null);
     }
 
+    public Scope(ScopeChecker scopeChecker, Scope parent) {
+        this(scopeChecker, parent, false);
+    }
+
     public Scope(ScopeChecker scopeChecker, Scope parent, boolean 
maskParentScope) {
-        this(scopeChecker, parent);
+        this.scopeChecker = scopeChecker;
+        this.parent = parent;
         this.maskParentScope = maskParentScope;
+        this.symbols = new LinkedHashMap<>();
     }
 
     /**
@@ -81,36 +80,6 @@
         symbols.put(ident.getValue(), ident);
     }
 
-    /**
-     * Add a symbol and its definition expression into the scope
-     *
-     * @param ident
-     */
-    public void addSymbolExpressionMappingToScope(VariableExpr ident, 
Expression expr) {
-        varExprMap.put(ident.getVar().getValue(), expr);
-    }
-
-    /**
-     * Remove a symbol and its definition expression into the scope
-     *
-     * @param ident
-     */
-    public Expression removeSymbolExpressionMapping(VariableExpr ident) {
-        if (ident == null) {
-            return null;
-        }
-        return varExprMap.remove(ident.getVar().getValue());
-    }
-
-    /**
-     * @return the variable substituion environment for inlining variable 
references by its original
-     */
-    public VariableSubstitutionEnvironment getVarSubstitutionEnvironment() {
-        VariableSubstitutionEnvironment env = new 
VariableSubstitutionEnvironment();
-        env.addMappings(varExprMap);
-        return env;
-    }
-
     public void addNewVarSymbolToScope(VarIdentifier ident) {
         scopeChecker.incVarCounter();
         ident.setId(scopeChecker.getVarCounter());
@@ -120,8 +89,8 @@
     /**
      * Add a FunctionDescriptor into functionSignatures
      *
-     * @param fd
-     *            FunctionDescriptor
+     * @param signature
+     *            FunctionSignature
      * @param varargs
      *            whether this function has varargs
      */
@@ -163,7 +132,6 @@
         if (functionSignatures != null && scope.functionSignatures != null) {
             functionSignatures.addAll(scope.functionSignatures);
         }
-        varExprMap.putAll(scope.varExprMap);
     }
 
     /**
@@ -172,7 +140,7 @@
      * @return an iterator of visible symbols.
      */
     public Iterator<Identifier> liveSymbols() {
-        final Iterator<Identifier> identifierIterator = 
symbols.values().iterator();
+        final Iterator<Identifier> identifierIterator = new 
ReverseListIterator<>(new ArrayList<>(symbols.values()));
         final Iterator<Identifier> parentIterator = parent == null ? null : 
parent.liveSymbols();
         return new Iterator<Identifier>() {
             private Identifier currentSymbol = null;
@@ -180,7 +148,7 @@
             @Override
             public boolean hasNext() {
                 currentSymbol = null;
-                if (identifierIterator != null && 
identifierIterator.hasNext()) {
+                if (identifierIterator.hasNext()) {
                     currentSymbol = identifierIterator.next();
                 } else if (!maskParentScope && parentIterator != null && 
parentIterator.hasNext()) {
                     do {
@@ -213,8 +181,8 @@
         };
     }
 
-    public Set<VariableExpr> getLiveVariables() {
-        Set<VariableExpr> vars = new HashSet<VariableExpr>();
+    public LinkedHashSet<VariableExpr> getLiveVariables() {
+        LinkedHashSet<VariableExpr> vars = new LinkedHashSet<>();
         Iterator<Identifier> identifierIterator = liveSymbols();
         while (identifierIterator.hasNext()) {
             Identifier identifier = identifierIterator.next();
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/OperatorExpr.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/OperatorExpr.java
index b35aa91..ed23d25 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/OperatorExpr.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/OperatorExpr.java
@@ -98,7 +98,7 @@
         addOperator(op);
     }
 
-    public void addOperator(OperatorType op) throws CompilationException {
+    public void addOperator(OperatorType op) {
         if (op == null) {
             throw new NullPointerException();
         }
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
index dfe371e..dea0e3a 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
@@ -247,13 +247,6 @@
             gc.setGroupVar(groupVar);
         }
 
-        // Adds the group variable into the "with" (i.e., re-binding) variable 
list.
-        VariableExpr gbyVarRef = new VariableExpr(gc.getGroupVar().getVar());
-        gbyVarRef.setIsNewVar(false);
-        Map<Expression, VariableExpr> withVarMap = new HashMap<>();
-        withVarMap.put(gbyVarRef, (VariableExpr) 
SqlppRewriteUtil.deepCopy(gbyVarRef));
-        gc.setWithVarMap(withVarMap);
-
         // Call super.visit(...) to scope variables.
         return super.visit(gc, arg);
     }
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
index 6e6ffeb..a96bf50 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
@@ -135,6 +135,17 @@
                 + datasetName + "!");
     }
 
+    // Rewrites for an undefined variable reference, which potentially could 
be a syntatic sugar.
+    private Expression wrapWithResolveFunction(VariableExpr expr, 
Set<VariableExpr> liveVars)
+            throws CompilationException {
+        List<Expression> argList = new ArrayList<>();
+        //Ignore the parser-generated prefix "$" for a dataset.
+        String varName = 
SqlppVariableUtil.toUserDefinedVariableName(expr.getVar().getValue()).getValue();
+        argList.add(new LiteralExpr(new StringLiteral(varName)));
+        argList.addAll(liveVars);
+        return new CallExpr(new FunctionSignature(BuiltinFunctions.RESOLVE), 
argList);
+    }
+
     // Checks whether we need to error the variable reference, e.g., the 
variable is referred
     // in a LIMIT clause.
     private void checkError(String varName) throws CompilationException {
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
index 2d6ac53..b2c473c 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
@@ -22,9 +22,8 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.Set;
 
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.lang.common.base.ILangExpression;
@@ -77,12 +76,9 @@
         return varName;
     }
 
-    public static Set<VariableExpr> getLiveVariables(Scope scope, boolean 
includeWithVariables) {
-        Set<VariableExpr> results = new HashSet<>();
-        Set<VariableExpr> liveVars = scope.getLiveVariables();
-        Iterator<VariableExpr> liveVarIter = liveVars.iterator();
-        while (liveVarIter.hasNext()) {
-            VariableExpr liveVar = liveVarIter.next();
+    public static LinkedHashSet<VariableExpr> getLiveVariables(Scope scope, 
boolean includeWithVariables) {
+        LinkedHashSet<VariableExpr> results = new LinkedHashSet<>();
+        for (VariableExpr liveVar : scope.getLiveVariables()) {
             // Variables defined in WITH clauses are named value access.
             // TODO(buyingi): remove this if block once we can accurately type
             // ordered lists with UNION item type. Currently it is typed as 
[ANY].
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
index 38d09f9..d77cd63 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
@@ -264,15 +264,16 @@
     public Void visit(GroupbyClause gc, Integer step) throws 
CompilationException {
         if (gc.isGroupAll()) {
             out.println(skip(step) + "Group All");
-            return null;
         }
-        out.println(skip(step) + "Groupby");
-        for (GbyVariableExpressionPair pair : gc.getGbyPairList()) {
-            if (pair.getVar() != null) {
-                pair.getVar().accept(this, step + 1);
-                out.println(skip(step + 1) + ":=");
+        else {
+            out.println(skip(step) + "Groupby");
+            for (GbyVariableExpressionPair pair : gc.getGbyPairList()) {
+                if (pair.getVar() != null) {
+                    pair.getVar().accept(this, step + 1);
+                    out.println(skip(step + 1) + ":=");
+                }
+                pair.getExpr().accept(this, step + 1);
             }
-            pair.getExpr().accept(this, step + 1);
         }
         if (gc.hasGroupVar()) {
             out.print(skip(step + 1) + "GROUP AS ");
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
index 2f9cb32..52435e6 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
@@ -57,7 +57,6 @@
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
-import org.apache.asterix.om.functions.BuiltinFunctions;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.algebricks.core.algebra.base.Counter;
 
@@ -243,7 +242,7 @@
             }
         }
         if (gc.hasGroupVar()) {
-            addNewVarSymbolToScope(scopeChecker.getCurrentScope(), 
gc.getGroupVar().getVar());
+            addNewVarSymbolToScope(newScope, gc.getGroupVar().getVar());
         }
         if (gc.hasWithMap()) {
             Map<Expression, VariableExpr> newWithMap = new HashMap<>();
@@ -363,17 +362,6 @@
             insertStatement.setReturnExpression(visit(returningExpr, 
insertStatement));
         }
         return null;
-    }
-
-    // Rewrites for an undefined variable reference, which potentially could 
be a syntatic sugar.
-    protected Expression wrapWithResolveFunction(VariableExpr expr, 
Set<VariableExpr> liveVars)
-            throws CompilationException {
-        List<Expression> argList = new ArrayList<>();
-        //Ignore the parser-generated prefix "$" for a dataset.
-        String varName = 
SqlppVariableUtil.toUserDefinedVariableName(expr.getVar().getValue()).getValue();
-        argList.add(new LiteralExpr(new StringLiteral(varName)));
-        argList.addAll(liveVars);
-        return new CallExpr(new FunctionSignature(BuiltinFunctions.RESOLVE), 
argList);
     }
 
     // Adds a new encountered alias identifier into a scope
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj 
b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index a58ce0f..a6d7d12 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -143,6 +143,7 @@
 import org.apache.asterix.lang.common.statement.UpsertStatement;
 import org.apache.asterix.lang.common.statement.WriteStatement;
 import org.apache.asterix.lang.common.struct.Identifier;
+import org.apache.asterix.lang.common.struct.OperatorType;
 import org.apache.asterix.lang.common.struct.QuantifiedPair;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
@@ -1970,6 +1971,7 @@
        <AND>
        operand = IsExpr()
        {
+         op.addOperator(OperatorType.AND);
          op.addOperand(operand);
        }
     )?
diff --git a/asterixdb/pom.xml b/asterixdb/pom.xml
index 11d9218..c2bd159 100644
--- a/asterixdb/pom.xml
+++ b/asterixdb/pom.xml
@@ -1040,6 +1040,11 @@
         <version>3.5</version>
       </dependency>
       <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-collections4</artifactId>
+        <version>4.1</version>
+      </dependency>
+      <dependency>
         <groupId>xerces</groupId>
         <artifactId>xercesImpl</artifactId>
         <version>2.11.0</version>
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/ExternalGroupByPOperator.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/ExternalGroupByPOperator.java
index 9e7daf0..eecd066 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/ExternalGroupByPOperator.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/physical/ExternalGroupByPOperator.java
@@ -179,18 +179,23 @@
         Mutable<ILogicalOperator> r0 = p0.getRoots().get(0);
         AggregateOperator aggOp = (AggregateOperator) r0.getValue();
 
+        compileSubplans(inputSchemas[0], gby, opSchema, context);
+
         IPartialAggregationTypeComputer partialAggregationTypeComputer = 
context.getPartialAggregationTypeComputer();
         List<Object> intermediateTypes = new ArrayList<Object>();
         int n = aggOp.getExpressions().size();
         ISerializedAggregateEvaluatorFactory[] aff = new 
ISerializedAggregateEvaluatorFactory[n];
         int i = 0;
         IExpressionRuntimeProvider expressionRuntimeProvider = 
context.getExpressionRuntimeProvider();
-        IVariableTypeEnvironment aggOpInputEnv = 
context.getTypeEnvironment(aggOp.getInputs().get(0).getValue());
+        ILogicalOperator aggOpInput = aggOp.getInputs().get(0).getValue();
+        IOperatorSchema aggOpInputSchema = context.getSchema(aggOpInput);
+        IOperatorSchema[] aggOpInputSchemas = new IOperatorSchema[] { 
aggOpInputSchema };
+        IVariableTypeEnvironment aggOpInputEnv = 
context.getTypeEnvironment(aggOpInput);
         IVariableTypeEnvironment outputEnv = context.getTypeEnvironment(op);
         for (Mutable<ILogicalExpression> exprRef : aggOp.getExpressions()) {
             AggregateFunctionCallExpression aggFun = 
(AggregateFunctionCallExpression) exprRef.getValue();
             aff[i++] = 
expressionRuntimeProvider.createSerializableAggregateFunctionFactory(aggFun, 
aggOpInputEnv,
-                    inputSchemas, context);
+                    aggOpInputSchemas, context);
             intermediateTypes
                     .add(partialAggregationTypeComputer.getType(aggFun, 
aggOpInputEnv, context.getMetadataProvider()));
         }
@@ -215,7 +220,6 @@
             aggOpInputEnv.setVarType(var, outputEnv.getVarType(var));
         }
 
-        compileSubplans(inputSchemas[0], gby, opSchema, context);
         IOperatorDescriptorRegistry spec = builder.getJobSpec();
         IBinaryComparatorFactory[] comparatorFactories = 
JobGenHelper.variablesToAscBinaryComparatorFactories(gbyCols,
                 aggOpInputEnv, context);

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/2169
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I69b1c5422017ceaa74a0cd83085c910292b00418
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Dmitry Lychagin <[email protected]>

Reply via email to