Updated the policy to have a boolean function for entering nested plans.
diff --git a/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/InlineVariablePolicy.java b/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/InlineVariablePolicy.java
index efcc7a8..e476c97 100644
--- a/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/InlineVariablePolicy.java
+++ b/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/InlineVariablePolicy.java
@@ -14,13 +14,7 @@
  */
 package edu.uci.ics.hyracks.algebricks.rewriter.rules;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang3.mutable.Mutable;
-
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
 import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
 
@@ -31,6 +25,11 @@
 public class InlineVariablePolicy implements InlineVariablesRule.IInlineVariablePolicy {
 
     @Override
+    public boolean enterNestedPlans() {
+        return false;
+    }
+
+    @Override
     public boolean isCandidateForInlining(ILogicalExpression expr) {
         if (expr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
             return true;
@@ -39,16 +38,6 @@
     }
 
     @Override
-    public List<Mutable<ILogicalOperator>> descendIntoNextOperator(AbstractLogicalOperator op) {
-        List<Mutable<ILogicalOperator>> descendOp = new ArrayList<Mutable<ILogicalOperator>>();
-        // Descend into children removing projects on the way.
-        for (Mutable<ILogicalOperator> inputOpRef : op.getInputs()) {
-            descendOp.add(inputOpRef);
-        }
-        return descendOp;
-    }
-
-    @Override
     public boolean isCanidateInlineTarget(AbstractLogicalOperator op) {
         // Only inline variables in operators that can deal with arbitrary expressions.
         if (!op.requiresVariableReferenceExpressions()) {
diff --git a/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/InlineVariablesRule.java b/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/InlineVariablesRule.java
index 9e1a0e6..2c154ef 100644
--- a/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/InlineVariablesRule.java
+++ b/algebricks/algebricks-rewriter/src/main/java/edu/uci/ics/hyracks/algebricks/rewriter/rules/InlineVariablesRule.java
@@ -26,6 +26,7 @@
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalPlan;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
@@ -33,6 +34,7 @@
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
+import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
 import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
 import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 import edu.uci.ics.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionReferenceTransform;
@@ -44,24 +46,26 @@
  * Inlining variables may enable other optimizations by allowing selects and assigns to be moved
  * (e.g., a select may be pushed into a join to enable an efficient physical join operator).
  * 
+ * <pre>
  * Preconditions/Assumptions:
  * Assumes no projects are in the plan. Only inlines variables whose assigned expression is a function call
  * (i.e., this rule ignores right-hand side constants and other variable references expressions
  * 
  * Postconditions/Examples:
  * All qualifying variables have been inlined.
- *
+ * 
  * Example (simplified):
- *
+ * 
  * Before plan:
  * select <- [$$1 < $$2 + $$0]
  *   assign [$$2] <- [funcZ() + $$0]
  *     assign [$$0, $$1] <- [funcX(), funcY()]
- *
+ * 
  * After plan:
  * select <- [funcY() < funcZ() + funcX() + funcX()]
  *   assign [$$2] <- [funcZ() + funcX()]
  *     assign [$$0, $$1] <- [funcX(), funcY()]
+ * </pre>
  */
 public class InlineVariablesRule implements IAlgebraicRewriteRule {
 
@@ -140,9 +144,21 @@
             }
         }
 
+        // Descend into children removing projects on the way.  
         boolean modified = false;
-        // Follow all operators from this operator.
-        for (Mutable<ILogicalOperator> inputOpRef : policy.descendIntoNextOperator(op)) {
+        for (Mutable<ILogicalOperator> inputOpRef : op.getInputs()) {
+            // Descend into nested plans.
+            if (op.hasNestedPlans() && policy.enterNestedPlans()) {
+                AbstractOperatorWithNestedPlans o2 = (AbstractOperatorWithNestedPlans) op;
+                for (ILogicalPlan p : o2.getNestedPlans()) {
+                    for (Mutable<ILogicalOperator> rootOpRef : p.getRoots()) {
+                        if (inlineVariables(rootOpRef, context)) {
+                            modified = true;
+                        }
+                    }
+                }
+            }
+            // Children
             if (inlineVariables(inputOpRef, context)) {
                 modified = true;
             }
@@ -244,9 +260,9 @@
 
     public static interface IInlineVariablePolicy {
 
-        public boolean isCandidateForInlining(ILogicalExpression expr);
+        public boolean enterNestedPlans();
 
-        public List<Mutable<ILogicalOperator>> descendIntoNextOperator(AbstractLogicalOperator op);
+        public boolean isCandidateForInlining(ILogicalExpression expr);
 
         public boolean isCanidateInlineTarget(AbstractLogicalOperator op);