mirror of https://github.com/apache/druid.git
fix json_value sql planning with decimal type, fix vectorized expression math null value handling in default mode (#13214)
* fix json_value sql planning with decimal type, fix vectorized expression math null value handling in default mode changes: * json_value 'returning' decimal will now plan to native double typed query instead of ending up with default string typing, allowing decimal vector math expressions to work with this type * vector math expressions now zero out 'null' values even in 'default' mode (druid.generic.useDefaultValueForNull=false) to prevent downstream things that do not check the null vector from producing incorrect results * more better * test and why not vectorize * more test, more fix
This commit is contained in:
parent
3e13584e0e
commit
6eff6c9ae4
|
@ -112,7 +112,7 @@ final class BinMinusExpr extends BinaryEvalOpExprBase
|
||||||
@Override
|
@Override
|
||||||
public boolean canVectorize(InputBindingInspector inspector)
|
public boolean canVectorize(InputBindingInspector inspector)
|
||||||
{
|
{
|
||||||
return inspector.areNumeric(left, right) && inspector.canVectorize(left, right);
|
return inspector.areScalar(left, right) && inspector.canVectorize(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -151,7 +151,7 @@ final class BinMulExpr extends BinaryEvalOpExprBase
|
||||||
@Override
|
@Override
|
||||||
public boolean canVectorize(InputBindingInspector inspector)
|
public boolean canVectorize(InputBindingInspector inspector)
|
||||||
{
|
{
|
||||||
return inspector.areNumeric(left, right) && inspector.canVectorize(left, right);
|
return inspector.areScalar(left, right) && inspector.canVectorize(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -190,7 +190,7 @@ final class BinDivExpr extends BinaryEvalOpExprBase
|
||||||
@Override
|
@Override
|
||||||
public boolean canVectorize(InputBindingInspector inspector)
|
public boolean canVectorize(InputBindingInspector inspector)
|
||||||
{
|
{
|
||||||
return inspector.areNumeric(left, right) && inspector.canVectorize(left, right);
|
return inspector.areScalar(left, right) && inspector.canVectorize(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -229,7 +229,7 @@ class BinPowExpr extends BinaryEvalOpExprBase
|
||||||
@Override
|
@Override
|
||||||
public boolean canVectorize(InputBindingInspector inspector)
|
public boolean canVectorize(InputBindingInspector inspector)
|
||||||
{
|
{
|
||||||
return inspector.areNumeric(left, right) && inspector.canVectorize(left, right);
|
return inspector.areScalar(left, right) && inspector.canVectorize(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -268,7 +268,7 @@ class BinModuloExpr extends BinaryEvalOpExprBase
|
||||||
@Override
|
@Override
|
||||||
public boolean canVectorize(InputBindingInspector inspector)
|
public boolean canVectorize(InputBindingInspector inspector)
|
||||||
{
|
{
|
||||||
return inspector.areNumeric(left, right) && inspector.canVectorize(left, right);
|
return inspector.areScalar(left, right) && inspector.canVectorize(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.druid.math.expr.vector;
|
||||||
|
|
||||||
|
import org.apache.druid.math.expr.Expr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* common machinery for processing two input operators and functions, which should always treat null inputs as null
|
||||||
|
* output, and are backed by a primitive values instead of an object values (and need to use the null vectors instead of
|
||||||
|
* checking the vector themselves for nulls)
|
||||||
|
*
|
||||||
|
* this one is specialized for producing double[], see {@link BivariateLongFunctionVectorValueProcessor} for
|
||||||
|
* long[] primitives.
|
||||||
|
*/
|
||||||
|
public abstract class BivariateDoubleFunctionVectorValueProcessor<TLeftInput, TRightInput>
|
||||||
|
implements ExprVectorProcessor<double[]>
|
||||||
|
{
|
||||||
|
final ExprVectorProcessor<TLeftInput> left;
|
||||||
|
final ExprVectorProcessor<TRightInput> right;
|
||||||
|
final int maxVectorSize;
|
||||||
|
final boolean[] outNulls;
|
||||||
|
final double[] outValues;
|
||||||
|
|
||||||
|
protected BivariateDoubleFunctionVectorValueProcessor(
|
||||||
|
ExprVectorProcessor<TLeftInput> left,
|
||||||
|
ExprVectorProcessor<TRightInput> right,
|
||||||
|
int maxVectorSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
this.maxVectorSize = maxVectorSize;
|
||||||
|
this.outValues = new double[maxVectorSize];
|
||||||
|
this.outNulls = new boolean[maxVectorSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ExprEvalVector<double[]> evalVector(Expr.VectorInputBinding bindings)
|
||||||
|
{
|
||||||
|
final ExprEvalVector<TLeftInput> lhs = left.evalVector(bindings);
|
||||||
|
final ExprEvalVector<TRightInput> rhs = right.evalVector(bindings);
|
||||||
|
|
||||||
|
final int currentSize = bindings.getCurrentVectorSize();
|
||||||
|
final boolean[] leftNulls = lhs.getNullVector();
|
||||||
|
final boolean[] rightNulls = rhs.getNullVector();
|
||||||
|
final boolean hasLeftNulls = leftNulls != null;
|
||||||
|
final boolean hasRightNulls = rightNulls != null;
|
||||||
|
final boolean hasNulls = hasLeftNulls || hasRightNulls;
|
||||||
|
|
||||||
|
final TLeftInput leftInput = lhs.values();
|
||||||
|
final TRightInput rightInput = rhs.values();
|
||||||
|
|
||||||
|
if (hasNulls) {
|
||||||
|
for (int i = 0; i < currentSize; i++) {
|
||||||
|
outNulls[i] = (hasLeftNulls && leftNulls[i]) || (hasRightNulls && rightNulls[i]);
|
||||||
|
if (!outNulls[i]) {
|
||||||
|
processIndex(leftInput, rightInput, i);
|
||||||
|
} else {
|
||||||
|
outValues[i] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < currentSize; i++) {
|
||||||
|
processIndex(leftInput, rightInput, i);
|
||||||
|
outNulls[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return asEval();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void processIndex(TLeftInput leftInput, TRightInput rightInput, int i);
|
||||||
|
|
||||||
|
final ExprEvalVector<double[]> asEval()
|
||||||
|
{
|
||||||
|
return new ExprEvalDoubleVector(outValues, outNulls);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,8 +26,9 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic vector processor that processes 2 inputs and works for both primitive value vectors and object vectors.
|
* Basic vector processor that processes 2 inputs and works for both primitive value vectors and object vectors.
|
||||||
* Different from {@link BivariateFunctionVectorValueProcessor} and {@link BivariateFunctionVectorObjectProcessor} in
|
* Different from {@link BivariateLongFunctionVectorValueProcessor}, {@link BivariateDoubleFunctionVectorValueProcessor}
|
||||||
* that subclasses of this class must check for and directly decide how to handle null values.
|
* and {@link BivariateFunctionVectorObjectProcessor} in that subclasses of this class must check for and directly
|
||||||
|
* decide how to handle null values.
|
||||||
*/
|
*/
|
||||||
public abstract class BivariateFunctionVectorProcessor<TLeftInput, TRightInput, TOutput>
|
public abstract class BivariateFunctionVectorProcessor<TLeftInput, TRightInput, TOutput>
|
||||||
implements ExprVectorProcessor<TOutput>
|
implements ExprVectorProcessor<TOutput>
|
||||||
|
|
|
@ -25,32 +25,34 @@ import org.apache.druid.math.expr.Expr;
|
||||||
* common machinery for processing two input operators and functions, which should always treat null inputs as null
|
* common machinery for processing two input operators and functions, which should always treat null inputs as null
|
||||||
* output, and are backed by a primitive values instead of an object values (and need to use the null vectors instead of
|
* output, and are backed by a primitive values instead of an object values (and need to use the null vectors instead of
|
||||||
* checking the vector themselves for nulls)
|
* checking the vector themselves for nulls)
|
||||||
|
*
|
||||||
|
* this one is specialized for producing long[], see {@link BivariateDoubleFunctionVectorValueProcessor} for
|
||||||
|
* double[] primitives.
|
||||||
*/
|
*/
|
||||||
public abstract class BivariateFunctionVectorValueProcessor<TLeftInput, TRightInput, TOutput>
|
public abstract class BivariateLongFunctionVectorValueProcessor<TLeftInput, TRightInput>
|
||||||
implements ExprVectorProcessor<TOutput>
|
implements ExprVectorProcessor<long[]>
|
||||||
{
|
{
|
||||||
final ExprVectorProcessor<TLeftInput> left;
|
final ExprVectorProcessor<TLeftInput> left;
|
||||||
final ExprVectorProcessor<TRightInput> right;
|
final ExprVectorProcessor<TRightInput> right;
|
||||||
final int maxVectorSize;
|
final int maxVectorSize;
|
||||||
final boolean[] outNulls;
|
final boolean[] outNulls;
|
||||||
final TOutput outValues;
|
final long[] outValues;
|
||||||
|
|
||||||
protected BivariateFunctionVectorValueProcessor(
|
protected BivariateLongFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<TLeftInput> left,
|
ExprVectorProcessor<TLeftInput> left,
|
||||||
ExprVectorProcessor<TRightInput> right,
|
ExprVectorProcessor<TRightInput> right,
|
||||||
int maxVectorSize,
|
int maxVectorSize
|
||||||
TOutput outValues
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.left = left;
|
this.left = left;
|
||||||
this.right = right;
|
this.right = right;
|
||||||
this.maxVectorSize = maxVectorSize;
|
this.maxVectorSize = maxVectorSize;
|
||||||
|
this.outValues = new long[maxVectorSize];
|
||||||
this.outNulls = new boolean[maxVectorSize];
|
this.outNulls = new boolean[maxVectorSize];
|
||||||
this.outValues = outValues;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final ExprEvalVector<TOutput> evalVector(Expr.VectorInputBinding bindings)
|
public final ExprEvalVector<long[]> evalVector(Expr.VectorInputBinding bindings)
|
||||||
{
|
{
|
||||||
final ExprEvalVector<TLeftInput> lhs = left.evalVector(bindings);
|
final ExprEvalVector<TLeftInput> lhs = left.evalVector(bindings);
|
||||||
final ExprEvalVector<TRightInput> rhs = right.evalVector(bindings);
|
final ExprEvalVector<TRightInput> rhs = right.evalVector(bindings);
|
||||||
|
@ -70,6 +72,8 @@ public abstract class BivariateFunctionVectorValueProcessor<TLeftInput, TRightIn
|
||||||
outNulls[i] = (hasLeftNulls && leftNulls[i]) || (hasRightNulls && rightNulls[i]);
|
outNulls[i] = (hasLeftNulls && leftNulls[i]) || (hasRightNulls && rightNulls[i]);
|
||||||
if (!outNulls[i]) {
|
if (!outNulls[i]) {
|
||||||
processIndex(leftInput, rightInput, i);
|
processIndex(leftInput, rightInput, i);
|
||||||
|
} else {
|
||||||
|
outValues[i] = 0L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,5 +87,8 @@ public abstract class BivariateFunctionVectorValueProcessor<TLeftInput, TRightIn
|
||||||
|
|
||||||
abstract void processIndex(TLeftInput leftInput, TRightInput rightInput, int i);
|
abstract void processIndex(TLeftInput leftInput, TRightInput rightInput, int i);
|
||||||
|
|
||||||
abstract ExprEvalVector<TOutput> asEval();
|
final ExprEvalVector<long[]> asEval()
|
||||||
|
{
|
||||||
|
return new ExprEvalLongVector(outValues, outNulls);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -22,14 +22,14 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link UnivariateFunctionVectorValueProcessor} for processing (double[]) -> double[]
|
* specialized {@link UnivariateDoubleFunctionVectorValueProcessor} for processing (double[]) -> double[]
|
||||||
*/
|
*/
|
||||||
public abstract class DoubleOutDoubleInFunctionVectorValueProcessor
|
public abstract class DoubleOutDoubleInFunctionVectorValueProcessor
|
||||||
extends UnivariateFunctionVectorValueProcessor<double[], double[]>
|
extends UnivariateDoubleFunctionVectorValueProcessor<double[]>
|
||||||
{
|
{
|
||||||
public DoubleOutDoubleInFunctionVectorValueProcessor(ExprVectorProcessor<double[]> processor, int maxVectorSize)
|
public DoubleOutDoubleInFunctionVectorValueProcessor(ExprVectorProcessor<double[]> processor, int maxVectorSize)
|
||||||
{
|
{
|
||||||
super(CastToTypeVectorProcessor.cast(processor, ExpressionType.DOUBLE), maxVectorSize, new double[maxVectorSize]);
|
super(CastToTypeVectorProcessor.cast(processor, ExpressionType.DOUBLE), maxVectorSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract double apply(double input);
|
public abstract double apply(double input);
|
||||||
|
@ -45,10 +45,4 @@ public abstract class DoubleOutDoubleInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(input[i]);
|
outValues[i] = apply(input[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<double[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalDoubleVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,10 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link BivariateFunctionVectorValueProcessor} for processing (double[], long[]) -> double[]
|
* specialized {@link BivariateDoubleFunctionVectorValueProcessor} for processing (double[], long[]) -> double[]
|
||||||
*/
|
*/
|
||||||
public abstract class DoubleOutDoubleLongInFunctionVectorValueProcessor
|
public abstract class DoubleOutDoubleLongInFunctionVectorValueProcessor
|
||||||
extends BivariateFunctionVectorValueProcessor<double[], long[], double[]>
|
extends BivariateDoubleFunctionVectorValueProcessor<double[], long[]>
|
||||||
{
|
{
|
||||||
public DoubleOutDoubleLongInFunctionVectorValueProcessor(
|
public DoubleOutDoubleLongInFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<double[]> left,
|
ExprVectorProcessor<double[]> left,
|
||||||
|
@ -36,8 +36,7 @@ public abstract class DoubleOutDoubleLongInFunctionVectorValueProcessor
|
||||||
super(
|
super(
|
||||||
CastToTypeVectorProcessor.cast(left, ExpressionType.DOUBLE),
|
CastToTypeVectorProcessor.cast(left, ExpressionType.DOUBLE),
|
||||||
CastToTypeVectorProcessor.cast(right, ExpressionType.LONG),
|
CastToTypeVectorProcessor.cast(right, ExpressionType.LONG),
|
||||||
maxVectorSize,
|
maxVectorSize
|
||||||
new double[maxVectorSize]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +53,4 @@ public abstract class DoubleOutDoubleLongInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(leftInput[i], rightInput[i]);
|
outValues[i] = apply(leftInput[i], rightInput[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<double[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalDoubleVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,10 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link BivariateFunctionVectorValueProcessor} for processing (double[], double[]) -> double[]
|
* specialized {@link BivariateDoubleFunctionVectorValueProcessor} for processing (double[], double[]) -> double[]
|
||||||
*/
|
*/
|
||||||
public abstract class DoubleOutDoublesInFunctionVectorValueProcessor
|
public abstract class DoubleOutDoublesInFunctionVectorValueProcessor
|
||||||
extends BivariateFunctionVectorValueProcessor<double[], double[], double[]>
|
extends BivariateDoubleFunctionVectorValueProcessor<double[], double[]>
|
||||||
{
|
{
|
||||||
public DoubleOutDoublesInFunctionVectorValueProcessor(
|
public DoubleOutDoublesInFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<double[]> left,
|
ExprVectorProcessor<double[]> left,
|
||||||
|
@ -36,8 +36,7 @@ public abstract class DoubleOutDoublesInFunctionVectorValueProcessor
|
||||||
super(
|
super(
|
||||||
CastToTypeVectorProcessor.cast(left, ExpressionType.DOUBLE),
|
CastToTypeVectorProcessor.cast(left, ExpressionType.DOUBLE),
|
||||||
CastToTypeVectorProcessor.cast(right, ExpressionType.DOUBLE),
|
CastToTypeVectorProcessor.cast(right, ExpressionType.DOUBLE),
|
||||||
maxVectorSize,
|
maxVectorSize
|
||||||
new double[maxVectorSize]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +53,4 @@ public abstract class DoubleOutDoublesInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(leftInput[i], rightInput[i]);
|
outValues[i] = apply(leftInput[i], rightInput[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<double[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalDoubleVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,10 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link BivariateFunctionVectorValueProcessor} for processing (long[], double[]) -> double[]
|
* specialized {@link BivariateDoubleFunctionVectorValueProcessor} for processing (long[], double[]) -> double[]
|
||||||
*/
|
*/
|
||||||
public abstract class DoubleOutLongDoubleInFunctionVectorValueProcessor
|
public abstract class DoubleOutLongDoubleInFunctionVectorValueProcessor
|
||||||
extends BivariateFunctionVectorValueProcessor<long[], double[], double[]>
|
extends BivariateDoubleFunctionVectorValueProcessor<long[], double[]>
|
||||||
{
|
{
|
||||||
public DoubleOutLongDoubleInFunctionVectorValueProcessor(
|
public DoubleOutLongDoubleInFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<long[]> left,
|
ExprVectorProcessor<long[]> left,
|
||||||
|
@ -36,8 +36,7 @@ public abstract class DoubleOutLongDoubleInFunctionVectorValueProcessor
|
||||||
super(
|
super(
|
||||||
CastToTypeVectorProcessor.cast(left, ExpressionType.LONG),
|
CastToTypeVectorProcessor.cast(left, ExpressionType.LONG),
|
||||||
CastToTypeVectorProcessor.cast(right, ExpressionType.DOUBLE),
|
CastToTypeVectorProcessor.cast(right, ExpressionType.DOUBLE),
|
||||||
maxVectorSize,
|
maxVectorSize
|
||||||
new double[maxVectorSize]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +53,4 @@ public abstract class DoubleOutLongDoubleInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(leftInput[i], rightInput[i]);
|
outValues[i] = apply(leftInput[i], rightInput[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<double[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalDoubleVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,14 +22,14 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link UnivariateFunctionVectorValueProcessor} for processing (long[]) -> double[]
|
* specialized {@link UnivariateDoubleFunctionVectorValueProcessor} for processing (long[]) -> double[]
|
||||||
*/
|
*/
|
||||||
public abstract class DoubleOutLongInFunctionVectorValueProcessor
|
public abstract class DoubleOutLongInFunctionVectorValueProcessor
|
||||||
extends UnivariateFunctionVectorValueProcessor<long[], double[]>
|
extends UnivariateDoubleFunctionVectorValueProcessor<long[]>
|
||||||
{
|
{
|
||||||
public DoubleOutLongInFunctionVectorValueProcessor(ExprVectorProcessor<long[]> processor, int maxVectorSize)
|
public DoubleOutLongInFunctionVectorValueProcessor(ExprVectorProcessor<long[]> processor, int maxVectorSize)
|
||||||
{
|
{
|
||||||
super(CastToTypeVectorProcessor.cast(processor, ExpressionType.LONG), maxVectorSize, new double[maxVectorSize]);
|
super(CastToTypeVectorProcessor.cast(processor, ExpressionType.LONG), maxVectorSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract double apply(long input);
|
public abstract double apply(long input);
|
||||||
|
@ -45,10 +45,4 @@ public abstract class DoubleOutLongInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(input[i]);
|
outValues[i] = apply(input[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<double[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalDoubleVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,10 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link BivariateFunctionVectorValueProcessor} for processing (long[], long[]) -> double[]
|
* specialized {@link BivariateDoubleFunctionVectorValueProcessor} for processing (long[], long[]) -> double[]
|
||||||
*/
|
*/
|
||||||
public abstract class DoubleOutLongsInFunctionVectorValueProcessor
|
public abstract class DoubleOutLongsInFunctionVectorValueProcessor
|
||||||
extends BivariateFunctionVectorValueProcessor<long[], long[], double[]>
|
extends BivariateDoubleFunctionVectorValueProcessor<long[], long[]>
|
||||||
{
|
{
|
||||||
public DoubleOutLongsInFunctionVectorValueProcessor(
|
public DoubleOutLongsInFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<long[]> left,
|
ExprVectorProcessor<long[]> left,
|
||||||
|
@ -36,8 +36,7 @@ public abstract class DoubleOutLongsInFunctionVectorValueProcessor
|
||||||
super(
|
super(
|
||||||
CastToTypeVectorProcessor.cast(left, ExpressionType.LONG),
|
CastToTypeVectorProcessor.cast(left, ExpressionType.LONG),
|
||||||
CastToTypeVectorProcessor.cast(right, ExpressionType.LONG),
|
CastToTypeVectorProcessor.cast(right, ExpressionType.LONG),
|
||||||
maxVectorSize,
|
maxVectorSize
|
||||||
new double[maxVectorSize]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +53,4 @@ public abstract class DoubleOutLongsInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(leftInput[i], rightInput[i]);
|
outValues[i] = apply(leftInput[i], rightInput[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<double[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalDoubleVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,14 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link UnivariateFunctionVectorValueProcessor} for processing (long[]) -> long[]
|
* specialized {@link UnivariateLongFunctionVectorValueProcessor} for processing (long[]) -> long[]
|
||||||
*/
|
*/
|
||||||
public abstract class LongOutDoubleInFunctionVectorValueProcessor extends UnivariateFunctionVectorValueProcessor<double[], long[]>
|
public abstract class LongOutDoubleInFunctionVectorValueProcessor
|
||||||
|
extends UnivariateLongFunctionVectorValueProcessor<double[]>
|
||||||
{
|
{
|
||||||
public LongOutDoubleInFunctionVectorValueProcessor(ExprVectorProcessor<double[]> processor, int maxVectorSize)
|
public LongOutDoubleInFunctionVectorValueProcessor(ExprVectorProcessor<double[]> processor, int maxVectorSize)
|
||||||
{
|
{
|
||||||
super(CastToTypeVectorProcessor.cast(processor, ExpressionType.DOUBLE), maxVectorSize, new long[maxVectorSize]);
|
super(CastToTypeVectorProcessor.cast(processor, ExpressionType.DOUBLE), maxVectorSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract long apply(double input);
|
public abstract long apply(double input);
|
||||||
|
@ -44,10 +45,4 @@ public abstract class LongOutDoubleInFunctionVectorValueProcessor extends Univar
|
||||||
{
|
{
|
||||||
outValues[i] = apply(input[i]);
|
outValues[i] = apply(input[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<long[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalLongVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,10 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link BivariateFunctionVectorValueProcessor} for processing (double[], long[]) -> long[]
|
* specialized {@link BivariateLongFunctionVectorValueProcessor} for processing (double[], long[]) -> long[]
|
||||||
*/
|
*/
|
||||||
public abstract class LongOutDoubleLongInFunctionVectorValueProcessor
|
public abstract class LongOutDoubleLongInFunctionVectorValueProcessor
|
||||||
extends BivariateFunctionVectorValueProcessor<double[], long[], long[]>
|
extends BivariateLongFunctionVectorValueProcessor<double[], long[]>
|
||||||
{
|
{
|
||||||
public LongOutDoubleLongInFunctionVectorValueProcessor(
|
public LongOutDoubleLongInFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<double[]> left,
|
ExprVectorProcessor<double[]> left,
|
||||||
|
@ -36,8 +36,7 @@ public abstract class LongOutDoubleLongInFunctionVectorValueProcessor
|
||||||
super(
|
super(
|
||||||
CastToTypeVectorProcessor.cast(left, ExpressionType.DOUBLE),
|
CastToTypeVectorProcessor.cast(left, ExpressionType.DOUBLE),
|
||||||
CastToTypeVectorProcessor.cast(right, ExpressionType.LONG),
|
CastToTypeVectorProcessor.cast(right, ExpressionType.LONG),
|
||||||
maxVectorSize,
|
maxVectorSize
|
||||||
new long[maxVectorSize]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +53,4 @@ public abstract class LongOutDoubleLongInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(leftInput[i], rightInput[i]);
|
outValues[i] = apply(leftInput[i], rightInput[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<long[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalLongVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,10 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link BivariateFunctionVectorValueProcessor} for processing (double[], double[]) -> long[]
|
* specialized {@link BivariateLongFunctionVectorValueProcessor} for processing (double[], double[]) -> long[]
|
||||||
*/
|
*/
|
||||||
public abstract class LongOutDoublesInFunctionVectorValueProcessor
|
public abstract class LongOutDoublesInFunctionVectorValueProcessor
|
||||||
extends BivariateFunctionVectorValueProcessor<double[], double[], long[]>
|
extends BivariateLongFunctionVectorValueProcessor<double[], double[]>
|
||||||
{
|
{
|
||||||
public LongOutDoublesInFunctionVectorValueProcessor(
|
public LongOutDoublesInFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<double[]> left,
|
ExprVectorProcessor<double[]> left,
|
||||||
|
@ -36,8 +36,7 @@ public abstract class LongOutDoublesInFunctionVectorValueProcessor
|
||||||
super(
|
super(
|
||||||
CastToTypeVectorProcessor.cast(left, ExpressionType.DOUBLE),
|
CastToTypeVectorProcessor.cast(left, ExpressionType.DOUBLE),
|
||||||
CastToTypeVectorProcessor.cast(right, ExpressionType.DOUBLE),
|
CastToTypeVectorProcessor.cast(right, ExpressionType.DOUBLE),
|
||||||
maxVectorSize,
|
maxVectorSize
|
||||||
new long[maxVectorSize]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +53,4 @@ public abstract class LongOutDoublesInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(leftInput[i], rightInput[i]);
|
outValues[i] = apply(leftInput[i], rightInput[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<long[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalLongVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,10 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link BivariateFunctionVectorValueProcessor} for processing (long[], double[]) -> long[]
|
* specialized {@link BivariateLongFunctionVectorValueProcessor} for processing (long[], double[]) -> long[]
|
||||||
*/
|
*/
|
||||||
public abstract class LongOutLongDoubleInFunctionVectorValueProcessor
|
public abstract class LongOutLongDoubleInFunctionVectorValueProcessor
|
||||||
extends BivariateFunctionVectorValueProcessor<long[], double[], long[]>
|
extends BivariateLongFunctionVectorValueProcessor<long[], double[]>
|
||||||
{
|
{
|
||||||
public LongOutLongDoubleInFunctionVectorValueProcessor(
|
public LongOutLongDoubleInFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<long[]> left,
|
ExprVectorProcessor<long[]> left,
|
||||||
|
@ -36,8 +36,7 @@ public abstract class LongOutLongDoubleInFunctionVectorValueProcessor
|
||||||
super(
|
super(
|
||||||
CastToTypeVectorProcessor.cast(left, ExpressionType.LONG),
|
CastToTypeVectorProcessor.cast(left, ExpressionType.LONG),
|
||||||
CastToTypeVectorProcessor.cast(right, ExpressionType.DOUBLE),
|
CastToTypeVectorProcessor.cast(right, ExpressionType.DOUBLE),
|
||||||
maxVectorSize,
|
maxVectorSize
|
||||||
new long[maxVectorSize]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +53,4 @@ public abstract class LongOutLongDoubleInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(leftInput[i], rightInput[i]);
|
outValues[i] = apply(leftInput[i], rightInput[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<long[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalLongVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,14 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link UnivariateFunctionVectorValueProcessor} for processing (long[]) -> long[]
|
* specialized {@link UnivariateLongFunctionVectorValueProcessor} for processing (long[]) -> long[]
|
||||||
*/
|
*/
|
||||||
public abstract class LongOutLongInFunctionVectorValueProcessor extends UnivariateFunctionVectorValueProcessor<long[], long[]>
|
public abstract class LongOutLongInFunctionVectorValueProcessor
|
||||||
|
extends UnivariateLongFunctionVectorValueProcessor<long[]>
|
||||||
{
|
{
|
||||||
public LongOutLongInFunctionVectorValueProcessor(ExprVectorProcessor<long[]> processor, int maxVectorSize)
|
public LongOutLongInFunctionVectorValueProcessor(ExprVectorProcessor<long[]> processor, int maxVectorSize)
|
||||||
{
|
{
|
||||||
super(CastToTypeVectorProcessor.cast(processor, ExpressionType.LONG), maxVectorSize, new long[maxVectorSize]);
|
super(CastToTypeVectorProcessor.cast(processor, ExpressionType.LONG), maxVectorSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract long apply(long input);
|
public abstract long apply(long input);
|
||||||
|
@ -44,10 +45,4 @@ public abstract class LongOutLongInFunctionVectorValueProcessor extends Univaria
|
||||||
{
|
{
|
||||||
outValues[i] = apply(input[i]);
|
outValues[i] = apply(input[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<long[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalLongVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,10 @@ package org.apache.druid.math.expr.vector;
|
||||||
import org.apache.druid.math.expr.ExpressionType;
|
import org.apache.druid.math.expr.ExpressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specialized {@link BivariateFunctionVectorValueProcessor} for processing (long[], long[]) -> long[]
|
* specialized {@link BivariateLongFunctionVectorValueProcessor} for processing (long[], long[]) -> long[]
|
||||||
*/
|
*/
|
||||||
public abstract class LongOutLongsInFunctionVectorValueProcessor
|
public abstract class LongOutLongsInFunctionVectorValueProcessor
|
||||||
extends BivariateFunctionVectorValueProcessor<long[], long[], long[]>
|
extends BivariateLongFunctionVectorValueProcessor<long[], long[]>
|
||||||
{
|
{
|
||||||
public LongOutLongsInFunctionVectorValueProcessor(
|
public LongOutLongsInFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<long[]> left,
|
ExprVectorProcessor<long[]> left,
|
||||||
|
@ -36,8 +36,7 @@ public abstract class LongOutLongsInFunctionVectorValueProcessor
|
||||||
super(
|
super(
|
||||||
CastToTypeVectorProcessor.cast(left, ExpressionType.LONG),
|
CastToTypeVectorProcessor.cast(left, ExpressionType.LONG),
|
||||||
CastToTypeVectorProcessor.cast(right, ExpressionType.LONG),
|
CastToTypeVectorProcessor.cast(right, ExpressionType.LONG),
|
||||||
maxVectorSize,
|
maxVectorSize
|
||||||
new long[maxVectorSize]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +53,4 @@ public abstract class LongOutLongsInFunctionVectorValueProcessor
|
||||||
{
|
{
|
||||||
outValues[i] = apply(leftInput[i], rightInput[i]);
|
outValues[i] = apply(leftInput[i], rightInput[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
final ExprEvalVector<long[]> asEval()
|
|
||||||
{
|
|
||||||
return new ExprEvalLongVector(outValues, outNulls);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.druid.math.expr.vector;
|
||||||
|
|
||||||
|
import org.apache.druid.math.expr.Expr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* common machinery for processing single input operators and functions, which should always treat null input as null
|
||||||
|
* output, and are backed by a primitive value instead of an object value (and need to use the null vector instead of
|
||||||
|
* checking the vector itself for nulls)
|
||||||
|
*
|
||||||
|
* this one is specialized for producing double[], see {@link UnivariateLongFunctionVectorValueProcessor} for
|
||||||
|
* long[] primitives.
|
||||||
|
*/
|
||||||
|
public abstract class UnivariateDoubleFunctionVectorValueProcessor<TInput> implements ExprVectorProcessor<double[]>
|
||||||
|
{
|
||||||
|
final ExprVectorProcessor<TInput> processor;
|
||||||
|
final int maxVectorSize;
|
||||||
|
final boolean[] outNulls;
|
||||||
|
final double[] outValues;
|
||||||
|
|
||||||
|
public UnivariateDoubleFunctionVectorValueProcessor(
|
||||||
|
ExprVectorProcessor<TInput> processor,
|
||||||
|
int maxVectorSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.processor = processor;
|
||||||
|
this.maxVectorSize = maxVectorSize;
|
||||||
|
this.outNulls = new boolean[maxVectorSize];
|
||||||
|
this.outValues = new double[maxVectorSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ExprEvalVector<double[]> evalVector(Expr.VectorInputBinding bindings)
|
||||||
|
{
|
||||||
|
final ExprEvalVector<TInput> lhs = processor.evalVector(bindings);
|
||||||
|
|
||||||
|
final int currentSize = bindings.getCurrentVectorSize();
|
||||||
|
final boolean[] inputNulls = lhs.getNullVector();
|
||||||
|
final boolean hasNulls = inputNulls != null;
|
||||||
|
|
||||||
|
final TInput input = lhs.values();
|
||||||
|
|
||||||
|
if (hasNulls) {
|
||||||
|
for (int i = 0; i < currentSize; i++) {
|
||||||
|
outNulls[i] = inputNulls[i];
|
||||||
|
if (!outNulls[i]) {
|
||||||
|
processIndex(input, i);
|
||||||
|
} else {
|
||||||
|
outValues[i] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < currentSize; i++) {
|
||||||
|
outNulls[i] = false;
|
||||||
|
processIndex(input, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return asEval();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void processIndex(TInput input, int i);
|
||||||
|
|
||||||
|
final ExprEvalVector<double[]> asEval()
|
||||||
|
{
|
||||||
|
return new ExprEvalDoubleVector(outValues, outNulls);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,28 +25,30 @@ import org.apache.druid.math.expr.Expr;
|
||||||
* common machinery for processing single input operators and functions, which should always treat null input as null
|
* common machinery for processing single input operators and functions, which should always treat null input as null
|
||||||
* output, and are backed by a primitive value instead of an object value (and need to use the null vector instead of
|
* output, and are backed by a primitive value instead of an object value (and need to use the null vector instead of
|
||||||
* checking the vector itself for nulls)
|
* checking the vector itself for nulls)
|
||||||
|
*
|
||||||
|
* this one is specialized for producing long[], see {@link UnivariateDoubleFunctionVectorValueProcessor} for
|
||||||
|
* double[] primitives.
|
||||||
*/
|
*/
|
||||||
public abstract class UnivariateFunctionVectorValueProcessor<TInput, TOutput> implements ExprVectorProcessor<TOutput>
|
public abstract class UnivariateLongFunctionVectorValueProcessor<TInput> implements ExprVectorProcessor<long[]>
|
||||||
{
|
{
|
||||||
final ExprVectorProcessor<TInput> processor;
|
final ExprVectorProcessor<TInput> processor;
|
||||||
final int maxVectorSize;
|
final int maxVectorSize;
|
||||||
final boolean[] outNulls;
|
final boolean[] outNulls;
|
||||||
final TOutput outValues;
|
final long[] outValues;
|
||||||
|
|
||||||
public UnivariateFunctionVectorValueProcessor(
|
public UnivariateLongFunctionVectorValueProcessor(
|
||||||
ExprVectorProcessor<TInput> processor,
|
ExprVectorProcessor<TInput> processor,
|
||||||
int maxVectorSize,
|
int maxVectorSize
|
||||||
TOutput outValues
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.processor = processor;
|
this.processor = processor;
|
||||||
this.maxVectorSize = maxVectorSize;
|
this.maxVectorSize = maxVectorSize;
|
||||||
this.outNulls = new boolean[maxVectorSize];
|
this.outNulls = new boolean[maxVectorSize];
|
||||||
this.outValues = outValues;
|
this.outValues = new long[maxVectorSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final ExprEvalVector<TOutput> evalVector(Expr.VectorInputBinding bindings)
|
public final ExprEvalVector<long[]> evalVector(Expr.VectorInputBinding bindings)
|
||||||
{
|
{
|
||||||
final ExprEvalVector<TInput> lhs = processor.evalVector(bindings);
|
final ExprEvalVector<TInput> lhs = processor.evalVector(bindings);
|
||||||
|
|
||||||
|
@ -61,6 +63,8 @@ public abstract class UnivariateFunctionVectorValueProcessor<TInput, TOutput> im
|
||||||
outNulls[i] = inputNulls[i];
|
outNulls[i] = inputNulls[i];
|
||||||
if (!outNulls[i]) {
|
if (!outNulls[i]) {
|
||||||
processIndex(input, i);
|
processIndex(input, i);
|
||||||
|
} else {
|
||||||
|
outValues[i] = 0L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -74,5 +78,8 @@ public abstract class UnivariateFunctionVectorValueProcessor<TInput, TOutput> im
|
||||||
|
|
||||||
abstract void processIndex(TInput input, int i);
|
abstract void processIndex(TInput input, int i);
|
||||||
|
|
||||||
abstract ExprEvalVector<TOutput> asEval();
|
final ExprEvalVector<long[]> asEval()
|
||||||
|
{
|
||||||
|
return new ExprEvalLongVector(outValues, outNulls);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -158,9 +158,9 @@ public class VectorMathProcessors
|
||||||
}
|
}
|
||||||
} else if (leftType.is(ExprType.STRING)) {
|
} else if (leftType.is(ExprType.STRING)) {
|
||||||
if (Types.is(rightType, ExprType.LONG)) {
|
if (Types.is(rightType, ExprType.LONG)) {
|
||||||
processor = longOutLongsInProcessor.get();
|
processor = doubleOutDoubleLongInProcessor.get();
|
||||||
} else if (Types.is(rightType, ExprType.DOUBLE)) {
|
} else if (Types.is(rightType, ExprType.DOUBLE)) {
|
||||||
processor = doubleOutLongDoubleInProcessor.get();
|
processor = doubleOutDoublesInProcessor.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (processor == null) {
|
if (processor == null) {
|
||||||
|
@ -696,7 +696,7 @@ public class VectorMathProcessors
|
||||||
{
|
{
|
||||||
final ExpressionType leftType = left.getOutputType(inspector);
|
final ExpressionType leftType = left.getOutputType(inspector);
|
||||||
final ExpressionType rightType = right.getOutputType(inspector);
|
final ExpressionType rightType = right.getOutputType(inspector);
|
||||||
BivariateFunctionVectorValueProcessor<?, ?, ?> processor = null;
|
ExprVectorProcessor<?> processor = null;
|
||||||
if ((Types.is(leftType, ExprType.LONG) && Types.isNullOr(rightType, ExprType.LONG)) ||
|
if ((Types.is(leftType, ExprType.LONG) && Types.isNullOr(rightType, ExprType.LONG)) ||
|
||||||
(leftType == null && Types.is(rightType, ExprType.LONG))) {
|
(leftType == null && Types.is(rightType, ExprType.LONG))) {
|
||||||
processor = new DoubleOutLongsInFunctionVectorValueProcessor(
|
processor = new DoubleOutLongsInFunctionVectorValueProcessor(
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class VectorExprSanityTest extends InitializedNullHandlingTest
|
||||||
@Test
|
@Test
|
||||||
public void testBinaryMathOperators()
|
public void testBinaryMathOperators()
|
||||||
{
|
{
|
||||||
final String[] columns = new String[]{"d1", "d2", "l1", "l2", "1", "1.0", "nonexistent", "null"};
|
final String[] columns = new String[]{"d1", "d2", "l1", "l2", "1", "1.0", "nonexistent", "null", "s1"};
|
||||||
final String[] columns2 = new String[]{"d1", "d2", "l1", "l2", "1", "1.0"};
|
final String[] columns2 = new String[]{"d1", "d2", "l1", "l2", "1", "1.0"};
|
||||||
final String[][] templateInputs = makeTemplateArgs(columns, columns2);
|
final String[][] templateInputs = makeTemplateArgs(columns, columns2);
|
||||||
final String[] templates =
|
final String[] templates =
|
||||||
|
@ -305,7 +305,7 @@ public class VectorExprSanityTest extends InitializedNullHandlingTest
|
||||||
ExprEvalVector<?> vectorEval = parsed.buildVectorized(bindings.rhs).evalVector(bindings.rhs);
|
ExprEvalVector<?> vectorEval = parsed.buildVectorized(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(outputType, vectorEval.getType());
|
Assert.assertEquals(expr, outputType, vectorEval.getType());
|
||||||
}
|
}
|
||||||
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]);
|
||||||
|
|
|
@ -247,7 +247,8 @@ public class VirtualColumns implements Cacheable
|
||||||
|
|
||||||
public boolean canVectorize(ColumnInspector columnInspector)
|
public boolean canVectorize(ColumnInspector columnInspector)
|
||||||
{
|
{
|
||||||
return virtualColumns.stream().allMatch(virtualColumn -> virtualColumn.canVectorize(columnInspector));
|
final ColumnInspector inspector = wrapInspector(columnInspector);
|
||||||
|
return virtualColumns.stream().allMatch(virtualColumn -> virtualColumn.canVectorize(inspector));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,6 +51,7 @@ import org.apache.druid.segment.column.ColumnType;
|
||||||
import org.apache.druid.segment.column.ValueType;
|
import org.apache.druid.segment.column.ValueType;
|
||||||
import org.apache.druid.segment.data.IndexedInts;
|
import org.apache.druid.segment.data.IndexedInts;
|
||||||
import org.apache.druid.segment.data.ZeroIndexedInts;
|
import org.apache.druid.segment.data.ZeroIndexedInts;
|
||||||
|
import org.apache.druid.segment.nested.NestedDataComplexTypeSerde;
|
||||||
import org.apache.druid.testing.InitializedNullHandlingTest;
|
import org.apache.druid.testing.InitializedNullHandlingTest;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
|
@ -471,6 +472,37 @@ public class VirtualColumnsTest extends InitializedNullHandlingTest
|
||||||
Assert.assertTrue(virtualColumns.exists("v2"));
|
Assert.assertTrue(virtualColumns.exists("v2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompositeVirtualColumnsCapabilitiesHasAccessToOtherVirtualColumns()
|
||||||
|
{
|
||||||
|
final ColumnInspector baseInspector = new ColumnInspector()
|
||||||
|
{
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ColumnCapabilities getColumnCapabilities(String column)
|
||||||
|
{
|
||||||
|
if ("x".equals(column)) {
|
||||||
|
return ColumnCapabilitiesImpl.createSimpleNumericColumnCapabilities(ColumnType.LONG);
|
||||||
|
}
|
||||||
|
if ("n".equals(column)) {
|
||||||
|
return ColumnCapabilitiesImpl.createDefault().setType(NestedDataComplexTypeSerde.TYPE);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
final NestedFieldVirtualColumn v0 = new NestedFieldVirtualColumn("n", "$.x", "v0", ColumnType.STRING);
|
||||||
|
final NestedFieldVirtualColumn v1 = new NestedFieldVirtualColumn("n", "$.y", "v1", ColumnType.LONG);
|
||||||
|
final ExpressionVirtualColumn expr1 = new ExpressionVirtualColumn("v2", "v0 * v1", null, TestExprMacroTable.INSTANCE);
|
||||||
|
final ExpressionVirtualColumn expr2 = new ExpressionVirtualColumn("v3", "v0 * x", null, TestExprMacroTable.INSTANCE);
|
||||||
|
final VirtualColumns virtualColumns = VirtualColumns.create(ImmutableList.of(v0, v1, expr1, expr2));
|
||||||
|
|
||||||
|
Assert.assertEquals(ColumnType.STRING, virtualColumns.getColumnCapabilities(baseInspector, "v0").toColumnType());
|
||||||
|
Assert.assertEquals(ColumnType.LONG, virtualColumns.getColumnCapabilities(baseInspector, "v1").toColumnType());
|
||||||
|
Assert.assertEquals(ColumnType.DOUBLE, virtualColumns.getColumnCapabilities(baseInspector, "v2").toColumnType());
|
||||||
|
Assert.assertEquals(ColumnType.DOUBLE, virtualColumns.getColumnCapabilities(baseInspector, "v3").toColumnType());
|
||||||
|
Assert.assertTrue(virtualColumns.canVectorize(baseInspector));
|
||||||
|
}
|
||||||
|
|
||||||
private VirtualColumns makeVirtualColumns()
|
private VirtualColumns makeVirtualColumns()
|
||||||
{
|
{
|
||||||
final ExpressionVirtualColumn expr = new ExpressionVirtualColumn(
|
final ExpressionVirtualColumn expr = new ExpressionVirtualColumn(
|
||||||
|
|
|
@ -276,7 +276,8 @@ public class NestedDataOperatorConversions
|
||||||
call.operand(0),
|
call.operand(0),
|
||||||
call.operand(1)
|
call.operand(1)
|
||||||
);
|
);
|
||||||
} else if (SqlTypeName.APPROX_TYPES.contains(sqlType.getSqlTypeName())) {
|
} else if (SqlTypeName.DECIMAL.equals(sqlType.getSqlTypeName()) ||
|
||||||
|
SqlTypeName.APPROX_TYPES.contains(sqlType.getSqlTypeName())) {
|
||||||
rewrite = JsonValueDoubleOperatorConversion.FUNCTION.createCall(
|
rewrite = JsonValueDoubleOperatorConversion.FUNCTION.createCall(
|
||||||
SqlParserPos.ZERO,
|
SqlParserPos.ZERO,
|
||||||
call.operand(0),
|
call.operand(0),
|
||||||
|
|
|
@ -1951,6 +1951,35 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReturningAndSumPathWithMaths()
|
||||||
|
{
|
||||||
|
testQuery(
|
||||||
|
"SELECT "
|
||||||
|
+ "SUM(JSON_VALUE(nest, '$.x' RETURNING BIGINT) / 100) "
|
||||||
|
+ "FROM druid.nested",
|
||||||
|
ImmutableList.of(
|
||||||
|
Druids.newTimeseriesQueryBuilder()
|
||||||
|
.dataSource(DATA_SOURCE)
|
||||||
|
.intervals(querySegmentSpec(Filtration.eternity()))
|
||||||
|
.granularity(Granularities.ALL)
|
||||||
|
.virtualColumns(
|
||||||
|
expressionVirtualColumn("v0", "(\"v1\" / 100)", ColumnType.LONG),
|
||||||
|
new NestedFieldVirtualColumn("nest", "$.x", "v1", ColumnType.LONG)
|
||||||
|
)
|
||||||
|
.aggregators(aggregators(new LongSumAggregatorFactory("a0", "v0")))
|
||||||
|
.context(QUERY_CONTEXT_DEFAULT)
|
||||||
|
.build()
|
||||||
|
),
|
||||||
|
ImmutableList.of(
|
||||||
|
new Object[]{4L}
|
||||||
|
),
|
||||||
|
RowSignature.builder()
|
||||||
|
.add("EXPR$0", ColumnType.LONG)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReturningAndSumPathDouble()
|
public void testReturningAndSumPathDouble()
|
||||||
{
|
{
|
||||||
|
@ -2003,6 +2032,35 @@ public class CalciteNestedDataQueryTest extends BaseCalciteQueryTest
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReturningAndSumPathDecimalWithMaths()
|
||||||
|
{
|
||||||
|
testQuery(
|
||||||
|
"SELECT "
|
||||||
|
+ "SUM(JSON_VALUE(nest, '$.x' RETURNING DECIMAL) / 100.0) "
|
||||||
|
+ "FROM druid.nested",
|
||||||
|
ImmutableList.of(
|
||||||
|
Druids.newTimeseriesQueryBuilder()
|
||||||
|
.dataSource(DATA_SOURCE)
|
||||||
|
.intervals(querySegmentSpec(Filtration.eternity()))
|
||||||
|
.granularity(Granularities.ALL)
|
||||||
|
.virtualColumns(
|
||||||
|
expressionVirtualColumn("v0", "(\"v1\" / 100.0)", ColumnType.DOUBLE),
|
||||||
|
new NestedFieldVirtualColumn("nest", "$.x", "v1", ColumnType.DOUBLE)
|
||||||
|
)
|
||||||
|
.aggregators(aggregators(new DoubleSumAggregatorFactory("a0", "v0")))
|
||||||
|
.context(QUERY_CONTEXT_DEFAULT)
|
||||||
|
.build()
|
||||||
|
),
|
||||||
|
ImmutableList.of(
|
||||||
|
new Object[]{4.0}
|
||||||
|
),
|
||||||
|
RowSignature.builder()
|
||||||
|
.add("EXPR$0", ColumnType.DOUBLE)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReturningAndSumPathStrings()
|
public void testReturningAndSumPathStrings()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue