@@ -177,7 +177,8 @@ public class Analyzer extends ParameterizedRuleExecutor<LogicalPlan, AnalyzerCon
177
177
new ResolveEnrich (),
178
178
new ResolveInference (),
179
179
new ResolveLookupTables (),
180
- new ResolveFunctions ()
180
+ new ResolveFunctions (),
181
+ new ResolveImplicitlyCastUnionTypes ()
181
182
),
182
183
new Batch <>(
183
184
"Resolution" ,
@@ -188,9 +189,9 @@ public class Analyzer extends ParameterizedRuleExecutor<LogicalPlan, AnalyzerCon
188
189
*/
189
190
new ImplicitCasting (),
190
191
new ResolveRefs (),
191
- new ResolveUnionTypes (), // Must be after ResolveRefs, so union types can be found
192
+ new ResolveUnionTypes () // Must be after ResolveRefs, so union types can be found
192
193
// Must be after ResolveUnionTypes, if there is explicit casting on the union typed fields, implicit casting won't be added
193
- new ImplicitCastingForUnionTypedFields ()
194
+ // new ImplicitCastingForUnionTypedFields()
194
195
),
195
196
new Batch <>("Finish Analysis" , Limiter .ONCE , new AddImplicitLimit (), new AddImplicitForkLimit (), new UnionTypesCleanup ())
196
197
);
@@ -1577,6 +1578,31 @@ private static Expression castStringLiteral(Expression from, DataType target) {
1577
1578
}
1578
1579
}
1579
1580
1581
+ private static class ResolveImplicitlyCastUnionTypes extends Rule <LogicalPlan , LogicalPlan > {
1582
+ @ Override
1583
+ public LogicalPlan apply (LogicalPlan plan ) {
1584
+ return plan .transformUp (EsRelation .class , relation -> relation .transformExpressionsUp (FieldAttribute .class , f -> {
1585
+ if (f .field () instanceof InvalidMappedField imf && imf .types ().stream ().allMatch (DataType ::isDate )) {
1586
+ HashMap <ResolveUnionTypes .TypeResolutionKey , Expression > typeResolutions = new HashMap <>();
1587
+
1588
+ var convert = new ToDateNanos (f .source (), f );
1589
+
1590
+ imf .types ().forEach (type -> {
1591
+ ResolveUnionTypes .TypeResolutionKey key = new ResolveUnionTypes .TypeResolutionKey (f .name (), type );
1592
+ var concreteConvert = ResolveUnionTypes .typeSpecificConvert (convert , f .source (), type , imf );
1593
+ typeResolutions .put (key , concreteConvert );
1594
+ });
1595
+
1596
+ var resolvedField = ResolveUnionTypes .resolvedMultiTypeEsField (f , typeResolutions );
1597
+
1598
+ return new FieldAttribute (f .source (), f .parentName (), f .name (), resolvedField , f .nullable (), f .id (), f .synthetic ());
1599
+ }
1600
+
1601
+ return f ;
1602
+ }));
1603
+ }
1604
+ }
1605
+
1580
1606
/**
1581
1607
* The EsqlIndexResolver will create InvalidMappedField instances for fields that are ambiguous (i.e. have multiple mappings).
1582
1608
* During {@link ResolveRefs} we do not convert these to UnresolvedAttribute instances, as we want to first determine if they can
@@ -1598,7 +1624,7 @@ public LogicalPlan apply(LogicalPlan plan) {
1598
1624
// Collect field attributes from previous runs
1599
1625
plan .forEachUp (EsRelation .class , rel -> {
1600
1626
for (Attribute attr : rel .output ()) {
1601
- if (attr instanceof FieldAttribute fa && fa .field () instanceof MultiTypeEsField ) {
1627
+ if (attr instanceof FieldAttribute fa && fa .field () instanceof MultiTypeEsField && fa . synthetic () ) {
1602
1628
unionFieldAttributes .add (fa );
1603
1629
}
1604
1630
}
@@ -1702,7 +1728,7 @@ private Expression createIfDoesNotAlreadyExist(
1702
1728
}
1703
1729
}
1704
1730
1705
- private MultiTypeEsField resolvedMultiTypeEsField (FieldAttribute fa , HashMap <TypeResolutionKey , Expression > typeResolutions ) {
1731
+ public static MultiTypeEsField resolvedMultiTypeEsField (FieldAttribute fa , HashMap <TypeResolutionKey , Expression > typeResolutions ) {
1706
1732
Map <String , Expression > typesToConversionExpressions = new HashMap <>();
1707
1733
InvalidMappedField imf = (InvalidMappedField ) fa .field ();
1708
1734
imf .getTypesToIndices ().forEach ((typeName , indexNames ) -> {
@@ -1715,7 +1741,7 @@ private MultiTypeEsField resolvedMultiTypeEsField(FieldAttribute fa, HashMap<Typ
1715
1741
return MultiTypeEsField .resolveFrom (imf , typesToConversionExpressions );
1716
1742
}
1717
1743
1718
- private Expression typeSpecificConvert (ConvertFunction convert , Source source , DataType type , InvalidMappedField mtf ) {
1744
+ private static Expression typeSpecificConvert (ConvertFunction convert , Source source , DataType type , InvalidMappedField mtf ) {
1719
1745
EsField field = new EsField (mtf .getName (), type , mtf .getProperties (), mtf .isAggregatable ());
1720
1746
FieldAttribute originalFieldAttr = (FieldAttribute ) convert .field ();
1721
1747
FieldAttribute resolvedAttr = new FieldAttribute (
0 commit comments