diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/QueryPlanningBenchmark.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/QueryPlanningBenchmark.java index dd12ce85b3bd8..ebbb12f33d009 100644 --- a/benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/QueryPlanningBenchmark.java +++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/QueryPlanningBenchmark.java @@ -92,7 +92,8 @@ public void setup() { System.nanoTime(), false, AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.getDefault(Settings.EMPTY), - AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.get(Settings.EMPTY) + AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.get(Settings.EMPTY), + null ); var fields = 10_000; diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/EvalBenchmark.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/EvalBenchmark.java index 4c0995bae53c5..cc678b65cf37c 100644 --- a/benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/EvalBenchmark.java +++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/EvalBenchmark.java @@ -373,7 +373,8 @@ private static Configuration configuration() { 0, false, AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_MAX_SIZE.getDefault(Settings.EMPTY), - AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.getDefault(Settings.EMPTY) + AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.getDefault(Settings.EMPTY), + null ); } diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/ConfigurationBuilder.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/ConfigurationBuilder.java index 611b16ad52bea..88b6bf0f147b1 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/ConfigurationBuilder.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/ConfigurationBuilder.java @@ -43,6 +43,8 @@ public class ConfigurationBuilder { private Map> tables; private long queryStartTimeNanos; + private String projectRouting; + public ConfigurationBuilder(Configuration configuration) { clusterName = configuration.clusterName(); username = configuration.username(); @@ -58,6 +60,7 @@ public ConfigurationBuilder(Configuration configuration) { allowPartialResults = configuration.allowPartialResults(); tables = configuration.tables(); queryStartTimeNanos = configuration.queryStartTimeNanos(); + projectRouting = configuration.projectRouting(); } public ConfigurationBuilder clusterName(String clusterName) { @@ -130,6 +133,11 @@ public ConfigurationBuilder queryStartTimeNanos(long queryStartTimeNanos) { return this; } + public ConfigurationBuilder projectRouting(String projectRouting) { + this.projectRouting = projectRouting; + return this; + } + public Configuration build() { return new Configuration( zoneId, @@ -145,7 +153,8 @@ public Configuration build() { queryStartTimeNanos, allowPartialResults, resultTruncationMaxSizeTimeseries, - resultTruncationDefaultSizeTimeseries + resultTruncationDefaultSizeTimeseries, + projectRouting ); } } diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/ConfigurationTestUtils.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/ConfigurationTestUtils.java index af784827be003..8a57e74fa5035 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/ConfigurationTestUtils.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/ConfigurationTestUtils.java @@ -76,7 +76,8 @@ public static Configuration randomConfiguration(String query, Map SYNC_PARSER = objectParserSync(() -> syncEsqlQueryRequest(null)); private static final ObjectParser ASYNC_PARSER = objectParserAsync(() -> asyncEsqlQueryRequest(null)); @@ -121,6 +122,7 @@ private static void objectParserCommon(ObjectParser parser) parser.declareString((request, localeTag) -> request.locale(Locale.forLanguageTag(localeTag)), LOCALE_FIELD); parser.declareBoolean(EsqlQueryRequest::profile, PROFILE_FIELD); parser.declareField((p, r, c) -> new ParseTables(r, p).parseTables(), TABLES_FIELD, ObjectParser.ValueType.OBJECT); + parser.declareString(EsqlQueryRequest::projectRouting, PROJECT_ROUTING); } private static ObjectParser objectParserSync(Supplier supplier) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/capabilities/ConfigurationAware.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/capabilities/ConfigurationAware.java index ae4463dd1a626..c6c8b19383cc3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/capabilities/ConfigurationAware.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/capabilities/ConfigurationAware.java @@ -33,7 +33,8 @@ public interface ConfigurationAware { 0, false, 0, - 0 + 0, + null ); Configuration configuration(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Configuration.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Configuration.java index 35260893790aa..a88cf29855dea 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Configuration.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/Configuration.java @@ -60,6 +60,7 @@ public class Configuration implements Writeable { private final Map> tables; private final long queryStartTimeNanos; + private final String projectRouting; public Configuration( ZoneId zi, @@ -75,7 +76,8 @@ public Configuration( long queryStartTimeNanos, boolean allowPartialResults, int resultTruncationMaxSizeTimeseries, - int resultTruncationDefaultSizeTimeseries + int resultTruncationDefaultSizeTimeseries, + String projectRouting ) { this.zoneId = zi.normalized(); this.now = ZonedDateTime.now(Clock.tick(Clock.system(zoneId), Duration.ofNanos(1))); @@ -93,6 +95,7 @@ public Configuration( assert tables != null; this.queryStartTimeNanos = queryStartTimeNanos; this.allowPartialResults = allowPartialResults; + this.projectRouting = projectRouting; } public Configuration(BlockStreamInput in) throws IOException { @@ -120,6 +123,9 @@ public Configuration(BlockStreamInput in) throws IOException { this.resultTruncationMaxSizeTimeseries = this.resultTruncationMaxSizeRegular; this.resultTruncationDefaultSizeTimeseries = this.resultTruncationDefaultSizeRegular; } + + // not needed on the data nodes for now + this.projectRouting = null; } @Override @@ -233,7 +239,8 @@ public Configuration withoutTables() { queryStartTimeNanos, allowPartialResults, resultTruncationMaxSizeTimeseries, - resultTruncationDefaultSizeTimeseries + resultTruncationDefaultSizeTimeseries, + projectRouting ); } @@ -252,6 +259,10 @@ public boolean allowPartialResults() { return allowPartialResults; } + public String projectRouting() { + return projectRouting; + } + private static void writeQuery(StreamOutput out, String query) throws IOException { if (query.length() > QUERY_COMPRESS_THRESHOLD_CHARS) { // compare on chars to avoid UTF-8 encoding unless actually required out.writeBoolean(true); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java index 36766375cbc85..9883a66d2f6a1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java @@ -202,7 +202,8 @@ public void execute(EsqlQueryRequest request, EsqlExecutionInfo executionInfo, P System.nanoTime(), request.allowPartialResults(), clusterSettings.timeseriesResultTruncationMaxSize(), - clusterSettings.timeseriesResultTruncationDefaultSize() + clusterSettings.timeseriesResultTruncationDefaultSize(), + projectRouting(request, statement) ); FoldContext foldContext = configuration.newFoldContext(); @@ -258,6 +259,18 @@ public void onResponse(Versioned analyzedPlan) { ); } + private String projectRouting(EsqlQueryRequest request, EsqlStatement statement) { + String projectRouting = statement.setting(QuerySettings.PROJECT_ROUTING); + if (projectRouting == null) { + projectRouting = request.projectRouting(); + } + + if (projectRouting != null && crossProjectModeDecider.crossProjectEnabled() == false) { + throw new VerificationException("[project_routing] is only allowed when cross-project search is enabled"); + } + return projectRouting; + } + /** * Execute an analyzed plan. Most code should prefer calling {@link #execute} but * this is public for testing. diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java index b295d04242043..3f655958820cc 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequestTests.java @@ -64,6 +64,7 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; public class EsqlQueryRequestTests extends ESTestCase { @@ -877,6 +878,16 @@ public void testTask() throws IOException { assertThat(json, equalTo(expected)); } + public void testProjectRouting() throws IOException { + String json = """ + { + "query": "FROM test", + "project_routing": "_alias:_origin" + }"""; + EsqlQueryRequest request = parseEsqlQueryRequest(json, randomBoolean()); + assertThat(request.projectRouting(), is("_alias:_origin")); + } + private List randomParameters() { if (randomBoolean()) { return Collections.emptyList(); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DayNameTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DayNameTests.java index 4fe528a12216c..7adb91e571403 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DayNameTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/DayNameTests.java @@ -154,7 +154,8 @@ private Configuration configWithZoneAndLocale(ZoneId zone, Locale locale) { System.nanoTime(), randomBoolean(), AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_MAX_SIZE.getDefault(Settings.EMPTY), - AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.getDefault(Settings.EMPTY) + AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.getDefault(Settings.EMPTY), + null ); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/MonthNameTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/MonthNameTests.java index 698d36232f665..4889fb8db4a83 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/MonthNameTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/date/MonthNameTests.java @@ -154,7 +154,8 @@ private Configuration configWithZoneAndLocale(ZoneId zone, Locale locale) { System.nanoTime(), randomBoolean(), AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_MAX_SIZE.getDefault(Settings.EMPTY), - AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.getDefault(Settings.EMPTY) + AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.getDefault(Settings.EMPTY), + null ); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/EvalMapperTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/EvalMapperTests.java index 92622106d7c3c..b60a9867630d6 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/EvalMapperTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/EvalMapperTests.java @@ -82,7 +82,8 @@ public class EvalMapperTests extends ESTestCase { System.nanoTime(), false, 10000000, - 100000 + 100000, + null ); @ParametersFactory(argumentFormatting = "%1$s") diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlannerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlannerTests.java index d773c070af50e..d86d6747e2981 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlannerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlannerTests.java @@ -370,7 +370,8 @@ private Configuration config() { System.nanoTime(), randomBoolean(), AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_MAX_SIZE.getDefault(null), - AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.getDefault(null) + AnalyzerSettings.QUERY_TIMESERIES_RESULT_TRUNCATION_DEFAULT_SIZE.getDefault(null), + null ); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/session/ConfigurationSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/session/ConfigurationSerializationTests.java index 18cc5970aafa9..3a2d6e619ea69 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/session/ConfigurationSerializationTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/session/ConfigurationSerializationTests.java @@ -104,7 +104,8 @@ protected Configuration mutateInstance(Configuration in) { System.nanoTime(), randomBoolean(), in.resultTruncationMaxSize(true), - in.resultTruncationDefaultSize(true) + in.resultTruncationDefaultSize(true), + null ); } }