diff options
author | Jinfeng Ni <jni@maprtech.com> | 2014-06-18 07:11:54 -0700 |
---|---|---|
committer | Jacques Nadeau <jacques@apache.org> | 2014-06-20 10:54:50 -0700 |
commit | 43bb57e758495d6c3e47e29b27e1f97b9f81f268 (patch) | |
tree | 8b61dcd5db9b4f7340348478271617487a628083 /exec/java-exec/src/main | |
parent | a314c824ba99edf0c29b004c121904847bab2c15 (diff) |
DRILL-1044: Optimize boolean and/or operators by short-circuit and fast-success / fast-fail approach.
Diffstat (limited to 'exec/java-exec/src/main')
21 files changed, 227 insertions, 49 deletions
diff --git a/exec/java-exec/src/main/codegen/templates/CastDateDate.java b/exec/java-exec/src/main/codegen/templates/CastDateDate.java index 821323b30..93edd5ad5 100644 --- a/exec/java-exec/src/main/codegen/templates/CastDateDate.java +++ b/exec/java-exec/src/main/codegen/templates/CastDateDate.java @@ -30,6 +30,7 @@ import io.netty.buffer.ByteBuf; import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; @@ -41,7 +42,7 @@ import org.joda.time.DateMidnight; import org.apache.drill.exec.expr.fn.impl.DateUtility; @SuppressWarnings("unused") -@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL) +@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL, costCategory=FunctionCostCategory.COMPLEX) public class Cast${type.from}To${type.to} implements DrillSimpleFunc { @Param ${type.from}Holder in; diff --git a/exec/java-exec/src/main/codegen/templates/CastDateVarChar.java b/exec/java-exec/src/main/codegen/templates/CastDateVarChar.java index 5b7ed6d72..e2fd9d59f 100644 --- a/exec/java-exec/src/main/codegen/templates/CastDateVarChar.java +++ b/exec/java-exec/src/main/codegen/templates/CastDateVarChar.java @@ -32,6 +32,7 @@ import io.netty.buffer.ByteBuf; import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; @@ -44,7 +45,8 @@ import org.joda.time.DateMidnight; import org.apache.drill.exec.expr.fn.impl.DateUtility; @SuppressWarnings("unused") -@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL) +@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public class Cast${type.from}To${type.to} implements DrillSimpleFunc { @Param ${type.from}Holder in; diff --git a/exec/java-exec/src/main/codegen/templates/CastIntervalVarChar.java b/exec/java-exec/src/main/codegen/templates/CastIntervalVarChar.java index 19adb27bf..4c88fccfd 100644 --- a/exec/java-exec/src/main/codegen/templates/CastIntervalVarChar.java +++ b/exec/java-exec/src/main/codegen/templates/CastIntervalVarChar.java @@ -31,6 +31,7 @@ import io.netty.buffer.ByteBuf; import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; @@ -98,10 +99,12 @@ public class Cast${type.from}To${type.to} implements DrillSimpleFunc { package org.apache.drill.exec.expr.fn.impl.gcast; + import io.netty.buffer.ByteBuf; import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; @@ -150,10 +153,12 @@ public class Cast${type.from}To${type.to} implements DrillSimpleFunc { package org.apache.drill.exec.expr.fn.impl.gcast; + import io.netty.buffer.ByteBuf; import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; @@ -166,7 +171,8 @@ import org.joda.time.DateMidnight; import org.apache.drill.exec.expr.fn.impl.DateUtility; @SuppressWarnings("unused") -@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL) +@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public class Cast${type.from}To${type.to} implements DrillSimpleFunc { @Param ${type.from}Holder in; diff --git a/exec/java-exec/src/main/codegen/templates/CastVarCharDate.java b/exec/java-exec/src/main/codegen/templates/CastVarCharDate.java index 5a3127a4c..e2e11434b 100644 --- a/exec/java-exec/src/main/codegen/templates/CastVarCharDate.java +++ b/exec/java-exec/src/main/codegen/templates/CastVarCharDate.java @@ -30,6 +30,7 @@ import io.netty.buffer.ByteBuf; import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; @@ -41,7 +42,8 @@ import org.joda.time.DateMidnight; import org.apache.drill.exec.expr.fn.impl.DateUtility; @SuppressWarnings("unused") -@FunctionTemplate(names = {"cast${type.to?upper_case}", "${type.alias}"}, scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL) +@FunctionTemplate(names = {"cast${type.to?upper_case}", "${type.alias}"}, scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public class Cast${type.from}To${type.to} implements DrillSimpleFunc { @Param ${type.from}Holder in; diff --git a/exec/java-exec/src/main/codegen/templates/DateIntervalFunctions.java b/exec/java-exec/src/main/codegen/templates/DateIntervalFunctions.java index a4bea61ac..b518c4432 100644 --- a/exec/java-exec/src/main/codegen/templates/DateIntervalFunctions.java +++ b/exec/java-exec/src/main/codegen/templates/DateIntervalFunctions.java @@ -27,10 +27,9 @@ package org.apache.drill.exec.expr.fn.impl; -import javax.xml.ws.Holder; - import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; @@ -191,6 +190,7 @@ package org.apache.drill.exec.expr.fn.impl; import org.apache.drill.exec.expr.DrillSimpleFunc; import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.expr.annotations.Output; import org.apache.drill.exec.expr.annotations.Param; @@ -200,7 +200,8 @@ import org.apache.drill.exec.record.RecordBatch; @SuppressWarnings("unused") public class GCompare${type.name}Functions { - @FunctionTemplate(name = "compare_to", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) + @FunctionTemplate(name = "compare_to", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public static class GCCompare${type.name} implements DrillSimpleFunc { @Param ${type.name}Holder left; @@ -220,7 +221,8 @@ public class GCompare${type.name}Functions { } } - @FunctionTemplate(name = "less_than", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) + @FunctionTemplate(name = "less_than", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public static class LessThan${type.name} implements DrillSimpleFunc { @Param ${type.name}Holder left; @@ -241,7 +243,8 @@ public class GCompare${type.name}Functions { } } - @FunctionTemplate(name = "less_than_or_equal_to", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) + @FunctionTemplate(name = "less_than_or_equal_to", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public static class LessThanE${type.name} implements DrillSimpleFunc { @Param ${type.name}Holder left; @@ -262,7 +265,8 @@ public class GCompare${type.name}Functions { } } - @FunctionTemplate(name = "greater_than", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) + @FunctionTemplate(name = "greater_than", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public static class GreaterThan${type.name} implements DrillSimpleFunc { @Param ${type.name}Holder left; @@ -283,7 +287,8 @@ public class GCompare${type.name}Functions { } } - @FunctionTemplate(name = "greater_than_or_equal_to", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) + @FunctionTemplate(name = "greater_than_or_equal_to", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public static class GreaterThanE${type.name} implements DrillSimpleFunc { @Param ${type.name}Holder left; @@ -304,7 +309,8 @@ public class GCompare${type.name}Functions { } } - @FunctionTemplate(name = "equal", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) + @FunctionTemplate(name = "equal", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public static class Equals${type.name} implements DrillSimpleFunc { @Param ${type.name}Holder left; @@ -324,7 +330,8 @@ public class GCompare${type.name}Functions { } } - @FunctionTemplate(name = "not_equal", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL) + @FunctionTemplate(name = "not_equal", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL, + costCategory = FunctionCostCategory.COMPLEX) public static class NotEquals${type.name} implements DrillSimpleFunc { @Param ${type.name}Holder left; diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/ConstantExpressionIdentifier.java b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/ConstantExpressionIdentifier.java index 489f62310..c65951de5 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/ConstantExpressionIdentifier.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/ConstantExpressionIdentifier.java @@ -22,6 +22,7 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Set; +import org.apache.drill.common.expression.BooleanOperator; import org.apache.drill.common.expression.CastExpression; import org.apache.drill.common.expression.ConvertExpression; import org.apache.drill.common.expression.FunctionCall; @@ -108,7 +109,12 @@ public class ConstantExpressionIdentifier implements ExprVisitor<Boolean, Identi public Boolean visitFunctionHolderExpression(FunctionHolderExpression holder, IdentityHashMap<LogicalExpression, Object> value) throws RuntimeException { return checkChildren(holder, value, !holder.isAggregating() && !holder.isRandom()); } - + + @Override + public Boolean visitBooleanOperator(BooleanOperator op, IdentityHashMap<LogicalExpression, Object> value) throws RuntimeException { + return checkChildren(op, value, true); + } + @Override public Boolean visitIfExpression(IfExpression ifExpr, IdentityHashMap<LogicalExpression, Object> value){ return checkChildren(ifExpr, value, true); diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/DrillFuncHolderExpr.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/DrillFuncHolderExpr.java index f164bd84a..0341c457e 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/DrillFuncHolderExpr.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/DrillFuncHolderExpr.java @@ -71,4 +71,27 @@ public class DrillFuncHolderExpr extends FunctionHolderExpression implements Ite public boolean isComplexWriterFuncHolder() { return holder instanceof DrillComplexWriterFuncHolder; } + + @Override + public int getSelfCost() { + return holder.getCostCategory(); + } + + @Override + public int getCumulativeCost() { + int cost = this.getSelfCost(); + + for (LogicalExpression arg : this.args) { + cost += arg.getCumulativeCost(); + } + + return cost; + } + + @Override + public DrillFuncHolderExpr copy(List<LogicalExpression> args) { + return new DrillFuncHolderExpr(this.nameUsed, this.holder, args, this.getPosition()); + } + } + diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java index d65e61891..f2019b837 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Set; import org.apache.commons.io.input.NullReader; +import org.apache.drill.common.expression.BooleanOperator; import org.apache.drill.common.expression.CastExpression; import org.apache.drill.common.expression.ConvertExpression; import org.apache.drill.common.expression.FunctionCall; @@ -55,7 +56,7 @@ import org.apache.drill.exec.compile.sig.ConstantExpressionIdentifier; import org.apache.drill.exec.expr.ClassGenerator.BlockType; import org.apache.drill.exec.expr.ClassGenerator.HoldingContainer; import org.apache.drill.exec.expr.fn.DrillFuncHolder; -import org.apache.drill.exec.expr.fn.DrillSCBooleanOPHolder; +import org.apache.drill.exec.expr.fn.DrillBooleanOPHolder; import org.apache.drill.exec.expr.fn.FunctionImplementationRegistry; import org.apache.drill.exec.expr.fn.HiveFuncHolder; import org.apache.drill.exec.physical.impl.filter.ReturnValueExpression; @@ -97,6 +98,18 @@ public class EvaluationVisitor { } @Override + public HoldingContainer visitBooleanOperator(BooleanOperator op, + ClassGenerator<?> generator) throws RuntimeException { + if (op.getName().equals("booleanAnd")) { + return visitBooleanAnd(op, generator); + }else if(op.getName().equals("booleanOr")) { + return visitBooleanOr(op, generator); + } else { + throw new UnsupportedOperationException("BooleanOperator can only be booleanAnd, booleanOr. You are using " + op.getName()); + } + } + + @Override public HoldingContainer visitFunctionHolderExpression(FunctionHolderExpression holderExpr, ClassGenerator<?> generator) throws RuntimeException { // TODO: hack: (Drill/Hive)FuncHolderExpr reference classes in exec so @@ -106,13 +119,6 @@ public class EvaluationVisitor { if (holderExpr instanceof DrillFuncHolderExpr) { DrillFuncHolder holder = ((DrillFuncHolderExpr) holderExpr).getHolder(); - if (holder instanceof DrillSCBooleanOPHolder && holderExpr.getName().equals("booleanAnd")) { - return visitBooleanAnd(holderExpr, generator); - } - - if (holder instanceof DrillSCBooleanOPHolder && holderExpr.getName().equals("booleanOr")) { - return visitBooleanOr(holderExpr, generator); - } JVar[] workspaceVars = holder.renderStart(generator, null); @@ -603,10 +609,10 @@ public class EvaluationVisitor { return fc.accept(this, value); } - private HoldingContainer visitBooleanAnd(FunctionHolderExpression holderExpr, + private HoldingContainer visitBooleanAnd(BooleanOperator op, ClassGenerator<?> generator) { - HoldingContainer out = generator.declare(holderExpr.getMajorType()); + HoldingContainer out = generator.declare(op.getMajorType()); JLabel label = generator.getEvalBlockLabel("AndOP"); JBlock eval = generator.getEvalBlock().block(); // enter into nested block @@ -623,8 +629,8 @@ public class EvaluationVisitor { // null true null // null false false // null null null - for (int i = 0; i < holderExpr.args.size(); i++) { - arg = holderExpr.args.get(i).accept(this, generator); + for (int i = 0; i < op.args.size(); i++) { + arg = op.args.get(i).accept(this, generator); JBlock earlyExit = null; if (arg.isOptional()) { @@ -665,10 +671,10 @@ public class EvaluationVisitor { return out; } - private HoldingContainer visitBooleanOr(FunctionHolderExpression holderExpr, + private HoldingContainer visitBooleanOr(BooleanOperator op, ClassGenerator<?> generator) { - HoldingContainer out = generator.declare(holderExpr.getMajorType()); + HoldingContainer out = generator.declare(op.getMajorType()); JLabel label = generator.getEvalBlockLabel("OrOP"); JBlock eval = generator.getEvalBlock().block(); @@ -686,8 +692,8 @@ public class EvaluationVisitor { // null false null // null null null - for (int i = 0; i < holderExpr.args.size(); i++) { - arg = holderExpr.args.get(i).accept(this, generator); + for (int i = 0; i < op.args.size(); i++) { + arg = op.args.get(i).accept(this, generator); JBlock earlyExit = null; if (arg.isOptional()) { @@ -762,6 +768,19 @@ public class EvaluationVisitor { } @Override + public HoldingContainer visitBooleanOperator(BooleanOperator e, ClassGenerator<?> generator) + throws RuntimeException { + if (constantBoundaries.contains(e)) { + generator.getMappingSet().enterConstant(); + HoldingContainer c = super.visitBooleanOperator(e, generator); + return renderConstantExpression(generator, c); + } else if (generator.getMappingSet().isWithinConstant()) { + return super.visitBooleanOperator(e, generator).setConstant(true); + } else { + return super.visitBooleanOperator(e, generator); + } + } + @Override public HoldingContainer visitIfExpression(IfExpression e, ClassGenerator<?> generator) throws RuntimeException { if (constantBoundaries.contains(e)) { generator.getMappingSet().enterConstant(); diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java index 18609f864..4e10d2011 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java @@ -26,6 +26,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import org.apache.drill.common.expression.BooleanOperator; import org.apache.drill.common.expression.CastExpression; import org.apache.drill.common.expression.ConvertExpression; import org.apache.drill.common.expression.ErrorCollector; @@ -57,6 +58,7 @@ import org.apache.drill.common.expression.ValueExpressions.IntExpression; import org.apache.drill.common.expression.ValueExpressions.QuotedString; import org.apache.drill.common.expression.fn.CastFunctions; import org.apache.drill.common.expression.visitors.AbstractExprVisitor; +import org.apache.drill.common.expression.visitors.ConditionalExprOptimizer; import org.apache.drill.common.expression.visitors.ExpressionValidator; import org.apache.drill.common.types.TypeProtos; import org.apache.drill.common.types.TypeProtos.DataMode; @@ -89,6 +91,11 @@ public class ExpressionTreeMaterializer { public static LogicalExpression materialize(LogicalExpression expr, VectorAccessible batch, ErrorCollector errorCollector, FunctionImplementationRegistry registry, boolean allowComplexWriterExpr) { LogicalExpression out = expr.accept(new MaterializeVisitor(batch, errorCollector, allowComplexWriterExpr), registry); + + if (!errorCollector.hasErrors()) { + out = out.accept(ConditionalExprOptimizer.INSTANCE, null); + } + if(out instanceof NullExpression){ return new TypedNullConstant(Types.optional(MinorType.INT)); }else{ @@ -126,6 +133,19 @@ public class ExpressionTreeMaterializer { } @Override + public LogicalExpression visitBooleanOperator(BooleanOperator op, FunctionImplementationRegistry registry) { + List<LogicalExpression> args = Lists.newArrayList(); + for (int i = 0; i < op.args.size(); ++i) { + LogicalExpression newExpr = op.args.get(i).accept(this, registry); + assert newExpr != null : String.format("Materialization of %s return a null expression.", op.args.get(i)); + args.add(newExpr); + } + + //replace with a new function call, since its argument could be changed. + return new BooleanOperator(op.getName(), args, op.getPosition()); + } + + @Override public LogicalExpression visitFunctionCall(FunctionCall call, FunctionImplementationRegistry registry) { List<LogicalExpression> args = Lists.newArrayList(); for (int i = 0; i < call.args.size(); ++i) { diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HiveFuncHolderExpr.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HiveFuncHolderExpr.java index afcd9cd04..c765d3977 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HiveFuncHolderExpr.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HiveFuncHolderExpr.java @@ -66,4 +66,10 @@ public class HiveFuncHolderExpr extends FunctionHolderExpression implements Iter public boolean isRandom() { return holder.isRandom(); } + + @Override + public HiveFuncHolderExpr copy(List<LogicalExpression> args) { + return new HiveFuncHolderExpr(this.nameUsed, this.holder, args, this.getPosition()); + } + } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HoldingContainerExpression.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HoldingContainerExpression.java index fd26e860d..45051b976 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HoldingContainerExpression.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HoldingContainerExpression.java @@ -25,6 +25,7 @@ import org.apache.drill.common.expression.visitors.ExprVisitor; import org.apache.drill.common.types.TypeProtos.MajorType; import org.apache.drill.exec.expr.ClassGenerator.HoldingContainer; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.common.collect.Iterators; public class HoldingContainerExpression implements LogicalExpression{ @@ -60,4 +61,15 @@ public class HoldingContainerExpression implements LogicalExpression{ public ExpressionPosition getPosition() { return ExpressionPosition.UNKNOWN; } + + @Override + public int getSelfCost() { + return 0; // TODO + } + + @Override + public int getCumulativeCost() { + return 0; // TODO + } + } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ValueVectorReadExpression.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ValueVectorReadExpression.java index 6e2809aa8..f8236d9a8 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ValueVectorReadExpression.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ValueVectorReadExpression.java @@ -78,6 +78,15 @@ public class ValueVectorReadExpression implements LogicalExpression{ public Iterator<LogicalExpression> iterator() { return Iterators.emptyIterator(); } - - + + @Override + public int getSelfCost() { + return 0; // TODO + } + + @Override + public int getCumulativeCost() { + return 0; // TODO + } + } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ValueVectorWriteExpression.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ValueVectorWriteExpression.java index 02277afe5..d2770578b 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ValueVectorWriteExpression.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ValueVectorWriteExpression.java @@ -78,5 +78,15 @@ public class ValueVectorWriteExpression implements LogicalExpression { return Iterators.singletonIterator(child); } + @Override + public int getSelfCost() { + return 0; // TODO + } + + @Override + public int getCumulativeCost() { + return 0; // TODO + } + } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java index b364a4a75..be43d38e7 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java @@ -46,6 +46,8 @@ public @interface FunctionTemplate { boolean isBinaryCommutative() default false; boolean isRandom() default false; + FunctionCostCategory costCategory() default FunctionCostCategory.SIMPLE; + public static enum NullHandling { INTERNAL, NULL_IF_NULL; } @@ -64,4 +66,23 @@ public @interface FunctionTemplate { DECIMAL_ZERO_SCALE, SC_BOOLEAN_OPERATOR } + + public static enum FunctionCostCategory { + SIMPLE(1), MEDIUM(3), COMPLEX(5); + + private final int value; + + private FunctionCostCategory(int value) { + this.value = value; + } + + public int getValue() { + return this.value; + } + + public static FunctionCostCategory getDefault() { + return SIMPLE; + } + + } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillAggFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillAggFuncHolder.java index 48c35f2e4..efe3ee318 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillAggFuncHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillAggFuncHolder.java @@ -25,6 +25,7 @@ import org.apache.drill.common.types.Types; import org.apache.drill.exec.expr.ClassGenerator; import org.apache.drill.exec.expr.ClassGenerator.BlockType; import org.apache.drill.exec.expr.ClassGenerator.HoldingContainer; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.record.TypedFieldId; @@ -48,12 +49,18 @@ class DrillAggFuncHolder extends DrillFuncHolder{ private final String add; private final String output; private final String cleanup; - + public DrillAggFuncHolder(FunctionScope scope, NullHandling nullHandling, boolean isBinaryCommutative, boolean isRandom, String[] registeredNames, ValueReference[] parameters, ValueReference returnValue, WorkspaceReference[] workspaceVars, Map<String, String> methods, List<String> imports) { + this(scope, nullHandling, isBinaryCommutative, isRandom, registeredNames, parameters, returnValue, workspaceVars, methods, imports, FunctionCostCategory.getDefault()); + } + + public DrillAggFuncHolder(FunctionScope scope, NullHandling nullHandling, boolean isBinaryCommutative, boolean isRandom, + String[] registeredNames, ValueReference[] parameters, ValueReference returnValue, WorkspaceReference[] workspaceVars, + Map<String, String> methods, List<String> imports, FunctionCostCategory costCategory) { super(scope, nullHandling, isBinaryCommutative, isRandom, - registeredNames, parameters, returnValue, workspaceVars, methods, imports); + registeredNames, parameters, returnValue, workspaceVars, methods, imports, costCategory); Preconditions.checkArgument(nullHandling == NullHandling.INTERNAL, "An aggregation function is required to do its own null handling."); setup = methods.get("setup"); reset = methods.get("reset"); diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillSCBooleanOPHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillBooleanOPHolder.java index d6d7037d5..9032d37b6 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillSCBooleanOPHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillBooleanOPHolder.java @@ -21,15 +21,16 @@ package org.apache.drill.exec.expr.fn; import java.util.List; import java.util.Map; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; -public class DrillSCBooleanOPHolder extends DrillSimpleFuncHolder{ +public class DrillBooleanOPHolder extends DrillSimpleFuncHolder{ - public DrillSCBooleanOPHolder(FunctionScope scope, NullHandling nullHandling, boolean isBinaryCommutative, boolean isRandom, + public DrillBooleanOPHolder(FunctionScope scope, NullHandling nullHandling, boolean isBinaryCommutative, boolean isRandom, String[] registeredNames, ValueReference[] parameters, ValueReference returnValue, WorkspaceReference[] workspaceVars, Map<String, String> methods, List<String> imports) { - super(scope, nullHandling, isBinaryCommutative, isRandom, registeredNames, parameters, returnValue, workspaceVars, methods, imports); + super(scope, nullHandling, isBinaryCommutative, isRandom, registeredNames, parameters, returnValue, workspaceVars, methods, imports, FunctionCostCategory.getDefault()); } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFuncHolder.java index fc8dc0041..f3c1e130e 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFuncHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillFuncHolder.java @@ -31,6 +31,7 @@ import org.apache.drill.exec.expr.ClassGenerator.BlockType; import org.apache.drill.exec.expr.ClassGenerator.HoldingContainer; import org.apache.drill.exec.expr.TypeHelper; import org.apache.drill.exec.expr.annotations.FunctionTemplate; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; import org.apache.drill.exec.vector.complex.impl.NullableBigIntSingularReaderImpl; @@ -51,6 +52,7 @@ public abstract class DrillFuncHolder { protected final FunctionTemplate.FunctionScope scope; protected final FunctionTemplate.NullHandling nullHandling; + protected final FunctionTemplate.FunctionCostCategory costCategory; protected final boolean isBinaryCommutative; protected final boolean isRandom; protected final String[] registeredNames; @@ -62,7 +64,7 @@ public abstract class DrillFuncHolder { public DrillFuncHolder(FunctionScope scope, NullHandling nullHandling, boolean isBinaryCommutative, boolean isRandom, String[] registeredNames, ValueReference[] parameters, ValueReference returnValue, - WorkspaceReference[] workspaceVars, Map<String, String> methods, List<String> imports) { + WorkspaceReference[] workspaceVars, Map<String, String> methods, List<String> imports, FunctionCostCategory costCategory) { super(); this.scope = scope; this.nullHandling = nullHandling; @@ -74,6 +76,7 @@ public abstract class DrillFuncHolder { this.parameters = parameters; this.returnValue = returnValue; this.imports = ImmutableList.copyOf(imports); + this.costCategory = costCategory; } public List<String> getImports() { @@ -223,6 +226,10 @@ public abstract class DrillFuncHolder { return registeredNames; } + public int getCostCategory() { + return this.costCategory.getValue(); + } + @Override public String toString() { final int maxLen = 10; diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillSimpleFuncHolder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillSimpleFuncHolder.java index 01fc514d2..53df02ded 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillSimpleFuncHolder.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/DrillSimpleFuncHolder.java @@ -27,6 +27,7 @@ import org.apache.drill.common.types.TypeProtos.MajorType; import org.apache.drill.exec.expr.ClassGenerator; import org.apache.drill.exec.expr.ClassGenerator.BlockType; import org.apache.drill.exec.expr.ClassGenerator.HoldingContainer; +import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionCostCategory; import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope; import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling; @@ -46,11 +47,16 @@ class DrillSimpleFuncHolder extends DrillFuncHolder{ private final String resetBody; private final String cleanupBody; - public DrillSimpleFuncHolder(FunctionScope scope, NullHandling nullHandling, boolean isBinaryCommutative, boolean isRandom, String[] registeredNames, ValueReference[] parameters, ValueReference returnValue, WorkspaceReference[] workspaceVars, Map<String, String> methods, List<String> imports) { - super(scope, nullHandling, isBinaryCommutative, isRandom, registeredNames, parameters, returnValue, workspaceVars, methods, imports); + this(scope, nullHandling, isBinaryCommutative, isRandom, registeredNames, parameters, returnValue, workspaceVars, methods, imports, FunctionCostCategory.getDefault()); + } + + public DrillSimpleFuncHolder(FunctionScope scope, NullHandling nullHandling, boolean isBinaryCommutative, boolean isRandom, + String[] registeredNames, ValueReference[] parameters, ValueReference returnValue, WorkspaceReference[] workspaceVars, + Map<String, String> methods, List<String> imports, FunctionCostCategory costCategory) { + super(scope, nullHandling, isBinaryCommutative, isRandom, registeredNames, parameters, returnValue, workspaceVars, methods, imports, costCategory); setupBody = methods.get("setup"); evalBody = methods.get("eval"); resetBody = methods.get("reset"); diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java index 2107421e5..8328549f3 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionConverter.java @@ -220,7 +220,7 @@ public class FunctionConverter { switch(template.scope()){ case POINT_AGGREGATE: return new DrillAggFuncHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), - template.isRandom(), registeredNames, ps, outputField, works, methods, imports); + template.isRandom(), registeredNames, ps, outputField, works, methods, imports, template.costCategory()); case DECIMAL_AGGREGATE: return new DrillDecimalAggFuncHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), template.isRandom(), registeredNames, ps, outputField, works, methods, imports); @@ -234,9 +234,9 @@ public class FunctionConverter { return new DrillSimpleFuncHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), template.isRandom(), registeredNames, - ps, outputField, works, methods, imports); + ps, outputField, works, methods, imports, template.costCategory()); case SC_BOOLEAN_OPERATOR: - return new DrillSCBooleanOPHolder(template.scope(), template.nulls(), + return new DrillBooleanOPHolder(template.scope(), template.nulls(), template.isBinaryCommutative(), template.isRandom(), registeredNames, ps, outputField, works, methods, imports); diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/filter/ReturnValueExpression.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/filter/ReturnValueExpression.java index 4ec4b096e..1aa300635 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/filter/ReturnValueExpression.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/filter/ReturnValueExpression.java @@ -70,5 +70,12 @@ public class ReturnValueExpression implements LogicalExpression{ return returnTrueOnOne; } + public int getSelfCost() { + throw new UnsupportedOperationException(String.format("The type of %s doesn't currently support LogicalExpression.getSelfCost().", this.getClass().getCanonicalName())); + } + + public int getCumulativeCost() { + throw new UnsupportedOperationException(String.format("The type of %s doesn't currently support LogicalExpression.getCumulativeCost().", this.getClass().getCanonicalName())); + } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java index dd3037887..21ff421a5 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java @@ -98,13 +98,19 @@ public class DrillOptiq { for(RexNode r : call.getOperands()){ args.add(r.accept(this)); } - args = Lists.reverse(args); - LogicalExpression lastArg = args.get(0); - for(int i = 1; i < args.size(); i++){ - lastArg = FunctionCallFactory.createExpression(funcName, Lists.newArrayList(args.get(i), lastArg)); - } - return lastArg; + if (FunctionCallFactory.isBooleanOperator(funcName)) { + LogicalExpression func = FunctionCallFactory.createBooleanOperator(funcName, args); + return func; + } else { + args = Lists.reverse(args); + LogicalExpression lastArg = args.get(0); + for(int i = 1; i < args.size(); i++){ + lastArg = FunctionCallFactory.createExpression(funcName, Lists.newArrayList(args.get(i), lastArg)); + } + + return lastArg; + } case FUNCTION: case FUNCTION_ID: logger.debug("Function"); |