ESQL: Move more test type error testing (#119945)
This reduces the number of test cases in ESQL a little more ala #119678. It migrates a few random tests and all of the multivalue functions: ``` 92775 -> 43760 3m45 -> 4m04 ``` This adds a few more error test cases that were missing to make sure it all lines up well. And it fixes a few error messages in a few functions. That's *likely* where the extra time goes.
This commit is contained in:
parent
8082cfa27e
commit
1c13465991
|
@ -32,7 +32,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "pattern",
|
||||
"type" : "text",
|
||||
"type" : "keyword",
|
||||
"optional" : false,
|
||||
"description" : "Pattern."
|
||||
}
|
||||
|
|
|
@ -76,6 +76,24 @@
|
|||
"variadic" : false,
|
||||
"returnType" : "date"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field1",
|
||||
"type" : "date_nanos",
|
||||
"optional" : false,
|
||||
"description" : ""
|
||||
},
|
||||
{
|
||||
"name" : "field2",
|
||||
"type" : "date_nanos",
|
||||
"optional" : false,
|
||||
"description" : ""
|
||||
}
|
||||
],
|
||||
"variadic" : false,
|
||||
"returnType" : "date_nanos"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
|
@ -184,6 +202,24 @@
|
|||
"variadic" : false,
|
||||
"returnType" : "keyword"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field1",
|
||||
"type" : "keyword",
|
||||
"optional" : false,
|
||||
"description" : ""
|
||||
},
|
||||
{
|
||||
"name" : "field2",
|
||||
"type" : "text",
|
||||
"optional" : false,
|
||||
"description" : ""
|
||||
}
|
||||
],
|
||||
"variadic" : false,
|
||||
"returnType" : "keyword"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
|
@ -202,6 +238,24 @@
|
|||
"variadic" : false,
|
||||
"returnType" : "long"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field1",
|
||||
"type" : "text",
|
||||
"optional" : false,
|
||||
"description" : ""
|
||||
},
|
||||
{
|
||||
"name" : "field2",
|
||||
"type" : "keyword",
|
||||
"optional" : false,
|
||||
"description" : ""
|
||||
}
|
||||
],
|
||||
"variadic" : false,
|
||||
"returnType" : "keyword"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
|
@ -220,6 +274,24 @@
|
|||
"variadic" : false,
|
||||
"returnType" : "keyword"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field1",
|
||||
"type" : "unsigned_long",
|
||||
"optional" : false,
|
||||
"description" : ""
|
||||
},
|
||||
{
|
||||
"name" : "field2",
|
||||
"type" : "unsigned_long",
|
||||
"optional" : false,
|
||||
"description" : ""
|
||||
}
|
||||
],
|
||||
"variadic" : false,
|
||||
"returnType" : "unsigned_long"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
|
|
|
@ -161,6 +161,18 @@
|
|||
"variadic" : false,
|
||||
"returnType" : "keyword"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "unsigned_long",
|
||||
"optional" : false,
|
||||
"description" : "Multivalue expression."
|
||||
}
|
||||
],
|
||||
"variadic" : false,
|
||||
"returnType" : "unsigned_long"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
|
|
|
@ -316,6 +316,30 @@
|
|||
"variadic" : false,
|
||||
"returnType" : "keyword"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "unsigned_long",
|
||||
"optional" : false,
|
||||
"description" : "Multivalue expression. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "start",
|
||||
"type" : "integer",
|
||||
"optional" : false,
|
||||
"description" : "Start position. If `null`, the function returns `null`. The start argument can be negative. An index of -1 is used to specify the last value in the list."
|
||||
},
|
||||
{
|
||||
"name" : "end",
|
||||
"type" : "integer",
|
||||
"optional" : true,
|
||||
"description" : "End position(included). Optional; if omitted, the position at `start` is returned. The end argument can be negative. An index of -1 is used to specify the last value in the list."
|
||||
}
|
||||
],
|
||||
"variadic" : false,
|
||||
"returnType" : "unsigned_long"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "pattern",
|
||||
"type" : "text",
|
||||
"type" : "keyword",
|
||||
"optional" : false,
|
||||
"description" : "A regular expression."
|
||||
}
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
|===
|
||||
str | pattern | result
|
||||
keyword | keyword | boolean
|
||||
text | text | boolean
|
||||
text | keyword | boolean
|
||||
|===
|
||||
|
|
|
@ -9,13 +9,17 @@ boolean | boolean | boolean
|
|||
cartesian_point | cartesian_point | cartesian_point
|
||||
cartesian_shape | cartesian_shape | cartesian_shape
|
||||
date | date | date
|
||||
date_nanos | date_nanos | date_nanos
|
||||
double | double | double
|
||||
geo_point | geo_point | geo_point
|
||||
geo_shape | geo_shape | geo_shape
|
||||
integer | integer | integer
|
||||
ip | ip | ip
|
||||
keyword | keyword | keyword
|
||||
keyword | text | keyword
|
||||
long | long | long
|
||||
text | keyword | keyword
|
||||
text | text | keyword
|
||||
unsigned_long | unsigned_long | unsigned_long
|
||||
version | version | version
|
||||
|===
|
||||
|
|
|
@ -18,5 +18,6 @@ ip | ip
|
|||
keyword | keyword
|
||||
long | long
|
||||
text | keyword
|
||||
unsigned_long | unsigned_long
|
||||
version | version
|
||||
|===
|
||||
|
|
|
@ -18,5 +18,6 @@ ip | integer | integer | ip
|
|||
keyword | integer | integer | keyword
|
||||
long | integer | integer | long
|
||||
text | integer | integer | keyword
|
||||
unsigned_long | integer | integer | unsigned_long
|
||||
version | integer | integer | version
|
||||
|===
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
|===
|
||||
str | pattern | result
|
||||
keyword | keyword | boolean
|
||||
text | text | boolean
|
||||
text | keyword | boolean
|
||||
|===
|
||||
|
|
|
@ -55,6 +55,7 @@ public class MvAppend extends EsqlScalarFunction implements EvaluatorMapper {
|
|||
"cartesian_point",
|
||||
"cartesian_shape",
|
||||
"date",
|
||||
"date_nanos",
|
||||
"double",
|
||||
"geo_point",
|
||||
"geo_shape",
|
||||
|
@ -62,6 +63,7 @@ public class MvAppend extends EsqlScalarFunction implements EvaluatorMapper {
|
|||
"ip",
|
||||
"keyword",
|
||||
"long",
|
||||
"unsigned_long",
|
||||
"version" },
|
||||
description = "Concatenates values of two multi-value fields."
|
||||
)
|
||||
|
@ -74,6 +76,7 @@ public class MvAppend extends EsqlScalarFunction implements EvaluatorMapper {
|
|||
"cartesian_point",
|
||||
"cartesian_shape",
|
||||
"date",
|
||||
"date_nanos",
|
||||
"double",
|
||||
"geo_point",
|
||||
"geo_shape",
|
||||
|
@ -82,6 +85,7 @@ public class MvAppend extends EsqlScalarFunction implements EvaluatorMapper {
|
|||
"keyword",
|
||||
"long",
|
||||
"text",
|
||||
"unsigned_long",
|
||||
"version" }
|
||||
) Expression field1,
|
||||
@Param(
|
||||
|
@ -91,6 +95,7 @@ public class MvAppend extends EsqlScalarFunction implements EvaluatorMapper {
|
|||
"cartesian_point",
|
||||
"cartesian_shape",
|
||||
"date",
|
||||
"date_nanos",
|
||||
"double",
|
||||
"geo_point",
|
||||
"geo_shape",
|
||||
|
@ -99,6 +104,7 @@ public class MvAppend extends EsqlScalarFunction implements EvaluatorMapper {
|
|||
"keyword",
|
||||
"long",
|
||||
"text",
|
||||
"unsigned_long",
|
||||
"version" }
|
||||
) Expression field2
|
||||
) {
|
||||
|
|
|
@ -46,6 +46,7 @@ public class MvDedupe extends AbstractMultivalueFunction {
|
|||
"ip",
|
||||
"keyword",
|
||||
"long",
|
||||
"unsigned_long",
|
||||
"version" },
|
||||
description = "Remove duplicate values from a multivalued field.",
|
||||
note = "`MV_DEDUPE` may, but won't always, sort the values in the column.",
|
||||
|
@ -69,6 +70,7 @@ public class MvDedupe extends AbstractMultivalueFunction {
|
|||
"keyword",
|
||||
"long",
|
||||
"text",
|
||||
"unsigned_long",
|
||||
"version" },
|
||||
description = "Multivalue expression."
|
||||
) Expression field
|
||||
|
|
|
@ -67,6 +67,7 @@ public class MvSlice extends EsqlScalarFunction implements OptionalArgument, Eva
|
|||
"ip",
|
||||
"keyword",
|
||||
"long",
|
||||
"unsigned_long",
|
||||
"version" },
|
||||
description = """
|
||||
Returns a subset of the multivalued field using the start and end index values.
|
||||
|
@ -96,6 +97,7 @@ public class MvSlice extends EsqlScalarFunction implements OptionalArgument, Eva
|
|||
"keyword",
|
||||
"long",
|
||||
"text",
|
||||
"unsigned_long",
|
||||
"version" },
|
||||
description = "Multivalue expression. If `null`, the function returns `null`."
|
||||
) Expression field,
|
||||
|
|
|
@ -384,7 +384,9 @@ public abstract class AbstractFunctionTestCase extends ESTestCase {
|
|||
|
||||
/**
|
||||
* Build a test case that asserts that the combination of parameter types is an error.
|
||||
* @deprecated use an extension of {@link ErrorsForCasesWithoutExamplesTestCase}
|
||||
*/
|
||||
@Deprecated
|
||||
protected static TestCaseSupplier typeErrorSupplier(
|
||||
boolean includeOrdinal,
|
||||
List<Set<DataType>> validPerPosition,
|
||||
|
@ -643,11 +645,17 @@ public abstract class AbstractFunctionTestCase extends ESTestCase {
|
|||
protected Object toJavaObjectUnsignedLongAware(Block block, int position) {
|
||||
Object result;
|
||||
result = toJavaObject(block, position);
|
||||
if (result != null && testCase.expectedType() == DataType.UNSIGNED_LONG) {
|
||||
assertThat(result, instanceOf(Long.class));
|
||||
result = NumericUtils.unsignedLongAsBigInteger((Long) result);
|
||||
if (result == null || testCase.expectedType() != DataType.UNSIGNED_LONG) {
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
if (result instanceof List<?> l) {
|
||||
return l.stream().map(v -> {
|
||||
assertThat(v, instanceOf(Long.class));
|
||||
return NumericUtils.unsignedLongAsBigInteger((Long) v);
|
||||
}).toList();
|
||||
}
|
||||
assertThat(result, instanceOf(Long.class));
|
||||
return NumericUtils.unsignedLongAsBigInteger((Long) result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -372,7 +372,11 @@ public abstract class AbstractScalarFunctionTestCase extends AbstractFunctionTes
|
|||
Object result = nullOptimized.fold(FoldContext.small());
|
||||
// Decode unsigned longs into BigIntegers
|
||||
if (testCase.expectedType() == DataType.UNSIGNED_LONG && result != null) {
|
||||
result = NumericUtils.unsignedLongAsBigInteger((Long) result);
|
||||
if (result instanceof List<?> l) {
|
||||
result = l.stream().map(v -> NumericUtils.unsignedLongAsBigInteger((Long) v)).toList();
|
||||
} else {
|
||||
result = NumericUtils.unsignedLongAsBigInteger((Long) result);
|
||||
}
|
||||
}
|
||||
assertThat(result, testCase.getMatcher());
|
||||
if (testCase.getExpectedBuildEvaluatorWarnings() != null) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.xpack.esql.core.expression.Expression;
|
|||
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvCountErrorTests;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -24,6 +25,10 @@ import java.util.stream.Stream;
|
|||
import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomLiteral;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
|
||||
/**
|
||||
* Extend me to test that all cases not mentioned in a subclass of
|
||||
* {@link AbstractFunctionTestCase} produce type errors.
|
||||
*/
|
||||
public abstract class ErrorsForCasesWithoutExamplesTestCase extends ESTestCase {
|
||||
protected abstract List<TestCaseSupplier> cases();
|
||||
|
||||
|
@ -37,6 +42,15 @@ public abstract class ErrorsForCasesWithoutExamplesTestCase extends ESTestCase {
|
|||
*/
|
||||
protected abstract Expression build(Source source, List<Expression> args);
|
||||
|
||||
/**
|
||||
* A matcher for the invalid type error message.
|
||||
* <p>
|
||||
* If you are implementing this for a function that should process all types
|
||||
* then have a look how {@link MvCountErrorTests} does it. It's nice to throw
|
||||
* an error explaining this. But while someone is implementing a new type
|
||||
* they will want to turn that off temporarily. And we say that in the note too.
|
||||
* </p>
|
||||
*/
|
||||
protected abstract Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature);
|
||||
|
||||
protected final List<TestCaseSupplier> paramsToSuppliers(Iterable<Object[]> cases) {
|
||||
|
@ -56,8 +70,8 @@ public abstract class ErrorsForCasesWithoutExamplesTestCase extends ESTestCase {
|
|||
List<TestCaseSupplier> cases = cases();
|
||||
Set<List<DataType>> valid = cases.stream().map(TestCaseSupplier::types).collect(Collectors.toSet());
|
||||
List<Set<DataType>> validPerPosition = AbstractFunctionTestCase.validPerPosition(valid);
|
||||
Iterable<List<DataType>> missingSignatures = missingSignatures(cases, valid)::iterator;
|
||||
for (List<DataType> signature : missingSignatures) {
|
||||
Iterable<List<DataType>> testCandidates = testCandidates(cases, valid)::iterator;
|
||||
for (List<DataType> signature : testCandidates) {
|
||||
logger.debug("checking {}", signature);
|
||||
List<Expression> args = new ArrayList<>(signature.size());
|
||||
for (DataType type : signature) {
|
||||
|
@ -80,7 +94,10 @@ public abstract class ErrorsForCasesWithoutExamplesTestCase extends ESTestCase {
|
|||
assertThat("didn't check any signatures", checked, greaterThan(0));
|
||||
}
|
||||
|
||||
private Stream<List<DataType>> missingSignatures(List<TestCaseSupplier> cases, Set<List<DataType>> valid) {
|
||||
/**
|
||||
* Build a {@link Stream} of test signatures that we should check are invalid.
|
||||
*/
|
||||
protected Stream<List<DataType>> testCandidates(List<TestCaseSupplier> cases, Set<List<DataType>> valid) {
|
||||
return cases.stream()
|
||||
.map(s -> s.types().size())
|
||||
.collect(Collectors.toSet())
|
||||
|
@ -125,7 +142,7 @@ public abstract class ErrorsForCasesWithoutExamplesTestCase extends ESTestCase {
|
|||
}
|
||||
if (badArgPosition == -1) {
|
||||
throw new IllegalStateException(
|
||||
"Can't generate error message for these types, you probably need a custom error message function"
|
||||
"Can't generate error message for these types, you probably need a custom error message function signature =" + signature
|
||||
);
|
||||
}
|
||||
String ordinal = includeOrdinal ? TypeResolutions.ParamOrdinal.fromIndex(badArgPosition).name().toLowerCase(Locale.ROOT) + " " : "";
|
||||
|
|
|
@ -1416,6 +1416,10 @@ public record TestCaseSupplier(String name, List<DataType> types, Supplier<TestC
|
|||
*/
|
||||
private final String[] expectedBuildEvaluatorWarnings;
|
||||
|
||||
/**
|
||||
* @deprecated use subclasses of {@link ErrorsForCasesWithoutExamplesTestCase}
|
||||
*/
|
||||
@Deprecated
|
||||
private final String expectedTypeError;
|
||||
private final boolean canBuildEvaluator;
|
||||
|
||||
|
@ -1436,6 +1440,11 @@ public record TestCaseSupplier(String name, List<DataType> types, Supplier<TestC
|
|||
this(data, evaluatorToString, expectedType, matcher, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a test case for type errors.
|
||||
* @deprecated use a subclass of {@link ErrorsForCasesWithoutExamplesTestCase} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static TestCase typeError(List<TypedData> data, String expectedTypeError) {
|
||||
return new TestCase(data, null, null, null, null, null, expectedTypeError, null, null, null);
|
||||
}
|
||||
|
@ -1556,6 +1565,10 @@ public record TestCaseSupplier(String name, List<DataType> types, Supplier<TestC
|
|||
return foldingExceptionMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use subclasses of {@link ErrorsForCasesWithoutExamplesTestCase}
|
||||
*/
|
||||
@Deprecated
|
||||
public String getExpectedTypeError() {
|
||||
return expectedTypeError;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.fulltext;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class KqlErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(KqlTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<List<DataType>> testCandidates(List<TestCaseSupplier> cases, Set<List<DataType>> valid) {
|
||||
// Don't test null, as it is not allowed but the expected message is not a type error - so we check it separately in VerifierTests
|
||||
return super.testCandidates(cases, valid).filter(sig -> false == sig.contains(DataType.NULL));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new Kql(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "string"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.fulltext;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.AbstractFunctionTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.EsqlBinaryComparison;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MatchErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MatchTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new Match(source, args.get(0), args.get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(
|
||||
errorMessageStringForMatch(validPerPosition, signature, (l, p) -> p == 0 ? FIELD_TYPE_ERROR_STRING : QUERY_TYPE_ERROR_STRING)
|
||||
);
|
||||
}
|
||||
|
||||
private static String errorMessageStringForMatch(
|
||||
List<Set<DataType>> validPerPosition,
|
||||
List<DataType> signature,
|
||||
AbstractFunctionTestCase.PositionalErrorMessageSupplier positionalErrorMessageSupplier
|
||||
) {
|
||||
for (int i = 0; i < signature.size(); i++) {
|
||||
// Need to check for nulls and bad parameters in order
|
||||
if (signature.get(i) == DataType.NULL) {
|
||||
return TypeResolutions.ParamOrdinal.fromIndex(i).name().toLowerCase(Locale.ROOT)
|
||||
+ " argument of ["
|
||||
+ sourceForSignature(signature)
|
||||
+ "] cannot be null, received []";
|
||||
}
|
||||
if (validPerPosition.get(i).contains(signature.get(i)) == false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return typeErrorMessage(true, validPerPosition, signature, positionalErrorMessageSupplier);
|
||||
} catch (IllegalStateException e) {
|
||||
// This means all the positional args were okay, so the expected error is for nulls or from the combination
|
||||
return EsqlBinaryComparison.formatIncompatibleTypesMessage(signature.get(0), signature.get(1), sourceForSignature(signature));
|
||||
}
|
||||
}
|
||||
|
||||
private static final String FIELD_TYPE_ERROR_STRING =
|
||||
"keyword, text, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version";
|
||||
|
||||
private static final String QUERY_TYPE_ERROR_STRING =
|
||||
"keyword, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version";
|
||||
}
|
|
@ -11,20 +11,16 @@ import com.carrotsearch.randomizedtesting.annotations.Name;
|
|||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.core.util.NumericUtils;
|
||||
import org.elasticsearch.xpack.esql.expression.function.AbstractFunctionTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.FunctionName;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.EsqlBinaryComparison;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier.stringCases;
|
||||
|
@ -33,12 +29,6 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
@FunctionName("match")
|
||||
public class MatchTests extends AbstractFunctionTestCase {
|
||||
|
||||
private static final String FIELD_TYPE_ERROR_STRING =
|
||||
"keyword, text, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version";
|
||||
|
||||
private static final String QUERY_TYPE_ERROR_STRING =
|
||||
"keyword, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version";
|
||||
|
||||
public MatchTests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCaseSupplier) {
|
||||
this.testCase = testCaseSupplier.get();
|
||||
}
|
||||
|
@ -53,37 +43,7 @@ public class MatchTests extends AbstractFunctionTestCase {
|
|||
addQueryAsStringTestCases(suppliers);
|
||||
addStringTestCases(suppliers);
|
||||
|
||||
return parameterSuppliersFromTypedData(
|
||||
errorsForCasesWithoutExamples(
|
||||
suppliers,
|
||||
(o, v, t) -> errorMessageStringForMatch(o, v, t, (l, p) -> p == 0 ? FIELD_TYPE_ERROR_STRING : QUERY_TYPE_ERROR_STRING)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static String errorMessageStringForMatch(
|
||||
boolean includeOrdinal,
|
||||
List<Set<DataType>> validPerPosition,
|
||||
List<DataType> types,
|
||||
PositionalErrorMessageSupplier positionalErrorMessageSupplier
|
||||
) {
|
||||
for (int i = 0; i < types.size(); i++) {
|
||||
// Need to check for nulls and bad parameters in order
|
||||
if (types.get(i) == DataType.NULL) {
|
||||
return TypeResolutions.ParamOrdinal.fromIndex(i).name().toLowerCase(Locale.ROOT)
|
||||
+ " argument of [] cannot be null, received [null]";
|
||||
}
|
||||
if (validPerPosition.get(i).contains(types.get(i)) == false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return typeErrorMessage(includeOrdinal, validPerPosition, types, positionalErrorMessageSupplier);
|
||||
} catch (IllegalStateException e) {
|
||||
// This means all the positional args were okay, so the expected error is for nulls or from the combination
|
||||
return EsqlBinaryComparison.formatIncompatibleTypesMessage(types.get(0), types.get(1), "");
|
||||
}
|
||||
return parameterSuppliersFromTypedData(suppliers);
|
||||
}
|
||||
|
||||
private static void addNonNumericCases(List<TestCaseSupplier> suppliers) {
|
||||
|
@ -410,10 +370,6 @@ public class MatchTests extends AbstractFunctionTestCase {
|
|||
|
||||
public final void testLiteralExpressions() {
|
||||
Expression expression = buildLiteralExpression(testCase);
|
||||
if (testCase.getExpectedTypeError() != null) {
|
||||
assertTypeResolutionFailure(expression);
|
||||
return;
|
||||
}
|
||||
assertFalse("expected resolved", expression.typeResolved().unresolved());
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,6 @@ public abstract class NoneFieldFullTextFunctionTestCase extends AbstractFunction
|
|||
|
||||
public final void testFold() {
|
||||
Expression expression = buildLiteralExpression(testCase);
|
||||
if (testCase.getExpectedTypeError() != null) {
|
||||
assertTypeResolutionFailure(expression);
|
||||
return;
|
||||
}
|
||||
assertFalse("expected resolved", expression.typeResolved().unresolved());
|
||||
}
|
||||
|
||||
|
@ -46,9 +42,7 @@ public abstract class NoneFieldFullTextFunctionTestCase extends AbstractFunction
|
|||
)
|
||||
);
|
||||
}
|
||||
List<TestCaseSupplier> errorsSuppliers = errorsForCasesWithoutExamples(suppliers, (v, p) -> "string");
|
||||
// Don't test null, as it is not allowed but the expected message is not a type error - so we check it separately in VerifierTests
|
||||
return parameterSuppliersFromTypedData(errorsSuppliers.stream().filter(s -> s.types().contains(DataType.NULL) == false).toList());
|
||||
return parameterSuppliersFromTypedData(suppliers);
|
||||
}
|
||||
|
||||
private static TestCaseSupplier.TestCase testCase(DataType strType, String str, Matcher<Boolean> matcher) {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.fulltext;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class QueryStringErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(QueryStringTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<List<DataType>> testCandidates(List<TestCaseSupplier> cases, Set<List<DataType>> valid) {
|
||||
// Don't test null, as it is not allowed but the expected message is not a type error - so we check it separately in VerifierTests
|
||||
return super.testCandidates(cases, valid).filter(sig -> false == sig.contains(DataType.NULL));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new QueryString(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "string"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.fulltext;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class TermErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(TermTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<List<DataType>> testCandidates(List<TestCaseSupplier> cases, Set<List<DataType>> valid) {
|
||||
// Don't test null, as it is not allowed but the expected message is not a type error - so we check it separately in VerifierTests
|
||||
return super.testCandidates(cases, valid).filter(sig -> false == sig.contains(DataType.NULL));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new Term(source, args.get(0), args.get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(true, validPerPosition, signature, (v, p) -> "string"));
|
||||
}
|
||||
}
|
|
@ -45,12 +45,7 @@ public class TermTests extends AbstractFunctionTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
List<TestCaseSupplier> suppliersWithErrors = errorsForCasesWithoutExamples(suppliers, (v, p) -> "string");
|
||||
|
||||
// Don't test null, as it is not allowed but the expected message is not a type error - so we check it separately in VerifierTests
|
||||
return parameterSuppliersFromTypedData(
|
||||
suppliersWithErrors.stream().filter(s -> s.types().contains(DataType.NULL) == false).toList()
|
||||
);
|
||||
return parameterSuppliersFromTypedData(suppliers);
|
||||
}
|
||||
|
||||
protected static List<Set<DataType>> supportedParams() {
|
||||
|
|
|
@ -770,10 +770,6 @@ public class CaseTests extends AbstractScalarFunctionTestCase {
|
|||
}
|
||||
|
||||
public void testFancyFolding() {
|
||||
if (testCase.getExpectedTypeError() != null) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
Expression e = buildFieldExpression(testCase);
|
||||
if (extra().foldable == false) {
|
||||
assertThat(e.foldable(), equalTo(false));
|
||||
|
@ -794,7 +790,7 @@ public class CaseTests extends AbstractScalarFunctionTestCase {
|
|||
}
|
||||
|
||||
public void testPartialFold() {
|
||||
if (testCase.getExpectedTypeError() != null || extra().foldable()) {
|
||||
if (extra().foldable()) {
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvAppendErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvAppendTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvAppend(source, args.get(0), args.get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(
|
||||
"second argument of ["
|
||||
+ sourceForSignature(signature)
|
||||
+ "] must be ["
|
||||
+ signature.get(0).noText().typeName()
|
||||
+ "], found value [] type ["
|
||||
+ signature.get(1).typeName()
|
||||
+ "]"
|
||||
);
|
||||
}
|
||||
}
|
|
@ -13,15 +13,18 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
|||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.geo.GeometryTestUtils;
|
||||
import org.elasticsearch.geo.ShapeTestUtils;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.core.util.NumericUtils;
|
||||
import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomLiteral;
|
||||
import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.CARTESIAN;
|
||||
|
@ -41,8 +44,7 @@ public class MvAppendTests extends AbstractScalarFunctionTestCase {
|
|||
longs(suppliers);
|
||||
doubles(suppliers);
|
||||
bytesRefs(suppliers);
|
||||
nulls(suppliers);
|
||||
return parameterSuppliersFromTypedData(suppliers);
|
||||
return parameterSuppliersFromTypedData(anyNullIsNull(true, suppliers));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,7 +104,20 @@ public class MvAppendTests extends AbstractScalarFunctionTestCase {
|
|||
equalTo(result)
|
||||
);
|
||||
}));
|
||||
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.UNSIGNED_LONG), () -> {
|
||||
List<Long> field1 = randomList(1, 10, ESTestCase::randomLong);
|
||||
List<Long> field2 = randomList(1, 10, ESTestCase::randomLong);
|
||||
var result = Stream.concat(field1.stream(), field2.stream()).map(NumericUtils::unsignedLongAsBigInteger).toList();
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(field1, DataType.UNSIGNED_LONG, "field1"),
|
||||
new TestCaseSupplier.TypedData(field2, DataType.UNSIGNED_LONG, "field2")
|
||||
),
|
||||
"MvAppendLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]",
|
||||
DataType.UNSIGNED_LONG,
|
||||
equalTo(result)
|
||||
);
|
||||
}));
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.DATETIME, DataType.DATETIME), () -> {
|
||||
List<Long> field1 = randomList(1, 10, () -> randomLong());
|
||||
List<Long> field2 = randomList(1, 10, () -> randomLong());
|
||||
|
@ -118,6 +133,21 @@ public class MvAppendTests extends AbstractScalarFunctionTestCase {
|
|||
equalTo(result)
|
||||
);
|
||||
}));
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.DATE_NANOS, DataType.DATE_NANOS), () -> {
|
||||
List<Long> field1 = randomList(1, 10, () -> randomNonNegativeLong());
|
||||
List<Long> field2 = randomList(1, 10, () -> randomNonNegativeLong());
|
||||
var result = new ArrayList<>(field1);
|
||||
result.addAll(field2);
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(field1, DataType.DATE_NANOS, "field1"),
|
||||
new TestCaseSupplier.TypedData(field2, DataType.DATE_NANOS, "field2")
|
||||
),
|
||||
"MvAppendLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]",
|
||||
DataType.DATE_NANOS,
|
||||
equalTo(result)
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
private static void doubles(List<TestCaseSupplier> suppliers) {
|
||||
|
@ -139,54 +169,25 @@ public class MvAppendTests extends AbstractScalarFunctionTestCase {
|
|||
}
|
||||
|
||||
private static void bytesRefs(List<TestCaseSupplier> suppliers) {
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.KEYWORD, DataType.KEYWORD), () -> {
|
||||
List<Object> field1 = randomList(1, 10, () -> randomLiteral(DataType.KEYWORD).value());
|
||||
List<Object> field2 = randomList(1, 10, () -> randomLiteral(DataType.KEYWORD).value());
|
||||
var result = new ArrayList<>(field1);
|
||||
result.addAll(field2);
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(field1, DataType.KEYWORD, "field1"),
|
||||
new TestCaseSupplier.TypedData(field2, DataType.KEYWORD, "field2")
|
||||
),
|
||||
"MvAppendBytesRefEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]",
|
||||
DataType.KEYWORD,
|
||||
equalTo(result)
|
||||
);
|
||||
}));
|
||||
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.TEXT, DataType.TEXT), () -> {
|
||||
List<Object> field1 = randomList(1, 10, () -> randomLiteral(DataType.TEXT).value());
|
||||
List<Object> field2 = randomList(1, 10, () -> randomLiteral(DataType.TEXT).value());
|
||||
var result = new ArrayList<>(field1);
|
||||
result.addAll(field2);
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(field1, DataType.TEXT, "field1"),
|
||||
new TestCaseSupplier.TypedData(field2, DataType.TEXT, "field2")
|
||||
),
|
||||
"MvAppendBytesRefEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]",
|
||||
DataType.TEXT,
|
||||
equalTo(result)
|
||||
);
|
||||
}));
|
||||
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.SEMANTIC_TEXT, DataType.SEMANTIC_TEXT), () -> {
|
||||
List<Object> field1 = randomList(1, 10, () -> randomLiteral(DataType.SEMANTIC_TEXT).value());
|
||||
List<Object> field2 = randomList(1, 10, () -> randomLiteral(DataType.SEMANTIC_TEXT).value());
|
||||
var result = new ArrayList<>(field1);
|
||||
result.addAll(field2);
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(field1, DataType.SEMANTIC_TEXT, "field1"),
|
||||
new TestCaseSupplier.TypedData(field2, DataType.SEMANTIC_TEXT, "field2")
|
||||
),
|
||||
"MvAppendBytesRefEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]",
|
||||
DataType.SEMANTIC_TEXT,
|
||||
equalTo(result)
|
||||
);
|
||||
}));
|
||||
|
||||
for (DataType lhs : new DataType[] { DataType.KEYWORD, DataType.TEXT, DataType.SEMANTIC_TEXT }) {
|
||||
for (DataType rhs : new DataType[] { DataType.KEYWORD, DataType.TEXT, DataType.SEMANTIC_TEXT }) {
|
||||
suppliers.add(new TestCaseSupplier(List.of(lhs, rhs), () -> {
|
||||
List<Object> field1 = randomList(1, 10, () -> randomLiteral(lhs).value());
|
||||
List<Object> field2 = randomList(1, 10, () -> randomLiteral(rhs).value());
|
||||
var result = new ArrayList<>(field1);
|
||||
result.addAll(field2);
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(field1, lhs, "field1"),
|
||||
new TestCaseSupplier.TypedData(field2, rhs, "field2")
|
||||
),
|
||||
"MvAppendBytesRefEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]",
|
||||
DataType.KEYWORD,
|
||||
equalTo(result)
|
||||
);
|
||||
}));
|
||||
}
|
||||
}
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.IP, DataType.IP), () -> {
|
||||
List<Object> field1 = randomList(1, 10, () -> randomLiteral(DataType.IP).value());
|
||||
List<Object> field2 = randomList(1, 10, () -> randomLiteral(DataType.IP).value());
|
||||
|
@ -283,31 +284,4 @@ public class MvAppendTests extends AbstractScalarFunctionTestCase {
|
|||
);
|
||||
}));
|
||||
}
|
||||
|
||||
private static void nulls(List<TestCaseSupplier> suppliers) {
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.INTEGER, DataType.INTEGER), () -> {
|
||||
List<Integer> field2 = randomList(2, 10, () -> randomInt());
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(null, DataType.INTEGER, "field1"),
|
||||
new TestCaseSupplier.TypedData(field2, DataType.INTEGER, "field2")
|
||||
),
|
||||
"MvAppendIntEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]",
|
||||
DataType.INTEGER,
|
||||
equalTo(null)
|
||||
);
|
||||
}));
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.INTEGER, DataType.INTEGER), () -> {
|
||||
List<Integer> field1 = randomList(2, 10, () -> randomInt());
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(field1, DataType.INTEGER, "field1"),
|
||||
new TestCaseSupplier.TypedData(null, DataType.INTEGER, "field2")
|
||||
),
|
||||
"MvAppendIntEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]",
|
||||
DataType.INTEGER,
|
||||
equalTo(null)
|
||||
);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvAvgErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvAvgTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvAvg(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "numeric"));
|
||||
}
|
||||
}
|
|
@ -55,7 +55,7 @@ public class MvAvgTests extends AbstractMultivalueFunctionTestCase {
|
|||
*/
|
||||
(size, data) -> avg.apply(size, data.mapToDouble(v -> unsignedLongToDouble(NumericUtils.asLongUnsigned(v))))
|
||||
);
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecks(true, cases, (v, p) -> "numeric");
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvConcatErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvConcatTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvConcat(source, args.get(0), args.get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(true, validPerPosition, signature, (v, p) -> "string"));
|
||||
}
|
||||
}
|
|
@ -67,7 +67,7 @@ public class MvConcatTests extends AbstractScalarFunctionTestCase {
|
|||
}
|
||||
}
|
||||
}
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecks(false, suppliers, (v, p) -> "string");
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, suppliers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvCountErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvCountTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvCount(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> {
|
||||
/*
|
||||
* In general MvCount should support all signatures. While building a
|
||||
* new type you may we to temporarily remove this.
|
||||
*/
|
||||
throw new UnsupportedOperationException("all signatures should be supported");
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertNumberOfCheckedSignatures(int checked) {
|
||||
/*
|
||||
* In general MvCount should support all signatures. While building a
|
||||
* new type you may we to temporarily relax this.
|
||||
*/
|
||||
assertThat("all signatures should be supported", checked, equalTo(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -41,7 +41,7 @@ public class MvCountTests extends AbstractMultivalueFunctionTestCase {
|
|||
cartesianPoints(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count())));
|
||||
geoShape(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count())));
|
||||
cartesianShape(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count())));
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecks(true, cases, (v, p) -> "");
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvDedupeErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvDedupeTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvDedupe(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> {
|
||||
/*
|
||||
* In general MvDedupe should support all signatures. While building a
|
||||
* new type you may we to temporarily remove this.
|
||||
*/
|
||||
throw new UnsupportedOperationException("all signatures should be supported");
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertNumberOfCheckedSignatures(int checked) {
|
||||
/*
|
||||
* In general MvDedupe should support all signatures. While building a
|
||||
* new type you may we to temporarily relax this.
|
||||
*/
|
||||
assertThat("all signatures should be supported", checked, equalTo(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -47,9 +47,7 @@ public class MvDedupeTests extends AbstractMultivalueFunctionTestCase {
|
|||
cartesianShape(cases, "mv_dedupe", "MvDedupe", DataType.CARTESIAN_SHAPE, (size, values) -> getMatcher(values));
|
||||
geoPoints(cases, "mv_dedupe", "MvDedupe", (size, values) -> getMatcher(values));
|
||||
geoShape(cases, "mv_dedupe", "MvDedupe", DataType.GEO_SHAPE, (size, values) -> getMatcher(values));
|
||||
|
||||
// TODO switch extraction to BigInteger so this just works.
|
||||
// unsignedLongs(cases, "mv_dedupe", "MvDedupe", (size, values) -> getMatcher(values));
|
||||
unsignedLongs(cases, "mv_dedupe", "MvDedupe", (size, values) -> getMatcher(values));
|
||||
return parameterSuppliersFromTypedData(anyNullIsNull(false, cases));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvFirstErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvFirstTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvFirst(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> {
|
||||
/*
|
||||
* In general MvFirst should support all signatures. While building a
|
||||
* new type you may we to temporarily remove this.
|
||||
*/
|
||||
throw new UnsupportedOperationException("all signatures should be supported");
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertNumberOfCheckedSignatures(int checked) {
|
||||
/*
|
||||
* In general MvFirst should support all signatures. While building a
|
||||
* new type you may we to temporarily relax this.
|
||||
*/
|
||||
assertThat("all signatures should be supported", checked, equalTo(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -42,16 +42,11 @@ public class MvFirstTests extends AbstractMultivalueFunctionTestCase {
|
|||
cartesianPoints(cases, "mv_first", "MvFirst", DataType.CARTESIAN_POINT, (size, values) -> equalTo(values.findFirst().get()));
|
||||
geoShape(cases, "mv_first", "MvFirst", DataType.GEO_SHAPE, (size, values) -> equalTo(values.findFirst().get()));
|
||||
cartesianShape(cases, "mv_first", "MvFirst", DataType.CARTESIAN_SHAPE, (size, values) -> equalTo(values.findFirst().get()));
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecks(false, cases, (v, p) -> "");
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, Expression field) {
|
||||
return new MvFirst(source, field);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataType expectedType(List<DataType> argTypes) {
|
||||
return argTypes.get(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvLastErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvLastTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvLast(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> {
|
||||
/*
|
||||
* In general MvLast should support all signatures. While building a
|
||||
* new type you may we to temporarily remove this.
|
||||
*/
|
||||
throw new UnsupportedOperationException("all signatures should be supported");
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertNumberOfCheckedSignatures(int checked) {
|
||||
/*
|
||||
* In general MvLast should support all signatures. While building a
|
||||
* new type you may we to temporarily relax this.
|
||||
*/
|
||||
assertThat("all signatures should be supported", checked, equalTo(0));
|
||||
}
|
||||
}
|
|
@ -42,16 +42,11 @@ public class MvLastTests extends AbstractMultivalueFunctionTestCase {
|
|||
cartesianPoints(cases, "mv_last", "MvLast", DataType.CARTESIAN_POINT, (size, values) -> equalTo(values.reduce((f, s) -> s).get()));
|
||||
geoShape(cases, "mv_last", "MvLast", DataType.GEO_SHAPE, (size, values) -> equalTo(values.reduce((f, s) -> s).get()));
|
||||
cartesianShape(cases, "mv_last", "MvLast", DataType.CARTESIAN_SHAPE, (size, values) -> equalTo(values.reduce((f, s) -> s).get()));
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecks(false, cases, (v, p) -> "representable");
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, Expression field) {
|
||||
return new MvLast(source, field);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataType expectedType(List<DataType> argTypes) {
|
||||
return argTypes.get(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvMaxErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvMaxTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvMax(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "representableNonSpatial"));
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ public class MvMaxTests extends AbstractMultivalueFunctionTestCase {
|
|||
unsignedLongs(cases, "mv_max", "MvMax", (size, values) -> equalTo(values.reduce(BigInteger::max).get()));
|
||||
dateTimes(cases, "mv_max", "MvMax", (size, values) -> equalTo(values.max().getAsLong()));
|
||||
dateNanos(cases, "mv_max", "MvMax", DataType.DATE_NANOS, (size, values) -> equalTo(values.max().getAsLong()));
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecks(false, cases, (v, p) -> "representableNonSpatial");
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvMedianAbsoluteDeviationErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvMedianAbsoluteDeviationTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvMedianAbsoluteDeviation(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "numeric"));
|
||||
}
|
||||
}
|
|
@ -122,7 +122,7 @@ public class MvMedianAbsoluteDeviationTests extends AbstractMultivalueFunctionTe
|
|||
)
|
||||
);
|
||||
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecks(false, cases, (v, p) -> "numeric");
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvMedianErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvMedianTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvMedian(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "numeric"));
|
||||
}
|
||||
}
|
|
@ -92,7 +92,7 @@ public class MvMedianTests extends AbstractMultivalueFunctionTestCase {
|
|||
)
|
||||
)
|
||||
);
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecks(false, cases, (v, p) -> "numeric");
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvMinErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvMinTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvMin(source, args.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "representableNonSpatial"));
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ public class MvMinTests extends AbstractMultivalueFunctionTestCase {
|
|||
unsignedLongs(cases, "mv_min", "MvMin", (size, values) -> equalTo(values.reduce(BigInteger::min).get()));
|
||||
dateTimes(cases, "mv_min", "MvMin", (size, values) -> equalTo(values.min().getAsLong()));
|
||||
dateNanos(cases, "mv_min", "MvMin", DataType.DATE_NANOS, (size, values) -> equalTo(values.min().getAsLong()));
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecks(false, cases, (v, p) -> "representableNonSpatial");
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvSliceErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvSliceTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvSlice(source, args.get(0), args.get(1), args.size() > 2 ? args.get(2) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(true, validPerPosition, signature, (v, p) -> switch (p) {
|
||||
case 1, 2 -> "integer";
|
||||
default -> throw new UnsupportedOperationException();
|
||||
}));
|
||||
}
|
||||
}
|
|
@ -16,9 +16,11 @@ import org.elasticsearch.geo.ShapeTestUtils;
|
|||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.core.util.NumericUtils;
|
||||
import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -199,6 +201,24 @@ public class MvSliceTests extends AbstractScalarFunctionTestCase {
|
|||
equalTo(start == end ? field.get(start) : field.subList(start, end + 1))
|
||||
);
|
||||
}));
|
||||
|
||||
suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.INTEGER, DataType.INTEGER), () -> {
|
||||
List<Long> field = randomList(1, 10, () -> randomNonNegativeLong());
|
||||
List<BigInteger> result = field.stream().map(NumericUtils::unsignedLongAsBigInteger).toList();
|
||||
int length = field.size();
|
||||
int start = randomIntBetween(0, length - 1);
|
||||
int end = randomIntBetween(start, length - 1);
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(field, DataType.UNSIGNED_LONG, "field"),
|
||||
new TestCaseSupplier.TypedData(start, DataType.INTEGER, "start"),
|
||||
new TestCaseSupplier.TypedData(end, DataType.INTEGER, "end")
|
||||
),
|
||||
"MvSliceLongEvaluator[field=Attribute[channel=0], start=Attribute[channel=1], end=Attribute[channel=2]]",
|
||||
DataType.UNSIGNED_LONG,
|
||||
equalTo(start == end ? result.get(start) : result.subList(start, end + 1))
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
private static void doubles(List<TestCaseSupplier> suppliers) {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.multivalue;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class MvZipErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(MvZipTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new MvZip(source, args.get(0), args.get(1), args.size() > 2 ? args.get(2) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(true, validPerPosition, signature, (v, p) -> "string"));
|
||||
}
|
||||
}
|
|
@ -52,7 +52,7 @@ public class MvZipTests extends AbstractScalarFunctionTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
return parameterSuppliersFromTypedData(errorsForCasesWithoutExamples(suppliers, (v, p) -> "string"));
|
||||
return parameterSuppliersFromTypedData(suppliers);
|
||||
}
|
||||
|
||||
private static TestCaseSupplier supplier(DataType leftType, DataType rightType, DataType delimType) {
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class ConcatErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
List<TestCaseSupplier> suppliers = paramsToSuppliers(ConcatTests.parameters());
|
||||
// TODO support longer lists. Though this thing has 100s so we probably can't do them all.
|
||||
suppliers.removeIf(s -> s.types().size() > 3);
|
||||
return suppliers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new Concat(source, args.get(0), args.subList(1, args.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "string"));
|
||||
}
|
||||
}
|
|
@ -26,7 +26,6 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
|
@ -48,23 +47,6 @@ public class ConcatTests extends AbstractScalarFunctionTestCase {
|
|||
for (int length = 4; length < 100; length++) {
|
||||
suppliers(suppliers, length);
|
||||
}
|
||||
Set<DataType> supported = Set.of(DataType.NULL, DataType.KEYWORD, DataType.TEXT, DataType.SEMANTIC_TEXT);
|
||||
List<Set<DataType>> supportedPerPosition = List.of(supported, supported);
|
||||
for (DataType lhs : DataType.types()) {
|
||||
if (lhs == DataType.NULL || DataType.isRepresentable(lhs) == false) {
|
||||
continue;
|
||||
}
|
||||
for (DataType rhs : DataType.types()) {
|
||||
if (rhs == DataType.NULL || DataType.isRepresentable(rhs) == false) {
|
||||
continue;
|
||||
}
|
||||
if (DataType.isString(lhs) && DataType.isString(rhs)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
suppliers.add(typeErrorSupplier(false, supportedPerPosition, List.of(lhs, rhs), (v, p) -> "string"));
|
||||
}
|
||||
}
|
||||
return parameterSuppliersFromTypedData(suppliers);
|
||||
}
|
||||
|
||||
|
@ -133,7 +115,6 @@ public class ConcatTests extends AbstractScalarFunctionTestCase {
|
|||
return new TestCaseSupplier.TestCase(values, expectedToString, DataType.KEYWORD, equalTo(new BytesRef(expectedValue)));
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -159,11 +140,6 @@ public class ConcatTests extends AbstractScalarFunctionTestCase {
|
|||
fieldValues.add(new BytesRef("dummy"));
|
||||
}
|
||||
Expression expression = build(testCase.getSource(), mix);
|
||||
if (testCase.getExpectedTypeError() != null) {
|
||||
assertTrue("expected unresolved", expression.typeResolved().unresolved());
|
||||
assertThat(expression.typeResolved().message(), equalTo(testCase.getExpectedTypeError()));
|
||||
return;
|
||||
}
|
||||
|
||||
int totalLength = testDataLength();
|
||||
if (totalLength >= Concat.MAX_CONCAT_LENGTH || rarely()) {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class RLikeErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(RLikeTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<List<DataType>> testCandidates(List<TestCaseSupplier> cases, Set<List<DataType>> valid) {
|
||||
/*
|
||||
* We can't support certain signatures, and it's safe not to test them because
|
||||
* you can't even build them.... The building comes directly from the parser
|
||||
* and can only make certain types.
|
||||
*/
|
||||
return super.testCandidates(cases, valid).filter(sig -> sig.get(1) == DataType.KEYWORD)
|
||||
.filter(sig -> sig.size() > 2 && sig.get(2) == DataType.BOOLEAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return RLikeTests.buildRLike(logger, source, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "string"));
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.string;
|
|||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
|
||||
|
@ -25,7 +26,6 @@ import java.util.List;
|
|||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomLiteral;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
@ -69,28 +69,6 @@ public class RLikeTests extends AbstractScalarFunctionTestCase {
|
|||
casesForString(cases, "3 bytes, 1 code point", () -> "☕", false, escapeString, optionalPattern);
|
||||
casesForString(cases, "6 bytes, 2 code points", () -> "❗️", false, escapeString, optionalPattern);
|
||||
casesForString(cases, "100 random code points", () -> randomUnicodeOfCodepointLength(100), true, escapeString, optionalPattern);
|
||||
for (DataType type : DataType.types()) {
|
||||
if (DataType.isString(type) || type == DataType.NULL) {
|
||||
continue;
|
||||
}
|
||||
if (DataType.isRepresentable(type) == false) {
|
||||
continue;
|
||||
}
|
||||
cases.add(
|
||||
new TestCaseSupplier(
|
||||
List.of(type, DataType.KEYWORD, DataType.BOOLEAN),
|
||||
() -> TestCaseSupplier.TestCase.typeError(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(randomLiteral(type).value(), type, "e"),
|
||||
new TestCaseSupplier.TypedData(new BytesRef(randomAlphaOfLength(10)), DataType.KEYWORD, "pattern")
|
||||
.forceLiteral(),
|
||||
new TestCaseSupplier.TypedData(false, DataType.BOOLEAN, "caseInsensitive").forceLiteral()
|
||||
),
|
||||
"argument of [] must be [string], found value [e] type [" + type.typeName() + "]"
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
return parameterSuppliersFromTypedData(cases);
|
||||
}
|
||||
|
||||
|
@ -127,12 +105,12 @@ public class RLikeTests extends AbstractScalarFunctionTestCase {
|
|||
|
||||
private static void cases(List<TestCaseSupplier> cases, String title, Supplier<TextAndPattern> textAndPattern, boolean expected) {
|
||||
for (DataType type : DataType.stringTypes()) {
|
||||
cases.add(new TestCaseSupplier(title + " with " + type.esType(), List.of(type, type, DataType.BOOLEAN), () -> {
|
||||
cases.add(new TestCaseSupplier(title + " with " + type.esType(), List.of(type, DataType.KEYWORD, DataType.BOOLEAN), () -> {
|
||||
TextAndPattern v = textAndPattern.get();
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(new BytesRef(v.text), type, "e"),
|
||||
new TestCaseSupplier.TypedData(new BytesRef(v.pattern), type, "pattern").forceLiteral(),
|
||||
new TestCaseSupplier.TypedData(new BytesRef(v.pattern), DataType.KEYWORD, "pattern").forceLiteral(),
|
||||
new TestCaseSupplier.TypedData(false, DataType.BOOLEAN, "caseInsensitive").forceLiteral()
|
||||
),
|
||||
startsWith("AutomataMatchEvaluator[input=Attribute[channel=0], pattern=digraph Automaton {\n"),
|
||||
|
@ -140,12 +118,12 @@ public class RLikeTests extends AbstractScalarFunctionTestCase {
|
|||
equalTo(expected)
|
||||
);
|
||||
}));
|
||||
cases.add(new TestCaseSupplier(title + " with " + type.esType(), List.of(type, type), () -> {
|
||||
cases.add(new TestCaseSupplier(title + " with " + type.esType(), List.of(type, DataType.KEYWORD), () -> {
|
||||
TextAndPattern v = textAndPattern.get();
|
||||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(new BytesRef(v.text), type, "e"),
|
||||
new TestCaseSupplier.TypedData(new BytesRef(v.pattern), type, "pattern").forceLiteral()
|
||||
new TestCaseSupplier.TypedData(new BytesRef(v.pattern), DataType.KEYWORD, "pattern").forceLiteral()
|
||||
),
|
||||
startsWith("AutomataMatchEvaluator[input=Attribute[channel=0], pattern=digraph Automaton {\n"),
|
||||
DataType.BOOLEAN,
|
||||
|
@ -157,6 +135,10 @@ public class RLikeTests extends AbstractScalarFunctionTestCase {
|
|||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return buildRLike(logger, source, args);
|
||||
}
|
||||
|
||||
static Expression buildRLike(Logger logger, Source source, List<Expression> args) {
|
||||
Expression expression = args.get(0);
|
||||
Literal pattern = (Literal) args.get(1);
|
||||
Literal caseInsensitive = args.size() > 2 ? (Literal) args.get(2) : null;
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.string;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class WildcardLikeErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(WildcardLikeTests.parameters());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<List<DataType>> testCandidates(List<TestCaseSupplier> cases, Set<List<DataType>> valid) {
|
||||
/*
|
||||
* We can't support certain signatures, and it's safe not to test them because
|
||||
* you can't even build them.... The building comes directly from the parser
|
||||
* and can only make certain types.
|
||||
*/
|
||||
return super.testCandidates(cases, valid).filter(sig -> sig.get(1) == DataType.KEYWORD)
|
||||
.filter(sig -> sig.size() > 2 && sig.get(2) == DataType.BOOLEAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return RLikeTests.buildRLike(logger, source, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "string"));
|
||||
}
|
||||
}
|
|
@ -55,7 +55,7 @@ public class WildcardLikeTests extends AbstractScalarFunctionTestCase {
|
|||
|
||||
private static void addCases(List<TestCaseSupplier> suppliers) {
|
||||
for (DataType type : new DataType[] { DataType.KEYWORD, DataType.TEXT, DataType.SEMANTIC_TEXT }) {
|
||||
suppliers.add(new TestCaseSupplier(" with " + type.esType(), List.of(type, type), () -> {
|
||||
suppliers.add(new TestCaseSupplier(" with " + type.esType(), List.of(type, DataType.KEYWORD), () -> {
|
||||
BytesRef str = new BytesRef(randomAlphaOfLength(5));
|
||||
String patternString = randomAlphaOfLength(2);
|
||||
BytesRef pattern = new BytesRef(patternString + "*");
|
||||
|
@ -63,7 +63,7 @@ public class WildcardLikeTests extends AbstractScalarFunctionTestCase {
|
|||
return new TestCaseSupplier.TestCase(
|
||||
List.of(
|
||||
new TestCaseSupplier.TypedData(str, type, "str"),
|
||||
new TestCaseSupplier.TypedData(pattern, type, "pattern").forceLiteral()
|
||||
new TestCaseSupplier.TypedData(pattern, DataType.KEYWORD, "pattern").forceLiteral()
|
||||
),
|
||||
startsWith("AutomataMatchEvaluator[input=Attribute[channel=0], pattern=digraph Automaton {\n"),
|
||||
DataType.BOOLEAN,
|
||||
|
@ -75,6 +75,10 @@ public class WildcardLikeTests extends AbstractScalarFunctionTestCase {
|
|||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return buildWildcardLike(source, args);
|
||||
}
|
||||
|
||||
static Expression buildWildcardLike(Source source, List<Expression> args) {
|
||||
Expression expression = args.get(0);
|
||||
Literal pattern = (Literal) args.get(1);
|
||||
if (args.size() > 2) {
|
||||
|
|
Loading…
Reference in New Issue