From 84b4bf56d8be710cf793d26106b2c475fa901469 Mon Sep 17 00:00:00 2001 From: Clint Wylie Date: Thu, 2 Dec 2021 16:40:23 -0800 Subject: [PATCH] vectorize logical operators and boolean functions (#11184) changes: * adds new config, druid.expressions.useStrictBooleans which make longs the official boolean type of all expressions * vectorize logical operators and boolean functions, some only if useStrictBooleans is true --- .../query/SqlExpressionBenchmark.java | 14 +- .../config/NullValueHandlingConfig.java | 13 +- .../math/expr/BinaryLogicalOperatorExpr.java | 262 ++++--- .../druid/math/expr/BinaryOperatorExpr.java | 65 ++ .../apache/druid/math/expr/ConstantExpr.java | 10 +- .../java/org/apache/druid/math/expr/Expr.java | 77 +- .../org/apache/druid/math/expr/ExprEval.java | 12 +- .../druid/math/expr/ExpressionProcessing.java | 20 +- .../math/expr/ExpressionProcessingConfig.java | 21 +- .../org/apache/druid/math/expr/Function.java | 39 +- .../druid/math/expr/UnaryOperatorExpr.java | 33 +- .../BivariateFunctionVectorProcessor.java | 73 +- ...BivariateFunctionVectorValueProcessor.java | 87 +++ ...DoubleInFunctionVectorValueProcessor.java} | 8 +- ...leLongInFunctionVectorValueProcessor.java} | 8 +- ...oublesInFunctionVectorValueProcessor.java} | 8 +- ...DoubleInFunctionVectorValueProcessor.java} | 8 +- ...utLongInFunctionVectorValueProcessor.java} | 8 +- ...tLongsInFunctionVectorValueProcessor.java} | 8 +- ...DoubleInFunctionVectorValueProcessor.java} | 6 +- ...leLongInFunctionVectorValueProcessor.java} | 8 +- ...oublesInFunctionVectorValueProcessor.java} | 8 +- ...DoubleInFunctionVectorValueProcessor.java} | 8 +- ...utLongInFunctionVectorValueProcessor.java} | 6 +- ...tLongsInFunctionVectorValueProcessor.java} | 8 +- ...ricalBivariateFunctionVectorProcessor.java | 34 + ...ivariateFunctionVectorValueProcessor.java} | 4 +- .../vector/VectorComparisonProcessors.java | 599 ++++++++++++-- .../expr/vector/VectorMathProcessors.java | 324 ++++---- .../math/expr/vector/VectorProcessors.java | 738 +++++++++++++++++- .../org/apache/druid/math/expr/EvalTest.java | 480 ++++++++---- .../druid/math/expr/OutputTypeTest.java | 111 ++- .../druid/math/expr/VectorExprSanityTest.java | 57 +- docs/configuration/index.md | 6 + docs/misc/math-expr.md | 56 +- .../cluster/_common/common.runtime.properties | 7 +- .../large/_common/common.runtime.properties | 7 +- .../medium/_common/common.runtime.properties | 7 +- .../_common/common.runtime.properties | 7 +- .../_common/common.runtime.properties | 7 +- .../small/_common/common.runtime.properties | 7 +- .../xlarge/_common/common.runtime.properties | 7 +- .../parquet/simple/ParquetGroupConverter.java | 2 +- .../expression/TimestampFloorExprMacro.java | 4 +- .../CaseInsensitiveExprMacroTest.java | 19 +- .../expression/ContainsExprMacroTest.java | 17 +- .../query/groupby/GroupByQueryRunnerTest.java | 35 + .../ExpressionFilterStrictBooleansTest.java | 53 ++ .../segment/filter/ExpressionFilterTest.java | 15 + .../SqlVectorizedExpressionSanityTest.java | 7 +- website/.spelling | 2 + 51 files changed, 2753 insertions(+), 677 deletions(-) create mode 100644 core/src/main/java/org/apache/druid/math/expr/vector/BivariateFunctionVectorValueProcessor.java rename core/src/main/java/org/apache/druid/math/expr/vector/{DoubleOutDoubleInFunctionVectorProcessor.java => DoubleOutDoubleInFunctionVectorValueProcessor.java} (79%) rename core/src/main/java/org/apache/druid/math/expr/vector/{DoubleOutDoubleLongInFunctionVectorProcessor.java => DoubleOutDoubleLongInFunctionVectorValueProcessor.java} (84%) rename core/src/main/java/org/apache/druid/math/expr/vector/{DoubleOutDoublesInFunctionVectorProcessor.java => DoubleOutDoublesInFunctionVectorValueProcessor.java} (84%) rename core/src/main/java/org/apache/druid/math/expr/vector/{DoubleOutLongDoubleInFunctionVectorProcessor.java => DoubleOutLongDoubleInFunctionVectorValueProcessor.java} (84%) rename core/src/main/java/org/apache/druid/math/expr/vector/{DoubleOutLongInFunctionVectorProcessor.java => DoubleOutLongInFunctionVectorValueProcessor.java} (80%) rename core/src/main/java/org/apache/druid/math/expr/vector/{DoubleOutLongsInFunctionVectorProcessor.java => DoubleOutLongsInFunctionVectorValueProcessor.java} (84%) rename core/src/main/java/org/apache/druid/math/expr/vector/{LongOutDoubleInFunctionVectorProcessor.java => LongOutDoubleInFunctionVectorValueProcessor.java} (80%) rename core/src/main/java/org/apache/druid/math/expr/vector/{LongOutDoubleLongInFunctionVectorProcessor.java => LongOutDoubleLongInFunctionVectorValueProcessor.java} (84%) rename core/src/main/java/org/apache/druid/math/expr/vector/{LongOutDoublesInFunctionVectorProcessor.java => LongOutDoublesInFunctionVectorValueProcessor.java} (84%) rename core/src/main/java/org/apache/druid/math/expr/vector/{LongOutLongDoubleInFunctionVectorProcessor.java => LongOutLongDoubleInFunctionVectorValueProcessor.java} (84%) rename core/src/main/java/org/apache/druid/math/expr/vector/{LongOutLongInFunctionVectorProcessor.java => LongOutLongInFunctionVectorValueProcessor.java} (80%) rename core/src/main/java/org/apache/druid/math/expr/vector/{LongOutLongsInFunctionVectorProcessor.java => LongOutLongsInFunctionVectorValueProcessor.java} (84%) create mode 100644 core/src/main/java/org/apache/druid/math/expr/vector/SymmetricalBivariateFunctionVectorProcessor.java rename core/src/main/java/org/apache/druid/math/expr/vector/{UnivariateFunctionVectorProcessor.java => UnivariateFunctionVectorValueProcessor.java} (93%) create mode 100644 processing/src/test/java/org/apache/druid/segment/filter/ExpressionFilterStrictBooleansTest.java diff --git a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlExpressionBenchmark.java b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlExpressionBenchmark.java index 76cdbfa9ab6d..000874e2a1f3 100644 --- a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlExpressionBenchmark.java +++ b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlExpressionBenchmark.java @@ -26,6 +26,7 @@ import org.apache.druid.java.util.common.guava.Sequence; import org.apache.druid.java.util.common.io.Closer; import org.apache.druid.java.util.common.logger.Logger; +import org.apache.druid.math.expr.ExpressionProcessing; import org.apache.druid.query.DruidProcessingConfig; import org.apache.druid.query.QueryContexts; import org.apache.druid.query.QueryRunnerFactoryConglomerate; @@ -80,6 +81,7 @@ public class SqlExpressionBenchmark static { NullHandling.initializeForTests(); Calcites.setSystemProperties(); + ExpressionProcessing.initializeForStrictBooleansTests(true); } private static final DruidProcessingConfig PROCESSING_CONFIG = new DruidProcessingConfig() @@ -181,8 +183,12 @@ public String getFormatString() "SELECT CONCAT(string2, '-', long2), SUM(long1 * double4) FROM foo GROUP BY 1 ORDER BY 2", // 28: group by single input string low cardinality expr with expr agg "SELECT CONCAT(string2, '-', 'foo'), SUM(long1 * long4) FROM foo GROUP BY 1 ORDER BY 2", - // 28: group by single input string high cardinality expr with expr agg - "SELECT CONCAT(string3, '-', 'foo'), SUM(long1 * long4) FROM foo GROUP BY 1 ORDER BY 2" + // 29: group by single input string high cardinality expr with expr agg + "SELECT CONCAT(string3, '-', 'foo'), SUM(long1 * long4) FROM foo GROUP BY 1 ORDER BY 2", + // 30: logical and operator + "SELECT CAST(long1 as BOOLEAN) AND CAST (long2 as BOOLEAN), COUNT(*) FROM foo GROUP BY 1 ORDER BY 2", + // 31: isnull, notnull + "SELECT long5 IS NULL, long3 IS NOT NULL, count(*) FROM foo GROUP BY 1,2 ORDER BY 3" ); @Param({"5000000"}) @@ -226,7 +232,9 @@ public String getFormatString() "26", "27", "28", - "29" + "29", + "30", + "31" }) private String query; diff --git a/core/src/main/java/org/apache/druid/common/config/NullValueHandlingConfig.java b/core/src/main/java/org/apache/druid/common/config/NullValueHandlingConfig.java index fa0594782268..c733f847fc3d 100644 --- a/core/src/main/java/org/apache/druid/common/config/NullValueHandlingConfig.java +++ b/core/src/main/java/org/apache/druid/common/config/NullValueHandlingConfig.java @@ -29,12 +29,17 @@ public class NullValueHandlingConfig @JsonProperty("useDefaultValueForNull") private final boolean useDefaultValuesForNull; + @JsonCreator - public NullValueHandlingConfig(@JsonProperty("useDefaultValueForNull") Boolean useDefaultValuesForNull) + public NullValueHandlingConfig( + @JsonProperty("useDefaultValueForNull") Boolean useDefaultValuesForNull + ) { - this.useDefaultValuesForNull = useDefaultValuesForNull == null - ? Boolean.valueOf(System.getProperty(NULL_HANDLING_CONFIG_STRING, "true")) - : useDefaultValuesForNull; + if (useDefaultValuesForNull == null) { + this.useDefaultValuesForNull = Boolean.valueOf(System.getProperty(NULL_HANDLING_CONFIG_STRING, "true")); + } else { + this.useDefaultValuesForNull = useDefaultValuesForNull; + } } public boolean isUseDefaultValuesForNull() diff --git a/core/src/main/java/org/apache/druid/math/expr/BinaryLogicalOperatorExpr.java b/core/src/main/java/org/apache/druid/math/expr/BinaryLogicalOperatorExpr.java index 40556625b4f5..7b991ca13ab1 100644 --- a/core/src/main/java/org/apache/druid/math/expr/BinaryLogicalOperatorExpr.java +++ b/core/src/main/java/org/apache/druid/math/expr/BinaryLogicalOperatorExpr.java @@ -19,9 +19,11 @@ package org.apache.druid.math.expr; +import org.apache.druid.common.config.NullHandling; import org.apache.druid.java.util.common.guava.Comparators; import org.apache.druid.math.expr.vector.ExprVectorProcessor; import org.apache.druid.math.expr.vector.VectorComparisonProcessors; +import org.apache.druid.math.expr.vector.VectorProcessors; import org.apache.druid.segment.column.Types; import javax.annotation.Nullable; @@ -29,7 +31,7 @@ // logical operators live here @SuppressWarnings("ClassName") -class BinLtExpr extends BinaryEvalOpExprBase +class BinLtExpr extends BinaryBooleanOpExprBase { BinLtExpr(String op, Expr left, Expr right) { @@ -43,33 +45,22 @@ protected BinaryOpExprBase copy(Expr left, Expr right) } @Override - protected ExprEval evalString(@Nullable String left, @Nullable String right) + protected boolean evalString(@Nullable String left, @Nullable String right) { - return ExprEval.ofLongBoolean(Comparators.naturalNullsFirst().compare(left, right) < 0); + return Comparators.naturalNullsFirst().compare(left, right) < 0; } @Override - protected final long evalLong(long left, long right) + protected final boolean evalLong(long left, long right) { - return Evals.asLong(left < right); + return left < right; } @Override - protected final double evalDouble(double left, double right) + protected final boolean evalDouble(double left, double right) { // Use Double.compare for more consistent NaN handling. - return Evals.asDouble(Double.compare(left, right) < 0); - } - - @Nullable - @Override - public ExpressionType getOutputType(InputBindingInspector inspector) - { - ExpressionType implicitCast = super.getOutputType(inspector); - if (Types.isNullOr(implicitCast, ExprType.STRING)) { - return ExpressionType.LONG; - } - return implicitCast; + return Double.compare(left, right) < 0; } @Override @@ -86,7 +77,7 @@ public ExprVectorProcessor buildVectorized(VectorInputBindingInspector in } @SuppressWarnings("ClassName") -class BinLeqExpr extends BinaryEvalOpExprBase +class BinLeqExpr extends BinaryBooleanOpExprBase { BinLeqExpr(String op, Expr left, Expr right) { @@ -100,33 +91,22 @@ protected BinaryOpExprBase copy(Expr left, Expr right) } @Override - protected ExprEval evalString(@Nullable String left, @Nullable String right) + protected boolean evalString(@Nullable String left, @Nullable String right) { - return ExprEval.ofLongBoolean(Comparators.naturalNullsFirst().compare(left, right) <= 0); + return Comparators.naturalNullsFirst().compare(left, right) <= 0; } @Override - protected final long evalLong(long left, long right) + protected final boolean evalLong(long left, long right) { - return Evals.asLong(left <= right); + return left <= right; } @Override - protected final double evalDouble(double left, double right) + protected final boolean evalDouble(double left, double right) { // Use Double.compare for more consistent NaN handling. - return Evals.asDouble(Double.compare(left, right) <= 0); - } - - @Nullable - @Override - public ExpressionType getOutputType(InputBindingInspector inspector) - { - ExpressionType implicitCast = super.getOutputType(inspector); - if (Types.isNullOr(implicitCast, ExprType.STRING)) { - return ExpressionType.LONG; - } - return implicitCast; + return Double.compare(left, right) <= 0; } @Override @@ -143,7 +123,7 @@ public ExprVectorProcessor buildVectorized(VectorInputBindingInspector in } @SuppressWarnings("ClassName") -class BinGtExpr extends BinaryEvalOpExprBase +class BinGtExpr extends BinaryBooleanOpExprBase { BinGtExpr(String op, Expr left, Expr right) { @@ -157,34 +137,24 @@ protected BinaryOpExprBase copy(Expr left, Expr right) } @Override - protected ExprEval evalString(@Nullable String left, @Nullable String right) + protected boolean evalString(@Nullable String left, @Nullable String right) { - return ExprEval.ofLongBoolean(Comparators.naturalNullsFirst().compare(left, right) > 0); + return Comparators.naturalNullsFirst().compare(left, right) > 0; } @Override - protected final long evalLong(long left, long right) + protected final boolean evalLong(long left, long right) { - return Evals.asLong(left > right); + return left > right; } @Override - protected final double evalDouble(double left, double right) + protected final boolean evalDouble(double left, double right) { // Use Double.compare for more consistent NaN handling. - return Evals.asDouble(Double.compare(left, right) > 0); + return Double.compare(left, right) > 0; } - @Nullable - @Override - public ExpressionType getOutputType(InputBindingInspector inspector) - { - ExpressionType implicitCast = super.getOutputType(inspector); - if (Types.isNullOr(implicitCast, ExprType.STRING)) { - return ExpressionType.LONG; - } - return implicitCast; - } @Override public boolean canVectorize(InputBindingInspector inspector) { @@ -199,7 +169,7 @@ public ExprVectorProcessor buildVectorized(VectorInputBindingInspector in } @SuppressWarnings("ClassName") -class BinGeqExpr extends BinaryEvalOpExprBase +class BinGeqExpr extends BinaryBooleanOpExprBase { BinGeqExpr(String op, Expr left, Expr right) { @@ -213,33 +183,22 @@ protected BinaryOpExprBase copy(Expr left, Expr right) } @Override - protected ExprEval evalString(@Nullable String left, @Nullable String right) + protected boolean evalString(@Nullable String left, @Nullable String right) { - return ExprEval.ofLongBoolean(Comparators.naturalNullsFirst().compare(left, right) >= 0); + return Comparators.naturalNullsFirst().compare(left, right) >= 0; } @Override - protected final long evalLong(long left, long right) + protected final boolean evalLong(long left, long right) { - return Evals.asLong(left >= right); + return left >= right; } @Override - protected final double evalDouble(double left, double right) + protected final boolean evalDouble(double left, double right) { // Use Double.compare for more consistent NaN handling. - return Evals.asDouble(Double.compare(left, right) >= 0); - } - - @Nullable - @Override - public ExpressionType getOutputType(InputBindingInspector inspector) - { - ExpressionType implicitCast = super.getOutputType(inspector); - if (Types.isNullOr(implicitCast, ExprType.STRING)) { - return ExpressionType.LONG; - } - return implicitCast; + return Double.compare(left, right) >= 0; } @Override @@ -256,7 +215,7 @@ public ExprVectorProcessor buildVectorized(VectorInputBindingInspector in } @SuppressWarnings("ClassName") -class BinEqExpr extends BinaryEvalOpExprBase +class BinEqExpr extends BinaryBooleanOpExprBase { BinEqExpr(String op, Expr left, Expr right) { @@ -270,32 +229,21 @@ protected BinaryOpExprBase copy(Expr left, Expr right) } @Override - protected ExprEval evalString(@Nullable String left, @Nullable String right) + protected boolean evalString(@Nullable String left, @Nullable String right) { - return ExprEval.ofLongBoolean(Objects.equals(left, right)); + return Objects.equals(left, right); } @Override - protected final long evalLong(long left, long right) + protected final boolean evalLong(long left, long right) { - return Evals.asLong(left == right); + return left == right; } @Override - protected final double evalDouble(double left, double right) + protected final boolean evalDouble(double left, double right) { - return Evals.asDouble(left == right); - } - - @Nullable - @Override - public ExpressionType getOutputType(InputBindingInspector inspector) - { - ExpressionType implicitCast = super.getOutputType(inspector); - if (Types.isNullOr(implicitCast, ExprType.STRING)) { - return ExpressionType.LONG; - } - return implicitCast; + return left == right; } @Override @@ -312,7 +260,7 @@ public ExprVectorProcessor buildVectorized(VectorInputBindingInspector in } @SuppressWarnings("ClassName") -class BinNeqExpr extends BinaryEvalOpExprBase +class BinNeqExpr extends BinaryBooleanOpExprBase { BinNeqExpr(String op, Expr left, Expr right) { @@ -326,32 +274,21 @@ protected BinaryOpExprBase copy(Expr left, Expr right) } @Override - protected ExprEval evalString(@Nullable String left, @Nullable String right) - { - return ExprEval.ofLongBoolean(!Objects.equals(left, right)); - } - - @Override - protected final long evalLong(long left, long right) + protected boolean evalString(@Nullable String left, @Nullable String right) { - return Evals.asLong(left != right); + return !Objects.equals(left, right); } @Override - protected final double evalDouble(double left, double right) + protected final boolean evalLong(long left, long right) { - return Evals.asDouble(left != right); + return left != right; } - @Nullable @Override - public ExpressionType getOutputType(InputBindingInspector inspector) + protected final boolean evalDouble(double left, double right) { - ExpressionType implicitCast = super.getOutputType(inspector); - if (Types.isNullOr(implicitCast, ExprType.STRING)) { - return ExpressionType.LONG; - } - return implicitCast; + return left != right; } @Override @@ -385,7 +322,59 @@ protected BinaryOpExprBase copy(Expr left, Expr right) public ExprEval eval(ObjectBinding bindings) { ExprEval leftVal = left.eval(bindings); - return leftVal.asBoolean() ? right.eval(bindings) : leftVal; + if (!ExpressionProcessing.useStrictBooleans()) { + return leftVal.asBoolean() ? right.eval(bindings) : leftVal; + } + + // if left is false, always false + if (leftVal.value() != null && !leftVal.asBoolean()) { + return ExprEval.ofLongBoolean(false); + } + ExprEval rightVal; + if (NullHandling.sqlCompatible() || Types.is(leftVal.type(), ExprType.STRING)) { + // true/null, null/true, null/null -> null + // false/null, null/false -> false + if (leftVal.value() == null) { + rightVal = right.eval(bindings); + if (rightVal.value() == null || rightVal.asBoolean()) { + return ExprEval.ofLong(null); + } + return ExprEval.ofLongBoolean(false); + } else { + // left value must be true + rightVal = right.eval(bindings); + if (rightVal.value() == null) { + return ExprEval.ofLong(null); + } + } + } else { + rightVal = right.eval(bindings); + } + return ExprEval.ofLongBoolean(leftVal.asBoolean() && rightVal.asBoolean()); + } + + @Override + public boolean canVectorize(InputBindingInspector inspector) + { + return ExpressionProcessing.useStrictBooleans() && + inspector.areSameTypes(left, right) && + inspector.canVectorize(left, right); + } + + @Override + public ExprVectorProcessor buildVectorized(VectorInputBindingInspector inspector) + { + return VectorProcessors.and(inspector, left, right); + } + + @Nullable + @Override + public ExpressionType getOutputType(InputBindingInspector inspector) + { + if (!ExpressionProcessing.useStrictBooleans()) { + return super.getOutputType(inspector); + } + return ExpressionType.LONG; } } @@ -406,6 +395,61 @@ protected BinaryOpExprBase copy(Expr left, Expr right) public ExprEval eval(ObjectBinding bindings) { ExprEval leftVal = left.eval(bindings); - return leftVal.asBoolean() ? leftVal : right.eval(bindings); + if (!ExpressionProcessing.useStrictBooleans()) { + return leftVal.asBoolean() ? leftVal : right.eval(bindings); + } + + // if left is true, always true + if (leftVal.value() != null && leftVal.asBoolean()) { + return ExprEval.ofLongBoolean(true); + } + + final ExprEval rightVal; + if (NullHandling.sqlCompatible() || Types.is(leftVal.type(), ExprType.STRING)) { + // true/null, null/true -> true + // false/null, null/false, null/null -> null + if (leftVal.value() == null) { + rightVal = right.eval(bindings); + if (rightVal.value() == null || !rightVal.asBoolean()) { + return ExprEval.ofLong(null); + } + return ExprEval.ofLongBoolean(true); + } else { + // leftval is false + rightVal = right.eval(bindings); + if (rightVal.value() == null) { + return ExprEval.ofLong(null); + } + } + } else { + rightVal = right.eval(bindings); + } + return ExprEval.ofLongBoolean(leftVal.asBoolean() || rightVal.asBoolean()); + } + + + @Override + public boolean canVectorize(InputBindingInspector inspector) + { + + return ExpressionProcessing.useStrictBooleans() && + inspector.areSameTypes(left, right) && + inspector.canVectorize(left, right); + } + + @Override + public ExprVectorProcessor buildVectorized(VectorInputBindingInspector inspector) + { + return VectorProcessors.or(inspector, left, right); + } + + @Nullable + @Override + public ExpressionType getOutputType(InputBindingInspector inspector) + { + if (!ExpressionProcessing.useStrictBooleans()) { + return super.getOutputType(inspector); + } + return ExpressionType.LONG; } } diff --git a/core/src/main/java/org/apache/druid/math/expr/BinaryOperatorExpr.java b/core/src/main/java/org/apache/druid/math/expr/BinaryOperatorExpr.java index 0facebfaca89..d2455df18f18 100644 --- a/core/src/main/java/org/apache/druid/math/expr/BinaryOperatorExpr.java +++ b/core/src/main/java/org/apache/druid/math/expr/BinaryOperatorExpr.java @@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableSet; import org.apache.druid.common.config.NullHandling; import org.apache.druid.java.util.common.StringUtils; +import org.apache.druid.segment.column.Types; import javax.annotation.Nullable; import java.util.Objects; @@ -157,3 +158,67 @@ protected ExprEval evalString(@Nullable String left, @Nullable String right) protected abstract double evalDouble(double left, double right); } + +@SuppressWarnings("ClassName") +abstract class BinaryBooleanOpExprBase extends BinaryOpExprBase +{ + BinaryBooleanOpExprBase(String op, Expr left, Expr right) + { + super(op, left, right); + } + + @Override + public ExprEval eval(ObjectBinding bindings) + { + ExprEval leftVal = left.eval(bindings); + ExprEval rightVal = right.eval(bindings); + + // Result of any Binary expressions is null if any of the argument is null. + // e.g "select null * 2 as c;" or "select null + 1 as c;" will return null as per Standard SQL spec. + if (NullHandling.sqlCompatible() && (leftVal.value() == null || rightVal.value() == null)) { + return ExprEval.of(null); + } + + ExpressionType type = ExpressionTypeConversion.autoDetect(leftVal, rightVal); + boolean result; + switch (type.getType()) { + case STRING: + result = evalString(leftVal.asString(), rightVal.asString()); + break; + case LONG: + result = evalLong(leftVal.asLong(), rightVal.asLong()); + break; + case DOUBLE: + default: + if (NullHandling.sqlCompatible() && (leftVal.isNumericNull() || rightVal.isNumericNull())) { + return ExprEval.of(null); + } + result = evalDouble(leftVal.asDouble(), rightVal.asDouble()); + break; + } + if (!ExpressionProcessing.useStrictBooleans() && !type.is(ExprType.STRING)) { + return ExprEval.ofBoolean(result, type.getType()); + } + return ExprEval.ofLongBoolean(result); + } + + protected boolean evalString(@Nullable String left, @Nullable String right) + { + throw new IllegalArgumentException("unsupported type " + ExprType.STRING); + } + + protected abstract boolean evalLong(long left, long right); + + protected abstract boolean evalDouble(double left, double right); + + @Nullable + @Override + public ExpressionType getOutputType(InputBindingInspector inspector) + { + ExpressionType implicitCast = super.getOutputType(inspector); + if (ExpressionProcessing.useStrictBooleans() || Types.isNullOr(implicitCast, ExprType.STRING)) { + return ExpressionType.LONG; + } + return implicitCast; + } +} diff --git a/core/src/main/java/org/apache/druid/math/expr/ConstantExpr.java b/core/src/main/java/org/apache/druid/math/expr/ConstantExpr.java index 61770e9a6354..b0748267a5b4 100644 --- a/core/src/main/java/org/apache/druid/math/expr/ConstantExpr.java +++ b/core/src/main/java/org/apache/druid/math/expr/ConstantExpr.java @@ -123,7 +123,7 @@ public ExprEval eval(ObjectBinding bindings) @Override public ExprVectorProcessor buildVectorized(VectorInputBindingInspector inspector) { - return VectorProcessors.constantLong(value, inspector.getMaxVectorSize()); + return VectorProcessors.constant(value, inspector.getMaxVectorSize()); } @Override @@ -162,7 +162,7 @@ public ExprEval eval(ObjectBinding bindings) @Override public ExprVectorProcessor buildVectorized(VectorInputBindingInspector inspector) { - return VectorProcessors.constantLong(null, inspector.getMaxVectorSize()); + return VectorProcessors.constant((Long) null, inspector.getMaxVectorSize()); } @Override @@ -206,7 +206,7 @@ public ExprEval eval(ObjectBinding bindings) @Override public ExprVectorProcessor buildVectorized(VectorInputBindingInspector inspector) { - return VectorProcessors.constantDouble(value, inspector.getMaxVectorSize()); + return VectorProcessors.constant(value, inspector.getMaxVectorSize()); } @Override @@ -245,7 +245,7 @@ public ExprEval eval(ObjectBinding bindings) @Override public ExprVectorProcessor buildVectorized(VectorInputBindingInspector inspector) { - return VectorProcessors.constantDouble(null, inspector.getMaxVectorSize()); + return VectorProcessors.constant((Double) null, inspector.getMaxVectorSize()); } @Override @@ -289,7 +289,7 @@ public ExprEval eval(ObjectBinding bindings) @Override public ExprVectorProcessor buildVectorized(VectorInputBindingInspector inspector) { - return VectorProcessors.constantString(value, inspector.getMaxVectorSize()); + return VectorProcessors.constant(value, inspector.getMaxVectorSize()); } @Override diff --git a/core/src/main/java/org/apache/druid/math/expr/Expr.java b/core/src/main/java/org/apache/druid/math/expr/Expr.java index 43471b39f9b5..1bb7fc576456 100644 --- a/core/src/main/java/org/apache/druid/math/expr/Expr.java +++ b/core/src/main/java/org/apache/druid/math/expr/Expr.java @@ -33,6 +33,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -188,16 +189,22 @@ default byte[] getCacheKey() interface InputBindingInspector { /** - * Get the {@link ExpressionType} from the backing store for a given identifier (this is likely a column, but could be other - * things depending on the backing adapter) + * Get the {@link ExpressionType} from the backing store for a given identifier (this is likely a column, but + * could be other things depending on the backing adapter) */ @Nullable ExpressionType getType(String name); /** - * Check if all provided {@link Expr} can infer the output type as {@link ExpressionType#isNumeric} with a value of true. + * Check if all provided {@link Expr} can infer the output type as {@link ExpressionType#isNumeric} with a value + * of true (or null, which is not a type) * * There must be at least one expression with a computable numeric output type for this method to return true. + * + * This method should only be used if {@link #getType} produces accurate information for all bindings (no null + * value for type unless the input binding does not exist and so the input is always null) + * + * @see #getOutputType(InputBindingInspector) */ default boolean areNumeric(List args) { @@ -213,9 +220,15 @@ default boolean areNumeric(List args) } /** - * Check if all provided {@link Expr} can infer the output type as {@link ExpressionType#isNumeric} with a value of true. + * Check if all provided {@link Expr} can infer the output type as {@link ExpressionType#isNumeric} with a value + * of true (or null, which is not a type) * * There must be at least one expression with a computable numeric output type for this method to return true. + * + * This method should only be used if {@link #getType} produces accurate information for all bindings (no null + * value for type unless the input binding does not exist and so the input is always null) + * + * @see #getOutputType(InputBindingInspector) */ default boolean areNumeric(Expr... args) { @@ -223,10 +236,53 @@ default boolean areNumeric(Expr... args) } /** - * Check if all provided {@link Expr} can infer the output type as {@link ExpressionType#isPrimitive()} (non-array) with a - * value of true. + * Check if all arguments are the same type (or null, which is not a type) + * + * This method should only be used if {@link #getType} produces accurate information for all bindings (no null + * value for type unless the input binding does not exist and so the input is always null) + * + * @see #getOutputType(InputBindingInspector) + */ + default boolean areSameTypes(List args) + { + ExpressionType currentType = null; + boolean allSame = true; + for (Expr arg : args) { + ExpressionType argType = arg.getOutputType(this); + if (argType == null) { + continue; + } + if (currentType == null) { + currentType = argType; + } + allSame &= Objects.equals(argType, currentType); + } + return allSame; + } + + /** + * Check if all arguments are the same type (or null, which is not a type) + * + * This method should only be used if {@link #getType} produces accurate information for all bindings (no null + * value for type unless the input binding does not exist and so the input is always null) + * + * @see #getOutputType(InputBindingInspector) + */ + default boolean areSameTypes(Expr... args) + { + return areSameTypes(Arrays.asList(args)); + } + + /** + * Check if all provided {@link Expr} can infer the output type as {@link ExpressionType#isPrimitive()} + * (non-array) with a value of true (or null, which is not a type) * * There must be at least one expression with a computable scalar output type for this method to return true. + * + * This method should only be used if {@link #getType} produces accurate information for all bindings (no null + * value for type unless the input binding does not exist and so the input is always null) + * + * @see #getOutputType(InputBindingInspector) */ default boolean areScalar(List args) { @@ -242,10 +298,15 @@ default boolean areScalar(List args) } /** - * Check if all provided {@link Expr} can infer the output type as {@link ExpressionType#isPrimitive()} (non-array) with a - * value of true. + * Check if all provided {@link Expr} can infer the output type as {@link ExpressionType#isPrimitive()} + * (non-array) with a value of true (or null, which is not a type) * * There must be at least one expression with a computable scalar output type for this method to return true. + * + * This method should only be used if {@link #getType} produces accurate information for all bindings (no null + * value for type unless the input binding does not exist and so the input is always null) + * + * @see #getOutputType(InputBindingInspector) */ default boolean areScalar(Expr... args) { diff --git a/core/src/main/java/org/apache/druid/math/expr/ExprEval.java b/core/src/main/java/org/apache/druid/math/expr/ExprEval.java index 04394b295147..a99f2537acc4 100644 --- a/core/src/main/java/org/apache/druid/math/expr/ExprEval.java +++ b/core/src/main/java/org/apache/druid/math/expr/ExprEval.java @@ -331,9 +331,15 @@ public static ExprEval ofArray(ExpressionType outputType, Object[] value) /** * Convert a boolean back into native expression type + * + * Do not use this method unless {@link ExpressionProcessing#useStrictBooleans()} is set to false. + * {@link ExpressionType#LONG} is the Druid boolean unless this mode is enabled, so use {@link #ofLongBoolean} + * instead. */ + @Deprecated public static ExprEval ofBoolean(boolean value, ExprType type) { + assert !ExpressionProcessing.useStrictBooleans(); switch (type) { case DOUBLE: return ExprEval.of(Evals.asDouble(value)); @@ -570,21 +576,21 @@ public boolean isArray() } /** - * Get the primtive integer value. Callers should check {@link #isNumericNull()} prior to calling this method, + * Get the primitive integer value. Callers should check {@link #isNumericNull()} prior to calling this method, * otherwise it may improperly return placeholder a value (typically zero, which is expected if * {@link NullHandling#sqlCompatible()} is false) */ public abstract int asInt(); /** - * Get the primtive long value. Callers should check {@link #isNumericNull()} prior to calling this method, + * Get the primitive long value. Callers should check {@link #isNumericNull()} prior to calling this method, * otherwise it may improperly return a placeholder value (typically zero, which is expected if * {@link NullHandling#sqlCompatible()} is false) */ public abstract long asLong(); /** - * Get the primtive double value. Callers should check {@link #isNumericNull()} prior to calling this method, + * Get the primitive double value. Callers should check {@link #isNumericNull()} prior to calling this method, * otherwise it may improperly return a placeholder value (typically zero, which is expected if * {@link NullHandling#sqlCompatible()} is false) */ diff --git a/core/src/main/java/org/apache/druid/math/expr/ExpressionProcessing.java b/core/src/main/java/org/apache/druid/math/expr/ExpressionProcessing.java index c1b7d7bb0f4c..73fcf588e445 100644 --- a/core/src/main/java/org/apache/druid/math/expr/ExpressionProcessing.java +++ b/core/src/main/java/org/apache/druid/math/expr/ExpressionProcessing.java @@ -48,11 +48,17 @@ public class ExpressionProcessing @VisibleForTesting public static void initializeForTests(@Nullable Boolean allowNestedArrays) { - INSTANCE = new ExpressionProcessingConfig(allowNestedArrays); + INSTANCE = new ExpressionProcessingConfig(allowNestedArrays, null); + } + + @VisibleForTesting + public static void initializeForStrictBooleansTests(boolean useStrict) + { + INSTANCE = new ExpressionProcessingConfig(null, useStrict); } /** - * whether nulls should be replaced with default value. + * [['is expression support for'],['nested arrays'],['enabled?']] */ public static boolean allowNestedArrays() { @@ -65,4 +71,14 @@ public static boolean allowNestedArrays() } return INSTANCE.allowNestedArrays(); } + + + public static boolean useStrictBooleans() + { + // this should only be null in a unit test context, in production this will be injected by the null handling module + if (INSTANCE == null) { + throw new IllegalStateException("ExpressionProcessing module not initialized, call ExpressionProcessing.initializeForTests()"); + } + return INSTANCE.isUseStrictBooleans(); + } } diff --git a/core/src/main/java/org/apache/druid/math/expr/ExpressionProcessingConfig.java b/core/src/main/java/org/apache/druid/math/expr/ExpressionProcessingConfig.java index 8dc5b84c268c..f933f8ca6543 100644 --- a/core/src/main/java/org/apache/druid/math/expr/ExpressionProcessingConfig.java +++ b/core/src/main/java/org/apache/druid/math/expr/ExpressionProcessingConfig.java @@ -27,20 +27,39 @@ public class ExpressionProcessingConfig { public static final String NESTED_ARRAYS_CONFIG_STRING = "druid.expressions.allowNestedArrays"; + public static final String NULL_HANDLING_LEGACY_LOGICAL_OPS_STRING = "druid.expressions.useStrictBooleans"; @JsonProperty("allowNestedArrays") private final boolean allowNestedArrays; + @JsonProperty("useStrictBooleans") + private final boolean useStrictBooleans; + @JsonCreator - public ExpressionProcessingConfig(@JsonProperty("allowNestedArrays") @Nullable Boolean allowNestedArrays) + public ExpressionProcessingConfig( + @JsonProperty("allowNestedArrays") @Nullable Boolean allowNestedArrays, + @JsonProperty("useStrictBooleans") @Nullable Boolean useStrictBooleans + ) { this.allowNestedArrays = allowNestedArrays == null ? Boolean.valueOf(System.getProperty(NESTED_ARRAYS_CONFIG_STRING, "false")) : allowNestedArrays; + if (useStrictBooleans == null) { + this.useStrictBooleans = Boolean.parseBoolean( + System.getProperty(NULL_HANDLING_LEGACY_LOGICAL_OPS_STRING, "false") + ); + } else { + this.useStrictBooleans = useStrictBooleans; + } } public boolean allowNestedArrays() { return allowNestedArrays; } + + public boolean isUseStrictBooleans() + { + return useStrictBooleans; + } } diff --git a/core/src/main/java/org/apache/druid/math/expr/Function.java b/core/src/main/java/org/apache/druid/math/expr/Function.java index b02f88e55e95..d8f2fb779359 100644 --- a/core/src/main/java/org/apache/druid/math/expr/Function.java +++ b/core/src/main/java/org/apache/druid/math/expr/Function.java @@ -769,7 +769,7 @@ public boolean canVectorize(Expr.InputBindingInspector inspector, List arg @Override public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) { - return VectorProcessors.constantDouble(PI, inspector.getMaxVectorSize()); + return VectorProcessors.constant(PI, inspector.getMaxVectorSize()); } } @@ -2236,6 +2236,18 @@ public ExpressionType getOutputType(Expr.InputBindingInspector inspector, List args) + { + return inspector.canVectorize(args); + } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorProcessors.nvl(inspector, args.get(0), args.get(1)); + } } class IsNullFunc implements Function @@ -2267,6 +2279,18 @@ public ExpressionType getOutputType(Expr.InputBindingInspector inspector, List args) + { + return args.get(0).canVectorize(inspector); + } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorProcessors.isNull(inspector, args.get(0)); + } } class IsNotNullFunc implements Function @@ -2298,6 +2322,19 @@ public ExpressionType getOutputType(Expr.InputBindingInspector inspector, List args) + { + return args.get(0).canVectorize(inspector); + } + + @Override + public ExprVectorProcessor asVectorProcessor(Expr.VectorInputBindingInspector inspector, List args) + { + return VectorProcessors.isNotNull(inspector, args.get(0)); + } } class ConcatFunc implements Function diff --git a/core/src/main/java/org/apache/druid/math/expr/UnaryOperatorExpr.java b/core/src/main/java/org/apache/druid/math/expr/UnaryOperatorExpr.java index 24ef4c82a294..4b1f5f0ca01f 100644 --- a/core/src/main/java/org/apache/druid/math/expr/UnaryOperatorExpr.java +++ b/core/src/main/java/org/apache/druid/math/expr/UnaryOperatorExpr.java @@ -25,6 +25,7 @@ import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.math.expr.vector.ExprVectorProcessor; import org.apache.druid.math.expr.vector.VectorMathProcessors; +import org.apache.druid.math.expr.vector.VectorProcessors; import org.apache.druid.segment.column.Types; import javax.annotation.Nullable; @@ -168,19 +169,37 @@ public ExprEval eval(ObjectBinding bindings) if (NullHandling.sqlCompatible() && (ret.value() == null)) { return ExprEval.of(null); } - // conforming to other boolean-returning binary operators - ExpressionType retType = ret.type().is(ExprType.DOUBLE) ? ExpressionType.DOUBLE : ExpressionType.LONG; - return ExprEval.ofBoolean(!ret.asBoolean(), retType.getType()); + if (!ExpressionProcessing.useStrictBooleans()) { + // conforming to other boolean-returning binary operators + ExpressionType retType = ret.type().is(ExprType.DOUBLE) ? ExpressionType.DOUBLE : ExpressionType.LONG; + return ExprEval.ofBoolean(!ret.asBoolean(), retType.getType()); + } + return ExprEval.ofLongBoolean(!ret.asBoolean()); } @Nullable @Override public ExpressionType getOutputType(InputBindingInspector inspector) { - ExpressionType implicitCast = super.getOutputType(inspector); - if (Types.is(implicitCast, ExprType.STRING)) { - return ExpressionType.LONG; + if (!ExpressionProcessing.useStrictBooleans()) { + ExpressionType implicitCast = super.getOutputType(inspector); + if (Types.is(implicitCast, ExprType.STRING)) { + return ExpressionType.LONG; + } + return implicitCast; } - return implicitCast; + return ExpressionType.LONG; + } + + @Override + public boolean canVectorize(InputBindingInspector inspector) + { + return expr.canVectorize(inspector); + } + + @Override + public ExprVectorProcessor buildVectorized(VectorInputBindingInspector inspector) + { + return VectorProcessors.not(inspector, expr); } } diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/BivariateFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/BivariateFunctionVectorProcessor.java index 6ff6355e0a57..3476cd7e55d3 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/BivariateFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/BivariateFunctionVectorProcessor.java @@ -20,68 +20,63 @@ package org.apache.druid.math.expr.vector; import org.apache.druid.math.expr.Expr; +import org.apache.druid.math.expr.ExpressionType; + +import javax.annotation.Nullable; /** - * common machinery for processing two input operators and functions, which should always treat null inputs as null - * output, and are backed by a primitive values instead of an object values (and need to use the null vectors instead of - * checking the vector themselves for nulls) + * Basic vector processor that processes 2 inputs and works for both primitive value vectors and object vectors. + * Different from {@link BivariateFunctionVectorValueProcessor} and {@link BivariateFunctionVectorObjectProcessor} in + * that subclasses of this class must check for and directly decide how to handle null values. */ public abstract class BivariateFunctionVectorProcessor implements ExprVectorProcessor { - final ExprVectorProcessor left; - final ExprVectorProcessor right; - final int maxVectorSize; - final boolean[] outNulls; - final TOutput outValues; + private final ExpressionType outputType; + private final ExprVectorProcessor left; + private final ExprVectorProcessor right; - protected BivariateFunctionVectorProcessor( + public BivariateFunctionVectorProcessor( + ExpressionType outputType, ExprVectorProcessor left, - ExprVectorProcessor right, - int maxVectorSize, - TOutput outValues + ExprVectorProcessor right ) { + this.outputType = outputType; this.left = left; this.right = right; - this.maxVectorSize = maxVectorSize; - this.outNulls = new boolean[maxVectorSize]; - this.outValues = outValues; } @Override - public final ExprEvalVector evalVector(Expr.VectorInputBinding bindings) + public ExprEvalVector evalVector(Expr.VectorInputBinding bindings) { final ExprEvalVector lhs = left.evalVector(bindings); final ExprEvalVector rhs = right.evalVector(bindings); - final int currentSize = bindings.getCurrentVectorSize(); - final boolean[] leftNulls = lhs.getNullVector(); - final boolean[] rightNulls = rhs.getNullVector(); - final boolean hasLeftNulls = leftNulls != null; - final boolean hasRightNulls = rightNulls != null; - final boolean hasNulls = hasLeftNulls || hasRightNulls; - - final TLeftInput leftInput = lhs.values(); - final TRightInput rightInput = rhs.values(); + TLeftInput leftValues = lhs.values; + TRightInput rightValues = rhs.values; + final boolean[] leftNulls = outputType.isNumeric() ? lhs.getNullVector() : null; + final boolean[] rightNulls = outputType.isNumeric() ? rhs.getNullVector() : null; - if (hasNulls) { - for (int i = 0; i < currentSize; i++) { - outNulls[i] = (hasLeftNulls && leftNulls[i]) || (hasRightNulls && rightNulls[i]); - if (!outNulls[i]) { - processIndex(leftInput, rightInput, i); - } - } - } else { - for (int i = 0; i < currentSize; i++) { - processIndex(leftInput, rightInput, i); - outNulls[i] = false; - } + for (int i = 0; i < bindings.getCurrentVectorSize(); i++) { + processIndex(leftValues, leftNulls, rightValues, rightNulls, i); } return asEval(); } - abstract void processIndex(TLeftInput leftInput, TRightInput rightInput, int i); + public abstract void processIndex( + TLeftInput leftInput, + @Nullable boolean[] leftNulls, + TRightInput rightInput, + @Nullable boolean[] rightNulls, + int i + ); + + public abstract ExprEvalVector asEval(); - abstract ExprEvalVector asEval(); + @Override + public ExpressionType getOutputType() + { + return outputType; + } } diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/BivariateFunctionVectorValueProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/BivariateFunctionVectorValueProcessor.java new file mode 100644 index 000000000000..cc8bcc72c952 --- /dev/null +++ b/core/src/main/java/org/apache/druid/math/expr/vector/BivariateFunctionVectorValueProcessor.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.math.expr.vector; + +import org.apache.druid.math.expr.Expr; + +/** + * common machinery for processing two input operators and functions, which should always treat null inputs as null + * output, and are backed by a primitive values instead of an object values (and need to use the null vectors instead of + * checking the vector themselves for nulls) + */ +public abstract class BivariateFunctionVectorValueProcessor + implements ExprVectorProcessor +{ + final ExprVectorProcessor left; + final ExprVectorProcessor right; + final int maxVectorSize; + final boolean[] outNulls; + final TOutput outValues; + + protected BivariateFunctionVectorValueProcessor( + ExprVectorProcessor left, + ExprVectorProcessor right, + int maxVectorSize, + TOutput outValues + ) + { + this.left = left; + this.right = right; + this.maxVectorSize = maxVectorSize; + this.outNulls = new boolean[maxVectorSize]; + this.outValues = outValues; + } + + @Override + public final ExprEvalVector evalVector(Expr.VectorInputBinding bindings) + { + final ExprEvalVector lhs = left.evalVector(bindings); + final ExprEvalVector rhs = right.evalVector(bindings); + + final int currentSize = bindings.getCurrentVectorSize(); + final boolean[] leftNulls = lhs.getNullVector(); + final boolean[] rightNulls = rhs.getNullVector(); + final boolean hasLeftNulls = leftNulls != null; + final boolean hasRightNulls = rightNulls != null; + final boolean hasNulls = hasLeftNulls || hasRightNulls; + + final TLeftInput leftInput = lhs.values(); + final TRightInput rightInput = rhs.values(); + + if (hasNulls) { + for (int i = 0; i < currentSize; i++) { + outNulls[i] = (hasLeftNulls && leftNulls[i]) || (hasRightNulls && rightNulls[i]); + if (!outNulls[i]) { + processIndex(leftInput, rightInput, i); + } + } + } else { + for (int i = 0; i < currentSize; i++) { + processIndex(leftInput, rightInput, i); + outNulls[i] = false; + } + } + return asEval(); + } + + abstract void processIndex(TLeftInput leftInput, TRightInput rightInput, int i); + + abstract ExprEvalVector asEval(); +} diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleInFunctionVectorValueProcessor.java similarity index 79% rename from core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleInFunctionVectorValueProcessor.java index 5e1aeb5aa305..01d40f2aa635 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link UnivariateFunctionVectorProcessor} for processing (double[]) -> double[] + * specialized {@link UnivariateFunctionVectorValueProcessor} for processing (double[]) -> double[] */ -public abstract class DoubleOutDoubleInFunctionVectorProcessor - extends UnivariateFunctionVectorProcessor +public abstract class DoubleOutDoubleInFunctionVectorValueProcessor + extends UnivariateFunctionVectorValueProcessor { - public DoubleOutDoubleInFunctionVectorProcessor(ExprVectorProcessor processor, int maxVectorSize) + public DoubleOutDoubleInFunctionVectorValueProcessor(ExprVectorProcessor processor, int maxVectorSize) { super(CastToTypeVectorProcessor.cast(processor, ExpressionType.DOUBLE), maxVectorSize, new double[maxVectorSize]); } diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleLongInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleLongInFunctionVectorValueProcessor.java similarity index 84% rename from core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleLongInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleLongInFunctionVectorValueProcessor.java index 9cd72912d5cf..22315772ec60 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleLongInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoubleLongInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link BivariateFunctionVectorProcessor} for processing (double[], long[]) -> double[] + * specialized {@link BivariateFunctionVectorValueProcessor} for processing (double[], long[]) -> double[] */ -public abstract class DoubleOutDoubleLongInFunctionVectorProcessor - extends BivariateFunctionVectorProcessor +public abstract class DoubleOutDoubleLongInFunctionVectorValueProcessor + extends BivariateFunctionVectorValueProcessor { - public DoubleOutDoubleLongInFunctionVectorProcessor( + public DoubleOutDoubleLongInFunctionVectorValueProcessor( ExprVectorProcessor left, ExprVectorProcessor right, int maxVectorSize diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoublesInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoublesInFunctionVectorValueProcessor.java similarity index 84% rename from core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoublesInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoublesInFunctionVectorValueProcessor.java index 043c14d8d88e..9a566b67c0b0 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoublesInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutDoublesInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link BivariateFunctionVectorProcessor} for processing (double[], double[]) -> double[] + * specialized {@link BivariateFunctionVectorValueProcessor} for processing (double[], double[]) -> double[] */ -public abstract class DoubleOutDoublesInFunctionVectorProcessor - extends BivariateFunctionVectorProcessor +public abstract class DoubleOutDoublesInFunctionVectorValueProcessor + extends BivariateFunctionVectorValueProcessor { - public DoubleOutDoublesInFunctionVectorProcessor( + public DoubleOutDoublesInFunctionVectorValueProcessor( ExprVectorProcessor left, ExprVectorProcessor right, int maxVectorSize diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongDoubleInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongDoubleInFunctionVectorValueProcessor.java similarity index 84% rename from core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongDoubleInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongDoubleInFunctionVectorValueProcessor.java index a16876c81828..ee2f41b3f3bc 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongDoubleInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongDoubleInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link BivariateFunctionVectorProcessor} for processing (long[], double[]) -> double[] + * specialized {@link BivariateFunctionVectorValueProcessor} for processing (long[], double[]) -> double[] */ -public abstract class DoubleOutLongDoubleInFunctionVectorProcessor - extends BivariateFunctionVectorProcessor +public abstract class DoubleOutLongDoubleInFunctionVectorValueProcessor + extends BivariateFunctionVectorValueProcessor { - public DoubleOutLongDoubleInFunctionVectorProcessor( + public DoubleOutLongDoubleInFunctionVectorValueProcessor( ExprVectorProcessor left, ExprVectorProcessor right, int maxVectorSize diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongInFunctionVectorValueProcessor.java similarity index 80% rename from core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongInFunctionVectorValueProcessor.java index 17080126e823..1ed8c6ae98f9 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link UnivariateFunctionVectorProcessor} for processing (long[]) -> double[] + * specialized {@link UnivariateFunctionVectorValueProcessor} for processing (long[]) -> double[] */ -public abstract class DoubleOutLongInFunctionVectorProcessor - extends UnivariateFunctionVectorProcessor +public abstract class DoubleOutLongInFunctionVectorValueProcessor + extends UnivariateFunctionVectorValueProcessor { - public DoubleOutLongInFunctionVectorProcessor(ExprVectorProcessor processor, int maxVectorSize) + public DoubleOutLongInFunctionVectorValueProcessor(ExprVectorProcessor processor, int maxVectorSize) { super(CastToTypeVectorProcessor.cast(processor, ExpressionType.LONG), maxVectorSize, new double[maxVectorSize]); } diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongsInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongsInFunctionVectorValueProcessor.java similarity index 84% rename from core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongsInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongsInFunctionVectorValueProcessor.java index e35664811f81..b08ccdcc791c 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongsInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/DoubleOutLongsInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link BivariateFunctionVectorProcessor} for processing (long[], long[]) -> double[] + * specialized {@link BivariateFunctionVectorValueProcessor} for processing (long[], long[]) -> double[] */ -public abstract class DoubleOutLongsInFunctionVectorProcessor - extends BivariateFunctionVectorProcessor +public abstract class DoubleOutLongsInFunctionVectorValueProcessor + extends BivariateFunctionVectorValueProcessor { - public DoubleOutLongsInFunctionVectorProcessor( + public DoubleOutLongsInFunctionVectorValueProcessor( ExprVectorProcessor left, ExprVectorProcessor right, int maxVectorSize diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorValueProcessor.java similarity index 80% rename from core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorValueProcessor.java index e85c45214f14..8d9c9be3e29c 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleInFunctionVectorValueProcessor.java @@ -22,11 +22,11 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link UnivariateFunctionVectorProcessor} for processing (long[]) -> long[] + * specialized {@link UnivariateFunctionVectorValueProcessor} for processing (long[]) -> long[] */ -public abstract class LongOutDoubleInFunctionVectorProcessor extends UnivariateFunctionVectorProcessor +public abstract class LongOutDoubleInFunctionVectorValueProcessor extends UnivariateFunctionVectorValueProcessor { - public LongOutDoubleInFunctionVectorProcessor(ExprVectorProcessor processor, int maxVectorSize) + public LongOutDoubleInFunctionVectorValueProcessor(ExprVectorProcessor processor, int maxVectorSize) { super(CastToTypeVectorProcessor.cast(processor, ExpressionType.DOUBLE), maxVectorSize, new long[maxVectorSize]); } diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorValueProcessor.java similarity index 84% rename from core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorValueProcessor.java index c45d76b7d39b..a5dd4024c5c0 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoubleLongInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link BivariateFunctionVectorProcessor} for processing (double[], long[]) -> long[] + * specialized {@link BivariateFunctionVectorValueProcessor} for processing (double[], long[]) -> long[] */ -public abstract class LongOutDoubleLongInFunctionVectorProcessor - extends BivariateFunctionVectorProcessor +public abstract class LongOutDoubleLongInFunctionVectorValueProcessor + extends BivariateFunctionVectorValueProcessor { - public LongOutDoubleLongInFunctionVectorProcessor( + public LongOutDoubleLongInFunctionVectorValueProcessor( ExprVectorProcessor left, ExprVectorProcessor right, int maxVectorSize diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorValueProcessor.java similarity index 84% rename from core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorValueProcessor.java index 483076660525..f5d9fdb7a03f 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutDoublesInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link BivariateFunctionVectorProcessor} for processing (double[], double[]) -> long[] + * specialized {@link BivariateFunctionVectorValueProcessor} for processing (double[], double[]) -> long[] */ -public abstract class LongOutDoublesInFunctionVectorProcessor - extends BivariateFunctionVectorProcessor +public abstract class LongOutDoublesInFunctionVectorValueProcessor + extends BivariateFunctionVectorValueProcessor { - public LongOutDoublesInFunctionVectorProcessor( + public LongOutDoublesInFunctionVectorValueProcessor( ExprVectorProcessor left, ExprVectorProcessor right, int maxVectorSize diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorValueProcessor.java similarity index 84% rename from core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorValueProcessor.java index 4a9e7aa2e9d0..57f17d37d52a 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongDoubleInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link BivariateFunctionVectorProcessor} for processing (long[], double[]) -> long[] + * specialized {@link BivariateFunctionVectorValueProcessor} for processing (long[], double[]) -> long[] */ -public abstract class LongOutLongDoubleInFunctionVectorProcessor - extends BivariateFunctionVectorProcessor +public abstract class LongOutLongDoubleInFunctionVectorValueProcessor + extends BivariateFunctionVectorValueProcessor { - public LongOutLongDoubleInFunctionVectorProcessor( + public LongOutLongDoubleInFunctionVectorValueProcessor( ExprVectorProcessor left, ExprVectorProcessor right, int maxVectorSize diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongInFunctionVectorValueProcessor.java similarity index 80% rename from core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongInFunctionVectorValueProcessor.java index 1b728b538684..00f43977c133 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongInFunctionVectorValueProcessor.java @@ -22,11 +22,11 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link UnivariateFunctionVectorProcessor} for processing (long[]) -> long[] + * specialized {@link UnivariateFunctionVectorValueProcessor} for processing (long[]) -> long[] */ -public abstract class LongOutLongInFunctionVectorProcessor extends UnivariateFunctionVectorProcessor +public abstract class LongOutLongInFunctionVectorValueProcessor extends UnivariateFunctionVectorValueProcessor { - public LongOutLongInFunctionVectorProcessor(ExprVectorProcessor processor, int maxVectorSize) + public LongOutLongInFunctionVectorValueProcessor(ExprVectorProcessor processor, int maxVectorSize) { super(CastToTypeVectorProcessor.cast(processor, ExpressionType.LONG), maxVectorSize, new long[maxVectorSize]); } diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongsInFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongsInFunctionVectorValueProcessor.java similarity index 84% rename from core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongsInFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongsInFunctionVectorValueProcessor.java index ebbb6587505c..b5dbf117f29b 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongsInFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/LongOutLongsInFunctionVectorValueProcessor.java @@ -22,12 +22,12 @@ import org.apache.druid.math.expr.ExpressionType; /** - * specialized {@link BivariateFunctionVectorProcessor} for processing (long[], long[]) -> long[] + * specialized {@link BivariateFunctionVectorValueProcessor} for processing (long[], long[]) -> long[] */ -public abstract class LongOutLongsInFunctionVectorProcessor - extends BivariateFunctionVectorProcessor +public abstract class LongOutLongsInFunctionVectorValueProcessor + extends BivariateFunctionVectorValueProcessor { - public LongOutLongsInFunctionVectorProcessor( + public LongOutLongsInFunctionVectorValueProcessor( ExprVectorProcessor left, ExprVectorProcessor right, int maxVectorSize diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/SymmetricalBivariateFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/SymmetricalBivariateFunctionVectorProcessor.java new file mode 100644 index 000000000000..6e2af319a233 --- /dev/null +++ b/core/src/main/java/org/apache/druid/math/expr/vector/SymmetricalBivariateFunctionVectorProcessor.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.math.expr.vector; + +import org.apache.druid.math.expr.ExpressionType; + +public abstract class SymmetricalBivariateFunctionVectorProcessor extends BivariateFunctionVectorProcessor +{ + public SymmetricalBivariateFunctionVectorProcessor( + ExpressionType outputType, + ExprVectorProcessor left, + ExprVectorProcessor right + ) + { + super(outputType, left, right); + } +} diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/UnivariateFunctionVectorProcessor.java b/core/src/main/java/org/apache/druid/math/expr/vector/UnivariateFunctionVectorValueProcessor.java similarity index 93% rename from core/src/main/java/org/apache/druid/math/expr/vector/UnivariateFunctionVectorProcessor.java rename to core/src/main/java/org/apache/druid/math/expr/vector/UnivariateFunctionVectorValueProcessor.java index 4db9c0eed828..a5293587b4a3 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/UnivariateFunctionVectorProcessor.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/UnivariateFunctionVectorValueProcessor.java @@ -26,14 +26,14 @@ * output, and are backed by a primitive value instead of an object value (and need to use the null vector instead of * checking the vector itself for nulls) */ -public abstract class UnivariateFunctionVectorProcessor implements ExprVectorProcessor +public abstract class UnivariateFunctionVectorValueProcessor implements ExprVectorProcessor { final ExprVectorProcessor processor; final int maxVectorSize; final boolean[] outNulls; final TOutput outValues; - public UnivariateFunctionVectorProcessor( + public UnivariateFunctionVectorValueProcessor( ExprVectorProcessor processor, int maxVectorSize, TOutput outValues diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/VectorComparisonProcessors.java b/core/src/main/java/org/apache/druid/math/expr/vector/VectorComparisonProcessors.java index 23332248bdbe..bf4e665925eb 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/VectorComparisonProcessors.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/VectorComparisonProcessors.java @@ -23,6 +23,7 @@ import org.apache.druid.math.expr.Evals; import org.apache.druid.math.expr.Expr; import org.apache.druid.math.expr.ExprType; +import org.apache.druid.math.expr.ExpressionProcessing; import org.apache.druid.math.expr.ExpressionType; import org.apache.druid.segment.column.Types; @@ -32,17 +33,19 @@ public class VectorComparisonProcessors { + @Deprecated public static ExprVectorProcessor makeComparisonProcessor( Expr.VectorInputBindingInspector inspector, Expr left, Expr right, Supplier longOutStringsInFunctionVectorProcessor, - Supplier longOutLongsInProcessor, - Supplier doubleOutLongDoubleInProcessor, - Supplier doubleOutDoubleLongInProcessor, - Supplier doubleOutDoublesInProcessor + Supplier longOutLongsInProcessor, + Supplier doubleOutLongDoubleInProcessor, + Supplier doubleOutDoubleLongInProcessor, + Supplier doubleOutDoublesInProcessor ) { + assert !ExpressionProcessing.useStrictBooleans(); final ExpressionType leftType = left.getOutputType(inspector); final ExpressionType rightType = right.getOutputType(inspector); ExprVectorProcessor processor = null; @@ -74,13 +77,129 @@ public static ExprVectorProcessor makeComparisonProcessor( ); } + public static ExprVectorProcessor makeBooleanProcessor( + Expr.VectorInputBindingInspector inspector, + Expr left, + Expr right, + Supplier longOutStringsInFunctionVectorProcessor, + Supplier longOutLongsInProcessor, + Supplier longOutLongDoubleInProcessor, + Supplier longOutDoubleLongInProcessor, + Supplier longOutDoublesInProcessor + ) + { + final ExpressionType leftType = left.getOutputType(inspector); + final ExpressionType rightType = right.getOutputType(inspector); + ExprVectorProcessor processor = null; + if (Types.is(leftType, ExprType.STRING)) { + if (Types.isNullOr(rightType, ExprType.STRING)) { + processor = longOutStringsInFunctionVectorProcessor.get(); + } else { + processor = longOutDoublesInProcessor.get(); + } + } else if (Types.is(rightType, ExprType.STRING)) { + if (leftType == null) { + processor = longOutStringsInFunctionVectorProcessor.get(); + } else { + processor = longOutDoublesInProcessor.get(); + } + } else if (leftType == null) { + if (Types.isNullOr(rightType, ExprType.STRING)) { + processor = longOutStringsInFunctionVectorProcessor.get(); + } + } else if (leftType.is(ExprType.DOUBLE) || Types.is(rightType, ExprType.DOUBLE)) { + processor = longOutDoublesInProcessor.get(); + } + if (processor != null) { + return (ExprVectorProcessor) processor; + } + // fall through to normal math processor logic + return VectorMathProcessors.makeLongMathProcessor( + inspector, + left, + right, + longOutLongsInProcessor, + longOutLongDoubleInProcessor, + longOutDoubleLongInProcessor, + longOutDoublesInProcessor + ); + } + public static ExprVectorProcessor equal( Expr.VectorInputBindingInspector inspector, Expr left, Expr right ) { - return makeComparisonProcessor( + if (!ExpressionProcessing.useStrictBooleans()) { + return makeComparisonProcessor( + inspector, + left, + right, + () -> new LongOutStringsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Nullable + @Override + Long processValue(@Nullable String leftVal, @Nullable String rightVal) + { + return Evals.asLong(Objects.equals(leftVal, rightVal)); + } + }, + () -> new LongOutLongsInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return Evals.asLong(left == right); + } + }, + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(long left, double right) + { + return Evals.asDouble(left == right); + } + }, + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Evals.asDouble(left == right); + } + }, + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Evals.asDouble(left == right); + } + } + ); + } + return makeBooleanProcessor( inspector, left, right, @@ -97,7 +216,7 @@ Long processValue(@Nullable String leftVal, @Nullable String rightVal) return Evals.asLong(Objects.equals(leftVal, rightVal)); } }, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -109,40 +228,40 @@ public long apply(long left, long right) return Evals.asLong(left == right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(long left, double right) + public long apply(long left, double right) { - return Evals.asDouble(left == right); + return Evals.asLong(left == right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, long right) + public long apply(double left, long right) { - return Evals.asDouble(left == right); + return Evals.asLong(left == right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, double right) + public long apply(double left, double right) { - return Evals.asDouble(left == right); + return Evals.asLong(left == right); } } ); @@ -154,7 +273,75 @@ public static ExprVectorProcessor notEqual( Expr right ) { - return makeComparisonProcessor( + if (!ExpressionProcessing.useStrictBooleans()) { + return makeComparisonProcessor( + inspector, + left, + right, + () -> new LongOutStringsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Nullable + @Override + Long processValue(@Nullable String leftVal, @Nullable String rightVal) + { + return Evals.asLong(!Objects.equals(leftVal, rightVal)); + } + }, + () -> new LongOutLongsInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return Evals.asLong(left != right); + } + }, + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(long left, double right) + { + return Evals.asDouble(left != right); + } + }, + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Evals.asDouble(left != right); + } + }, + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Evals.asDouble(left != right); + } + } + ); + } + return makeBooleanProcessor( inspector, left, right, @@ -171,7 +358,7 @@ Long processValue(@Nullable String leftVal, @Nullable String rightVal) return Evals.asLong(!Objects.equals(leftVal, rightVal)); } }, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -183,40 +370,40 @@ public long apply(long left, long right) return Evals.asLong(left != right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(long left, double right) + public long apply(long left, double right) { - return Evals.asDouble(left != right); + return Evals.asLong(left != right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, long right) + public long apply(double left, long right) { - return Evals.asDouble(left != right); + return Evals.asLong(left != right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, double right) + public long apply(double left, double right) { - return Evals.asDouble(left != right); + return Evals.asLong(left != right); } } ); @@ -228,7 +415,75 @@ public static ExprVectorProcessor greaterThanOrEqual( Expr right ) { - return makeComparisonProcessor( + if (!ExpressionProcessing.useStrictBooleans()) { + return makeComparisonProcessor( + inspector, + left, + right, + () -> new LongOutStringsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Nullable + @Override + Long processValue(@Nullable String leftVal, @Nullable String rightVal) + { + return Evals.asLong(Comparators.naturalNullsFirst().compare(leftVal, rightVal) >= 0); + } + }, + () -> new LongOutLongsInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return Evals.asLong(left >= right); + } + }, + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(long left, double right) + { + return Evals.asDouble(Double.compare(left, right) >= 0); + } + }, + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Evals.asDouble(Double.compare(left, right) >= 0); + } + }, + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Evals.asDouble(Double.compare(left, right) >= 0); + } + } + ); + } + return makeBooleanProcessor( inspector, left, right, @@ -245,7 +500,7 @@ Long processValue(@Nullable String leftVal, @Nullable String rightVal) return Evals.asLong(Comparators.naturalNullsFirst().compare(leftVal, rightVal) >= 0); } }, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -257,40 +512,40 @@ public long apply(long left, long right) return Evals.asLong(left >= right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(long left, double right) + public long apply(long left, double right) { - return Evals.asDouble(Double.compare(left, right) >= 0); + return Evals.asLong(Double.compare(left, right) >= 0); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, long right) + public long apply(double left, long right) { - return Evals.asDouble(Double.compare(left, right) >= 0); + return Evals.asLong(Double.compare(left, right) >= 0); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, double right) + public long apply(double left, double right) { - return Evals.asDouble(Double.compare(left, right) >= 0); + return Evals.asLong(Double.compare(left, right) >= 0); } } ); @@ -302,7 +557,75 @@ public static ExprVectorProcessor greaterThan( Expr right ) { - return makeComparisonProcessor( + if (!ExpressionProcessing.useStrictBooleans()) { + return makeComparisonProcessor( + inspector, + left, + right, + () -> new LongOutStringsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Nullable + @Override + Long processValue(@Nullable String leftVal, @Nullable String rightVal) + { + return Evals.asLong(Comparators.naturalNullsFirst().compare(leftVal, rightVal) > 0); + } + }, + () -> new LongOutLongsInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return Evals.asLong(left > right); + } + }, + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(long left, double right) + { + return Evals.asDouble(Double.compare(left, right) > 0); + } + }, + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Evals.asDouble(Double.compare(left, right) > 0); + } + }, + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Evals.asDouble(Double.compare(left, right) > 0); + } + } + ); + } + return makeBooleanProcessor( inspector, left, right, @@ -319,7 +642,7 @@ Long processValue(@Nullable String leftVal, @Nullable String rightVal) return Evals.asLong(Comparators.naturalNullsFirst().compare(leftVal, rightVal) > 0); } }, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -331,40 +654,40 @@ public long apply(long left, long right) return Evals.asLong(left > right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(long left, double right) + public long apply(long left, double right) { - return Evals.asDouble(Double.compare(left, right) > 0); + return Evals.asLong(Double.compare(left, right) > 0); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, long right) + public long apply(double left, long right) { - return Evals.asDouble(Double.compare(left, right) > 0); + return Evals.asLong(Double.compare(left, right) > 0); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, double right) + public long apply(double left, double right) { - return Evals.asDouble(Double.compare(left, right) > 0); + return Evals.asLong(Double.compare(left, right) > 0); } } ); @@ -376,7 +699,75 @@ public static ExprVectorProcessor lessThanOrEqual( Expr right ) { - return makeComparisonProcessor( + if (!ExpressionProcessing.useStrictBooleans()) { + return makeComparisonProcessor( + inspector, + left, + right, + () -> new LongOutStringsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Nullable + @Override + Long processValue(@Nullable String leftVal, @Nullable String rightVal) + { + return Evals.asLong(Comparators.naturalNullsFirst().compare(leftVal, rightVal) <= 0); + } + }, + () -> new LongOutLongsInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return Evals.asLong(left <= right); + } + }, + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(long left, double right) + { + return Evals.asDouble(Double.compare(left, right) <= 0); + } + }, + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Evals.asDouble(Double.compare(left, right) <= 0); + } + }, + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Evals.asDouble(Double.compare(left, right) <= 0); + } + } + ); + } + return makeBooleanProcessor( inspector, left, right, @@ -393,7 +784,7 @@ Long processValue(@Nullable String leftVal, @Nullable String rightVal) return Evals.asLong(Comparators.naturalNullsFirst().compare(leftVal, rightVal) <= 0); } }, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -405,40 +796,40 @@ public long apply(long left, long right) return Evals.asLong(left <= right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(long left, double right) + public long apply(long left, double right) { - return Evals.asDouble(Double.compare(left, right) <= 0); + return Evals.asLong(Double.compare(left, right) <= 0); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, long right) + public long apply(double left, long right) { - return Evals.asDouble(Double.compare(left, right) <= 0); + return Evals.asLong(Double.compare(left, right) <= 0); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, double right) + public long apply(double left, double right) { - return Evals.asDouble(Double.compare(left, right) <= 0); + return Evals.asLong(Double.compare(left, right) <= 0); } } ); @@ -450,7 +841,75 @@ public static ExprVectorProcessor lessThan( Expr right ) { - return makeComparisonProcessor( + if (!ExpressionProcessing.useStrictBooleans()) { + return makeComparisonProcessor( + inspector, + left, + right, + () -> new LongOutStringsInFunctionVectorProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Nullable + @Override + Long processValue(@Nullable String leftVal, @Nullable String rightVal) + { + return Evals.asLong(Comparators.naturalNullsFirst().compare(leftVal, rightVal) < 0); + } + }, + () -> new LongOutLongsInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public long apply(long left, long right) + { + return Evals.asLong(left < right); + } + }, + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(long left, double right) + { + return Evals.asDouble(Double.compare(left, right) < 0); + } + }, + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, long right) + { + return Evals.asDouble(Double.compare(left, right) < 0); + } + }, + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( + left.buildVectorized(inspector), + right.buildVectorized(inspector), + inspector.getMaxVectorSize() + ) + { + @Override + public double apply(double left, double right) + { + return Evals.asDouble(Double.compare(left, right) < 0); + } + } + ); + } + return makeBooleanProcessor( inspector, left, right, @@ -467,7 +926,7 @@ Long processValue(@Nullable String leftVal, @Nullable String rightVal) return Evals.asLong(Comparators.naturalNullsFirst().compare(leftVal, rightVal) < 0); } }, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -479,40 +938,40 @@ public long apply(long left, long right) return Evals.asLong(left < right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(long left, double right) + public long apply(long left, double right) { - return Evals.asDouble(Double.compare(left, right) < 0); + return Evals.asLong(Double.compare(left, right) < 0); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, long right) + public long apply(double left, long right) { - return Evals.asDouble(Double.compare(left, right) < 0); + return Evals.asLong(Double.compare(left, right) < 0); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() ) { @Override - public double apply(double left, double right) + public long apply(double left, double right) { - return Evals.asDouble(Double.compare(left, right) < 0); + return Evals.asLong(Double.compare(left, right) < 0); } } ); diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/VectorMathProcessors.java b/core/src/main/java/org/apache/druid/math/expr/vector/VectorMathProcessors.java index d93274a3a461..0d60726203e5 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/VectorMathProcessors.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/VectorMathProcessors.java @@ -40,8 +40,8 @@ public class VectorMathProcessors public static ExprVectorProcessor makeMathProcessor( Expr.VectorInputBindingInspector inspector, Expr arg, - Supplier longOutLongInSupplier, - Supplier doubleOutDoubleInSupplier + Supplier longOutLongInSupplier, + Supplier doubleOutDoubleInSupplier ) { final ExpressionType inputType = arg.getOutputType(inspector); @@ -68,8 +68,8 @@ public static ExprVectorProcessor makeMathProcessor( public static ExprVectorProcessor makeDoubleMathProcessor( Expr.VectorInputBindingInspector inspector, Expr arg, - Supplier doubleOutLongInSupplier, - Supplier doubleOutDoubleInSupplier + Supplier doubleOutLongInSupplier, + Supplier doubleOutDoubleInSupplier ) { final ExpressionType inputType = arg.getOutputType(inspector); @@ -96,8 +96,8 @@ public static ExprVectorProcessor makeDoubleMathProcessor( public static ExprVectorProcessor makeLongMathProcessor( Expr.VectorInputBindingInspector inspector, Expr arg, - Supplier longOutLongInSupplier, - Supplier longOutDoubleInSupplier + Supplier longOutLongInSupplier, + Supplier longOutDoubleInSupplier ) { final ExpressionType inputType = arg.getOutputType(inspector); @@ -127,10 +127,10 @@ public static ExprVectorProcessor makeMathProcessor( Expr.VectorInputBindingInspector inspector, Expr left, Expr right, - Supplier longOutLongsInProcessor, - Supplier doubleOutLongDoubleInProcessor, - Supplier doubleOutDoubleLongInProcessor, - Supplier doubleOutDoublesInProcessor + Supplier longOutLongsInProcessor, + Supplier doubleOutLongDoubleInProcessor, + Supplier doubleOutDoubleLongInProcessor, + Supplier doubleOutDoublesInProcessor ) { final ExpressionType leftType = left.getOutputType(inspector); @@ -180,10 +180,10 @@ public static ExprVectorProcessor makeDoubleMathProcessor( Expr.VectorInputBindingInspector inspector, Expr left, Expr right, - Supplier doubleOutLongsInProcessor, - Supplier doubleOutLongDoubleInProcessor, - Supplier doubleOutDoubleLongInProcessor, - Supplier doubleOutDoublesInProcessor + Supplier doubleOutLongsInProcessor, + Supplier doubleOutLongDoubleInProcessor, + Supplier doubleOutDoubleLongInProcessor, + Supplier doubleOutDoublesInProcessor ) { final ExpressionType leftType = left.getOutputType(inspector); @@ -225,10 +225,10 @@ public static ExprVectorProcessor makeLongMathProcessor( Expr.VectorInputBindingInspector inspector, Expr left, Expr right, - Supplier longOutLongsInProcessor, - Supplier longOutLongDoubleInProcessor, - Supplier longOutDoubleLongInProcessor, - Supplier longOutDoublesInProcessor + Supplier longOutLongsInProcessor, + Supplier longOutLongDoubleInProcessor, + Supplier longOutDoubleLongInProcessor, + Supplier longOutDoublesInProcessor ) { final ExpressionType leftType = left.getOutputType(inspector); @@ -265,7 +265,7 @@ public static ExprVectorProcessor plus(Expr.VectorInputBindingInspector i inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -277,7 +277,7 @@ public long apply(long left, long right) return left + right; } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -289,7 +289,7 @@ public double apply(long left, double right) return (double) left + right; } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -301,7 +301,7 @@ public double apply(double left, long right) return left + (double) right; } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -322,7 +322,7 @@ public static ExprVectorProcessor minus(Expr.VectorInputBindingInspector inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -334,7 +334,7 @@ public long apply(long left, long right) return left - right; } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -346,7 +346,7 @@ public double apply(long left, double right) return (double) left - right; } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -358,7 +358,7 @@ public double apply(double left, long right) return left - (double) right; } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -379,7 +379,7 @@ public static ExprVectorProcessor multiply(Expr.VectorInputBindingInspect inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -391,7 +391,7 @@ public long apply(long left, long right) return left * right; } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -403,7 +403,7 @@ public double apply(long left, double right) return (double) left * right; } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -415,7 +415,7 @@ public double apply(double left, long right) return left * (double) right; } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -436,7 +436,7 @@ public static ExprVectorProcessor divide(Expr.VectorInputBindingInspector inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -448,7 +448,7 @@ public long apply(long left, long right) return left / right; } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -460,7 +460,7 @@ public double apply(long left, double right) return (double) left / right; } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -472,7 +472,7 @@ public double apply(double left, long right) return left / (double) right; } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -493,7 +493,7 @@ public static ExprVectorProcessor longDivide(Expr.VectorInputBindingInspe inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -505,7 +505,7 @@ public long apply(long left, long right) return left / right; } }, - () -> new LongOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -517,7 +517,7 @@ public long apply(long left, double right) return (long) (left / right); } }, - () -> new LongOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -529,7 +529,7 @@ public long apply(double left, long right) return (long) (left / right); } }, - () -> new LongOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -550,7 +550,7 @@ public static ExprVectorProcessor modulo(Expr.VectorInputBindingInspector inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -562,7 +562,7 @@ public long apply(long left, long right) return left % right; } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -574,7 +574,7 @@ public double apply(long left, double right) return (double) left % right; } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -586,7 +586,7 @@ public double apply(double left, long right) return left % (double) right; } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -606,7 +606,7 @@ public static ExprVectorProcessor negate(Expr.VectorInputBindingInspector return makeMathProcessor( inspector, arg, - () -> new LongOutLongInFunctionVectorProcessor( + () -> new LongOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -617,7 +617,7 @@ public long apply(long input) return -input; } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -637,7 +637,7 @@ public static ExprVectorProcessor power(Expr.VectorInputBindingInspector inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -649,7 +649,7 @@ public long apply(long left, long right) return LongMath.pow(left, Ints.checkedCast(right)); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -661,7 +661,7 @@ public double apply(long left, double right) return Math.pow(left, right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -673,7 +673,7 @@ public double apply(double left, long right) return Math.pow(left, right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -696,10 +696,10 @@ public static ExprVectorProcessor doublePower( { final ExpressionType leftType = left.getOutputType(inspector); final ExpressionType rightType = right.getOutputType(inspector); - BivariateFunctionVectorProcessor processor = null; + BivariateFunctionVectorValueProcessor processor = null; if ((Types.is(leftType, ExprType.LONG) && Types.isNullOr(rightType, ExprType.LONG)) || (leftType == null && Types.is(rightType, ExprType.LONG))) { - processor = new DoubleOutLongsInFunctionVectorProcessor( + processor = new DoubleOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -725,7 +725,7 @@ public static ExprVectorProcessor max(Expr.VectorInputBindingInspector in inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -737,7 +737,7 @@ public long apply(long left, long right) return Math.max(left, right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -749,7 +749,7 @@ public double apply(long left, double right) return Math.max(left, right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -761,7 +761,7 @@ public double apply(double left, long right) return Math.max(left, right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -782,7 +782,7 @@ public static ExprVectorProcessor min(Expr.VectorInputBindingInspector in inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -794,7 +794,7 @@ public long apply(long left, long right) return Math.min(left, right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -806,7 +806,7 @@ public double apply(long left, double right) return Math.min(left, right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -818,7 +818,7 @@ public double apply(double left, long right) return Math.min(left, right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -839,7 +839,7 @@ public static ExprVectorProcessor atan2(Expr.VectorInputBindingInspector inspector, left, right, - () -> new DoubleOutLongsInFunctionVectorProcessor( + () -> new DoubleOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -851,7 +851,7 @@ public double apply(long left, long right) return Math.atan2(left, right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -863,7 +863,7 @@ public double apply(long left, double right) return Math.atan2(left, right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -875,7 +875,7 @@ public double apply(double left, long right) return Math.atan2(left, right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -896,7 +896,7 @@ public static ExprVectorProcessor copySign(Expr.VectorInputBindingInspect inspector, left, right, - () -> new DoubleOutLongsInFunctionVectorProcessor( + () -> new DoubleOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -908,7 +908,7 @@ public double apply(long left, long right) return Math.copySign((double) left, (double) right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -920,7 +920,7 @@ public double apply(long left, double right) return Math.copySign((double) left, right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -932,7 +932,7 @@ public double apply(double left, long right) return Math.copySign(left, (double) right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -953,7 +953,7 @@ public static ExprVectorProcessor hypot(Expr.VectorInputBindingInspector inspector, left, right, - () -> new DoubleOutLongsInFunctionVectorProcessor( + () -> new DoubleOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -965,7 +965,7 @@ public double apply(long left, long right) return Math.hypot(left, right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -977,7 +977,7 @@ public double apply(long left, double right) return Math.hypot(left, right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -989,7 +989,7 @@ public double apply(double left, long right) return Math.hypot(left, right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1010,7 +1010,7 @@ public static ExprVectorProcessor remainder(Expr.VectorInputBindingInspec inspector, left, right, - () -> new DoubleOutLongsInFunctionVectorProcessor( + () -> new DoubleOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1022,7 +1022,7 @@ public double apply(long left, long right) return Math.IEEEremainder(left, right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1034,7 +1034,7 @@ public double apply(long left, double right) return Math.IEEEremainder(left, right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1046,7 +1046,7 @@ public double apply(double left, long right) return Math.IEEEremainder(left, right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1067,7 +1067,7 @@ public static ExprVectorProcessor nextAfter(Expr.VectorInputBindingInspec inspector, left, right, - () -> new DoubleOutLongsInFunctionVectorProcessor( + () -> new DoubleOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1079,7 +1079,7 @@ public double apply(long left, long right) return Math.nextAfter((double) left, (double) right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1091,7 +1091,7 @@ public double apply(long left, double right) return Math.nextAfter((double) left, right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1103,7 +1103,7 @@ public double apply(double left, long right) return Math.nextAfter(left, (double) right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1124,7 +1124,7 @@ public static ExprVectorProcessor scalb(Expr.VectorInputBindingInspector inspector, left, right, - () -> new DoubleOutLongsInFunctionVectorProcessor( + () -> new DoubleOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1136,7 +1136,7 @@ public double apply(long left, long right) return Math.scalb((double) left, (int) right); } }, - () -> new DoubleOutLongDoubleInFunctionVectorProcessor( + () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1148,7 +1148,7 @@ public double apply(long left, double right) return Math.scalb((double) left, (int) right); } }, - () -> new DoubleOutDoubleLongInFunctionVectorProcessor( + () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1160,7 +1160,7 @@ public double apply(double left, long right) return Math.scalb(left, (int) right); } }, - () -> new DoubleOutDoublesInFunctionVectorProcessor( + () -> new DoubleOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -1180,7 +1180,7 @@ public static ExprVectorProcessor acos(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1191,7 +1191,7 @@ public double apply(long input) return Math.acos(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1210,7 +1210,7 @@ public static ExprVectorProcessor asin(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1221,7 +1221,7 @@ public double apply(long input) return Math.asin(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1240,7 +1240,7 @@ public static ExprVectorProcessor atan(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1251,7 +1251,7 @@ public double apply(long input) return Math.atan(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1270,7 +1270,7 @@ public static ExprVectorProcessor cos(Expr.VectorInputBindingInspector in return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1281,7 +1281,7 @@ public double apply(long input) return Math.cos(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1300,7 +1300,7 @@ public static ExprVectorProcessor cosh(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1311,7 +1311,7 @@ public double apply(long input) return Math.cosh(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1330,7 +1330,7 @@ public static ExprVectorProcessor cot(Expr.VectorInputBindingInspector in return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1341,7 +1341,7 @@ public double apply(long input) return Math.cos(input) / Math.sin(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1360,7 +1360,7 @@ public static ExprVectorProcessor sin(Expr.VectorInputBindingInspector in return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1371,7 +1371,7 @@ public double apply(long input) return Math.sin(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1390,7 +1390,7 @@ public static ExprVectorProcessor sinh(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1401,7 +1401,7 @@ public double apply(long input) return Math.sinh(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1420,7 +1420,7 @@ public static ExprVectorProcessor tan(Expr.VectorInputBindingInspector in return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1431,7 +1431,7 @@ public double apply(long input) return Math.tan(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1450,7 +1450,7 @@ public static ExprVectorProcessor tanh(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1461,7 +1461,7 @@ public double apply(long input) return Math.tanh(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1480,7 +1480,7 @@ public static ExprVectorProcessor abs(Expr.VectorInputBindingInspector in return makeMathProcessor( inspector, arg, - () -> new LongOutLongInFunctionVectorProcessor( + () -> new LongOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1491,7 +1491,7 @@ public long apply(long input) return Math.abs(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1510,7 +1510,7 @@ public static ExprVectorProcessor cbrt(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1521,7 +1521,7 @@ public double apply(long input) return Math.cbrt(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1540,7 +1540,7 @@ public static ExprVectorProcessor ceil(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1551,7 +1551,7 @@ public double apply(long input) return Math.ceil(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1570,7 +1570,7 @@ public static ExprVectorProcessor floor(Expr.VectorInputBindingInspector return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1581,7 +1581,7 @@ public double apply(long input) return Math.floor(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1600,7 +1600,7 @@ public static ExprVectorProcessor exp(Expr.VectorInputBindingInspector in return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1611,7 +1611,7 @@ public double apply(long input) return Math.exp(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1630,7 +1630,7 @@ public static ExprVectorProcessor expm1(Expr.VectorInputBindingInspector return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1641,7 +1641,7 @@ public double apply(long input) return Math.expm1(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1660,7 +1660,7 @@ public static ExprVectorProcessor getExponent(Expr.VectorInputBindingInsp return makeLongMathProcessor( inspector, arg, - () -> new LongOutLongInFunctionVectorProcessor( + () -> new LongOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1671,7 +1671,7 @@ public long apply(long input) return Math.getExponent((double) input); } }, - () -> new LongOutDoubleInFunctionVectorProcessor( + () -> new LongOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1690,7 +1690,7 @@ public static ExprVectorProcessor log(Expr.VectorInputBindingInspector in return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1701,7 +1701,7 @@ public double apply(long input) return Math.log(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1720,7 +1720,7 @@ public static ExprVectorProcessor log10(Expr.VectorInputBindingInspector return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1731,7 +1731,7 @@ public double apply(long input) return Math.log10(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1750,7 +1750,7 @@ public static ExprVectorProcessor log1p(Expr.VectorInputBindingInspector return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1761,7 +1761,7 @@ public double apply(long input) return Math.log1p(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1780,7 +1780,7 @@ public static ExprVectorProcessor nextUp(Expr.VectorInputBindingInspector return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1791,7 +1791,7 @@ public double apply(long input) return Math.nextUp((double) input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1810,7 +1810,7 @@ public static ExprVectorProcessor rint(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1821,7 +1821,7 @@ public double apply(long input) return Math.rint(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1840,7 +1840,7 @@ public static ExprVectorProcessor signum(Expr.VectorInputBindingInspector return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1851,7 +1851,7 @@ public double apply(long input) return Math.signum(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1870,7 +1870,7 @@ public static ExprVectorProcessor sqrt(Expr.VectorInputBindingInspector i return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1881,7 +1881,7 @@ public double apply(long input) return Math.sqrt(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1900,7 +1900,7 @@ public static ExprVectorProcessor toDegrees(Expr.VectorInputBindingInspec return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1911,7 +1911,7 @@ public double apply(long input) return Math.toDegrees(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1930,7 +1930,7 @@ public static ExprVectorProcessor toRadians(Expr.VectorInputBindingInspec return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1941,7 +1941,7 @@ public double apply(long input) return Math.toRadians(input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1960,7 +1960,7 @@ public static ExprVectorProcessor ulp(Expr.VectorInputBindingInspector in return makeDoubleMathProcessor( inspector, arg, - () -> new DoubleOutLongInFunctionVectorProcessor( + () -> new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1971,7 +1971,7 @@ public double apply(long input) return Math.ulp((double) input); } }, - () -> new DoubleOutDoubleInFunctionVectorProcessor( + () -> new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -1990,7 +1990,7 @@ public static ExprVectorProcessor bitwiseComplement(Expr.VectorInputBindi return makeLongMathProcessor( inspector, arg, - () -> new LongOutLongInFunctionVectorProcessor( + () -> new LongOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -2001,7 +2001,7 @@ public long apply(long input) return ~input; } }, - () -> new LongOutDoubleInFunctionVectorProcessor( + () -> new LongOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -2024,7 +2024,7 @@ public static ExprVectorProcessor bitwiseConvertDoubleToLongBits( ExprVectorProcessor processor = null; if (Types.is(inputType, ExprType.LONG)) { - processor = new LongOutLongInFunctionVectorProcessor( + processor = new LongOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -2036,7 +2036,7 @@ public long apply(long input) } }; } else if (Types.is(inputType, ExprType.DOUBLE)) { - processor = new LongOutDoubleInFunctionVectorProcessor( + processor = new LongOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -2063,7 +2063,7 @@ public static ExprVectorProcessor bitwiseConvertLongBitsToDouble( ExprVectorProcessor processor = null; if (Types.is(inputType, ExprType.LONG)) { - processor = new DoubleOutLongInFunctionVectorProcessor( + processor = new DoubleOutLongInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -2075,7 +2075,7 @@ public double apply(long input) } }; } else if (Types.is(inputType, ExprType.DOUBLE)) { - processor = new DoubleOutDoubleInFunctionVectorProcessor( + processor = new DoubleOutDoubleInFunctionVectorValueProcessor( arg.buildVectorized(inspector), inspector.getMaxVectorSize() ) @@ -2099,7 +2099,7 @@ public static ExprVectorProcessor bitwiseAnd(Expr.VectorInputBindingInspe inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2111,7 +2111,7 @@ public long apply(long left, long right) return left & right; } }, - () -> new LongOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2123,7 +2123,7 @@ public long apply(long left, double right) return left & (long) right; } }, - () -> new LongOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2135,7 +2135,7 @@ public long apply(double left, long right) return (long) left & right; } }, - () -> new LongOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2156,7 +2156,7 @@ public static ExprVectorProcessor bitwiseOr(Expr.VectorInputBindingInspec inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2168,7 +2168,7 @@ public long apply(long left, long right) return left | right; } }, - () -> new LongOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2180,7 +2180,7 @@ public long apply(long left, double right) return left | (long) right; } }, - () -> new LongOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2192,7 +2192,7 @@ public long apply(double left, long right) return (long) left | right; } }, - () -> new LongOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2213,7 +2213,7 @@ public static ExprVectorProcessor bitwiseXor(Expr.VectorInputBindingInspe inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2225,7 +2225,7 @@ public long apply(long left, long right) return left ^ right; } }, - () -> new LongOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2237,7 +2237,7 @@ public long apply(long left, double right) return left ^ (long) right; } }, - () -> new LongOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2249,7 +2249,7 @@ public long apply(double left, long right) return (long) left ^ right; } }, - () -> new LongOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2274,7 +2274,7 @@ public static ExprVectorProcessor bitwiseShiftLeft( inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2286,7 +2286,7 @@ public long apply(long left, long right) return left << right; } }, - () -> new LongOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2298,7 +2298,7 @@ public long apply(long left, double right) return left << (long) right; } }, - () -> new LongOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2310,7 +2310,7 @@ public long apply(double left, long right) return (long) left << right; } }, - () -> new LongOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2335,7 +2335,7 @@ public static ExprVectorProcessor bitwiseShiftRight( inspector, left, right, - () -> new LongOutLongsInFunctionVectorProcessor( + () -> new LongOutLongsInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2347,7 +2347,7 @@ public long apply(long left, long right) return left >> right; } }, - () -> new LongOutLongDoubleInFunctionVectorProcessor( + () -> new LongOutLongDoubleInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2359,7 +2359,7 @@ public long apply(long left, double right) return left >> (long) right; } }, - () -> new LongOutDoubleLongInFunctionVectorProcessor( + () -> new LongOutDoubleLongInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() @@ -2371,7 +2371,7 @@ public long apply(double left, long right) return (long) left >> right; } }, - () -> new LongOutDoublesInFunctionVectorProcessor( + () -> new LongOutDoublesInFunctionVectorValueProcessor( left.buildVectorized(inspector), right.buildVectorized(inspector), inspector.getMaxVectorSize() diff --git a/core/src/main/java/org/apache/druid/math/expr/vector/VectorProcessors.java b/core/src/main/java/org/apache/druid/math/expr/vector/VectorProcessors.java index e8815f4a6826..47c7389805f5 100644 --- a/core/src/main/java/org/apache/druid/math/expr/vector/VectorProcessors.java +++ b/core/src/main/java/org/apache/druid/math/expr/vector/VectorProcessors.java @@ -19,16 +19,62 @@ package org.apache.druid.math.expr.vector; +import com.google.common.base.Preconditions; import org.apache.druid.common.config.NullHandling; +import org.apache.druid.math.expr.Evals; import org.apache.druid.math.expr.Expr; +import org.apache.druid.math.expr.ExprType; +import org.apache.druid.math.expr.ExpressionProcessing; import org.apache.druid.math.expr.ExpressionType; +import org.apache.druid.math.expr.Exprs; +import org.apache.druid.segment.column.Types; import javax.annotation.Nullable; import java.util.Arrays; +import java.util.function.Supplier; public class VectorProcessors { - public static ExprVectorProcessor constantString(@Nullable String constant, int maxVectorSize) + /** + * Make a 2 argument, symmetrical processor where both argments must be the same input type and produce the same + * output type + * long, long -> long + * double, double -> double + * string, string -> string + */ + public static ExprVectorProcessor makeSymmetricalProcessor( + Expr.VectorInputBindingInspector inspector, + Expr left, + Expr right, + Supplier> longProcessor, + Supplier> doubleProcessor, + Supplier> stringProcessor + ) + { + final ExpressionType leftType = left.getOutputType(inspector); + + if (leftType == null) { + return right.buildVectorized(inspector); + } + + Preconditions.checkArgument(inspector.areSameTypes(left, right)); + + ExprVectorProcessor processor = null; + if (Types.is(leftType, ExprType.STRING)) { + processor = stringProcessor.get(); + } else if (Types.is(leftType, ExprType.LONG)) { + processor = longProcessor.get(); + } else if (Types.is(leftType, ExprType.DOUBLE)) { + processor = doubleProcessor.get(); + } + + if (processor == null) { + throw Exprs.cannotVectorize(); + } + return (ExprVectorProcessor) processor; + } + + public static ExprVectorProcessor constant(@Nullable String constant, int maxVectorSize) { final String[] strings = new String[maxVectorSize]; Arrays.fill(strings, constant); @@ -49,7 +95,7 @@ public ExpressionType getOutputType() }; } - public static ExprVectorProcessor constantDouble(@Nullable Double constant, int maxVectorSize) + public static ExprVectorProcessor constant(@Nullable Double constant, int maxVectorSize) { final double[] doubles = new double[maxVectorSize]; final boolean[] nulls; @@ -77,7 +123,7 @@ public ExpressionType getOutputType() }; } - public static ExprVectorProcessor constantLong(@Nullable Long constant, int maxVectorSize) + public static ExprVectorProcessor constant(@Nullable Long constant, int maxVectorSize) { final long[] longs = new long[maxVectorSize]; final boolean[] nulls; @@ -135,6 +181,692 @@ public void processIndex(String[] strings, long[] longs, boolean[] outputNulls, return (ExprVectorProcessor) processor; } + public static ExprVectorProcessor isNull(Expr.VectorInputBindingInspector inspector, Expr expr) + { + + final ExpressionType type = expr.getOutputType(inspector); + + if (type == null) { + return constant(1L, inspector.getMaxVectorSize()); + } + final long[] outputValues = new long[inspector.getMaxVectorSize()]; + + ExprVectorProcessor processor = null; + if (Types.is(type, ExprType.STRING)) { + final ExprVectorProcessor input = expr.buildVectorized(inspector); + processor = new ExprVectorProcessor() + { + @Override + public ExprEvalVector evalVector(Expr.VectorInputBinding bindings) + { + final ExprEvalVector inputEval = input.evalVector(bindings); + + final int currentSize = bindings.getCurrentVectorSize(); + final String[] values = inputEval.values(); + for (int i = 0; i < currentSize; i++) { + if (values[i] == null) { + outputValues[i] = 1L; + } else { + outputValues[i] = 0L; + } + } + return new ExprEvalLongVector(outputValues, null); + } + + @Override + public ExpressionType getOutputType() + { + return ExpressionType.LONG; + } + }; + } else if (Types.is(type, ExprType.LONG)) { + final ExprVectorProcessor input = expr.buildVectorized(inspector); + processor = new ExprVectorProcessor() + { + @Override + public ExprEvalVector evalVector(Expr.VectorInputBinding bindings) + { + final ExprEvalVector inputEval = input.evalVector(bindings); + + final int currentSize = bindings.getCurrentVectorSize(); + final boolean[] nulls = inputEval.getNullVector(); + if (nulls == null) { + Arrays.fill(outputValues, 0L); + } else { + for (int i = 0; i < currentSize; i++) { + if (nulls[i]) { + outputValues[i] = 1L; + } else { + outputValues[i] = 0L; + } + } + } + return new ExprEvalLongVector(outputValues, null); + } + + @Override + public ExpressionType getOutputType() + { + return ExpressionType.LONG; + } + }; + } else if (Types.is(type, ExprType.DOUBLE)) { + final ExprVectorProcessor input = expr.buildVectorized(inspector); + processor = new ExprVectorProcessor() + { + @Override + public ExprEvalVector evalVector(Expr.VectorInputBinding bindings) + { + final ExprEvalVector inputEval = input.evalVector(bindings); + + final int currentSize = bindings.getCurrentVectorSize(); + final boolean[] nulls = inputEval.getNullVector(); + if (nulls == null) { + Arrays.fill(outputValues, 0L); + } else { + for (int i = 0; i < currentSize; i++) { + if (nulls[i]) { + outputValues[i] = 1L; + } else { + outputValues[i] = 0L; + } + } + } + return new ExprEvalLongVector(outputValues, null); + } + + @Override + public ExpressionType getOutputType() + { + return ExpressionType.LONG; + } + }; + } + + if (processor == null) { + throw Exprs.cannotVectorize(); + } + return (ExprVectorProcessor) processor; + } + + public static ExprVectorProcessor isNotNull(Expr.VectorInputBindingInspector inspector, Expr expr) + { + + final ExpressionType type = expr.getOutputType(inspector); + if (type == null) { + return constant(0L, inspector.getMaxVectorSize()); + } + + final long[] outputValues = new long[inspector.getMaxVectorSize()]; + + ExprVectorProcessor processor = null; + if (Types.is(type, ExprType.STRING)) { + final ExprVectorProcessor input = expr.buildVectorized(inspector); + processor = new ExprVectorProcessor() + { + @Override + public ExprEvalVector evalVector(Expr.VectorInputBinding bindings) + { + final ExprEvalVector inputEval = input.evalVector(bindings); + + final int currentSize = bindings.getCurrentVectorSize(); + final String[] values = inputEval.values(); + for (int i = 0; i < currentSize; i++) { + if (values[i] == null) { + outputValues[i] = 0L; + } else { + outputValues[i] = 1L; + } + } + return new ExprEvalLongVector(outputValues, null); + } + + @Override + public ExpressionType getOutputType() + { + return ExpressionType.LONG; + } + }; + } else if (Types.is(type, ExprType.LONG)) { + final ExprVectorProcessor input = expr.buildVectorized(inspector); + processor = new ExprVectorProcessor() + { + @Override + public ExprEvalVector evalVector(Expr.VectorInputBinding bindings) + { + final ExprEvalVector inputEval = input.evalVector(bindings); + + final int currentSize = bindings.getCurrentVectorSize(); + final boolean[] nulls = inputEval.getNullVector(); + if (nulls == null) { + Arrays.fill(outputValues, 1L); + } else { + for (int i = 0; i < currentSize; i++) { + if (nulls[i]) { + outputValues[i] = 0L; + } else { + outputValues[i] = 1L; + } + } + } + return new ExprEvalLongVector(outputValues, null); + } + + @Override + public ExpressionType getOutputType() + { + return ExpressionType.LONG; + } + }; + } else if (Types.is(type, ExprType.DOUBLE)) { + final ExprVectorProcessor input = expr.buildVectorized(inspector); + processor = new ExprVectorProcessor() + { + @Override + public ExprEvalVector evalVector(Expr.VectorInputBinding bindings) + { + final ExprEvalVector inputEval = input.evalVector(bindings); + + final int currentSize = bindings.getCurrentVectorSize(); + final boolean[] nulls = inputEval.getNullVector(); + if (nulls == null) { + Arrays.fill(outputValues, 1L); + } else { + for (int i = 0; i < currentSize; i++) { + if (nulls[i]) { + outputValues[i] = 0L; + } else { + outputValues[i] = 1L; + } + } + } + return new ExprEvalLongVector(outputValues, null); + } + + @Override + public ExpressionType getOutputType() + { + return ExpressionType.LONG; + } + }; + } + + if (processor == null) { + throw Exprs.cannotVectorize(); + } + return (ExprVectorProcessor) processor; + } + + public static ExprVectorProcessor nvl(Expr.VectorInputBindingInspector inspector, Expr left, Expr right) + { + final int maxVectorSize = inspector.getMaxVectorSize(); + + return makeSymmetricalProcessor( + inspector, + left, + right, + () -> new SymmetricalBivariateFunctionVectorProcessor( + ExpressionType.LONG, + left.buildVectorized(inspector), + right.buildVectorized(inspector) + ) + { + final long[] output = new long[maxVectorSize]; + final boolean[] outputNulls = new boolean[maxVectorSize]; + + @Override + public void processIndex( + long[] leftInput, + @Nullable boolean[] leftNulls, + long[] rightInput, + @Nullable boolean[] rightNulls, + int i + ) + { + if (leftNulls != null && leftNulls[i]) { + if (rightNulls != null) { + output[i] = rightNulls[i] ? 0L : rightInput[i]; + outputNulls[i] = rightNulls[i]; + } else { + output[i] = rightInput[i]; + } + } else { + output[i] = leftInput[i]; + } + } + + @Override + public ExprEvalVector asEval() + { + return new ExprEvalLongVector(output, outputNulls); + } + }, + () -> new SymmetricalBivariateFunctionVectorProcessor( + ExpressionType.DOUBLE, + left.buildVectorized(inspector), + right.buildVectorized(inspector) + ) + { + final double[] output = new double[maxVectorSize]; + final boolean[] outputNulls = new boolean[maxVectorSize]; + + @Override + public void processIndex( + double[] leftInput, + @Nullable boolean[] leftNulls, + double[] rightInput, + @Nullable boolean[] rightNulls, + int i + ) + { + if (leftNulls != null && leftNulls[i]) { + if (rightNulls != null) { + output[i] = rightNulls[i] ? 0.0 : rightInput[i]; + outputNulls[i] = rightNulls[i]; + } else { + output[i] = rightInput[i]; + } + } else { + output[i] = leftInput[i]; + } + } + + @Override + public ExprEvalVector asEval() + { + return new ExprEvalDoubleVector(output, outputNulls); + } + }, + () -> new SymmetricalBivariateFunctionVectorProcessor( + ExpressionType.STRING, + left.buildVectorized(inspector), + right.buildVectorized(inspector) + ) + { + final String[] output = new String[maxVectorSize]; + + @Override + public void processIndex( + String[] leftInput, + @Nullable boolean[] leftNulls, + String[] rightInput, + @Nullable boolean[] rightNulls, + int i + ) + { + output[i] = leftInput[i] != null ? leftInput[i] : rightInput[i]; + } + + @Override + public ExprEvalVector asEval() + { + return new ExprEvalStringVector(output); + } + } + ); + } + + public static ExprVectorProcessor not(Expr.VectorInputBindingInspector inspector, Expr expr) + { + final ExpressionType inputType = expr.getOutputType(inspector); + final int maxVectorSize = inspector.getMaxVectorSize(); + ExprVectorProcessor processor = null; + if (Types.is(inputType, ExprType.STRING)) { + processor = new LongOutStringInFunctionVectorProcessor(expr.buildVectorized(inspector), maxVectorSize) + { + @Override + public void processIndex(String[] strings, long[] longs, boolean[] outputNulls, int i) + { + outputNulls[i] = strings[i] == null; + if (!outputNulls[i]) { + longs[i] = Evals.asLong(!Evals.asBoolean(strings[i])); + } + } + }; + } else if (Types.is(inputType, ExprType.LONG)) { + processor = new LongOutLongInFunctionVectorValueProcessor(expr.buildVectorized(inspector), maxVectorSize) + { + @Override + public long apply(long input) + { + return Evals.asLong(!Evals.asBoolean(input)); + } + }; + } else if (Types.is(inputType, ExprType.DOUBLE)) { + if (!ExpressionProcessing.useStrictBooleans()) { + processor = new DoubleOutDoubleInFunctionVectorValueProcessor(expr.buildVectorized(inspector), maxVectorSize) + { + @Override + public double apply(double input) + { + return Evals.asDouble(!Evals.asBoolean(input)); + } + }; + } else { + processor = new LongOutDoubleInFunctionVectorValueProcessor(expr.buildVectorized(inspector), maxVectorSize) + { + @Override + public long apply(double input) + { + return Evals.asLong(!Evals.asBoolean(input)); + } + }; + } + } + if (processor == null) { + throw Exprs.cannotVectorize(); + } + return (ExprVectorProcessor) processor; + } + + public static ExprVectorProcessor or(Expr.VectorInputBindingInspector inspector, Expr left, Expr right) + { + final int maxVectorSize = inspector.getMaxVectorSize(); + return makeSymmetricalProcessor( + inspector, + left, + right, + () -> new SymmetricalBivariateFunctionVectorProcessor( + ExpressionType.LONG, + left.buildVectorized(inspector), + right.buildVectorized(inspector) + ) + { + final long[] output = new long[maxVectorSize]; + final boolean[] outputNulls = new boolean[maxVectorSize]; + + @Override + public void processIndex( + long[] leftInput, + @Nullable boolean[] leftNulls, + long[] rightInput, + @Nullable boolean[] rightNulls, + int i + ) + { + if (NullHandling.sqlCompatible()) { + // true/null, null/true -> true + // false/null, null/false, null/null -> null + final boolean leftNull = leftNulls != null && leftNulls[i]; + final boolean rightNull = rightNulls != null && rightNulls[i]; + if (leftNull) { + if (rightNull) { + output[i] = 0L; + outputNulls[i] = true; + return; + } + final boolean bool = Evals.asBoolean(rightInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = !bool; + return; + } else if (rightNull) { + final boolean bool = Evals.asBoolean(leftInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = !bool; + return; + } + } + output[i] = Evals.asLong(Evals.asBoolean(leftInput[i]) || Evals.asBoolean(rightInput[i])); + } + + @Override + public ExprEvalVector asEval() + { + return new ExprEvalLongVector(output, outputNulls); + } + }, + () -> new BivariateFunctionVectorProcessor( + ExpressionType.LONG, + left.buildVectorized(inspector), + right.buildVectorized(inspector) + ) + { + final long[] output = new long[maxVectorSize]; + final boolean[] outputNulls = new boolean[maxVectorSize]; + + @Override + public void processIndex( + double[] leftInput, + @Nullable boolean[] leftNulls, + double[] rightInput, + @Nullable boolean[] rightNulls, + int i + ) + { + if (NullHandling.sqlCompatible()) { + // true/null, null/true -> true + // false/null, null/false, null/null -> null + final boolean leftNull = leftNulls != null && leftNulls[i]; + final boolean rightNull = rightNulls != null && rightNulls[i]; + if (leftNull) { + if (rightNull) { + output[i] = 0; + outputNulls[i] = true; + return; + } + final boolean bool = Evals.asBoolean(rightInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = !bool; + return; + } else if (rightNull) { + final boolean bool = Evals.asBoolean(leftInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = !bool; + return; + } + } + output[i] = Evals.asLong(Evals.asBoolean(leftInput[i]) || Evals.asBoolean(rightInput[i])); + } + + @Override + public ExprEvalVector asEval() + { + return new ExprEvalLongVector(output, outputNulls); + } + }, + () -> new BivariateFunctionVectorProcessor( + ExpressionType.LONG, + left.buildVectorized(inspector), + right.buildVectorized(inspector) + ) + { + final long[] output = new long[maxVectorSize]; + final boolean[] outputNulls = new boolean[maxVectorSize]; + + @Override + public void processIndex( + String[] leftInput, + @Nullable boolean[] leftNulls, + String[] rightInput, + @Nullable boolean[] rightNulls, + int i + ) + { + // true/null, null/true -> true + // false/null, null/false, null/null -> null + final boolean leftNull = leftInput[i] == null; + final boolean rightNull = rightInput[i] == null; + if (leftNull) { + if (rightNull) { + outputNulls[i] = true; + return; + } + final boolean bool = Evals.asBoolean(rightInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = !bool; + return; + } else if (rightNull) { + final boolean bool = Evals.asBoolean(leftInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = !bool; + return; + } + output[i] = Evals.asLong(Evals.asBoolean(leftInput[i]) || Evals.asBoolean(rightInput[i])); + } + + @Override + public ExprEvalVector asEval() + { + return new ExprEvalLongVector(output, outputNulls); + } + } + ); + } + + public static ExprVectorProcessor and(Expr.VectorInputBindingInspector inputTypes, Expr left, Expr right) + { + final int maxVectorSize = inputTypes.getMaxVectorSize(); + return makeSymmetricalProcessor( + inputTypes, + left, + right, + () -> new SymmetricalBivariateFunctionVectorProcessor( + ExpressionType.LONG, + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes) + ) + { + final long[] output = new long[maxVectorSize]; + final boolean[] outputNulls = new boolean[maxVectorSize]; + + @Override + public void processIndex( + long[] leftInput, + @Nullable boolean[] leftNulls, + long[] rightInput, + @Nullable boolean[] rightNulls, + int i + ) + { + if (NullHandling.sqlCompatible()) { + // true/null, null/true, null/null -> null + // false/null, null/false -> false + final boolean leftNull = leftNulls != null && leftNulls[i]; + final boolean rightNull = rightNulls != null && rightNulls[i]; + if (leftNull) { + if (rightNull) { + output[i] = 0L; + outputNulls[i] = true; + return; + } + final boolean bool = Evals.asBoolean(rightInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = bool; + return; + } else if (rightNull) { + final boolean bool = Evals.asBoolean(leftInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = bool; + return; + } + } + output[i] = Evals.asLong(Evals.asBoolean(leftInput[i]) && Evals.asBoolean(rightInput[i])); + } + + @Override + public ExprEvalVector asEval() + { + return new ExprEvalLongVector(output, outputNulls); + } + }, + () -> new BivariateFunctionVectorProcessor( + ExpressionType.DOUBLE, + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes) + ) + { + final long[] output = new long[maxVectorSize]; + final boolean[] outputNulls = new boolean[maxVectorSize]; + + @Override + public void processIndex( + double[] leftInput, + @Nullable boolean[] leftNulls, + double[] rightInput, + @Nullable boolean[] rightNulls, + int i + ) + { + if (NullHandling.sqlCompatible()) { + // true/null, null/true, null/null -> null + // false/null, null/false -> false + final boolean leftNull = leftNulls != null && leftNulls[i]; + final boolean rightNull = rightNulls != null && rightNulls[i]; + if (leftNull) { + if (rightNull) { + output[i] = 0L; + outputNulls[i] = true; + return; + } + final boolean bool = Evals.asBoolean(rightInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = bool; + return; + } else if (rightNull) { + final boolean bool = Evals.asBoolean(leftInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = bool; + return; + } + } + output[i] = Evals.asLong(Evals.asBoolean(leftInput[i]) && Evals.asBoolean(rightInput[i])); + } + + @Override + public ExprEvalVector asEval() + { + return new ExprEvalLongVector(output, outputNulls); + } + }, + () -> new BivariateFunctionVectorProcessor( + ExpressionType.STRING, + left.buildVectorized(inputTypes), + right.buildVectorized(inputTypes) + ) + { + final long[] output = new long[maxVectorSize]; + final boolean[] outputNulls = new boolean[maxVectorSize]; + + @Override + public void processIndex( + String[] leftInput, + @Nullable boolean[] leftNulls, + String[] rightInput, + @Nullable boolean[] rightNulls, + int i + ) + { + // true/null, null/true, null/null -> null + // false/null, null/false -> false + final boolean leftNull = leftInput[i] == null; + final boolean rightNull = rightInput[i] == null; + if (leftNull) { + if (rightNull) { + outputNulls[i] = true; + return; + } + final boolean bool = Evals.asBoolean(rightInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = bool; + return; + } else if (rightNull) { + final boolean bool = Evals.asBoolean(leftInput[i]); + output[i] = Evals.asLong(bool); + outputNulls[i] = bool; + return; + } + output[i] = Evals.asLong(Evals.asBoolean(leftInput[i]) && Evals.asBoolean(rightInput[i])); + } + + @Override + public ExprEvalVector asEval() + { + return new ExprEvalLongVector(output, outputNulls); + } + } + ); + } + private VectorProcessors() { // No instantiation diff --git a/core/src/test/java/org/apache/druid/math/expr/EvalTest.java b/core/src/test/java/org/apache/druid/math/expr/EvalTest.java index 2f7068381265..4b85836f7ced 100644 --- a/core/src/test/java/org/apache/druid/math/expr/EvalTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/EvalTest.java @@ -28,6 +28,9 @@ import org.junit.Test; import org.junit.rules.ExpectedException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + /** */ public class EvalTest extends InitializedNullHandlingTest @@ -38,14 +41,14 @@ public class EvalTest extends InitializedNullHandlingTest private long evalLong(String x, Expr.ObjectBinding bindings) { ExprEval ret = eval(x, bindings); - Assert.assertEquals(ExpressionType.LONG, ret.type()); + assertEquals(ExpressionType.LONG, ret.type()); return ret.asLong(); } private double evalDouble(String x, Expr.ObjectBinding bindings) { ExprEval ret = eval(x, bindings); - Assert.assertEquals(ExpressionType.DOUBLE, ret.type()); + assertEquals(ExpressionType.DOUBLE, ret.type()); return ret.asDouble(); } @@ -58,38 +61,67 @@ private ExprEval eval(String x, Expr.ObjectBinding bindings) public void testDoubleEval() { Expr.ObjectBinding bindings = InputBindings.withMap(ImmutableMap.of("x", 2.0d)); - Assert.assertEquals(2.0, evalDouble("x", bindings), 0.0001); - Assert.assertEquals(2.0, evalDouble("\"x\"", bindings), 0.0001); - Assert.assertEquals(304.0, evalDouble("300 + \"x\" * 2", bindings), 0.0001); - - Assert.assertFalse(evalDouble("1.0 && 0.0", bindings) > 0.0); - Assert.assertTrue(evalDouble("1.0 && 2.0", bindings) > 0.0); - - Assert.assertTrue(evalDouble("1.0 || 0.0", bindings) > 0.0); - Assert.assertFalse(evalDouble("0.0 || 0.0", bindings) > 0.0); - - Assert.assertTrue(evalDouble("2.0 > 1.0", bindings) > 0.0); - Assert.assertTrue(evalDouble("2.0 >= 2.0", bindings) > 0.0); - Assert.assertTrue(evalDouble("1.0 < 2.0", bindings) > 0.0); - Assert.assertTrue(evalDouble("2.0 <= 2.0", bindings) > 0.0); - Assert.assertTrue(evalDouble("2.0 == 2.0", bindings) > 0.0); - Assert.assertTrue(evalDouble("2.0 != 1.0", bindings) > 0.0); - - Assert.assertEquals(3.5, evalDouble("2.0 + 1.5", bindings), 0.0001); - Assert.assertEquals(0.5, evalDouble("2.0 - 1.5", bindings), 0.0001); - Assert.assertEquals(3.0, evalDouble("2.0 * 1.5", bindings), 0.0001); - Assert.assertEquals(4.0, evalDouble("2.0 / 0.5", bindings), 0.0001); - Assert.assertEquals(0.2, evalDouble("2.0 % 0.3", bindings), 0.0001); - Assert.assertEquals(8.0, evalDouble("2.0 ^ 3.0", bindings), 0.0001); - Assert.assertEquals(-1.5, evalDouble("-1.5", bindings), 0.0001); - - Assert.assertTrue(evalDouble("!-1.0", bindings) > 0.0); - Assert.assertTrue(evalDouble("!0.0", bindings) > 0.0); - Assert.assertFalse(evalDouble("!2.0", bindings) > 0.0); - - Assert.assertEquals(2.0, evalDouble("sqrt(4.0)", bindings), 0.0001); - Assert.assertEquals(2.0, evalDouble("if(1.0, 2.0, 3.0)", bindings), 0.0001); - Assert.assertEquals(3.0, evalDouble("if(0.0, 2.0, 3.0)", bindings), 0.0001); + assertEquals(2.0, evalDouble("x", bindings), 0.0001); + assertEquals(2.0, evalDouble("\"x\"", bindings), 0.0001); + assertEquals(304.0, evalDouble("300 + \"x\" * 2", bindings), 0.0001); + + try { + ExpressionProcessing.initializeForStrictBooleansTests(false); + Assert.assertFalse(evalDouble("1.0 && 0.0", bindings) > 0.0); + Assert.assertTrue(evalDouble("1.0 && 2.0", bindings) > 0.0); + + Assert.assertTrue(evalDouble("1.0 || 0.0", bindings) > 0.0); + Assert.assertFalse(evalDouble("0.0 || 0.0", bindings) > 0.0); + + Assert.assertTrue(evalDouble("2.0 > 1.0", bindings) > 0.0); + Assert.assertTrue(evalDouble("2.0 >= 2.0", bindings) > 0.0); + Assert.assertTrue(evalDouble("1.0 < 2.0", bindings) > 0.0); + Assert.assertTrue(evalDouble("2.0 <= 2.0", bindings) > 0.0); + Assert.assertTrue(evalDouble("2.0 == 2.0", bindings) > 0.0); + Assert.assertTrue(evalDouble("2.0 != 1.0", bindings) > 0.0); + + Assert.assertTrue(evalDouble("!-1.0", bindings) > 0.0); + Assert.assertTrue(evalDouble("!0.0", bindings) > 0.0); + Assert.assertFalse(evalDouble("!2.0", bindings) > 0.0); + } + finally { + ExpressionProcessing.initializeForTests(null); + } + try { + ExpressionProcessing.initializeForStrictBooleansTests(true); + Assert.assertEquals(0L, evalLong("1.0 && 0.0", bindings)); + Assert.assertEquals(1L, evalLong("1.0 && 2.0", bindings)); + + Assert.assertEquals(1L, evalLong("1.0 || 0.0", bindings)); + Assert.assertEquals(0L, evalLong("0.0 || 0.0", bindings)); + + Assert.assertEquals(1L, evalLong("2.0 > 1.0", bindings)); + Assert.assertEquals(1L, evalLong("2.0 >= 2.0", bindings)); + Assert.assertEquals(1L, evalLong("1.0 < 2.0", bindings)); + Assert.assertEquals(1L, evalLong("2.0 <= 2.0", bindings)); + Assert.assertEquals(1L, evalLong("2.0 == 2.0", bindings)); + Assert.assertEquals(1L, evalLong("2.0 != 1.0", bindings)); + + Assert.assertEquals(1L, evalLong("!-1.0", bindings)); + Assert.assertEquals(1L, evalLong("!0.0", bindings)); + Assert.assertEquals(0L, evalLong("!2.0", bindings)); + + assertEquals(3.5, evalDouble("2.0 + 1.5", bindings), 0.0001); + assertEquals(0.5, evalDouble("2.0 - 1.5", bindings), 0.0001); + assertEquals(3.0, evalDouble("2.0 * 1.5", bindings), 0.0001); + assertEquals(4.0, evalDouble("2.0 / 0.5", bindings), 0.0001); + assertEquals(0.2, evalDouble("2.0 % 0.3", bindings), 0.0001); + assertEquals(8.0, evalDouble("2.0 ^ 3.0", bindings), 0.0001); + assertEquals(-1.5, evalDouble("-1.5", bindings), 0.0001); + + + assertEquals(2.0, evalDouble("sqrt(4.0)", bindings), 0.0001); + assertEquals(2.0, evalDouble("if(1.0, 2.0, 3.0)", bindings), 0.0001); + assertEquals(3.0, evalDouble("if(0.0, 2.0, 3.0)", bindings), 0.0001); + } + finally { + ExpressionProcessing.initializeForTests(null); + } } @Test @@ -97,9 +129,9 @@ public void testLongEval() { Expr.ObjectBinding bindings = InputBindings.withMap(ImmutableMap.of("x", 9223372036854775807L)); - Assert.assertEquals(9223372036854775807L, evalLong("x", bindings)); - Assert.assertEquals(9223372036854775807L, evalLong("\"x\"", bindings)); - Assert.assertEquals(92233720368547759L, evalLong("\"x\" / 100 + 1", bindings)); + assertEquals(9223372036854775807L, evalLong("x", bindings)); + assertEquals(9223372036854775807L, evalLong("\"x\"", bindings)); + assertEquals(92233720368547759L, evalLong("\"x\" / 100 + 1", bindings)); Assert.assertFalse(evalLong("9223372036854775807 && 0", bindings) > 0); Assert.assertTrue(evalLong("9223372036854775807 && 9223372036854775806", bindings) > 0); @@ -116,104 +148,104 @@ public void testLongEval() Assert.assertTrue(evalLong("9223372036854775807 == 9223372036854775807", bindings) > 0); Assert.assertTrue(evalLong("9223372036854775807 != 9223372036854775806", bindings) > 0); - Assert.assertEquals(9223372036854775807L, evalLong("9223372036854775806 + 1", bindings)); - Assert.assertEquals(9223372036854775806L, evalLong("9223372036854775807 - 1", bindings)); - Assert.assertEquals(9223372036854775806L, evalLong("4611686018427387903 * 2", bindings)); - Assert.assertEquals(4611686018427387903L, evalLong("9223372036854775806 / 2", bindings)); - Assert.assertEquals(7L, evalLong("9223372036854775807 % 9223372036854775800", bindings)); - Assert.assertEquals(9223372030926249001L, evalLong("3037000499 ^ 2", bindings)); - Assert.assertEquals(-9223372036854775807L, evalLong("-9223372036854775807", bindings)); + assertEquals(9223372036854775807L, evalLong("9223372036854775806 + 1", bindings)); + assertEquals(9223372036854775806L, evalLong("9223372036854775807 - 1", bindings)); + assertEquals(9223372036854775806L, evalLong("4611686018427387903 * 2", bindings)); + assertEquals(4611686018427387903L, evalLong("9223372036854775806 / 2", bindings)); + assertEquals(7L, evalLong("9223372036854775807 % 9223372036854775800", bindings)); + assertEquals(9223372030926249001L, evalLong("3037000499 ^ 2", bindings)); + assertEquals(-9223372036854775807L, evalLong("-9223372036854775807", bindings)); Assert.assertTrue(evalLong("!-9223372036854775807", bindings) > 0); Assert.assertTrue(evalLong("!0", bindings) > 0); Assert.assertFalse(evalLong("!9223372036854775807", bindings) > 0); - Assert.assertEquals(3037000499L, evalLong("cast(sqrt(9223372036854775807), 'long')", bindings)); - Assert.assertEquals(1L, evalLong("if(x == 9223372036854775807, 1, 0)", bindings)); - Assert.assertEquals(0L, evalLong("if(x - 1 == 9223372036854775807, 1, 0)", bindings)); - - Assert.assertEquals(1271030400000L, evalLong("timestamp('2010-04-12')", bindings)); - Assert.assertEquals(1270998000000L, evalLong("timestamp('2010-04-12T+09:00')", bindings)); - Assert.assertEquals(1271055781000L, evalLong("timestamp('2010-04-12T07:03:01')", bindings)); - Assert.assertEquals(1271023381000L, evalLong("timestamp('2010-04-12T07:03:01+09:00')", bindings)); - Assert.assertEquals(1271023381419L, evalLong("timestamp('2010-04-12T07:03:01.419+09:00')", bindings)); - - Assert.assertEquals(1271030400L, evalLong("unix_timestamp('2010-04-12')", bindings)); - Assert.assertEquals(1270998000L, evalLong("unix_timestamp('2010-04-12T+09:00')", bindings)); - Assert.assertEquals(1271055781L, evalLong("unix_timestamp('2010-04-12T07:03:01')", bindings)); - Assert.assertEquals(1271023381L, evalLong("unix_timestamp('2010-04-12T07:03:01+09:00')", bindings)); - Assert.assertEquals(1271023381L, evalLong("unix_timestamp('2010-04-12T07:03:01.419+09:00')", bindings)); - Assert.assertEquals( + assertEquals(3037000499L, evalLong("cast(sqrt(9223372036854775807), 'long')", bindings)); + assertEquals(1L, evalLong("if(x == 9223372036854775807, 1, 0)", bindings)); + assertEquals(0L, evalLong("if(x - 1 == 9223372036854775807, 1, 0)", bindings)); + + assertEquals(1271030400000L, evalLong("timestamp('2010-04-12')", bindings)); + assertEquals(1270998000000L, evalLong("timestamp('2010-04-12T+09:00')", bindings)); + assertEquals(1271055781000L, evalLong("timestamp('2010-04-12T07:03:01')", bindings)); + assertEquals(1271023381000L, evalLong("timestamp('2010-04-12T07:03:01+09:00')", bindings)); + assertEquals(1271023381419L, evalLong("timestamp('2010-04-12T07:03:01.419+09:00')", bindings)); + + assertEquals(1271030400L, evalLong("unix_timestamp('2010-04-12')", bindings)); + assertEquals(1270998000L, evalLong("unix_timestamp('2010-04-12T+09:00')", bindings)); + assertEquals(1271055781L, evalLong("unix_timestamp('2010-04-12T07:03:01')", bindings)); + assertEquals(1271023381L, evalLong("unix_timestamp('2010-04-12T07:03:01+09:00')", bindings)); + assertEquals(1271023381L, evalLong("unix_timestamp('2010-04-12T07:03:01.419+09:00')", bindings)); + assertEquals( NullHandling.replaceWithDefault() ? "NULL" : "", eval("nvl(if(x == 9223372036854775807, '', 'x'), 'NULL')", bindings).asString() ); - Assert.assertEquals("x", eval("nvl(if(x == 9223372036854775806, '', 'x'), 'NULL')", bindings).asString()); + assertEquals("x", eval("nvl(if(x == 9223372036854775806, '', 'x'), 'NULL')", bindings).asString()); } @Test public void testArrayToScalar() { - Assert.assertEquals(1L, ExprEval.ofLongArray(new Long[]{1L}).asLong()); - Assert.assertEquals(1.0, ExprEval.ofLongArray(new Long[]{1L}).asDouble(), 0.0); - Assert.assertEquals(1, ExprEval.ofLongArray(new Long[]{1L}).asInt()); - Assert.assertEquals(true, ExprEval.ofLongArray(new Long[]{1L}).asBoolean()); - Assert.assertEquals("1", ExprEval.ofLongArray(new Long[]{1L}).asString()); - - - Assert.assertEquals(null, ExprEval.ofLongArray(new Long[]{null}).asString()); - - Assert.assertEquals(0L, ExprEval.ofLongArray(new Long[]{1L, 2L}).asLong()); - Assert.assertEquals(0.0, ExprEval.ofLongArray(new Long[]{1L, 2L}).asDouble(), 0.0); - Assert.assertEquals("[1, 2]", ExprEval.ofLongArray(new Long[]{1L, 2L}).asString()); - Assert.assertEquals(0, ExprEval.ofLongArray(new Long[]{1L, 2L}).asInt()); - Assert.assertEquals(false, ExprEval.ofLongArray(new Long[]{1L, 2L}).asBoolean()); - - Assert.assertEquals(1.1, ExprEval.ofDoubleArray(new Double[]{1.1}).asDouble(), 0.0); - Assert.assertEquals(1L, ExprEval.ofDoubleArray(new Double[]{1.1}).asLong()); - Assert.assertEquals("1.1", ExprEval.ofDoubleArray(new Double[]{1.1}).asString()); - Assert.assertEquals(1, ExprEval.ofDoubleArray(new Double[]{1.1}).asInt()); - Assert.assertEquals(true, ExprEval.ofDoubleArray(new Double[]{1.1}).asBoolean()); - - Assert.assertEquals(null, ExprEval.ofDoubleArray(new Double[]{null}).asString()); - - Assert.assertEquals(0.0, ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asDouble(), 0.0); - Assert.assertEquals(0L, ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asLong()); - Assert.assertEquals("[1.1, 2.2]", ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asString()); - Assert.assertEquals(0, ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asInt()); - Assert.assertEquals(false, ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asBoolean()); - - Assert.assertEquals("foo", ExprEval.ofStringArray(new String[]{"foo"}).asString()); - - Assert.assertEquals("1", ExprEval.ofStringArray(new String[]{"1"}).asString()); - Assert.assertEquals(1L, ExprEval.ofStringArray(new String[]{"1"}).asLong()); - Assert.assertEquals(1.0, ExprEval.ofStringArray(new String[]{"1"}).asDouble(), 0.0); - Assert.assertEquals(1, ExprEval.ofStringArray(new String[]{"1"}).asInt()); - Assert.assertEquals(false, ExprEval.ofStringArray(new String[]{"1"}).asBoolean()); - Assert.assertEquals(true, ExprEval.ofStringArray(new String[]{"true"}).asBoolean()); - - Assert.assertEquals("[1, 2.2]", ExprEval.ofStringArray(new String[]{"1", "2.2"}).asString()); - Assert.assertEquals(0L, ExprEval.ofStringArray(new String[]{"1", "2.2"}).asLong()); - Assert.assertEquals(0.0, ExprEval.ofStringArray(new String[]{"1", "2.2"}).asDouble(), 0.0); - Assert.assertEquals(0, ExprEval.ofStringArray(new String[]{"1", "2.2"}).asInt()); - Assert.assertEquals(false, ExprEval.ofStringArray(new String[]{"1", "2.2"}).asBoolean()); + assertEquals(1L, ExprEval.ofLongArray(new Long[]{1L}).asLong()); + assertEquals(1.0, ExprEval.ofLongArray(new Long[]{1L}).asDouble(), 0.0); + assertEquals(1, ExprEval.ofLongArray(new Long[]{1L}).asInt()); + assertEquals(true, ExprEval.ofLongArray(new Long[]{1L}).asBoolean()); + assertEquals("1", ExprEval.ofLongArray(new Long[]{1L}).asString()); + + + assertEquals(null, ExprEval.ofLongArray(new Long[]{null}).asString()); + + assertEquals(0L, ExprEval.ofLongArray(new Long[]{1L, 2L}).asLong()); + assertEquals(0.0, ExprEval.ofLongArray(new Long[]{1L, 2L}).asDouble(), 0.0); + assertEquals("[1, 2]", ExprEval.ofLongArray(new Long[]{1L, 2L}).asString()); + assertEquals(0, ExprEval.ofLongArray(new Long[]{1L, 2L}).asInt()); + assertEquals(false, ExprEval.ofLongArray(new Long[]{1L, 2L}).asBoolean()); + + assertEquals(1.1, ExprEval.ofDoubleArray(new Double[]{1.1}).asDouble(), 0.0); + assertEquals(1L, ExprEval.ofDoubleArray(new Double[]{1.1}).asLong()); + assertEquals("1.1", ExprEval.ofDoubleArray(new Double[]{1.1}).asString()); + assertEquals(1, ExprEval.ofDoubleArray(new Double[]{1.1}).asInt()); + assertEquals(true, ExprEval.ofDoubleArray(new Double[]{1.1}).asBoolean()); + + assertEquals(null, ExprEval.ofDoubleArray(new Double[]{null}).asString()); + + assertEquals(0.0, ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asDouble(), 0.0); + assertEquals(0L, ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asLong()); + assertEquals("[1.1, 2.2]", ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asString()); + assertEquals(0, ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asInt()); + assertEquals(false, ExprEval.ofDoubleArray(new Double[]{1.1, 2.2}).asBoolean()); + + assertEquals("foo", ExprEval.ofStringArray(new String[]{"foo"}).asString()); + + assertEquals("1", ExprEval.ofStringArray(new String[]{"1"}).asString()); + assertEquals(1L, ExprEval.ofStringArray(new String[]{"1"}).asLong()); + assertEquals(1.0, ExprEval.ofStringArray(new String[]{"1"}).asDouble(), 0.0); + assertEquals(1, ExprEval.ofStringArray(new String[]{"1"}).asInt()); + assertEquals(false, ExprEval.ofStringArray(new String[]{"1"}).asBoolean()); + assertEquals(true, ExprEval.ofStringArray(new String[]{"true"}).asBoolean()); + + assertEquals("[1, 2.2]", ExprEval.ofStringArray(new String[]{"1", "2.2"}).asString()); + assertEquals(0L, ExprEval.ofStringArray(new String[]{"1", "2.2"}).asLong()); + assertEquals(0.0, ExprEval.ofStringArray(new String[]{"1", "2.2"}).asDouble(), 0.0); + assertEquals(0, ExprEval.ofStringArray(new String[]{"1", "2.2"}).asInt()); + assertEquals(false, ExprEval.ofStringArray(new String[]{"1", "2.2"}).asBoolean()); // test casting arrays to scalars - Assert.assertEquals(1L, ExprEval.ofLongArray(new Long[]{1L}).castTo(ExpressionType.LONG).value()); - Assert.assertEquals(NullHandling.defaultLongValue(), ExprEval.ofLongArray(new Long[]{null}).castTo(ExpressionType.LONG).value()); - Assert.assertEquals(1.0, ExprEval.ofLongArray(new Long[]{1L}).castTo(ExpressionType.DOUBLE).asDouble(), 0.0); - Assert.assertEquals("1", ExprEval.ofLongArray(new Long[]{1L}).castTo(ExpressionType.STRING).value()); - - Assert.assertEquals(1.1, ExprEval.ofDoubleArray(new Double[]{1.1}).castTo(ExpressionType.DOUBLE).asDouble(), 0.0); - Assert.assertEquals(NullHandling.defaultDoubleValue(), ExprEval.ofDoubleArray(new Double[]{null}).castTo(ExpressionType.DOUBLE).value()); - Assert.assertEquals(1L, ExprEval.ofDoubleArray(new Double[]{1.1}).castTo(ExpressionType.LONG).value()); - Assert.assertEquals("1.1", ExprEval.ofDoubleArray(new Double[]{1.1}).castTo(ExpressionType.STRING).value()); - - Assert.assertEquals("foo", ExprEval.ofStringArray(new String[]{"foo"}).castTo(ExpressionType.STRING).value()); - Assert.assertEquals(NullHandling.defaultLongValue(), ExprEval.ofStringArray(new String[]{"foo"}).castTo(ExpressionType.LONG).value()); - Assert.assertEquals(NullHandling.defaultDoubleValue(), ExprEval.ofStringArray(new String[]{"foo"}).castTo(ExpressionType.DOUBLE).value()); - Assert.assertEquals("1", ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.STRING).value()); - Assert.assertEquals(1L, ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.LONG).value()); - Assert.assertEquals(1.0, ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.DOUBLE).value()); + assertEquals(1L, ExprEval.ofLongArray(new Long[]{1L}).castTo(ExpressionType.LONG).value()); + assertEquals(NullHandling.defaultLongValue(), ExprEval.ofLongArray(new Long[]{null}).castTo(ExpressionType.LONG).value()); + assertEquals(1.0, ExprEval.ofLongArray(new Long[]{1L}).castTo(ExpressionType.DOUBLE).asDouble(), 0.0); + assertEquals("1", ExprEval.ofLongArray(new Long[]{1L}).castTo(ExpressionType.STRING).value()); + + assertEquals(1.1, ExprEval.ofDoubleArray(new Double[]{1.1}).castTo(ExpressionType.DOUBLE).asDouble(), 0.0); + assertEquals(NullHandling.defaultDoubleValue(), ExprEval.ofDoubleArray(new Double[]{null}).castTo(ExpressionType.DOUBLE).value()); + assertEquals(1L, ExprEval.ofDoubleArray(new Double[]{1.1}).castTo(ExpressionType.LONG).value()); + assertEquals("1.1", ExprEval.ofDoubleArray(new Double[]{1.1}).castTo(ExpressionType.STRING).value()); + + assertEquals("foo", ExprEval.ofStringArray(new String[]{"foo"}).castTo(ExpressionType.STRING).value()); + assertEquals(NullHandling.defaultLongValue(), ExprEval.ofStringArray(new String[]{"foo"}).castTo(ExpressionType.LONG).value()); + assertEquals(NullHandling.defaultDoubleValue(), ExprEval.ofStringArray(new String[]{"foo"}).castTo(ExpressionType.DOUBLE).value()); + assertEquals("1", ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.STRING).value()); + assertEquals(1L, ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.LONG).value()); + assertEquals(1.0, ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.DOUBLE).value()); } @Test @@ -348,28 +380,200 @@ public void testBooleanReturn() Expr.ObjectBinding bindings = InputBindings.withMap( ImmutableMap.of("x", 100L, "y", 100L, "z", 100D, "w", 100D) ); - ExprEval eval = Parser.parse("x==y", ExprMacroTable.nil()).eval(bindings); - Assert.assertTrue(eval.asBoolean()); - Assert.assertEquals(ExpressionType.LONG, eval.type()); - eval = Parser.parse("x!=y", ExprMacroTable.nil()).eval(bindings); - Assert.assertFalse(eval.asBoolean()); - Assert.assertEquals(ExpressionType.LONG, eval.type()); + try { + ExpressionProcessing.initializeForStrictBooleansTests(false); + ExprEval eval = Parser.parse("x==z", ExprMacroTable.nil()).eval(bindings); + Assert.assertTrue(eval.asBoolean()); + assertEquals(ExpressionType.DOUBLE, eval.type()); - eval = Parser.parse("x==z", ExprMacroTable.nil()).eval(bindings); - Assert.assertTrue(eval.asBoolean()); - Assert.assertEquals(ExpressionType.DOUBLE, eval.type()); + eval = Parser.parse("x!=z", ExprMacroTable.nil()).eval(bindings); + Assert.assertFalse(eval.asBoolean()); + assertEquals(ExpressionType.DOUBLE, eval.type()); + + eval = Parser.parse("z==w", ExprMacroTable.nil()).eval(bindings); + Assert.assertTrue(eval.asBoolean()); + assertEquals(ExpressionType.DOUBLE, eval.type()); + + eval = Parser.parse("z!=w", ExprMacroTable.nil()).eval(bindings); + Assert.assertFalse(eval.asBoolean()); + assertEquals(ExpressionType.DOUBLE, eval.type()); + } + finally { + ExpressionProcessing.initializeForTests(null); + } + try { + ExpressionProcessing.initializeForStrictBooleansTests(true); + ExprEval eval = Parser.parse("x==y", ExprMacroTable.nil()).eval(bindings); + Assert.assertTrue(eval.asBoolean()); + assertEquals(ExpressionType.LONG, eval.type()); + + eval = Parser.parse("x!=y", ExprMacroTable.nil()).eval(bindings); + Assert.assertFalse(eval.asBoolean()); + assertEquals(ExpressionType.LONG, eval.type()); + + eval = Parser.parse("x==z", ExprMacroTable.nil()).eval(bindings); + Assert.assertTrue(eval.asBoolean()); + assertEquals(ExpressionType.LONG, eval.type()); + + eval = Parser.parse("x!=z", ExprMacroTable.nil()).eval(bindings); + Assert.assertFalse(eval.asBoolean()); + assertEquals(ExpressionType.LONG, eval.type()); + + eval = Parser.parse("z==w", ExprMacroTable.nil()).eval(bindings); + Assert.assertTrue(eval.asBoolean()); + assertEquals(ExpressionType.LONG, eval.type()); + + eval = Parser.parse("z!=w", ExprMacroTable.nil()).eval(bindings); + Assert.assertFalse(eval.asBoolean()); + assertEquals(ExpressionType.LONG, eval.type()); + } + finally { + ExpressionProcessing.initializeForTests(null); + } + } - eval = Parser.parse("x!=z", ExprMacroTable.nil()).eval(bindings); - Assert.assertFalse(eval.asBoolean()); - Assert.assertEquals(ExpressionType.DOUBLE, eval.type()); + @Test + public void testLogicalOperators() + { + Expr.ObjectBinding bindings = InputBindings.withMap( + ImmutableMap.of() + ); - eval = Parser.parse("z==w", ExprMacroTable.nil()).eval(bindings); - Assert.assertTrue(eval.asBoolean()); - Assert.assertEquals(ExpressionType.DOUBLE, eval.type()); + try { + ExpressionProcessing.initializeForStrictBooleansTests(true); + assertEquals(1L, eval("'true' && 'true'", bindings).value()); + assertEquals(0L, eval("'true' && 'false'", bindings).value()); + assertEquals(0L, eval("'false' && 'true'", bindings).value()); + assertEquals(0L, eval("'troo' && 'true'", bindings).value()); + assertEquals(0L, eval("'false' && 'false'", bindings).value()); + + assertEquals(1L, eval("'true' || 'true'", bindings).value()); + assertEquals(1L, eval("'true' || 'false'", bindings).value()); + assertEquals(1L, eval("'false' || 'true'", bindings).value()); + assertEquals(1L, eval("'troo' || 'true'", bindings).value()); + assertEquals(0L, eval("'false' || 'false'", bindings).value()); + + assertEquals(1L, eval("1 && 1", bindings).value()); + assertEquals(1L, eval("100 && 11", bindings).value()); + assertEquals(0L, eval("1 && 0", bindings).value()); + assertEquals(0L, eval("0 && 1", bindings).value()); + assertEquals(0L, eval("0 && 0", bindings).value()); + + assertEquals(1L, eval("1 || 1", bindings).value()); + assertEquals(1L, eval("100 || 11", bindings).value()); + assertEquals(1L, eval("1 || 0", bindings).value()); + assertEquals(1L, eval("0 || 1", bindings).value()); + assertEquals(1L, eval("111 || 0", bindings).value()); + assertEquals(1L, eval("0 || 111", bindings).value()); + assertEquals(0L, eval("0 || 0", bindings).value()); + + assertEquals(1L, eval("1.0 && 1.0", bindings).value()); + assertEquals(1L, eval("0.100 && 1.1", bindings).value()); + assertEquals(0L, eval("1.0 && 0.0", bindings).value()); + assertEquals(0L, eval("0.0 && 1.0", bindings).value()); + assertEquals(0L, eval("0.0 && 0.0", bindings).value()); + + assertEquals(1L, eval("1.0 || 1.0", bindings).value()); + assertEquals(1L, eval("0.2 || 0.3", bindings).value()); + assertEquals(1L, eval("1.0 || 0.0", bindings).value()); + assertEquals(1L, eval("0.0 || 1.0", bindings).value()); + assertEquals(1L, eval("1.11 || 0.0", bindings).value()); + assertEquals(1L, eval("0.0 || 0.111", bindings).value()); + assertEquals(0L, eval("0.0 || 0.0", bindings).value()); + + assertEquals(1L, eval("null || 1", bindings).value()); + assertEquals(1L, eval("1 || null", bindings).value()); + assertEquals(NullHandling.defaultLongValue(), eval("null || 0", bindings).value()); + assertEquals(NullHandling.defaultLongValue(), eval("0 || null", bindings).value()); + // null/null is evaluated as string typed + assertEquals(NullHandling.defaultLongValue(), eval("null || null", bindings).value()); + + assertEquals(NullHandling.defaultLongValue(), eval("null && 1", bindings).value()); + assertEquals(NullHandling.defaultLongValue(), eval("1 && null", bindings).value()); + assertEquals(0L, eval("null && 0", bindings).value()); + assertEquals(0L, eval("0 && null", bindings).value()); + // null/null is evaluated as string typed + assertEquals(NullHandling.defaultLongValue(), eval("null && null", bindings).value()); + } + finally { + // reset + ExpressionProcessing.initializeForTests(null); + } - eval = Parser.parse("z!=w", ExprMacroTable.nil()).eval(bindings); - Assert.assertFalse(eval.asBoolean()); - Assert.assertEquals(ExpressionType.DOUBLE, eval.type()); + try { + // turn on legacy insanity mode + ExpressionProcessing.initializeForStrictBooleansTests(false); + + assertEquals("true", eval("'true' && 'true'", bindings).value()); + assertEquals("false", eval("'true' && 'false'", bindings).value()); + assertEquals("false", eval("'false' && 'true'", bindings).value()); + assertEquals("troo", eval("'troo' && 'true'", bindings).value()); + assertEquals("false", eval("'false' && 'false'", bindings).value()); + + assertEquals("true", eval("'true' || 'true'", bindings).value()); + assertEquals("true", eval("'true' || 'false'", bindings).value()); + assertEquals("true", eval("'false' || 'true'", bindings).value()); + assertEquals("true", eval("'troo' || 'true'", bindings).value()); + assertEquals("false", eval("'false' || 'false'", bindings).value()); + + assertEquals(1.0, eval("1.0 && 1.0", bindings).value()); + assertEquals(1.1, eval("0.100 && 1.1", bindings).value()); + assertEquals(0.0, eval("1.0 && 0.0", bindings).value()); + assertEquals(0.0, eval("0.0 && 1.0", bindings).value()); + assertEquals(0.0, eval("0.0 && 0.0", bindings).value()); + + assertEquals(1.0, eval("1.0 || 1.0", bindings).value()); + assertEquals(0.2, eval("0.2 || 0.3", bindings).value()); + assertEquals(1.0, eval("1.0 || 0.0", bindings).value()); + assertEquals(1.0, eval("0.0 || 1.0", bindings).value()); + assertEquals(1.11, eval("1.11 || 0.0", bindings).value()); + assertEquals(0.111, eval("0.0 || 0.111", bindings).value()); + assertEquals(0.0, eval("0.0 || 0.0", bindings).value()); + + assertEquals(1L, eval("1 && 1", bindings).value()); + assertEquals(11L, eval("100 && 11", bindings).value()); + assertEquals(0L, eval("1 && 0", bindings).value()); + assertEquals(0L, eval("0 && 1", bindings).value()); + assertEquals(0L, eval("0 && 0", bindings).value()); + + assertEquals(1L, eval("1 || 1", bindings).value()); + assertEquals(100L, eval("100 || 11", bindings).value()); + assertEquals(1L, eval("1 || 0", bindings).value()); + assertEquals(1L, eval("0 || 1", bindings).value()); + assertEquals(111L, eval("111 || 0", bindings).value()); + assertEquals(111L, eval("0 || 111", bindings).value()); + assertEquals(0L, eval("0 || 0", bindings).value()); + + assertEquals(1.0, eval("1.0 && 1.0", bindings).value()); + assertEquals(1.1, eval("0.100 && 1.1", bindings).value()); + assertEquals(0.0, eval("1.0 && 0.0", bindings).value()); + assertEquals(0.0, eval("0.0 && 1.0", bindings).value()); + assertEquals(0.0, eval("0.0 && 0.0", bindings).value()); + + assertEquals(1.0, eval("1.0 || 1.0", bindings).value()); + assertEquals(0.2, eval("0.2 || 0.3", bindings).value()); + assertEquals(1.0, eval("1.0 || 0.0", bindings).value()); + assertEquals(1.0, eval("0.0 || 1.0", bindings).value()); + assertEquals(1.11, eval("1.11 || 0.0", bindings).value()); + assertEquals(0.111, eval("0.0 || 0.111", bindings).value()); + assertEquals(0.0, eval("0.0 || 0.0", bindings).value()); + + assertEquals(1L, eval("null || 1", bindings).value()); + assertEquals(1L, eval("1 || null", bindings).value()); + assertEquals(0L, eval("null || 0", bindings).value()); + Assert.assertNull(eval("0 || null", bindings).value()); + Assert.assertNull(eval("null || null", bindings).value()); + + Assert.assertNull(eval("null && 1", bindings).value()); + Assert.assertNull(eval("1 && null", bindings).value()); + Assert.assertNull(eval("null && 0", bindings).value()); + assertEquals(0L, eval("0 && null", bindings).value()); + assertNull(eval("null && null", bindings).value()); + } + finally { + // reset + ExpressionProcessing.initializeForTests(null); + } } } diff --git a/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java b/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java index 2cb097e85ca7..e2f14dd712df 100644 --- a/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java @@ -75,12 +75,29 @@ public void testUnaryOperators() assertOutputType("-y", inspector, ExpressionType.LONG); assertOutputType("-z", inspector, ExpressionType.DOUBLE); - assertOutputType("!'true'", inspector, ExpressionType.LONG); - assertOutputType("!1", inspector, ExpressionType.LONG); - assertOutputType("!1.1", inspector, ExpressionType.DOUBLE); - assertOutputType("!x", inspector, ExpressionType.LONG); - assertOutputType("!y", inspector, ExpressionType.LONG); - assertOutputType("!z", inspector, ExpressionType.DOUBLE); + try { + ExpressionProcessing.initializeForStrictBooleansTests(true); + assertOutputType("!'true'", inspector, ExpressionType.LONG); + assertOutputType("!1", inspector, ExpressionType.LONG); + assertOutputType("!x", inspector, ExpressionType.LONG); + assertOutputType("!y", inspector, ExpressionType.LONG); + assertOutputType("!1.1", inspector, ExpressionType.LONG); + assertOutputType("!z", inspector, ExpressionType.LONG); + } + finally { + // reset + ExpressionProcessing.initializeForTests(null); + } + + try { + ExpressionProcessing.initializeForStrictBooleansTests(false); + assertOutputType("!1.1", inspector, ExpressionType.DOUBLE); + assertOutputType("!z", inspector, ExpressionType.DOUBLE); + } + finally { + // reset + ExpressionProcessing.initializeForTests(null); + } } @Test @@ -114,33 +131,61 @@ public void testBinaryMathOperators() assertOutputType("z^z_", inspector, ExpressionType.DOUBLE); assertOutputType("z%z_", inspector, ExpressionType.DOUBLE); - assertOutputType("y>y_", inspector, ExpressionType.LONG); - assertOutputType("y_=y", inspector, ExpressionType.LONG); - assertOutputType("y_==y", inspector, ExpressionType.LONG); - assertOutputType("y_!=y", inspector, ExpressionType.LONG); - assertOutputType("y_ && y", inspector, ExpressionType.LONG); - assertOutputType("y_ || y", inspector, ExpressionType.LONG); - - assertOutputType("z>y_", inspector, ExpressionType.DOUBLE); - assertOutputType("z=z", inspector, ExpressionType.DOUBLE); - assertOutputType("z==y", inspector, ExpressionType.DOUBLE); - assertOutputType("z!=y", inspector, ExpressionType.DOUBLE); - assertOutputType("z && y", inspector, ExpressionType.DOUBLE); - assertOutputType("y || z", inspector, ExpressionType.DOUBLE); - - assertOutputType("z>z_", inspector, ExpressionType.DOUBLE); - assertOutputType("z=z", inspector, ExpressionType.DOUBLE); - assertOutputType("z==z_", inspector, ExpressionType.DOUBLE); - assertOutputType("z!=z_", inspector, ExpressionType.DOUBLE); - assertOutputType("z && z_", inspector, ExpressionType.DOUBLE); - assertOutputType("z_ || z", inspector, ExpressionType.DOUBLE); - + try { + ExpressionProcessing.initializeForStrictBooleansTests(true); + assertOutputType("y>y_", inspector, ExpressionType.LONG); + assertOutputType("y_=y", inspector, ExpressionType.LONG); + assertOutputType("y_==y", inspector, ExpressionType.LONG); + assertOutputType("y_!=y", inspector, ExpressionType.LONG); + assertOutputType("y_ && y", inspector, ExpressionType.LONG); + assertOutputType("y_ || y", inspector, ExpressionType.LONG); + + assertOutputType("z>y_", inspector, ExpressionType.LONG); + assertOutputType("z=z", inspector, ExpressionType.LONG); + assertOutputType("z==y", inspector, ExpressionType.LONG); + assertOutputType("z!=y", inspector, ExpressionType.LONG); + assertOutputType("z && y", inspector, ExpressionType.LONG); + assertOutputType("y || z", inspector, ExpressionType.LONG); + + assertOutputType("z>z_", inspector, ExpressionType.LONG); + assertOutputType("z=z", inspector, ExpressionType.LONG); + assertOutputType("z==z_", inspector, ExpressionType.LONG); + assertOutputType("z!=z_", inspector, ExpressionType.LONG); + assertOutputType("z && z_", inspector, ExpressionType.LONG); + assertOutputType("z_ || z", inspector, ExpressionType.LONG); + } + finally { + ExpressionProcessing.initializeForTests(null); + } + try { + ExpressionProcessing.initializeForStrictBooleansTests(false); + assertOutputType("z>y_", inspector, ExpressionType.DOUBLE); + assertOutputType("z=z", inspector, ExpressionType.DOUBLE); + assertOutputType("z==y", inspector, ExpressionType.DOUBLE); + assertOutputType("z!=y", inspector, ExpressionType.DOUBLE); + assertOutputType("z && y", inspector, ExpressionType.DOUBLE); + assertOutputType("y || z", inspector, ExpressionType.DOUBLE); + + assertOutputType("z>z_", inspector, ExpressionType.DOUBLE); + assertOutputType("z=z", inspector, ExpressionType.DOUBLE); + assertOutputType("z==z_", inspector, ExpressionType.DOUBLE); + assertOutputType("z!=z_", inspector, ExpressionType.DOUBLE); + assertOutputType("z && z_", inspector, ExpressionType.DOUBLE); + assertOutputType("z_ || z", inspector, ExpressionType.DOUBLE); + } + finally { + ExpressionProcessing.initializeForTests(null); + } assertOutputType("1*(2 + 3.0)", inspector, ExpressionType.DOUBLE); } diff --git a/core/src/test/java/org/apache/druid/math/expr/VectorExprSanityTest.java b/core/src/test/java/org/apache/druid/math/expr/VectorExprSanityTest.java index 81abed544c10..5061d414a4e8 100644 --- a/core/src/test/java/org/apache/druid/math/expr/VectorExprSanityTest.java +++ b/core/src/test/java/org/apache/druid/math/expr/VectorExprSanityTest.java @@ -26,7 +26,9 @@ import org.apache.druid.java.util.common.logger.Logger; import org.apache.druid.math.expr.vector.ExprEvalVector; import org.apache.druid.testing.InitializedNullHandlingTest; +import org.junit.AfterClass; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; import javax.annotation.Nullable; @@ -58,8 +60,22 @@ public class VectorExprSanityTest extends InitializedNullHandlingTest .put("d2", ExpressionType.DOUBLE) .put("s1", ExpressionType.STRING) .put("s2", ExpressionType.STRING) + .put("boolString1", ExpressionType.STRING) + .put("boolString2", ExpressionType.STRING) .build(); + @BeforeClass + public static void setupTests() + { + ExpressionProcessing.initializeForStrictBooleansTests(true); + } + + @AfterClass + public static void teardownTests() + { + ExpressionProcessing.initializeForTests(null); + } + @Test public void testUnaryOperators() { @@ -99,6 +115,22 @@ public void testBinaryComparisonOperators() testFunctions(types, templates, args); } + @Test + public void testUnaryLogicOperators() + { + final String[] functions = new String[]{"!"}; + final String[] templates = new String[]{"%sd1", "%sl1", "%sboolString1"}; + testFunctions(types, templates, functions); + } + + @Test + public void testBinaryLogicOperators() + { + final String[] functions = new String[]{"&&", "||"}; + final String[] templates = new String[]{"d1 %s d2", "l1 %s l2", "boolString1 %s boolString2"}; + testFunctions(types, templates, functions); + } + @Test public void testBinaryOperatorTrees() { @@ -117,7 +149,7 @@ public void testBinaryOperatorTrees() @Test public void testUnivariateFunctions() { - final String[] functions = new String[]{"parse_long"}; + final String[] functions = new String[]{"parse_long", "isNull", "notNull"}; final String[] templates = new String[]{"%s(s1)", "%s(l1)", "%s(d1)", "%s(nonexistent)", "%s(null)"}; testFunctions(types, templates, functions); } @@ -192,6 +224,23 @@ public void testBivariateMathFunctions() testFunctions(types, templates, functions); } + @Test + public void testSymmetricalBivariateFunctions() + { + final String[] functions = new String[]{ + "nvl", + }; + final String[] templates = new String[]{ + "%s(d1, d2)", + "%s(l1, l2)", + "%s(s1, s2)", + "%s(nonexistent, l1)", + "%s(nonexistent, d1)", + "%s(nonexistent, s1)" + }; + testFunctions(types, templates, functions); + } + @Test public void testCast() { @@ -385,7 +434,11 @@ static NonnullPair makeBindings( String[] strings = new String[vectorSize]; for (int i = 0; i < vectorSize; i++) { nulls[i] = hasNulls && nullsFn.getAsBoolean(); - strings[i] = nulls[i] ? null : String.valueOf(stringFn.get()); + if (!nulls[i] && entry.getKey().startsWith("boolString")) { + strings[i] = String.valueOf(nullsFn.getAsBoolean()); + } else { + strings[i] = nulls[i] ? null : String.valueOf(stringFn.get()); + } if (objectBindings[i] == null) { objectBindings[i] = new SettableObjectBinding(); } diff --git a/docs/configuration/index.md b/docs/configuration/index.md index 0708c07e16db..f35d70676578 100644 --- a/docs/configuration/index.md +++ b/docs/configuration/index.md @@ -2109,6 +2109,12 @@ Supported query contexts: |`maxResults`|Ignored by groupBy v2. Can be used to lower the value of `druid.query.groupBy.maxResults` for a groupBy v1 query.|None| |`useOffheap`|Ignored by groupBy v2, and no longer supported for groupBy v1. Enabling this option with groupBy v1 will result in an error. For off-heap aggregation, switch to groupBy v2, which always operates off-heap.|false| +#### Expression processing configurations + +|Key|Description|Default| +|---|-----------|-------| +|`druid.expressions.useStrictBooleans`|Controls the behavior of Druid boolean operators and functions, if set to `true` all boolean values will be either a `1` or `0`. See [expression documentation](../misc/math-expr.md#logical-operator-modes)|false| +|`druid.expressions.allowNestedArrays`|If enabled, Druid array expressions can create nested arrays. This is experimental and should be used with caution.|false| ### Router #### Router Process Configs diff --git a/docs/misc/math-expr.md b/docs/misc/math-expr.md index 99e86bd5fc5f..14cbc038506f 100644 --- a/docs/misc/math-expr.md +++ b/docs/misc/math-expr.md @@ -65,8 +65,10 @@ The following built-in functions are available. |if|if(predicate,then,else) returns 'then' if 'predicate' evaluates to a positive number, otherwise it returns 'else' | |nvl|nvl(expr,expr-for-null) returns 'expr-for-null' if 'expr' is null (or empty string for string type) | |like|like(expr, pattern[, escape]) is equivalent to SQL `expr LIKE pattern`| -|case_searched|case_searched(expr1, result1, \[\[expr2, result2, ...\], else-result\])| -|case_simple|case_simple(expr, value1, result1, \[\[value2, result2, ...\], else-result\])| +|case_searched|case_searched(expr1, result1, \[\[expr2, result2, ...\], else-result\]) is similar to `CASE WHEN expr1 THEN result1 [ELSE else_result] END` in SQL| +|case_simple|case_simple(expr, value1, result1, \[\[value2, result2, ...\], else-result\]) is similar to `CASE expr WHEN value THEN result [ELSE else_result] END` in SQL| +|isnull|isnull(expr) returns 1 if the value is null, else 0| +|notnull|notnull(expr) returns 1 if the value is not null, else 0| |bloom_filter_test|bloom_filter_test(expr, filter) tests the value of 'expr' against 'filter', a bloom filter serialized as a base64 string. See [bloom filter extension](../development/extensions-core/bloom-filter.md) documentation for additional details.| ## String functions @@ -249,6 +251,14 @@ For the IPv4 address functions, the `address` argument can either be an IPv4 dot | ipv4_parse(address) | Parses `address` into an IPv4 address stored as a long. If `address` is a long that is a valid IPv4 address, then it is passed through. Returns null if `address` cannot be represented as an IPv4 address. | | ipv4_stringify(address) | Converts `address` into an IPv4 address dotted-decimal string. If `address` is a string that is a valid IPv4 address, then it is passed through. Returns null if `address` cannot be represented as an IPv4 address.| +## Other functions + +| function | description | +| --- | --- | +| human_readable_binary_byte_format(value[, precision]) | Format a number in human-readable [IEC](https://en.wikipedia.org/wiki/Binary_prefix) format. `precision` must be in the range of [0,3] (default: 2). For example:
  • human_readable_binary_byte_format(1048576) returns `1.00 MiB`
  • human_readable_binary_byte_format(1048576, 3) returns `1.000 MiB`
  • | +| human_readable_decimal_byte_format(value[, precision]) | Format a number in human-readable [SI](https://en.wikipedia.org/wiki/Binary_prefix) format. `precision` must be in the range of [0,3] (default: 2). For example:
  • human_readable_decimal_byte_format(1000000) returns `1.00 MB`
  • human_readable_decimal_byte_format(1000000, 3) returns `1.000 MB`
  • | +| human_readable_decimal_format(value[, precision]) | Format a number in human-readable SI format. `precision` must be in the range of [0,3] (default: 2). For example:
  • human_readable_decimal_format(1000000) returns `1.00 M`
  • human_readable_decimal_format(1000000, 3) returns `1.000 M`
  • | + ## Vectorization Support A number of expressions support ['vectorized' query engines](../querying/query-context.md#vectorization-parameters) @@ -257,16 +267,44 @@ supported features: * constants and identifiers are supported for any column type * `cast` is supported for numeric and string types * math operators: `+`,`-`,`*`,`/`,`%`,`^` are supported for numeric types -* comparison operators: `=`, `!=`, `>`, `>=`, `<`, `<=` are supported for numeric types +* logical operators: `!`, `&&`, `||`, are supported for string and numeric types (if `druid.expressions.useStrictBooleans=true`) +* comparison operators: `=`, `!=`, `>`, `>=`, `<`, `<=` are supported for string and numeric types * math functions: `abs`, `acos`, `asin`, `atan`, `cbrt`, `ceil`, `cos`, `cosh`, `cot`, `exp`, `expm1`, `floor`, `getExponent`, `log`, `log10`, `log1p`, `nextUp`, `rint`, `signum`, `sin`, `sinh`, `sqrt`, `tan`, `tanh`, `toDegrees`, `toRadians`, `ulp`, `atan2`, `copySign`, `div`, `hypot`, `max`, `min`, `nextAfter`, `pow`, `remainder`, `scalb` are supported for numeric types * time functions: `timestamp_floor` (with constant granularity argument) is supported for numeric types +* boolean functions: `isnull`, `notnull` are supported for string and numeric types +* conditional functions: `nvl` is supported for string and numeric types +* string functions: the concatenation operator (`+`) and `concat` function are supported for string and numeric types * other: `parse_long` is supported for numeric and string types +## Logical operator modes +Prior to the 0.23 release of Apache Druid, boolean function expressions have inconsistent handling of true and false values, and the logical 'and' and 'or' operators behave in a manner that is incompatible with SQL, even if SQL compatible null handling mode (`druid.generic.useDefaultValueForNull=false`) is enabled. Logical operators also pass through their input values similar to many scripting languages, and treat `null` as false, which can result in some rather strange behavior. Other boolean operations, such as comparisons and equality, retain their input types (e.g. `DOUBLE` comparison would produce `1.0` for true and `0.0` for false), while many other boolean functions strictly produce `LONG` typed values of `1` for true and `0` for false. + +After 0.23, while the inconsistent legacy behavior is still the default, it can be optionally be changed by setting `druid.expressions.useStrictBooleans=true`, so that these operations will allow correctly treating `null` values as "unknown" for SQL compatible behavior, and _all boolean output functions_ will output 'homogeneous' `LONG` typed boolean values of `1` for `true` and `0` for `false`. Additionally, + +For the "or" operator: +* `true || null`, `null || true`, -> `1` +* `false || null`, `null || false`, `null || null`-> `null` + +For the "and" operator: +* `true && null`, `null && true`, `null && null` -> `null` +* `false && null`, `null && false` -> `0` + +Druid currently still retains implicit conversion of `LONG`, `DOUBLE`, and `STRING` types into boolean values in both modes: +* `LONG` or `DOUBLE` - any value greater than 0 is considered `true`, else `false` +* `STRING` - the value `'true'` (case insensitive) is considered `true`, everything else is `false`. + +Legacy behavior: +* `100 && 11` -> `11` +* `0.7 || 0.3` -> `0.3` +* `100 && 0` -> `0` +* `'troo' && 'true'` -> `'troo'` +* `'troo' || 'true'` -> `'true'` + +SQL compatible behavior: +* `100 && 11` -> `1` +* `0.7 || 0.3` -> `1` +* `100 && 0` -> `0` +* `'troo' && 'true'` -> `0` +* `'troo' || 'true'` -> `1` -## Other functions -| function | description | -| --- | --- | -| human_readable_binary_byte_format(value[, precision]) | Format a number in human-readable [IEC](https://en.wikipedia.org/wiki/Binary_prefix) format. `precision` must be in the range of [0,3] (default: 2). For example:
  • human_readable_binary_byte_format(1048576) returns `1.00 MiB`
  • human_readable_binary_byte_format(1048576, 3) returns `1.000 MiB`
  • | -| human_readable_decimal_byte_format(value[, precision]) | Format a number in human-readable [SI](https://en.wikipedia.org/wiki/Binary_prefix) format. `precision` must be in the range of [0,3] (default: 2). For example:
  • human_readable_decimal_byte_format(1000000) returns `1.00 MB`
  • human_readable_decimal_byte_format(1000000, 3) returns `1.000 MB`
  • | -| human_readable_decimal_format(value[, precision]) | Format a number in human-readable SI format. `precision` must be in the range of [0,3] (default: 2). For example:
  • human_readable_decimal_format(1000000) returns `1.00 M`
  • human_readable_decimal_format(1000000, 3) returns `1.000 M`
  • | diff --git a/examples/conf/druid/cluster/_common/common.runtime.properties b/examples/conf/druid/cluster/_common/common.runtime.properties index 7f74ffbf4b69..fbd790f215e3 100644 --- a/examples/conf/druid/cluster/_common/common.runtime.properties +++ b/examples/conf/druid/cluster/_common/common.runtime.properties @@ -142,4 +142,9 @@ druid.sql.enable=true # # Lookups # -druid.lookup.enableLookupSyncOnStartup=false \ No newline at end of file +druid.lookup.enableLookupSyncOnStartup=false + +# +# Expression processing config +# +druid.expressions.useStrictBooleans=true diff --git a/examples/conf/druid/single-server/large/_common/common.runtime.properties b/examples/conf/druid/single-server/large/_common/common.runtime.properties index 7f74ffbf4b69..fbd790f215e3 100644 --- a/examples/conf/druid/single-server/large/_common/common.runtime.properties +++ b/examples/conf/druid/single-server/large/_common/common.runtime.properties @@ -142,4 +142,9 @@ druid.sql.enable=true # # Lookups # -druid.lookup.enableLookupSyncOnStartup=false \ No newline at end of file +druid.lookup.enableLookupSyncOnStartup=false + +# +# Expression processing config +# +druid.expressions.useStrictBooleans=true diff --git a/examples/conf/druid/single-server/medium/_common/common.runtime.properties b/examples/conf/druid/single-server/medium/_common/common.runtime.properties index 7f74ffbf4b69..fbd790f215e3 100644 --- a/examples/conf/druid/single-server/medium/_common/common.runtime.properties +++ b/examples/conf/druid/single-server/medium/_common/common.runtime.properties @@ -142,4 +142,9 @@ druid.sql.enable=true # # Lookups # -druid.lookup.enableLookupSyncOnStartup=false \ No newline at end of file +druid.lookup.enableLookupSyncOnStartup=false + +# +# Expression processing config +# +druid.expressions.useStrictBooleans=true diff --git a/examples/conf/druid/single-server/micro-quickstart/_common/common.runtime.properties b/examples/conf/druid/single-server/micro-quickstart/_common/common.runtime.properties index 7f74ffbf4b69..fbd790f215e3 100644 --- a/examples/conf/druid/single-server/micro-quickstart/_common/common.runtime.properties +++ b/examples/conf/druid/single-server/micro-quickstart/_common/common.runtime.properties @@ -142,4 +142,9 @@ druid.sql.enable=true # # Lookups # -druid.lookup.enableLookupSyncOnStartup=false \ No newline at end of file +druid.lookup.enableLookupSyncOnStartup=false + +# +# Expression processing config +# +druid.expressions.useStrictBooleans=true diff --git a/examples/conf/druid/single-server/nano-quickstart/_common/common.runtime.properties b/examples/conf/druid/single-server/nano-quickstart/_common/common.runtime.properties index 7f74ffbf4b69..fbd790f215e3 100644 --- a/examples/conf/druid/single-server/nano-quickstart/_common/common.runtime.properties +++ b/examples/conf/druid/single-server/nano-quickstart/_common/common.runtime.properties @@ -142,4 +142,9 @@ druid.sql.enable=true # # Lookups # -druid.lookup.enableLookupSyncOnStartup=false \ No newline at end of file +druid.lookup.enableLookupSyncOnStartup=false + +# +# Expression processing config +# +druid.expressions.useStrictBooleans=true diff --git a/examples/conf/druid/single-server/small/_common/common.runtime.properties b/examples/conf/druid/single-server/small/_common/common.runtime.properties index 7f74ffbf4b69..fbd790f215e3 100644 --- a/examples/conf/druid/single-server/small/_common/common.runtime.properties +++ b/examples/conf/druid/single-server/small/_common/common.runtime.properties @@ -142,4 +142,9 @@ druid.sql.enable=true # # Lookups # -druid.lookup.enableLookupSyncOnStartup=false \ No newline at end of file +druid.lookup.enableLookupSyncOnStartup=false + +# +# Expression processing config +# +druid.expressions.useStrictBooleans=true diff --git a/examples/conf/druid/single-server/xlarge/_common/common.runtime.properties b/examples/conf/druid/single-server/xlarge/_common/common.runtime.properties index 7f74ffbf4b69..fbd790f215e3 100644 --- a/examples/conf/druid/single-server/xlarge/_common/common.runtime.properties +++ b/examples/conf/druid/single-server/xlarge/_common/common.runtime.properties @@ -142,4 +142,9 @@ druid.sql.enable=true # # Lookups # -druid.lookup.enableLookupSyncOnStartup=false \ No newline at end of file +druid.lookup.enableLookupSyncOnStartup=false + +# +# Expression processing config +# +druid.expressions.useStrictBooleans=true diff --git a/extensions-core/parquet-extensions/src/main/java/org/apache/druid/data/input/parquet/simple/ParquetGroupConverter.java b/extensions-core/parquet-extensions/src/main/java/org/apache/druid/data/input/parquet/simple/ParquetGroupConverter.java index 24d5f556475c..1535f56fe69b 100644 --- a/extensions-core/parquet-extensions/src/main/java/org/apache/druid/data/input/parquet/simple/ParquetGroupConverter.java +++ b/extensions-core/parquet-extensions/src/main/java/org/apache/druid/data/input/parquet/simple/ParquetGroupConverter.java @@ -93,7 +93,7 @@ private static Object convertField(Group g, String fieldName, boolean binaryAsSt return convertLogicalList(g.getGroup(fieldIndex, 0), binaryAsString); } - // not a list, but not a primtive, return the nested group type + // not a list, but not a primitive, return the nested group type return g.getGroup(fieldIndex, 0); } } diff --git a/processing/src/main/java/org/apache/druid/query/expression/TimestampFloorExprMacro.java b/processing/src/main/java/org/apache/druid/query/expression/TimestampFloorExprMacro.java index 20507ad80050..2e1bee0578e4 100644 --- a/processing/src/main/java/org/apache/druid/query/expression/TimestampFloorExprMacro.java +++ b/processing/src/main/java/org/apache/druid/query/expression/TimestampFloorExprMacro.java @@ -28,7 +28,7 @@ import org.apache.druid.math.expr.InputBindings; import org.apache.druid.math.expr.vector.CastToTypeVectorProcessor; import org.apache.druid.math.expr.vector.ExprVectorProcessor; -import org.apache.druid.math.expr.vector.LongOutLongInFunctionVectorProcessor; +import org.apache.druid.math.expr.vector.LongOutLongInFunctionVectorValueProcessor; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -133,7 +133,7 @@ public boolean canVectorize(InputBindingInspector inspector) public ExprVectorProcessor buildVectorized(VectorInputBindingInspector inspector) { ExprVectorProcessor processor; - processor = new LongOutLongInFunctionVectorProcessor( + processor = new LongOutLongInFunctionVectorValueProcessor( CastToTypeVectorProcessor.cast(args.get(0).buildVectorized(inspector), ExpressionType.LONG), inspector.getMaxVectorSize() ) diff --git a/processing/src/test/java/org/apache/druid/query/expression/CaseInsensitiveExprMacroTest.java b/processing/src/test/java/org/apache/druid/query/expression/CaseInsensitiveExprMacroTest.java index ca03bbe3942d..ebc92b8666d4 100644 --- a/processing/src/test/java/org/apache/druid/query/expression/CaseInsensitiveExprMacroTest.java +++ b/processing/src/test/java/org/apache/druid/query/expression/CaseInsensitiveExprMacroTest.java @@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableMap; import org.apache.druid.common.config.NullHandling; import org.apache.druid.math.expr.ExprEval; -import org.apache.druid.math.expr.ExprType; import org.apache.druid.math.expr.InputBindings; import org.junit.Assert; import org.junit.Test; @@ -53,7 +52,7 @@ public void testMatchSearchLowerCase() { final ExprEval result = eval("icontains_string(a, 'OBA')", InputBindings.withMap(ImmutableMap.of("a", "foobar"))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -63,7 +62,7 @@ public void testMatchSearchUpperCase() { final ExprEval result = eval("icontains_string(a, 'oba')", InputBindings.withMap(ImmutableMap.of("a", "FOOBAR"))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -73,7 +72,7 @@ public void testNoMatch() { final ExprEval result = eval("icontains_string(a, 'bar')", InputBindings.withMap(ImmutableMap.of("a", "foo"))); Assert.assertEquals( - ExprEval.ofBoolean(false, ExprType.LONG).value(), + ExprEval.ofLongBoolean(false).value(), result.value() ); } @@ -87,7 +86,7 @@ public void testNullSearch() final ExprEval result = eval("icontains_string(a, null)", InputBindings.withMap(ImmutableMap.of("a", "foo"))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -97,7 +96,7 @@ public void testEmptyStringSearch() { final ExprEval result = eval("icontains_string(a, '')", InputBindings.withMap(ImmutableMap.of("a", "foo"))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -111,7 +110,7 @@ public void testNullSearchOnEmptyString() final ExprEval result = eval("icontains_string(a, null)", InputBindings.withMap(ImmutableMap.of("a", ""))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -121,7 +120,7 @@ public void testEmptyStringSearchOnEmptyString() { final ExprEval result = eval("icontains_string(a, '')", InputBindings.withMap(ImmutableMap.of("a", ""))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -138,7 +137,7 @@ public void testNullSearchOnNull() InputBindings.nilBindings() ); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -148,7 +147,7 @@ public void testEmptyStringSearchOnNull() { final ExprEval result = eval("icontains_string(a, '')", InputBindings.nilBindings()); Assert.assertEquals( - ExprEval.ofBoolean(!NullHandling.sqlCompatible(), ExprType.LONG).value(), + ExprEval.ofLongBoolean(!NullHandling.sqlCompatible()).value(), result.value() ); } diff --git a/processing/src/test/java/org/apache/druid/query/expression/ContainsExprMacroTest.java b/processing/src/test/java/org/apache/druid/query/expression/ContainsExprMacroTest.java index 883a435e9b01..4a29670540dd 100644 --- a/processing/src/test/java/org/apache/druid/query/expression/ContainsExprMacroTest.java +++ b/processing/src/test/java/org/apache/druid/query/expression/ContainsExprMacroTest.java @@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableMap; import org.apache.druid.common.config.NullHandling; import org.apache.druid.math.expr.ExprEval; -import org.apache.druid.math.expr.ExprType; import org.apache.druid.math.expr.InputBindings; import org.junit.Assert; import org.junit.Test; @@ -53,7 +52,7 @@ public void testMatch() { final ExprEval result = eval("contains_string(a, 'oba')", InputBindings.withMap(ImmutableMap.of("a", "foobar"))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -63,7 +62,7 @@ public void testNoMatch() { final ExprEval result = eval("contains_string(a, 'bar')", InputBindings.withMap(ImmutableMap.of("a", "foo"))); Assert.assertEquals( - ExprEval.ofBoolean(false, ExprType.LONG).value(), + ExprEval.ofLongBoolean(false).value(), result.value() ); } @@ -77,7 +76,7 @@ public void testNullSearch() final ExprEval result = eval("contains_string(a, null)", InputBindings.withMap(ImmutableMap.of("a", "foo"))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -87,7 +86,7 @@ public void testEmptyStringSearch() { final ExprEval result = eval("contains_string(a, '')", InputBindings.withMap(ImmutableMap.of("a", "foo"))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -101,7 +100,7 @@ public void testNullSearchOnEmptyString() final ExprEval result = eval("contains_string(a, null)", InputBindings.withMap(ImmutableMap.of("a", ""))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -111,7 +110,7 @@ public void testEmptyStringSearchOnEmptyString() { final ExprEval result = eval("contains_string(a, '')", InputBindings.withMap(ImmutableMap.of("a", ""))); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -125,7 +124,7 @@ public void testNullSearchOnNull() final ExprEval result = eval("contains_string(a, null)", InputBindings.nilBindings()); Assert.assertEquals( - ExprEval.ofBoolean(true, ExprType.LONG).value(), + ExprEval.ofLongBoolean(true).value(), result.value() ); } @@ -135,7 +134,7 @@ public void testEmptyStringSearchOnNull() { final ExprEval result = eval("contains_string(a, '')", InputBindings.nilBindings()); Assert.assertEquals( - ExprEval.ofBoolean(!NullHandling.sqlCompatible(), ExprType.LONG).value(), + ExprEval.ofLongBoolean(!NullHandling.sqlCompatible()).value(), result.value() ); } diff --git a/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java b/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java index ccfc87bdab3d..a2b5fed3f3e7 100644 --- a/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java +++ b/processing/src/test/java/org/apache/druid/query/groupby/GroupByQueryRunnerTest.java @@ -11211,6 +11211,41 @@ public void testGroupByOnVirtualColumn() TestHelper.assertExpectedObjects(expectedResults, results, "groupBy"); } + @Test + public void testGroupByOnVirtualColumnTimeFloor() + { + if (config.getDefaultStrategy().equals(GroupByStrategySelector.STRATEGY_V1)) { + expectedException.expect(UnsupportedOperationException.class); + } + + GroupByQuery query = makeQueryBuilder() + .setDataSource(QueryRunnerTestHelper.DATA_SOURCE) + .setQuerySegmentSpec(QueryRunnerTestHelper.FIRST_TO_THIRD) + .setVirtualColumns( + new ExpressionVirtualColumn( + "v", + "timestamp_floor(__time, 'P1D')", + ColumnType.LONG, + TestExprMacroTable.INSTANCE + ) + ) + .setDimensions( + new DefaultDimensionSpec("v", "v", ColumnType.LONG) + ) + .setAggregatorSpecs(QueryRunnerTestHelper.ROWS_COUNT) + .setGranularity(QueryRunnerTestHelper.ALL_GRAN) + .setLimit(5) + .build(); + + List expectedResults = Arrays.asList( + makeRow(query, "2011-04-01", "v", 1301616000000L, "rows", 13L), // 04-01 + makeRow(query, "2011-04-01", "v", 1301702400000L, "rows", 13L) // 04-02 + ); + + Iterable results = GroupByQueryRunnerTestHelper.runQuery(factory, runner, query); + TestHelper.assertExpectedObjects(expectedResults, results, "groupBy"); + } + @Test public void testGroupByWithExpressionAggregator() diff --git a/processing/src/test/java/org/apache/druid/segment/filter/ExpressionFilterStrictBooleansTest.java b/processing/src/test/java/org/apache/druid/segment/filter/ExpressionFilterStrictBooleansTest.java new file mode 100644 index 000000000000..589a73567768 --- /dev/null +++ b/processing/src/test/java/org/apache/druid/segment/filter/ExpressionFilterStrictBooleansTest.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.segment.filter; + +import com.google.common.base.Function; +import org.apache.druid.java.util.common.Pair; +import org.apache.druid.math.expr.ExpressionProcessing; +import org.apache.druid.segment.IndexBuilder; +import org.apache.druid.segment.StorageAdapter; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.Closeable; + +@RunWith(Parameterized.class) +public class ExpressionFilterStrictBooleansTest extends ExpressionFilterTest +{ + public ExpressionFilterStrictBooleansTest( + String testName, + IndexBuilder indexBuilder, + Function> finisher, + boolean cnf, + boolean optimize + ) + { + super(testName, indexBuilder, finisher, cnf, optimize); + } + + @Before + @Override + public void setup() + { + ExpressionProcessing.initializeForStrictBooleansTests(true); + } +} diff --git a/processing/src/test/java/org/apache/druid/segment/filter/ExpressionFilterTest.java b/processing/src/test/java/org/apache/druid/segment/filter/ExpressionFilterTest.java index efa3cf5555b7..6ce89e38e624 100644 --- a/processing/src/test/java/org/apache/druid/segment/filter/ExpressionFilterTest.java +++ b/processing/src/test/java/org/apache/druid/segment/filter/ExpressionFilterTest.java @@ -36,14 +36,17 @@ import org.apache.druid.data.input.impl.TimestampSpec; import org.apache.druid.java.util.common.DateTimes; import org.apache.druid.java.util.common.Pair; +import org.apache.druid.math.expr.ExpressionProcessing; import org.apache.druid.query.expression.TestExprMacroTable; import org.apache.druid.query.filter.ExpressionDimFilter; import org.apache.druid.query.filter.Filter; import org.apache.druid.segment.IndexBuilder; import org.apache.druid.segment.StorageAdapter; import org.apache.druid.segment.incremental.IncrementalIndexSchema; +import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -118,6 +121,18 @@ public ExpressionFilterTest( @Rule public ExpectedException expectedException = ExpectedException.none(); + @Before + public void setup() + { + ExpressionProcessing.initializeForStrictBooleansTests(false); + } + + @After + public void teardown() + { + ExpressionProcessing.initializeForTests(null); + } + @AfterClass public static void tearDown() throws Exception { diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java index 423a44598c6e..2339cdd29bba 100644 --- a/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java +++ b/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java @@ -31,6 +31,7 @@ import org.apache.druid.java.util.common.guava.Yielders; import org.apache.druid.java.util.common.io.Closer; import org.apache.druid.java.util.common.logger.Logger; +import org.apache.druid.math.expr.ExpressionProcessing; import org.apache.druid.query.QueryContexts; import org.apache.druid.query.QueryRunnerFactoryConglomerate; import org.apache.druid.segment.QueryableIndex; @@ -87,7 +88,9 @@ public class SqlVectorizedExpressionSanityTest extends InitializedNullHandlingTe "SELECT string1 + string2, COUNT(*) FROM foo GROUP BY 1 ORDER BY 2", "SELECT CONCAT(string1, '-', 'foo'), COUNT(*) FROM foo GROUP BY 1 ORDER BY 2", "SELECT CONCAT(string1, '-', string2), string3, COUNT(*) FROM foo GROUP BY 1,2 ORDER BY 3", - "SELECT CONCAT(string1, '-', string2, '-', long1, '-', double1, '-', float1) FROM foo GROUP BY 1" + "SELECT CONCAT(string1, '-', string2, '-', long1, '-', double1, '-', float1) FROM foo GROUP BY 1", + "SELECT CAST(long1 as BOOLEAN) AND CAST (long2 as BOOLEAN), COUNT(*) FROM foo GROUP BY 1 ORDER BY 2", + "SELECT long5 IS NULL, long3 IS NOT NULL, count(*) FROM foo GROUP BY 1,2 ORDER BY 3" ); private static final int ROWS_PER_SEGMENT = 100_000; @@ -103,6 +106,7 @@ public class SqlVectorizedExpressionSanityTest extends InitializedNullHandlingTe public static void setupClass() { Calcites.setSystemProperties(); + ExpressionProcessing.initializeForStrictBooleansTests(true); CLOSER = Closer.create(); final GeneratorSchemaInfo schemaInfo = GeneratorBasicSchemas.SCHEMA_MAP.get("expression-testbench"); @@ -146,6 +150,7 @@ public static void setupClass() public static void teardownClass() throws IOException { CLOSER.close(); + ExpressionProcessing.initializeForTests(null); } @Parameterized.Parameters(name = "query = {0}") diff --git a/website/.spelling b/website/.spelling index aa2bc7874884..30ff2e145445 100644 --- a/website/.spelling +++ b/website/.spelling @@ -1184,6 +1184,7 @@ getExponent hypot ipv4_match ipv4_parse +isnull ipv4_stringify java.lang.Math java.lang.String @@ -1193,6 +1194,7 @@ lpad ltrim nextUp nextafter +notnull nvl parse_long regexp_extract