2929import org .elasticsearch .xpack .esql .plan .logical .join .Join ;
3030import org .elasticsearch .xpack .esql .plan .logical .join .JoinConfig ;
3131import org .elasticsearch .xpack .esql .plan .logical .join .JoinTypes ;
32+ import org .elasticsearch .xpack .esql .plan .physical .AggregateExec ;
3233import org .elasticsearch .xpack .esql .plan .physical .EnrichExec ;
3334import org .elasticsearch .xpack .esql .plan .physical .ExchangeExec ;
3435import org .elasticsearch .xpack .esql .plan .physical .FragmentExec ;
@@ -202,8 +203,12 @@ private PhysicalPlan mapUnary(UnaryPlan unary) {
202203
203204 private PhysicalPlan mapToFragmentExec (LogicalPlan logical , PhysicalPlan child ) {
204205 Holder <Boolean > hasFragment = new Holder <>(false );
206+ Holder <Boolean > forceLocal = new Holder <>(false );
205207
206208 var childTransformed = child .transformUp (f -> {
209+ if (forceLocal .get ()) {
210+ return f ;
211+ }
207212 // Once we reached FragmentExec, we stuff our Enrich under it
208213 if (f instanceof FragmentExec ) {
209214 hasFragment .set (true );
@@ -216,12 +221,21 @@ private PhysicalPlan mapToFragmentExec(LogicalPlan logical, PhysicalPlan child)
216221 }));
217222 }
218223 if (f instanceof EnrichExec enrichExec ) {
219- // It can only be ANY because COORDINATOR would have errored out earlier, and REMOTE should be under FragmentExec
220- assert enrichExec .mode () == Enrich .Mode .ANY : "enrich must be in ANY mode here" ;
221- return enrichExec .child ();
224+ assert enrichExec .mode () != Enrich .Mode .REMOTE : "Unexpected remote ENRICH when looking for fragment" ;
225+ if (enrichExec .mode () == Enrich .Mode .ANY ) {
226+ return enrichExec .child ();
227+ } else {
228+ forceLocal .set (true );
229+ return f ;
230+ }
222231 }
223232 if (f instanceof UnaryExec unaryExec ) {
224- if (f instanceof LimitExec || f instanceof ExchangeExec || f instanceof TopNExec ) {
233+ if (f instanceof AggregateExec || f instanceof TopNExec ) {
234+ // We can't make a fragment here...
235+ forceLocal .set (true );
236+ return f ;
237+ }
238+ if (f instanceof LimitExec || f instanceof ExchangeExec ) {
225239 return f ;
226240 } else {
227241 return unaryExec .child ();
@@ -230,10 +244,13 @@ private PhysicalPlan mapToFragmentExec(LogicalPlan logical, PhysicalPlan child)
230244 if (f instanceof LookupJoinExec lj ) {
231245 return lj .right ();
232246 }
233- // Currently, it's either UnaryExec or LeafExec. Leaf will either resolve to FragmentExec or we'll ignore it.
234247 return f ;
235248 });
236249
250+ if (forceLocal .get ()) {
251+ return null ;
252+ }
253+
237254 if (hasFragment .get ()) {
238255 return childTransformed ;
239256 }
0 commit comments