diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java index bd0a7635a4653..e6192ffc81fe4 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryRequest.java @@ -50,6 +50,7 @@ public class EsqlQueryRequest extends org.elasticsearch.xpack.core.esql.action.E private TimeValue waitForCompletionTimeout = DEFAULT_WAIT_FOR_COMPLETION; private TimeValue keepAlive = DEFAULT_KEEP_ALIVE; private boolean keepOnCompletion; + private boolean validationOnly; private boolean onSnapshotBuild = Build.current().isSnapshot(); private boolean acceptedPragmaRisks = false; private Boolean allowPartialResults = null; @@ -202,6 +203,14 @@ public void keepOnCompletion(boolean keepOnCompletion) { this.keepOnCompletion = keepOnCompletion; } + public boolean validationOnly() { + return validationOnly; + } + + public void validationOnly(boolean validationOnly) { + this.validationOnly = validationOnly; + } + /** * Add a "table" to the request for use with things like {@code LOOKUP}. */ diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java index e77d7b41aaca6..011d8769b36f4 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/RequestXContent.java @@ -85,6 +85,7 @@ String fields() { static final ParseField WAIT_FOR_COMPLETION_TIMEOUT = new ParseField("wait_for_completion_timeout"); static final ParseField KEEP_ALIVE = new ParseField("keep_alive"); static final ParseField KEEP_ON_COMPLETION = new ParseField("keep_on_completion"); + static final ParseField VALIDATION_ONLY = new ParseField("validation_only"); private static final ObjectParser SYNC_PARSER = objectParserSync(EsqlQueryRequest::syncEsqlQueryRequest); private static final ObjectParser ASYNC_PARSER = objectParserAsync(EsqlQueryRequest::asyncEsqlQueryRequest); @@ -114,6 +115,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.declareBoolean(EsqlQueryRequest::validationOnly, VALIDATION_ONLY); } private static ObjectParser objectParserSync(Supplier supplier) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/TransportEsqlQueryAction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/TransportEsqlQueryAction.java index ab96b0505477d..caf55fc16ea41 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/TransportEsqlQueryAction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/TransportEsqlQueryAction.java @@ -250,7 +250,7 @@ private void innerExecute(Task task, EsqlQueryRequest request, ActionListener { recordCCSTelemetry(task, executionInfo, request, null); - planExecutor.metrics().recordTook(executionInfo.overallTook().millis()); + // planExecutor.metrics().recordTook(executionInfo.overallTook().millis()); listener.onResponse(toResponse(task, request, configuration, result)); }, ex -> { recordCCSTelemetry(task, executionInfo, request, ex); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querylog/EsqlQueryLog.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querylog/EsqlQueryLog.java index cd410c8eba804..cc94dfd2bea39 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querylog/EsqlQueryLog.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querylog/EsqlQueryLog.java @@ -15,6 +15,7 @@ import org.elasticsearch.index.SlowLogFieldProvider; import org.elasticsearch.index.SlowLogFields; import org.elasticsearch.xcontent.json.JsonStringEncoder; +import org.elasticsearch.xpack.esql.action.EsqlExecutionInfo; import org.elasticsearch.xpack.esql.session.Result; import java.nio.charset.StandardCharsets; @@ -66,7 +67,8 @@ public void onQueryPhase(Result esqlResult, String query) { if (esqlResult == null) { return; // TODO review, it happens in some tests, not sure if it's a thing also in prod } - long tookInNanos = esqlResult.executionInfo().overallTook().nanos(); + EsqlExecutionInfo executionResult = esqlResult.executionInfo(); + long tookInNanos = executionResult == null ? 0 : executionResult.overallTook().nanos(); log(() -> Message.of(esqlResult, query, includeUser ? additionalFields.queryFields() : Map.of()), tookInNanos); } 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 7312ddb7da790..5bc1691949278 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 @@ -181,12 +181,13 @@ public void execute(EsqlQueryRequest request, EsqlExecutionInfo executionInfo, P new EsqlCCSUtils.CssPartialErrorsActionListener(executionInfo, listener) { @Override public void onResponse(LogicalPlan analyzedPlan) { - preMapper.preMapper( - analyzedPlan, - listener.delegateFailureAndWrap( - (l, p) -> executeOptimizedPlan(request, executionInfo, planRunner, optimizedPlan(p), l) - ) - ); + preMapper.preMapper(analyzedPlan, listener.delegateFailureAndWrap((l, p) -> { + if (request.validationOnly()) { + l.onResponse(new Result(new ArrayList<>(), new ArrayList<>(), DriverCompletionInfo.EMPTY, null)); + } else { + executeOptimizedPlan(request, executionInfo, planRunner, optimizedPlan(p), l); + } + })); } } );