@@ -212,7 +212,7 @@ protected List<Batch<LogicalPlan>> batches() {
212212 return RULES ;
213213 }
214214
215- private static class ResolveTable extends ParameterizedAnalyzerRule <UnresolvedRelation , AnalyzerContext > {
215+ private static class ResolveTable extends ParameterizedAnalyzerRule . Sync <UnresolvedRelation , AnalyzerContext > {
216216
217217 @ Override
218218 protected LogicalPlan rule (UnresolvedRelation plan , AnalyzerContext context ) {
@@ -312,7 +312,7 @@ private static void mappingAsAttributes(List<Attribute> list, Source source, Str
312312 }
313313 }
314314
315- private static class ResolveEnrich extends ParameterizedAnalyzerRule <Enrich , AnalyzerContext > {
315+ private static class ResolveEnrich extends ParameterizedAnalyzerRule . Sync <Enrich , AnalyzerContext > {
316316
317317 @ Override
318318 protected LogicalPlan rule (Enrich plan , AnalyzerContext context ) {
@@ -398,7 +398,7 @@ private static NamedExpression createEnrichFieldExpression(
398398 }
399399 }
400400
401- private static class ResolveInference extends ParameterizedAnalyzerRule <InferencePlan <?>, AnalyzerContext > {
401+ private static class ResolveInference extends ParameterizedAnalyzerRule . Sync <InferencePlan <?>, AnalyzerContext > {
402402 @ Override
403403 protected LogicalPlan rule (InferencePlan <?> plan , AnalyzerContext context ) {
404404 assert plan .inferenceId ().resolved () && plan .inferenceId ().foldable ();
@@ -426,7 +426,7 @@ protected LogicalPlan rule(InferencePlan<?> plan, AnalyzerContext context) {
426426 }
427427 }
428428
429- private static class ResolveLookupTables extends ParameterizedAnalyzerRule <Lookup , AnalyzerContext > {
429+ private static class ResolveLookupTables extends ParameterizedAnalyzerRule . Sync <Lookup , AnalyzerContext > {
430430
431431 @ Override
432432 protected LogicalPlan rule (Lookup lookup , AnalyzerContext context ) {
@@ -474,7 +474,7 @@ private LocalRelation tableMapAsRelation(Source source, Map<String, Column> mapT
474474 }
475475 }
476476
477- public static class ResolveRefs extends ParameterizedAnalyzerRule <LogicalPlan , AnalyzerContext > {
477+ public static class ResolveRefs extends ParameterizedAnalyzerRule . Sync <LogicalPlan , AnalyzerContext > {
478478 @ Override
479479 protected LogicalPlan rule (LogicalPlan plan , AnalyzerContext context ) {
480480 if (plan .childrenResolved () == false ) {
@@ -1286,7 +1286,7 @@ private static Attribute handleSpecialFields(UnresolvedAttribute u, Attribute na
12861286 return named .withLocation (u .source ());
12871287 }
12881288
1289- private static class ResolveFunctions extends ParameterizedAnalyzerRule <LogicalPlan , AnalyzerContext > {
1289+ private static class ResolveFunctions extends ParameterizedAnalyzerRule . Sync <LogicalPlan , AnalyzerContext > {
12901290
12911291 @ Override
12921292 protected LogicalPlan rule (LogicalPlan plan , AnalyzerContext context ) {
@@ -1319,7 +1319,7 @@ public static org.elasticsearch.xpack.esql.core.expression.function.Function res
13191319 }
13201320 }
13211321
1322- private static class AddImplicitLimit extends ParameterizedRule <LogicalPlan , LogicalPlan , AnalyzerContext > {
1322+ private static class AddImplicitLimit extends ParameterizedRule . Sync <LogicalPlan , LogicalPlan , AnalyzerContext > {
13231323 @ Override
13241324 public LogicalPlan apply (LogicalPlan logicalPlan , AnalyzerContext context ) {
13251325 List <LogicalPlan > limits = logicalPlan .collectFirstChildren (Limit .class ::isInstance );
@@ -1338,7 +1338,7 @@ public LogicalPlan apply(LogicalPlan logicalPlan, AnalyzerContext context) {
13381338 }
13391339 }
13401340
1341- private static class AddImplicitForkLimit extends ParameterizedRule <LogicalPlan , LogicalPlan , AnalyzerContext > {
1341+ private static class AddImplicitForkLimit extends ParameterizedRule . Sync <LogicalPlan , LogicalPlan , AnalyzerContext > {
13421342 private final AddImplicitLimit addImplicitLimit = new AddImplicitLimit ();
13431343
13441344 @ Override
@@ -1386,7 +1386,7 @@ private BitSet gatherPreAnalysisMetrics(LogicalPlan plan, BitSet b) {
13861386 * </ul>
13871387 * Coalesce(Int, Long) will NOT be converted to Coalesce(Long, Long) or Coalesce(Int, Int).
13881388 */
1389- private static class ImplicitCasting extends ParameterizedRule <LogicalPlan , LogicalPlan , AnalyzerContext > {
1389+ private static class ImplicitCasting extends ParameterizedRule . Sync <LogicalPlan , LogicalPlan , AnalyzerContext > {
13901390 @ Override
13911391 public LogicalPlan apply (LogicalPlan plan , AnalyzerContext context ) {
13921392 // do implicit casting for function arguments
@@ -1634,15 +1634,16 @@ private static Expression processVectorFunction(org.elasticsearch.xpack.esql.cor
16341634 }
16351635
16361636 /**
1637- * The EsqlIndexResolver will create InvalidMappedField instances for fields that are ambiguous (i.e. have multiple mappings).
1638- * During {@link ResolveRefs} we do not convert these to UnresolvedAttribute instances, as we want to first determine if they can
1639- * instead be handled by conversion functions within the query. This rule looks for matching conversion functions and converts
1640- * those fields into MultiTypeEsField, which encapsulates the knowledge of how to convert these into a single type.
1641- * This knowledge will be used later in generating the FieldExtractExec with built-in type conversion.
1642- * Any fields which could not be resolved by conversion functions will be converted to UnresolvedAttribute instances in a later rule
1643- * (See {@link UnionTypesCleanup} below).
1637+ * {@link ResolveUnionTypes} creates new, synthetic attributes for union types:
1638+ * If there was no {@code AbstractConvertFunction} that resolved multi-type fields in the {@link ResolveUnionTypes} rule,
1639+ * then there could still be some {@code FieldAttribute}s that contain unresolved {@link MultiTypeEsField}s.
1640+ * These need to be converted back to actual {@code UnresolvedAttribute} in order for validation to generate appropriate failures.
1641+ * <p>
1642+ * Finally, if {@code client_ip} is present in 2 indices, once with type {@code ip} and once with type {@code keyword},
1643+ * using {@code EVAL x = to_ip(client_ip)} will create a single attribute @{code $$client_ip$converted_to$ip}.
1644+ * This should not spill into the query output, so we drop such attributes at the end.
16441645 */
1645- private static class ResolveUnionTypes extends Rule <LogicalPlan , LogicalPlan > {
1646+ private static class ResolveUnionTypes extends Rule . Sync <LogicalPlan , LogicalPlan > {
16461647
16471648 record TypeResolutionKey (String fieldName , DataType fieldType ) {}
16481649
@@ -1652,6 +1653,7 @@ record TypeResolutionKey(String fieldName, DataType fieldType) {}
16521653 public LogicalPlan apply (LogicalPlan plan ) {
16531654 unionFieldAttributes = new ArrayList <>();
16541655 return plan .transformUp (LogicalPlan .class , p -> p .childrenResolved () == false ? p : doRule (p ));
1656+
16551657 }
16561658
16571659 private LogicalPlan doRule (LogicalPlan plan ) {
@@ -1850,7 +1852,7 @@ private static Expression typeSpecificConvert(ConvertFunction convert, Source so
18501852 * using {@code EVAL x = to_ip(client_ip)} will create a single attribute @{code $$client_ip$converted_to$ip}.
18511853 * This should not spill into the query output, so we drop such attributes at the end.
18521854 */
1853- private static class UnionTypesCleanup extends Rule <LogicalPlan , LogicalPlan > {
1855+ private static class UnionTypesCleanup extends Rule . Sync <LogicalPlan , LogicalPlan > {
18541856 public LogicalPlan apply (LogicalPlan plan ) {
18551857 LogicalPlan planWithCheckedUnionTypes = plan .transformUp (
18561858 LogicalPlan .class ,
@@ -1898,7 +1900,7 @@ private static LogicalPlan planWithoutSyntheticAttributes(LogicalPlan plan) {
18981900 /**
18991901 * Cast the union typed fields in EsRelation to date_nanos if they are mixed date and date_nanos types.
19001902 */
1901- private static class DateMillisToNanosInEsRelation extends Rule <LogicalPlan , LogicalPlan > {
1903+ private static class DateMillisToNanosInEsRelation extends Rule . Sync <LogicalPlan , LogicalPlan > {
19021904
19031905 private final boolean isSnapshot ;
19041906
0 commit comments