move numeric null value coercion out of expression processing engine (#13809)

* move numeric null value coercion out of expression processing engine
* add ExprEval.valueOrDefault() to allow consumers to automatically coerce to default values
* rename Expr.buildVectorized as Expr.asVectorProcessor more consistent naming with Function and ApplyFunction; javadocs for some stuff
This commit is contained in:
Clint Wylie 2023-02-28 18:10:07 -08:00 committed by GitHub
parent faf602108b
commit 6cf754b0e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 713 additions and 597 deletions

View File

@ -57,9 +57,9 @@ public interface ApplyFunction extends NamedFunction
/** /**
* Builds a 'vectorized' function expression processor, that can build vectorized processors for its input values * Builds a 'vectorized' function expression processor, that can build vectorized processors for its input values
* using {@link Expr#buildVectorized}, for use in vectorized query engines. * using {@link Expr#asVectorProcessor}, for use in vectorized query engines.
* *
* @see Expr#buildVectorized(Expr.VectorInputBindingInspector) * @see Expr#asVectorProcessor(Expr.VectorInputBindingInspector)
* @see Function#asVectorProcessor(Expr.VectorInputBindingInspector, List) * @see Function#asVectorProcessor(Expr.VectorInputBindingInspector, List)
*/ */
default <T> ExprVectorProcessor<T> asVectorProcessor( default <T> ExprVectorProcessor<T> asVectorProcessor(

View File

@ -70,7 +70,7 @@ class BinLtExpr extends BinaryBooleanOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorComparisonProcessors.lessThan(inspector, left, right); return VectorComparisonProcessors.lessThan(inspector, left, right);
} }
@ -116,7 +116,7 @@ class BinLeqExpr extends BinaryBooleanOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorComparisonProcessors.lessThanOrEqual(inspector, left, right); return VectorComparisonProcessors.lessThanOrEqual(inspector, left, right);
} }
@ -162,7 +162,7 @@ class BinGtExpr extends BinaryBooleanOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorComparisonProcessors.greaterThan(inspector, left, right); return VectorComparisonProcessors.greaterThan(inspector, left, right);
} }
@ -208,7 +208,7 @@ class BinGeqExpr extends BinaryBooleanOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorComparisonProcessors.greaterThanOrEqual(inspector, left, right); return VectorComparisonProcessors.greaterThanOrEqual(inspector, left, right);
} }
@ -253,7 +253,7 @@ class BinEqExpr extends BinaryBooleanOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorComparisonProcessors.equal(inspector, left, right); return VectorComparisonProcessors.equal(inspector, left, right);
} }
@ -298,7 +298,7 @@ class BinNeqExpr extends BinaryBooleanOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorComparisonProcessors.notEqual(inspector, left, right); return VectorComparisonProcessors.notEqual(inspector, left, right);
} }
@ -331,7 +331,9 @@ class BinAndExpr extends BinaryOpExprBase
return ExprEval.ofLongBoolean(false); return ExprEval.ofLongBoolean(false);
} }
ExprEval rightVal; ExprEval rightVal;
if (NullHandling.sqlCompatible() || Types.is(leftVal.type(), ExprType.STRING)) { // null values can (but not always) appear as string typed
// so type isn't necessarily string unless value is non-null
if (NullHandling.sqlCompatible() || (Types.is(leftVal.type(), ExprType.STRING))) {
// true/null, null/true, null/null -> null // true/null, null/true, null/null -> null
// false/null, null/false -> false // false/null, null/false -> false
if (leftVal.value() == null) { if (leftVal.value() == null) {
@ -362,7 +364,7 @@ class BinAndExpr extends BinaryOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorProcessors.and(inspector, left, right); return VectorProcessors.and(inspector, left, right);
} }
@ -405,7 +407,9 @@ class BinOrExpr extends BinaryOpExprBase
} }
final ExprEval rightVal; final ExprEval rightVal;
if (NullHandling.sqlCompatible() || Types.is(leftVal.type(), ExprType.STRING)) { // null values can (but not always) appear as string typed
// so type isn't necessarily string unless value is non-null
if (NullHandling.sqlCompatible() || (Types.is(leftVal.type(), ExprType.STRING))) {
// true/null, null/true -> true // true/null, null/true -> true
// false/null, null/false, null/null -> null // false/null, null/false, null/null -> null
if (leftVal.value() == null) { if (leftVal.value() == null) {
@ -438,7 +442,7 @@ class BinOrExpr extends BinaryOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorProcessors.or(inspector, left, right); return VectorProcessors.or(inspector, left, right);
} }

View File

@ -70,7 +70,7 @@ final class BinPlusExpr extends BinaryEvalOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
ExpressionType type = ExpressionTypeConversion.operator( ExpressionType type = ExpressionTypeConversion.operator(
left.getOutputType(inspector), left.getOutputType(inspector),
@ -116,7 +116,7 @@ final class BinMinusExpr extends BinaryEvalOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorMathProcessors.minus(inspector, left, right); return VectorMathProcessors.minus(inspector, left, right);
} }
@ -155,7 +155,7 @@ final class BinMulExpr extends BinaryEvalOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorMathProcessors.multiply(inspector, left, right); return VectorMathProcessors.multiply(inspector, left, right);
} }
@ -194,7 +194,7 @@ final class BinDivExpr extends BinaryEvalOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorMathProcessors.divide(inspector, left, right); return VectorMathProcessors.divide(inspector, left, right);
} }
@ -233,7 +233,7 @@ class BinPowExpr extends BinaryEvalOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorMathProcessors.power(inspector, left, right); return VectorMathProcessors.power(inspector, left, right);
} }
@ -272,7 +272,7 @@ class BinModuloExpr extends BinaryEvalOpExprBase
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorMathProcessors.modulo(inspector, left, right); return VectorMathProcessors.modulo(inspector, left, right);
} }

View File

@ -175,7 +175,7 @@ class LongExpr extends ConstantExpr<Long>
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorProcessors.constant(value, inspector.getMaxVectorSize()); return VectorProcessors.constant(value, inspector.getMaxVectorSize());
} }
@ -214,7 +214,7 @@ class NullLongExpr extends ConstantExpr<Long>
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorProcessors.constant((Long) null, inspector.getMaxVectorSize()); return VectorProcessors.constant((Long) null, inspector.getMaxVectorSize());
} }
@ -258,7 +258,7 @@ class DoubleExpr extends ConstantExpr<Double>
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorProcessors.constant(value, inspector.getMaxVectorSize()); return VectorProcessors.constant(value, inspector.getMaxVectorSize());
} }
@ -297,7 +297,7 @@ class NullDoubleExpr extends ConstantExpr<Double>
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorProcessors.constant((Double) null, inspector.getMaxVectorSize()); return VectorProcessors.constant((Double) null, inspector.getMaxVectorSize());
} }
@ -341,7 +341,7 @@ class StringExpr extends ConstantExpr<String>
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorProcessors.constant(value, inspector.getMaxVectorSize()); return VectorProcessors.constant(value, inspector.getMaxVectorSize());
} }

View File

@ -164,7 +164,7 @@ public interface Expr extends Cacheable
/** /**
* Check if an expression can be 'vectorized', for a given set of inputs. If this method returns true, * Check if an expression can be 'vectorized', for a given set of inputs. If this method returns true,
* {@link #buildVectorized} is expected to produce a {@link ExprVectorProcessor} which can evaluate values in batches * {@link #asVectorProcessor} is expected to produce a {@link ExprVectorProcessor} which can evaluate values in batches
* to use with vectorized query engines. * to use with vectorized query engines.
* *
* @param inspector * @param inspector
@ -180,7 +180,7 @@ public interface Expr extends Cacheable
* *
* @param inspector * @param inspector
*/ */
default <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) default <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
throw Exprs.cannotVectorize(this); throw Exprs.cannotVectorize(this);
} }
@ -345,7 +345,7 @@ public interface Expr extends Cacheable
} }
/** /**
* {@link InputBindingInspector} + vectorizations stuff for {@link #buildVectorized} * {@link InputBindingInspector} + vectorizations stuff for {@link #asVectorProcessor}
*/ */
interface VectorInputBindingInspector extends InputBindingInspector interface VectorInputBindingInspector extends InputBindingInspector
{ {

View File

@ -109,14 +109,14 @@ public abstract class ExprEval<T>
int offset = position; int offset = position;
switch (type.getType()) { switch (type.getType()) {
case LONG: case LONG:
if (eval.isNumericNull()) { if (eval.value() == null) {
TypeStrategies.writeNull(buffer, offset); TypeStrategies.writeNull(buffer, offset);
} else { } else {
TypeStrategies.writeNotNullNullableLong(buffer, offset, eval.asLong()); TypeStrategies.writeNotNullNullableLong(buffer, offset, eval.asLong());
} }
break; break;
case DOUBLE: case DOUBLE:
if (eval.isNumericNull()) { if (eval.value() == null) {
TypeStrategies.writeNull(buffer, offset); TypeStrategies.writeNull(buffer, offset);
} else { } else {
TypeStrategies.writeNotNullNullableDouble(buffer, offset, eval.asDouble()); TypeStrategies.writeNotNullNullableDouble(buffer, offset, eval.asDouble());
@ -163,14 +163,14 @@ public abstract class ExprEval<T>
Object[] array = new Object[val.size()]; Object[] array = new Object[val.size()];
int i = 0; int i = 0;
for (Object o : val) { for (Object o : val) {
array[i++] = o == null ? null : ExprEval.ofType(ExpressionType.LONG, o).value(); array[i++] = o != null ? ExprEval.ofType(ExpressionType.LONG, o).value() : null;
} }
return new NonnullPair<>(ExpressionType.LONG_ARRAY, array); return new NonnullPair<>(ExpressionType.LONG_ARRAY, array);
} else if (coercedType == Float.class || coercedType == Double.class) { } else if (coercedType == Float.class || coercedType == Double.class) {
Object[] array = new Object[val.size()]; Object[] array = new Object[val.size()];
int i = 0; int i = 0;
for (Object o : val) { for (Object o : val) {
array[i++] = ExprEval.ofType(ExpressionType.DOUBLE, o).value(); array[i++] = o != null ? ExprEval.ofType(ExpressionType.DOUBLE, o).value() : null;
} }
return new NonnullPair<>(ExpressionType.DOUBLE_ARRAY, array); return new NonnullPair<>(ExpressionType.DOUBLE_ARRAY, array);
} else if (coercedType == Object.class) { } else if (coercedType == Object.class) {
@ -205,7 +205,7 @@ public abstract class ExprEval<T>
Object[] array = new Object[val.size()]; Object[] array = new Object[val.size()];
int i = 0; int i = 0;
for (Object o : val) { for (Object o : val) {
array[i++] = o == null ? null : ExprEval.ofType(ExpressionType.STRING, o).value(); array[i++] = o != null ? ExprEval.ofType(ExpressionType.STRING, o).value() : null;
} }
return new NonnullPair<>(ExpressionType.STRING_ARRAY, array); return new NonnullPair<>(ExpressionType.STRING_ARRAY, array);
} }
@ -345,7 +345,6 @@ public abstract class ExprEval<T>
@Deprecated @Deprecated
public static ExprEval ofBoolean(boolean value, ExprType type) public static ExprEval ofBoolean(boolean value, ExprType type)
{ {
assert !ExpressionProcessing.useStrictBooleans();
switch (type) { switch (type) {
case DOUBLE: case DOUBLE:
return ExprEval.of(Evals.asDouble(value)); return ExprEval.of(Evals.asDouble(value));
@ -398,7 +397,7 @@ public abstract class ExprEval<T>
final Long[] inputArray = (Long[]) val; final Long[] inputArray = (Long[]) val;
final Object[] array = new Object[inputArray.length]; final Object[] array = new Object[inputArray.length];
for (int i = 0; i < inputArray.length; i++) { for (int i = 0; i < inputArray.length; i++) {
array[i] = inputArray[i] != null ? inputArray[i] : NullHandling.defaultLongValue(); array[i] = inputArray[i];
} }
return new ArrayExprEval(ExpressionType.LONG_ARRAY, array); return new ArrayExprEval(ExpressionType.LONG_ARRAY, array);
} }
@ -414,7 +413,7 @@ public abstract class ExprEval<T>
final Integer[] inputArray = (Integer[]) val; final Integer[] inputArray = (Integer[]) val;
final Object[] array = new Object[inputArray.length]; final Object[] array = new Object[inputArray.length];
for (int i = 0; i < inputArray.length; i++) { for (int i = 0; i < inputArray.length; i++) {
array[i] = inputArray[i] != null ? inputArray[i].longValue() : NullHandling.defaultLongValue(); array[i] = inputArray[i] != null ? inputArray[i].longValue() : null;
} }
return new ArrayExprEval(ExpressionType.LONG_ARRAY, array); return new ArrayExprEval(ExpressionType.LONG_ARRAY, array);
} }
@ -430,7 +429,7 @@ public abstract class ExprEval<T>
final Double[] inputArray = (Double[]) val; final Double[] inputArray = (Double[]) val;
final Object[] array = new Object[inputArray.length]; final Object[] array = new Object[inputArray.length];
for (int i = 0; i < inputArray.length; i++) { for (int i = 0; i < inputArray.length; i++) {
array[i] = inputArray[i] != null ? inputArray[i] : NullHandling.defaultDoubleValue(); array[i] = inputArray[i] != null ? inputArray[i] : null;
} }
return new ArrayExprEval(ExpressionType.DOUBLE_ARRAY, array); return new ArrayExprEval(ExpressionType.DOUBLE_ARRAY, array);
} }
@ -446,7 +445,7 @@ public abstract class ExprEval<T>
final Float[] inputArray = (Float[]) val; final Float[] inputArray = (Float[]) val;
final Object[] array = new Object[inputArray.length]; final Object[] array = new Object[inputArray.length];
for (int i = 0; i < inputArray.length; i++) { for (int i = 0; i < inputArray.length; i++) {
array[i] = inputArray[i] != null ? inputArray[i].doubleValue() : NullHandling.defaultDoubleValue(); array[i] = inputArray[i] != null ? inputArray[i].doubleValue() : null;
} }
return new ArrayExprEval(ExpressionType.DOUBLE_ARRAY, array); return new ArrayExprEval(ExpressionType.DOUBLE_ARRAY, array);
} }
@ -561,7 +560,6 @@ public abstract class ExprEval<T>
if (bytes != null) { if (bytes != null) {
TypeStrategy<?> strategy = type.getStrategy(); TypeStrategy<?> strategy = type.getStrategy();
assert strategy != null;
ByteBuffer bb = ByteBuffer.wrap(bytes); ByteBuffer bb = ByteBuffer.wrap(bytes);
return ofComplex(type, strategy.read(bb)); return ofComplex(type, strategy.read(bb));
} }
@ -653,6 +651,12 @@ public abstract class ExprEval<T>
return value; return value;
} }
@Nullable
public T valueOrDefault()
{
return value;
}
void cacheStringValue(@Nullable String value) void cacheStringValue(@Nullable String value)
{ {
stringValue = value; stringValue = value;
@ -662,7 +666,6 @@ public abstract class ExprEval<T>
@Nullable @Nullable
String getCachedStringValue() String getCachedStringValue()
{ {
assert stringValueCached;
return stringValue; return stringValue;
} }
@ -743,25 +746,34 @@ public abstract class ExprEval<T>
@Override @Override
public final int asInt() public final int asInt()
{ {
if (value == null) {
return 0;
}
return value.intValue(); return value.intValue();
} }
@Override @Override
public final long asLong() public final long asLong()
{ {
if (value == null) {
return 0L;
}
return value.longValue(); return value.longValue();
} }
@Override @Override
public final double asDouble() public final double asDouble()
{ {
if (value == null) {
return 0.0;
}
return value.doubleValue(); return value.doubleValue();
} }
@Override @Override
public boolean isNumericNull() public boolean isNumericNull()
{ {
return value == null; return NullHandling.sqlCompatible() && value == null;
} }
} }
@ -771,7 +783,7 @@ public abstract class ExprEval<T>
private DoubleExprEval(@Nullable Number value) private DoubleExprEval(@Nullable Number value)
{ {
super(value == null ? NullHandling.defaultDoubleValue() : (Double) value.doubleValue()); super(value == null ? null : value.doubleValue());
} }
@Override @Override
@ -780,6 +792,15 @@ public abstract class ExprEval<T>
return ExpressionType.DOUBLE; return ExpressionType.DOUBLE;
} }
@Override
public Number valueOrDefault()
{
if (value == null) {
return NullHandling.defaultDoubleValue();
}
return value;
}
@Override @Override
public final boolean asBoolean() public final boolean asBoolean()
{ {
@ -823,7 +844,7 @@ public abstract class ExprEval<T>
@Override @Override
public Expr toExpr() public Expr toExpr()
{ {
if (isNumericNull()) { if (value == null) {
return new NullDoubleExpr(); return new NullDoubleExpr();
} }
return new DoubleExpr(value.doubleValue()); return new DoubleExpr(value.doubleValue());
@ -836,7 +857,7 @@ public abstract class ExprEval<T>
private LongExprEval(@Nullable Number value) private LongExprEval(@Nullable Number value)
{ {
super(value == null ? NullHandling.defaultLongValue() : (Long) value.longValue()); super(value == null ? null : value.longValue());
} }
@Override @Override
@ -845,6 +866,15 @@ public abstract class ExprEval<T>
return ExpressionType.LONG; return ExpressionType.LONG;
} }
@Override
public Number valueOrDefault()
{
if (value == null) {
return NullHandling.defaultLongValue();
}
return value;
}
@Override @Override
public final boolean asBoolean() public final boolean asBoolean()
{ {
@ -888,7 +918,7 @@ public abstract class ExprEval<T>
@Override @Override
public Expr toExpr() public Expr toExpr()
{ {
if (isNumericNull()) { if (value == null) {
return new NullLongExpr(); return new NullLongExpr();
} }
return new LongExpr(value.longValue()); return new LongExpr(value.longValue());
@ -974,7 +1004,6 @@ public abstract class ExprEval<T>
{ {
Number number = computeNumber(); Number number = computeNumber();
if (number == null) { if (number == null) {
assert NullHandling.replaceWithDefault();
return 0; return 0;
} }
return number.intValue(); return number.intValue();
@ -984,7 +1013,6 @@ public abstract class ExprEval<T>
{ {
Number number = computeNumber(); Number number = computeNumber();
if (number == null) { if (number == null) {
assert NullHandling.replaceWithDefault();
return 0L; return 0L;
} }
return number.longValue(); return number.longValue();
@ -994,7 +1022,6 @@ public abstract class ExprEval<T>
{ {
Number number = computeNumber(); Number number = computeNumber();
if (number == null) { if (number == null) {
assert NullHandling.replaceWithDefault();
return 0.0d; return 0.0d;
} }
return number.doubleValue(); return number.doubleValue();
@ -1042,11 +1069,16 @@ public abstract class ExprEval<T>
case STRING: case STRING:
return this; return this;
case ARRAY: case ARRAY:
final Number number = computeNumber();
switch (castTo.getElementType().getType()) { switch (castTo.getElementType().getType()) {
case DOUBLE: case DOUBLE:
return ExprEval.ofDoubleArray(value == null ? null : new Object[] {computeDouble()}); return ExprEval.ofDoubleArray(
value == null ? null : new Object[] {number == null ? null : number.doubleValue()}
);
case LONG: case LONG:
return ExprEval.ofLongArray(value == null ? null : new Object[] {computeLong()}); return ExprEval.ofLongArray(
value == null ? null : new Object[] {number == null ? null : number.longValue()}
);
case STRING: case STRING:
return ExprEval.ofStringArray(value == null ? null : new Object[] {value}); return ExprEval.ofStringArray(value == null ? null : new Object[] {value});
} }
@ -1131,7 +1163,6 @@ public abstract class ExprEval<T>
scalar = computeNumber((String) getScalarValue()); scalar = computeNumber((String) getScalarValue());
} }
if (scalar == null) { if (scalar == null) {
assert NullHandling.replaceWithDefault();
return 0; return 0;
} }
return scalar.intValue(); return scalar.intValue();
@ -1150,7 +1181,6 @@ public abstract class ExprEval<T>
scalar = computeNumber((String) getScalarValue()); scalar = computeNumber((String) getScalarValue());
} }
if (scalar == null) { if (scalar == null) {
assert NullHandling.replaceWithDefault();
return 0; return 0;
} }
return scalar.longValue(); return scalar.longValue();
@ -1169,7 +1199,6 @@ public abstract class ExprEval<T>
scalar = computeNumber((String) getScalarValue()); scalar = computeNumber((String) getScalarValue());
} }
if (scalar == null) { if (scalar == null) {
assert NullHandling.replaceWithDefault();
return 0.0; return 0.0;
} }
return scalar.doubleValue(); return scalar.doubleValue();
@ -1184,7 +1213,6 @@ public abstract class ExprEval<T>
if (arrayType.getElementType().isNumeric()) { if (arrayType.getElementType().isNumeric()) {
Number scalarValue = (Number) getScalarValue(); Number scalarValue = (Number) getScalarValue();
if (scalarValue == null) { if (scalarValue == null) {
assert NullHandling.replaceWithDefault();
return false; return false;
} }
return Evals.asBoolean(scalarValue.longValue()); return Evals.asBoolean(scalarValue.longValue());
@ -1257,7 +1285,6 @@ public abstract class ExprEval<T>
@Nullable @Nullable
protected Object getScalarValue() protected Object getScalarValue()
{ {
assert value != null && value.length == 1;
return value[0]; return value[0];
} }
} }

View File

@ -131,9 +131,9 @@ public interface Function extends NamedFunction
/** /**
* Builds a 'vectorized' function expression processor, that can build vectorized processors for its input values * Builds a 'vectorized' function expression processor, that can build vectorized processors for its input values
* using {@link Expr#buildVectorized}, for use in vectorized query engines. * using {@link Expr#asVectorProcessor}, for use in vectorized query engines.
* *
* @see Expr#buildVectorized(Expr.VectorInputBindingInspector) * @see Expr#asVectorProcessor(Expr.VectorInputBindingInspector)
* @see ApplyFunction#asVectorProcessor(Expr.VectorInputBindingInspector, Expr, List) * @see ApplyFunction#asVectorProcessor(Expr.VectorInputBindingInspector, Expr, List)
*/ */
default <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingInspector inspector, List<Expr> args) default <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingInspector inspector, List<Expr> args)
@ -1176,7 +1176,7 @@ public interface Function extends NamedFunction
{ {
if (y == 0) { if (y == 0) {
if (x != 0) { if (x != 0) {
return ExprEval.ofLong(NullHandling.defaultLongValue()); return ExprEval.ofLong(null);
} }
return ExprEval.ofLong(0); return ExprEval.ofLong(0);
} }
@ -1188,7 +1188,7 @@ public interface Function extends NamedFunction
{ {
if (y == 0 || Double.isNaN(y)) { if (y == 0 || Double.isNaN(y)) {
if (x != 0) { if (x != 0) {
return ExprEval.ofDouble(NullHandling.defaultDoubleValue()); return ExprEval.ofDouble(null);
} }
return ExprEval.ofDouble(0); return ExprEval.ofDouble(0);
} }
@ -2014,7 +2014,7 @@ public interface Function extends NamedFunction
public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingInspector inspector, List<Expr> args) public <T> ExprVectorProcessor<T> asVectorProcessor(Expr.VectorInputBindingInspector inspector, List<Expr> args)
{ {
return CastToTypeVectorProcessor.cast( return CastToTypeVectorProcessor.cast(
args.get(0).buildVectorized(inspector), args.get(0).asVectorProcessor(inspector),
ExpressionType.fromString(StringUtils.toUpperCase(args.get(1).getLiteralValue().toString())) ExpressionType.fromString(StringUtils.toUpperCase(args.get(1).getLiteralValue().toString()))
); );
} }
@ -2384,7 +2384,7 @@ public interface Function extends NamedFunction
public ExprEval apply(List<Expr> args, Expr.ObjectBinding bindings) public ExprEval apply(List<Expr> args, Expr.ObjectBinding bindings)
{ {
final String arg = args.get(0).eval(bindings).asString(); final String arg = args.get(0).eval(bindings).asString();
return arg == null ? ExprEval.ofLong(NullHandling.defaultLongValue()) : ExprEval.of(arg.length()); return arg == null ? ExprEval.ofLong(null) : ExprEval.of(arg.length());
} }
@Override @Override

View File

@ -90,9 +90,9 @@ class LambdaExpr implements Expr
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return expr.buildVectorized(inspector); return expr.asVectorProcessor(inspector);
} }
@Override @Override
@ -190,7 +190,7 @@ class FunctionExpr implements Expr
} }
@Override @Override
public ExprVectorProcessor<?> buildVectorized(VectorInputBindingInspector inspector) public ExprVectorProcessor<?> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return function.asVectorProcessor(inspector, args); return function.asVectorProcessor(inspector, args);
} }
@ -313,7 +313,7 @@ class ApplyFunctionExpr implements Expr
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return function.asVectorProcessor(inspector, lambdaExpr, argsExpr); return function.asVectorProcessor(inspector, lambdaExpr, argsExpr);
} }

View File

@ -147,7 +147,7 @@ class IdentifierExpr implements Expr
} }
@Override @Override
public ExprVectorProcessor<?> buildVectorized(VectorInputBindingInspector inspector) public ExprVectorProcessor<?> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorProcessors.identifier(inspector, binding); return VectorProcessors.identifier(inspector, binding);
} }

View File

@ -147,7 +147,7 @@ class UnaryMinusExpr extends UnaryExpr
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorMathProcessors.negate(inspector, expr); return VectorMathProcessors.negate(inspector, expr);
} }
@ -203,7 +203,7 @@ class UnaryNotExpr extends UnaryExpr
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
return VectorProcessors.not(inspector, expr); return VectorProcessors.not(inspector, expr);
} }

View File

@ -19,11 +19,9 @@
package org.apache.druid.math.expr.vector; package org.apache.druid.math.expr.vector;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.math.expr.ExpressionType; import org.apache.druid.math.expr.ExpressionType;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.lang.reflect.Array;
/** /**
* Result of {@link ExprVectorProcessor#evalVector} which wraps the actual evaluated results of the operation over the * Result of {@link ExprVectorProcessor#evalVector} which wraps the actual evaluated results of the operation over the
@ -48,15 +46,6 @@ public abstract class ExprEvalVector<T>
return values; return values;
} }
@Nullable
public Object get(int index)
{
if (nulls == null || NullHandling.replaceWithDefault() || !nulls[index]) {
return Array.get(values, index);
}
return null;
}
@Nullable @Nullable
public boolean[] getNullVector() public boolean[] getNullVector()
{ {

View File

@ -19,6 +19,7 @@
package org.apache.druid.math.expr.vector; package org.apache.druid.math.expr.vector;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.math.expr.ExpressionType; import org.apache.druid.math.expr.ExpressionType;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -52,7 +53,7 @@ public abstract class LongOutObjectsInFunctionVectorProcessor
final Long outVal = processValue(in1[i], in2[i]); final Long outVal = processValue(in1[i], in2[i]);
if (outVal == null) { if (outVal == null) {
outValues[i] = 0L; outValues[i] = 0L;
outNulls[i] = true; outNulls[i] = NullHandling.sqlCompatible();
} else { } else {
outValues[i] = outVal; outValues[i] = outVal;
outNulls[i] = false; outNulls[i] = false;
@ -63,7 +64,7 @@ public abstract class LongOutObjectsInFunctionVectorProcessor
void processNull(int i) void processNull(int i)
{ {
outValues[i] = 0L; outValues[i] = 0L;
outNulls[i] = true; outNulls[i] = NullHandling.sqlCompatible();
} }
@Override @Override

View File

@ -137,8 +137,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -151,8 +151,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -163,8 +163,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -175,8 +175,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -187,8 +187,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoublesInFunctionVectorValueProcessor( () -> new DoubleOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -205,8 +205,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -219,8 +219,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -231,8 +231,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongDoubleInFunctionVectorValueProcessor( () -> new LongOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -243,8 +243,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoubleLongInFunctionVectorValueProcessor( () -> new LongOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -255,8 +255,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoublesInFunctionVectorValueProcessor( () -> new LongOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -281,8 +281,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -295,8 +295,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -307,8 +307,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -319,8 +319,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -331,8 +331,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoublesInFunctionVectorValueProcessor( () -> new DoubleOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -349,8 +349,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -363,8 +363,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -375,8 +375,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongDoubleInFunctionVectorValueProcessor( () -> new LongOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -387,8 +387,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoubleLongInFunctionVectorValueProcessor( () -> new LongOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -399,8 +399,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoublesInFunctionVectorValueProcessor( () -> new LongOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -425,8 +425,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -441,8 +441,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -453,8 +453,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -465,8 +465,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -477,8 +477,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoublesInFunctionVectorValueProcessor( () -> new DoubleOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -495,8 +495,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -511,8 +511,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -523,8 +523,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongDoubleInFunctionVectorValueProcessor( () -> new LongOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -535,8 +535,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoubleLongInFunctionVectorValueProcessor( () -> new LongOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -547,8 +547,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoublesInFunctionVectorValueProcessor( () -> new LongOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -573,8 +573,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -589,8 +589,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -601,8 +601,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -613,8 +613,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -625,8 +625,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoublesInFunctionVectorValueProcessor( () -> new DoubleOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -643,8 +643,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -659,8 +659,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -671,8 +671,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongDoubleInFunctionVectorValueProcessor( () -> new LongOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -683,8 +683,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoubleLongInFunctionVectorValueProcessor( () -> new LongOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -695,8 +695,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoublesInFunctionVectorValueProcessor( () -> new LongOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -721,8 +721,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -737,8 +737,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -749,8 +749,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -761,8 +761,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -773,8 +773,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoublesInFunctionVectorValueProcessor( () -> new DoubleOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -791,8 +791,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -807,8 +807,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -819,8 +819,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongDoubleInFunctionVectorValueProcessor( () -> new LongOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -831,8 +831,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoubleLongInFunctionVectorValueProcessor( () -> new LongOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -843,8 +843,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoublesInFunctionVectorValueProcessor( () -> new LongOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -869,8 +869,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -885,8 +885,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -897,8 +897,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutLongDoubleInFunctionVectorValueProcessor( () -> new DoubleOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -909,8 +909,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoubleLongInFunctionVectorValueProcessor( () -> new DoubleOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -921,8 +921,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new DoubleOutDoublesInFunctionVectorValueProcessor( () -> new DoubleOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -939,8 +939,8 @@ public class VectorComparisonProcessors
left, left,
right, right,
() -> new LongOutObjectsInFunctionVectorProcessor( () -> new LongOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -955,8 +955,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongsInFunctionVectorValueProcessor( () -> new LongOutLongsInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -967,8 +967,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutLongDoubleInFunctionVectorValueProcessor( () -> new LongOutLongDoubleInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -979,8 +979,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoubleLongInFunctionVectorValueProcessor( () -> new LongOutDoubleLongInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {
@ -991,8 +991,8 @@ public class VectorComparisonProcessors
} }
}, },
() -> new LongOutDoublesInFunctionVectorValueProcessor( () -> new LongOutDoublesInFunctionVectorValueProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {

View File

@ -55,7 +55,7 @@ public class VectorProcessors
// if type is null, it means the input is all nulls // if type is null, it means the input is all nulls
if (leftType == null) { if (leftType == null) {
return right.buildVectorized(inspector); return right.asVectorProcessor(inspector);
} }
Preconditions.checkArgument( Preconditions.checkArgument(
@ -80,6 +80,11 @@ public class VectorProcessors
return (ExprVectorProcessor<T>) processor; return (ExprVectorProcessor<T>) processor;
} }
/**
* Creates an {@link ExprVectorProcessor} that creates a {@link ExprEvalVector} for a constant {@link String} value.
*
* @see org.apache.druid.math.expr.ConstantExpr
*/
public static <T> ExprVectorProcessor<T> constant(@Nullable String constant, int maxVectorSize) public static <T> ExprVectorProcessor<T> constant(@Nullable String constant, int maxVectorSize)
{ {
final Object[] strings = new Object[maxVectorSize]; final Object[] strings = new Object[maxVectorSize];
@ -101,13 +106,18 @@ public class VectorProcessors
}; };
} }
/**
* Creates an {@link ExprVectorProcessor} that creates a {@link ExprEvalVector} for a constant {@link Double} value.
*
* @see org.apache.druid.math.expr.ConstantExpr
*/
public static <T> ExprVectorProcessor<T> constant(@Nullable Double constant, int maxVectorSize) public static <T> ExprVectorProcessor<T> constant(@Nullable Double constant, int maxVectorSize)
{ {
final double[] doubles = new double[maxVectorSize]; final double[] doubles = new double[maxVectorSize];
final boolean[] nulls; final boolean[] nulls;
if (constant == null) { if (constant == null) {
nulls = new boolean[maxVectorSize]; nulls = new boolean[maxVectorSize];
Arrays.fill(nulls, true); Arrays.fill(nulls, NullHandling.sqlCompatible());
} else { } else {
nulls = null; nulls = null;
Arrays.fill(doubles, constant); Arrays.fill(doubles, constant);
@ -129,13 +139,18 @@ public class VectorProcessors
}; };
} }
/**
* Creates an {@link ExprVectorProcessor} that creates a {@link ExprEvalVector} for a constant {@link Long} value.
*
* @see org.apache.druid.math.expr.ConstantExpr
*/
public static <T> ExprVectorProcessor<T> constant(@Nullable Long constant, int maxVectorSize) public static <T> ExprVectorProcessor<T> constant(@Nullable Long constant, int maxVectorSize)
{ {
final long[] longs = new long[maxVectorSize]; final long[] longs = new long[maxVectorSize];
final boolean[] nulls; final boolean[] nulls;
if (constant == null) { if (constant == null) {
nulls = new boolean[maxVectorSize]; nulls = new boolean[maxVectorSize];
Arrays.fill(nulls, true); Arrays.fill(nulls, NullHandling.sqlCompatible());
} else { } else {
nulls = null; nulls = null;
Arrays.fill(longs, constant); Arrays.fill(longs, constant);
@ -157,6 +172,14 @@ public class VectorProcessors
}; };
} }
/**
* Creates an {@link ExprVectorProcessor} that creates a {@link ExprEvalVector} for some expression variable input
* binding, typically for segment column value vectors from a
* {@link org.apache.druid.segment.vector.VectorValueSelector} or
* {@link org.apache.druid.segment.vector.VectorObjectSelector}.
*
* @see org.apache.druid.math.expr.IdentifierExpr
*/
public static ExprVectorProcessor<?> identifier(Expr.VectorInputBindingInspector inspector, String binding) public static ExprVectorProcessor<?> identifier(Expr.VectorInputBindingInspector inspector, String binding)
{ {
ExpressionType inputType = inspector.getType(binding); ExpressionType inputType = inspector.getType(binding);
@ -206,10 +229,15 @@ public class VectorProcessors
} }
} }
/**
* Creates an {@link ExprVectorProcessor} that will parse a string into a long value given a radix.
*
* @see org.apache.druid.math.expr.Function.ParseLong
*/
public static <T> ExprVectorProcessor<T> parseLong(Expr.VectorInputBindingInspector inspector, Expr arg, int radix) public static <T> ExprVectorProcessor<T> parseLong(Expr.VectorInputBindingInspector inspector, Expr arg, int radix)
{ {
final ExprVectorProcessor<?> processor = new LongOutObjectInFunctionVectorProcessor( final ExprVectorProcessor<?> processor = new LongOutObjectInFunctionVectorProcessor(
arg.buildVectorized(inspector), arg.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -242,6 +270,12 @@ public class VectorProcessors
return (ExprVectorProcessor<T>) processor; return (ExprVectorProcessor<T>) processor;
} }
/**
* Creates an {@link ExprVectorProcessor} for the 'isnull' function, that produces a "boolean" typed output
* vector (long[]) with values set to 1 if the input value was null or 0 if it was not null.
*
* @see org.apache.druid.math.expr.Function.IsNullFunc
*/
public static <T> ExprVectorProcessor<T> isNull(Expr.VectorInputBindingInspector inspector, Expr expr) public static <T> ExprVectorProcessor<T> isNull(Expr.VectorInputBindingInspector inspector, Expr expr)
{ {
@ -254,7 +288,7 @@ public class VectorProcessors
ExprVectorProcessor<?> processor = null; ExprVectorProcessor<?> processor = null;
if (Types.is(type, ExprType.STRING)) { if (Types.is(type, ExprType.STRING)) {
final ExprVectorProcessor<Object[]> input = expr.buildVectorized(inspector); final ExprVectorProcessor<Object[]> input = expr.asVectorProcessor(inspector);
processor = new ExprVectorProcessor<long[]>() processor = new ExprVectorProcessor<long[]>()
{ {
@Override @Override
@ -281,7 +315,7 @@ public class VectorProcessors
} }
}; };
} else if (Types.is(type, ExprType.LONG)) { } else if (Types.is(type, ExprType.LONG)) {
final ExprVectorProcessor<long[]> input = expr.buildVectorized(inspector); final ExprVectorProcessor<long[]> input = expr.asVectorProcessor(inspector);
processor = new ExprVectorProcessor<long[]>() processor = new ExprVectorProcessor<long[]>()
{ {
@Override @Override
@ -312,7 +346,7 @@ public class VectorProcessors
} }
}; };
} else if (Types.is(type, ExprType.DOUBLE)) { } else if (Types.is(type, ExprType.DOUBLE)) {
final ExprVectorProcessor<double[]> input = expr.buildVectorized(inspector); final ExprVectorProcessor<double[]> input = expr.asVectorProcessor(inspector);
processor = new ExprVectorProcessor<long[]>() processor = new ExprVectorProcessor<long[]>()
{ {
@Override @Override
@ -350,6 +384,12 @@ public class VectorProcessors
return (ExprVectorProcessor<T>) processor; return (ExprVectorProcessor<T>) processor;
} }
/**
* Creates an {@link ExprVectorProcessor} for the 'isnotnull' function, that produces a "boolean" typed output
* vector (long[]) with values set to 1 if the input value was not null or 0 if it was null.
*
* @see org.apache.druid.math.expr.Function.IsNotNullFunc
*/
public static <T> ExprVectorProcessor<T> isNotNull(Expr.VectorInputBindingInspector inspector, Expr expr) public static <T> ExprVectorProcessor<T> isNotNull(Expr.VectorInputBindingInspector inspector, Expr expr)
{ {
@ -362,7 +402,7 @@ public class VectorProcessors
ExprVectorProcessor<?> processor = null; ExprVectorProcessor<?> processor = null;
if (Types.is(type, ExprType.STRING)) { if (Types.is(type, ExprType.STRING)) {
final ExprVectorProcessor<Object[]> input = expr.buildVectorized(inspector); final ExprVectorProcessor<Object[]> input = expr.asVectorProcessor(inspector);
processor = new ExprVectorProcessor<long[]>() processor = new ExprVectorProcessor<long[]>()
{ {
@Override @Override
@ -389,7 +429,7 @@ public class VectorProcessors
} }
}; };
} else if (Types.is(type, ExprType.LONG)) { } else if (Types.is(type, ExprType.LONG)) {
final ExprVectorProcessor<long[]> input = expr.buildVectorized(inspector); final ExprVectorProcessor<long[]> input = expr.asVectorProcessor(inspector);
processor = new ExprVectorProcessor<long[]>() processor = new ExprVectorProcessor<long[]>()
{ {
@Override @Override
@ -420,7 +460,7 @@ public class VectorProcessors
} }
}; };
} else if (Types.is(type, ExprType.DOUBLE)) { } else if (Types.is(type, ExprType.DOUBLE)) {
final ExprVectorProcessor<double[]> input = expr.buildVectorized(inspector); final ExprVectorProcessor<double[]> input = expr.asVectorProcessor(inspector);
processor = new ExprVectorProcessor<long[]>() processor = new ExprVectorProcessor<long[]>()
{ {
@Override @Override
@ -458,6 +498,12 @@ public class VectorProcessors
return (ExprVectorProcessor<T>) processor; return (ExprVectorProcessor<T>) processor;
} }
/**
* Creates an {@link ExprVectorProcessor} for the 'nvl' function, that will return the first argument value if it is
* not null, else the value of the 2nd argument.
*
* @see org.apache.druid.math.expr.Function.NvlFunc
*/
public static <T> ExprVectorProcessor<T> nvl(Expr.VectorInputBindingInspector inspector, Expr left, Expr right) public static <T> ExprVectorProcessor<T> nvl(Expr.VectorInputBindingInspector inspector, Expr left, Expr right)
{ {
final int maxVectorSize = inspector.getMaxVectorSize(); final int maxVectorSize = inspector.getMaxVectorSize();
@ -468,8 +514,8 @@ public class VectorProcessors
right, right,
() -> new SymmetricalBivariateFunctionVectorProcessor<long[]>( () -> new SymmetricalBivariateFunctionVectorProcessor<long[]>(
ExpressionType.LONG, ExpressionType.LONG,
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector) right.asVectorProcessor(inspector)
) )
{ {
final long[] output = new long[maxVectorSize]; final long[] output = new long[maxVectorSize];
@ -504,8 +550,8 @@ public class VectorProcessors
}, },
() -> new SymmetricalBivariateFunctionVectorProcessor<double[]>( () -> new SymmetricalBivariateFunctionVectorProcessor<double[]>(
ExpressionType.DOUBLE, ExpressionType.DOUBLE,
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector) right.asVectorProcessor(inspector)
) )
{ {
final double[] output = new double[maxVectorSize]; final double[] output = new double[maxVectorSize];
@ -540,8 +586,8 @@ public class VectorProcessors
}, },
() -> new SymmetricalBivariateFunctionVectorProcessor<Object[]>( () -> new SymmetricalBivariateFunctionVectorProcessor<Object[]>(
ExpressionType.STRING, ExpressionType.STRING,
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector) right.asVectorProcessor(inspector)
) )
{ {
final Object[] output = new Object[maxVectorSize]; final Object[] output = new Object[maxVectorSize];
@ -567,6 +613,15 @@ public class VectorProcessors
); );
} }
/**
* Creates an {@link ExprVectorProcessor} for the logical 'not' operator, which produces a long typed vector output
* with values set by the following rules:
* false -> true (1)
* null -> null
* true -> false (0)
*
* @see org.apache.druid.math.expr.UnaryNotExpr
*/
public static <T> ExprVectorProcessor<T> not(Expr.VectorInputBindingInspector inspector, Expr expr) public static <T> ExprVectorProcessor<T> not(Expr.VectorInputBindingInspector inspector, Expr expr)
{ {
final ExpressionType inputType = expr.getOutputType(inspector); final ExpressionType inputType = expr.getOutputType(inspector);
@ -574,7 +629,7 @@ public class VectorProcessors
ExprVectorProcessor<?> processor = null; ExprVectorProcessor<?> processor = null;
if (Types.is(inputType, ExprType.STRING)) { if (Types.is(inputType, ExprType.STRING)) {
processor = new LongOutObjectInFunctionVectorProcessor( processor = new LongOutObjectInFunctionVectorProcessor(
expr.buildVectorized(inspector), expr.asVectorProcessor(inspector),
maxVectorSize, maxVectorSize,
ExpressionType.STRING ExpressionType.STRING
) )
@ -589,7 +644,7 @@ public class VectorProcessors
} }
}; };
} else if (Types.is(inputType, ExprType.LONG)) { } else if (Types.is(inputType, ExprType.LONG)) {
processor = new LongOutLongInFunctionVectorValueProcessor(expr.buildVectorized(inspector), maxVectorSize) processor = new LongOutLongInFunctionVectorValueProcessor(expr.asVectorProcessor(inspector), maxVectorSize)
{ {
@Override @Override
public long apply(long input) public long apply(long input)
@ -599,7 +654,7 @@ public class VectorProcessors
}; };
} else if (Types.is(inputType, ExprType.DOUBLE)) { } else if (Types.is(inputType, ExprType.DOUBLE)) {
if (!ExpressionProcessing.useStrictBooleans()) { if (!ExpressionProcessing.useStrictBooleans()) {
processor = new DoubleOutDoubleInFunctionVectorValueProcessor(expr.buildVectorized(inspector), maxVectorSize) processor = new DoubleOutDoubleInFunctionVectorValueProcessor(expr.asVectorProcessor(inspector), maxVectorSize)
{ {
@Override @Override
public double apply(double input) public double apply(double input)
@ -608,7 +663,7 @@ public class VectorProcessors
} }
}; };
} else { } else {
processor = new LongOutDoubleInFunctionVectorValueProcessor(expr.buildVectorized(inspector), maxVectorSize) processor = new LongOutDoubleInFunctionVectorValueProcessor(expr.asVectorProcessor(inspector), maxVectorSize)
{ {
@Override @Override
public long apply(double input) public long apply(double input)
@ -624,6 +679,15 @@ public class VectorProcessors
return (ExprVectorProcessor<T>) processor; return (ExprVectorProcessor<T>) processor;
} }
/**
* Creates an {@link ExprVectorProcessor} for the logical 'or' operator, which produces a long typed vector output
* with values set by the following rules:
* true/null, null/true -> true (1)
* false/null, null/false, null/null -> null
* false/false -> false (0)
*
* @see org.apache.druid.math.expr.BinOrExpr
*/
public static <T> ExprVectorProcessor<T> or(Expr.VectorInputBindingInspector inspector, Expr left, Expr right) public static <T> ExprVectorProcessor<T> or(Expr.VectorInputBindingInspector inspector, Expr left, Expr right)
{ {
final int maxVectorSize = inspector.getMaxVectorSize(); final int maxVectorSize = inspector.getMaxVectorSize();
@ -633,8 +697,8 @@ public class VectorProcessors
right, right,
() -> new SymmetricalBivariateFunctionVectorProcessor<long[]>( () -> new SymmetricalBivariateFunctionVectorProcessor<long[]>(
ExpressionType.LONG, ExpressionType.LONG,
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector) right.asVectorProcessor(inspector)
) )
{ {
final long[] output = new long[maxVectorSize]; final long[] output = new long[maxVectorSize];
@ -657,7 +721,7 @@ public class VectorProcessors
if (leftNull) { if (leftNull) {
if (rightNull) { if (rightNull) {
output[i] = 0L; output[i] = 0L;
outputNulls[i] = true; outputNulls[i] = NullHandling.sqlCompatible();
return; return;
} }
final boolean bool = Evals.asBoolean(rightInput[i]); final boolean bool = Evals.asBoolean(rightInput[i]);
@ -682,8 +746,8 @@ public class VectorProcessors
}, },
() -> new BivariateFunctionVectorProcessor<double[], double[], long[]>( () -> new BivariateFunctionVectorProcessor<double[], double[], long[]>(
ExpressionType.LONG, ExpressionType.LONG,
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector) right.asVectorProcessor(inspector)
) )
{ {
final long[] output = new long[maxVectorSize]; final long[] output = new long[maxVectorSize];
@ -706,7 +770,7 @@ public class VectorProcessors
if (leftNull) { if (leftNull) {
if (rightNull) { if (rightNull) {
output[i] = 0; output[i] = 0;
outputNulls[i] = true; outputNulls[i] = NullHandling.sqlCompatible();
return; return;
} }
final boolean bool = Evals.asBoolean(rightInput[i]); final boolean bool = Evals.asBoolean(rightInput[i]);
@ -731,8 +795,8 @@ public class VectorProcessors
}, },
() -> new BivariateFunctionVectorProcessor<Object[], Object[], long[]>( () -> new BivariateFunctionVectorProcessor<Object[], Object[], long[]>(
ExpressionType.LONG, ExpressionType.LONG,
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector) right.asVectorProcessor(inspector)
) )
{ {
final long[] output = new long[maxVectorSize]; final long[] output = new long[maxVectorSize];
@ -753,7 +817,7 @@ public class VectorProcessors
final boolean rightNull = rightInput[i] == null; final boolean rightNull = rightInput[i] == null;
if (leftNull) { if (leftNull) {
if (rightNull) { if (rightNull) {
outputNulls[i] = true; outputNulls[i] = NullHandling.sqlCompatible();
return; return;
} }
final boolean bool = Evals.asBoolean((String) rightInput[i]); final boolean bool = Evals.asBoolean((String) rightInput[i]);
@ -778,6 +842,15 @@ public class VectorProcessors
); );
} }
/**
* Creates an {@link ExprVectorProcessor} for the logical 'and' operator, which produces a long typed vector output
* with values set by the following rules:
* true/true -> true (1)
* true/null, null/true, null/null -> null
* false/null, null/false -> false (0)
*
* @see org.apache.druid.math.expr.BinAndExpr
*/
public static <T> ExprVectorProcessor<T> and(Expr.VectorInputBindingInspector inputTypes, Expr left, Expr right) public static <T> ExprVectorProcessor<T> and(Expr.VectorInputBindingInspector inputTypes, Expr left, Expr right)
{ {
final int maxVectorSize = inputTypes.getMaxVectorSize(); final int maxVectorSize = inputTypes.getMaxVectorSize();
@ -787,8 +860,8 @@ public class VectorProcessors
right, right,
() -> new SymmetricalBivariateFunctionVectorProcessor<long[]>( () -> new SymmetricalBivariateFunctionVectorProcessor<long[]>(
ExpressionType.LONG, ExpressionType.LONG,
left.buildVectorized(inputTypes), left.asVectorProcessor(inputTypes),
right.buildVectorized(inputTypes) right.asVectorProcessor(inputTypes)
) )
{ {
final long[] output = new long[maxVectorSize]; final long[] output = new long[maxVectorSize];
@ -811,7 +884,7 @@ public class VectorProcessors
if (leftNull) { if (leftNull) {
if (rightNull) { if (rightNull) {
output[i] = 0L; output[i] = 0L;
outputNulls[i] = true; outputNulls[i] = NullHandling.sqlCompatible();
return; return;
} }
final boolean bool = Evals.asBoolean(rightInput[i]); final boolean bool = Evals.asBoolean(rightInput[i]);
@ -836,8 +909,8 @@ public class VectorProcessors
}, },
() -> new BivariateFunctionVectorProcessor<double[], double[], long[]>( () -> new BivariateFunctionVectorProcessor<double[], double[], long[]>(
ExpressionType.DOUBLE, ExpressionType.DOUBLE,
left.buildVectorized(inputTypes), left.asVectorProcessor(inputTypes),
right.buildVectorized(inputTypes) right.asVectorProcessor(inputTypes)
) )
{ {
final long[] output = new long[maxVectorSize]; final long[] output = new long[maxVectorSize];
@ -860,7 +933,7 @@ public class VectorProcessors
if (leftNull) { if (leftNull) {
if (rightNull) { if (rightNull) {
output[i] = 0L; output[i] = 0L;
outputNulls[i] = true; outputNulls[i] = NullHandling.sqlCompatible();
return; return;
} }
final boolean bool = Evals.asBoolean(rightInput[i]); final boolean bool = Evals.asBoolean(rightInput[i]);
@ -885,8 +958,8 @@ public class VectorProcessors
}, },
() -> new BivariateFunctionVectorProcessor<Object[], Object[], long[]>( () -> new BivariateFunctionVectorProcessor<Object[], Object[], long[]>(
ExpressionType.STRING, ExpressionType.STRING,
left.buildVectorized(inputTypes), left.asVectorProcessor(inputTypes),
right.buildVectorized(inputTypes) right.asVectorProcessor(inputTypes)
) )
{ {
final long[] output = new long[maxVectorSize]; final long[] output = new long[maxVectorSize];
@ -907,7 +980,7 @@ public class VectorProcessors
final boolean rightNull = rightInput[i] == null; final boolean rightNull = rightInput[i] == null;
if (leftNull) { if (leftNull) {
if (rightNull) { if (rightNull) {
outputNulls[i] = true; outputNulls[i] = NullHandling.sqlCompatible();
return; return;
} }
final boolean bool = Evals.asBoolean((String) rightInput[i]); final boolean bool = Evals.asBoolean((String) rightInput[i]);
@ -939,6 +1012,11 @@ public class VectorProcessors
// No instantiation // No instantiation
} }
/**
* Basic scaffolding for an 'identifier' {@link ExprVectorProcessor}
*
* @see #identifier
*/
abstract static class IdentifierVectorProcessor<T> implements ExprVectorProcessor<T> abstract static class IdentifierVectorProcessor<T> implements ExprVectorProcessor<T>
{ {
private final ExpressionType outputType; private final ExpressionType outputType;

View File

@ -34,8 +34,8 @@ public class VectorStringProcessors
final ExprVectorProcessor processor; final ExprVectorProcessor processor;
if (NullHandling.sqlCompatible()) { if (NullHandling.sqlCompatible()) {
processor = new ObjectOutObjectsInFunctionVectorProcessor( processor = new ObjectOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -50,8 +50,8 @@ public class VectorStringProcessors
}; };
} else { } else {
processor = new ObjectOutObjectsInFunctionVectorProcessor( processor = new ObjectOutObjectsInFunctionVectorProcessor(
left.buildVectorized(inspector), left.asVectorProcessor(inspector),
right.buildVectorized(inspector), right.asVectorProcessor(inspector),
inspector.getMaxVectorSize(), inspector.getMaxVectorSize(),
ExpressionType.STRING ExpressionType.STRING
) )
@ -73,7 +73,7 @@ public class VectorStringProcessors
final ExprVectorProcessor<Object[]>[] inputProcessors = new ExprVectorProcessor[inputs.size()]; final ExprVectorProcessor<Object[]>[] inputProcessors = new ExprVectorProcessor[inputs.size()];
for (int i = 0; i < inputs.size(); i++) { for (int i = 0; i < inputs.size(); i++) {
inputProcessors[i] = CastToTypeVectorProcessor.cast( inputProcessors[i] = CastToTypeVectorProcessor.cast(
inputs.get(i).buildVectorized(inspector), inputs.get(i).asVectorProcessor(inspector),
ExpressionType.STRING ExpressionType.STRING
); );
} }

View File

@ -206,7 +206,7 @@ public class AggregatorUtil
* Only one of fieldName and fieldExpression should be non-null * Only one of fieldName and fieldExpression should be non-null
*/ */
static ColumnValueSelector makeColumnValueSelectorWithFloatDefault( static ColumnValueSelector makeColumnValueSelectorWithFloatDefault(
final ColumnSelectorFactory metricFactory, final ColumnSelectorFactory columnSelectorFactory,
@Nullable final String fieldName, @Nullable final String fieldName,
@Nullable final Expr fieldExpression, @Nullable final Expr fieldExpression,
final float nullValue final float nullValue
@ -216,9 +216,12 @@ public class AggregatorUtil
throw new IllegalArgumentException("Only one of fieldName or expression should be non-null"); throw new IllegalArgumentException("Only one of fieldName or expression should be non-null");
} }
if (fieldName != null) { if (fieldName != null) {
return metricFactory.makeColumnValueSelector(fieldName); return columnSelectorFactory.makeColumnValueSelector(fieldName);
} else { } else {
final ColumnValueSelector<ExprEval> baseSelector = ExpressionSelectors.makeExprEvalSelector(metricFactory, fieldExpression); final ColumnValueSelector<ExprEval> baseSelector = ExpressionSelectors.makeExprEvalSelector(
columnSelectorFactory,
fieldExpression
);
class ExpressionFloatColumnSelector implements FloatColumnSelector class ExpressionFloatColumnSelector implements FloatColumnSelector
{ {
@Override @Override
@ -226,22 +229,22 @@ public class AggregatorUtil
{ {
// Although baseSelector.getObject is nullable // Although baseSelector.getObject is nullable
// exprEval returned from Expression selectors is never null. // exprEval returned from Expression selectors is never null.
final ExprEval exprEval = baseSelector.getObject(); final ExprEval<?> exprEval = baseSelector.getObject();
return exprEval.isNumericNull() ? nullValue : (float) exprEval.asDouble(); return exprEval.isNumericNull() ? nullValue : (float) exprEval.asDouble();
} }
@Override
public boolean isNull()
{
final ExprEval<?> exprEval = baseSelector.getObject();
return exprEval == null || exprEval.isNumericNull();
}
@Override @Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector) public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{ {
inspector.visit("baseSelector", baseSelector); inspector.visit("baseSelector", baseSelector);
} }
@Override
public boolean isNull()
{
final ExprEval exprEval = baseSelector.getObject();
return exprEval == null || exprEval.isNumericNull();
}
} }
return new ExpressionFloatColumnSelector(); return new ExpressionFloatColumnSelector();
} }
@ -250,8 +253,8 @@ public class AggregatorUtil
/** /**
* Only one of fieldName and fieldExpression should be non-null * Only one of fieldName and fieldExpression should be non-null
*/ */
static ColumnValueSelector makeColumnValueSelectorWithLongDefault( static ColumnValueSelector<?> makeColumnValueSelectorWithLongDefault(
final ColumnSelectorFactory metricFactory, final ColumnSelectorFactory columnSelectorFactory,
@Nullable final String fieldName, @Nullable final String fieldName,
@Nullable final Expr fieldExpression, @Nullable final Expr fieldExpression,
final long nullValue final long nullValue
@ -261,30 +264,33 @@ public class AggregatorUtil
throw new IllegalArgumentException("Only one of fieldName and fieldExpression should be non-null"); throw new IllegalArgumentException("Only one of fieldName and fieldExpression should be non-null");
} }
if (fieldName != null) { if (fieldName != null) {
return metricFactory.makeColumnValueSelector(fieldName); return columnSelectorFactory.makeColumnValueSelector(fieldName);
} else { } else {
final ColumnValueSelector<ExprEval> baseSelector = ExpressionSelectors.makeExprEvalSelector(metricFactory, fieldExpression); final ColumnValueSelector<ExprEval> baseSelector = ExpressionSelectors.makeExprEvalSelector(
columnSelectorFactory,
fieldExpression
);
class ExpressionLongColumnSelector implements LongColumnSelector class ExpressionLongColumnSelector implements LongColumnSelector
{ {
@Override @Override
public long getLong() public long getLong()
{ {
final ExprEval exprEval = baseSelector.getObject(); final ExprEval<?> exprEval = baseSelector.getObject();
return exprEval.isNumericNull() ? nullValue : exprEval.asLong(); return exprEval.isNumericNull() ? nullValue : exprEval.asLong();
} }
@Override
public boolean isNull()
{
final ExprEval<?> exprEval = baseSelector.getObject();
return exprEval == null || exprEval.isNumericNull();
}
@Override @Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector) public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{ {
inspector.visit("baseSelector", baseSelector); inspector.visit("baseSelector", baseSelector);
} }
@Override
public boolean isNull()
{
final ExprEval exprEval = baseSelector.getObject();
return exprEval == null || exprEval.isNumericNull();
}
} }
return new ExpressionLongColumnSelector(); return new ExpressionLongColumnSelector();
} }
@ -293,8 +299,8 @@ public class AggregatorUtil
/** /**
* Only one of fieldName and fieldExpression should be non-null * Only one of fieldName and fieldExpression should be non-null
*/ */
static ColumnValueSelector makeColumnValueSelectorWithDoubleDefault( static ColumnValueSelector<?> makeColumnValueSelectorWithDoubleDefault(
final ColumnSelectorFactory metricFactory, final ColumnSelectorFactory columnSelectorFactory,
@Nullable final String fieldName, @Nullable final String fieldName,
@Nullable final Expr fieldExpression, @Nullable final Expr fieldExpression,
final double nullValue final double nullValue
@ -304,30 +310,33 @@ public class AggregatorUtil
throw new IllegalArgumentException("Only one of fieldName and fieldExpression should be non-null"); throw new IllegalArgumentException("Only one of fieldName and fieldExpression should be non-null");
} }
if (fieldName != null) { if (fieldName != null) {
return metricFactory.makeColumnValueSelector(fieldName); return columnSelectorFactory.makeColumnValueSelector(fieldName);
} else { } else {
final ColumnValueSelector<ExprEval> baseSelector = ExpressionSelectors.makeExprEvalSelector(metricFactory, fieldExpression); final ColumnValueSelector<ExprEval> baseSelector = ExpressionSelectors.makeExprEvalSelector(
columnSelectorFactory,
fieldExpression
);
class ExpressionDoubleColumnSelector implements DoubleColumnSelector class ExpressionDoubleColumnSelector implements DoubleColumnSelector
{ {
@Override @Override
public double getDouble() public double getDouble()
{ {
final ExprEval exprEval = baseSelector.getObject(); final ExprEval<?> exprEval = baseSelector.getObject();
return exprEval.isNumericNull() ? nullValue : exprEval.asDouble(); return exprEval.isNumericNull() ? nullValue : exprEval.asDouble();
} }
@Override
public boolean isNull()
{
final ExprEval<?> exprEval = baseSelector.getObject();
return exprEval == null || exprEval.isNumericNull();
}
@Override @Override
public void inspectRuntimeShape(RuntimeShapeInspector inspector) public void inspectRuntimeShape(RuntimeShapeInspector inspector)
{ {
inspector.visit("baseSelector", baseSelector); inspector.visit("baseSelector", baseSelector);
} }
@Override
public boolean isNull()
{
final ExprEval exprEval = baseSelector.getObject();
return exprEval == null || exprEval.isNumericNull();
}
} }
return new ExpressionDoubleColumnSelector(); return new ExpressionDoubleColumnSelector();
} }

View File

@ -59,7 +59,7 @@ public class ExpressionLambdaAggregator implements Aggregator
} }
} }
final ExprEval<?> eval = lambda.eval(bindings); final ExprEval<?> eval = lambda.eval(bindings);
final int estimatedSize = eval.type().getNullableStrategy().estimateSizeBytes(eval.value()); final int estimatedSize = eval.type().getNullableStrategy().estimateSizeBytes(eval.valueOrDefault());
if (estimatedSize > maxSizeBytes) { if (estimatedSize > maxSizeBytes) {
throw new ISE( throw new ISE(
"Exceeded memory usage when aggregating type [%s], size [%s] is larger than max [%s]", "Exceeded memory usage when aggregating type [%s], size [%s] is larger than max [%s]",
@ -76,7 +76,7 @@ public class ExpressionLambdaAggregator implements Aggregator
@Override @Override
public Object get() public Object get()
{ {
return hasValue ? bindings.getAccumulator().value() : null; return hasValue ? bindings.getAccumulator().valueOrDefault() : null;
} }
@Override @Override

View File

@ -346,7 +346,7 @@ public class ExpressionLambdaAggregatorFactory extends AggregatorFactory
// arbitrarily assign lhs and rhs to accumulator and aggregator name inputs to re-use combine function // arbitrarily assign lhs and rhs to accumulator and aggregator name inputs to re-use combine function
return combineExpression.get().eval( return combineExpression.get().eval(
combineBindings.get().withBinding(accumulatorId, lhs).withBinding(name, rhs) combineBindings.get().withBinding(accumulatorId, lhs).withBinding(name, rhs)
).value(); ).valueOrDefault();
} }
@Override @Override
@ -362,7 +362,7 @@ public class ExpressionLambdaAggregatorFactory extends AggregatorFactory
Expr finalizeExpr; Expr finalizeExpr;
finalizeExpr = finalizeExpression.get(); finalizeExpr = finalizeExpression.get();
if (finalizeExpr != null) { if (finalizeExpr != null) {
return finalizeExpr.eval(finalizeBindings.get().withBinding(FINALIZE_IDENTIFIER, object)).value(); return finalizeExpr.eval(finalizeBindings.get().withBinding(FINALIZE_IDENTIFIER, object)).valueOrDefault();
} }
return object; return object;
} }

View File

@ -53,7 +53,7 @@ public class ExpressionLambdaAggregatorInputBindings implements Expr.ObjectBindi
public Object get(String name) public Object get(String name)
{ {
if (accumlatorIdentifier.equals(name)) { if (accumlatorIdentifier.equals(name)) {
return accumulator.value(); return accumulator.valueOrDefault();
} }
return inputBindings.get(name); return inputBindings.get(name);
} }

View File

@ -90,7 +90,7 @@ public class ExpressionLambdaBufferAggregator implements BufferAggregator
if (isNullUnlessAggregated && (buf.get(position) & NOT_AGGREGATED_BIT) != 0) { if (isNullUnlessAggregated && (buf.get(position) & NOT_AGGREGATED_BIT) != 0) {
return null; return null;
} }
return ExprEval.deserialize(buf, position, maxSizeBytes, outputType, false).value(); return ExprEval.deserialize(buf, position, maxSizeBytes, outputType, false).valueOrDefault();
} }
@Override @Override

View File

@ -171,7 +171,7 @@ public class ExpressionPostAggregator implements PostAggregator
} }
); );
return parsed.get().eval(InputBindings.withMap(finalizedValues)).value(); return parsed.get().eval(InputBindings.withMap(finalizedValues)).valueOrDefault();
} }
@Override @Override

View File

@ -66,7 +66,7 @@ public class ExprUtils
origin = null; origin = null;
} else { } else {
Chronology chronology = timeZone == null ? ISOChronology.getInstanceUTC() : ISOChronology.getInstance(timeZone); Chronology chronology = timeZone == null ? ISOChronology.getInstanceUTC() : ISOChronology.getInstance(timeZone);
final Object value = originArg.eval(bindings).value(); final Object value = originArg.eval(bindings).valueOrDefault();
if (value instanceof String && NullHandling.isNullOrEquivalent((String) value)) { if (value instanceof String && NullHandling.isNullOrEquivalent((String) value)) {
// We get a blank string here, when sql compatible null handling is enabled // We get a blank string here, when sql compatible null handling is enabled
// and expression contains empty string for for origin // and expression contains empty string for for origin

View File

@ -124,11 +124,11 @@ public class TimestampFloorExprMacro implements ExprMacroTable.ExprMacro
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
ExprVectorProcessor<?> processor; ExprVectorProcessor<?> processor;
processor = new LongOutLongInFunctionVectorValueProcessor( processor = new LongOutLongInFunctionVectorValueProcessor(
CastToTypeVectorProcessor.cast(args.get(0).buildVectorized(inspector), ExpressionType.LONG), CastToTypeVectorProcessor.cast(args.get(0).asVectorProcessor(inspector), ExpressionType.LONG),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {

View File

@ -119,11 +119,11 @@ public class TimestampShiftExprMacro implements ExprMacroTable.ExprMacro
} }
@Override @Override
public <T> ExprVectorProcessor<T> buildVectorized(VectorInputBindingInspector inspector) public <T> ExprVectorProcessor<T> asVectorProcessor(VectorInputBindingInspector inspector)
{ {
ExprVectorProcessor<?> processor; ExprVectorProcessor<?> processor;
processor = new LongOutLongInFunctionVectorValueProcessor( processor = new LongOutLongInFunctionVectorValueProcessor(
CastToTypeVectorProcessor.cast(args.get(0).buildVectorized(inspector), ExpressionType.LONG), CastToTypeVectorProcessor.cast(args.get(0).asVectorProcessor(inspector), ExpressionType.LONG),
inspector.getMaxVectorSize() inspector.getMaxVectorSize()
) )
{ {

View File

@ -110,7 +110,7 @@ public class ExpressionSelectors
{ {
// No need for null check on getObject() since baseSelector impls will never return null. // No need for null check on getObject() since baseSelector impls will never return null.
ExprEval eval = baseSelector.getObject(); ExprEval eval = baseSelector.getObject();
return eval.value(); return eval.valueOrDefault();
} }
@Override @Override
@ -196,14 +196,7 @@ public class ExpressionSelectors
Expr expression Expr expression
) )
{ {
return makeExprEvalSelector(columnSelectorFactory, ExpressionPlanner.plan(columnSelectorFactory, expression)); ExpressionPlan plan = ExpressionPlanner.plan(columnSelectorFactory, expression);
}
public static ColumnValueSelector<ExprEval> makeExprEvalSelector(
ColumnSelectorFactory columnSelectorFactory,
ExpressionPlan plan
)
{
final RowIdSupplier rowIdSupplier = columnSelectorFactory.getRowIdSupplier(); final RowIdSupplier rowIdSupplier = columnSelectorFactory.getRowIdSupplier();
if (plan.is(ExpressionPlan.Trait.SINGLE_INPUT_SCALAR)) { if (plan.is(ExpressionPlan.Trait.SINGLE_INPUT_SCALAR)) {
@ -548,6 +541,6 @@ public class ExpressionSelectors
} }
return Arrays.stream(asArray).collect(Collectors.toList()); return Arrays.stream(asArray).collect(Collectors.toList());
} }
return eval.value(); return eval.valueOrDefault();
} }
} }

View File

@ -79,11 +79,11 @@ public class ExpressionVectorSelectors
if (plan.isConstant()) { if (plan.isConstant()) {
return ConstantVectorSelectors.vectorValueSelector( return ConstantVectorSelectors.vectorValueSelector(
factory.getReadableVectorInspector(), factory.getReadableVectorInspector(),
(Number) plan.getExpression().eval(InputBindings.nilBindings()).value() (Number) plan.getExpression().eval(InputBindings.nilBindings()).valueOrDefault()
); );
} }
final Expr.VectorInputBinding bindings = createVectorBindings(plan.getAnalysis(), factory); final Expr.VectorInputBinding bindings = createVectorBindings(plan.getAnalysis(), factory);
final ExprVectorProcessor<?> processor = plan.getExpression().buildVectorized(bindings); final ExprVectorProcessor<?> processor = plan.getExpression().asVectorProcessor(bindings);
return new ExpressionVectorValueSelector(processor, bindings); return new ExpressionVectorValueSelector(processor, bindings);
} }
@ -98,12 +98,12 @@ public class ExpressionVectorSelectors
if (plan.isConstant()) { if (plan.isConstant()) {
return ConstantVectorSelectors.vectorObjectSelector( return ConstantVectorSelectors.vectorObjectSelector(
factory.getReadableVectorInspector(), factory.getReadableVectorInspector(),
plan.getExpression().eval(InputBindings.nilBindings()).value() plan.getExpression().eval(InputBindings.nilBindings()).valueOrDefault()
); );
} }
final Expr.VectorInputBinding bindings = createVectorBindings(plan.getAnalysis(), factory); final Expr.VectorInputBinding bindings = createVectorBindings(plan.getAnalysis(), factory);
final ExprVectorProcessor<?> processor = plan.getExpression().buildVectorized(bindings); final ExprVectorProcessor<?> processor = plan.getExpression().asVectorProcessor(bindings);
return new ExpressionVectorObjectSelector(processor, bindings); return new ExpressionVectorObjectSelector(processor, bindings);
} }

View File

@ -507,7 +507,7 @@ public class NestedFieldVirtualColumn implements VirtualColumn
nullVector = new boolean[objectSelector.getMaxVectorSize()]; nullVector = new boolean[objectSelector.getMaxVectorSize()];
} }
longVector[i] = 0L; longVector[i] = 0L;
nullVector[i] = true; nullVector[i] = NullHandling.sqlCompatible();
} else { } else {
Long l; Long l;
if (v instanceof Number) { if (v instanceof Number) {
@ -525,7 +525,7 @@ public class NestedFieldVirtualColumn implements VirtualColumn
nullVector = new boolean[objectSelector.getMaxVectorSize()]; nullVector = new boolean[objectSelector.getMaxVectorSize()];
} }
longVector[i] = 0L; longVector[i] = 0L;
nullVector[i] = true; nullVector[i] = NullHandling.sqlCompatible();
} }
} }
} }
@ -570,7 +570,7 @@ public class NestedFieldVirtualColumn implements VirtualColumn
nullVector = new boolean[objectSelector.getMaxVectorSize()]; nullVector = new boolean[objectSelector.getMaxVectorSize()];
} }
doubleVector[i] = 0.0; doubleVector[i] = 0.0;
nullVector[i] = true; nullVector[i] = NullHandling.sqlCompatible();
} else { } else {
Double d; Double d;
if (v instanceof Number) { if (v instanceof Number) {
@ -588,7 +588,7 @@ public class NestedFieldVirtualColumn implements VirtualColumn
nullVector = new boolean[objectSelector.getMaxVectorSize()]; nullVector = new boolean[objectSelector.getMaxVectorSize()];
} }
doubleVector[i] = 0.0; doubleVector[i] = 0.0;
nullVector[i] = true; nullVector[i] = NullHandling.sqlCompatible();
} }
} }
} }

View File

@ -62,7 +62,7 @@ public class SingleStringInputDeferredEvaluationExpressionDimensionVectorSelecto
} }
this.selector = selector; this.selector = selector;
this.inputBinding = new StringLookupVectorInputBindings(); this.inputBinding = new StringLookupVectorInputBindings();
this.stringProcessor = expression.buildVectorized(inputBinding); this.stringProcessor = expression.asVectorProcessor(inputBinding);
} }
@Override @Override

View File

@ -247,18 +247,18 @@ public class EvalTest extends InitializedNullHandlingTest
// test casting arrays to scalars // test casting arrays to scalars
assertEquals(1L, ExprEval.ofLongArray(new Long[]{1L}).castTo(ExpressionType.LONG).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(null, 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.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", 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(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(null, ExprEval.ofDoubleArray(new Double[]{null}).castTo(ExpressionType.DOUBLE).value());
assertEquals(1L, ExprEval.ofDoubleArray(new Double[]{1.1}).castTo(ExpressionType.LONG).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("1.1", ExprEval.ofDoubleArray(new Double[]{1.1}).castTo(ExpressionType.STRING).value());
assertEquals("foo", ExprEval.ofStringArray(new String[]{"foo"}).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(null, ExprEval.ofStringArray(new String[]{"foo"}).castTo(ExpressionType.LONG).value());
assertEquals(NullHandling.defaultDoubleValue(), ExprEval.ofStringArray(new String[]{"foo"}).castTo(ExpressionType.DOUBLE).value()); assertEquals(null, ExprEval.ofStringArray(new String[]{"foo"}).castTo(ExpressionType.DOUBLE).value());
assertEquals("1", ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.STRING).value()); assertEquals("1", ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.STRING).value());
assertEquals(1L, ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.LONG).value()); assertEquals(1L, ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.LONG).value());
assertEquals(1.0, ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.DOUBLE).value()); assertEquals(1.0, ExprEval.ofStringArray(new String[]{"1"}).castTo(ExpressionType.DOUBLE).value());
@ -518,17 +518,18 @@ public class EvalTest extends InitializedNullHandlingTest
assertEquals(1L, eval("null || 1", bindings).value()); assertEquals(1L, eval("null || 1", bindings).value());
assertEquals(1L, eval("1 || null", bindings).value()); assertEquals(1L, eval("1 || null", bindings).value());
assertEquals(NullHandling.defaultLongValue(), eval("null || 0", bindings).value()); // in sql incompatible mode, null is false, so we return 0
assertEquals(NullHandling.defaultLongValue(), eval("0 || null", bindings).value()); assertEquals(NullHandling.defaultLongValue(), eval("null || 0", bindings).valueOrDefault());
// null/null is evaluated as string typed assertEquals(NullHandling.defaultLongValue(), eval("0 || null", bindings).valueOrDefault());
assertEquals(NullHandling.defaultLongValue(), eval("null || null", bindings).value()); assertEquals(NullHandling.defaultLongValue(), eval("null || null", bindings).valueOrDefault());
assertEquals(NullHandling.defaultLongValue(), eval("null && 1", bindings).value()); // in sql incompatible mode, null is false, so we return 0
assertEquals(NullHandling.defaultLongValue(), eval("1 && null", bindings).value()); assertEquals(NullHandling.defaultLongValue(), eval("null && 1", bindings).valueOrDefault());
assertEquals(NullHandling.defaultLongValue(), eval("1 && null", bindings).valueOrDefault());
assertEquals(NullHandling.defaultLongValue(), eval("null && null", bindings).valueOrDefault());
// if either side is false, output is false in both modes
assertEquals(0L, eval("null && 0", bindings).value()); assertEquals(0L, eval("null && 0", bindings).value());
assertEquals(0L, eval("0 && null", 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 { finally {
// reset // reset
@ -707,6 +708,26 @@ public class EvalTest extends InitializedNullHandlingTest
} }
} }
@Test
public void testValueOrDefault()
{
ExprEval<?> longNull = ExprEval.ofLong(null);
ExprEval<?> doubleNull = ExprEval.ofDouble(null);
Assert.assertEquals(NullHandling.sqlCompatible(), longNull.isNumericNull());
Assert.assertEquals(NullHandling.sqlCompatible(), doubleNull.isNumericNull());
Assert.assertEquals(NullHandling.defaultLongValue(), longNull.valueOrDefault());
Assert.assertEquals(NullHandling.defaultDoubleValue(), doubleNull.valueOrDefault());
if (NullHandling.replaceWithDefault()) {
Assert.assertEquals(0L, longNull.asLong());
Assert.assertEquals(0, longNull.asInt());
Assert.assertEquals(0.0, longNull.asDouble(), 0.0);
Assert.assertEquals(0L, doubleNull.asLong());
Assert.assertEquals(0, doubleNull.asInt());
Assert.assertEquals(0.0, doubleNull.asDouble(), 0.0);
}
}
@Test @Test
public void testEvalOfType() public void testEvalOfType()
{ {
@ -831,7 +852,7 @@ public class EvalTest extends InitializedNullHandlingTest
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1L, 2L, null, 3L}); eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1L, 2L, null, 3L});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
Assert.assertArrayEquals(new Object[] {1L, 2L, NullHandling.defaultLongValue(), 3L}, (Object[]) eval.value()); Assert.assertArrayEquals(new Object[] {1L, 2L, null, 3L}, (Object[]) eval.value());
// arrays might have to fall back to using 'bestEffortOf', but will cast it to the expected output type // arrays might have to fall back to using 'bestEffortOf', but will cast it to the expected output type
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {"1", "2", "3"}); eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {"1", "2", "3"});
@ -844,7 +865,7 @@ public class EvalTest extends InitializedNullHandlingTest
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {"1", "2", "wat", "3"}); eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {"1", "2", "wat", "3"});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
Assert.assertArrayEquals(new Object[] {1L, 2L, NullHandling.defaultLongValue(), 3L}, (Object[]) eval.value()); Assert.assertArrayEquals(new Object[] {1L, 2L, null, 3L}, (Object[]) eval.value());
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1.0, 2.0, 3.0}); eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1.0, 2.0, 3.0});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
@ -856,7 +877,7 @@ public class EvalTest extends InitializedNullHandlingTest
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1.0, 2.0, null, 3.0}); eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1.0, 2.0, null, 3.0});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
Assert.assertArrayEquals(new Object[] {1L, 2L, NullHandling.defaultLongValue(), 3L}, (Object[]) eval.value()); Assert.assertArrayEquals(new Object[] {1L, 2L, null, 3L}, (Object[]) eval.value());
eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1.0, 2L, "3", true, false}); eval = ExprEval.ofType(ExpressionType.LONG_ARRAY, new Object[] {1.0, 2L, "3", true, false});
Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.LONG_ARRAY, eval.type());
@ -885,7 +906,7 @@ public class EvalTest extends InitializedNullHandlingTest
eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {"1", "2", "wat", "3"}); eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {"1", "2", "wat", "3"});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
Assert.assertArrayEquals(new Object[] {1.0, 2.0, NullHandling.defaultDoubleValue(), 3.0}, (Object[]) eval.value()); Assert.assertArrayEquals(new Object[] {1.0, 2.0, null, 3.0}, (Object[]) eval.value());
eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1L, 2L, 3L}); eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1L, 2L, 3L});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
@ -897,7 +918,7 @@ public class EvalTest extends InitializedNullHandlingTest
eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1L, 2L, null, 3L}); eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1L, 2L, null, 3L});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
Assert.assertArrayEquals(new Object[] {1.0, 2.0, NullHandling.defaultDoubleValue(), 3.0}, (Object[]) eval.value()); Assert.assertArrayEquals(new Object[] {1.0, 2.0, null, 3.0}, (Object[]) eval.value());
eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1.0, 2L, "3", true, false}); eval = ExprEval.ofType(ExpressionType.DOUBLE_ARRAY, new Object[] {1.0, 2L, "3", true, false});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
@ -934,7 +955,7 @@ public class EvalTest extends InitializedNullHandlingTest
ExpressionType nestedLongArray = ExpressionTypeFactory.getInstance().ofArray(ExpressionType.LONG_ARRAY); ExpressionType nestedLongArray = ExpressionTypeFactory.getInstance().ofArray(ExpressionType.LONG_ARRAY);
final Object[] expectedLongArray = new Object[]{ final Object[] expectedLongArray = new Object[]{
new Object[] {1L, 2L, 3L}, new Object[] {1L, 2L, 3L},
new Object[] {5L, NullHandling.defaultLongValue(), 9L}, new Object[] {5L, null, 9L},
null, null,
new Object[] {2L, 4L, 6L} new Object[] {2L, 4L, 6L}
}; };
@ -979,7 +1000,7 @@ public class EvalTest extends InitializedNullHandlingTest
ExpressionType nestedDoubleArray = ExpressionTypeFactory.getInstance().ofArray(ExpressionType.DOUBLE_ARRAY); ExpressionType nestedDoubleArray = ExpressionTypeFactory.getInstance().ofArray(ExpressionType.DOUBLE_ARRAY);
final Object[] expectedDoubleArray = new Object[]{ final Object[] expectedDoubleArray = new Object[]{
new Object[] {1.1, 2.2, 3.3}, new Object[] {1.1, 2.2, 3.3},
new Object[] {5.5, NullHandling.defaultDoubleValue(), 9.9}, new Object[] {5.5, null, 9.9},
null, null,
new Object[] {2.2, 4.4, 6.6} new Object[] {2.2, 4.4, 6.6}
}; };
@ -1109,7 +1130,7 @@ public class EvalTest extends InitializedNullHandlingTest
eval = ExprEval.bestEffortOf(new Object[] {null, 1.0, 2.0, 3.0}); eval = ExprEval.bestEffortOf(new Object[] {null, 1.0, 2.0, 3.0});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());
Assert.assertArrayEquals(new Object[] {NullHandling.defaultDoubleValue(), 1.0, 2.0, 3.0}, (Object[]) eval.value()); Assert.assertArrayEquals(new Object[] {null, 1.0, 2.0, 3.0}, (Object[]) eval.value());
eval = ExprEval.bestEffortOf(new Double[] {1.0, 2.0, 3.0}); eval = ExprEval.bestEffortOf(new Double[] {1.0, 2.0, 3.0});
Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type()); Assert.assertEquals(ExpressionType.DOUBLE_ARRAY, eval.type());

View File

@ -21,7 +21,6 @@ package org.apache.druid.math.expr;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.java.util.common.ISE; import org.apache.druid.java.util.common.ISE;
import org.apache.druid.java.util.common.NonnullPair; import org.apache.druid.java.util.common.NonnullPair;
import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.java.util.common.StringUtils;
@ -403,11 +402,11 @@ public class ExprEvalTest extends InitializedNullHandlingTest
{ {
ExprEval someStringArray = ExprEval.ofStringArray(new String[]{"1", "2", "foo", null, "3.3"}); ExprEval someStringArray = ExprEval.ofStringArray(new String[]{"1", "2", "foo", null, "3.3"});
Assert.assertArrayEquals( Assert.assertArrayEquals(
new Object[]{1L, 2L, NullHandling.defaultLongValue(), NullHandling.defaultLongValue(), 3L}, new Object[]{1L, 2L, null, null, 3L},
someStringArray.castTo(ExpressionType.LONG_ARRAY).asArray() someStringArray.castTo(ExpressionType.LONG_ARRAY).asArray()
); );
Assert.assertArrayEquals( Assert.assertArrayEquals(
new Object[]{1.0, 2.0, NullHandling.defaultDoubleValue(), NullHandling.defaultDoubleValue(), 3.3}, new Object[]{1.0, 2.0, null, null, 3.3},
someStringArray.castTo(ExpressionType.DOUBLE_ARRAY).asArray() someStringArray.castTo(ExpressionType.DOUBLE_ARRAY).asArray()
); );
} }

View File

@ -139,7 +139,7 @@ public class FunctionTest extends InitializedNullHandlingTest
public void testStrlen() public void testStrlen()
{ {
assertExpr("strlen(x)", 3L); assertExpr("strlen(x)", 3L);
assertExpr("strlen(nonexistent)", NullHandling.defaultLongValue()); assertExpr("strlen(nonexistent)", null);
} }
@Test @Test
@ -298,7 +298,7 @@ public class FunctionTest extends InitializedNullHandlingTest
public void testArrayAppend() public void testArrayAppend()
{ {
assertArrayExpr("array_append([1, 2, 3], 4)", new Long[]{1L, 2L, 3L, 4L}); assertArrayExpr("array_append([1, 2, 3], 4)", new Long[]{1L, 2L, 3L, 4L});
assertArrayExpr("array_append([1, 2, 3], 'bar')", new Long[]{1L, 2L, 3L, NullHandling.defaultLongValue()}); assertArrayExpr("array_append([1, 2, 3], 'bar')", new Long[]{1L, 2L, 3L, null});
assertArrayExpr("array_append([], 1)", new String[]{"1"}); assertArrayExpr("array_append([], 1)", new String[]{"1"});
assertArrayExpr("array_append(<LONG>[], 1)", new Long[]{1L}); assertArrayExpr("array_append(<LONG>[], 1)", new Long[]{1L});
} }
@ -317,11 +317,11 @@ public class FunctionTest extends InitializedNullHandlingTest
public void testArraySetAdd() public void testArraySetAdd()
{ {
assertArrayExpr("array_set_add([1, 2, 3], 4)", new Long[]{1L, 2L, 3L, 4L}); assertArrayExpr("array_set_add([1, 2, 3], 4)", new Long[]{1L, 2L, 3L, 4L});
assertArrayExpr("array_set_add([1, 2, 3], 'bar')", new Long[]{NullHandling.defaultLongValue(), 1L, 2L, 3L}); assertArrayExpr("array_set_add([1, 2, 3], 'bar')", new Long[]{null, 1L, 2L, 3L});
assertArrayExpr("array_set_add([1, 2, 2], 1)", new Long[]{1L, 2L}); assertArrayExpr("array_set_add([1, 2, 2], 1)", new Long[]{1L, 2L});
assertArrayExpr("array_set_add([], 1)", new String[]{"1"}); assertArrayExpr("array_set_add([], 1)", new String[]{"1"});
assertArrayExpr("array_set_add(<LONG>[], 1)", new Long[]{1L}); assertArrayExpr("array_set_add(<LONG>[], 1)", new Long[]{1L});
assertArrayExpr("array_set_add(<LONG>[], null)", new Long[]{NullHandling.defaultLongValue()}); assertArrayExpr("array_set_add(<LONG>[], null)", new Long[]{null});
} }
@Test @Test
@ -392,7 +392,7 @@ public class FunctionTest extends InitializedNullHandlingTest
public void testArrayPrepend() public void testArrayPrepend()
{ {
assertArrayExpr("array_prepend(4, [1, 2, 3])", new Long[]{4L, 1L, 2L, 3L}); assertArrayExpr("array_prepend(4, [1, 2, 3])", new Long[]{4L, 1L, 2L, 3L});
assertArrayExpr("array_prepend('bar', [1, 2, 3])", new Long[]{NullHandling.defaultLongValue(), 1L, 2L, 3L}); assertArrayExpr("array_prepend('bar', [1, 2, 3])", new Long[]{null, 1L, 2L, 3L});
assertArrayExpr("array_prepend(1, [])", new String[]{"1"}); assertArrayExpr("array_prepend(1, [])", new String[]{"1"});
assertArrayExpr("array_prepend(1, <LONG>[])", new Long[]{1L}); assertArrayExpr("array_prepend(1, <LONG>[])", new Long[]{1L});
assertArrayExpr("array_prepend(1, <DOUBLE>[])", new Double[]{1.0}); assertArrayExpr("array_prepend(1, <DOUBLE>[])", new Double[]{1.0});
@ -797,10 +797,10 @@ public class FunctionTest extends InitializedNullHandlingTest
// happy path maths // happy path maths
assertExpr("safe_divide(3, 1)", 3L); assertExpr("safe_divide(3, 1)", 3L);
assertExpr("safe_divide(4.5, 2)", 2.25); assertExpr("safe_divide(4.5, 2)", 2.25);
assertExpr("safe_divide(3, 0)", NullHandling.defaultLongValue()); assertExpr("safe_divide(3, 0)", null);
assertExpr("safe_divide(1, 0.0)", NullHandling.defaultDoubleValue()); assertExpr("safe_divide(1, 0.0)", null);
// NaN and Infinity cases // NaN and Infinity cases
assertExpr("safe_divide(NaN, 0.0)", NullHandling.defaultDoubleValue()); assertExpr("safe_divide(NaN, 0.0)", null);
assertExpr("safe_divide(0, NaN)", 0.0); assertExpr("safe_divide(0, NaN)", 0.0);
assertExpr("safe_divide(0, POSITIVE_INFINITY)", NullHandling.defaultLongValue()); assertExpr("safe_divide(0, POSITIVE_INFINITY)", NullHandling.defaultLongValue());
assertExpr("safe_divide(POSITIVE_INFINITY,0)", NullHandling.defaultLongValue()); assertExpr("safe_divide(POSITIVE_INFINITY,0)", NullHandling.defaultLongValue());

View File

@ -45,7 +45,7 @@ import java.util.function.Supplier;
* randomize inputs to various vector expressions and make sure the results match nonvectorized expressions * randomize inputs to various vector expressions and make sure the results match nonvectorized expressions
* *
* this is not a replacement for correctness tests, but will ensure that vectorized and non-vectorized expression * this is not a replacement for correctness tests, but will ensure that vectorized and non-vectorized expression
* evaluation is at least self consistent... * evaluation is at least self-consistent...
*/ */
public class VectorExprSanityTest extends InitializedNullHandlingTest public class VectorExprSanityTest extends InitializedNullHandlingTest
{ {
@ -302,11 +302,12 @@ public class VectorExprSanityTest extends InitializedNullHandlingTest
{ {
Assert.assertTrue(StringUtils.format("Cannot vectorize %s", expr), parsed.canVectorize(bindings.rhs)); Assert.assertTrue(StringUtils.format("Cannot vectorize %s", expr), parsed.canVectorize(bindings.rhs));
ExpressionType outputType = parsed.getOutputType(bindings.rhs); ExpressionType outputType = parsed.getOutputType(bindings.rhs);
ExprEvalVector<?> vectorEval = parsed.buildVectorized(bindings.rhs).evalVector(bindings.rhs); ExprEvalVector<?> vectorEval = parsed.asVectorProcessor(bindings.rhs).evalVector(bindings.rhs);
// 'null' expressions can have an output type of null, but still evaluate in default mode, so skip type checks // 'null' expressions can have an output type of null, but still evaluate in default mode, so skip type checks
if (outputType != null) { if (outputType != null) {
Assert.assertEquals(expr, outputType, vectorEval.getType()); Assert.assertEquals(expr, outputType, vectorEval.getType());
} }
final Object[] vectorVals = vectorEval.getObjectVector();
for (int i = 0; i < VECTOR_SIZE; i++) { for (int i = 0; i < VECTOR_SIZE; i++) {
ExprEval<?> eval = parsed.eval(bindings.lhs[i]); ExprEval<?> eval = parsed.eval(bindings.lhs[i]);
// 'null' expressions can have an output type of null, but still evaluate in default mode, so skip type checks // 'null' expressions can have an output type of null, but still evaluate in default mode, so skip type checks
@ -315,8 +316,8 @@ public class VectorExprSanityTest extends InitializedNullHandlingTest
} }
Assert.assertEquals( Assert.assertEquals(
StringUtils.format("Values do not match for row %s for expression %s", i, expr), StringUtils.format("Values do not match for row %s for expression %s", i, expr),
eval.value(), eval.valueOrDefault(),
vectorEval.get(i) vectorVals[i]
); );
} }
} }

View File

@ -193,8 +193,7 @@ public class ExprMacroTest
@Test @Test
public void testIPv4AddressParse() public void testIPv4AddressParse()
{ {
Long nullLong = NullHandling.replaceWithDefault() ? NullHandling.ZERO_LONG : null; assertExpr("ipv4_parse(x)", null);
assertExpr("ipv4_parse(x)", nullLong);
assertExpr("ipv4_parse(ipv4_string)", IPV4_LONG); assertExpr("ipv4_parse(ipv4_string)", IPV4_LONG);
assertExpr("ipv4_parse(ipv4_long)", IPV4_LONG); assertExpr("ipv4_parse(ipv4_long)", IPV4_LONG);
assertExpr("ipv4_parse(ipv4_stringify(ipv4_long))", IPV4_LONG); assertExpr("ipv4_parse(ipv4_stringify(ipv4_long))", IPV4_LONG);

View File

@ -19,7 +19,6 @@
package org.apache.druid.query.expression; package org.apache.druid.query.expression;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.math.expr.Expr; import org.apache.druid.math.expr.Expr;
import org.apache.druid.math.expr.ExprEval; import org.apache.druid.math.expr.ExprEval;
import org.apache.druid.math.expr.InputBindings; import org.apache.druid.math.expr.InputBindings;
@ -33,7 +32,6 @@ public class IPv4AddressParseExprMacroTest extends MacroTestBase
{ {
private static final Expr VALID = ExprEval.of("192.168.0.1").toExpr(); private static final Expr VALID = ExprEval.of("192.168.0.1").toExpr();
private static final long EXPECTED = 3232235521L; private static final long EXPECTED = 3232235521L;
private static final Long NULL = NullHandling.replaceWithDefault() ? NullHandling.ZERO_LONG : null;
public IPv4AddressParseExprMacroTest() public IPv4AddressParseExprMacroTest()
{ {
@ -57,45 +55,45 @@ public class IPv4AddressParseExprMacroTest extends MacroTestBase
} }
@Test @Test
public void testNullStringArg() public void testnullStringArg()
{ {
Expr nullString = ExprEval.of(null).toExpr(); Expr nullString = ExprEval.of(null).toExpr();
Assert.assertSame(NULL, eval(nullString)); Assert.assertNull(eval(nullString));
} }
@Test @Test
public void testNullLongArg() public void testnullLongArg()
{ {
Expr nullLong = ExprEval.ofLong(null).toExpr(); Expr nullLong = ExprEval.ofLong(null).toExpr();
Assert.assertEquals(NULL, eval(nullLong)); Assert.assertNull(eval(nullLong));
} }
@Test @Test
public void testInvalidArgType() public void testInvalidArgType()
{ {
Expr longArray = ExprEval.ofLongArray(new Long[]{1L, 2L}).toExpr(); Expr longArray = ExprEval.ofLongArray(new Long[]{1L, 2L}).toExpr();
Assert.assertEquals(NULL, eval(longArray)); Assert.assertNull(eval(longArray));
} }
@Test @Test
public void testInvalidStringArgNotIPAddress() public void testInvalidStringArgNotIPAddress()
{ {
Expr notIpAddress = ExprEval.of("druid.apache.org").toExpr(); Expr notIpAddress = ExprEval.of("druid.apache.org").toExpr();
Assert.assertEquals(NULL, eval(notIpAddress)); Assert.assertNull(eval(notIpAddress));
} }
@Test @Test
public void testInvalidStringArgIPv6Compatible() public void testInvalidStringArgIPv6Compatible()
{ {
Expr ipv6Compatible = ExprEval.of("::192.168.0.1").toExpr(); Expr ipv6Compatible = ExprEval.of("::192.168.0.1").toExpr();
Assert.assertEquals(NULL, eval(ipv6Compatible)); Assert.assertNull(eval(ipv6Compatible));
} }
@Test @Test
public void testValidStringArgIPv6Mapped() public void testValidStringArgIPv6Mapped()
{ {
Expr ipv6Mapped = ExprEval.of("::ffff:192.168.0.1").toExpr(); Expr ipv6Mapped = ExprEval.of("::ffff:192.168.0.1").toExpr();
Assert.assertEquals(NULL, eval(ipv6Mapped)); Assert.assertNull(eval(ipv6Mapped));
} }
@Test @Test
@ -108,14 +106,14 @@ public class IPv4AddressParseExprMacroTest extends MacroTestBase
public void testValidStringArgUnsignedInt() public void testValidStringArgUnsignedInt()
{ {
Expr unsignedInt = ExprEval.of("3232235521").toExpr(); Expr unsignedInt = ExprEval.of("3232235521").toExpr();
Assert.assertEquals(NULL, eval(unsignedInt)); Assert.assertNull(eval(unsignedInt));
} }
@Test @Test
public void testInvalidLongArgTooLow() public void testInvalidLongArgTooLow()
{ {
Expr tooLow = ExprEval.ofLong(-1L).toExpr(); Expr tooLow = ExprEval.ofLong(-1L).toExpr();
Assert.assertEquals(NULL, eval(tooLow)); Assert.assertNull(eval(tooLow));
} }
@Test @Test
@ -138,7 +136,7 @@ public class IPv4AddressParseExprMacroTest extends MacroTestBase
public void testInvalidLongArgTooHigh() public void testInvalidLongArgTooHigh()
{ {
Expr tooHigh = ExprEval.ofLong(0x1_00_00_00_00L).toExpr(); Expr tooHigh = ExprEval.ofLong(0x1_00_00_00_00L).toExpr();
Assert.assertEquals(NULL, eval(tooHigh)); Assert.assertNull(eval(tooHigh));
} }
@Test @Test

View File

@ -24,7 +24,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.jackson.DefaultObjectMapper;
import org.apache.druid.java.util.common.Pair; import org.apache.druid.java.util.common.Pair;
import org.apache.druid.math.expr.Expr; import org.apache.druid.math.expr.Expr;
@ -173,7 +172,7 @@ public class NestedDataExpressionsTest extends InitializedNullHandlingTest
expr = Parser.parse("json_value(nester, '$.y.a', 'LONG')", MACRO_TABLE); expr = Parser.parse("json_value(nester, '$.y.a', 'LONG')", MACRO_TABLE);
eval = expr.eval(inputBindings); eval = expr.eval(inputBindings);
Assert.assertEquals(NullHandling.defaultLongValue(), eval.value()); Assert.assertNull(eval.value());
Assert.assertEquals(ExpressionType.LONG, eval.type()); Assert.assertEquals(ExpressionType.LONG, eval.type());
expr = Parser.parse("json_value(nester, '$.y.a.b.c[12]')", MACRO_TABLE); expr = Parser.parse("json_value(nester, '$.y.a.b.c[12]')", MACRO_TABLE);

View File

@ -191,7 +191,7 @@ public class DruidRexExecutor implements RexExecutor
// column selector anyway // column selector anyway
literal = constExp; literal = constExp;
} else { } else {
literal = rexBuilder.makeLiteral(exprResult.value(), constExp.getType(), true); literal = rexBuilder.makeLiteral(exprResult.valueOrDefault(), constExp.getType(), true);
} }
} }

View File

@ -118,7 +118,7 @@ public class DruidUnnestDatasourceRel extends DruidRel<DruidUnnestDatasourceRel>
// with the input column being called "inline" in the native query // with the input column being called "inline" in the native query
UnnestDataSource dataSource = UnnestDataSource.create( UnnestDataSource dataSource = UnnestDataSource.create(
InlineDataSource.fromIterable( InlineDataSource.fromIterable(
Collections.singletonList(new Object[]{eval.value()}), Collections.singletonList(new Object[]{eval.valueOrDefault()}),
RowSignature.builder().add("inline", ExpressionType.toColumnType(eval.type())).build() RowSignature.builder().add("inline", ExpressionType.toColumnType(eval.type())).build()
), ),
"inline", "inline",

View File

@ -707,7 +707,7 @@ public class ExpressionsTest extends ExpressionTestBase
DruidExpression.ofColumn(ColumnType.STRING, "hexstr") DruidExpression.ofColumn(ColumnType.STRING, "hexstr")
) )
), ),
NullHandling.sqlCompatible() ? null : 0L null
); );
} }

View File

@ -21,7 +21,6 @@ package org.apache.druid.sql.calcite.expression;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexNode;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.math.expr.ExpressionValidationException; import org.apache.druid.math.expr.ExpressionValidationException;
import org.apache.druid.segment.column.ColumnType; import org.apache.druid.segment.column.ColumnType;
import org.apache.druid.segment.column.RowSignature; import org.apache.druid.segment.column.RowSignature;
@ -39,7 +38,6 @@ public class IPv4AddressParseExpressionTest extends ExpressionTestBase
private static final String VALID = "192.168.0.1"; private static final String VALID = "192.168.0.1";
private static final long EXPECTED = 3232235521L; private static final long EXPECTED = 3232235521L;
private static final Object IGNORE_EXPECTED_RESULT = null; private static final Object IGNORE_EXPECTED_RESULT = null;
private static final Long NULL = NullHandling.replaceWithDefault() ? NullHandling.ZERO_LONG : null;
private static final String VAR = "f"; private static final String VAR = "f";
private static final RowSignature ROW_SIGNATURE = RowSignature.builder().add(VAR, ColumnType.FLOAT).build(); private static final RowSignature ROW_SIGNATURE = RowSignature.builder().add(VAR, ColumnType.FLOAT).build();
@ -88,7 +86,7 @@ public class IPv4AddressParseExpressionTest extends ExpressionTestBase
testExpression( testExpression(
testHelper.getConstantNull(), testHelper.getConstantNull(),
buildExpectedExpression((String) null), buildExpectedExpression((String) null),
NULL null
); );
} }
@ -99,7 +97,7 @@ public class IPv4AddressParseExpressionTest extends ExpressionTestBase
testExpression( testExpression(
testHelper.makeInputRef(variableNameWithInvalidType), testHelper.makeInputRef(variableNameWithInvalidType),
buildExpectedExpression(testHelper.makeVariable(variableNameWithInvalidType)), buildExpectedExpression(testHelper.makeVariable(variableNameWithInvalidType)),
NULL null
); );
} }
@ -110,7 +108,7 @@ public class IPv4AddressParseExpressionTest extends ExpressionTestBase
testExpression( testExpression(
testHelper.makeLiteral(notIpAddress), testHelper.makeLiteral(notIpAddress),
buildExpectedExpression(notIpAddress), buildExpectedExpression(notIpAddress),
NULL null
); );
} }
@ -121,7 +119,7 @@ public class IPv4AddressParseExpressionTest extends ExpressionTestBase
testExpression( testExpression(
testHelper.makeLiteral(ipv6Compatible), testHelper.makeLiteral(ipv6Compatible),
buildExpectedExpression(ipv6Compatible), buildExpectedExpression(ipv6Compatible),
NULL null
); );
} }
@ -132,7 +130,7 @@ public class IPv4AddressParseExpressionTest extends ExpressionTestBase
testExpression( testExpression(
testHelper.makeLiteral(ipv6Mapped), testHelper.makeLiteral(ipv6Mapped),
buildExpectedExpression(ipv6Mapped), buildExpectedExpression(ipv6Mapped),
NULL null
); );
} }
@ -153,7 +151,7 @@ public class IPv4AddressParseExpressionTest extends ExpressionTestBase
testExpression( testExpression(
testHelper.makeLiteral(unsignedInt), testHelper.makeLiteral(unsignedInt),
buildExpectedExpression(unsignedInt), buildExpectedExpression(unsignedInt),
NULL null
); );
} }
@ -164,7 +162,7 @@ public class IPv4AddressParseExpressionTest extends ExpressionTestBase
testExpression( testExpression(
testHelper.makeLiteral(tooLow), testHelper.makeLiteral(tooLow),
buildExpectedExpression(tooLow), buildExpectedExpression(tooLow),
NULL null
); );
} }
@ -207,7 +205,7 @@ public class IPv4AddressParseExpressionTest extends ExpressionTestBase
testExpression( testExpression(
testHelper.makeLiteral(tooHigh), testHelper.makeLiteral(tooHigh),
buildExpectedExpression(tooHigh), buildExpectedExpression(tooHigh),
NULL null
); );
} }