Skip to content

Commit d4e4d70

Browse files
more tests and validation of data type conversions
1 parent da2bf6f commit d4e4d70

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

x-pack/plugin/esql/qa/testFixtures/src/main/resources/union_types.csv-spec

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2144,9 +2144,9 @@ required_capability: implicit_casting_date_and_date_nanos
21442144

21452145
FROM date_nanos, date_nanos_union_types
21462146
| EVAL a = nanos::date_nanos::datetime
2147+
| WHERE millis < "2023-10-23T13:00:00"
21472148
| MV_EXPAND a
21482149
| SORT a, millis, nanos
2149-
| LIMIT 14
21502150
;
21512151

21522152
warningRegex:evaluation of \[FROM .*date_nanos.*date_nanos_union_types.*\] failed, treating result as null. Only first 20 failures recorded.
@@ -2167,6 +2167,11 @@ millis:date_nanos | nanos:date_nanos
21672167
1999-10-23T12:15:03.360103847Z | [2023-01-23T13:55:01.543Z, 2023-02-23T13:33:34.937Z, 2023-03-23T12:15:03.360Z] | 0 | 2023-03-23T12:15:03.360Z
21682168
2023-10-23T12:15:03.360Z | 2023-10-23T12:15:03.360103847Z | 1698063303360103847 | 2023-10-23T12:15:03.360Z
21692169
2023-10-23T12:15:03.360Z | 2023-10-23T12:15:03.360103847Z | 1698063303360103847 | 2023-10-23T12:15:03.360Z
2170+
2023-10-23T12:15:03.360103847Z | 2023-10-23T12:15:03.360Z | 1698063303360103847 | 2023-10-23T12:15:03.360Z
2171+
2023-10-23T12:15:03.360103847Z | 2023-10-23T12:15:03.360Z | 1698063303360103847 | 2023-10-23T12:15:03.360Z
2172+
2023-10-23T12:27:28.948Z | 2023-10-23T12:27:28.948Z | 1698064048948000000 | 2023-10-23T12:27:28.948Z
2173+
2023-10-23T12:27:28.948Z | 2023-10-23T12:27:28.948Z | 1698064048948000000 | 2023-10-23T12:27:28.948Z
2174+
2023-10-23T12:15:03.360103847Z | null | 1698063303360103847 | null
21702175
;
21712176

21722177
ImplicitCastingMultiTypedMVFieldsEval

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,15 +1697,18 @@ private Expression resolveConvertFunction(ConvertFunction convert, List<FieldAtt
16971697
&& fa.field() instanceof MultiTypeEsField mtf) {
16981698
// This is an explicit casting of a union typed field that has been converted to MultiTypeEsField in EsRelation by
16991699
// DateMillisToNanosInEsRelation, it is not necessary to cast it again to the same type, replace the implicit casting
1700-
// with explicit casting.
1700+
// with explicit casting. However, it is useful to differentiate implicit and explicit casting in some cases, for
1701+
// example, an expression like multiTypeEsField(synthetic=false, date_nanos)::date_nanos::datetime is rewritten to
1702+
// multiTypeEsField(synthetic=true, date_nanos)::datetime, the implicit casting is overwritten by explicit casting and
1703+
// the multiTypeEsField is not casted to datetime directly.
17011704
if (((Expression) convert).dataType() == mtf.getDataType()) {
17021705
return createIfDoesNotAlreadyExist(fa, mtf, unionFieldAttributes);
17031706
}
17041707

17051708
// Data type is different between implicit(date_nanos) and explicit casting, if the conversion is supported, create a
17061709
// new MultiTypeEsField with explicit casting type, and add it to unionFieldAttributes.
17071710
Set<DataType> supportedTypes = convert.supportedTypes();
1708-
if (supportedTypes.contains(fa.dataType())) {
1711+
if (supportedTypes.contains(fa.dataType()) && canConvertOriginalTypes(mtf, supportedTypes)) {
17091712
// Build the mapping between index name and conversion expressions
17101713
Map<String, Expression> indexToConversionExpressions = new HashMap<>();
17111714
for (Map.Entry<String, Expression> entry : mtf.getIndexToConversionExpressions().entrySet()) {
@@ -1716,7 +1719,7 @@ private Expression resolveConvertFunction(ConvertFunction convert, List<FieldAtt
17161719
indexToConversionExpressions.put(indexName, newConvertFunction);
17171720
}
17181721
MultiTypeEsField multiTypeEsField = new MultiTypeEsField(
1719-
fa.name(),
1722+
fa.fieldName(),
17201723
convertExpression.dataType(),
17211724
false,
17221725
indexToConversionExpressions
@@ -1767,6 +1770,16 @@ private static MultiTypeEsField resolvedMultiTypeEsField(
17671770
return MultiTypeEsField.resolveFrom(imf, typesToConversionExpressions);
17681771
}
17691772

1773+
private static boolean canConvertOriginalTypes(MultiTypeEsField multiTypeEsField, Set<DataType> supportedTypes) {
1774+
return multiTypeEsField.getIndexToConversionExpressions()
1775+
.values()
1776+
.stream()
1777+
.allMatch(
1778+
e -> e instanceof AbstractConvertFunction convertFunction
1779+
&& supportedTypes.contains(convertFunction.field().dataType().widenSmallNumeric())
1780+
);
1781+
}
1782+
17701783
private static Expression typeSpecificConvert(ConvertFunction convert, Source source, DataType type, InvalidMappedField mtf) {
17711784
EsField field = new EsField(mtf.getName(), type, mtf.getProperties(), mtf.isAggregatable());
17721785
return typeSpecificConvert(convert, source, field);

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/QueryTranslatorTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,5 +436,16 @@ public void testToDateNanos() {
436436
"2020-01-01T00:00:00.000Z","boost":0.0.*""" + """
437437
esql_single_value":\\{"field":"date_and_date_nanos".*"must_not".*"term":\\{"date_and_date_nanos":\\{"value":\
438438
"2025-01-01T00:00:00.000Z","boost":0.0.*"""));
439+
440+
// explicit casting
441+
assertQueryTranslationDateDateNanosUnionTypes(
442+
"""
443+
FROM test* | WHERE date_and_date_nanos::datetime < "2025-12-31" and date_and_date_nanos > "2025-01-01\"""",
444+
stats,
445+
containsString("""
446+
"esql_single_value":{"field":"date_and_date_nanos",\
447+
"next":{"range":{"date_and_date_nanos":{"gt":"2025-01-01T00:00:00.000Z","time_zone":"Z",\
448+
"format":"strict_date_optional_time_nanos","boost":0.0}}}""")
449+
);
439450
}
440451
}

0 commit comments

Comments
 (0)