Skip to content

Commit 0a57e41

Browse files
ioanatiakderusso
authored andcommitted
ES|QL: CCS check for FORK/RERANK/COMPLETION (elastic#129463)
1 parent 64c172c commit 0a57e41

File tree

4 files changed

+49
-19
lines changed

4 files changed

+49
-19
lines changed

x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RequestIndexFilteringTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ public void testIndicesDontExist() throws IOException {
225225
// currently we don't support remote clusters in LOOKUP JOIN
226226
// this check happens before resolving actual indices and results in a different error message
227227
RemoteClusterAware.isRemoteIndexName(pattern)
228-
? allOf(containsString("parsing_exception"), containsString("remote clusters are not supported in LOOKUP JOIN"))
228+
? allOf(containsString("parsing_exception"), containsString("remote clusters are not supported"))
229229
: allOf(containsString("verification_exception"), containsString("Unknown index [foo]"))
230230
);
231231
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/LogicalPlanBuilder.java

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ public PlanFactory visitJoinCommand(EsqlBaseParser.JoinCommandContext ctx) {
586586
if (RemoteClusterAware.isRemoteIndexName(rightPattern)) {
587587
throw new ParsingException(
588588
source(target),
589-
"invalid index pattern [{}], remote clusters are not supported in LOOKUP JOIN",
589+
"invalid index pattern [{}], remote clusters are not supported with LOOKUP JOIN",
590590
rightPattern
591591
);
592592
}
@@ -627,22 +627,26 @@ public PlanFactory visitJoinCommand(EsqlBaseParser.JoinCommandContext ctx) {
627627
}
628628

629629
return p -> {
630-
p.forEachUp(UnresolvedRelation.class, r -> {
631-
for (var leftPattern : Strings.splitStringByCommaToArray(r.indexPattern().indexPattern())) {
632-
if (RemoteClusterAware.isRemoteIndexName(leftPattern)) {
633-
throw new ParsingException(
634-
source(target),
635-
"invalid index pattern [{}], remote clusters are not supported in LOOKUP JOIN",
636-
r.indexPattern().indexPattern()
637-
);
638-
}
639-
}
640-
});
641-
630+
checkForRemoteClusters(p, source(target), "LOOKUP JOIN");
642631
return new LookupJoin(source, p, right, joinFields);
643632
};
644633
}
645634

635+
private void checkForRemoteClusters(LogicalPlan plan, Source source, String commandName) {
636+
plan.forEachUp(UnresolvedRelation.class, r -> {
637+
for (var indexPattern : Strings.splitStringByCommaToArray(r.indexPattern().indexPattern())) {
638+
if (RemoteClusterAware.isRemoteIndexName(indexPattern)) {
639+
throw new ParsingException(
640+
source,
641+
"invalid index pattern [{}], remote clusters are not supported with {}",
642+
r.indexPattern().indexPattern(),
643+
commandName
644+
);
645+
}
646+
}
647+
});
648+
}
649+
646650
@Override
647651
@SuppressWarnings("unchecked")
648652
public PlanFactory visitForkCommand(EsqlBaseParser.ForkCommandContext ctx) {
@@ -651,6 +655,7 @@ public PlanFactory visitForkCommand(EsqlBaseParser.ForkCommandContext ctx) {
651655
throw new ParsingException(source(ctx), "Fork requires at least two branches");
652656
}
653657
return input -> {
658+
checkForRemoteClusters(input, source(ctx), "FORK");
654659
List<LogicalPlan> subPlans = subQueries.stream().map(planFactory -> planFactory.apply(input)).toList();
655660
return new Fork(source(ctx), subPlans, List.of());
656661
};
@@ -748,7 +753,10 @@ public PlanFactory visitRerankCommand(EsqlBaseParser.RerankCommandContext ctx) {
748753

749754
Literal inferenceId = ctx.inferenceId != null ? inferenceId(ctx.inferenceId) : Literal.keyword(source, Rerank.DEFAULT_INFERENCE_ID);
750755

751-
return p -> new Rerank(source, p, inferenceId, queryText, visitRerankFields(ctx.rerankFields()));
756+
return p -> {
757+
checkForRemoteClusters(p, source, "RERANK");
758+
return new Rerank(source, p, inferenceId, queryText, visitRerankFields(ctx.rerankFields()));
759+
};
752760
}
753761

754762
@Override
@@ -760,7 +768,10 @@ public PlanFactory visitCompletionCommand(EsqlBaseParser.CompletionCommandContex
760768
? new UnresolvedAttribute(source, Completion.DEFAULT_OUTPUT_FIELD_NAME)
761769
: visitQualifiedName(ctx.targetField);
762770

763-
return p -> new Completion(source, p, inferenceId, prompt, targetField);
771+
return p -> {
772+
checkForRemoteClusters(p, source, "COMPLETION");
773+
return new Completion(source, p, inferenceId, prompt, targetField);
774+
};
764775
}
765776

766777
public Literal inferenceId(EsqlBaseParser.IdentifierOrParameterContext ctx) {

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plan/logical/Fork.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.elasticsearch.common.io.stream.StreamOutput;
1111
import org.elasticsearch.xpack.esql.analysis.Analyzer;
1212
import org.elasticsearch.xpack.esql.capabilities.PostAnalysisPlanVerificationAware;
13+
import org.elasticsearch.xpack.esql.capabilities.TelemetryAware;
1314
import org.elasticsearch.xpack.esql.common.Failure;
1415
import org.elasticsearch.xpack.esql.common.Failures;
1516
import org.elasticsearch.xpack.esql.core.expression.Attribute;
@@ -32,7 +33,7 @@
3233
* A Fork is a n-ary {@code Plan} where each child is a sub plan, e.g.
3334
* {@code FORK [WHERE content:"fox" ] [WHERE content:"dog"] }
3435
*/
35-
public class Fork extends LogicalPlan implements PostAnalysisPlanVerificationAware {
36+
public class Fork extends LogicalPlan implements PostAnalysisPlanVerificationAware, TelemetryAware {
3637

3738
public static final String FORK_FIELD = "_fork";
3839
private final List<Attribute> output;

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3174,7 +3174,7 @@ public void testInvalidJoinPatterns() {
31743174
var joinPattern = randomIndexPattern(CROSS_CLUSTER, without(WILDCARD_PATTERN), without(INDEX_SELECTOR));
31753175
expectError(
31763176
"FROM " + fromPatterns + " | LOOKUP JOIN " + joinPattern + " ON " + randomIdentifier(),
3177-
"invalid index pattern [" + unquoteIndexPattern(joinPattern) + "], remote clusters are not supported in LOOKUP JOIN"
3177+
"invalid index pattern [" + unquoteIndexPattern(joinPattern) + "], remote clusters are not supported with LOOKUP JOIN"
31783178
);
31793179
}
31803180
{
@@ -3183,7 +3183,7 @@ public void testInvalidJoinPatterns() {
31833183
var joinPattern = randomIndexPattern(without(CROSS_CLUSTER), without(WILDCARD_PATTERN), without(INDEX_SELECTOR));
31843184
expectError(
31853185
"FROM " + fromPatterns + " | LOOKUP JOIN " + joinPattern + " ON " + randomIdentifier(),
3186-
"invalid index pattern [" + unquoteIndexPattern(fromPatterns) + "], remote clusters are not supported in LOOKUP JOIN"
3186+
"invalid index pattern [" + unquoteIndexPattern(fromPatterns) + "], remote clusters are not supported with LOOKUP JOIN"
31873187
);
31883188
}
31893189

@@ -3414,6 +3414,12 @@ public void testInvalidFork() {
34143414
expectError("FROM foo* | FORK ( LIMIT 10 ) ( y+2 )", "line 1:33: mismatched input 'y+2'");
34153415
expectError("FROM foo* | FORK (where true) ()", "line 1:32: mismatched input ')'");
34163416
expectError("FROM foo* | FORK () (where true)", "line 1:19: mismatched input ')'");
3417+
3418+
var fromPatterns = randomIndexPatterns(CROSS_CLUSTER);
3419+
expectError(
3420+
"FROM " + fromPatterns + " | FORK (EVAL a = 1) (EVAL a = 2)",
3421+
"invalid index pattern [" + unquoteIndexPattern(fromPatterns) + "], remote clusters are not supported with FORK"
3422+
);
34173423
}
34183424

34193425
public void testFieldNamesAsCommands() throws Exception {
@@ -3539,6 +3545,12 @@ public void testInvalidRerank() {
35393545
assumeTrue("RERANK requires corresponding capability", EsqlCapabilities.Cap.RERANK.isEnabled());
35403546
expectError("FROM foo* | RERANK ON title WITH inferenceId", "line 1:20: mismatched input 'ON' expecting {QUOTED_STRING");
35413547
expectError("FROM foo* | RERANK \"query text\" WITH inferenceId", "line 1:33: mismatched input 'WITH' expecting 'on'");
3548+
3549+
var fromPatterns = randomIndexPatterns(CROSS_CLUSTER);
3550+
expectError(
3551+
"FROM " + fromPatterns + " | RERANK \"query text\" ON title WITH inferenceId",
3552+
"invalid index pattern [" + unquoteIndexPattern(fromPatterns) + "], remote clusters are not supported with RERANK"
3553+
);
35423554
}
35433555

35443556
public void testCompletionUsingFieldAsPrompt() {
@@ -3589,6 +3601,12 @@ public void testInvalidCompletion() {
35893601
expectError("FROM foo* | COMPLETION completion=prompt WITH", "line 1:46: mismatched input '<EOF>' expecting {");
35903602

35913603
expectError("FROM foo* | COMPLETION completion=prompt", "line 1:41: mismatched input '<EOF>' expecting {");
3604+
3605+
var fromPatterns = randomIndexPatterns(CROSS_CLUSTER);
3606+
expectError(
3607+
"FROM " + fromPatterns + " | COMPLETION prompt_field WITH inferenceId",
3608+
"invalid index pattern [" + unquoteIndexPattern(fromPatterns) + "], remote clusters are not supported with COMPLETION"
3609+
);
35923610
}
35933611

35943612
public void testSample() {

0 commit comments

Comments
 (0)