>From <[email protected]>:

[email protected] has uploaded this change for review. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18788 )


Change subject: [ASTERIXDB-3496][COMP] Move Array related Unnest Operator 
higher up in the tree.
......................................................................

[ASTERIXDB-3496][COMP] Move Array related Unnest Operator higher up in the tree.

Change-Id: Ief11655b5131e8fe472f2743289da49c53b86fae
---
A 
asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
M 
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
4 files changed, 194 insertions(+), 8 deletions(-)



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

diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
index 4a97acb..17488c9 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
@@ -20,6 +20,7 @@
 package org.apache.asterix.optimizer.rules.cbo;

 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -57,6 +58,7 @@
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
+import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
 import 
org.apache.hyracks.algebricks.core.algebra.prettyprint.IPlanPrettyPrinter;
@@ -92,6 +94,13 @@

     // The OrderBy operator at root of the query tree (if exists)
     private ILogicalOperator rootOrderByOp;
+    //first is Operator whose input has to be changed
+    // second input number that has to be changed
+    // third Assign Operator at the top
+    // fourth Unnest operator at the bottom
+    private List<Quadruple<ILogicalOperator, Integer, ILogicalOperator, 
ILogicalOperator>> parentAssignUnnestOps =
+            new ArrayList<>(); // assign on top of Unnest. Save the parent of 
the assign op
+    private ILogicalOperator returnOp;

     private List<LogicalVariable> resultAndJoinVars = new ArrayList();

@@ -245,14 +254,19 @@
             printPlan(pp, (AbstractLogicalOperator) newJoinOps.get(0), "New 
Whole Plan after buildNewTree 2");
             printPlan(pp, (AbstractLogicalOperator) root, "New Whole Plan 
after buildNewTree");

+            opRef.setValue(root);
+            context.computeAndSetTypeEnvironmentForOperator(root);
+            String viewOutPlan2 = new ALogicalPlanImpl(opRef).toString(); 
//useful when debugging
+            root = moveUnnestOps(root);
+
             // this will be the new root
             opRef.setValue(root);
-
-            if (LOGGER.isTraceEnabled()) {
-                String viewOutPlan = new ALogicalPlanImpl(opRef).toString(); 
//useful when debugging
-                LOGGER.trace("viewOutPlan");
-                LOGGER.trace(viewOutPlan);
-            }
+            context.computeAndSetTypeEnvironmentForOperator(root);
+            //if (LOGGER.isTraceEnabled()) {
+            String viewOutPlan = new ALogicalPlanImpl(opRef).toString(); 
//useful when debugging
+            LOGGER.trace("viewOutPlan");
+            LOGGER.trace(viewOutPlan);
+            //}

             if (LOGGER.isTraceEnabled()) {
                 LOGGER.trace("---------------------------- Printing Leaf 
Inputs");
@@ -271,10 +285,111 @@
         } else {
             buildNewTree(cheapestPlanNode);
         }
-        context.computeAndSetTypeEnvironmentForOperator(op);
+        //context.computeAndSetTypeEnvironmentForOperator(op);
         return true;
     }

+    private ILogicalOperator moveUnnestOps(ILogicalOperator root) throws 
AlgebricksException {
+        findUnnestOps(root);
+        //removeUnnestOps();
+
+        for (int i = 0; i < parentAssignUnnestOps.size(); i++) {
+            ILogicalOperator lOp = parentAssignUnnestOps.get(i).getFirst();
+            int inputNo = parentAssignUnnestOps.get(i).getSecond();
+            AssignOperator aOp = (AssignOperator) 
parentAssignUnnestOps.get(i).getThird();
+            if (aOp.getVariables().size() == 1) { // handle only this case for 
now.
+                LogicalVariable var = aOp.getVariables().get(0);
+                returnOp = null;
+                findOperatorWithThisVar(var, newJoinOps.get(0));
+                if (returnOp == null) {
+                    // Now remove this UnnestOp from its original place
+                    removeUnnestOp2(i);
+                    
parentAssignUnnestOps.get(i).getFourth().getInputs().get(0).setValue(root);
+                    root = aOp;
+                }
+                /*else {
+                    ILogicalOperator saveInput = 
op.getInputs().get(inputNo).getValue(); // but do we know if this is the right 
input??
+                    
op.getInputs().get(0).getValue().getInputs().get(inputNo).setValue(aOp);
+                    
parentAssignUnnestOps.get(i).getFourth().getInputs().get(0).setValue(saveInput);
+                }*/
+            }
+        }
+        return root;
+    }
+
+    private void findOperatorWithThisVar(LogicalVariable var, ILogicalOperator 
op) throws AlgebricksException {
+        if (op.getOperatorTag().equals(LogicalOperatorTag.EMPTYTUPLESOURCE)) {
+            return;
+        }
+        Collection<LogicalVariable> vars = new ArrayList<>();
+        //skip the original
+        VariableUtilities.getUsedVariables(op, vars);
+        if (vars.contains(var)) {
+            returnOp = op;
+            return;
+        }
+        for (int i = 0; i < op.getInputs().size(); i++) {
+            findOperatorWithThisVar(var, op.getInputs().get(i).getValue());
+        }
+    }
+
+    private void removeUnnestOp(int n) {
+        for (int i = n; i <= n; i++) {
+            ILogicalOperator lOp = parentAssignUnnestOps.get(i).getFirst();
+            int inputNo = parentAssignUnnestOps.get(i).getSecond();
+            AssignOperator aOp = (AssignOperator) 
(lOp.getInputs().get(inputNo).getValue());
+            ILogicalOperator unnestOp = aOp.getInputs().get(0).getValue();
+            
lOp.getInputs().get(inputNo).setValue(unnestOp.getInputs().get(0).getValue());
+            // This bypasses the AssignOp and the UnnestOp. We will hopefully 
find a better place for this AssignUnnest Pair.
+        }
+    }
+
+    private void removeUnnestOp2(int i) {
+
+        ILogicalOperator lOp = parentAssignUnnestOps.get(i).getFirst();
+        int inputNo = parentAssignUnnestOps.get(i).getSecond();
+        AssignOperator aOp = (AssignOperator) 
parentAssignUnnestOps.get(i).getThird();
+        UnnestOperator unnestOp = (UnnestOperator) 
parentAssignUnnestOps.get(i).getFourth();
+        
lOp.getInputs().get(inputNo).setValue(unnestOp.getInputs().get(0).getValue());
+
+    }
+
+    private void removeUnnestOps() {
+        for (int i = 0; i < parentAssignUnnestOps.size(); i++) {
+            ILogicalOperator lOp = parentAssignUnnestOps.get(i).getFirst();
+            int inputNo = parentAssignUnnestOps.get(i).getSecond();
+            AssignOperator aOp = (AssignOperator) 
(lOp.getInputs().get(inputNo).getValue());
+            ILogicalOperator unnestOp = aOp.getInputs().get(0).getValue();
+            
lOp.getInputs().get(inputNo).setValue(unnestOp.getInputs().get(0).getValue());
+            // This bypasses the AssignOp and the UnnestOp. We will hopefully 
find a better place for this AssignUnnest Pair.
+        }
+    }
+
+    private void findUnnestOps(ILogicalOperator op) {
+        for (int i = 0; i < op.getInputs().size(); i++) {
+            ILogicalOperator p = op.getInputs().get(i).getValue();
+            if (p.getOperatorTag() == LogicalOperatorTag.EMPTYTUPLESOURCE) {
+                return;
+            }
+            if (p.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
+                // Tackling only one ASSIGN and UNNEST FOR NOW
+                if (p.getInputs().get(0).getValue().getOperatorTag() == 
LogicalOperatorTag.ASSIGN) {
+                    return;
+                }
+                if (p.getInputs().get(0).getValue().getOperatorTag() == 
LogicalOperatorTag.UNNEST) {
+                    UnnestOperator unnestOp = (UnnestOperator) 
p.getInputs().get(0).getValue();
+                    ILogicalExpression foo = 
unnestOp.getExpressionRef().getValue();
+                    LogicalExpressionTag tag = foo.getExpressionTag();
+                    //Expression expr = (Expression) 
unnestOp.getExpressionRef();
+                    if (unnestOp.getArray()) {
+                        parentAssignUnnestOps.add(new Quadruple(op, i, p, 
p.getInputs().get(0).getValue()));
+                    }
+                }
+            }
+            findUnnestOps(p);
+        }
+    }
+
     private void collectJoinConditionsVariables() {
         for (JoinOperator jOp : allJoinOps) {
             AbstractBinaryJoinOperator joinOp = jOp.getAbstractJoinOp();
@@ -1042,4 +1157,4 @@
         }
         return true;
     }
-}
\ No newline at end of file
+}
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 302d4e0..0d58589 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
@@ -330,6 +330,9 @@
         } else {
             unnestOp = new UnnestOperator(fromVar, new 
MutableObject<>(pUnnestExpr.first));
         }
+        if (fromExpr.getKind() == Kind.FIELD_ACCESSOR_EXPRESSION) {
+            unnestOp.setArray(true);
+        }
         ExternalSubpathAnnotation hint = ((AbstractExpression) 
fromExpr).findHint(ExternalSubpathAnnotation.class);
         if (hint != null) {
             unnestOp.getAnnotations().put(SUBPATH, hint.getSubPath());
diff --git 
a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
 
b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
new file mode 100644
index 0000000..5b622c2
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
@@ -0,0 +1,50 @@
+-- DISTRIBUTE_RESULT  |UNPARTITIONED|
+  -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
+    -- STREAM_LIMIT  |UNPARTITIONED|
+      -- STREAM_PROJECT  |PARTITIONED|
+        -- ASSIGN  |PARTITIONED|
+          -- STREAM_PROJECT  |PARTITIONED|
+            -- SORT_MERGE_EXCHANGE [$$193(DESC), $$o_entry_d(ASC) ]  
|PARTITIONED|
+              -- STREAM_LIMIT  |PARTITIONED|
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  -- STABLE_SORT [topK: 100] [$$193(DESC), $$o_entry_d(ASC)]  
|PARTITIONED|
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      -- STREAM_PROJECT  |PARTITIONED|
+                        -- STREAM_SELECT  |PARTITIONED|
+                          -- STREAM_PROJECT  |PARTITIONED|
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              -- SORT_GROUP_BY[$$199, $$200, $$201, $$202, 
$$203, $$204, $$205]  |PARTITIONED|
+                                      {
+                                        -- AGGREGATE  |LOCAL|
+                                          -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                      }
+                                -- HASH_PARTITION_EXCHANGE [$$199, $$200, 
$$201, $$202, $$203, $$204, $$205]  |PARTITIONED|
+                                  -- SORT_GROUP_BY[$$175, $$183, $$184, $$185, 
$$179, $$180, $$181]  |PARTITIONED|
+                                          {
+                                            -- AGGREGATE  |LOCAL|
+                                              -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                          }
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      -- STREAM_PROJECT  |PARTITIONED|
+                                        -- ASSIGN  |PARTITIONED|
+                                          -- STREAM_PROJECT  |PARTITIONED|
+                                            -- UNNEST  |PARTITIONED|
+                                              -- STREAM_PROJECT  |PARTITIONED|
+                                                -- ONE_TO_ONE_EXCHANGE  
|PARTITIONED|
+                                                  -- HYBRID_HASH_JOIN [$$188, 
$$183, $$184][$$185, $$189, $$190]  |PARTITIONED|
+                                                    -- HASH_PARTITION_EXCHANGE 
[$$188, $$183, $$184]  |PARTITIONED|
+                                                      -- STREAM_PROJECT  
|PARTITIONED|
+                                                        -- ASSIGN  
|PARTITIONED|
+                                                          -- STREAM_PROJECT  
|PARTITIONED|
+                                                            -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                              -- 
DATASOURCE_SCAN (test.orders)  |PARTITIONED|
+                                                                -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                  -- 
EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                    -- HASH_PARTITION_EXCHANGE 
[$$185, $$189, $$190]  |PARTITIONED|
+                                                      -- STREAM_PROJECT  
|PARTITIONED|
+                                                        -- ASSIGN  
|PARTITIONED|
+                                                          -- STREAM_PROJECT  
|PARTITIONED|
+                                                            -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                              -- 
DATASOURCE_SCAN (test.customer)  |PARTITIONED|
+                                                                -- 
ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                  -- 
EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
index face56e..d6252a8 100644
--- 
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
+++ 
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
@@ -28,6 +28,7 @@
 import 
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor;

 public class UnnestOperator extends AbstractUnnestNonMapOperator {
+    private boolean array = false;

     public UnnestOperator(LogicalVariable variable, 
Mutable<ILogicalExpression> expression) {
         super(variable, expression);
@@ -58,4 +59,12 @@
     public LogicalOperatorTag getOperatorTag() {
         return LogicalOperatorTag.UNNEST;
     }
+
+    public void setArray(boolean array) {
+        this.array = array;
+    }
+
+    public boolean getArray() {
+        return array;
+    }
 }

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

Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: Ief11655b5131e8fe472f2743289da49c53b86fae
Gerrit-Change-Number: 18788
Gerrit-PatchSet: 1
Gerrit-Owner: [email protected]
Gerrit-MessageType: newchange

Reply via email to