|  | 
| 134 | 134 | import static java.util.Collections.emptyList; | 
| 135 | 135 | import static java.util.Collections.singletonList; | 
| 136 | 136 | import static org.elasticsearch.xpack.core.enrich.EnrichPolicy.GEO_MATCH_TYPE; | 
|  | 137 | +import static org.elasticsearch.xpack.esql.action.EsqlCapabilities.Cap.IMPLICIT_CASTING_DATE_AND_DATE_NANOS; | 
| 137 | 138 | import static org.elasticsearch.xpack.esql.core.type.DataType.BOOLEAN; | 
| 138 | 139 | import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; | 
| 139 | 140 | import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS; | 
| @@ -175,7 +176,7 @@ public class Analyzer extends ParameterizedRuleExecutor<LogicalPlan, AnalyzerCon | 
| 175 | 176 |             new ResolveInference(), | 
| 176 | 177 |             new ResolveLookupTables(), | 
| 177 | 178 |             new ResolveFunctions(), | 
| 178 |  | -            new DateMillisToNanosInEsRelation() | 
|  | 179 | +            new DateMillisToNanosInEsRelation(IMPLICIT_CASTING_DATE_AND_DATE_NANOS.isEnabled()) | 
| 179 | 180 |         ), | 
| 180 | 181 |         new Batch<>( | 
| 181 | 182 |             "Resolution", | 
| @@ -1819,10 +1820,6 @@ private static boolean canConvertOriginalTypes(MultiTypeEsField multiTypeEsField | 
| 1819 | 1820 | 
 | 
| 1820 | 1821 |         private static Expression typeSpecificConvert(ConvertFunction convert, Source source, DataType type, InvalidMappedField mtf) { | 
| 1821 | 1822 |             EsField field = new EsField(mtf.getName(), type, mtf.getProperties(), mtf.isAggregatable()); | 
| 1822 |  | -            return typeSpecificConvert(convert, source, field); | 
| 1823 |  | -        } | 
| 1824 |  | - | 
| 1825 |  | -        private static Expression typeSpecificConvert(ConvertFunction convert, Source source, EsField field) { | 
| 1826 | 1823 |             FieldAttribute originalFieldAttr = (FieldAttribute) convert.field(); | 
| 1827 | 1824 |             FieldAttribute resolvedAttr = new FieldAttribute( | 
| 1828 | 1825 |                 source, | 
| @@ -1902,23 +1899,42 @@ private static LogicalPlan planWithoutSyntheticAttributes(LogicalPlan plan) { | 
| 1902 | 1899 |      * Cast the union typed fields in EsRelation to date_nanos if they are mixed date and date_nanos types. | 
| 1903 | 1900 |      */ | 
| 1904 | 1901 |     private static class DateMillisToNanosInEsRelation extends Rule<LogicalPlan, LogicalPlan> { | 
|  | 1902 | + | 
|  | 1903 | +        private final boolean isSnapshot; | 
|  | 1904 | + | 
|  | 1905 | +        DateMillisToNanosInEsRelation(boolean isSnapshot) { | 
|  | 1906 | +            this.isSnapshot = isSnapshot; | 
|  | 1907 | +        } | 
|  | 1908 | + | 
| 1905 | 1909 |         @Override | 
| 1906 | 1910 |         public LogicalPlan apply(LogicalPlan plan) { | 
| 1907 |  | -            return plan.transformUp(EsRelation.class, relation -> { | 
| 1908 |  | -                if (relation.indexMode() == IndexMode.LOOKUP) { | 
| 1909 |  | -                    return relation; | 
| 1910 |  | -                } | 
| 1911 |  | -                return relation.transformExpressionsUp(FieldAttribute.class, f -> { | 
| 1912 |  | -                    if (f.field() instanceof InvalidMappedField imf && imf.types().stream().allMatch(DataType::isDate)) { | 
| 1913 |  | -                        HashMap<ResolveUnionTypes.TypeResolutionKey, Expression> typeResolutions = new HashMap<>(); | 
| 1914 |  | -                        var convert = new ToDateNanos(f.source(), f); | 
| 1915 |  | -                        imf.types().forEach(type -> typeResolutions(f, convert, type, imf, typeResolutions)); | 
| 1916 |  | -                        var resolvedField = ResolveUnionTypes.resolvedMultiTypeEsField(f, typeResolutions); | 
| 1917 |  | -                        return new FieldAttribute(f.source(), f.parentName(), f.name(), resolvedField, f.nullable(), f.id(), f.synthetic()); | 
|  | 1911 | +            if (isSnapshot) { | 
|  | 1912 | +                return plan.transformUp(EsRelation.class, relation -> { | 
|  | 1913 | +                    if (relation.indexMode() == IndexMode.LOOKUP) { | 
|  | 1914 | +                        return relation; | 
| 1918 | 1915 |                     } | 
| 1919 |  | -                    return f; | 
|  | 1916 | +                    return relation.transformExpressionsUp(FieldAttribute.class, f -> { | 
|  | 1917 | +                        if (f.field() instanceof InvalidMappedField imf && imf.types().stream().allMatch(DataType::isDate)) { | 
|  | 1918 | +                            HashMap<ResolveUnionTypes.TypeResolutionKey, Expression> typeResolutions = new HashMap<>(); | 
|  | 1919 | +                            var convert = new ToDateNanos(f.source(), f); | 
|  | 1920 | +                            imf.types().forEach(type -> typeResolutions(f, convert, type, imf, typeResolutions)); | 
|  | 1921 | +                            var resolvedField = ResolveUnionTypes.resolvedMultiTypeEsField(f, typeResolutions); | 
|  | 1922 | +                            return new FieldAttribute( | 
|  | 1923 | +                                f.source(), | 
|  | 1924 | +                                f.parentName(), | 
|  | 1925 | +                                f.name(), | 
|  | 1926 | +                                resolvedField, | 
|  | 1927 | +                                f.nullable(), | 
|  | 1928 | +                                f.id(), | 
|  | 1929 | +                                f.synthetic() | 
|  | 1930 | +                            ); | 
|  | 1931 | +                        } | 
|  | 1932 | +                        return f; | 
|  | 1933 | +                    }); | 
| 1920 | 1934 |                 }); | 
| 1921 |  | -            }); | 
|  | 1935 | +            } else { | 
|  | 1936 | +                return plan; | 
|  | 1937 | +            } | 
| 1922 | 1938 |         } | 
| 1923 | 1939 |     } | 
| 1924 | 1940 | 
 | 
|  | 
0 commit comments