@@ -173,7 +173,7 @@ public class Analyzer extends ParameterizedRuleExecutor<LogicalPlan, AnalyzerCon
173173 new ResolveInference (),
174174 new ResolveLookupTables (),
175175 new ResolveFunctions (),
176- new ResolveUnionTypesInEsRelation ()
176+ new DateMillisToNanosInEsRelation ()
177177 ),
178178 new Batch <>(
179179 "Resolution" ,
@@ -1665,9 +1665,7 @@ private Expression resolveConvertFunction(ConvertFunction convert, List<FieldAtt
16651665 }
16661666 imf .types ().forEach (type -> {
16671667 if (supportedTypes .contains (type .widenSmallNumeric ())) {
1668- TypeResolutionKey key = new TypeResolutionKey (fa .name (), type );
1669- var concreteConvert = typeSpecificConvert (convert , fa .source (), type , imf );
1670- typeResolutions .put (key , concreteConvert );
1668+ typeResolutions (fa , convert , type , imf , typeResolutions );
16711669 }
16721670 });
16731671 // If all mapped types were resolved, create a new FieldAttribute with the resolved MultiTypeEsField
@@ -1676,53 +1674,36 @@ private Expression resolveConvertFunction(ConvertFunction convert, List<FieldAtt
16761674 return createIfDoesNotAlreadyExist (fa , resolvedField , unionFieldAttributes );
16771675 }
16781676 } else if (convert .field () instanceof FieldAttribute fa
1679- && fa .synthetic () == false // MultiTypeEsField in EsRelation created by ResolveUnionTypesInEsRelation has synthetic = false
1677+ && fa .synthetic () == false // MultiTypeEsField in EsRelation created by DateMillisToNanosInEsRelation has synthetic = false
16801678 && fa .field () instanceof MultiTypeEsField mtf ) {
16811679 // This is an explicit casting of a union typed field that has been converted to MultiTypeEsField in EsRelation by
16821680 // ResolveUnionTypesInEsRelation, it is not necessary to cast it into date_nanos and then do explicit casting.
16831681 if (((Expression ) convert ).dataType () == mtf .getDataType ()) {
1684- // The same data type between implicit(date_nanos) and explicit casting, explicit conversion is not needed
1685- return convert .field ();
1686- } else {
1687- // Data type is different between implicit(date_nanos) and explicit casting, create a new MultiTypeEsField with
1688- // explicit casting type. TODO Is there an easy way to convert one MultiTypeEsField to another MultiTypeEsField?
1689- HashMap <TypeResolutionKey , Expression > typeResolutions = new HashMap <>();
1690- Set <DataType > supportedTypes = convert .supportedTypes ();
1691- Holder <Boolean > conversionSupported = new Holder <>(true );
1692- // Get the type of each field in the multi typed field and check if the explicit conversion is supported
1693- mtf .getIndexToConversionExpressions ().forEach ((indexName , conversionExpression ) -> {
1694- AbstractConvertFunction c = (AbstractConvertFunction ) conversionExpression ;
1695- FieldAttribute fieldAttribute = (FieldAttribute ) c .field ();
1696- DataType type = fieldAttribute .dataType ();
1697- if (supportedTypes .contains (type .widenSmallNumeric ())) {
1698- TypeResolutionKey key = new TypeResolutionKey (fa .name (), type );
1699- var concreteConvert = typeSpecificConvert (convert , fa .source (), fieldAttribute .field ());
1700- typeResolutions .putIfAbsent (key , concreteConvert );
1701- } else {
1702- conversionSupported .set (false );
1703- }
1704- });
1705- // If the conversions are supported, all the data types in a MultiTypeEsField can be cast to the explicit casting
1706- // data type, create a new FieldAttribute with a new MultiTypeEsField, and add it to unionFieldAttributes.
1707- if (conversionSupported .get ()) {
1708- // Build the mapping between index name and conversion expressions, as a MultiTypeEsField does not store the
1709- // mapping between data types and index names,
1710- Map <String , Expression > indexToConversionExpressions = new HashMap <>();
1711- for (Map .Entry <String , Expression > entry : mtf .getIndexToConversionExpressions ().entrySet ()) {
1712- String indexName = entry .getKey ();
1713- AbstractConvertFunction originalConversionFunction = (AbstractConvertFunction ) entry .getValue ();
1714- TypeResolutionKey key = new TypeResolutionKey (fa .name (), originalConversionFunction .field ().dataType ());
1715- Expression newConversionFunction = typeResolutions .get (key );
1716- indexToConversionExpressions .put (indexName , newConversionFunction );
1717- }
1718- MultiTypeEsField multiTypeEsField = new MultiTypeEsField (
1719- fa .name (),
1720- ((Expression ) convert ).dataType (),
1721- false ,
1722- indexToConversionExpressions
1723- );
1724- return createIfDoesNotAlreadyExist (fa , multiTypeEsField , unionFieldAttributes );
1682+ // The same data type between implicit(date_nanos) and explicit casting, explicit conversion is not needed, mark is
1683+ // as synthetic = true as it is an explicit conversion
1684+ return createIfDoesNotAlreadyExist (fa , mtf , unionFieldAttributes );
1685+ }
1686+
1687+ // Data type is different between implicit(date_nanos) and explicit casting, if the conversion is supported, create a
1688+ // new MultiTypeEsField with explicit casting type, and add it to unionFieldAttributes.
1689+ Set <DataType > supportedTypes = convert .supportedTypes ();
1690+ if (supportedTypes .contains (fa .dataType ())) {
1691+ // Build the mapping between index name and conversion expressions
1692+ Map <String , Expression > indexToConversionExpressions = new HashMap <>();
1693+ for (Map .Entry <String , Expression > entry : mtf .getIndexToConversionExpressions ().entrySet ()) {
1694+ String indexName = entry .getKey ();
1695+ AbstractConvertFunction originalConversionFunction = (AbstractConvertFunction ) entry .getValue ();
1696+ Expression originalField = originalConversionFunction .field ();
1697+ Expression newConvertFunction = convertExpression .replaceChildren (Collections .singletonList (originalField ));
1698+ indexToConversionExpressions .put (indexName , newConvertFunction );
17251699 }
1700+ MultiTypeEsField multiTypeEsField = new MultiTypeEsField (
1701+ fa .name (),
1702+ convertExpression .dataType (),
1703+ false ,
1704+ indexToConversionExpressions
1705+ );
1706+ return createIfDoesNotAlreadyExist (fa , multiTypeEsField , unionFieldAttributes );
17261707 }
17271708 } else if (convert .field () instanceof AbstractConvertFunction subConvert ) {
17281709 return convertExpression .replaceChildren (
@@ -1852,7 +1833,7 @@ private static LogicalPlan planWithoutSyntheticAttributes(LogicalPlan plan) {
18521833 /**
18531834 * Cast the union typed fields in EsRelation to date_nanos if they are mixed date and date_nanos types.
18541835 */
1855- private static class ResolveUnionTypesInEsRelation extends Rule <LogicalPlan , LogicalPlan > {
1836+ private static class DateMillisToNanosInEsRelation extends Rule <LogicalPlan , LogicalPlan > {
18561837 @ Override
18571838 public LogicalPlan apply (LogicalPlan plan ) {
18581839 return plan .transformUp (EsRelation .class , relation -> {
@@ -1863,11 +1844,7 @@ public LogicalPlan apply(LogicalPlan plan) {
18631844 if (f .field () instanceof InvalidMappedField imf && imf .types ().stream ().allMatch (DataType ::isDate )) {
18641845 HashMap <ResolveUnionTypes .TypeResolutionKey , Expression > typeResolutions = new HashMap <>();
18651846 var convert = new ToDateNanos (f .source (), f );
1866- imf .types ().forEach (type -> {
1867- ResolveUnionTypes .TypeResolutionKey key = new ResolveUnionTypes .TypeResolutionKey (f .name (), type );
1868- var concreteConvert = ResolveUnionTypes .typeSpecificConvert (convert , f .source (), type , imf );
1869- typeResolutions .put (key , concreteConvert );
1870- });
1847+ imf .types ().forEach (type -> typeResolutions (f , convert , type , imf , typeResolutions ));
18711848 var resolvedField = ResolveUnionTypes .resolvedMultiTypeEsField (f , typeResolutions );
18721849 return new FieldAttribute (f .source (), f .parentName (), f .name (), resolvedField , f .nullable (), f .id (), f .synthetic ());
18731850 }
@@ -1876,4 +1853,16 @@ public LogicalPlan apply(LogicalPlan plan) {
18761853 });
18771854 }
18781855 }
1856+
1857+ private static void typeResolutions (
1858+ FieldAttribute fieldAttribute ,
1859+ ConvertFunction convert ,
1860+ DataType type ,
1861+ InvalidMappedField imf ,
1862+ HashMap <ResolveUnionTypes .TypeResolutionKey , Expression > typeResolutions
1863+ ) {
1864+ ResolveUnionTypes .TypeResolutionKey key = new ResolveUnionTypes .TypeResolutionKey (fieldAttribute .name (), type );
1865+ var concreteConvert = ResolveUnionTypes .typeSpecificConvert (convert , fieldAttribute .source (), type , imf );
1866+ typeResolutions .put (key , concreteConvert );
1867+ }
18791868}
0 commit comments