You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@asterixdb.apache.org by AsterixDB Code Review <do...@asterix-gerrit.ics.uci.edu> on 2026/10/21 05:39:34 UTC

[L] Change in asterixdb[master]: [NO ISSUE][COMP] Fix references to outer variables after GROUP BY

From Ali Alsuliman <al...@gmail.com>:

Ali Alsuliman has uploaded this change for review. ( https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/22131?usp=email )


Change subject: [NO ISSUE][COMP] Fix references to outer variables after GROUP BY
......................................................................

[NO ISSUE][COMP] Fix references to outer variables after GROUP BY

- user model changes: yes, a reference to an outer variable that is
  shadowed by a FROM or LET variable of the block is now rejected
  (ASX1074) instead of binding to an arbitrary row
- storage format changes: no
- interface changes: no

Details: Three defects around a variable bound outside a select block
(a WITH alias, a top-level LET, an enclosing query's variable) when the
block has a GROUP BY. The first two shared a FROM alias named like the
outer variable; the third needs no name clash.

1. A window function after the GROUP BY builds its frame record from
   the variables still in scope, checked by name. A FROM variable of
   the block was kept whenever an outer variable had the same name,
   although it is dead above the GROUP BY. WITH inlining then
   substituted the alias body into that field and the translator kept
   only the body's output variable, leaving a reference nothing
   produces: the internal sanity check rejects the plan ("undefined
   used variables"), and without it the field is removed before
   anything reads it. SqlppWindowAggregationSugarVisitor now keeps a
   variable only when its name resolves to that very variable.

2. An outer variable referenced after the GROUP BY is carried through
   it as a decoration "v := v", whose expression is evaluated before
   the GROUP BY. When a FROM or LET variable of the block has the same
   name, the name resolves there to the local variable, so the
   decoration silently became one arbitrary row of each group: with a
   WITH alias t, "SELECT a, t.b FROM t GROUP BY t.a" returned some
   member's b, "SUM(t.b) OVER ()" summed one member per group, and in
   a correlated subquery an inner alias shadowing an outer one read
   the inner rows. The same queries without the clash are rejected as
   an undefined identifier. No expression before the GROUP BY can
   denote the shadowed variable, so SqlppGroupByAggregationSugarVisitor
   rejects the reference as an ambiguous alias (ASX1074), pointing at
   the place it is used.

3. When the decorated value is a listify computed by a subplan below
   the GROUP BY, two rules removed that listify as unused while the
   decoration still read it, and the query failed in type inference
   (a NullPointerException, or "undefined used variables" under the
   sanity check). PushAggregateIntoNestedSubplanRule counted the uses
   of a listify for every operator except GROUP BY and CLUSTER BY,
   whose decoration expressions were never counted; it fires once the
   block also has a SQL-92 aggregate. RemoveRedundantListifyRule
   prunes the variables used above an operator to the operator's live
   variables before visiting its nested plans, and carried that pruned
   set down to the inputs as well, forgetting a decoration's use of an
   input variable; this hit every reference to a WITH alias that
   cannot be inlined. The first rule now counts the GROUP BY's own
   used variables; the second prunes only for the nested plans.

Generated-by: Claude Fable 5.1 <no...@anthropic.com>
Change-Id: I6baf3834be542eb22f174f5fcc5794988e6c3271
---
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/RemoveRedundantListifyRule.java
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.1.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.2.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.3.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.4.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.5.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.6.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.1.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.2.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.3.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.4.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.1.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.2.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.3.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.4.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.5.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.1.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.2.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.3.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.4.query.sqlpp
A asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.1.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.2.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.3.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.4.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.1.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.2.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.3.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.4.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.5.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.1.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.2.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.3.adm
A asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.4.adm
M asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
M asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java
M asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowAggregationSugarVisitor.java
37 files changed, 578 insertions(+), 10 deletions(-)



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

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 9dfb3fe..d0c305f 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
@@ -200,6 +200,9 @@
                 // of the group by operator (if possible).
                 collectAggregateVars(nspListifyVarsCount, nspWithAgg, nspAggVarToPlanIndex,
                         (AbstractOperatorWithNestedPlans) op1);
+                // A decoration can read a listify produced below (an outer variable carried through the
+                // group-by); without counting it the listify is removed as unused.
+                countListifyUses(nspListifyVarsCount, used);
                 break;
             case CLUSTER_BY:
                 // CLUSTER BY carries its members listify as a nested plan, exactly as GROUP BY does;
@@ -207,18 +210,23 @@
                 // plan before the operator is expanded, so the list itself is never materialized.
                 collectAggregateVars(nspListifyVarsCount, nspWithAgg, nspAggVarToPlanIndex,
                         (AbstractOperatorWithNestedPlans) op1);
+                countListifyUses(nspListifyVarsCount, used);
                 break;
             default:
-                for (LogicalVariable v : used) {
-                    Integer m = nspListifyVarsCount.get(v);
-                    if (m != null) {
-                        nspListifyVarsCount.put(v, m + 1);
-                    }
-                }
+                countListifyUses(nspListifyVarsCount, used);
         }
         return change;
     }
 
+    private static void countListifyUses(Map<LogicalVariable, Integer> nspListifyVarsCount, Set<LogicalVariable> used) {
+        for (LogicalVariable v : used) {
+            Integer m = nspListifyVarsCount.get(v);
+            if (m != null) {
+                nspListifyVarsCount.put(v, m + 1);
+            }
+        }
+    }
+
     private void collectAggregateVars(Map<LogicalVariable, Integer> nspListifyVarsCount,
             Map<LogicalVariable, AbstractOperatorWithNestedPlans> nspWithAgg,
             Map<LogicalVariable, Integer> nspAggVarToPlanIndex, AbstractOperatorWithNestedPlans op) {
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveRedundantListifyRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveRedundantListifyRule.java
index 0f490be..0d60652 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveRedundantListifyRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveRedundantListifyRule.java
@@ -127,14 +127,17 @@
         VariableUtilities.getUsedVariables(op, varSet);
         if (op.hasNestedPlans()) {
             boolean isSubplanOp = op.getOperatorTag() == LogicalOperatorTag.SUBPLAN;
-            // Variables used by the parent operators should be live at op.
+            // Variables used by the parent operators should be live at op. The pruned set is for the nested
+            // plans only: the inputs must still see everything op itself uses, such as a listify read by a
+            // group-by decoration, which is an input variable and not live at op.
             Set<LogicalVariable> localLiveVars = new ListSet<>();
             VariableUtilities.getLiveVariables(op, localLiveVars);
-            varSet.retainAll(localLiveVars);
+            Set<LogicalVariable> nestedVarSet = new HashSet<>(varSet);
+            nestedVarSet.retainAll(localLiveVars);
             AbstractOperatorWithNestedPlans aonp = (AbstractOperatorWithNestedPlans) op;
             for (ILogicalPlan p : aonp.getNestedPlans()) {
                 for (Mutable<ILogicalOperator> r : p.getRoots()) {
-                    if (applyRuleDown(r, isSubplanOp, varSet, context)) {
+                    if (applyRuleDown(r, isSubplanOp, nestedVarSet, context)) {
                         changed = true;
                     }
                     context.addToDontApplySet(this, r.getValue());
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.1.query.sqlpp
new file mode 100644
index 0000000..fb86389
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.1.query.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description  : An outer variable (WITH alias, top-level LET, enclosing query
+ *                variable) referenced after GROUP BY while a FROM variable of
+ *                the block has the same name. There is no expression before the
+ *                GROUP BY that can denote the outer variable, so the reference
+ *                is rejected instead of binding to an arbitrary row.
+ * Expected Res : Failure
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, t.b AS b
+FROM t
+GROUP BY t.a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.2.query.sqlpp
new file mode 100644
index 0000000..59a38e6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.2.query.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, SUM(t.b) OVER () AS tot
+FROM t
+GROUP BY t.a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.3.query.sqlpp
new file mode 100644
index 0000000..5b457d3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.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.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a
+FROM t
+GROUP BY t.a
+HAVING t.b > 15;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.4.query.sqlpp
new file mode 100644
index 0000000..4a9aa90
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.4.query.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+SELECT r.b AS outer_b,
+       (SELECT a, r.b AS b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS r GROUP BY r.a) AS inr
+FROM [{"b":5}] AS r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.5.query.sqlpp
new file mode 100644
index 0000000..acf1fdf
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.5.query.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+LET t = 5
+SELECT a, t AS tt
+FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS t
+GROUP BY t.a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.6.query.sqlpp
new file mode 100644
index 0000000..7057529
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-01-error/gby-outer-shadow-01-error.6.query.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, (SELECT VALUE t.b FROM g AS y) AS bs
+FROM t
+GROUP BY t.a GROUP AS g;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.1.query.sqlpp
new file mode 100644
index 0000000..61134c7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.1.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description  : The same shapes as gby-outer-shadow-01-error without the name
+ *                clash, and references that resolve through the group variable.
+ */
+
+SELECT o.b AS outer_b,
+       (SELECT a, o.b AS b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS r GROUP BY r.a ORDER BY a) AS inr
+FROM [{"b":5}] AS o;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.2.query.sqlpp
new file mode 100644
index 0000000..532322f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.2.query.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+SELECT a, (SELECT VALUE t.b FROM g AS y) AS bs
+FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS t
+GROUP BY t.a GROUP AS g
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.3.query.sqlpp
new file mode 100644
index 0000000..045b423
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.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.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, SUM(t.b) AS s
+FROM t
+GROUP BY t.a
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.4.query.sqlpp
new file mode 100644
index 0000000..6d1ed33
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-shadow-02/gby-outer-shadow-02.4.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.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, SUM(u.b) AS s, (SELECT VALUE y.u.b FROM g AS y) AS bs
+FROM t AS u
+GROUP BY u.a GROUP AS g
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.1.query.sqlpp
new file mode 100644
index 0000000..13094b7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.1.query.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description  : A WITH variable (inlined or not) referenced after GROUP BY,
+ *                next to a SQL-92 aggregate. The CTE value is carried through
+ *                the GROUP BY as a decoration; the optimizer must keep its
+ *                producer.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, s, t AS whole
+FROM t AS u
+GROUP BY u.a
+LET s = SUM(u.b)
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.2.query.sqlpp
new file mode 100644
index 0000000..5375355
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.2.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.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, ARRAY_LENGTH(t) AS n, SUM(u.b) AS s
+FROM t AS u
+GROUP BY u.a
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.3.query.sqlpp
new file mode 100644
index 0000000..8a6304f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.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.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, (SELECT VALUE y.b FROM t AS y) AS all_b, SUM(u.b) AS s
+FROM t AS u
+GROUP BY u.a
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.4.query.sqlpp
new file mode 100644
index 0000000..8a9a522
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.4.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.
+ */
+
+WITH t AS (SELECT x.a, x.b, random() AS r FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, ARRAY_LENGTH(t) AS n
+FROM t AS u
+GROUP BY u.a
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.5.query.sqlpp
new file mode 100644
index 0000000..239b24b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-outer-with-01/gby-outer-with-01.5.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.
+ */
+
+WITH t AS (SELECT x.a, x.b, random() AS r FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, ARRAY_LENGTH(t) AS n, COUNT(*) OVER () AS c
+FROM t AS u
+GROUP BY u.a
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.1.query.sqlpp
new file mode 100644
index 0000000..d318723
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.1.query.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description  : A FROM alias that is also the name of a WITH alias or of an
+ *                outer query variable, followed by GROUP BY and a window
+ *                function. The window frame record must not reference the
+ *                FROM variable, which is dead after the GROUP BY.
+ */
+
+WITH t AS (SELECT x.a FROM [{"a":1},{"a":2}] AS x)
+SELECT a, COUNT(*) OVER () AS c
+FROM t
+GROUP BY t.a
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.2.query.sqlpp
new file mode 100644
index 0000000..8e3bb95
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.2.query.sqlpp
@@ -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.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, s, SUM(s) OVER () AS tot
+FROM t
+GROUP BY t.a
+LET s = SUM(t.b)
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.3.query.sqlpp
new file mode 100644
index 0000000..50b14fb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.3.query.sqlpp
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+SELECT (SELECT a, COUNT(*) OVER () AS c FROM [{"a":1},{"a":2}] AS r GROUP BY r.a ORDER BY a) AS inr
+FROM [{"x":1}] AS r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.4.query.sqlpp
new file mode 100644
index 0000000..562936e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/window/win_outer_alias_01/win_outer_alias_01.4.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.
+ */
+
+WITH t AS (SELECT x.a, x.b FROM [{"a":1,"b":10},{"a":1,"b":20},{"a":2,"b":30}] AS x)
+SELECT a, (SELECT VALUE y.row.b FROM g AS y) AS bs, SUM(t.b) AS s, COUNT(*) OVER () AS c
+FROM t
+GROUP BY t.a GROUP AS g(t AS row)
+ORDER BY a;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.1.adm
new file mode 100644
index 0000000..8f5721b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.1.adm
@@ -0,0 +1 @@
+{ "outer_b": 5, "inr": [ { "a": 1, "b": 5 }, { "a": 2, "b": 5 } ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.2.adm
new file mode 100644
index 0000000..0c2cb31
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.2.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "bs": [ 10, 20 ] }
+{ "a": 2, "bs": [ 30 ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.3.adm
new file mode 100644
index 0000000..cbb2f50
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.3.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "s": 30 }
+{ "a": 2, "s": 30 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.4.adm
new file mode 100644
index 0000000..e8d68ad
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-shadow-02/gby-outer-shadow-02.4.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "s": 30, "bs": [ 10, 20 ] }
+{ "a": 2, "s": 30, "bs": [ 30 ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.1.adm
new file mode 100644
index 0000000..7d04cea
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.1.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "s": 30, "whole": [ { "a": 1, "b": 10 }, { "a": 1, "b": 20 }, { "a": 2, "b": 30 } ] }
+{ "a": 2, "s": 30, "whole": [ { "a": 1, "b": 10 }, { "a": 1, "b": 20 }, { "a": 2, "b": 30 } ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.2.adm
new file mode 100644
index 0000000..0a656d3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.2.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "n": 3, "s": 30 }
+{ "a": 2, "n": 3, "s": 30 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.3.adm
new file mode 100644
index 0000000..c4ee097
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.3.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "all_b": [ 10, 20, 30 ], "s": 30 }
+{ "a": 2, "all_b": [ 10, 20, 30 ], "s": 30 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.4.adm
new file mode 100644
index 0000000..5dc92ed
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.4.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "n": 3 }
+{ "a": 2, "n": 3 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.5.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.5.adm
new file mode 100644
index 0000000..07d07c3a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/group-by/gby-outer-with-01/gby-outer-with-01.5.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "n": 3, "c": 2 }
+{ "a": 2, "n": 3, "c": 2 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.1.adm
new file mode 100644
index 0000000..946c323
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.1.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "c": 2 }
+{ "a": 2, "c": 2 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.2.adm
new file mode 100644
index 0000000..ce4aeb2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.2.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "s": 30, "tot": 60 }
+{ "a": 2, "s": 30, "tot": 60 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.3.adm
new file mode 100644
index 0000000..da94637
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.3.adm
@@ -0,0 +1 @@
+{ "inr": [ { "a": 1, "c": 2 }, { "a": 2, "c": 2 } ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.4.adm
new file mode 100644
index 0000000..8fd113f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/win_outer_alias_01/win_outer_alias_01.4.adm
@@ -0,0 +1,2 @@
+{ "a": 1, "bs": [ 10, 20 ], "s": 30, "c": 2 }
+{ "a": 2, "bs": [ 30 ], "s": 30, "c": 2 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
index b45705d..35fc63d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
@@ -6355,6 +6355,27 @@
         <output-dir compare="Text">query-ASTERIXDB-3016</output-dir>
       </compilation-unit>
     </test-case-->
+    <test-case FilePath="group-by">
+      <compilation-unit name="gby-outer-shadow-01-error">
+        <output-dir compare="Text">none</output-dir>
+        <expected-error>ASX1074: Cannot resolve ambiguous alias reference for identifier t (in line 30, at column 11)</expected-error>
+        <expected-error>ASX1074: Cannot resolve ambiguous alias reference for identifier t (in line 21, at column 15)</expected-error>
+        <expected-error>ASX1074: Cannot resolve ambiguous alias reference for identifier t (in line 24, at column 8)</expected-error>
+        <expected-error>ASX1074: Cannot resolve ambiguous alias reference for identifier r (in line 21, at column 19)</expected-error>
+        <expected-error>ASX1074: Cannot resolve ambiguous alias reference for identifier t (in line 21, at column 11)</expected-error>
+        <expected-error>ASX1074: Cannot resolve ambiguous alias reference for identifier t (in line 21, at column 25)</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="group-by">
+      <compilation-unit name="gby-outer-shadow-02">
+        <output-dir compare="Text">gby-outer-shadow-02</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="group-by">
+      <compilation-unit name="gby-outer-with-01">
+        <output-dir compare="Text">gby-outer-with-01</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="index-join">
     <test-case FilePath="index-join">
@@ -16851,6 +16872,11 @@
         <output-dir compare="Text">win_opt_02</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="window">
+      <compilation-unit name="win_outer_alias_01">
+        <output-dir compare="Text">win_outer_alias_01</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="column">
     <test-case FilePath="column">
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java
index 19d0e48..2a56df6 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java
@@ -134,6 +134,13 @@
                             groupbyClause.getSourceLocation(), decorVars + ":" + freeVariables);
                 }
                 decorVars.retainAll(freeVariables);
+                for (VariableExpr var : decorVars) {
+                    if (isShadowedBeforeGroupBy(var, preGroupVars)) {
+                        throw new CompilationException(ErrorCode.AMBIGUOUS_IDENTIFIER,
+                                findSourceLocation(var, freeVariables),
+                                SqlppVariableUtil.toUserDefinedName(var.getVar().getValue()));
+                    }
+                }
 
                 if (!decorVars.isEmpty()) {
                     // Adds necessary decoration variables for the GROUP BY.
@@ -272,6 +279,30 @@
         return freeVariables;
     }
 
+    /**
+     * An outer variable referenced after the GROUP BY is carried through it as a decoration evaluated before
+     * the GROUP BY. Where a FROM/LET variable of this block has the same name, no expression there can denote
+     * the outer one: a decoration would silently rebind to the local variable (one arbitrary row per group), so
+     * the reference is rejected instead.
+     */
+    private static boolean isShadowedBeforeGroupBy(VariableExpr var, Set<VariableExpr> preGroupVars) {
+        for (VariableExpr preGroupVar : preGroupVars) {
+            if (preGroupVar.equals(var)) {
+                return preGroupVar.getVar() != var.getVar();
+            }
+        }
+        return false;
+    }
+
+    private static SourceLocation findSourceLocation(VariableExpr var, Collection<VariableExpr> references) {
+        for (VariableExpr ref : references) {
+            if (ref.equals(var) && ref.getSourceLocation() != null) {
+                return ref.getSourceLocation();
+            }
+        }
+        return var.getSourceLocation();
+    }
+
     private void removeExternalVariables(Collection<VariableExpr> freeVariables) {
         if (!externalVars.isEmpty()) {
             freeVariables.removeIf(ve -> externalVars.contains(ve.getVar()));
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowAggregationSugarVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowAggregationSugarVisitor.java
index 38419c8..2fc5bca 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowAggregationSugarVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowAggregationSugarVisitor.java
@@ -154,7 +154,9 @@
 
     private void addToFieldList(List<Pair<Expression, Identifier>> outFieldList, List<VariableExpr> varList) {
         for (VariableExpr varExpr : varList) {
-            if (scopeChecker.lookupSymbol(varExpr.getVar().getValue()) != null) {
+            // Identity, not name: after GROUP BY a WITH or outer-query variable of the same name still resolves,
+            // and a name match would put the block's dead FROM/LET variable into the window record.
+            if (scopeChecker.lookupSymbol(varExpr.getVar().getValue()) == varExpr.getVar()) {
                 SqlppVariableUtil.addToFieldVariableList(varExpr, outFieldList);
             }
         }

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/22131?usp=email
To unsubscribe, or for help writing mail filters, visit https://asterix-gerrit.ics.uci.edu/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: I6baf3834be542eb22f174f5fcc5794988e6c3271
Gerrit-Change-Number: 22131
Gerrit-PatchSet: 1
Gerrit-Owner: Ali Alsuliman <al...@gmail.com>