Skip to content

Commit

Permalink
ESQL: Test utilities for functions
Browse files Browse the repository at this point in the history
Adds utilities to generate test cases for `null` arguments and
combinations of arguments that aren't supported. The `null` arguments
cases are asserted to return `null` which is how *most* functions work.
The invalid argument type cominations are asserted to return an error.

This slightly modifies some functions to explicitly return `null` if
given an always-null argument. It's simpler to test this way and easier
to line up. So doing something like `GREATEST(1, 2, null)` will both
return `null` and have the type `null`.
  • Loading branch information
nik9000 committed Aug 23, 2023
1 parent 543c125 commit c638304
Show file tree
Hide file tree
Showing 24 changed files with 543 additions and 309 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,15 @@ public interface ExpressionEvaluator {
Block eval(Page page);
}

public static final ExpressionEvaluator CONSTANT_NULL = page -> Block.constantNullBlock(page.getPositionCount());
public static final ExpressionEvaluator CONSTANT_NULL = new ExpressionEvaluator() {
@Override
public Block eval(Page page) {
return Block.constantNullBlock(page.getPositionCount());
}

@Override
public String toString() {
return "ConstantNull";
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ a:integer | b:integer | l:integer
leastNull
ROW l=LEAST(10, 5, null);

l:integer
l:null
null
;

Expand All @@ -1052,7 +1052,7 @@ a:integer | b:integer | g:integer
greatestNull
ROW g=GREATEST(10, 5, null);

g:integer
g:null
null
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,17 @@ protected TypeResolution resolveType() {
}

for (int position = 0; position < children().size(); position++) {
if (dataType == null || dataType == NULL) {
dataType = children().get(position).dataType();
Expression child = children().get(position);
if (child.dataType() == DataTypes.NULL) {
dataType = DataTypes.NULL;
break;
}
if (dataType == null) {
dataType = child.dataType();
continue;
}
TypeResolution resolution = TypeResolutions.isType(
children().get(position),
child,
t -> t == dataType,
sourceText(),
TypeResolutions.ParamOrdinal.fromIndex(position),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,17 @@ protected TypeResolution resolveType() {
}

for (int position = 0; position < children().size(); position++) {
if (dataType == null || dataType == NULL) {
dataType = children().get(position).dataType();
Expression child = children().get(position);
if (child.dataType() == DataTypes.NULL) {
dataType = DataTypes.NULL;
break;
}
if (dataType == null) {
dataType = child.dataType();
continue;
}
TypeResolution resolution = TypeResolutions.isType(
children().get(position),
child,
t -> t == dataType,
sourceText(),
TypeResolutions.ParamOrdinal.fromIndex(position),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ public Supplier<EvalOperator.ExpressionEvaluator> toEvaluator(
if (dataType() == DataTypes.INTEGER) {
return () -> new AbsIntEvaluator(field.get());
}
if (dataType() == DataTypes.NULL) {
return () -> EvalOperator.CONSTANT_NULL;
}
throw EsqlUnsupportedOperationException.unsupportedDataType(dataType());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ abstract class AbstractTrigonometricFunction extends UnaryScalarFunction impleme
public final Supplier<EvalOperator.ExpressionEvaluator> toEvaluator(
Function<Expression, Supplier<EvalOperator.ExpressionEvaluator>> toEvaluator
) {
if (field.dataType() == DataTypes.NULL) {
return () -> EvalOperator.CONSTANT_NULL;
}
Supplier<EvalOperator.ExpressionEvaluator> fieldEval = Cast.cast(field().dataType(), DataTypes.DOUBLE, toEvaluator.apply(field()));
return () -> doubleEvaluator(fieldEval.get());
}
Expand All @@ -55,6 +58,9 @@ protected final TypeResolution resolveType() {

@Override
public final DataType dataType() {
if (field.dataType() == DataTypes.NULL) {
return DataTypes.NULL;
}
return DataTypes.DOUBLE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ static double process(double y, double x) {

@Override
public DataType dataType() {
if (y.dataType() == DataTypes.NULL || x.dataType() == DataTypes.NULL) {
return DataTypes.NULL;
}
return DataTypes.DOUBLE;
}

Expand All @@ -82,6 +85,9 @@ public boolean foldable() {
public Supplier<EvalOperator.ExpressionEvaluator> toEvaluator(
Function<Expression, Supplier<EvalOperator.ExpressionEvaluator>> toEvaluator
) {
if (y.dataType() == DataTypes.NULL || x.dataType() == DataTypes.NULL) {
return () -> EvalOperator.CONSTANT_NULL;
}
Supplier<EvalOperator.ExpressionEvaluator> yEval = Cast.cast(y.dataType(), DataTypes.DOUBLE, toEvaluator.apply(y));
Supplier<EvalOperator.ExpressionEvaluator> xEval = Cast.cast(x.dataType(), DataTypes.DOUBLE, toEvaluator.apply(x));
return () -> new Atan2Evaluator(yEval.get(), xEval.get());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ public Supplier<EvalOperator.ExpressionEvaluator> toEvaluator(
if (fieldType == DataTypes.UNSIGNED_LONG) {
return toEvaluator(toEvaluator, Function.identity(), RoundUnsignedLongEvaluator::new);
}
if (fieldType == DataTypes.NULL) {
return () -> EvalOperator.CONSTANT_NULL;
}
throw EsqlUnsupportedOperationException.unsupportedDataType(fieldType);
}

Expand Down
Loading

0 comments on commit c638304

Please sign in to comment.