Skip to content

Commit

Permalink
[ES|QL] To_DatePeriod and To_TimeDuration return better error message…
Browse files Browse the repository at this point in the history
…s on union_type fields (elastic#114934)

* better error messages with union_type fields
  • Loading branch information
fang-xing-esql authored Nov 12, 2024
1 parent dd32cb6 commit eb6d47f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 1 deletion.
6 changes: 6 additions & 0 deletions docs/changelog/114934.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 114934
summary: "[ES|QL] To_DatePeriod and To_TimeDuration return better error messages on\
\ `union_type` fields"
area: ES|QL
type: bug
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.elasticsearch.xpack.esql.expression.function.UnsupportedAttribute;
import org.elasticsearch.xpack.esql.expression.function.scalar.EsqlScalarFunction;
import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction;
import org.elasticsearch.xpack.esql.expression.function.scalar.convert.FoldablesConvertFunction;
import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDouble;
import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToInteger;
import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToLong;
Expand Down Expand Up @@ -1226,6 +1227,16 @@ private Expression resolveConvertFunction(AbstractConvertFunction convert, List<
if (convert.field() instanceof FieldAttribute fa && fa.field() instanceof InvalidMappedField imf) {
HashMap<TypeResolutionKey, Expression> typeResolutions = new HashMap<>();
Set<DataType> supportedTypes = convert.supportedTypes();
if (convert instanceof FoldablesConvertFunction fcf) {
// FoldablesConvertFunction does not accept fields as inputs, they only accept constants
String unresolvedMessage = "argument of ["
+ fcf.sourceText()
+ "] must be a constant, received ["
+ Expressions.name(fa)
+ "]";
Expression ua = new UnresolvedAttribute(fa.source(), fa.name(), unresolvedMessage);
return fcf.replaceChildren(Collections.singletonList(ua));
}
imf.types().forEach(type -> {
if (supportedTypes.contains(type.widenSmallNumeric())) {
TypeResolutionKey key = new TypeResolutionKey(fa.name(), type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ protected final TypeResolution resolveType() {

@Override
protected final Map<DataType, BuildFactory> factories() {
// TODO if a union type field is provided as an input, the correct error message is not shown, #112668 is a follow up
// This is used by ResolveUnionTypes, which is expected to be applied to ES fields only
// FoldablesConvertFunction takes only constants as inputs, so this is empty
return Map.of();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,34 @@ public void testUnsupportedAndMultiTypedFields() {
+ " [ip] in [test1, test2, test3] and [2] other indices, [keyword] in [test6]",
error("from test* | where multi_typed is not null", analyzer)
);

for (String functionName : List.of("to_timeduration", "to_dateperiod")) {
String lineNumber = functionName.equalsIgnoreCase("to_timeduration") ? "47" : "45";
String errorType = functionName.equalsIgnoreCase("to_timeduration") ? "time_duration" : "date_period";
assertEquals(
"1:" + lineNumber + ": Cannot use field [unsupported] with unsupported type [flattened]",
error("from test* | eval x = now() + " + functionName + "(unsupported)", analyzer)
);
assertEquals(
"1:" + lineNumber + ": argument of [" + functionName + "(multi_typed)] must be a constant, received [multi_typed]",
error("from test* | eval x = now() + " + functionName + "(multi_typed)", analyzer)
);
assertThat(
error("from test* | eval x = unsupported, y = now() + " + functionName + "(x)", analyzer),
containsString("1:23: Cannot use field [unsupported] with unsupported type [flattened]")
);
assertThat(
error("from test* | eval x = multi_typed, y = now() + " + functionName + "(x)", analyzer),
containsString(
"1:48: argument of ["
+ functionName
+ "(x)] must be ["
+ errorType
+ " or string], "
+ "found value [x] type [unsupported]"
)
);
}
}

public void testRoundFunctionInvalidInputs() {
Expand Down

0 comments on commit eb6d47f

Please sign in to comment.