12
12
import org .elasticsearch .index .query .QueryBuilder ;
13
13
import org .elasticsearch .index .query .QueryRewriteContext ;
14
14
import org .elasticsearch .index .query .Rewriteable ;
15
+ import org .elasticsearch .xpack .esql .core .expression .Expression ;
15
16
import org .elasticsearch .xpack .esql .core .util .Holder ;
16
17
import org .elasticsearch .xpack .esql .plan .logical .EsRelation ;
18
+ import org .elasticsearch .xpack .esql .plan .logical .Fork ;
17
19
import org .elasticsearch .xpack .esql .plan .logical .LogicalPlan ;
18
20
import org .elasticsearch .xpack .esql .planner .TranslatorHandler ;
19
21
import org .elasticsearch .xpack .esql .plugin .TransportActionServices ;
22
24
import java .io .IOException ;
23
25
import java .util .HashSet ;
24
26
import java .util .Set ;
27
+ import java .util .function .Function ;
28
+ import java .util .stream .Collectors ;
25
29
26
30
/**
27
31
* Some {@link FullTextFunction} implementations such as {@link org.elasticsearch.xpack.esql.expression.function.fulltext.Match}
@@ -34,11 +38,7 @@ public final class QueryBuilderResolver {
34
38
private QueryBuilderResolver () {}
35
39
36
40
public static void resolveQueryBuilders (LogicalPlan plan , TransportActionServices services , ActionListener <LogicalPlan > listener ) {
37
- var hasFullTextFunctions = plan .anyMatch (p -> {
38
- Holder <Boolean > hasFullTextFunction = new Holder <>(false );
39
- p .forEachExpression (FullTextFunction .class , unused -> hasFullTextFunction .set (true ));
40
- return hasFullTextFunction .get ();
41
- });
41
+ var hasFullTextFunctions = hasFullTextFunctions (plan );
42
42
if (hasFullTextFunctions ) {
43
43
Rewriteable .rewriteAndFetch (
44
44
new FullTextFunctionsRewritable (plan ),
@@ -69,12 +69,29 @@ private static Set<String> indexNames(LogicalPlan plan) {
69
69
return indexNames ;
70
70
}
71
71
72
+ private static boolean hasFullTextFunctions (LogicalPlan plan ) {
73
+ return plan .anyMatch (p -> {
74
+ Holder <Boolean > hasFullTextFunction = new Holder <>(false );
75
+ p .forEachExpression (FullTextFunction .class , unused -> hasFullTextFunction .set (true ));
76
+
77
+ if (p instanceof Fork fork ) {
78
+ fork .subPlans ().forEach (subPlan -> {
79
+ if (hasFullTextFunctions (subPlan )) {
80
+ hasFullTextFunction .set (true );
81
+ }
82
+ });
83
+ }
84
+
85
+ return hasFullTextFunction .get ();
86
+ });
87
+ }
88
+
72
89
private record FullTextFunctionsRewritable (LogicalPlan plan ) implements Rewriteable <QueryBuilderResolver .FullTextFunctionsRewritable > {
73
90
@ Override
74
91
public FullTextFunctionsRewritable rewrite (QueryRewriteContext ctx ) throws IOException {
75
92
Holder <IOException > exceptionHolder = new Holder <>();
76
93
Holder <Boolean > updated = new Holder <>(false );
77
- LogicalPlan newPlan = plan . transformExpressionsDown ( FullTextFunction . class , f -> {
94
+ LogicalPlan newPlan = transformPlan ( plan , f -> {
78
95
QueryBuilder builder = f .queryBuilder (), initial = builder ;
79
96
builder = builder == null ? f .asQuery (TranslatorHandler .TRANSLATOR_HANDLER ).toQueryBuilder () : builder ;
80
97
try {
@@ -91,5 +108,15 @@ public FullTextFunctionsRewritable rewrite(QueryRewriteContext ctx) throws IOExc
91
108
}
92
109
return updated .get () ? new FullTextFunctionsRewritable (newPlan ) : this ;
93
110
}
111
+
112
+ private LogicalPlan transformPlan (LogicalPlan plan , Function <FullTextFunction , ? extends Expression > rule ) {
113
+ return plan .transformExpressionsDown (FullTextFunction .class , rule ).transformDown (Fork .class , fork -> {
114
+ var subPlans = fork .subPlans ()
115
+ .stream ()
116
+ .map (subPlan -> subPlan .transformExpressionsDown (FullTextFunction .class , rule ))
117
+ .collect (Collectors .toList ());
118
+ return new Fork (fork .source (), fork .child (), subPlans );
119
+ });
120
+ }
94
121
}
95
122
}
0 commit comments