This is an automated email from the ASF dual-hosted git repository.

dlych pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git

commit 9b39f07e53ab454bc137df7b3d5e616b6cc13066
Author: Dmitry Lychagin <[email protected]>
AuthorDate: Tue Nov 10 18:11:02 2020 -0800

    [NO ISSUE][COMP] Keep constant assigns in subplans
    
    - user model changes: no
    - storage format changes: no
    - interface changes: no
    
    Details:
    - Do not move constant assigns out of subplans
    - Fix PushSubplanIntoGroupByRule handling of
      right branches of binary operators
    
    Change-Id: Ic0e892f71d464babdcc45e975b6425ff2555aaa6
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/8823
    Integration-Tests: Jenkins <[email protected]>
    Tested-by: Jenkins <[email protected]>
    Reviewed-by: Ali Alsuliman <[email protected]>
---
 ...ixMoveFreeVariableOperatorOutOfSubplanRule.java |  11 +-
 .../queries/leftouterjoin/loj-03-no-listify.sqlpp  |  49 ++++++++
 .../results/leftouterjoin/loj-03-no-listify.plan   | 127 +++++++++++++++++++++
 .../loj-03-no-listify.1.ddl.sqlpp}                 |  17 ++-
 .../loj-03-no-listify.2.update.sqlpp}              |  26 +++--
 .../loj-03-no-listify.3.query.sqlpp}               |  28 +++--
 .../loj-03-no-listify/loj-03-no-listify.3.adm      |   2 +
 .../test/resources/runtimets/testsuite_sqlpp.xml   |   5 +
 .../MoveFreeVariableOperatorOutOfSubplanRule.java  |  22 ++--
 .../rules/subplan/PushSubplanIntoGroupByRule.java  |  33 ++++--
 10 files changed, 272 insertions(+), 48 deletions(-)

diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
index 4d6b4bb..66dcc83 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
@@ -18,13 +18,22 @@
  */
 package org.apache.asterix.optimizer.rules.subplan;
 
+import java.util.Set;
+
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
 import 
org.apache.hyracks.algebricks.rewriter.rules.subplan.MoveFreeVariableOperatorOutOfSubplanRule;
 
 public class AsterixMoveFreeVariableOperatorOutOfSubplanRule extends 
MoveFreeVariableOperatorOutOfSubplanRule {
 
     @Override
-    protected boolean movableOperator(LogicalOperatorTag operatorTag) {
+    protected boolean movableOperatorKind(LogicalOperatorTag operatorTag) {
         return (operatorTag == LogicalOperatorTag.ASSIGN);
     }
+
+    @Override
+    protected boolean movableIndependentOperator(ILogicalOperator op, 
Set<LogicalVariable> usedVars) {
+        return !usedVars.isEmpty();
+    }
 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/leftouterjoin/loj-03-no-listify.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/leftouterjoin/loj-03-no-listify.sqlpp
new file mode 100644
index 0000000..510e26c
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/leftouterjoin/loj-03-no-listify.sqlpp
@@ -0,0 +1,49 @@
+/*
+ * 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: Test that listify() is eliminated
+ *              on the right side of an outer join
+ */
+
+DROP DATAVERSE test IF EXISTS;
+CREATE DATAVERSE test;
+
+USE test;
+
+CREATE TYPE tasksType AS {
+  id : integer
+};
+
+CREATE DATASET tasks(tasksType) PRIMARY KEY id;
+
+SELECT t0.taskId, t0.cnt_all, t1.cnt_x, t2.cnt_y, t3.cnt_z
+FROM (
+  SELECT taskId, COUNT(1) AS cnt_all FROM tasks GROUP BY taskId ORDER BY taskId
+) AS t0
+LEFT OUTER JOIN (
+  SELECT taskId, COUNT(1) AS cnt_x FROM tasks WHERE status="x" GROUP BY taskId
+) AS t1 ON t0.taskId = t1.taskId
+LEFT OUTER JOIN (
+  SELECT taskId, COUNT(1) AS cnt_y FROM tasks WHERE status="y" GROUP BY taskId
+) AS t2 ON t0.taskId = t2.taskId
+LEFT OUTER JOIN (
+  SELECT taskId, COUNT(1) AS cnt_z FROM tasks WHERE status="z" GROUP BY taskId
+) AS t3 ON t0.taskId = t3.taskId
+ORDER BY t0.taskId;
diff --git 
a/asterixdb/asterix-app/src/test/resources/optimizerts/results/leftouterjoin/loj-03-no-listify.plan
 
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/leftouterjoin/loj-03-no-listify.plan
new file mode 100644
index 0000000..5184b51
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/optimizerts/results/leftouterjoin/loj-03-no-listify.plan
@@ -0,0 +1,127 @@
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    -- STREAM_PROJECT  |PARTITIONED|
+      -- ASSIGN  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$taskId(ASC) ]  |PARTITIONED|
+          -- STABLE_SORT [$$taskId(ASC)]  |PARTITIONED|
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              -- STREAM_PROJECT  |PARTITIONED|
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  -- HYBRID_HASH_JOIN [$$taskId][$$taskId]  |PARTITIONED|
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      -- STREAM_PROJECT  |PARTITIONED|
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          -- HYBRID_HASH_JOIN [$$taskId][$$taskId]  
|PARTITIONED|
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              -- STREAM_PROJECT  |PARTITIONED|
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  -- HYBRID_HASH_JOIN [$$taskId][$$taskId]  
|PARTITIONED|
+                                    -- HASH_PARTITION_MERGE_EXCHANGE 
MERGE:[$$taskId(ASC)] HASH:[$$taskId]  |PARTITIONED|
+                                      -- SORT_GROUP_BY[$$263]  |PARTITIONED|
+                                              {
+                                                -- AGGREGATE  |LOCAL|
+                                                  -- NESTED_TUPLE_SOURCE  
|LOCAL|
+                                              }
+                                        -- HASH_PARTITION_EXCHANGE [$$263]  
|PARTITIONED|
+                                          -- SORT_GROUP_BY[$$226]  
|PARTITIONED|
+                                                  {
+                                                    -- AGGREGATE  |LOCAL|
+                                                      -- NESTED_TUPLE_SOURCE  
|LOCAL|
+                                                  }
+                                            -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
+                                              -- STREAM_PROJECT  |PARTITIONED|
+                                                -- ASSIGN  |PARTITIONED|
+                                                  -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
+                                                    -- REPLICATE  |PARTITIONED|
+                                                      -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
+                                                        -- ASSIGN  
|PARTITIONED|
+                                                          -- STREAM_PROJECT  
|PARTITIONED|
+                                                            -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                              -- 
DATASOURCE_SCAN  |PARTITIONED|
+                                                                -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                  -- 
EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      -- STREAM_PROJECT  |PARTITIONED|
+                                        -- ASSIGN  |PARTITIONED|
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- SORT_GROUP_BY[$$265]  
|PARTITIONED|
+                                                    {
+                                                      -- AGGREGATE  |LOCAL|
+                                                        -- NESTED_TUPLE_SOURCE 
 |LOCAL|
+                                                    }
+                                              -- HASH_PARTITION_EXCHANGE 
[$$265]  |PARTITIONED|
+                                                -- SORT_GROUP_BY[$$227]  
|PARTITIONED|
+                                                        {
+                                                          -- AGGREGATE  |LOCAL|
+                                                            -- 
NESTED_TUPLE_SOURCE  |LOCAL|
+                                                        }
+                                                  -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
+                                                    -- STREAM_PROJECT  
|PARTITIONED|
+                                                      -- STREAM_SELECT  
|PARTITIONED|
+                                                        -- ONE_TO_ONE_EXCHANGE 
 |PARTITIONED|
+                                                          -- REPLICATE  
|PARTITIONED|
+                                                            -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                              -- ASSIGN  
|PARTITIONED|
+                                                                -- 
STREAM_PROJECT  |PARTITIONED|
+                                                                  -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                    -- 
DATASOURCE_SCAN  |PARTITIONED|
+                                                                      -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                        -- 
EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              -- STREAM_PROJECT  |PARTITIONED|
+                                -- ASSIGN  |PARTITIONED|
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- SORT_GROUP_BY[$$267]  |PARTITIONED|
+                                            {
+                                              -- AGGREGATE  |LOCAL|
+                                                -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                            }
+                                      -- HASH_PARTITION_EXCHANGE [$$267]  
|PARTITIONED|
+                                        -- SORT_GROUP_BY[$$228]  |PARTITIONED|
+                                                {
+                                                  -- AGGREGATE  |LOCAL|
+                                                    -- NESTED_TUPLE_SOURCE  
|LOCAL|
+                                                }
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            -- STREAM_PROJECT  |PARTITIONED|
+                                              -- STREAM_SELECT  |PARTITIONED|
+                                                -- STREAM_PROJECT  
|PARTITIONED|
+                                                  -- ASSIGN  |PARTITIONED|
+                                                    -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
+                                                      -- REPLICATE  
|PARTITIONED|
+                                                        -- ONE_TO_ONE_EXCHANGE 
 |PARTITIONED|
+                                                          -- ASSIGN  
|PARTITIONED|
+                                                            -- STREAM_PROJECT  
|PARTITIONED|
+                                                              -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                -- 
DATASOURCE_SCAN  |PARTITIONED|
+                                                                  -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                    -- 
EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      -- STREAM_PROJECT  |PARTITIONED|
+                        -- ASSIGN  |PARTITIONED|
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            -- SORT_GROUP_BY[$$269]  |PARTITIONED|
+                                    {
+                                      -- AGGREGATE  |LOCAL|
+                                        -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                    }
+                              -- HASH_PARTITION_EXCHANGE [$$269]  |PARTITIONED|
+                                -- SORT_GROUP_BY[$$229]  |PARTITIONED|
+                                        {
+                                          -- AGGREGATE  |LOCAL|
+                                            -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                        }
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- STREAM_PROJECT  |PARTITIONED|
+                                      -- STREAM_SELECT  |PARTITIONED|
+                                        -- STREAM_PROJECT  |PARTITIONED|
+                                          -- ASSIGN  |PARTITIONED|
+                                            -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
+                                              -- REPLICATE  |PARTITIONED|
+                                                -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
+                                                  -- ASSIGN  |PARTITIONED|
+                                                    -- STREAM_PROJECT  
|PARTITIONED|
+                                                      -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
+                                                        -- DATASOURCE_SCAN  
|PARTITIONED|
+                                                          -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                            -- 
EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-03-no-listify/loj-03-no-listify.1.ddl.sqlpp
similarity index 62%
copy from 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
copy to 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-03-no-listify/loj-03-no-listify.1.ddl.sqlpp
index 4d6b4bb..bc81bff 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-03-no-listify/loj-03-no-listify.1.ddl.sqlpp
@@ -16,15 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.optimizer.rules.subplan;
 
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import 
org.apache.hyracks.algebricks.rewriter.rules.subplan.MoveFreeVariableOperatorOutOfSubplanRule;
+DROP DATAVERSE test IF EXISTS;
+CREATE DATAVERSE test;
 
-public class AsterixMoveFreeVariableOperatorOutOfSubplanRule extends 
MoveFreeVariableOperatorOutOfSubplanRule {
+USE test;
 
-    @Override
-    protected boolean movableOperator(LogicalOperatorTag operatorTag) {
-        return (operatorTag == LogicalOperatorTag.ASSIGN);
-    }
-}
+CREATE TYPE tasksType AS {
+  id : integer
+};
+
+CREATE DATASET tasks(tasksType) PRIMARY KEY id;
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-03-no-listify/loj-03-no-listify.2.update.sqlpp
similarity index 61%
copy from 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
copy to 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-03-no-listify/loj-03-no-listify.2.update.sqlpp
index 4d6b4bb..061d357 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-03-no-listify/loj-03-no-listify.2.update.sqlpp
@@ -16,15 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.optimizer.rules.subplan;
 
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import 
org.apache.hyracks.algebricks.rewriter.rules.subplan.MoveFreeVariableOperatorOutOfSubplanRule;
+USE test;
 
-public class AsterixMoveFreeVariableOperatorOutOfSubplanRule extends 
MoveFreeVariableOperatorOutOfSubplanRule {
-
-    @Override
-    protected boolean movableOperator(LogicalOperatorTag operatorTag) {
-        return (operatorTag == LogicalOperatorTag.ASSIGN);
-    }
-}
+INSERT INTO tasks
+([
+  {"id": 1,  "taskId":1, "status":"x"},
+  {"id": 2,  "taskId":1, "status":"x"},
+  {"id": 3,  "taskId":1, "status":"y"},
+  {"id": 4,  "taskId":1, "status":"y"},
+  {"id": 5,  "taskId":1, "status":"z"},
+  {"id": 6,  "taskId":1, "status":"z"},
+  {"id": 7,  "taskId":2, "status":"x"},
+  {"id": 8,  "taskId":2, "status":"x"},
+  {"id": 9,  "taskId":2, "status":"y"},
+  {"id": 10, "taskId":2, "status":"y"},
+  {"id": 11, "taskId":2, "status":"z"},
+  {"id": 12, "taskId":2, "status":"z"}
+]);
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-03-no-listify/loj-03-no-listify.3.query.sqlpp
similarity index 54%
copy from 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
copy to 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-03-no-listify/loj-03-no-listify.3.query.sqlpp
index 4d6b4bb..d64e711 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/AsterixMoveFreeVariableOperatorOutOfSubplanRule.java
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/leftouterjoin/loj-03-no-listify/loj-03-no-listify.3.query.sqlpp
@@ -16,15 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.asterix.optimizer.rules.subplan;
 
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import 
org.apache.hyracks.algebricks.rewriter.rules.subplan.MoveFreeVariableOperatorOutOfSubplanRule;
+/*
+ * Description: Test that listify() is eliminated
+ *              on the right side of an outer join
+ */
 
-public class AsterixMoveFreeVariableOperatorOutOfSubplanRule extends 
MoveFreeVariableOperatorOutOfSubplanRule {
+USE test;
 
-    @Override
-    protected boolean movableOperator(LogicalOperatorTag operatorTag) {
-        return (operatorTag == LogicalOperatorTag.ASSIGN);
-    }
-}
+SELECT t0.taskId, t0.cnt_all, t1.cnt_x, t2.cnt_y, t3.cnt_z
+FROM (
+  SELECT taskId, COUNT(1) AS cnt_all FROM tasks GROUP BY taskId ORDER BY taskId
+) AS t0
+LEFT OUTER JOIN (
+  SELECT taskId, COUNT(1) AS cnt_x FROM tasks WHERE status="x" GROUP BY taskId
+) AS t1 ON t0.taskId = t1.taskId
+LEFT OUTER JOIN (
+  SELECT taskId, COUNT(1) AS cnt_y FROM tasks WHERE status="y" GROUP BY taskId
+) AS t2 ON t0.taskId = t2.taskId
+LEFT OUTER JOIN (
+  SELECT taskId, COUNT(1) AS cnt_z FROM tasks WHERE status="z" GROUP BY taskId
+) AS t3 ON t0.taskId = t3.taskId
+ORDER BY t0.taskId;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-03-no-listify/loj-03-no-listify.3.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-03-no-listify/loj-03-no-listify.3.adm
new file mode 100644
index 0000000..466b846
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/leftouterjoin/loj-03-no-listify/loj-03-no-listify.3.adm
@@ -0,0 +1,2 @@
+{ "cnt_all": 6, "cnt_x": 2, "cnt_y": 2, "cnt_z": 2, "taskId": 1 }
+{ "cnt_all": 6, "cnt_x": 2, "cnt_y": 2, "cnt_z": 2, "taskId": 2 }
\ No newline at end of file
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 032097a..ff37ac5 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -11847,6 +11847,11 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="leftouterjoin">
+      <compilation-unit name="loj-03-no-listify">
+        <output-dir compare="Text">loj-03-no-listify</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="leftouterjoin">
       <compilation-unit name="query_issue658">
         <output-dir compare="Text">query_issue658</output-dir>
       </compilation-unit>
diff --git 
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/MoveFreeVariableOperatorOutOfSubplanRule.java
 
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/MoveFreeVariableOperatorOutOfSubplanRule.java
index 94cae74..66ee3a4 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/MoveFreeVariableOperatorOutOfSubplanRule.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/MoveFreeVariableOperatorOutOfSubplanRule.java
@@ -92,8 +92,7 @@ public class MoveFreeVariableOperatorOutOfSubplanRule extends 
AbstractDecorrelat
                     ILogicalOperator childOp = childOpRef.getValue();
 
                     // Try to move operators that only uses free variables out 
of the subplan.
-                    if (movableOperator(currentOp.getOperatorTag())
-                            && independentOperator(currentOp, 
liveVarsBeforeSubplan)
+                    if (movableOperator(currentOp, liveVarsBeforeSubplan)
                             && producedVariablesCanbePropagated(currentOp)) {
                         extractOperator(subplanOp, inputOp, currentOpRef);
                         inputOp = currentOp;
@@ -109,12 +108,17 @@ public class MoveFreeVariableOperatorOutOfSubplanRule 
extends AbstractDecorrelat
         return changed;
     }
 
-    // Checks whether the current operator is independent of the nested input 
pipeline in the subplan.
-    private boolean independentOperator(ILogicalOperator op, 
Set<LogicalVariable> liveVarsBeforeSubplan)
+    private boolean movableOperator(ILogicalOperator op, Set<LogicalVariable> 
liveVarsBeforeSubplan)
             throws AlgebricksException {
+        if (!movableOperatorKind(op.getOperatorTag())) {
+            return false;
+        }
+
+        // Checks whether the current operator is independent of the nested 
input pipeline in the subplan.
         Set<LogicalVariable> usedVars = new HashSet<>();
         VariableUtilities.getUsedVariables(op, usedVars);
-        return liveVarsBeforeSubplan.containsAll(usedVars);
+        boolean independent = liveVarsBeforeSubplan.containsAll(usedVars);
+        return independent && movableIndependentOperator(op, usedVars);
     }
 
     // Checks whether there is a variable killing operator in the nested 
pipeline
@@ -152,7 +156,11 @@ public class MoveFreeVariableOperatorOutOfSubplanRule 
extends AbstractDecorrelat
         currentOp.getInputs().get(0).setValue(inputOp);
     }
 
-    protected boolean movableOperator(LogicalOperatorTag operatorTag) {
-        return (operatorTag == LogicalOperatorTag.ASSIGN || operatorTag == 
LogicalOperatorTag.SUBPLAN);
+    protected boolean movableOperatorKind(LogicalOperatorTag operatorTag) {
+        return operatorTag == LogicalOperatorTag.ASSIGN || operatorTag == 
LogicalOperatorTag.SUBPLAN;
+    }
+
+    protected boolean movableIndependentOperator(ILogicalOperator op, 
Set<LogicalVariable> usedVars) {
+        return true;
     }
 }
diff --git 
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/PushSubplanIntoGroupByRule.java
 
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/PushSubplanIntoGroupByRule.java
index 6d5d67d..420bf12 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/PushSubplanIntoGroupByRule.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/subplan/PushSubplanIntoGroupByRule.java
@@ -70,29 +70,30 @@ public class PushSubplanIntoGroupByRule implements 
IAlgebraicRewriteRule {
             rootRef = opRef;
             invoked = true;
         }
-        return rewriteForOperator(rootRef, opRef, context);
+        return rewriteForOperator(rootRef, opRef.getValue(), context);
     }
 
     // The core rewriting function for an operator.
-    private boolean rewriteForOperator(Mutable<ILogicalOperator> rootRef, 
Mutable<ILogicalOperator> opRef,
+    private boolean rewriteForOperator(Mutable<ILogicalOperator> rootRef, 
ILogicalOperator parentOperator,
             IOptimizationContext context) throws AlgebricksException {
         boolean changed = false;
-        ILogicalOperator parentOperator = opRef.getValue();
-        for (Mutable<ILogicalOperator> ref : parentOperator.getInputs()) {
+        List<Mutable<ILogicalOperator>> parentInputs = 
parentOperator.getInputs();
+        for (int i = 0, n = parentInputs.size(); i < n; i++) {
+            Mutable<ILogicalOperator> ref = parentInputs.get(i);
             ILogicalOperator op = ref.getValue();
             // Only processes subplan operator.
-            Deque<SubplanOperator> subplans = new ArrayDeque<>();
             if (op.getOperatorTag() != LogicalOperatorTag.SUBPLAN) {
                 // Recursively rewrites the child plan.
-                changed |= rewriteForOperator(rootRef, ref, context);
+                changed |= rewriteForOperator(rootRef, op, context);
                 continue;
             }
+            Deque<SubplanOperator> subplans = new ArrayDeque<>();
             while (op.getOperatorTag() == LogicalOperatorTag.SUBPLAN) {
                 SubplanOperator currentSubplan = (SubplanOperator) op;
                 // Recursively rewrites the pipelines inside a nested subplan.
                 for (ILogicalPlan subplan : currentSubplan.getNestedPlans()) {
                     for (Mutable<ILogicalOperator> nestedRootRef : 
subplan.getRoots()) {
-                        changed |= rewriteForOperator(nestedRootRef, 
nestedRootRef, context);
+                        changed |= rewriteForOperator(nestedRootRef, 
nestedRootRef.getValue(), context);
                     }
                 }
                 subplans.addFirst(currentSubplan);
@@ -106,17 +107,17 @@ public class PushSubplanIntoGroupByRule implements 
IAlgebraicRewriteRule {
             // Recursively rewrites the pipelines inside a nested subplan.
             for (ILogicalPlan subplan : gby.getNestedPlans()) {
                 for (Mutable<ILogicalOperator> nestedRootRef : 
subplan.getRoots()) {
-                    changed |= rewriteForOperator(nestedRootRef, 
nestedRootRef, context);
+                    changed |= rewriteForOperator(nestedRootRef, 
nestedRootRef.getValue(), context);
                 }
             }
-            changed |= pushSubplansIntoGroupBy(rootRef, parentOperator, 
subplans, gby, context);
+            changed |= pushSubplansIntoGroupBy(rootRef, parentOperator, i, 
subplans, gby, context);
         }
         return changed;
     }
 
     // Pushes subplans into the group by operator.
     private boolean pushSubplansIntoGroupBy(Mutable<ILogicalOperator> 
currentRootRef, ILogicalOperator parentOperator,
-            Deque<SubplanOperator> subplans, GroupByOperator gby, 
IOptimizationContext context)
+            int parentChildIdx, Deque<SubplanOperator> subplans, 
GroupByOperator gby, IOptimizationContext context)
             throws AlgebricksException {
         boolean changed = false;
         List<ILogicalPlan> newGbyNestedPlans = new ArrayList<>();
@@ -226,8 +227,16 @@ public class PushSubplanIntoGroupByRule implements 
IAlgebraicRewriteRule {
         gby.getNestedPlans().addAll(newGbyNestedPlans);
 
         // Connects the group-by operator with its parent operator.
-        ILogicalOperator parent = !subplans.isEmpty() ? subplans.getFirst() : 
parentOperator;
-        parent.getInputs().get(0).setValue(gby);
+        ILogicalOperator parent;
+        int childIdx;
+        if (!subplans.isEmpty()) {
+            parent = subplans.getFirst();
+            childIdx = 0;
+        } else {
+            parent = parentOperator;
+            childIdx = parentChildIdx;
+        }
+        parent.getInputs().get(childIdx).setValue(gby);
 
         // Removes unnecessary pipelines inside the group by operator.
         changed |= cleanup(currentRootRef.getValue(), gby);

Reply via email to