[NO ISSUE][COMP] Expand optimizer sanity tests
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Check that each optimization rule computes output type
environment for each operator it creates
- Also check that each physical optimization rule computes
output schema for each new operator it creates
Change-Id: I5ff9338524407e14a16640a08fc0abeb74a3ebdf
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/8023
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceMaterializationForInsertWithSelfScanRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceMaterializationForInsertWithSelfScanRule.java
index f4d8419..d838d71 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceMaterializationForInsertWithSelfScanRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceMaterializationForInsertWithSelfScanRule.java
@@ -70,10 +70,12 @@
materializeOperator.getInputs()
.add(new MutableObject<ILogicalOperator>(insertOp.getInputs().get(0).getValue()));
context.computeAndSetTypeEnvironmentForOperator(materializeOperator);
+ materializeOperator.recomputeSchema();
insertOp.getInputs().clear();
insertOp.getInputs().add(new MutableObject<ILogicalOperator>(materializeOperator));
context.computeAndSetTypeEnvironmentForOperator(insertOp);
+ insertOp.recomputeSchema();
return true;
} else {
return false;
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceRandomPartitioningFeedComputationRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceRandomPartitioningFeedComputationRule.java
index 4a75cb3..9195c5e 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceRandomPartitioningFeedComputationRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceRandomPartitioningFeedComputationRule.java
@@ -75,6 +75,7 @@
exchangeOp.setExecutionMode(em);
exchangeOp.computeDeliveredPhysicalProperties(context);
context.computeAndSetTypeEnvironmentForOperator(exchangeOp);
+ exchangeOp.recomputeSchema();
AssignOperator assignOp = (AssignOperator) opRef.getValue();
AssignPOperator assignPhyOp = (AssignPOperator) assignOp.getPhysicalOperator();
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetupCommitExtensionOpRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetupCommitExtensionOpRule.java
index cc50dce4..fbf086b 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetupCommitExtensionOpRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/SetupCommitExtensionOpRule.java
@@ -110,6 +110,7 @@
//update plan link
extensionOperator.getInputs().add(eOp.getInputs().get(0));
context.computeAndSetTypeEnvironmentForOperator(extensionOperator);
+ extensionOperator.recomputeSchema();
opRef.setValue(extensionOperator);
return true;
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/util/IntervalJoinUtils.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/util/IntervalJoinUtils.java
index d887914..fa5ef51 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/util/IntervalJoinUtils.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/util/IntervalJoinUtils.java
@@ -247,5 +247,6 @@
op.getInputs().set(branch, aoRef);
context.computeAndSetTypeEnvironmentForOperator(ao);
+ ao.recomputeSchema();
}
}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStructureVerifier.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStructureVerifier.java
index 1fad860..8495099 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStructureVerifier.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStructureVerifier.java
@@ -37,6 +37,7 @@
import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
import org.apache.hyracks.algebricks.core.algebra.prettyprint.IPlanPrettyPrinter;
+import org.apache.hyracks.algebricks.core.algebra.typing.ITypingContext;
import org.apache.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil;
import org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionReferenceTransform;
@@ -55,6 +56,10 @@
private static final String ERROR_MESSAGE_TEMPLATE_2 = "shared %s (%s) between %s and %s";
+ private static final String ERROR_MESSAGE_TEMPLATE_3 = "missing output type environment in %s";
+
+ private static final String ERROR_MESSAGE_TEMPLATE_4 = "missing schema in %s";
+
private final ExpressionReferenceVerifierVisitor exprVisitor = new ExpressionReferenceVerifierVisitor();
private final Map<Mutable<ILogicalOperator>, ILogicalOperator> opRefMap = new IdentityHashMap<>();
@@ -69,12 +74,23 @@
private final IPlanPrettyPrinter prettyPrinter;
- public PlanStructureVerifier(IPlanPrettyPrinter prettyPrinter) {
+ private final ITypingContext typeEnvProvider;
+
+ private boolean ensureTypeEnv;
+
+ private boolean ensureSchema;
+
+ public PlanStructureVerifier(IPlanPrettyPrinter prettyPrinter, ITypingContext typeEnvProvider) {
this.prettyPrinter = prettyPrinter;
+ this.typeEnvProvider = typeEnvProvider;
}
public void verifyPlanStructure(Mutable<ILogicalOperator> opRef) throws AlgebricksException {
reset();
+ ILogicalOperator op = opRef.getValue();
+ // if root has type-env/schema then ensure that all children have them too
+ ensureTypeEnv = typeEnvProvider.getOutputTypeEnvironment(op) != null;
+ ensureSchema = op.getSchema() != null;
walk(opRef);
reset();
}
@@ -84,6 +100,8 @@
opMap.clear();
exprRefMap.clear();
exprMap.clear();
+ ensureTypeEnv = false;
+ ensureSchema = false;
}
private void walk(Mutable<ILogicalOperator> opRef) throws AlgebricksException {
@@ -137,6 +155,15 @@
exprVisitor.setOperator(op);
op.acceptExpressionTransform(exprVisitor);
+ if (ensureTypeEnv && typeEnvProvider.getOutputTypeEnvironment(op) == null) {
+ throw new AlgebricksException(
+ String.format(ERROR_MESSAGE_TEMPLATE_3, PlanStabilityVerifier.printOperator(op, prettyPrinter)));
+ }
+ if (ensureSchema && op.getSchema() == null) {
+ throw new AlgebricksException(
+ String.format(ERROR_MESSAGE_TEMPLATE_4, PlanStabilityVerifier.printOperator(op, prettyPrinter)));
+ }
+
List<Mutable<ILogicalOperator>> children = op.getInputs();
if (op instanceof AbstractOperatorWithNestedPlans) {
children = new ArrayList<>(children);
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java
index ecb8390..d1fd247 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java
@@ -111,7 +111,7 @@
this.conflictingTypeResovler = conflictingTypeResovler;
this.warningCollector = warningCollector;
boolean isSanityCheckEnabled = physicalOptimizationConfig.isSanityCheckEnabled();
- this.planStructureVerifier = isSanityCheckEnabled ? new PlanStructureVerifier(prettyPrinter) : null;
+ this.planStructureVerifier = isSanityCheckEnabled ? new PlanStructureVerifier(prettyPrinter, this) : null;
this.planStabilityVerifier = isSanityCheckEnabled ? new PlanStabilityVerifier(prettyPrinter) : null;
}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/test/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStructureVerifierTest.java b/hyracks-fullstack/algebricks/algebricks-core/src/test/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStructureVerifierTest.java
index fa4061d..f047cec 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/test/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStructureVerifierTest.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/test/java/org/apache/hyracks/algebricks/core/algebra/plan/PlanStructureVerifierTest.java
@@ -19,20 +19,31 @@
package org.apache.hyracks.algebricks.core.algebra.plan;
+import java.util.HashMap;
+import java.util.Map;
+
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IMissableTypeComputer;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
+import org.apache.hyracks.algebricks.core.algebra.typing.ITypingContext;
import org.junit.Assert;
import org.junit.Test;
-public final class PlanStructureVerifierTest extends PlanVerifierTestBase {
+public final class PlanStructureVerifierTest extends PlanVerifierTestBase implements ITypingContext {
- final PlanStructureVerifier verifier = new PlanStructureVerifier(planPrinter);
+ final PlanStructureVerifier verifier = new PlanStructureVerifier(planPrinter, this);
@Test
public void testVerifySuccess() throws Exception {
@@ -242,4 +253,99 @@
Assert.assertTrue(e.getMessage(), e.getMessage().contains("cycle"));
}
}
+
+ @Test
+ public void testNoSchema() {
+ EmptyTupleSourceOperator ets = newETS();
+ ets.recomputeSchema();
+
+ AssignOperator op1 = newAssign(newVar(), newMutable(ConstantExpression.TRUE));
+ op1.getInputs().add(newMutable(ets));
+ op1.recomputeSchema();
+
+ op1.getInputs().clear();
+
+ AssignOperator op2 = newAssign(newVar(), newMutable(ConstantExpression.FALSE));
+ // no schema
+ op1.getInputs().add(newMutable(op2));
+
+ try {
+ verifier.verifyPlanStructure(newMutable(op1));
+ Assert.fail("Expected to catch " + AlgebricksException.class.getName());
+ } catch (AlgebricksException e) {
+ Assert.assertTrue(e.getMessage(), e.getMessage().contains("missing schema"));
+ }
+ }
+
+ @Test
+ public void testNoTypeEnvironment() throws Exception {
+ EmptyTupleSourceOperator ets = newETS();
+ computeAndSetTypeEnvironmentForOperator(ets);
+ ets.recomputeSchema();
+
+ SelectOperator op1 = new SelectOperator(newMutable(ConstantExpression.TRUE), false, null);
+ op1.getInputs().add(newMutable(ets));
+ computeAndSetTypeEnvironmentForOperator(op1);
+ op1.recomputeSchema();
+
+ op1.getInputs().clear();
+
+ SelectOperator op2 = new SelectOperator(newMutable(ConstantExpression.FALSE), false, null);
+ op2.getInputs().add(newMutable(ets));
+ op2.recomputeSchema();
+ // no type env
+
+ op1.getInputs().add(newMutable(op2));
+
+ try {
+ verifier.verifyPlanStructure(newMutable(op1));
+ Assert.fail("Expected to catch " + AlgebricksException.class.getName());
+ } catch (AlgebricksException e) {
+ Assert.assertTrue(e.getMessage(), e.getMessage().contains("missing output type environment"));
+ }
+ }
+
+ // ITypingContext
+
+ final Map<ILogicalOperator, IVariableTypeEnvironment> typeEnvMap = new HashMap<>();
+
+ @Override
+ public void computeAndSetTypeEnvironmentForOperator(ILogicalOperator op) throws AlgebricksException {
+ setOutputTypeEnvironment(op, op.computeOutputTypeEnvironment(this));
+ }
+
+ @Override
+ public void setOutputTypeEnvironment(ILogicalOperator op, IVariableTypeEnvironment env) {
+ typeEnvMap.put(op, env);
+ }
+
+ @Override
+ public IVariableTypeEnvironment getOutputTypeEnvironment(ILogicalOperator op) {
+ return typeEnvMap.get(op);
+ }
+
+ @Override
+ public void invalidateTypeEnvironmentForOperator(ILogicalOperator op) {
+ typeEnvMap.remove(op);
+ }
+
+ @Override
+ public IExpressionTypeComputer getExpressionTypeComputer() {
+ return null;
+ }
+
+ @Override
+ public IMissableTypeComputer getMissableTypeComputer() {
+ return null;
+ }
+
+ @Override
+ public IConflictingTypeResolver getConflictingTypeResolver() {
+ return null;
+ }
+
+ @Override
+ public IMetadataProvider<?, ?> getMetadataProvider() {
+ return null;
+ }
}
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractCommonOperatorsRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractCommonOperatorsRule.java
index 3effcc8..f9e6b13 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractCommonOperatorsRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractCommonOperatorsRule.java
@@ -185,9 +185,11 @@
Mutable<ILogicalOperator> beforeExchangeRef = new MutableObject<ILogicalOperator>(beforeExchange);
beforeExchange.getInputs().add(candidate);
context.computeAndSetTypeEnvironmentForOperator(beforeExchange);
+ beforeExchange.recomputeSchema();
rop.getInputs().add(beforeExchangeRef);
}
context.computeAndSetTypeEnvironmentForOperator(rop);
+ rop.recomputeSchema();
for (Mutable<ILogicalOperator> parentRef : originalCandidateParents) {
AbstractLogicalOperator parent = (AbstractLogicalOperator) parentRef.getValue();
@@ -203,11 +205,13 @@
exchange.getInputs().add(new MutableObject<>(rop));
rop.getOutputs().add(exchangeRef);
context.computeAndSetTypeEnvironmentForOperator(exchange);
+ exchange.recomputeSchema();
parent.getInputs().set(index, exchangeRef);
context.computeAndSetTypeEnvironmentForOperator(parent);
+ parent.recomputeSchema();
}
}
- List<LogicalVariable> liveVarsNew = new ArrayList<LogicalVariable>();
+ List<LogicalVariable> liveVarsNew = new ArrayList<>();
VariableUtilities.getLiveVariables(candidate.getValue(), liveVarsNew);
for (Mutable<ILogicalOperator> ref : group) {
if (ref.equals(candidate)) {
@@ -244,8 +248,11 @@
// set the types
context.computeAndSetTypeEnvironmentForOperator(exchOp);
+ exchOp.recomputeSchema();
context.computeAndSetTypeEnvironmentForOperator(assignOperator);
+ assignOperator.recomputeSchema();
context.computeAndSetTypeEnvironmentForOperator(projectOperator);
+ projectOperator.recomputeSchema();
List<Mutable<ILogicalOperator>> parentOpList = childrenToParents.get(ref);
for (Mutable<ILogicalOperator> parentOpRef : parentOpList) {
@@ -265,8 +272,10 @@
exchg.getInputs().add(new MutableObject<ILogicalOperator>(childOp));
parentOp.getInputs().set(index, new MutableObject<ILogicalOperator>(exchg));
context.computeAndSetTypeEnvironmentForOperator(exchg);
+ exchg.recomputeSchema();
}
context.computeAndSetTypeEnvironmentForOperator(parentOp);
+ parentOp.recomputeSchema();
}
}
cleanupPlan();
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/InsertProjectBeforeUnionRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/InsertProjectBeforeUnionRule.java
index c4ae57d..5745d9b 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/InsertProjectBeforeUnionRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/InsertProjectBeforeUnionRule.java
@@ -82,7 +82,9 @@
projectOp.setPhysicalOperator(new StreamProjectPOperator());
projectOp.setExecutionMode(inputOp.getExecutionMode());
context.computeAndSetTypeEnvironmentForOperator(projectOp);
+ projectOp.recomputeSchema();
context.computeAndSetTypeEnvironmentForOperator(inputOp);
+ inputOp.recomputeSchema();
}
private boolean isIdentical(List<LogicalVariable> finalSchema, List<LogicalVariable> inputSchema)
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/IntroduceProjectsRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/IntroduceProjectsRule.java
index af67be2..ca92331 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/IntroduceProjectsRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/IntroduceProjectsRule.java
@@ -165,6 +165,7 @@
projectOp.getInputs().add(new MutableObject<ILogicalOperator>(childOp));
op.getInputs().get(i).setValue(projectOp);
context.computeAndSetTypeEnvironmentForOperator(projectOp);
+ projectOp.recomputeSchema();
modified = true;
}
}
@@ -183,6 +184,7 @@
if (modified) {
context.computeAndSetTypeEnvironmentForOperator(op);
+ op.recomputeSchema();
}
return modified;
}
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/IsolateHyracksOperatorsRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/IsolateHyracksOperatorsRule.java
index 35b2dea..e13ec30 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/IsolateHyracksOperatorsRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/IsolateHyracksOperatorsRule.java
@@ -27,10 +27,8 @@
import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
import org.apache.hyracks.algebricks.core.algebra.base.PhysicalOperatorTag;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator.ExecutionMode;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.ExchangeOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.physical.OneToOneExchangePOperator;
-import org.apache.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil;
import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
public class IsolateHyracksOperatorsRule implements IAlgebraicRewriteRule {
@@ -124,20 +122,17 @@
return false;
}
- private final static void insertOneToOneExchange(Mutable<ILogicalOperator> i, IOptimizationContext context)
+ private static void insertOneToOneExchange(Mutable<ILogicalOperator> inOpRef, IOptimizationContext context)
throws AlgebricksException {
+ ILogicalOperator inOp = inOpRef.getValue();
+
ExchangeOperator e = new ExchangeOperator();
e.setPhysicalOperator(new OneToOneExchangePOperator());
- ILogicalOperator inOp = i.getValue();
-
- e.getInputs().add(new MutableObject<ILogicalOperator>(inOp));
- i.setValue(e);
- // e.recomputeSchema();
- OperatorPropertiesUtil.computeSchemaAndPropertiesRecIfNull(e, context);
- ExecutionMode em = ((AbstractLogicalOperator) inOp).getExecutionMode();
- e.setExecutionMode(em);
- e.computeDeliveredPhysicalProperties(context);
+ e.getInputs().add(new MutableObject<>(inOp));
+ e.setExecutionMode(inOp.getExecutionMode());
context.computeAndSetTypeEnvironmentForOperator(e);
- }
+ e.recomputeSchema();
+ inOpRef.setValue(e);
+ }
}
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushProjectDownRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushProjectDownRule.java
index 9457b60..c919195 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushProjectDownRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/PushProjectDownRule.java
@@ -68,7 +68,9 @@
Set<LogicalVariable> toPush = new LinkedHashSet<LogicalVariable>();
toPush.addAll(pi.getVariables());
- Pair<Boolean, Boolean> p = pushThroughOp(toPush, opRef2, op, context);
+ boolean recomputeSchema = op.getSchema() != null;
+
+ Pair<Boolean, Boolean> p = pushThroughOp(toPush, opRef2, op, context, recomputeSchema);
boolean smthWasPushed = p.first;
if (p.second) { // the original projection is redundant
opRef.setValue(op.getInputs().get(0).getValue());
@@ -79,7 +81,8 @@
}
private static Pair<Boolean, Boolean> pushThroughOp(Set<LogicalVariable> toPush, Mutable<ILogicalOperator> opRef2,
- ILogicalOperator initialOp, IOptimizationContext context) throws AlgebricksException {
+ ILogicalOperator initialOp, IOptimizationContext context, boolean recomputeSchema)
+ throws AlgebricksException {
List<LogicalVariable> initProjectList = new ArrayList<LogicalVariable>(toPush);
AbstractLogicalOperator op2 = (AbstractLogicalOperator) opRef2.getValue();
do {
@@ -135,6 +138,9 @@
gby.getDecorList().addAll(newDecorList);
if (gbyChanged) {
context.computeAndSetTypeEnvironmentForOperator(gby);
+ if (recomputeSchema) {
+ gby.recomputeSchema();
+ }
}
}
used2.clear();
@@ -149,7 +155,7 @@
boolean smthWasPushed = false;
for (Mutable<ILogicalOperator> c : op2.getInputs()) {
- if (pushNeededProjections(toPush, c, context, initialOp)) {
+ if (pushNeededProjections(toPush, c, context, initialOp, recomputeSchema)) {
smthWasPushed = true;
}
}
@@ -157,7 +163,7 @@
AbstractOperatorWithNestedPlans n = (AbstractOperatorWithNestedPlans) op2;
for (ILogicalPlan p : n.getNestedPlans()) {
for (Mutable<ILogicalOperator> r : p.getRoots()) {
- if (pushNeededProjections(toPush, r, context, initialOp)) {
+ if (pushNeededProjections(toPush, r, context, initialOp, recomputeSchema)) {
smthWasPushed = true;
}
}
@@ -168,7 +174,8 @@
// It does not try to push above another Projection.
private static boolean pushNeededProjections(Set<LogicalVariable> toPush, Mutable<ILogicalOperator> opRef,
- IOptimizationContext context, ILogicalOperator initialOp) throws AlgebricksException {
+ IOptimizationContext context, ILogicalOperator initialOp, boolean recomputeSchema)
+ throws AlgebricksException {
Set<LogicalVariable> allP = new LinkedHashSet<LogicalVariable>();
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
VariableUtilities.getSubplanLocalLiveVariables(op, allP);
@@ -183,19 +190,19 @@
// projection would be redundant, since we would project everything
// but we can try with the children
boolean push = false;
- if (pushThroughOp(toProject, opRef, initialOp, context).first) {
+ if (pushThroughOp(toProject, opRef, initialOp, context, recomputeSchema).first) {
push = true;
}
return push;
} else {
- return pushAllProjectionsOnTopOf(toProject, opRef, context, initialOp);
+ return pushAllProjectionsOnTopOf(toProject, opRef, context, initialOp, recomputeSchema);
}
}
// It does not try to push above another Projection.
private static boolean pushAllProjectionsOnTopOf(Collection<LogicalVariable> toPush,
- Mutable<ILogicalOperator> opRef, IOptimizationContext context, ILogicalOperator initialOp)
- throws AlgebricksException {
+ Mutable<ILogicalOperator> opRef, IOptimizationContext context, ILogicalOperator initialOp,
+ boolean recomputeSchema) throws AlgebricksException {
if (toPush.isEmpty()) {
return false;
}
@@ -215,6 +222,9 @@
opRef.setValue(pi2);
pi2.setExecutionMode(op.getExecutionMode());
context.computeAndSetTypeEnvironmentForOperator(pi2);
+ if (recomputeSchema) {
+ pi2.recomputeSchema();
+ }
return true;
}