>From Ali Alsuliman <[email protected]>:

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


Change subject: push assign to join branch
......................................................................

push assign to join branch

Change-Id: I74452d71423610ca2a34631235f5da8325e3b625
---
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java
2 files changed, 80 insertions(+), 39 deletions(-)



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

diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
index abc434f..e4bcbd8 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
@@ -21,6 +21,8 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;

 import org.apache.asterix.algebra.base.OperatorAnnotation;
 import org.apache.asterix.om.base.AInt32;
@@ -45,6 +47,7 @@
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
 import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
+import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 import org.apache.hyracks.api.exceptions.SourceLocation;

@@ -85,20 +88,54 @@
         if (fce.getFunctionIdentifier() != 
BuiltinFunctions.FIELD_ACCESS_BY_NAME) {
             return changed;
         }
-        changed |= extractFirstArg(fce, op, context);
-        IVariableTypeEnvironment env = 
context.getOutputTypeEnvironment(op.getInputs().get(0).getValue());
-        IAType t = (IAType) env.getType(fce.getArguments().get(0).getValue());
-        changed |= rewriteFieldAccess(exprRef, fce, 
TypeComputeUtils.getActualType(t));
+        int k = extractFirstArg(fce, op, context);
+        changed |= k >= 0;
+        if (k < 0) {
+            if (op.getInputs().size() > 1) {
+                context.computeAndSetTypeEnvironmentForOperator(op);
+                changed |= rewriteFieldAccessUsing(op, exprRef, context, fce);
+                return changed;
+            }
+            k = 0;
+        }
+        changed |= rewriteFieldAccessUsing(op.getInputs().get(k).getValue(), 
exprRef, context, fce);
         return changed;
     }

-    // Extracts the first argument of a field-access expression into an 
separate assign operator.
-    private boolean extractFirstArg(AbstractFunctionCallExpression fce, 
ILogicalOperator op,
+    // Extracts the first argument of a field-access expression into a 
separate assign operator.
+    private static int extractFirstArg(AbstractFunctionCallExpression fce, 
ILogicalOperator op,
             IOptimizationContext context) throws AlgebricksException {
         ILogicalExpression firstArg = fce.getArguments().get(0).getValue();
         if (firstArg.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) 
{
-            return false;
+            return -1;
         }
+        if (op.getInputs().size() > 1) {
+            return extractToBranch(fce, op, context, firstArg);
+        }
+        extractToAssignOp(fce, op.getInputs().get(0), context, firstArg);
+        return 0;
+    }
+
+    private static int extractToBranch(AbstractFunctionCallExpression fce, 
ILogicalOperator op,
+            IOptimizationContext ctx, ILogicalExpression firstArg) throws 
AlgebricksException {
+        Set<LogicalVariable> usedByExpr = new HashSet<>();
+        Set<LogicalVariable> inputLiveVars = new HashSet<>();
+        fce.getUsedVariables(usedByExpr);
+        int i = 0;
+        for (Mutable<ILogicalOperator> input : op.getInputs()) {
+            inputLiveVars.clear();
+            VariableUtilities.getLiveVariables(input.getValue(), 
inputLiveVars);
+            if (inputLiveVars.containsAll(usedByExpr)) {
+                extractToAssignOp(fce, input, ctx, firstArg);
+                return i;
+            }
+            i++;
+        }
+        return -1;
+    }
+
+    private static void extractToAssignOp(AbstractFunctionCallExpression fce, 
Mutable<ILogicalOperator> op,
+            IOptimizationContext context, ILogicalExpression firstArg) throws 
AlgebricksException {
         SourceLocation sourceLoc = firstArg.getSourceLocation();
         LogicalVariable var1 = context.newVar();
         AssignOperator assignOp = new AssignOperator(new 
ArrayList<>(Collections.singletonList(var1)),
@@ -107,14 +144,20 @@
         VariableReferenceExpression var1Ref = new 
VariableReferenceExpression(var1);
         var1Ref.setSourceLocation(sourceLoc);
         fce.getArguments().get(0).setValue(var1Ref);
-        assignOp.getInputs().add(new 
MutableObject<>(op.getInputs().get(0).getValue()));
-        op.getInputs().get(0).setValue(assignOp);
+        assignOp.getInputs().add(new MutableObject<>(op.getValue()));
+        op.setValue(assignOp);
         context.computeAndSetTypeEnvironmentForOperator(assignOp);
-        return true;
+    }
+
+    private static boolean rewriteFieldAccessUsing(ILogicalOperator op, 
Mutable<ILogicalExpression> exprRef,
+            IOptimizationContext ctx, AbstractFunctionCallExpression fce) 
throws AlgebricksException {
+        IVariableTypeEnvironment env = ctx.getOutputTypeEnvironment(op);
+        IAType t = (IAType) env.getType(fce.getArguments().get(0).getValue());
+        return rewriteFieldAccess(exprRef, fce, 
TypeComputeUtils.getActualType(t));
     }

     // Rewrites field-access-by-name into field-access-by-index if possible.
-    private boolean rewriteFieldAccess(Mutable<ILogicalExpression> exprRef, 
AbstractFunctionCallExpression fce,
+    private static boolean rewriteFieldAccess(Mutable<ILogicalExpression> 
exprRef, AbstractFunctionCallExpression fce,
             IAType t) {
         if (t.getTypeTag() != ATypeTag.OBJECT) {
             return false;
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java
index 42cce52..b361ee1 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java
@@ -21,12 +21,10 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;

 import org.apache.asterix.algebra.base.OperatorAnnotation;
-import org.apache.asterix.common.exceptions.CompilationException;
-import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.lang.common.util.FunctionUtil;
 import org.apache.asterix.om.base.AInt32;
 import org.apache.asterix.om.base.AString;
@@ -96,8 +94,7 @@
             context.addToDontApplySet(this, op1);
         }
         if (res && op1.getOperatorTag() == LogicalOperatorTag.SELECT) {
-            // checking if we can annotate a Selection as using just one field
-            // access
+            // checking if we can annotate a Selection as using just one field 
access
             SelectOperator sigma = (SelectOperator) op1;
             List<LogicalVariable> vars = new ArrayList<>();
             VariableUtilities.getUsedVariables(sigma, vars);
@@ -107,8 +104,7 @@
                 ILogicalExpression expr1 = getFirstExpr(assign1);
                 if (FunctionUtil.isFieldAccessFunction(expr1)) {
                     AbstractFunctionCallExpression f = 
(AbstractFunctionCallExpression) expr1;
-                    // f should be a call to a field/data access kind of
-                    // function
+                    // f should be a call to a field/data access kind of 
function
                     
sigma.getAnnotations().put(OperatorAnnotation.FIELD_ACCESS, 
f.getArguments().get(0));
                 }
             }
@@ -144,7 +140,9 @@
                     LogicalVariable v = context.newVar();
                     AssignOperator a2 = new AssignOperator(v, new 
MutableObject<>(f));
                     a2.setSourceLocation(expr.getSourceLocation());
-                    pushFieldAssign(a2, topOp, context);
+                    if (!pushFieldAssign(a2, topOp, context)) {
+                        return false;
+                    }
                     context.computeAndSetTypeEnvironmentForOperator(a2);
                     ILogicalExpression arg = 
f.getArguments().get(0).getValue();
                     if (arg.getExpressionTag() == 
LogicalExpressionTag.VARIABLE) {
@@ -183,59 +181,59 @@
         }
     }

-    private static void pushFieldAssign(AssignOperator a2, 
AbstractLogicalOperator topOp, IOptimizationContext context)
-            throws AlgebricksException {
+    private static boolean pushFieldAssign(AssignOperator a2, 
AbstractLogicalOperator topOp,
+            IOptimizationContext context) throws AlgebricksException {
         if (topOp.getInputs().size() == 1 && !topOp.hasNestedPlans()) {
             Mutable<ILogicalOperator> topChild = topOp.getInputs().get(0);
-            // plugAccessAboveOp(a2, topChild, context);
             List<Mutable<ILogicalOperator>> a2InptList = a2.getInputs();
-            a2InptList.clear();
             a2InptList.add(topChild);
             // and link it as child in the op. tree
             topOp.getInputs().set(0, new MutableObject<>(a2));
             findAndEliminateRedundantFieldAccess(a2, context);
+            return true;
         } else { // e.g., a join
-            LinkedList<LogicalVariable> usedInAccess = new 
LinkedList<LogicalVariable>();
+            Set<LogicalVariable> usedInAccess = new HashSet<>();
             VariableUtilities.getUsedVariables(a2, usedInAccess);

-            LinkedList<LogicalVariable> produced2 = new 
LinkedList<LogicalVariable>();
+            Set<LogicalVariable> produced2 = new HashSet<>();
             VariableUtilities.getProducedVariables(topOp, produced2);

             if (OperatorPropertiesUtil.disjoint(produced2, usedInAccess)) {
+                Set<LogicalVariable> inputLiveVars = new HashSet<>();
                 for (Mutable<ILogicalOperator> inp : topOp.getInputs()) {
-                    HashSet<LogicalVariable> v2 = new 
HashSet<LogicalVariable>();
-                    VariableUtilities.getLiveVariables(inp.getValue(), v2);
-                    if (!OperatorPropertiesUtil.disjoint(usedInAccess, v2)) {
-                        pushAccessAboveOpRef(a2, inp, context);
-                        return;
+                    inputLiveVars.clear();
+                    VariableUtilities.getLiveVariables(inp.getValue(), 
inputLiveVars);
+                    // push the assign to the correct branch that contains all 
the used vars
+                    if (inputLiveVars.containsAll(usedInAccess)) {
+                        pushAccessThroughOp(a2, inp, context);
+                        return true;
                     }
                 }
                 if (topOp.hasNestedPlans()) {
                     AbstractOperatorWithNestedPlans nestedOp = 
(AbstractOperatorWithNestedPlans) topOp;
                     for (ILogicalPlan plan : nestedOp.getNestedPlans()) {
                         for (Mutable<ILogicalOperator> root : plan.getRoots()) 
{
-                            HashSet<LogicalVariable> v2 = new 
HashSet<LogicalVariable>();
-                            
VariableUtilities.getLiveVariables(root.getValue(), v2);
-                            if (!OperatorPropertiesUtil.disjoint(usedInAccess, 
v2)) {
-                                pushAccessAboveOpRef(a2, root, context);
-                                return;
+                            inputLiveVars.clear();
+                            
VariableUtilities.getLiveVariables(root.getValue(), inputLiveVars);
+                            if (inputLiveVars.containsAll(usedInAccess)) {
+                                pushAccessThroughOp(a2, root, context);
+                                return true;
                             }
                         }
                     }
                 }
-                throw new CompilationException(ErrorCode.COMPILATION_ERROR, 
a2.getSourceLocation(),
-                        "Field access " + getFirstExpr(a2) + " does not 
correspond to any input");
             }
         }
+        return false;
     }

     /**
-     * Pushes one field-access assignment above toPushThroughChildRef
+     * Pushes one field-access assignment through toPushThroughChildRef
      *
      * @param toPush
      * @param toPushThroughChildRef
      */
-    private static void pushAccessAboveOpRef(AssignOperator toPush, 
Mutable<ILogicalOperator> toPushThroughChildRef,
+    private static void pushAccessThroughOp(AssignOperator toPush, 
Mutable<ILogicalOperator> toPushThroughChildRef,
             IOptimizationContext context) throws AlgebricksException {
         List<Mutable<ILogicalOperator>> tpInpList = toPush.getInputs();
         tpInpList.clear();

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20767?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: neo
Gerrit-Change-Id: I74452d71423610ca2a34631235f5da8325e3b625
Gerrit-Change-Number: 20767
Gerrit-PatchSet: 1
Gerrit-Owner: Ali Alsuliman <[email protected]>

Reply via email to