From 77101fcf4e7ac47bd8d298eda1f6359f47c3c3e0 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 11 Apr 2025 11:33:14 +0200 Subject: [PATCH 01/58] Merge --- .../elasticsearch/xpack/esql/action/EsqlCapabilities.java | 7 ++++++- .../esql/expression/function/EsqlFunctionRegistry.java | 5 +++-- .../expression/function/fulltext/FullTextWritables.java | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index 2ece0fdc92d11..82e37ba9cd516 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -984,7 +984,12 @@ public enum Cap { /** * Support avg_over_time aggregation that gets evaluated per time-series */ - AVG_OVER_TIME(Build.current().isSnapshot()); + AVG_OVER_TIME(Build.current().isSnapshot()), + + /** + * chicken_score ES|QL function + */ + CHICKEN_SCORE(Build.current().isSnapshot()); private final boolean enabled; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index 764f83a67e925..0e7e951ca2c73 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -34,6 +34,7 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.Top; import org.elasticsearch.xpack.esql.expression.function.aggregate.Values; import org.elasticsearch.xpack.esql.expression.function.aggregate.WeightedAvg; +import org.elasticsearch.xpack.esql.expression.function.fulltext.ChickenScore; import org.elasticsearch.xpack.esql.expression.function.fulltext.Kql; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; @@ -436,8 +437,8 @@ private static FunctionDefinition[][] snapshotFunctions() { def(Rate.class, Rate::withUnresolvedTimestamp, "rate"), def(MaxOverTime.class, uni(MaxOverTime::new), "max_over_time"), def(AvgOverTime.class, uni(AvgOverTime::new), "avg_over_time"), - def(Term.class, bi(Term::new), "term") } }; - } + def(ChickenScore.class, uni(ChickenScore::new), "chicken_score"), + def(Term.class, bi(Term::new), "term") } };} public EsqlFunctionRegistry snapshotRegistry() { if (Build.current().isSnapshot() == false) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java index 5c0a3857d7783..f52b2185f5d8b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java @@ -28,6 +28,9 @@ public static List getNamedWriteables() { if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { entries.add(Term.ENTRY); } + if (EsqlCapabilities.Cap.CHICKEN_SCORE.isEnabled()) { + entries.add(ChickenScore.ENTRY); + } return Collections.unmodifiableList(entries); } From e2f774de547e3f45c541502fa44c897cf8eeeab7 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Wed, 30 Apr 2025 11:24:09 +0200 Subject: [PATCH 02/58] first chicken_score PoC --- .../xpack/esql/expression/function/EsqlFunctionRegistry.java | 2 +- .../esql/expression/function/fulltext/FullTextFunction.java | 4 ++-- .../esql/expression/function/fulltext/FullTextWritables.java | 3 --- .../xpack/esql/planner/LocalExecutionPlanner.java | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index 7cb67a61397b1..d8ede5bdc0218 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -446,8 +446,8 @@ private static FunctionDefinition[][] snapshotFunctions() { def(Rate.class, Rate::withUnresolvedTimestamp, "rate"), def(MaxOverTime.class, uni(MaxOverTime::new), "max_over_time"), def(AvgOverTime.class, uni(AvgOverTime::new), "avg_over_time"), - def(ChickenScore.class, uni(ChickenScore::new), "chicken_score"), def(LastOverTime.class, LastOverTime::withUnresolvedTimestamp, "last_over_time"), + def(ChickenScore.class, uni(ChickenScore::new), "chicken_score"), def(Term.class, bi(Term::new), "term") } }; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index 994179be9f841..ee973ae178db4 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -227,9 +227,9 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu ); checkFullTextFunctionsParents(condition, failures); } else { - plan.forEachExpression(FullTextFunction.class, ftf -> { + /*plan.forEachExpression(FullTextFunction.class, ftf -> { failures.add(fail(ftf, "[{}] {} is only supported in WHERE commands", ftf.functionName(), ftf.functionType())); - }); + });*/ } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java index d849dffe703fd..7ef632c66d44b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java @@ -27,9 +27,6 @@ public static List getNamedWriteables() { if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { entries.add(Term.ENTRY); } - if (EsqlCapabilities.Cap.CHICKEN_SCORE.isEnabled()) { - entries.add(ChickenScore.ENTRY); - } return Collections.unmodifiableList(entries); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java index f263c2f80e429..cf27da60f78b7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java @@ -461,7 +461,7 @@ private PhysicalOperation planEval(EvalExec eval, LocalExecutionPlannerContext c PhysicalOperation source = plan(eval.child(), context); for (Alias field : eval.fields()) { - var evaluatorSupplier = EvalMapper.toEvaluator(context.foldCtx(), field.child(), source.layout); + var evaluatorSupplier = EvalMapper.toEvaluator(context.foldCtx(), field.child(), source.layout, shardContexts); Layout.Builder layout = source.layout.builder(); layout.append(field.toAttribute()); source = source.with(new EvalOperatorFactory(evaluatorSupplier), layout.build()); From 494f95e1856d0d26d9d686f548b2f2745a3737a4 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Wed, 30 Apr 2025 11:30:55 +0200 Subject: [PATCH 03/58] first chicken_score PoC --- .../esql/plugin/ChickenScoreFunctionIT.java | 294 ++++++++++++++++++ .../function/fulltext/ChickenScore.java | 113 +++++++ 2 files changed, 407 insertions(+) create mode 100644 x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java new file mode 100644 index 0000000000000..6790d69304706 --- /dev/null +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java @@ -0,0 +1,294 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.plugin; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.support.WriteRequest; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.xpack.esql.VerificationException; +import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; +import org.junit.Before; + +import java.util.List; + +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; +import static org.hamcrest.CoreMatchers.containsString; + +//@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") +public class ChickenScoreFunctionIT extends AbstractEsqlIntegTestCase { + + @Before + public void setupIndex() { + createAndPopulateIndex(); + } + + public void testSimpleChickenScoreWithWhereMatch() { + var query = """ + FROM test METADATA _score + | EVAL first_score = chicken_score(match(content, "brown")) + | WHERE match(content, "fox") + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587))); + } + } + + public void testSimpleEvalScoreWithWhereMatch() { + var query = """ + FROM test METADATA _score + | EVAL first_matching = match(content, "brown") + | WHERE match(content, "fox") + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_matching")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "boolean")); + assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, true), List.of(6, 0.9114001989364624, true))); + } + } + + /*public void testCombinedWhereMatch() { + var query = """ + FROM test + | WHERE match(content, "fox") AND id > 5 + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(6))); + } + } + + public void testMultipleMatch() { + var query = """ + FROM test + | WHERE match(content, "fox") AND match(content, "brown") + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(1), List.of(6))); + } + } + + public void testMultipleWhereMatch() { + var query = """ + FROM test + | WHERE match(content, "fox") AND match(content, "brown") + | EVAL summary = CONCAT("document with id: ", to_str(id), "and content: ", content) + | SORT summary + | LIMIT 4 + | WHERE match(content, "brown fox") + | KEEP id + """; + + var error = expectThrows(ElasticsearchException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("[MATCH] function cannot be used after LIMIT")); + } + + public void testNotWhereMatch() { + var query = """ + FROM test + | WHERE NOT match(content, "brown fox") + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(5))); + } + } + + public void testWhereMatchWithScoring() { + var query = """ + FROM test + METADATA _score + | WHERE match(content, "fox") + | KEEP id, _score + | SORT id ASC + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624))); + } + } + + public void testWhereMatchWithScoringDifferentSort() { + + var query = """ + FROM test + METADATA _score + | WHERE match(content, "fox") + | KEEP id, _score + | SORT id DESC + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of(List.of(6, 0.9114001989364624), List.of(1, 1.156558871269226))); + } + } + + public void testWhereMatchWithScoringSortScore() { + var query = """ + FROM test + METADATA _score + | WHERE match(content, "fox") + | KEEP id, _score + | SORT _score DESC + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624))); + } + } + + public void testWhereMatchWithScoringNoSort() { + var query = """ + FROM test + METADATA _score + | WHERE match(content, "fox") + | KEEP id, _score + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValuesInAnyOrder(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624))); + } + } + + public void testNonExistingColumn() { + var query = """ + FROM test + | WHERE match(something, "fox") + """; + + var error = expectThrows(VerificationException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("Unknown column [something]")); + } + + public void testWhereMatchEvalColumn() { + var query = """ + FROM test + | EVAL upper_content = to_upper(content) + | WHERE match(upper_content, "FOX") + | KEEP id + """; + + var error = expectThrows(VerificationException.class, () -> run(query)); + assertThat( + error.getMessage(), + containsString("[MATCH] function cannot operate on [upper_content], which is not a field from an index mapping") + ); + } + + public void testWhereMatchOverWrittenColumn() { + var query = """ + FROM test + | DROP content + | EVAL content = CONCAT("document with ID ", to_str(id)) + | WHERE match(content, "document") + """; + + var error = expectThrows(VerificationException.class, () -> run(query)); + assertThat( + error.getMessage(), + containsString("[MATCH] function cannot operate on [content], which is not a field from an index mapping") + ); + } + + public void testWhereMatchAfterStats() { + var query = """ + FROM test + | STATS count(*) + | WHERE match(content, "fox") + """; + + var error = expectThrows(VerificationException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("Unknown column [content]")); + } + + public void testWhereMatchNotPushedDown() { + var query = """ + FROM test + | WHERE match(content, "fox") OR length(content) < 20 + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(1), List.of(2), List.of(6))); + } + } + + public void testWhereMatchWithRow() { + var query = """ + ROW content = "a brown fox" + | WHERE match(content, "fox") + """; + + var error = expectThrows(ElasticsearchException.class, () -> run(query)); + assertThat( + error.getMessage(), + containsString("line 2:15: [MATCH] function cannot operate on [content], which is not a field from an index mapping") + ); + } + + public void testMatchWithinEval() { + var query = """ + FROM test + | EVAL matches_query = match(content, "fox") + """; + + var error = expectThrows(VerificationException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("[MATCH] function is only supported in WHERE commands")); + }*/ + + private void createAndPopulateIndex() { + var indexName = "test"; + var client = client().admin().indices(); + var CreateRequest = client.prepareCreate(indexName) + .setSettings(Settings.builder().put("index.number_of_shards", 1)) + .setMapping("id", "type=integer", "content", "type=text"); + assertAcked(CreateRequest); + client().prepareBulk() + .add(new IndexRequest(indexName).id("1").source("id", 1, "content", "This is a brown fox")) + .add(new IndexRequest(indexName).id("2").source("id", 2, "content", "This is a brown dog")) + .add(new IndexRequest(indexName).id("3").source("id", 3, "content", "This dog is really brown")) + .add(new IndexRequest(indexName).id("4").source("id", 4, "content", "The dog is brown but this document is very very long")) + .add(new IndexRequest(indexName).id("5").source("id", 5, "content", "There is also a white cat")) + .add(new IndexRequest(indexName).id("6").source("id", 6, "content", "The quick brown fox jumps over the lazy dog")) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .get(); + ensureYellow(indexName); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java new file mode 100644 index 0000000000000..e8a8c474c0acd --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java @@ -0,0 +1,113 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.ScoreOperator; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.expression.function.Function; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.score.ScoreMapper; + +import java.io.IOException; +import java.util.List; + +public class ChickenScore extends Function implements EvaluatorMapper { + + + @FunctionInfo( + returnType = "double", + preview = true, + description = "Scores a full text function. Returns scores for all the matching docs.", + examples = { @Example(file = "chickenscore-function", tag = "chickenscore-with-field") } + ) + public ChickenScore( + Source source, + @Param( + name = "query", + type = { "keyword", "text" }, + description = "full text function." + ) Expression scorableQuery + ) { + this(source, List.of(scorableQuery)); + } + + protected ChickenScore(Source source, List children) { + super(source, children); + } + + @Override + public DataType dataType() { + return DataType.DOUBLE; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new ChickenScore(source(), newChildren); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, ChickenScore::new, children()); + } + + @Override + public String getWriteableName() { + return "chicken_score"; + } + + @Override + public EvalOperator.ExpressionEvaluator.Factory toEvaluator(EvaluatorMapper.ToEvaluator toEvaluator) { + + ScoreOperator.ExpressionScorer.Factory scorerFactory = ScoreMapper.toScorer(children().getFirst(), toEvaluator.shardContexts()); + + return new EvalOperator.ExpressionEvaluator.Factory() { + @Override + public EvalOperator.ExpressionEvaluator get(DriverContext driverContext) { + return new ChickenScorerEvaluatorFactory(scorerFactory).get(driverContext); + } + }; + + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + + } + + private record ChickenScorerEvaluatorFactory(ScoreOperator.ExpressionScorer.Factory scoreFactory) + implements EvalOperator.ExpressionEvaluator.Factory { + + @Override + public EvalOperator.ExpressionEvaluator get(DriverContext context) { + return new EvalOperator.ExpressionEvaluator() { + + @Override + public void close() { + + } + + @Override + public Block eval(Page page) { + ScoreOperator.ExpressionScorer scorer = scoreFactory.get(context); + return scorer.score(page); + } + }; + } + } +} From 8f38eb3bdcd224c7138c0ee2920c6bd3836a4181 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Wed, 30 Apr 2025 09:39:16 +0000 Subject: [PATCH 04/58] [CI] Auto commit changes from spotless --- .../xpack/esql/plugin/ChickenScoreFunctionIT.java | 8 ++++---- .../expression/function/fulltext/ChickenScore.java | 12 ++++-------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java index 6790d69304706..1663074b32410 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java @@ -7,18 +7,15 @@ package org.elasticsearch.xpack.esql.plugin; -import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; import org.junit.Before; import java.util.List; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; -import static org.hamcrest.CoreMatchers.containsString; //@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") public class ChickenScoreFunctionIT extends AbstractEsqlIntegTestCase { @@ -40,7 +37,10 @@ public void testSimpleChickenScoreWithWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587))); + assertValues( + resp.values(), + List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587)) + ); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java index e8a8c474c0acd..6aac53b06401f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java @@ -27,8 +27,7 @@ import java.io.IOException; import java.util.List; -public class ChickenScore extends Function implements EvaluatorMapper { - +public class ChickenScore extends Function implements EvaluatorMapper { @FunctionInfo( returnType = "double", @@ -38,11 +37,7 @@ public class ChickenScore extends Function implements EvaluatorMapper { ) public ChickenScore( Source source, - @Param( - name = "query", - type = { "keyword", "text" }, - description = "full text function." - ) Expression scorableQuery + @Param(name = "query", type = { "keyword", "text" }, description = "full text function.") Expression scorableQuery ) { this(source, List.of(scorableQuery)); } @@ -91,7 +86,8 @@ public void writeTo(StreamOutput out) throws IOException { } private record ChickenScorerEvaluatorFactory(ScoreOperator.ExpressionScorer.Factory scoreFactory) - implements EvalOperator.ExpressionEvaluator.Factory { + implements + EvalOperator.ExpressionEvaluator.Factory { @Override public EvalOperator.ExpressionEvaluator get(DriverContext context) { From 701fe46c0ab78e7b88c063cf775a7810ecb5d611 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 2 May 2025 13:56:33 +0200 Subject: [PATCH 05/58] more tests, minor fixes --- .../esql/plugin/ChickenScoreFunctionIT.java | 56 ++++++++++++++++++- .../xpack/esql/action/EsqlCapabilities.java | 2 +- .../function/fulltext/ChickenScore.java | 16 ++---- 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java index 6790d69304706..84ef071fd08e6 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java @@ -28,6 +28,22 @@ public void setupIndex() { createAndPopulateIndex(); } + public void testSimpleWhereMatch() { + var query = """ + FROM test METADATA _score + | WHERE match(content, "brown") + | WHERE match(content, "fox") + | KEEP id, _score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); + } + } + public void testSimpleChickenScoreWithWhereMatch() { var query = """ FROM test METADATA _score @@ -40,21 +56,55 @@ public void testSimpleChickenScoreWithWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587))); + assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, 0.2708943784236908), + List.of(6, 0.9114001989364624, 0.21347221732139587))); + } + } + + public void testSimpleChickenScoreAlone() { + var query = """ + FROM test METADATA _score + | EVAL first_score = chicken_score(match(content, "brown")) + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues(resp.values(), List.of(List.of(1, 0.2708943784236908, 0.2708943784236908), + List.of(6, 0.21347221732139587, 0.21347221732139587))); + } + } + + public void testSimpleMatchScoreCopy() { + var query = """ + FROM test METADATA _score + | WHERE match(content, "fox") + | EVAL first_score = _score + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, 1.156558871269226), + List.of(6, 0.9114001989364624, 0.9114001989364624))); } } public void testSimpleEvalScoreWithWhereMatch() { var query = """ FROM test METADATA _score - | EVAL first_matching = match(content, "brown") + | EVAL first_score = match(content, "brown") | WHERE match(content, "fox") | KEEP id, _score, first_score | SORT id """; try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score", "first_matching")); + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "boolean")); assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, true), List.of(6, 0.9114001989364624, true))); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index 5e1145bcc1beb..56874c9fbb0a7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -1042,7 +1042,7 @@ public enum Cap { LAST_OVER_TIME(Build.current().isSnapshot()), /** - * chicken_score ES|QL function + * chicken_score function */ CHICKEN_SCORE(Build.current().isSnapshot()), diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java index e8a8c474c0acd..d3cb04d231097 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java @@ -29,7 +29,6 @@ public class ChickenScore extends Function implements EvaluatorMapper { - @FunctionInfo( returnType = "double", preview = true, @@ -76,18 +75,14 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(EvaluatorMapper.ToEv ScoreOperator.ExpressionScorer.Factory scorerFactory = ScoreMapper.toScorer(children().getFirst(), toEvaluator.shardContexts()); - return new EvalOperator.ExpressionEvaluator.Factory() { - @Override - public EvalOperator.ExpressionEvaluator get(DriverContext driverContext) { - return new ChickenScorerEvaluatorFactory(scorerFactory).get(driverContext); - } - }; + return driverContext -> new ChickenScorerEvaluatorFactory(scorerFactory).get(driverContext); } @Override public void writeTo(StreamOutput out) throws IOException { - + source().writeTo(out); + out.writeNamedWriteableCollection(this.children()); } private record ChickenScorerEvaluatorFactory(ScoreOperator.ExpressionScorer.Factory scoreFactory) @@ -97,14 +92,15 @@ private record ChickenScorerEvaluatorFactory(ScoreOperator.ExpressionScorer.Fact public EvalOperator.ExpressionEvaluator get(DriverContext context) { return new EvalOperator.ExpressionEvaluator() { + private final ScoreOperator.ExpressionScorer scorer = scoreFactory.get(context); + @Override public void close() { - + scorer.close(); } @Override public Block eval(Page page) { - ScoreOperator.ExpressionScorer scorer = scoreFactory.get(context); return scorer.score(page); } }; From 0ed4f70ccf10d91dc9c4d0ab897347752c2fc5dc Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 2 May 2025 14:47:33 +0200 Subject: [PATCH 06/58] minor test fixes --- .../xpack/esql/plugin/ChickenScoreFunctionIT.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java index 84ef071fd08e6..fb07b44546188 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java @@ -7,18 +7,15 @@ package org.elasticsearch.xpack.esql.plugin; -import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; import org.junit.Before; import java.util.List; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; -import static org.hamcrest.CoreMatchers.containsString; //@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") public class ChickenScoreFunctionIT extends AbstractEsqlIntegTestCase { @@ -72,8 +69,9 @@ public void testSimpleChickenScoreAlone() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues(resp.values(), List.of(List.of(1, 0.2708943784236908, 0.2708943784236908), - List.of(6, 0.21347221732139587, 0.21347221732139587))); + assertValues(resp.values(), List.of(List.of(1, 0.0, 0.2708943784236908), List.of(2, 0.0, 0.2708943784236908), + List.of(3, 0.0, 0.2708943784236908), List.of(4, 0.0, 0.19301524758338928), List.of(5, 0.0, 0.0), + List.of(6, 0.0, 0.21347221732139587))); } } From 9e78a737190c41065a607f4e04b140c1e929a32c Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 2 May 2025 14:52:10 +0200 Subject: [PATCH 07/58] spotless --- .../esql/plugin/ChickenScoreFunctionIT.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java index fb07b44546188..f66237e4a456d 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java @@ -53,8 +53,10 @@ public void testSimpleChickenScoreWithWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, 0.2708943784236908), - List.of(6, 0.9114001989364624, 0.21347221732139587))); + assertValues( + resp.values(), + List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587)) + ); } } @@ -69,9 +71,17 @@ public void testSimpleChickenScoreAlone() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues(resp.values(), List.of(List.of(1, 0.0, 0.2708943784236908), List.of(2, 0.0, 0.2708943784236908), - List.of(3, 0.0, 0.2708943784236908), List.of(4, 0.0, 0.19301524758338928), List.of(5, 0.0, 0.0), - List.of(6, 0.0, 0.21347221732139587))); + assertValues( + resp.values(), + List.of( + List.of(1, 0.0, 0.2708943784236908), + List.of(2, 0.0, 0.2708943784236908), + List.of(3, 0.0, 0.2708943784236908), + List.of(4, 0.0, 0.19301524758338928), + List.of(5, 0.0, 0.0), + List.of(6, 0.0, 0.21347221732139587) + ) + ); } } @@ -87,8 +97,10 @@ public void testSimpleMatchScoreCopy() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, 1.156558871269226), - List.of(6, 0.9114001989364624, 0.9114001989364624))); + assertValues( + resp.values(), + List.of(List.of(1, 1.156558871269226, 1.156558871269226), List.of(6, 0.9114001989364624, 0.9114001989364624)) + ); } } From ddb40cd2ffd6e1906ef15ab69e789976515d3dc7 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 8 May 2025 15:09:30 +0200 Subject: [PATCH 08/58] improved tests --- .../esql/plugin/ChickenScoreFunctionIT.java | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java index f66237e4a456d..e71b3d6cd6016 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java @@ -37,11 +37,14 @@ public void testSimpleWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score")); assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); + assertValues(resp.values(), List.of( + List.of(1, 1.4274532794952393), + List.of(6, 1.1248724460601807)) + ); } } - public void testSimpleChickenScoreWithWhereMatch() { + public void testSimpleChickenScoreWhereMatch() { var query = """ FROM test METADATA _score | EVAL first_score = chicken_score(match(content, "brown")) @@ -55,14 +58,18 @@ public void testSimpleChickenScoreWithWhereMatch() { assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); assertValues( resp.values(), - List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587)) + List.of( + List.of(1, 1.156558871269226, 0.2708943784236908), + List.of(6, 0.9114001989364624, 0.21347221732139587)) ); } } - public void testSimpleChickenScoreAlone() { + public void testChickenScorePlusWhereMatch() { var query = """ FROM test METADATA _score + | WHERE match(content, "brown") + | WHERE match(content, "fox") | EVAL first_score = chicken_score(match(content, "brown")) | KEEP id, _score, first_score | SORT id @@ -71,25 +78,17 @@ public void testSimpleChickenScoreAlone() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues( - resp.values(), - List.of( - List.of(1, 0.0, 0.2708943784236908), - List.of(2, 0.0, 0.2708943784236908), - List.of(3, 0.0, 0.2708943784236908), - List.of(4, 0.0, 0.19301524758338928), - List.of(5, 0.0, 0.0), - List.of(6, 0.0, 0.21347221732139587) - ) + assertValues(resp.values(), List.of( + List.of(1, 1.4274532794952393, 0.2708943784236908), + List.of(6, 1.1248724460601807, 0.21347221732139587)) ); } } - public void testSimpleMatchScoreCopy() { + public void testSimpleChickenScoreAlone() { var query = """ FROM test METADATA _score - | WHERE match(content, "fox") - | EVAL first_score = _score + | EVAL first_score = chicken_score(match(content, "brown")) | KEEP id, _score, first_score | SORT id """; @@ -99,7 +98,14 @@ public void testSimpleMatchScoreCopy() { assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); assertValues( resp.values(), - List.of(List.of(1, 1.156558871269226, 1.156558871269226), List.of(6, 0.9114001989364624, 0.9114001989364624)) + List.of( + List.of(1, 0.0, 0.2708943784236908), + List.of(2, 0.0, 0.2708943784236908), + List.of(3, 0.0, 0.2708943784236908), + List.of(4, 0.0, 0.19301524758338928), + List.of(5, 0.0, 0.0), + List.of(6, 0.0, 0.21347221732139587) + ) ); } } @@ -116,7 +122,9 @@ public void testSimpleEvalScoreWithWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "boolean")); - assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, true), List.of(6, 0.9114001989364624, true))); + assertValues(resp.values(), List.of( + List.of(1, 1.156558871269226, true), + List.of(6, 0.9114001989364624, true))); } } From d1e2f1a066d3e09fecc3c350efd4019937033c7b Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Thu, 8 May 2025 13:18:04 +0000 Subject: [PATCH 09/58] [CI] Auto commit changes from spotless --- .../esql/plugin/ChickenScoreFunctionIT.java | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java index e71b3d6cd6016..4a90104ad02c6 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java @@ -37,10 +37,7 @@ public void testSimpleWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score")); assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of( - List.of(1, 1.4274532794952393), - List.of(6, 1.1248724460601807)) - ); + assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); } } @@ -58,9 +55,7 @@ public void testSimpleChickenScoreWhereMatch() { assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); assertValues( resp.values(), - List.of( - List.of(1, 1.156558871269226, 0.2708943784236908), - List.of(6, 0.9114001989364624, 0.21347221732139587)) + List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587)) ); } } @@ -78,9 +73,9 @@ public void testChickenScorePlusWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues(resp.values(), List.of( - List.of(1, 1.4274532794952393, 0.2708943784236908), - List.of(6, 1.1248724460601807, 0.21347221732139587)) + assertValues( + resp.values(), + List.of(List.of(1, 1.4274532794952393, 0.2708943784236908), List.of(6, 1.1248724460601807, 0.21347221732139587)) ); } } @@ -122,9 +117,7 @@ public void testSimpleEvalScoreWithWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double", "boolean")); - assertValues(resp.values(), List.of( - List.of(1, 1.156558871269226, true), - List.of(6, 0.9114001989364624, true))); + assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, true), List.of(6, 0.9114001989364624, true))); } } From ec3b05a0072199a4760098e52a35ce78c1ee7158 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 16 May 2025 12:40:08 -0700 Subject: [PATCH 10/58] missing readFrom --- .../function/fulltext/ChickenScore.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java index 4188657791d2a..478c01423f042 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java @@ -7,6 +7,8 @@ package org.elasticsearch.xpack.esql.expression.function.fulltext; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.Page; @@ -22,6 +24,7 @@ import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; import org.elasticsearch.xpack.esql.score.ScoreMapper; import java.io.IOException; @@ -29,6 +32,14 @@ public class ChickenScore extends Function implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "chicken_score", + ChickenScore::readFrom + ); + + private static final String NAME = "chicken_score"; + @FunctionInfo( returnType = "double", preview = true, @@ -63,7 +74,7 @@ protected NodeInfo info() { @Override public String getWriteableName() { - return "chicken_score"; + return NAME; } @Override @@ -81,6 +92,12 @@ public void writeTo(StreamOutput out) throws IOException { out.writeNamedWriteableCollection(this.children()); } + private static Expression readFrom(StreamInput in) throws IOException { + Source source = Source.readFrom((PlanStreamInput) in); + Expression query = in.readNamedWriteable(Expression.class); + return new ChickenScore(source, query); + } + private record ChickenScorerEvaluatorFactory(ScoreOperator.ExpressionScorer.Factory scoreFactory) implements EvalOperator.ExpressionEvaluator.Factory { From d0c17a4c6c32c9bde2d824c1bf74d154dd0eef6c Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Wed, 21 May 2025 11:10:11 +0200 Subject: [PATCH 11/58] missing function wiring --- .../xpack/esql/plugin/ChickenScoreFunctionIT.java | 2 ++ .../esql/expression/function/fulltext/FullTextWritables.java | 3 +++ 2 files changed, 5 insertions(+) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java index d5bd027658960..25c81bbc4a192 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; import org.junit.Before; +import org.junit.Ignore; import java.util.List; @@ -44,6 +45,7 @@ public void testSimpleWhereMatch() { } } + @Ignore public void testAlternativeWhereMatch() { var query = """ FROM test METADATA _score diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java index 7ef632c66d44b..d849dffe703fd 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java @@ -27,6 +27,9 @@ public static List getNamedWriteables() { if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { entries.add(Term.ENTRY); } + if (EsqlCapabilities.Cap.CHICKEN_SCORE.isEnabled()) { + entries.add(ChickenScore.ENTRY); + } return Collections.unmodifiableList(entries); } From d6b2649a2e1bc6328f9feb19abe789981ab39a7a Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Wed, 21 May 2025 09:17:42 +0000 Subject: [PATCH 12/58] [CI] Auto commit changes from spotless --- .../xpack/esql/plugin/ChickenScoreFunctionIT.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java index 70ac588b5f714..dee9a7258587f 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java @@ -56,10 +56,7 @@ public void testAlternativeWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score")); assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of( - List.of(1, 1.4274532794952393), - List.of(6, 1.1248724460601807)) - ); + assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); } } From 6944207c79d1b4b39d312b2420907602d00aec2d Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 22 May 2025 12:37:17 +0200 Subject: [PATCH 13/58] chicken_score --> score, fixed FTF checks and namedwritable reading --- .../esql/plugin/ChickenScoreFunctionIT.java | 377 ------------------ .../xpack/esql/plugin/ScoreFunctionIT.java | 148 +++++++ .../xpack/esql/action/EsqlCapabilities.java | 4 +- .../function/EsqlFunctionRegistry.java | 4 +- .../function/fulltext/FullTextFunction.java | 16 +- .../function/fulltext/FullTextWritables.java | 4 +- .../{ChickenScore.java => ScoreFunction.java} | 26 +- .../esql/planner/LocalExecutionPlanner.java | 2 +- 8 files changed, 181 insertions(+), 400 deletions(-) delete mode 100644 x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java create mode 100644 x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java rename x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/{ChickenScore.java => ScoreFunction.java} (81%) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java deleted file mode 100644 index 70ac588b5f714..0000000000000 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ChickenScoreFunctionIT.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.plugin; - -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.action.support.WriteRequest; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; -import org.junit.Before; -import org.junit.Ignore; - -import java.util.List; - -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; - -//@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") -public class ChickenScoreFunctionIT extends AbstractEsqlIntegTestCase { - - @Before - public void setupIndex() { - createAndPopulateIndex(); - } - - public void testSimpleWhereMatch() { - var query = """ - FROM test METADATA _score - | WHERE match(content, "brown") - | WHERE match(content, "fox") - | KEEP id, _score - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); - } - } - - @Ignore - public void testAlternativeWhereMatch() { - var query = """ - FROM test METADATA _score - | EVAL s1 = chicken_score(match(content, "brown")) - | WHERE s1 > 0 - | WHERE match(content, "fox") - | KEEP id, _score - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of( - List.of(1, 1.4274532794952393), - List.of(6, 1.1248724460601807)) - ); - } - } - - public void testSimpleChickenScoreWhereMatch() { - var query = """ - FROM test METADATA _score - | EVAL first_score = chicken_score(match(content, "brown")) - | WHERE match(content, "fox") - | KEEP id, _score, first_score - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues( - resp.values(), - List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587)) - ); - } - } - - public void testChickenScorePlusWhereMatch() { - var query = """ - FROM test METADATA _score - | WHERE match(content, "brown") - | WHERE match(content, "fox") - | EVAL first_score = chicken_score(match(content, "brown")) - | KEEP id, _score, first_score - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues( - resp.values(), - List.of(List.of(1, 1.4274532794952393, 0.2708943784236908), List.of(6, 1.1248724460601807, 0.21347221732139587)) - ); - } - } - - public void testSimpleChickenScoreAlone() { - var query = """ - FROM test METADATA _score - | EVAL first_score = chicken_score(match(content, "brown")) - | KEEP id, _score, first_score - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); - assertValues( - resp.values(), - List.of( - List.of(1, 0.0, 0.2708943784236908), - List.of(2, 0.0, 0.2708943784236908), - List.of(3, 0.0, 0.2708943784236908), - List.of(4, 0.0, 0.19301524758338928), - List.of(5, 0.0, 0.0), - List.of(6, 0.0, 0.21347221732139587) - ) - ); - } - } - - public void testSimpleEvalScoreWithWhereMatch() { - var query = """ - FROM test METADATA _score - | EVAL first_score = match(content, "brown") - | WHERE match(content, "fox") - | KEEP id, _score, first_score - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double", "boolean")); - assertValues(resp.values(), List.of(List.of(1, 1.156558871269226, true), List.of(6, 0.9114001989364624, true))); - } - } - - /*public void testCombinedWhereMatch() { - var query = """ - FROM test - | WHERE match(content, "fox") AND id > 5 - | KEEP id - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id")); - assertColumnTypes(resp.columns(), List.of("integer")); - assertValues(resp.values(), List.of(List.of(6))); - } - } - - public void testMultipleMatch() { - var query = """ - FROM test - | WHERE match(content, "fox") AND match(content, "brown") - | KEEP id - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id")); - assertColumnTypes(resp.columns(), List.of("integer")); - assertValues(resp.values(), List.of(List.of(1), List.of(6))); - } - } - - public void testMultipleWhereMatch() { - var query = """ - FROM test - | WHERE match(content, "fox") AND match(content, "brown") - | EVAL summary = CONCAT("document with id: ", to_str(id), "and content: ", content) - | SORT summary - | LIMIT 4 - | WHERE match(content, "brown fox") - | KEEP id - """; - - var error = expectThrows(ElasticsearchException.class, () -> run(query)); - assertThat(error.getMessage(), containsString("[MATCH] function cannot be used after LIMIT")); - } - - public void testNotWhereMatch() { - var query = """ - FROM test - | WHERE NOT match(content, "brown fox") - | KEEP id - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id")); - assertColumnTypes(resp.columns(), List.of("integer")); - assertValues(resp.values(), List.of(List.of(5))); - } - } - - public void testWhereMatchWithScoring() { - var query = """ - FROM test - METADATA _score - | WHERE match(content, "fox") - | KEEP id, _score - | SORT id ASC - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624))); - } - } - - public void testWhereMatchWithScoringDifferentSort() { - - var query = """ - FROM test - METADATA _score - | WHERE match(content, "fox") - | KEEP id, _score - | SORT id DESC - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of(List.of(6, 0.9114001989364624), List.of(1, 1.156558871269226))); - } - } - - public void testWhereMatchWithScoringSortScore() { - var query = """ - FROM test - METADATA _score - | WHERE match(content, "fox") - | KEEP id, _score - | SORT _score DESC - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624))); - } - } - - public void testWhereMatchWithScoringNoSort() { - var query = """ - FROM test - METADATA _score - | WHERE match(content, "fox") - | KEEP id, _score - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValuesInAnyOrder(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624))); - } - } - - public void testNonExistingColumn() { - var query = """ - FROM test - | WHERE match(something, "fox") - """; - - var error = expectThrows(VerificationException.class, () -> run(query)); - assertThat(error.getMessage(), containsString("Unknown column [something]")); - } - - public void testWhereMatchEvalColumn() { - var query = """ - FROM test - | EVAL upper_content = to_upper(content) - | WHERE match(upper_content, "FOX") - | KEEP id - """; - - var error = expectThrows(VerificationException.class, () -> run(query)); - assertThat( - error.getMessage(), - containsString("[MATCH] function cannot operate on [upper_content], which is not a field from an index mapping") - ); - } - - public void testWhereMatchOverWrittenColumn() { - var query = """ - FROM test - | DROP content - | EVAL content = CONCAT("document with ID ", to_str(id)) - | WHERE match(content, "document") - """; - - var error = expectThrows(VerificationException.class, () -> run(query)); - assertThat( - error.getMessage(), - containsString("[MATCH] function cannot operate on [content], which is not a field from an index mapping") - ); - } - - public void testWhereMatchAfterStats() { - var query = """ - FROM test - | STATS count(*) - | WHERE match(content, "fox") - """; - - var error = expectThrows(VerificationException.class, () -> run(query)); - assertThat(error.getMessage(), containsString("Unknown column [content]")); - } - - public void testWhereMatchNotPushedDown() { - var query = """ - FROM test - | WHERE match(content, "fox") OR length(content) < 20 - | KEEP id - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id")); - assertColumnTypes(resp.columns(), List.of("integer")); - assertValues(resp.values(), List.of(List.of(1), List.of(2), List.of(6))); - } - } - - public void testWhereMatchWithRow() { - var query = """ - ROW content = "a brown fox" - | WHERE match(content, "fox") - """; - - var error = expectThrows(ElasticsearchException.class, () -> run(query)); - assertThat( - error.getMessage(), - containsString("line 2:15: [MATCH] function cannot operate on [content], which is not a field from an index mapping") - ); - } - - public void testMatchWithinEval() { - var query = """ - FROM test - | EVAL matches_query = match(content, "fox") - """; - - var error = expectThrows(VerificationException.class, () -> run(query)); - assertThat(error.getMessage(), containsString("[MATCH] function is only supported in WHERE commands")); - }*/ - - private void createAndPopulateIndex() { - var indexName = "test"; - var client = client().admin().indices(); - var CreateRequest = client.prepareCreate(indexName) - .setSettings(Settings.builder().put("index.number_of_shards", 1)) - .setMapping("id", "type=integer", "content", "type=text"); - assertAcked(CreateRequest); - client().prepareBulk() - .add(new IndexRequest(indexName).id("1").source("id", 1, "content", "This is a brown fox")) - .add(new IndexRequest(indexName).id("2").source("id", 2, "content", "This is a brown dog")) - .add(new IndexRequest(indexName).id("3").source("id", 3, "content", "This dog is really brown")) - .add(new IndexRequest(indexName).id("4").source("id", 4, "content", "The dog is brown but this document is very very long")) - .add(new IndexRequest(indexName).id("5").source("id", 5, "content", "There is also a white cat")) - .add(new IndexRequest(indexName).id("6").source("id", 6, "content", "The quick brown fox jumps over the lazy dog")) - .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) - .get(); - ensureYellow(indexName); - } -} diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java new file mode 100644 index 0000000000000..60c251a46faf8 --- /dev/null +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -0,0 +1,148 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.plugin; + +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.support.WriteRequest; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; +import org.junit.Before; +import org.junit.Ignore; + +import java.util.List; + +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; + +//@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") +public class ScoreFunctionIT extends AbstractEsqlIntegTestCase { + + @Before + public void setupIndex() { + createAndPopulateIndex(); + } + + public void testSimpleWhereMatch() { + var query = """ + FROM test METADATA _score + | WHERE match(content, "brown") + | WHERE match(content, "fox") + | KEEP id, _score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); + } + } + + @Ignore + public void testAlternativeWhereMatch() { + var query = """ + FROM test METADATA _score + | EVAL s1 = score(match(content, "brown")) + | WHERE s1 > 0 + | WHERE match(content, "fox") + | KEEP id, _score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of( + List.of(1, 1.4274532794952393), + List.of(6, 1.1248724460601807)) + ); + } + } + + public void testSimpleScoreWhereMatch() { + var query = """ + FROM test METADATA _score + | EVAL first_score = score(match(content, "brown")) + | WHERE match(content, "fox") + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587)) + ); + } + } + + public void testScorePlusWhereMatch() { + var query = """ + FROM test METADATA _score + | WHERE match(content, "brown") + | WHERE match(content, "fox") + | EVAL first_score = score(match(content, "brown")) + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 1.4274532794952393, 0.2708943784236908), List.of(6, 1.1248724460601807, 0.21347221732139587)) + ); + } + } + + public void testSimpleScoreAlone() { + var query = """ + FROM test METADATA _score + | EVAL first_score = score(match(content, "brown")) + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of( + List.of(1, 0.0, 0.2708943784236908), + List.of(2, 0.0, 0.2708943784236908), + List.of(3, 0.0, 0.2708943784236908), + List.of(4, 0.0, 0.19301524758338928), + List.of(5, 0.0, 0.0), + List.of(6, 0.0, 0.21347221732139587) + ) + ); + } + } + + private void createAndPopulateIndex() { + var indexName = "test"; + var client = client().admin().indices(); + var CreateRequest = client.prepareCreate(indexName) + .setSettings(Settings.builder().put("index.number_of_shards", 1)) + .setMapping("id", "type=integer", "content", "type=text"); + assertAcked(CreateRequest); + client().prepareBulk() + .add(new IndexRequest(indexName).id("1").source("id", 1, "content", "This is a brown fox")) + .add(new IndexRequest(indexName).id("2").source("id", 2, "content", "This is a brown dog")) + .add(new IndexRequest(indexName).id("3").source("id", 3, "content", "This dog is really brown")) + .add(new IndexRequest(indexName).id("4").source("id", 4, "content", "The dog is brown but this document is very very long")) + .add(new IndexRequest(indexName).id("5").source("id", 5, "content", "There is also a white cat")) + .add(new IndexRequest(indexName).id("6").source("id", 6, "content", "The quick brown fox jumps over the lazy dog")) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .get(); + ensureYellow(indexName); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index d0e0df4889f34..75c92499e4ce0 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -1048,9 +1048,9 @@ public enum Cap { LAST_OVER_TIME(Build.current().isSnapshot()), /** - * chicken_score function + * score function */ - CHICKEN_SCORE(Build.current().isSnapshot()), + SCORE_FUNCTION(Build.current().isSnapshot()), /** * Support for the SAMPLE command diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index c1393a81253bc..6e8454d0cb7e9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -40,7 +40,7 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.Top; import org.elasticsearch.xpack.esql.expression.function.aggregate.Values; import org.elasticsearch.xpack.esql.expression.function.aggregate.WeightedAvg; -import org.elasticsearch.xpack.esql.expression.function.fulltext.ChickenScore; +import org.elasticsearch.xpack.esql.expression.function.fulltext.ScoreFunction; import org.elasticsearch.xpack.esql.expression.function.fulltext.Kql; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.MultiMatch; @@ -452,7 +452,7 @@ private static FunctionDefinition[][] snapshotFunctions() { def(MinOverTime.class, uni(MinOverTime::new), "min_over_time"), def(AvgOverTime.class, uni(AvgOverTime::new), "avg_over_time"), def(LastOverTime.class, LastOverTime::withUnresolvedTimestamp, "last_over_time"), - def(ChickenScore.class, uni(ChickenScore::new), "chicken_score"), + def(ScoreFunction.class, uni(ScoreFunction::new), ScoreFunction.NAME), def(FirstOverTime.class, FirstOverTime::withUnresolvedTimestamp, "first_over_time"), def(Term.class, bi(Term::new), "term") } }; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index f8777c0a2556a..cc185b4bf5e0d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -50,6 +50,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.Predicate; @@ -229,9 +230,18 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu } else if (plan instanceof Aggregate agg) { checkFullTextFunctionsInAggs(agg, failures); } else { - /*plan.forEachExpression(FullTextFunction.class, ftf -> { - failures.add(fail(ftf, "[{}] {} is only supported in WHERE and STATS commands", ftf.functionName(), ftf.functionType())); - });*/ + // TODO : improve this check, as this is not 100% accurate + AtomicInteger scoredFullTextFunctions = new AtomicInteger(); + plan.forEachExpression(ScoreFunction.class, scoreFunction -> { + plan.forEachExpression(FullTextFunction.class, ftf -> { + scoredFullTextFunctions.getAndIncrement(); + }); + }); + if (scoredFullTextFunctions.get() == 0) { + plan.forEachExpression(FullTextFunction.class, ftf -> { + failures.add(fail(ftf, "[{}] {} is only supported in WHERE and STATS commands", ftf.functionName(), ftf.functionType())); + }); + } } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java index d849dffe703fd..1e83ff9e5b1e2 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java @@ -27,8 +27,8 @@ public static List getNamedWriteables() { if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { entries.add(Term.ENTRY); } - if (EsqlCapabilities.Cap.CHICKEN_SCORE.isEnabled()) { - entries.add(ChickenScore.ENTRY); + if (EsqlCapabilities.Cap.SCORE_FUNCTION.isEnabled()) { + entries.add(ScoreFunction.ENTRY); } return Collections.unmodifiableList(entries); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java similarity index 81% rename from x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java rename to x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java index 478c01423f042..672ea189e5781 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ChickenScore.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java @@ -30,30 +30,30 @@ import java.io.IOException; import java.util.List; -public class ChickenScore extends Function implements EvaluatorMapper { +public class ScoreFunction extends Function implements EvaluatorMapper { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( Expression.class, - "chicken_score", - ChickenScore::readFrom + "score", + ScoreFunction::readFrom ); - private static final String NAME = "chicken_score"; + public static final String NAME = "score"; @FunctionInfo( returnType = "double", preview = true, description = "Scores a full text function. Returns scores for all the matching docs.", - examples = { @Example(file = "chickenscore-function", tag = "chickenscore-with-field") } + examples = { @Example(file = "score-function", tag = "score-with-field") } ) - public ChickenScore( + public ScoreFunction( Source source, @Param(name = "query", type = { "keyword", "text" }, description = "full text function.") Expression scorableQuery ) { this(source, List.of(scorableQuery)); } - protected ChickenScore(Source source, List children) { + protected ScoreFunction(Source source, List children) { super(source, children); } @@ -64,12 +64,12 @@ public DataType dataType() { @Override public Expression replaceChildren(List newChildren) { - return new ChickenScore(source(), newChildren); + return new ScoreFunction(source(), newChildren); } @Override protected NodeInfo info() { - return NodeInfo.create(this, ChickenScore::new, children()); + return NodeInfo.create(this, ScoreFunction::new, children()); } @Override @@ -82,7 +82,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(EvaluatorMapper.ToEv ScoreOperator.ExpressionScorer.Factory scorerFactory = ScoreMapper.toScorer(children().getFirst(), toEvaluator.shardContexts()); - return driverContext -> new ChickenScorerEvaluatorFactory(scorerFactory).get(driverContext); + return driverContext -> new ScorerEvaluatorFactory(scorerFactory).get(driverContext); } @@ -94,11 +94,11 @@ public void writeTo(StreamOutput out) throws IOException { private static Expression readFrom(StreamInput in) throws IOException { Source source = Source.readFrom((PlanStreamInput) in); - Expression query = in.readNamedWriteable(Expression.class); - return new ChickenScore(source, query); + Expression query = in.readOptionalNamedWriteable(Expression.class); + return new ScoreFunction(source, query); } - private record ChickenScorerEvaluatorFactory(ScoreOperator.ExpressionScorer.Factory scoreFactory) + private record ScorerEvaluatorFactory(ScoreOperator.ExpressionScorer.Factory scoreFactory) implements EvalOperator.ExpressionEvaluator.Factory { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java index 7c7ae3a84bfcd..c10969dad2ae5 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java @@ -475,7 +475,7 @@ private PhysicalOperation planEval(EvalExec eval, LocalExecutionPlannerContext c PhysicalOperation source = plan(eval.child(), context); for (Alias field : eval.fields()) { - var evaluatorSupplier = EvalMapper.toEvaluator(context.foldCtx(), field.child(), source.layout, shardContexts); + var evaluatorSupplier = EvalMapper.toEvaluator(context.foldCtx(), field.child(), source.layout, context.shardContexts); Layout.Builder layout = source.layout.builder(); layout.append(field.toAttribute()); source = source.with(new EvalOperatorFactory(evaluatorSupplier), layout.build()); From 994c9de1bd1c954f71850a66154961bbfe2841d7 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 22 May 2025 12:39:15 +0200 Subject: [PATCH 14/58] spotless --- .../elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java | 5 +---- .../esql/expression/function/EsqlFunctionRegistry.java | 2 +- .../expression/function/fulltext/FullTextFunction.java | 8 ++++---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index 60c251a46faf8..4547a5495a6b8 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -56,10 +56,7 @@ public void testAlternativeWhereMatch() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "_score")); assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of( - List.of(1, 1.4274532794952393), - List.of(6, 1.1248724460601807)) - ); + assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index 6e8454d0cb7e9..09b4c366cca54 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -40,11 +40,11 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.Top; import org.elasticsearch.xpack.esql.expression.function.aggregate.Values; import org.elasticsearch.xpack.esql.expression.function.aggregate.WeightedAvg; -import org.elasticsearch.xpack.esql.expression.function.fulltext.ScoreFunction; import org.elasticsearch.xpack.esql.expression.function.fulltext.Kql; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.MultiMatch; import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; +import org.elasticsearch.xpack.esql.expression.function.fulltext.ScoreFunction; import org.elasticsearch.xpack.esql.expression.function.fulltext.Term; import org.elasticsearch.xpack.esql.expression.function.grouping.Bucket; import org.elasticsearch.xpack.esql.expression.function.grouping.Categorize; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index cc185b4bf5e0d..804a0722165c9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -233,13 +233,13 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu // TODO : improve this check, as this is not 100% accurate AtomicInteger scoredFullTextFunctions = new AtomicInteger(); plan.forEachExpression(ScoreFunction.class, scoreFunction -> { - plan.forEachExpression(FullTextFunction.class, ftf -> { - scoredFullTextFunctions.getAndIncrement(); - }); + plan.forEachExpression(FullTextFunction.class, ftf -> { scoredFullTextFunctions.getAndIncrement(); }); }); if (scoredFullTextFunctions.get() == 0) { plan.forEachExpression(FullTextFunction.class, ftf -> { - failures.add(fail(ftf, "[{}] {} is only supported in WHERE and STATS commands", ftf.functionName(), ftf.functionType())); + failures.add( + fail(ftf, "[{}] {} is only supported in WHERE and STATS commands", ftf.functionName(), ftf.functionType()) + ); }); } } From e8229e1de605573a7cad0ac35abbd421f12ab7fb Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 22 May 2025 14:48:33 +0200 Subject: [PATCH 15/58] minor test fix --- .../yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml index affbab8701f82..88fbc5dd4c5fe 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml @@ -123,7 +123,7 @@ setup: - match: {esql.functions.coalesce: $functions_coalesce} - gt: {esql.functions.categorize: $functions_categorize} # Testing for the entire function set isn't feasible, so we just check that we return the correct count as an approximation. - - length: {esql.functions: 142} # check the "sister" test below for a likely update to the same esql.functions length check + - length: {esql.functions: 143} # check the "sister" test below for a likely update to the same esql.functions length check --- "Basic ESQL usage output (telemetry) non-snapshot version": From 2edaef8b9a9f39905be59694609d5c31e731e92b Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 22 May 2025 15:05:55 +0200 Subject: [PATCH 16/58] more tests --- .../xpack/esql/plugin/ScoreFunctionIT.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index 4547a5495a6b8..0f366cc5cdb33 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -10,10 +10,14 @@ import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.CollectionUtils; +import org.elasticsearch.plugins.Plugin; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; +import org.elasticsearch.xpack.kql.KqlPlugin; import org.junit.Before; import org.junit.Ignore; +import java.util.Collection; import java.util.List; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; @@ -99,6 +103,109 @@ public void testScorePlusWhereMatch() { } } + public void testScorePlusWhereKql() { + var query = """ + FROM test METADATA _score + | WHERE kql("brown") + | WHERE match(content, "fox") + | EVAL first_score = score(kql("brown")) + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 1.4274532794952393, 0.2708943784236908), List.of(6, 1.1248724460601807, 0.21347221732139587)) + ); + } + } + + public void testScorePlusWhereQstr() { + var query = """ + FROM test METADATA _score + | WHERE qstr("brown") + | WHERE match(content, "fox") + | EVAL first_score = score(qstr("brown")) + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 1.4274532794952393, 0.2708943784236908), List.of(6, 1.1248724460601807, 0.21347221732139587)) + ); + } + } + + public void testScorePlusWhereQstrAndMatch() { + var query = """ + FROM test METADATA _score + | WHERE qstr("brown") AND match(content, "fox") + | EVAL first_score = score(qstr("brown") AND match(content, "fox")) + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 1.4274532794952393, 1.4274532496929169), List.of(6, 1.1248724460601807, 1.1248724162578583)) + ); + } + } + + public void testScorePlusWhereKqlAndMatch() { + var query = """ + FROM test METADATA _score + | WHERE kql("brown") AND match(content, "fox") + | EVAL first_score = score(kql("brown") AND match(content, "fox")) + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 1.4274532794952393, 1.4274532496929169), List.of(6, 1.1248724460601807, 1.1248724162578583)) + ); + } + } + + public void testScorePlusWhereQstrORMatch() { + var query = """ + FROM test METADATA _score + | WHERE qstr("brown") OR match(content, "fox") + | EVAL first_score = score(qstr("brown") OR match(content, "fox")) + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of( + List.of(1, 1.4274532794952393, 1.4274532496929169), + List.of(2, 0.2708943784236908, 0.2708943784236908), + List.of(3, 0.2708943784236908, 0.2708943784236908), + List.of(4, 0.19301524758338928, 0.19301524758338928), + List.of(6, 1.1248724460601807, 1.1248724162578583) + ) + ); + } + } + public void testSimpleScoreAlone() { var query = """ FROM test METADATA _score @@ -142,4 +249,9 @@ private void createAndPopulateIndex() { .get(); ensureYellow(indexName); } + + @Override + protected Collection> nodePlugins() { + return CollectionUtils.appendToCopy(super.nodePlugins(), KqlPlugin.class); + } } From f0d3b766ac8c1bb7eec6dc37c09e021c1c6967e3 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 22 May 2025 16:04:30 +0200 Subject: [PATCH 17/58] slightly better FTF check for EVAL s = score(...) --- .../function/fulltext/FullTextFunction.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index 804a0722165c9..0a9296fbd1c5c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -46,11 +46,11 @@ import org.elasticsearch.xpack.esql.querydsl.query.TranslationAwareExpressionQuery; import org.elasticsearch.xpack.esql.score.ExpressionScoreMapper; +import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.Predicate; @@ -230,18 +230,24 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu } else if (plan instanceof Aggregate agg) { checkFullTextFunctionsInAggs(agg, failures); } else { - // TODO : improve this check, as this is not 100% accurate - AtomicInteger scoredFullTextFunctions = new AtomicInteger(); - plan.forEachExpression(ScoreFunction.class, scoreFunction -> { - plan.forEachExpression(FullTextFunction.class, ftf -> { scoredFullTextFunctions.getAndIncrement(); }); - }); - if (scoredFullTextFunctions.get() == 0) { - plan.forEachExpression(FullTextFunction.class, ftf -> { + // TODO : improve this check, as this is not so nice :( + List scoredFTFs = new ArrayList<>(); + plan.forEachExpression( + ScoreFunction.class, + scoreFunction -> { plan.forEachExpression(FullTextFunction.class, scoredFTFs::add); } + ); + plan.forEachExpression(FullTextFunction.class, ftf -> { + if (scoredFTFs.remove(ftf) == false) { failures.add( - fail(ftf, "[{}] {} is only supported in WHERE and STATS commands", ftf.functionName(), ftf.functionType()) + fail( + ftf, + "[{}] {} is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + ftf.functionName(), + ftf.functionType() + ) ); - }); - } + } + }); } } From eac33c1bbd8f1bf5bab2dc07e9f47f55a3edd487 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 22 May 2025 16:12:18 +0200 Subject: [PATCH 18/58] improved tests --- .../xpack/esql/plugin/ScoreFunctionIT.java | 101 +++++++++++------- 1 file changed, 65 insertions(+), 36 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index 0f366cc5cdb33..d701e05145acf 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -15,7 +15,6 @@ import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; import org.elasticsearch.xpack.kql.KqlPlugin; import org.junit.Before; -import org.junit.Ignore; import java.util.Collection; import java.util.List; @@ -30,45 +29,52 @@ public void setupIndex() { createAndPopulateIndex(); } - public void testSimpleWhereMatch() { + + public void testScoreDifferentWhereMatch() { var query = """ FROM test METADATA _score - | WHERE match(content, "brown") + | EVAL first_score = score(match(content, "brown")) | WHERE match(content, "fox") - | KEEP id, _score + | KEEP id, _score, first_score | SORT id """; try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587)) + ); } } - @Ignore - public void testAlternativeWhereMatch() { + public void testScoreMultipleWhereMatchMatch() { var query = """ FROM test METADATA _score - | EVAL s1 = score(match(content, "brown")) - | WHERE s1 > 0 + | WHERE match(content, "brown") | WHERE match(content, "fox") - | KEEP id, _score + | EVAL first_score = score(match(content, "brown")) + | KEEP id, _score, first_score | SORT id """; try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id", "_score")); - assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 1.4274532794952393, 0.2708943784236908), List.of(6, 1.1248724460601807, 0.21347221732139587)) + ); } } - public void testSimpleScoreWhereMatch() { + public void testScoreMultipleWhereKqlMatch() { var query = """ FROM test METADATA _score - | EVAL first_score = score(match(content, "brown")) + | WHERE kql("brown") | WHERE match(content, "fox") + | EVAL first_score = score(kql("brown")) | KEEP id, _score, first_score | SORT id """; @@ -78,17 +84,17 @@ public void testSimpleScoreWhereMatch() { assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); assertValues( resp.values(), - List.of(List.of(1, 1.156558871269226, 0.2708943784236908), List.of(6, 0.9114001989364624, 0.21347221732139587)) + List.of(List.of(1, 1.4274532794952393, 0.2708943784236908), List.of(6, 1.1248724460601807, 0.21347221732139587)) ); } } - public void testScorePlusWhereMatch() { + public void testScoreMultipleWhereQstrMatch() { var query = """ FROM test METADATA _score - | WHERE match(content, "brown") + | WHERE qstr("brown") | WHERE match(content, "fox") - | EVAL first_score = score(match(content, "brown")) + | EVAL first_score = score(qstr("brown")) | KEEP id, _score, first_score | SORT id """; @@ -103,12 +109,11 @@ public void testScorePlusWhereMatch() { } } - public void testScorePlusWhereKql() { + public void testScoreSameWhereQstrAndMatch() { var query = """ FROM test METADATA _score - | WHERE kql("brown") - | WHERE match(content, "fox") - | EVAL first_score = score(kql("brown")) + | WHERE qstr("brown") AND match(content, "fox") + | EVAL first_score = score(qstr("brown") AND match(content, "fox")) | KEEP id, _score, first_score | SORT id """; @@ -118,16 +123,15 @@ public void testScorePlusWhereKql() { assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); assertValues( resp.values(), - List.of(List.of(1, 1.4274532794952393, 0.2708943784236908), List.of(6, 1.1248724460601807, 0.21347221732139587)) + List.of(List.of(1, 1.4274532794952393, 1.4274532496929169), List.of(6, 1.1248724460601807, 1.1248724162578583)) ); } } - public void testScorePlusWhereQstr() { + public void testScoreSingleWhereQstrAndMatch() { var query = """ FROM test METADATA _score - | WHERE qstr("brown") - | WHERE match(content, "fox") + | WHERE qstr("brown") AND match(content, "fox") | EVAL first_score = score(qstr("brown")) | KEEP id, _score, first_score | SORT id @@ -143,11 +147,11 @@ public void testScorePlusWhereQstr() { } } - public void testScorePlusWhereQstrAndMatch() { + public void testScoreSameWhereKqlAndMatch() { var query = """ FROM test METADATA _score - | WHERE qstr("brown") AND match(content, "fox") - | EVAL first_score = score(qstr("brown") AND match(content, "fox")) + | WHERE kql("brown") AND match(content, "fox") + | EVAL first_score = score(kql("brown") AND match(content, "fox")) | KEEP id, _score, first_score | SORT id """; @@ -162,11 +166,11 @@ public void testScorePlusWhereQstrAndMatch() { } } - public void testScorePlusWhereKqlAndMatch() { + public void testScoreSingleWhereKqlAndMatch() { var query = """ FROM test METADATA _score | WHERE kql("brown") AND match(content, "fox") - | EVAL first_score = score(kql("brown") AND match(content, "fox")) + | EVAL first_score = score(kql("brown")) | KEEP id, _score, first_score | SORT id """; @@ -176,12 +180,12 @@ public void testScorePlusWhereKqlAndMatch() { assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); assertValues( resp.values(), - List.of(List.of(1, 1.4274532794952393, 1.4274532496929169), List.of(6, 1.1248724460601807, 1.1248724162578583)) + List.of(List.of(1, 1.4274532794952393, 0.2708943784236908), List.of(6, 1.1248724460601807, 0.21347221732139587)) ); } } - public void testScorePlusWhereQstrORMatch() { + public void testScoreSameWhereQstrORMatch() { var query = """ FROM test METADATA _score | WHERE qstr("brown") OR match(content, "fox") @@ -206,6 +210,31 @@ public void testScorePlusWhereQstrORMatch() { } } + public void testScoreSingleWhereQstrORMatch() { + var query = """ + FROM test METADATA _score + | WHERE qstr("brown") OR match(content, "fox") + | EVAL first_score = score(qstr("brown")) + | KEEP id, _score, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double")); + assertValues( + resp.values(), + List.of( + List.of(1, 1.4274532794952393, 0.2708943784236908), + List.of(2, 0.2708943784236908, 0.2708943784236908), + List.of(3, 0.2708943784236908, 0.2708943784236908), + List.of(4, 0.19301524758338928, 0.19301524758338928), + List.of(6, 1.1248724460601807, 0.21347221732139587) + ) + ); + } + } + public void testSimpleScoreAlone() { var query = """ FROM test METADATA _score From bb78db6e5f98f7b3264b4476a8ff5a6ef54725a7 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 22 May 2025 16:12:43 +0200 Subject: [PATCH 19/58] spotless --- .../org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index d701e05145acf..1aa7a51d0ca89 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -29,7 +29,6 @@ public void setupIndex() { createAndPopulateIndex(); } - public void testScoreDifferentWhereMatch() { var query = """ FROM test METADATA _score From 68023d8d0e82b401062ef95be54ad6669b18f109 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 22 May 2025 16:34:38 +0200 Subject: [PATCH 20/58] more tests --- .../xpack/esql/plugin/ScoreFunctionIT.java | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index 1aa7a51d0ca89..a96b66ea7695d 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -48,7 +48,7 @@ public void testScoreDifferentWhereMatch() { } } - public void testScoreMultipleWhereMatchMatch() { + public void testScoreMultipleWhereMatch() { var query = """ FROM test METADATA _score | WHERE match(content, "brown") @@ -146,6 +146,29 @@ public void testScoreSingleWhereQstrAndMatch() { } } + public void testScoreBothWhereQstrAndMatch() { + var query = """ + FROM test METADATA _score + | WHERE qstr("brown") AND match(content, "fox") + | EVAL first_score = score(qstr("brown")) + | EVAL second_score = score(match(content, "fox")) + | KEEP id, _score, first_score, second_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score", "second_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double", "double")); + assertValues( + resp.values(), + List.of( + List.of(1, 1.4274532794952393, 0.2708943784236908, 1.156558871269226), + List.of(6, 1.1248724460601807, 0.21347221732139587, 0.9114001989364624) + ) + ); + } + } + public void testScoreSameWhereKqlAndMatch() { var query = """ FROM test METADATA _score @@ -184,6 +207,29 @@ public void testScoreSingleWhereKqlAndMatch() { } } + public void testScoreBothWhereKqlAndMatch() { + var query = """ + FROM test METADATA _score + | WHERE kql("brown") AND match(content, "fox") + | EVAL first_score = score(kql("brown")) + | EVAL second_score = score(match(content, "fox")) + | KEEP id, _score, first_score, second_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score", "second_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double", "double")); + assertValues( + resp.values(), + List.of( + List.of(1, 1.4274532794952393, 0.2708943784236908, 1.156558871269226), + List.of(6, 1.1248724460601807, 0.21347221732139587, 0.9114001989364624) + ) + ); + } + } + public void testScoreSameWhereQstrORMatch() { var query = """ FROM test METADATA _score @@ -234,6 +280,32 @@ public void testScoreSingleWhereQstrORMatch() { } } + public void testScoreBothWhereQstrORMatch() { + var query = """ + FROM test METADATA _score + | WHERE qstr("brown") OR match(content, "fox") + | EVAL first_score = score(qstr("brown")) + | EVAL second_score = score(match(content, "fox")) + | KEEP id, _score, first_score, second_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "_score", "first_score", "second_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double", "double", "double")); + assertValues( + resp.values(), + List.of( + List.of(1, 1.4274532794952393, 0.2708943784236908, 1.156558871269226), + List.of(2, 0.2708943784236908, 0.2708943784236908, 0.0), + List.of(3, 0.2708943784236908, 0.2708943784236908, 0.0), + List.of(4, 0.19301524758338928, 0.19301524758338928, 0.0), + List.of(6, 1.1248724460601807, 0.21347221732139587, 0.9114001989364624) + ) + ); + } + } + public void testSimpleScoreAlone() { var query = """ FROM test METADATA _score From 2e0c9d647eb8006fe8e6fea8b89c4e9087e2cf55 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 22 May 2025 18:59:19 +0200 Subject: [PATCH 21/58] verifier test fixes --- .../xpack/esql/analysis/VerifierTests.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java index d76a355a6c9a9..52300471ef1d7 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java @@ -1209,7 +1209,7 @@ public void testWeightedAvg() { public void testMatchInsideEval() throws Exception { assertEquals( - "1:36: [:] operator is only supported in WHERE and STATS commands\n" + "1:36: [:] operator is only supported in WHERE and STATS commands, or in EVAL within score(.) function\n" + "line 1:36: [:] operator cannot operate on [title], which is not a field from an index mapping", error("row title = \"brown fox\" | eval x = title:\"fox\" ") ); @@ -1369,12 +1369,12 @@ public void testKqlFunctionsNotAllowedAfterCommands() throws Exception { } public void testQueryStringFunctionOnlyAllowedInWhere() throws Exception { - assertEquals("1:9: [QSTR] function is only supported in WHERE and STATS commands", error("row a = qstr(\"Anna\")")); + assertEquals("1:9: [QSTR] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("row a = qstr(\"Anna\")")); checkFullTextFunctionsOnlyAllowedInWhere("QSTR", "qstr(\"Anna\")", "function"); } public void testKqlFunctionOnlyAllowedInWhere() throws Exception { - assertEquals("1:9: [KQL] function is only supported in WHERE and STATS commands", error("row a = kql(\"Anna\")")); + assertEquals("1:9: [KQL] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("row a = kql(\"Anna\")")); checkFullTextFunctionsOnlyAllowedInWhere("KQL", "kql(\"Anna\")", "function"); } @@ -1394,11 +1394,11 @@ public void testMatchOperatornOnlyAllowedInWhere() throws Exception { private void checkFullTextFunctionsOnlyAllowedInWhere(String functionName, String functionInvocation, String functionType) throws Exception { assertEquals( - "1:22: [" + functionName + "] " + functionType + " is only supported in WHERE and STATS commands", + "1:22: [" + functionName + "] " + functionType + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("from test | eval y = " + functionInvocation) ); assertEquals( - "1:18: [" + functionName + "] " + functionType + " is only supported in WHERE and STATS commands", + "1:18: [" + functionName + "] " + functionType + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("from test | sort " + functionInvocation + " asc") ); assertEquals( @@ -2478,7 +2478,7 @@ public void testMultiMatchTargetsExistingField() throws Exception { public void testMultiMatchInsideEval() throws Exception { assumeTrue("MultiMatch operator is available just for snapshots", Build.current().isSnapshot()); assertEquals( - "1:36: [MultiMatch] function is only supported in WHERE and STATS commands\n" + "1:36: [MultiMatch] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function\n" + "line 1:55: [MultiMatch] function cannot operate on [title], which is not a field from an index mapping", error("row title = \"brown fox\" | eval x = multi_match(\"fox\", title)") ); From d43d52e4f235eddd6820b707e6d359befa033cd4 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Thu, 22 May 2025 17:06:46 +0000 Subject: [PATCH 22/58] [CI] Auto commit changes from spotless --- .../xpack/esql/analysis/VerifierTests.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java index 52300471ef1d7..2dc33d72d579b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java @@ -1369,12 +1369,18 @@ public void testKqlFunctionsNotAllowedAfterCommands() throws Exception { } public void testQueryStringFunctionOnlyAllowedInWhere() throws Exception { - assertEquals("1:9: [QSTR] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("row a = qstr(\"Anna\")")); + assertEquals( + "1:9: [QSTR] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + error("row a = qstr(\"Anna\")") + ); checkFullTextFunctionsOnlyAllowedInWhere("QSTR", "qstr(\"Anna\")", "function"); } public void testKqlFunctionOnlyAllowedInWhere() throws Exception { - assertEquals("1:9: [KQL] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("row a = kql(\"Anna\")")); + assertEquals( + "1:9: [KQL] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + error("row a = kql(\"Anna\")") + ); checkFullTextFunctionsOnlyAllowedInWhere("KQL", "kql(\"Anna\")", "function"); } @@ -1394,11 +1400,19 @@ public void testMatchOperatornOnlyAllowedInWhere() throws Exception { private void checkFullTextFunctionsOnlyAllowedInWhere(String functionName, String functionInvocation, String functionType) throws Exception { assertEquals( - "1:22: [" + functionName + "] " + functionType + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + "1:22: [" + + functionName + + "] " + + functionType + + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("from test | eval y = " + functionInvocation) ); assertEquals( - "1:18: [" + functionName + "] " + functionType + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + "1:18: [" + + functionName + + "] " + + functionType + + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("from test | sort " + functionInvocation + " asc") ); assertEquals( From 14d763b5ae5522efea891c3a0f93b33053dbe087 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 23 May 2025 10:37:29 +0200 Subject: [PATCH 23/58] fixed info, test fixes --- .../_snippets/functions/appendix/values.md | 5 +++-- .../kibana/definition/functions/values.json | 2 +- .../esql/kibana/docs/functions/values.md | 3 ++- .../function/fulltext/ScoreFunction.java | 11 +++++----- .../xpack/esql/analysis/VerifierTests.java | 22 +++++++++++++++---- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/docs/reference/query-languages/esql/_snippets/functions/appendix/values.md b/docs/reference/query-languages/esql/_snippets/functions/appendix/values.md index 4a21c08c79756..f8928db80b968 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/appendix/values.md +++ b/docs/reference/query-languages/esql/_snippets/functions/appendix/values.md @@ -1,7 +1,8 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -::::{note} -Use [`TOP`](/reference/query-languages/esql/functions-operators/aggregation-functions.md#esql-top) if you need to keep repeated values. +::::{tip} +Use [`TOP`](/reference/query-languages/esql/functions-operators/aggregation-functions.md#esql-top) +if you need to keep repeated values. :::: ::::{warning} This can use a significant amount of memory and ES|QL doesn’t yet diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/values.json b/docs/reference/query-languages/esql/kibana/definition/functions/values.json index 7983f9d2b66ab..6ee883d6fd280 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/values.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/values.json @@ -2,7 +2,7 @@ "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", "type" : "agg", "name" : "values", - "description" : "Returns unique values as a multivalued field. The order of the returned values isn’t guaranteed.\nIf you need the values returned in order use `MV_SORT`.", + "description" : "Returns unique values as a multivalued field. The order of the returned values isn’t guaranteed.\nIf you need the values returned in order use\n`MV_SORT`.", "signatures" : [ { "params" : [ diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/values.md b/docs/reference/query-languages/esql/kibana/docs/functions/values.md index 130c7f3d60e20..3a95a12d03cd3 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/values.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/values.md @@ -2,7 +2,8 @@ ### VALUES Returns unique values as a multivalued field. The order of the returned values isn’t guaranteed. -If you need the values returned in order use [`MV_SORT`](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/mv-functions#esql-mv_sort). +If you need the values returned in order use +[`MV_SORT`](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/mv-functions#esql-mv_sort). ```esql FROM employees diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java index 672ea189e5781..b980fd8d15f3d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java @@ -30,6 +30,10 @@ import java.io.IOException; import java.util.List; +/** + * A function to be used to score specific portions of an ES|QL query e.g., in conjunction with + * an {@link org.elasticsearch.xpack.esql.plan.logical.Eval}. + */ public class ScoreFunction extends Function implements EvaluatorMapper { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( @@ -44,7 +48,7 @@ public class ScoreFunction extends Function implements EvaluatorMapper { returnType = "double", preview = true, description = "Scores a full text function. Returns scores for all the matching docs.", - examples = { @Example(file = "score-function", tag = "score-with-field") } + examples = { @Example(file = "score-function", tag = "score-single") } ) public ScoreFunction( Source source, @@ -69,7 +73,7 @@ public Expression replaceChildren(List newChildren) { @Override protected NodeInfo info() { - return NodeInfo.create(this, ScoreFunction::new, children()); + return NodeInfo.create(this, ScoreFunction::new, children().getFirst()); } @Override @@ -79,11 +83,8 @@ public String getWriteableName() { @Override public EvalOperator.ExpressionEvaluator.Factory toEvaluator(EvaluatorMapper.ToEvaluator toEvaluator) { - ScoreOperator.ExpressionScorer.Factory scorerFactory = ScoreMapper.toScorer(children().getFirst(), toEvaluator.shardContexts()); - return driverContext -> new ScorerEvaluatorFactory(scorerFactory).get(driverContext); - } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java index 52300471ef1d7..2dc33d72d579b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java @@ -1369,12 +1369,18 @@ public void testKqlFunctionsNotAllowedAfterCommands() throws Exception { } public void testQueryStringFunctionOnlyAllowedInWhere() throws Exception { - assertEquals("1:9: [QSTR] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("row a = qstr(\"Anna\")")); + assertEquals( + "1:9: [QSTR] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + error("row a = qstr(\"Anna\")") + ); checkFullTextFunctionsOnlyAllowedInWhere("QSTR", "qstr(\"Anna\")", "function"); } public void testKqlFunctionOnlyAllowedInWhere() throws Exception { - assertEquals("1:9: [KQL] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("row a = kql(\"Anna\")")); + assertEquals( + "1:9: [KQL] function is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + error("row a = kql(\"Anna\")") + ); checkFullTextFunctionsOnlyAllowedInWhere("KQL", "kql(\"Anna\")", "function"); } @@ -1394,11 +1400,19 @@ public void testMatchOperatornOnlyAllowedInWhere() throws Exception { private void checkFullTextFunctionsOnlyAllowedInWhere(String functionName, String functionInvocation, String functionType) throws Exception { assertEquals( - "1:22: [" + functionName + "] " + functionType + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + "1:22: [" + + functionName + + "] " + + functionType + + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("from test | eval y = " + functionInvocation) ); assertEquals( - "1:18: [" + functionName + "] " + functionType + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + "1:18: [" + + functionName + + "] " + + functionType + + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function", error("from test | sort " + functionInvocation + " asc") ); assertEquals( From 7e67a7bb9a0b802b5227bc26be1a0e48c54e8f88 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 23 May 2025 11:04:13 +0200 Subject: [PATCH 24/58] minor refactoring --- .../{ScoreFunctionIT.java => ScoreIT.java} | 2 +- .../function/EsqlFunctionRegistry.java | 4 ++-- .../function/fulltext/FullTextFunction.java | 5 +---- .../function/fulltext/FullTextWritables.java | 2 +- .../{ScoreFunction.java => Score.java} | 20 ++++++++----------- 5 files changed, 13 insertions(+), 20 deletions(-) rename x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/{ScoreFunctionIT.java => ScoreIT.java} (99%) rename x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/{ScoreFunction.java => Score.java} (88%) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreIT.java similarity index 99% rename from x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java rename to x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreIT.java index a96b66ea7695d..1fea97c204c2c 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreIT.java @@ -22,7 +22,7 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; //@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") -public class ScoreFunctionIT extends AbstractEsqlIntegTestCase { +public class ScoreIT extends AbstractEsqlIntegTestCase { @Before public void setupIndex() { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index bbda670a85881..a51052945895b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -44,7 +44,7 @@ import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.MultiMatch; import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; -import org.elasticsearch.xpack.esql.expression.function.fulltext.ScoreFunction; +import org.elasticsearch.xpack.esql.expression.function.fulltext.Score; import org.elasticsearch.xpack.esql.expression.function.fulltext.Term; import org.elasticsearch.xpack.esql.expression.function.grouping.Bucket; import org.elasticsearch.xpack.esql.expression.function.grouping.Categorize; @@ -454,7 +454,7 @@ private static FunctionDefinition[][] snapshotFunctions() { def(MinOverTime.class, uni(MinOverTime::new), "min_over_time"), def(AvgOverTime.class, uni(AvgOverTime::new), "avg_over_time"), def(LastOverTime.class, LastOverTime::withUnresolvedTimestamp, "last_over_time"), - def(ScoreFunction.class, uni(ScoreFunction::new), ScoreFunction.NAME), + def(Score.class, uni(Score::new), Score.NAME), def(FirstOverTime.class, FirstOverTime::withUnresolvedTimestamp, "first_over_time"), def(Term.class, bi(Term::new), "term") } }; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index 0a9296fbd1c5c..dd3ce21ae19a3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -232,10 +232,7 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu } else { // TODO : improve this check, as this is not so nice :( List scoredFTFs = new ArrayList<>(); - plan.forEachExpression( - ScoreFunction.class, - scoreFunction -> { plan.forEachExpression(FullTextFunction.class, scoredFTFs::add); } - ); + plan.forEachExpression(Score.class, scoreFunction -> { plan.forEachExpression(FullTextFunction.class, scoredFTFs::add); }); plan.forEachExpression(FullTextFunction.class, ftf -> { if (scoredFTFs.remove(ftf) == false) { failures.add( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java index 1e83ff9e5b1e2..5f606bff41da8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java @@ -28,7 +28,7 @@ public static List getNamedWriteables() { entries.add(Term.ENTRY); } if (EsqlCapabilities.Cap.SCORE_FUNCTION.isEnabled()) { - entries.add(ScoreFunction.ENTRY); + entries.add(Score.ENTRY); } return Collections.unmodifiableList(entries); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java similarity index 88% rename from x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java rename to x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index b980fd8d15f3d..7c0f28f30be37 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -34,30 +34,26 @@ * A function to be used to score specific portions of an ES|QL query e.g., in conjunction with * an {@link org.elasticsearch.xpack.esql.plan.logical.Eval}. */ -public class ScoreFunction extends Function implements EvaluatorMapper { +public class Score extends Function implements EvaluatorMapper { - public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( - Expression.class, - "score", - ScoreFunction::readFrom - ); + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "score", Score::readFrom); public static final String NAME = "score"; @FunctionInfo( returnType = "double", preview = true, - description = "Scores a full text function. Returns scores for all the matching docs.", + description = "Scores a full text function. Returns scores for all the resulting docs.", examples = { @Example(file = "score-function", tag = "score-single") } ) - public ScoreFunction( + public Score( Source source, @Param(name = "query", type = { "keyword", "text" }, description = "full text function.") Expression scorableQuery ) { this(source, List.of(scorableQuery)); } - protected ScoreFunction(Source source, List children) { + protected Score(Source source, List children) { super(source, children); } @@ -68,12 +64,12 @@ public DataType dataType() { @Override public Expression replaceChildren(List newChildren) { - return new ScoreFunction(source(), newChildren); + return new Score(source(), newChildren); } @Override protected NodeInfo info() { - return NodeInfo.create(this, ScoreFunction::new, children().getFirst()); + return NodeInfo.create(this, Score::new, children().getFirst()); } @Override @@ -96,7 +92,7 @@ public void writeTo(StreamOutput out) throws IOException { private static Expression readFrom(StreamInput in) throws IOException { Source source = Source.readFrom((PlanStreamInput) in); Expression query = in.readOptionalNamedWriteable(Expression.class); - return new ScoreFunction(source, query); + return new Score(source, query); } private record ScorerEvaluatorFactory(ScoreOperator.ExpressionScorer.Factory scoreFactory) From fa34213fc0e34340f926586150c1eb79d0b11fba Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 23 May 2025 15:47:21 +0200 Subject: [PATCH 25/58] enable score in WHERE with FTFs, more tests --- .../{ScoreIT.java => ScoreFunctionIT.java} | 135 ++++++++- .../function/fulltext/FullTextFunction.java | 3 + .../xpack/esql/parser/EsqlBaseParser.interp | 2 +- .../xpack/esql/parser/EsqlBaseParser.java | 286 +++++++++--------- 4 files changed, 281 insertions(+), 145 deletions(-) rename x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/{ScoreIT.java => ScoreFunctionIT.java} (75%) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java similarity index 75% rename from x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreIT.java rename to x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index 1fea97c204c2c..cab7956ada472 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -12,17 +12,20 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.CollectionUtils; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; import org.elasticsearch.xpack.kql.KqlPlugin; import org.junit.Before; +import org.junit.Ignore; import java.util.Collection; import java.util.List; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; +import static org.hamcrest.CoreMatchers.containsString; //@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") -public class ScoreIT extends AbstractEsqlIntegTestCase { +public class ScoreFunctionIT extends AbstractEsqlIntegTestCase { @Before public void setupIndex() { @@ -48,6 +51,136 @@ public void testScoreDifferentWhereMatch() { } } + public void testScoreDifferentWhereMatchNoMetadata() { + var query = """ + FROM test + | EVAL first_score = score(match(content, "brown")) + | WHERE match(content, "fox") + | KEEP id, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of(List.of(1, 0.2708943784236908), List.of(6, 0.21347221732139587))); + } + } + + public void testScoreInWhereWithMatch() { + var query = """ + FROM test + | WHERE score(match(content, "brown")) + """; + + var error = expectThrows(VerificationException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("Condition expression needs to be boolean, found [DOUBLE]")); + } + + public void testScoreInWhereWithFilter() { + var query = """ + FROM test + | WHERE score(id > 0) + """; + + var error = expectThrows(VerificationException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("Condition expression needs to be boolean, found [DOUBLE]")); + } + + public void testMatchScoreFilter() { + var query = """ + FROM test + | WHERE score(match(content, "brown")) > 0 + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(1), List.of(2), List.of(3), List.of(4), List.of(6))); + } + } + + public void testKqlScoreFilter() { + var query = """ + FROM test + | WHERE score(kql("brown")) > 0 + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(1), List.of(2), List.of(3), List.of(4), List.of(6))); + } + } + + public void testQstrScoreFilter() { + var query = """ + FROM test + | WHERE score(qstr("brown")) > 0 + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(1), List.of(2), List.of(3), List.of(4), List.of(6))); + } + } + + public void testMultipleFTFScoreFilter() { + var query = """ + FROM test + | WHERE score(match(content, "brown")) > 0.4 OR score(match(content, "fox")) > 0.2 + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(1), List.of(6))); + } + } + + public void testMultipleHybridScoreFilter() { + var query = """ + FROM test + | WHERE score(match(content, "brown")) > 0.2 AND id > 2 + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(3), List.of(6))); + } + } + + @Ignore("it's meaningless but it passes o_O") + public void testScoreMeaninglessFunction() { + var query = """ + FROM test + | EVAL meaningless = score(abs(-0.1)) + | KEEP id, meaningless + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "meaningless")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 0.0), List.of(2, 0.0), List.of(3, 0.0), List.of(4, 0.0), List.of(5, 0.0), List.of(6, 0.0)) + ); + } + } + public void testScoreMultipleWhereMatch() { var query = """ FROM test METADATA _score diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index dd3ce21ae19a3..3dfc1414a8328 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -34,6 +34,7 @@ import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; import org.elasticsearch.xpack.esql.expression.predicate.logical.BinaryLogic; import org.elasticsearch.xpack.esql.expression.predicate.logical.Not; +import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.EsqlBinaryComparison; import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.LucenePushdownPredicates; import org.elasticsearch.xpack.esql.plan.logical.Aggregate; import org.elasticsearch.xpack.esql.plan.logical.EsRelation; @@ -304,6 +305,8 @@ private static void checkFullTextFunctionsParents(Expression condition, Failures forEachFullTextFunctionParent(condition, (ftf, parent) -> { if ((parent instanceof FullTextFunction == false) && (parent instanceof BinaryLogic == false) + && (parent instanceof EsqlBinaryComparison == false) + && (parent instanceof Score == false) // e.g., WHERE score($ftf) > ... && (parent instanceof Not == false)) { failures.add( fail( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp index c5dbbd8e24fa4..ef320ee2c4f6a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp @@ -368,4 +368,4 @@ joinPredicate atn: -[4, 1, 139, 772, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 174, 8, 1, 10, 1, 12, 1, 177, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 185, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 217, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 5, 7, 230, 8, 7, 10, 7, 12, 7, 233, 9, 7, 1, 8, 1, 8, 1, 8, 3, 8, 238, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 5, 9, 245, 8, 9, 10, 9, 12, 9, 248, 9, 9, 1, 10, 1, 10, 1, 10, 3, 10, 253, 8, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 264, 8, 13, 10, 13, 12, 13, 267, 9, 13, 1, 13, 3, 13, 270, 8, 13, 1, 14, 1, 14, 1, 14, 3, 14, 275, 8, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 281, 8, 14, 3, 14, 283, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 295, 8, 18, 10, 18, 12, 18, 298, 9, 18, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 3, 20, 305, 8, 20, 1, 20, 1, 20, 3, 20, 309, 8, 20, 1, 21, 1, 21, 1, 21, 5, 21, 314, 8, 21, 10, 21, 12, 21, 317, 9, 21, 1, 22, 1, 22, 1, 22, 3, 22, 322, 8, 22, 1, 23, 1, 23, 1, 23, 5, 23, 327, 8, 23, 10, 23, 12, 23, 330, 9, 23, 1, 24, 1, 24, 1, 24, 5, 24, 335, 8, 24, 10, 24, 12, 24, 338, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 343, 8, 25, 10, 25, 12, 25, 346, 9, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 3, 27, 353, 8, 27, 1, 28, 1, 28, 3, 28, 357, 8, 28, 1, 29, 1, 29, 3, 29, 361, 8, 29, 1, 30, 1, 30, 1, 30, 3, 30, 366, 8, 30, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 375, 8, 32, 10, 32, 12, 32, 378, 9, 32, 1, 33, 1, 33, 3, 33, 382, 8, 33, 1, 33, 1, 33, 3, 33, 386, 8, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 398, 8, 36, 10, 36, 12, 36, 401, 9, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 411, 8, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 5, 41, 423, 8, 41, 10, 41, 12, 41, 426, 9, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 446, 8, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 452, 8, 46, 10, 46, 12, 46, 455, 9, 46, 3, 46, 457, 8, 46, 1, 47, 1, 47, 1, 47, 3, 47, 462, 8, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 475, 8, 49, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 481, 8, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 488, 8, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 4, 53, 497, 8, 53, 11, 53, 12, 53, 498, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 5, 55, 511, 8, 55, 10, 55, 12, 55, 514, 9, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 3, 56, 522, 8, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, 59, 539, 8, 59, 1, 60, 1, 60, 1, 60, 3, 60, 544, 8, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 553, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 560, 8, 61, 10, 61, 12, 61, 563, 9, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 570, 8, 61, 1, 61, 1, 61, 1, 61, 3, 61, 575, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 583, 8, 61, 10, 61, 12, 61, 586, 9, 61, 1, 62, 1, 62, 3, 62, 590, 8, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 3, 62, 597, 8, 62, 1, 62, 1, 62, 1, 62, 3, 62, 602, 8, 62, 1, 63, 1, 63, 1, 63, 3, 63, 607, 8, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 3, 64, 617, 8, 64, 1, 65, 1, 65, 1, 65, 1, 65, 3, 65, 623, 8, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 5, 65, 631, 8, 65, 10, 65, 12, 65, 634, 9, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 3, 66, 644, 8, 66, 1, 66, 1, 66, 1, 66, 5, 66, 649, 8, 66, 10, 66, 12, 66, 652, 9, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 5, 67, 660, 8, 67, 10, 67, 12, 67, 663, 9, 67, 1, 67, 1, 67, 3, 67, 667, 8, 67, 3, 67, 669, 8, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 5, 69, 679, 8, 69, 10, 69, 12, 69, 682, 9, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 703, 8, 71, 10, 71, 12, 71, 706, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 714, 8, 71, 10, 71, 12, 71, 717, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 725, 8, 71, 10, 71, 12, 71, 728, 9, 71, 1, 71, 1, 71, 3, 71, 732, 8, 71, 1, 72, 1, 72, 1, 73, 1, 73, 3, 73, 738, 8, 73, 1, 74, 3, 74, 741, 8, 74, 1, 74, 1, 74, 1, 75, 3, 75, 746, 8, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 5, 80, 765, 8, 80, 10, 80, 12, 80, 768, 9, 80, 1, 81, 1, 81, 1, 81, 0, 5, 2, 110, 122, 130, 132, 82, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 0, 9, 2, 0, 53, 53, 108, 108, 1, 0, 102, 103, 2, 0, 58, 58, 64, 64, 2, 0, 67, 67, 70, 70, 1, 0, 88, 89, 1, 0, 90, 92, 2, 0, 66, 66, 79, 79, 2, 0, 81, 81, 83, 87, 2, 0, 22, 22, 24, 25, 803, 0, 164, 1, 0, 0, 0, 2, 167, 1, 0, 0, 0, 4, 184, 1, 0, 0, 0, 6, 216, 1, 0, 0, 0, 8, 218, 1, 0, 0, 0, 10, 221, 1, 0, 0, 0, 12, 223, 1, 0, 0, 0, 14, 226, 1, 0, 0, 0, 16, 237, 1, 0, 0, 0, 18, 241, 1, 0, 0, 0, 20, 249, 1, 0, 0, 0, 22, 254, 1, 0, 0, 0, 24, 257, 1, 0, 0, 0, 26, 260, 1, 0, 0, 0, 28, 282, 1, 0, 0, 0, 30, 284, 1, 0, 0, 0, 32, 286, 1, 0, 0, 0, 34, 288, 1, 0, 0, 0, 36, 290, 1, 0, 0, 0, 38, 299, 1, 0, 0, 0, 40, 302, 1, 0, 0, 0, 42, 310, 1, 0, 0, 0, 44, 318, 1, 0, 0, 0, 46, 323, 1, 0, 0, 0, 48, 331, 1, 0, 0, 0, 50, 339, 1, 0, 0, 0, 52, 347, 1, 0, 0, 0, 54, 352, 1, 0, 0, 0, 56, 356, 1, 0, 0, 0, 58, 360, 1, 0, 0, 0, 60, 365, 1, 0, 0, 0, 62, 367, 1, 0, 0, 0, 64, 370, 1, 0, 0, 0, 66, 379, 1, 0, 0, 0, 68, 387, 1, 0, 0, 0, 70, 390, 1, 0, 0, 0, 72, 393, 1, 0, 0, 0, 74, 402, 1, 0, 0, 0, 76, 406, 1, 0, 0, 0, 78, 412, 1, 0, 0, 0, 80, 416, 1, 0, 0, 0, 82, 419, 1, 0, 0, 0, 84, 427, 1, 0, 0, 0, 86, 431, 1, 0, 0, 0, 88, 434, 1, 0, 0, 0, 90, 438, 1, 0, 0, 0, 92, 441, 1, 0, 0, 0, 94, 461, 1, 0, 0, 0, 96, 465, 1, 0, 0, 0, 98, 470, 1, 0, 0, 0, 100, 476, 1, 0, 0, 0, 102, 489, 1, 0, 0, 0, 104, 492, 1, 0, 0, 0, 106, 496, 1, 0, 0, 0, 108, 500, 1, 0, 0, 0, 110, 504, 1, 0, 0, 0, 112, 521, 1, 0, 0, 0, 114, 523, 1, 0, 0, 0, 116, 525, 1, 0, 0, 0, 118, 532, 1, 0, 0, 0, 120, 540, 1, 0, 0, 0, 122, 574, 1, 0, 0, 0, 124, 601, 1, 0, 0, 0, 126, 603, 1, 0, 0, 0, 128, 616, 1, 0, 0, 0, 130, 622, 1, 0, 0, 0, 132, 643, 1, 0, 0, 0, 134, 653, 1, 0, 0, 0, 136, 672, 1, 0, 0, 0, 138, 674, 1, 0, 0, 0, 140, 685, 1, 0, 0, 0, 142, 731, 1, 0, 0, 0, 144, 733, 1, 0, 0, 0, 146, 737, 1, 0, 0, 0, 148, 740, 1, 0, 0, 0, 150, 745, 1, 0, 0, 0, 152, 749, 1, 0, 0, 0, 154, 751, 1, 0, 0, 0, 156, 753, 1, 0, 0, 0, 158, 758, 1, 0, 0, 0, 160, 760, 1, 0, 0, 0, 162, 769, 1, 0, 0, 0, 164, 165, 3, 2, 1, 0, 165, 166, 5, 0, 0, 1, 166, 1, 1, 0, 0, 0, 167, 168, 6, 1, -1, 0, 168, 169, 3, 4, 2, 0, 169, 175, 1, 0, 0, 0, 170, 171, 10, 1, 0, 0, 171, 172, 5, 52, 0, 0, 172, 174, 3, 6, 3, 0, 173, 170, 1, 0, 0, 0, 174, 177, 1, 0, 0, 0, 175, 173, 1, 0, 0, 0, 175, 176, 1, 0, 0, 0, 176, 3, 1, 0, 0, 0, 177, 175, 1, 0, 0, 0, 178, 185, 3, 86, 43, 0, 179, 185, 3, 22, 11, 0, 180, 185, 3, 12, 6, 0, 181, 185, 3, 90, 45, 0, 182, 183, 4, 2, 1, 0, 183, 185, 3, 24, 12, 0, 184, 178, 1, 0, 0, 0, 184, 179, 1, 0, 0, 0, 184, 180, 1, 0, 0, 0, 184, 181, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 5, 1, 0, 0, 0, 186, 217, 3, 38, 19, 0, 187, 217, 3, 8, 4, 0, 188, 217, 3, 68, 34, 0, 189, 217, 3, 62, 31, 0, 190, 217, 3, 40, 20, 0, 191, 217, 3, 64, 32, 0, 192, 217, 3, 70, 35, 0, 193, 217, 3, 72, 36, 0, 194, 217, 3, 76, 38, 0, 195, 217, 3, 78, 39, 0, 196, 217, 3, 92, 46, 0, 197, 217, 3, 80, 40, 0, 198, 217, 3, 156, 78, 0, 199, 217, 3, 100, 50, 0, 200, 201, 4, 3, 2, 0, 201, 217, 3, 98, 49, 0, 202, 203, 4, 3, 3, 0, 203, 217, 3, 96, 48, 0, 204, 205, 4, 3, 4, 0, 205, 217, 3, 118, 59, 0, 206, 207, 4, 3, 5, 0, 207, 217, 3, 102, 51, 0, 208, 209, 4, 3, 6, 0, 209, 217, 3, 104, 52, 0, 210, 211, 4, 3, 7, 0, 211, 217, 3, 116, 58, 0, 212, 213, 4, 3, 8, 0, 213, 217, 3, 114, 57, 0, 214, 215, 4, 3, 9, 0, 215, 217, 3, 120, 60, 0, 216, 186, 1, 0, 0, 0, 216, 187, 1, 0, 0, 0, 216, 188, 1, 0, 0, 0, 216, 189, 1, 0, 0, 0, 216, 190, 1, 0, 0, 0, 216, 191, 1, 0, 0, 0, 216, 192, 1, 0, 0, 0, 216, 193, 1, 0, 0, 0, 216, 194, 1, 0, 0, 0, 216, 195, 1, 0, 0, 0, 216, 196, 1, 0, 0, 0, 216, 197, 1, 0, 0, 0, 216, 198, 1, 0, 0, 0, 216, 199, 1, 0, 0, 0, 216, 200, 1, 0, 0, 0, 216, 202, 1, 0, 0, 0, 216, 204, 1, 0, 0, 0, 216, 206, 1, 0, 0, 0, 216, 208, 1, 0, 0, 0, 216, 210, 1, 0, 0, 0, 216, 212, 1, 0, 0, 0, 216, 214, 1, 0, 0, 0, 217, 7, 1, 0, 0, 0, 218, 219, 5, 14, 0, 0, 219, 220, 3, 122, 61, 0, 220, 9, 1, 0, 0, 0, 221, 222, 3, 52, 26, 0, 222, 11, 1, 0, 0, 0, 223, 224, 5, 11, 0, 0, 224, 225, 3, 14, 7, 0, 225, 13, 1, 0, 0, 0, 226, 231, 3, 16, 8, 0, 227, 228, 5, 63, 0, 0, 228, 230, 3, 16, 8, 0, 229, 227, 1, 0, 0, 0, 230, 233, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 15, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 234, 235, 3, 46, 23, 0, 235, 236, 5, 59, 0, 0, 236, 238, 1, 0, 0, 0, 237, 234, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 239, 1, 0, 0, 0, 239, 240, 3, 122, 61, 0, 240, 17, 1, 0, 0, 0, 241, 246, 3, 20, 10, 0, 242, 243, 5, 63, 0, 0, 243, 245, 3, 20, 10, 0, 244, 242, 1, 0, 0, 0, 245, 248, 1, 0, 0, 0, 246, 244, 1, 0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 19, 1, 0, 0, 0, 248, 246, 1, 0, 0, 0, 249, 252, 3, 46, 23, 0, 250, 251, 5, 59, 0, 0, 251, 253, 3, 122, 61, 0, 252, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 21, 1, 0, 0, 0, 254, 255, 5, 19, 0, 0, 255, 256, 3, 26, 13, 0, 256, 23, 1, 0, 0, 0, 257, 258, 5, 20, 0, 0, 258, 259, 3, 26, 13, 0, 259, 25, 1, 0, 0, 0, 260, 265, 3, 28, 14, 0, 261, 262, 5, 63, 0, 0, 262, 264, 3, 28, 14, 0, 263, 261, 1, 0, 0, 0, 264, 267, 1, 0, 0, 0, 265, 263, 1, 0, 0, 0, 265, 266, 1, 0, 0, 0, 266, 269, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 268, 270, 3, 36, 18, 0, 269, 268, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 27, 1, 0, 0, 0, 271, 272, 3, 30, 15, 0, 272, 273, 5, 62, 0, 0, 273, 275, 1, 0, 0, 0, 274, 271, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 276, 1, 0, 0, 0, 276, 283, 3, 34, 17, 0, 277, 280, 3, 34, 17, 0, 278, 279, 5, 61, 0, 0, 279, 281, 3, 32, 16, 0, 280, 278, 1, 0, 0, 0, 280, 281, 1, 0, 0, 0, 281, 283, 1, 0, 0, 0, 282, 274, 1, 0, 0, 0, 282, 277, 1, 0, 0, 0, 283, 29, 1, 0, 0, 0, 284, 285, 7, 0, 0, 0, 285, 31, 1, 0, 0, 0, 286, 287, 7, 0, 0, 0, 287, 33, 1, 0, 0, 0, 288, 289, 7, 0, 0, 0, 289, 35, 1, 0, 0, 0, 290, 291, 5, 107, 0, 0, 291, 296, 5, 108, 0, 0, 292, 293, 5, 63, 0, 0, 293, 295, 5, 108, 0, 0, 294, 292, 1, 0, 0, 0, 295, 298, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 37, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 299, 300, 5, 8, 0, 0, 300, 301, 3, 14, 7, 0, 301, 39, 1, 0, 0, 0, 302, 304, 5, 13, 0, 0, 303, 305, 3, 42, 21, 0, 304, 303, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 308, 1, 0, 0, 0, 306, 307, 5, 60, 0, 0, 307, 309, 3, 14, 7, 0, 308, 306, 1, 0, 0, 0, 308, 309, 1, 0, 0, 0, 309, 41, 1, 0, 0, 0, 310, 315, 3, 44, 22, 0, 311, 312, 5, 63, 0, 0, 312, 314, 3, 44, 22, 0, 313, 311, 1, 0, 0, 0, 314, 317, 1, 0, 0, 0, 315, 313, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 43, 1, 0, 0, 0, 317, 315, 1, 0, 0, 0, 318, 321, 3, 16, 8, 0, 319, 320, 5, 14, 0, 0, 320, 322, 3, 122, 61, 0, 321, 319, 1, 0, 0, 0, 321, 322, 1, 0, 0, 0, 322, 45, 1, 0, 0, 0, 323, 328, 3, 60, 30, 0, 324, 325, 5, 65, 0, 0, 325, 327, 3, 60, 30, 0, 326, 324, 1, 0, 0, 0, 327, 330, 1, 0, 0, 0, 328, 326, 1, 0, 0, 0, 328, 329, 1, 0, 0, 0, 329, 47, 1, 0, 0, 0, 330, 328, 1, 0, 0, 0, 331, 336, 3, 54, 27, 0, 332, 333, 5, 65, 0, 0, 333, 335, 3, 54, 27, 0, 334, 332, 1, 0, 0, 0, 335, 338, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 336, 337, 1, 0, 0, 0, 337, 49, 1, 0, 0, 0, 338, 336, 1, 0, 0, 0, 339, 344, 3, 48, 24, 0, 340, 341, 5, 63, 0, 0, 341, 343, 3, 48, 24, 0, 342, 340, 1, 0, 0, 0, 343, 346, 1, 0, 0, 0, 344, 342, 1, 0, 0, 0, 344, 345, 1, 0, 0, 0, 345, 51, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 347, 348, 7, 1, 0, 0, 348, 53, 1, 0, 0, 0, 349, 353, 5, 129, 0, 0, 350, 353, 3, 56, 28, 0, 351, 353, 3, 58, 29, 0, 352, 349, 1, 0, 0, 0, 352, 350, 1, 0, 0, 0, 352, 351, 1, 0, 0, 0, 353, 55, 1, 0, 0, 0, 354, 357, 5, 77, 0, 0, 355, 357, 5, 96, 0, 0, 356, 354, 1, 0, 0, 0, 356, 355, 1, 0, 0, 0, 357, 57, 1, 0, 0, 0, 358, 361, 5, 95, 0, 0, 359, 361, 5, 97, 0, 0, 360, 358, 1, 0, 0, 0, 360, 359, 1, 0, 0, 0, 361, 59, 1, 0, 0, 0, 362, 366, 3, 52, 26, 0, 363, 366, 3, 56, 28, 0, 364, 366, 3, 58, 29, 0, 365, 362, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 365, 364, 1, 0, 0, 0, 366, 61, 1, 0, 0, 0, 367, 368, 5, 10, 0, 0, 368, 369, 5, 54, 0, 0, 369, 63, 1, 0, 0, 0, 370, 371, 5, 12, 0, 0, 371, 376, 3, 66, 33, 0, 372, 373, 5, 63, 0, 0, 373, 375, 3, 66, 33, 0, 374, 372, 1, 0, 0, 0, 375, 378, 1, 0, 0, 0, 376, 374, 1, 0, 0, 0, 376, 377, 1, 0, 0, 0, 377, 65, 1, 0, 0, 0, 378, 376, 1, 0, 0, 0, 379, 381, 3, 122, 61, 0, 380, 382, 7, 2, 0, 0, 381, 380, 1, 0, 0, 0, 381, 382, 1, 0, 0, 0, 382, 385, 1, 0, 0, 0, 383, 384, 5, 74, 0, 0, 384, 386, 7, 3, 0, 0, 385, 383, 1, 0, 0, 0, 385, 386, 1, 0, 0, 0, 386, 67, 1, 0, 0, 0, 387, 388, 5, 29, 0, 0, 388, 389, 3, 50, 25, 0, 389, 69, 1, 0, 0, 0, 390, 391, 5, 28, 0, 0, 391, 392, 3, 50, 25, 0, 392, 71, 1, 0, 0, 0, 393, 394, 5, 32, 0, 0, 394, 399, 3, 74, 37, 0, 395, 396, 5, 63, 0, 0, 396, 398, 3, 74, 37, 0, 397, 395, 1, 0, 0, 0, 398, 401, 1, 0, 0, 0, 399, 397, 1, 0, 0, 0, 399, 400, 1, 0, 0, 0, 400, 73, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 402, 403, 3, 48, 24, 0, 403, 404, 5, 57, 0, 0, 404, 405, 3, 48, 24, 0, 405, 75, 1, 0, 0, 0, 406, 407, 5, 7, 0, 0, 407, 408, 3, 132, 66, 0, 408, 410, 3, 152, 76, 0, 409, 411, 3, 82, 41, 0, 410, 409, 1, 0, 0, 0, 410, 411, 1, 0, 0, 0, 411, 77, 1, 0, 0, 0, 412, 413, 5, 9, 0, 0, 413, 414, 3, 132, 66, 0, 414, 415, 3, 152, 76, 0, 415, 79, 1, 0, 0, 0, 416, 417, 5, 27, 0, 0, 417, 418, 3, 46, 23, 0, 418, 81, 1, 0, 0, 0, 419, 424, 3, 84, 42, 0, 420, 421, 5, 63, 0, 0, 421, 423, 3, 84, 42, 0, 422, 420, 1, 0, 0, 0, 423, 426, 1, 0, 0, 0, 424, 422, 1, 0, 0, 0, 424, 425, 1, 0, 0, 0, 425, 83, 1, 0, 0, 0, 426, 424, 1, 0, 0, 0, 427, 428, 3, 52, 26, 0, 428, 429, 5, 59, 0, 0, 429, 430, 3, 142, 71, 0, 430, 85, 1, 0, 0, 0, 431, 432, 5, 6, 0, 0, 432, 433, 3, 88, 44, 0, 433, 87, 1, 0, 0, 0, 434, 435, 5, 98, 0, 0, 435, 436, 3, 2, 1, 0, 436, 437, 5, 99, 0, 0, 437, 89, 1, 0, 0, 0, 438, 439, 5, 33, 0, 0, 439, 440, 5, 136, 0, 0, 440, 91, 1, 0, 0, 0, 441, 442, 5, 5, 0, 0, 442, 445, 5, 38, 0, 0, 443, 444, 5, 75, 0, 0, 444, 446, 3, 48, 24, 0, 445, 443, 1, 0, 0, 0, 445, 446, 1, 0, 0, 0, 446, 456, 1, 0, 0, 0, 447, 448, 5, 80, 0, 0, 448, 453, 3, 94, 47, 0, 449, 450, 5, 63, 0, 0, 450, 452, 3, 94, 47, 0, 451, 449, 1, 0, 0, 0, 452, 455, 1, 0, 0, 0, 453, 451, 1, 0, 0, 0, 453, 454, 1, 0, 0, 0, 454, 457, 1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 456, 447, 1, 0, 0, 0, 456, 457, 1, 0, 0, 0, 457, 93, 1, 0, 0, 0, 458, 459, 3, 48, 24, 0, 459, 460, 5, 59, 0, 0, 460, 462, 1, 0, 0, 0, 461, 458, 1, 0, 0, 0, 461, 462, 1, 0, 0, 0, 462, 463, 1, 0, 0, 0, 463, 464, 3, 48, 24, 0, 464, 95, 1, 0, 0, 0, 465, 466, 5, 26, 0, 0, 466, 467, 3, 28, 14, 0, 467, 468, 5, 75, 0, 0, 468, 469, 3, 50, 25, 0, 469, 97, 1, 0, 0, 0, 470, 471, 5, 16, 0, 0, 471, 474, 3, 42, 21, 0, 472, 473, 5, 60, 0, 0, 473, 475, 3, 14, 7, 0, 474, 472, 1, 0, 0, 0, 474, 475, 1, 0, 0, 0, 475, 99, 1, 0, 0, 0, 476, 477, 5, 4, 0, 0, 477, 480, 3, 46, 23, 0, 478, 479, 5, 75, 0, 0, 479, 481, 3, 46, 23, 0, 480, 478, 1, 0, 0, 0, 480, 481, 1, 0, 0, 0, 481, 487, 1, 0, 0, 0, 482, 483, 5, 57, 0, 0, 483, 484, 3, 46, 23, 0, 484, 485, 5, 63, 0, 0, 485, 486, 3, 46, 23, 0, 486, 488, 1, 0, 0, 0, 487, 482, 1, 0, 0, 0, 487, 488, 1, 0, 0, 0, 488, 101, 1, 0, 0, 0, 489, 490, 5, 30, 0, 0, 490, 491, 3, 50, 25, 0, 491, 103, 1, 0, 0, 0, 492, 493, 5, 21, 0, 0, 493, 494, 3, 106, 53, 0, 494, 105, 1, 0, 0, 0, 495, 497, 3, 108, 54, 0, 496, 495, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 496, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 107, 1, 0, 0, 0, 500, 501, 5, 100, 0, 0, 501, 502, 3, 110, 55, 0, 502, 503, 5, 101, 0, 0, 503, 109, 1, 0, 0, 0, 504, 505, 6, 55, -1, 0, 505, 506, 3, 112, 56, 0, 506, 512, 1, 0, 0, 0, 507, 508, 10, 1, 0, 0, 508, 509, 5, 52, 0, 0, 509, 511, 3, 112, 56, 0, 510, 507, 1, 0, 0, 0, 511, 514, 1, 0, 0, 0, 512, 510, 1, 0, 0, 0, 512, 513, 1, 0, 0, 0, 513, 111, 1, 0, 0, 0, 514, 512, 1, 0, 0, 0, 515, 522, 3, 38, 19, 0, 516, 522, 3, 8, 4, 0, 517, 522, 3, 62, 31, 0, 518, 522, 3, 40, 20, 0, 519, 522, 3, 64, 32, 0, 520, 522, 3, 76, 38, 0, 521, 515, 1, 0, 0, 0, 521, 516, 1, 0, 0, 0, 521, 517, 1, 0, 0, 0, 521, 518, 1, 0, 0, 0, 521, 519, 1, 0, 0, 0, 521, 520, 1, 0, 0, 0, 522, 113, 1, 0, 0, 0, 523, 524, 5, 31, 0, 0, 524, 115, 1, 0, 0, 0, 525, 526, 5, 17, 0, 0, 526, 527, 3, 142, 71, 0, 527, 528, 5, 75, 0, 0, 528, 529, 3, 18, 9, 0, 529, 530, 5, 80, 0, 0, 530, 531, 3, 60, 30, 0, 531, 117, 1, 0, 0, 0, 532, 533, 5, 15, 0, 0, 533, 534, 3, 132, 66, 0, 534, 535, 5, 80, 0, 0, 535, 538, 3, 60, 30, 0, 536, 537, 5, 57, 0, 0, 537, 539, 3, 46, 23, 0, 538, 536, 1, 0, 0, 0, 538, 539, 1, 0, 0, 0, 539, 119, 1, 0, 0, 0, 540, 541, 5, 18, 0, 0, 541, 543, 3, 148, 74, 0, 542, 544, 3, 150, 75, 0, 543, 542, 1, 0, 0, 0, 543, 544, 1, 0, 0, 0, 544, 121, 1, 0, 0, 0, 545, 546, 6, 61, -1, 0, 546, 547, 5, 72, 0, 0, 547, 575, 3, 122, 61, 8, 548, 575, 3, 128, 64, 0, 549, 575, 3, 124, 62, 0, 550, 552, 3, 128, 64, 0, 551, 553, 5, 72, 0, 0, 552, 551, 1, 0, 0, 0, 552, 553, 1, 0, 0, 0, 553, 554, 1, 0, 0, 0, 554, 555, 5, 68, 0, 0, 555, 556, 5, 100, 0, 0, 556, 561, 3, 128, 64, 0, 557, 558, 5, 63, 0, 0, 558, 560, 3, 128, 64, 0, 559, 557, 1, 0, 0, 0, 560, 563, 1, 0, 0, 0, 561, 559, 1, 0, 0, 0, 561, 562, 1, 0, 0, 0, 562, 564, 1, 0, 0, 0, 563, 561, 1, 0, 0, 0, 564, 565, 5, 101, 0, 0, 565, 575, 1, 0, 0, 0, 566, 567, 3, 128, 64, 0, 567, 569, 5, 69, 0, 0, 568, 570, 5, 72, 0, 0, 569, 568, 1, 0, 0, 0, 569, 570, 1, 0, 0, 0, 570, 571, 1, 0, 0, 0, 571, 572, 5, 73, 0, 0, 572, 575, 1, 0, 0, 0, 573, 575, 3, 126, 63, 0, 574, 545, 1, 0, 0, 0, 574, 548, 1, 0, 0, 0, 574, 549, 1, 0, 0, 0, 574, 550, 1, 0, 0, 0, 574, 566, 1, 0, 0, 0, 574, 573, 1, 0, 0, 0, 575, 584, 1, 0, 0, 0, 576, 577, 10, 5, 0, 0, 577, 578, 5, 56, 0, 0, 578, 583, 3, 122, 61, 6, 579, 580, 10, 4, 0, 0, 580, 581, 5, 76, 0, 0, 581, 583, 3, 122, 61, 5, 582, 576, 1, 0, 0, 0, 582, 579, 1, 0, 0, 0, 583, 586, 1, 0, 0, 0, 584, 582, 1, 0, 0, 0, 584, 585, 1, 0, 0, 0, 585, 123, 1, 0, 0, 0, 586, 584, 1, 0, 0, 0, 587, 589, 3, 128, 64, 0, 588, 590, 5, 72, 0, 0, 589, 588, 1, 0, 0, 0, 589, 590, 1, 0, 0, 0, 590, 591, 1, 0, 0, 0, 591, 592, 5, 71, 0, 0, 592, 593, 3, 152, 76, 0, 593, 602, 1, 0, 0, 0, 594, 596, 3, 128, 64, 0, 595, 597, 5, 72, 0, 0, 596, 595, 1, 0, 0, 0, 596, 597, 1, 0, 0, 0, 597, 598, 1, 0, 0, 0, 598, 599, 5, 78, 0, 0, 599, 600, 3, 152, 76, 0, 600, 602, 1, 0, 0, 0, 601, 587, 1, 0, 0, 0, 601, 594, 1, 0, 0, 0, 602, 125, 1, 0, 0, 0, 603, 606, 3, 46, 23, 0, 604, 605, 5, 61, 0, 0, 605, 607, 3, 10, 5, 0, 606, 604, 1, 0, 0, 0, 606, 607, 1, 0, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, 5, 62, 0, 0, 609, 610, 3, 142, 71, 0, 610, 127, 1, 0, 0, 0, 611, 617, 3, 130, 65, 0, 612, 613, 3, 130, 65, 0, 613, 614, 3, 154, 77, 0, 614, 615, 3, 130, 65, 0, 615, 617, 1, 0, 0, 0, 616, 611, 1, 0, 0, 0, 616, 612, 1, 0, 0, 0, 617, 129, 1, 0, 0, 0, 618, 619, 6, 65, -1, 0, 619, 623, 3, 132, 66, 0, 620, 621, 7, 4, 0, 0, 621, 623, 3, 130, 65, 3, 622, 618, 1, 0, 0, 0, 622, 620, 1, 0, 0, 0, 623, 632, 1, 0, 0, 0, 624, 625, 10, 2, 0, 0, 625, 626, 7, 5, 0, 0, 626, 631, 3, 130, 65, 3, 627, 628, 10, 1, 0, 0, 628, 629, 7, 4, 0, 0, 629, 631, 3, 130, 65, 2, 630, 624, 1, 0, 0, 0, 630, 627, 1, 0, 0, 0, 631, 634, 1, 0, 0, 0, 632, 630, 1, 0, 0, 0, 632, 633, 1, 0, 0, 0, 633, 131, 1, 0, 0, 0, 634, 632, 1, 0, 0, 0, 635, 636, 6, 66, -1, 0, 636, 644, 3, 142, 71, 0, 637, 644, 3, 46, 23, 0, 638, 644, 3, 134, 67, 0, 639, 640, 5, 100, 0, 0, 640, 641, 3, 122, 61, 0, 641, 642, 5, 101, 0, 0, 642, 644, 1, 0, 0, 0, 643, 635, 1, 0, 0, 0, 643, 637, 1, 0, 0, 0, 643, 638, 1, 0, 0, 0, 643, 639, 1, 0, 0, 0, 644, 650, 1, 0, 0, 0, 645, 646, 10, 1, 0, 0, 646, 647, 5, 61, 0, 0, 647, 649, 3, 10, 5, 0, 648, 645, 1, 0, 0, 0, 649, 652, 1, 0, 0, 0, 650, 648, 1, 0, 0, 0, 650, 651, 1, 0, 0, 0, 651, 133, 1, 0, 0, 0, 652, 650, 1, 0, 0, 0, 653, 654, 3, 136, 68, 0, 654, 668, 5, 100, 0, 0, 655, 669, 5, 90, 0, 0, 656, 661, 3, 122, 61, 0, 657, 658, 5, 63, 0, 0, 658, 660, 3, 122, 61, 0, 659, 657, 1, 0, 0, 0, 660, 663, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 661, 662, 1, 0, 0, 0, 662, 666, 1, 0, 0, 0, 663, 661, 1, 0, 0, 0, 664, 665, 5, 63, 0, 0, 665, 667, 3, 138, 69, 0, 666, 664, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 669, 1, 0, 0, 0, 668, 655, 1, 0, 0, 0, 668, 656, 1, 0, 0, 0, 668, 669, 1, 0, 0, 0, 669, 670, 1, 0, 0, 0, 670, 671, 5, 101, 0, 0, 671, 135, 1, 0, 0, 0, 672, 673, 3, 60, 30, 0, 673, 137, 1, 0, 0, 0, 674, 675, 5, 93, 0, 0, 675, 680, 3, 140, 70, 0, 676, 677, 5, 63, 0, 0, 677, 679, 3, 140, 70, 0, 678, 676, 1, 0, 0, 0, 679, 682, 1, 0, 0, 0, 680, 678, 1, 0, 0, 0, 680, 681, 1, 0, 0, 0, 681, 683, 1, 0, 0, 0, 682, 680, 1, 0, 0, 0, 683, 684, 5, 94, 0, 0, 684, 139, 1, 0, 0, 0, 685, 686, 3, 152, 76, 0, 686, 687, 5, 62, 0, 0, 687, 688, 3, 142, 71, 0, 688, 141, 1, 0, 0, 0, 689, 732, 5, 73, 0, 0, 690, 691, 3, 150, 75, 0, 691, 692, 5, 102, 0, 0, 692, 732, 1, 0, 0, 0, 693, 732, 3, 148, 74, 0, 694, 732, 3, 150, 75, 0, 695, 732, 3, 144, 72, 0, 696, 732, 3, 56, 28, 0, 697, 732, 3, 152, 76, 0, 698, 699, 5, 98, 0, 0, 699, 704, 3, 146, 73, 0, 700, 701, 5, 63, 0, 0, 701, 703, 3, 146, 73, 0, 702, 700, 1, 0, 0, 0, 703, 706, 1, 0, 0, 0, 704, 702, 1, 0, 0, 0, 704, 705, 1, 0, 0, 0, 705, 707, 1, 0, 0, 0, 706, 704, 1, 0, 0, 0, 707, 708, 5, 99, 0, 0, 708, 732, 1, 0, 0, 0, 709, 710, 5, 98, 0, 0, 710, 715, 3, 144, 72, 0, 711, 712, 5, 63, 0, 0, 712, 714, 3, 144, 72, 0, 713, 711, 1, 0, 0, 0, 714, 717, 1, 0, 0, 0, 715, 713, 1, 0, 0, 0, 715, 716, 1, 0, 0, 0, 716, 718, 1, 0, 0, 0, 717, 715, 1, 0, 0, 0, 718, 719, 5, 99, 0, 0, 719, 732, 1, 0, 0, 0, 720, 721, 5, 98, 0, 0, 721, 726, 3, 152, 76, 0, 722, 723, 5, 63, 0, 0, 723, 725, 3, 152, 76, 0, 724, 722, 1, 0, 0, 0, 725, 728, 1, 0, 0, 0, 726, 724, 1, 0, 0, 0, 726, 727, 1, 0, 0, 0, 727, 729, 1, 0, 0, 0, 728, 726, 1, 0, 0, 0, 729, 730, 5, 99, 0, 0, 730, 732, 1, 0, 0, 0, 731, 689, 1, 0, 0, 0, 731, 690, 1, 0, 0, 0, 731, 693, 1, 0, 0, 0, 731, 694, 1, 0, 0, 0, 731, 695, 1, 0, 0, 0, 731, 696, 1, 0, 0, 0, 731, 697, 1, 0, 0, 0, 731, 698, 1, 0, 0, 0, 731, 709, 1, 0, 0, 0, 731, 720, 1, 0, 0, 0, 732, 143, 1, 0, 0, 0, 733, 734, 7, 6, 0, 0, 734, 145, 1, 0, 0, 0, 735, 738, 3, 148, 74, 0, 736, 738, 3, 150, 75, 0, 737, 735, 1, 0, 0, 0, 737, 736, 1, 0, 0, 0, 738, 147, 1, 0, 0, 0, 739, 741, 7, 4, 0, 0, 740, 739, 1, 0, 0, 0, 740, 741, 1, 0, 0, 0, 741, 742, 1, 0, 0, 0, 742, 743, 5, 55, 0, 0, 743, 149, 1, 0, 0, 0, 744, 746, 7, 4, 0, 0, 745, 744, 1, 0, 0, 0, 745, 746, 1, 0, 0, 0, 746, 747, 1, 0, 0, 0, 747, 748, 5, 54, 0, 0, 748, 151, 1, 0, 0, 0, 749, 750, 5, 53, 0, 0, 750, 153, 1, 0, 0, 0, 751, 752, 7, 7, 0, 0, 752, 155, 1, 0, 0, 0, 753, 754, 7, 8, 0, 0, 754, 755, 5, 115, 0, 0, 755, 756, 3, 158, 79, 0, 756, 757, 3, 160, 80, 0, 757, 157, 1, 0, 0, 0, 758, 759, 3, 28, 14, 0, 759, 159, 1, 0, 0, 0, 760, 761, 5, 75, 0, 0, 761, 766, 3, 162, 81, 0, 762, 763, 5, 63, 0, 0, 763, 765, 3, 162, 81, 0, 764, 762, 1, 0, 0, 0, 765, 768, 1, 0, 0, 0, 766, 764, 1, 0, 0, 0, 766, 767, 1, 0, 0, 0, 767, 161, 1, 0, 0, 0, 768, 766, 1, 0, 0, 0, 769, 770, 3, 128, 64, 0, 770, 163, 1, 0, 0, 0, 70, 175, 184, 216, 231, 237, 246, 252, 265, 269, 274, 280, 282, 296, 304, 308, 315, 321, 328, 336, 344, 352, 356, 360, 365, 376, 381, 385, 399, 410, 424, 445, 453, 456, 461, 474, 480, 487, 498, 512, 521, 538, 543, 552, 561, 569, 574, 582, 584, 589, 596, 601, 606, 616, 622, 630, 632, 643, 650, 661, 666, 668, 680, 704, 715, 726, 731, 737, 740, 745, 766] +[4, 1, 139, 772, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 174, 8, 1, 10, 1, 12, 1, 177, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 185, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 217, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 5, 7, 230, 8, 7, 10, 7, 12, 7, 233, 9, 7, 1, 8, 1, 8, 1, 8, 3, 8, 238, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 5, 9, 245, 8, 9, 10, 9, 12, 9, 248, 9, 9, 1, 10, 1, 10, 1, 10, 3, 10, 253, 8, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 264, 8, 13, 10, 13, 12, 13, 267, 9, 13, 1, 13, 3, 13, 270, 8, 13, 1, 14, 1, 14, 1, 14, 3, 14, 275, 8, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 281, 8, 14, 3, 14, 283, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 295, 8, 18, 10, 18, 12, 18, 298, 9, 18, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 3, 20, 305, 8, 20, 1, 20, 1, 20, 3, 20, 309, 8, 20, 1, 21, 1, 21, 1, 21, 5, 21, 314, 8, 21, 10, 21, 12, 21, 317, 9, 21, 1, 22, 1, 22, 1, 22, 3, 22, 322, 8, 22, 1, 23, 1, 23, 1, 23, 5, 23, 327, 8, 23, 10, 23, 12, 23, 330, 9, 23, 1, 24, 1, 24, 1, 24, 5, 24, 335, 8, 24, 10, 24, 12, 24, 338, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 343, 8, 25, 10, 25, 12, 25, 346, 9, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 3, 27, 353, 8, 27, 1, 28, 1, 28, 3, 28, 357, 8, 28, 1, 29, 1, 29, 3, 29, 361, 8, 29, 1, 30, 1, 30, 1, 30, 3, 30, 366, 8, 30, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 375, 8, 32, 10, 32, 12, 32, 378, 9, 32, 1, 33, 1, 33, 3, 33, 382, 8, 33, 1, 33, 1, 33, 3, 33, 386, 8, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 398, 8, 36, 10, 36, 12, 36, 401, 9, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 411, 8, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 5, 41, 423, 8, 41, 10, 41, 12, 41, 426, 9, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 446, 8, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 452, 8, 46, 10, 46, 12, 46, 455, 9, 46, 3, 46, 457, 8, 46, 1, 47, 1, 47, 1, 47, 3, 47, 462, 8, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 475, 8, 49, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 481, 8, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 488, 8, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 4, 53, 497, 8, 53, 11, 53, 12, 53, 498, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 5, 55, 511, 8, 55, 10, 55, 12, 55, 514, 9, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 3, 56, 522, 8, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, 59, 539, 8, 59, 1, 60, 1, 60, 1, 60, 3, 60, 544, 8, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 553, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 560, 8, 61, 10, 61, 12, 61, 563, 9, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 570, 8, 61, 1, 61, 1, 61, 1, 61, 3, 61, 575, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 583, 8, 61, 10, 61, 12, 61, 586, 9, 61, 1, 62, 1, 62, 3, 62, 590, 8, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 3, 62, 597, 8, 62, 1, 62, 1, 62, 1, 62, 3, 62, 602, 8, 62, 1, 63, 1, 63, 1, 63, 3, 63, 607, 8, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 3, 64, 617, 8, 64, 1, 65, 1, 65, 1, 65, 1, 65, 3, 65, 623, 8, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 5, 65, 631, 8, 65, 10, 65, 12, 65, 634, 9, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 3, 66, 644, 8, 66, 1, 66, 1, 66, 1, 66, 5, 66, 649, 8, 66, 10, 66, 12, 66, 652, 9, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 5, 67, 660, 8, 67, 10, 67, 12, 67, 663, 9, 67, 1, 67, 1, 67, 3, 67, 667, 8, 67, 3, 67, 669, 8, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 5, 69, 679, 8, 69, 10, 69, 12, 69, 682, 9, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 703, 8, 71, 10, 71, 12, 71, 706, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 714, 8, 71, 10, 71, 12, 71, 717, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 725, 8, 71, 10, 71, 12, 71, 728, 9, 71, 1, 71, 1, 71, 3, 71, 732, 8, 71, 1, 72, 1, 72, 1, 73, 1, 73, 3, 73, 738, 8, 73, 1, 74, 3, 74, 741, 8, 74, 1, 74, 1, 74, 1, 75, 3, 75, 746, 8, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 5, 80, 765, 8, 80, 10, 80, 12, 80, 768, 9, 80, 1, 81, 1, 81, 1, 81, 0, 5, 2, 110, 122, 130, 132, 82, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 0, 9, 2, 0, 53, 53, 108, 108, 1, 0, 102, 103, 2, 0, 58, 58, 64, 64, 2, 0, 67, 67, 70, 70, 1, 0, 88, 89, 1, 0, 90, 92, 2, 0, 66, 66, 79, 79, 2, 0, 81, 81, 83, 87, 2, 0, 22, 22, 24, 25, 803, 0, 164, 1, 0, 0, 0, 2, 167, 1, 0, 0, 0, 4, 184, 1, 0, 0, 0, 6, 216, 1, 0, 0, 0, 8, 218, 1, 0, 0, 0, 10, 221, 1, 0, 0, 0, 12, 223, 1, 0, 0, 0, 14, 226, 1, 0, 0, 0, 16, 237, 1, 0, 0, 0, 18, 241, 1, 0, 0, 0, 20, 249, 1, 0, 0, 0, 22, 254, 1, 0, 0, 0, 24, 257, 1, 0, 0, 0, 26, 260, 1, 0, 0, 0, 28, 282, 1, 0, 0, 0, 30, 284, 1, 0, 0, 0, 32, 286, 1, 0, 0, 0, 34, 288, 1, 0, 0, 0, 36, 290, 1, 0, 0, 0, 38, 299, 1, 0, 0, 0, 40, 302, 1, 0, 0, 0, 42, 310, 1, 0, 0, 0, 44, 318, 1, 0, 0, 0, 46, 323, 1, 0, 0, 0, 48, 331, 1, 0, 0, 0, 50, 339, 1, 0, 0, 0, 52, 347, 1, 0, 0, 0, 54, 352, 1, 0, 0, 0, 56, 356, 1, 0, 0, 0, 58, 360, 1, 0, 0, 0, 60, 365, 1, 0, 0, 0, 62, 367, 1, 0, 0, 0, 64, 370, 1, 0, 0, 0, 66, 379, 1, 0, 0, 0, 68, 387, 1, 0, 0, 0, 70, 390, 1, 0, 0, 0, 72, 393, 1, 0, 0, 0, 74, 402, 1, 0, 0, 0, 76, 406, 1, 0, 0, 0, 78, 412, 1, 0, 0, 0, 80, 416, 1, 0, 0, 0, 82, 419, 1, 0, 0, 0, 84, 427, 1, 0, 0, 0, 86, 431, 1, 0, 0, 0, 88, 434, 1, 0, 0, 0, 90, 438, 1, 0, 0, 0, 92, 441, 1, 0, 0, 0, 94, 461, 1, 0, 0, 0, 96, 465, 1, 0, 0, 0, 98, 470, 1, 0, 0, 0, 100, 476, 1, 0, 0, 0, 102, 489, 1, 0, 0, 0, 104, 492, 1, 0, 0, 0, 106, 496, 1, 0, 0, 0, 108, 500, 1, 0, 0, 0, 110, 504, 1, 0, 0, 0, 112, 521, 1, 0, 0, 0, 114, 523, 1, 0, 0, 0, 116, 525, 1, 0, 0, 0, 118, 532, 1, 0, 0, 0, 120, 540, 1, 0, 0, 0, 122, 574, 1, 0, 0, 0, 124, 601, 1, 0, 0, 0, 126, 603, 1, 0, 0, 0, 128, 616, 1, 0, 0, 0, 130, 622, 1, 0, 0, 0, 132, 643, 1, 0, 0, 0, 134, 653, 1, 0, 0, 0, 136, 672, 1, 0, 0, 0, 138, 674, 1, 0, 0, 0, 140, 685, 1, 0, 0, 0, 142, 731, 1, 0, 0, 0, 144, 733, 1, 0, 0, 0, 146, 737, 1, 0, 0, 0, 148, 740, 1, 0, 0, 0, 150, 745, 1, 0, 0, 0, 152, 749, 1, 0, 0, 0, 154, 751, 1, 0, 0, 0, 156, 753, 1, 0, 0, 0, 158, 758, 1, 0, 0, 0, 160, 760, 1, 0, 0, 0, 162, 769, 1, 0, 0, 0, 164, 165, 3, 2, 1, 0, 165, 166, 5, 0, 0, 1, 166, 1, 1, 0, 0, 0, 167, 168, 6, 1, -1, 0, 168, 169, 3, 4, 2, 0, 169, 175, 1, 0, 0, 0, 170, 171, 10, 1, 0, 0, 171, 172, 5, 52, 0, 0, 172, 174, 3, 6, 3, 0, 173, 170, 1, 0, 0, 0, 174, 177, 1, 0, 0, 0, 175, 173, 1, 0, 0, 0, 175, 176, 1, 0, 0, 0, 176, 3, 1, 0, 0, 0, 177, 175, 1, 0, 0, 0, 178, 185, 3, 86, 43, 0, 179, 185, 3, 22, 11, 0, 180, 185, 3, 12, 6, 0, 181, 185, 3, 90, 45, 0, 182, 183, 4, 2, 1, 0, 183, 185, 3, 24, 12, 0, 184, 178, 1, 0, 0, 0, 184, 179, 1, 0, 0, 0, 184, 180, 1, 0, 0, 0, 184, 181, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 5, 1, 0, 0, 0, 186, 217, 3, 38, 19, 0, 187, 217, 3, 8, 4, 0, 188, 217, 3, 68, 34, 0, 189, 217, 3, 62, 31, 0, 190, 217, 3, 40, 20, 0, 191, 217, 3, 64, 32, 0, 192, 217, 3, 70, 35, 0, 193, 217, 3, 72, 36, 0, 194, 217, 3, 76, 38, 0, 195, 217, 3, 78, 39, 0, 196, 217, 3, 92, 46, 0, 197, 217, 3, 80, 40, 0, 198, 217, 3, 156, 78, 0, 199, 217, 3, 100, 50, 0, 200, 201, 4, 3, 2, 0, 201, 217, 3, 98, 49, 0, 202, 203, 4, 3, 3, 0, 203, 217, 3, 96, 48, 0, 204, 205, 4, 3, 4, 0, 205, 217, 3, 118, 59, 0, 206, 207, 4, 3, 5, 0, 207, 217, 3, 102, 51, 0, 208, 209, 4, 3, 6, 0, 209, 217, 3, 104, 52, 0, 210, 211, 4, 3, 7, 0, 211, 217, 3, 116, 58, 0, 212, 213, 4, 3, 8, 0, 213, 217, 3, 114, 57, 0, 214, 215, 4, 3, 9, 0, 215, 217, 3, 120, 60, 0, 216, 186, 1, 0, 0, 0, 216, 187, 1, 0, 0, 0, 216, 188, 1, 0, 0, 0, 216, 189, 1, 0, 0, 0, 216, 190, 1, 0, 0, 0, 216, 191, 1, 0, 0, 0, 216, 192, 1, 0, 0, 0, 216, 193, 1, 0, 0, 0, 216, 194, 1, 0, 0, 0, 216, 195, 1, 0, 0, 0, 216, 196, 1, 0, 0, 0, 216, 197, 1, 0, 0, 0, 216, 198, 1, 0, 0, 0, 216, 199, 1, 0, 0, 0, 216, 200, 1, 0, 0, 0, 216, 202, 1, 0, 0, 0, 216, 204, 1, 0, 0, 0, 216, 206, 1, 0, 0, 0, 216, 208, 1, 0, 0, 0, 216, 210, 1, 0, 0, 0, 216, 212, 1, 0, 0, 0, 216, 214, 1, 0, 0, 0, 217, 7, 1, 0, 0, 0, 218, 219, 5, 14, 0, 0, 219, 220, 3, 122, 61, 0, 220, 9, 1, 0, 0, 0, 221, 222, 3, 52, 26, 0, 222, 11, 1, 0, 0, 0, 223, 224, 5, 11, 0, 0, 224, 225, 3, 14, 7, 0, 225, 13, 1, 0, 0, 0, 226, 231, 3, 16, 8, 0, 227, 228, 5, 63, 0, 0, 228, 230, 3, 16, 8, 0, 229, 227, 1, 0, 0, 0, 230, 233, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 15, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 234, 235, 3, 46, 23, 0, 235, 236, 5, 59, 0, 0, 236, 238, 1, 0, 0, 0, 237, 234, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 239, 1, 0, 0, 0, 239, 240, 3, 122, 61, 0, 240, 17, 1, 0, 0, 0, 241, 246, 3, 20, 10, 0, 242, 243, 5, 63, 0, 0, 243, 245, 3, 20, 10, 0, 244, 242, 1, 0, 0, 0, 245, 248, 1, 0, 0, 0, 246, 244, 1, 0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 19, 1, 0, 0, 0, 248, 246, 1, 0, 0, 0, 249, 252, 3, 46, 23, 0, 250, 251, 5, 59, 0, 0, 251, 253, 3, 122, 61, 0, 252, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 21, 1, 0, 0, 0, 254, 255, 5, 19, 0, 0, 255, 256, 3, 26, 13, 0, 256, 23, 1, 0, 0, 0, 257, 258, 5, 20, 0, 0, 258, 259, 3, 26, 13, 0, 259, 25, 1, 0, 0, 0, 260, 265, 3, 28, 14, 0, 261, 262, 5, 63, 0, 0, 262, 264, 3, 28, 14, 0, 263, 261, 1, 0, 0, 0, 264, 267, 1, 0, 0, 0, 265, 263, 1, 0, 0, 0, 265, 266, 1, 0, 0, 0, 266, 269, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 268, 270, 3, 36, 18, 0, 269, 268, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 27, 1, 0, 0, 0, 271, 272, 3, 30, 15, 0, 272, 273, 5, 62, 0, 0, 273, 275, 1, 0, 0, 0, 274, 271, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 276, 1, 0, 0, 0, 276, 283, 3, 34, 17, 0, 277, 280, 3, 34, 17, 0, 278, 279, 5, 61, 0, 0, 279, 281, 3, 32, 16, 0, 280, 278, 1, 0, 0, 0, 280, 281, 1, 0, 0, 0, 281, 283, 1, 0, 0, 0, 282, 274, 1, 0, 0, 0, 282, 277, 1, 0, 0, 0, 283, 29, 1, 0, 0, 0, 284, 285, 7, 0, 0, 0, 285, 31, 1, 0, 0, 0, 286, 287, 7, 0, 0, 0, 287, 33, 1, 0, 0, 0, 288, 289, 7, 0, 0, 0, 289, 35, 1, 0, 0, 0, 290, 291, 5, 107, 0, 0, 291, 296, 5, 108, 0, 0, 292, 293, 5, 63, 0, 0, 293, 295, 5, 108, 0, 0, 294, 292, 1, 0, 0, 0, 295, 298, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 37, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 299, 300, 5, 8, 0, 0, 300, 301, 3, 14, 7, 0, 301, 39, 1, 0, 0, 0, 302, 304, 5, 13, 0, 0, 303, 305, 3, 42, 21, 0, 304, 303, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 308, 1, 0, 0, 0, 306, 307, 5, 60, 0, 0, 307, 309, 3, 14, 7, 0, 308, 306, 1, 0, 0, 0, 308, 309, 1, 0, 0, 0, 309, 41, 1, 0, 0, 0, 310, 315, 3, 44, 22, 0, 311, 312, 5, 63, 0, 0, 312, 314, 3, 44, 22, 0, 313, 311, 1, 0, 0, 0, 314, 317, 1, 0, 0, 0, 315, 313, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 43, 1, 0, 0, 0, 317, 315, 1, 0, 0, 0, 318, 321, 3, 16, 8, 0, 319, 320, 5, 14, 0, 0, 320, 322, 3, 122, 61, 0, 321, 319, 1, 0, 0, 0, 321, 322, 1, 0, 0, 0, 322, 45, 1, 0, 0, 0, 323, 328, 3, 60, 30, 0, 324, 325, 5, 65, 0, 0, 325, 327, 3, 60, 30, 0, 326, 324, 1, 0, 0, 0, 327, 330, 1, 0, 0, 0, 328, 326, 1, 0, 0, 0, 328, 329, 1, 0, 0, 0, 329, 47, 1, 0, 0, 0, 330, 328, 1, 0, 0, 0, 331, 336, 3, 54, 27, 0, 332, 333, 5, 65, 0, 0, 333, 335, 3, 54, 27, 0, 334, 332, 1, 0, 0, 0, 335, 338, 1, 0, 0, 0, 336, 334, 1, 0, 0, 0, 336, 337, 1, 0, 0, 0, 337, 49, 1, 0, 0, 0, 338, 336, 1, 0, 0, 0, 339, 344, 3, 48, 24, 0, 340, 341, 5, 63, 0, 0, 341, 343, 3, 48, 24, 0, 342, 340, 1, 0, 0, 0, 343, 346, 1, 0, 0, 0, 344, 342, 1, 0, 0, 0, 344, 345, 1, 0, 0, 0, 345, 51, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 347, 348, 7, 1, 0, 0, 348, 53, 1, 0, 0, 0, 349, 353, 5, 129, 0, 0, 350, 353, 3, 56, 28, 0, 351, 353, 3, 58, 29, 0, 352, 349, 1, 0, 0, 0, 352, 350, 1, 0, 0, 0, 352, 351, 1, 0, 0, 0, 353, 55, 1, 0, 0, 0, 354, 357, 5, 77, 0, 0, 355, 357, 5, 96, 0, 0, 356, 354, 1, 0, 0, 0, 356, 355, 1, 0, 0, 0, 357, 57, 1, 0, 0, 0, 358, 361, 5, 95, 0, 0, 359, 361, 5, 97, 0, 0, 360, 358, 1, 0, 0, 0, 360, 359, 1, 0, 0, 0, 361, 59, 1, 0, 0, 0, 362, 366, 3, 52, 26, 0, 363, 366, 3, 56, 28, 0, 364, 366, 3, 58, 29, 0, 365, 362, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 365, 364, 1, 0, 0, 0, 366, 61, 1, 0, 0, 0, 367, 368, 5, 10, 0, 0, 368, 369, 5, 54, 0, 0, 369, 63, 1, 0, 0, 0, 370, 371, 5, 12, 0, 0, 371, 376, 3, 66, 33, 0, 372, 373, 5, 63, 0, 0, 373, 375, 3, 66, 33, 0, 374, 372, 1, 0, 0, 0, 375, 378, 1, 0, 0, 0, 376, 374, 1, 0, 0, 0, 376, 377, 1, 0, 0, 0, 377, 65, 1, 0, 0, 0, 378, 376, 1, 0, 0, 0, 379, 381, 3, 122, 61, 0, 380, 382, 7, 2, 0, 0, 381, 380, 1, 0, 0, 0, 381, 382, 1, 0, 0, 0, 382, 385, 1, 0, 0, 0, 383, 384, 5, 74, 0, 0, 384, 386, 7, 3, 0, 0, 385, 383, 1, 0, 0, 0, 385, 386, 1, 0, 0, 0, 386, 67, 1, 0, 0, 0, 387, 388, 5, 29, 0, 0, 388, 389, 3, 50, 25, 0, 389, 69, 1, 0, 0, 0, 390, 391, 5, 28, 0, 0, 391, 392, 3, 50, 25, 0, 392, 71, 1, 0, 0, 0, 393, 394, 5, 32, 0, 0, 394, 399, 3, 74, 37, 0, 395, 396, 5, 63, 0, 0, 396, 398, 3, 74, 37, 0, 397, 395, 1, 0, 0, 0, 398, 401, 1, 0, 0, 0, 399, 397, 1, 0, 0, 0, 399, 400, 1, 0, 0, 0, 400, 73, 1, 0, 0, 0, 401, 399, 1, 0, 0, 0, 402, 403, 3, 48, 24, 0, 403, 404, 5, 57, 0, 0, 404, 405, 3, 48, 24, 0, 405, 75, 1, 0, 0, 0, 406, 407, 5, 7, 0, 0, 407, 408, 3, 132, 66, 0, 408, 410, 3, 152, 76, 0, 409, 411, 3, 82, 41, 0, 410, 409, 1, 0, 0, 0, 410, 411, 1, 0, 0, 0, 411, 77, 1, 0, 0, 0, 412, 413, 5, 9, 0, 0, 413, 414, 3, 132, 66, 0, 414, 415, 3, 152, 76, 0, 415, 79, 1, 0, 0, 0, 416, 417, 5, 27, 0, 0, 417, 418, 3, 46, 23, 0, 418, 81, 1, 0, 0, 0, 419, 424, 3, 84, 42, 0, 420, 421, 5, 63, 0, 0, 421, 423, 3, 84, 42, 0, 422, 420, 1, 0, 0, 0, 423, 426, 1, 0, 0, 0, 424, 422, 1, 0, 0, 0, 424, 425, 1, 0, 0, 0, 425, 83, 1, 0, 0, 0, 426, 424, 1, 0, 0, 0, 427, 428, 3, 52, 26, 0, 428, 429, 5, 59, 0, 0, 429, 430, 3, 142, 71, 0, 430, 85, 1, 0, 0, 0, 431, 432, 5, 6, 0, 0, 432, 433, 3, 88, 44, 0, 433, 87, 1, 0, 0, 0, 434, 435, 5, 98, 0, 0, 435, 436, 3, 2, 1, 0, 436, 437, 5, 99, 0, 0, 437, 89, 1, 0, 0, 0, 438, 439, 5, 33, 0, 0, 439, 440, 5, 136, 0, 0, 440, 91, 1, 0, 0, 0, 441, 442, 5, 5, 0, 0, 442, 445, 5, 38, 0, 0, 443, 444, 5, 75, 0, 0, 444, 446, 3, 48, 24, 0, 445, 443, 1, 0, 0, 0, 445, 446, 1, 0, 0, 0, 446, 456, 1, 0, 0, 0, 447, 448, 5, 80, 0, 0, 448, 453, 3, 94, 47, 0, 449, 450, 5, 63, 0, 0, 450, 452, 3, 94, 47, 0, 451, 449, 1, 0, 0, 0, 452, 455, 1, 0, 0, 0, 453, 451, 1, 0, 0, 0, 453, 454, 1, 0, 0, 0, 454, 457, 1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 456, 447, 1, 0, 0, 0, 456, 457, 1, 0, 0, 0, 457, 93, 1, 0, 0, 0, 458, 459, 3, 48, 24, 0, 459, 460, 5, 59, 0, 0, 460, 462, 1, 0, 0, 0, 461, 458, 1, 0, 0, 0, 461, 462, 1, 0, 0, 0, 462, 463, 1, 0, 0, 0, 463, 464, 3, 48, 24, 0, 464, 95, 1, 0, 0, 0, 465, 466, 5, 26, 0, 0, 466, 467, 3, 28, 14, 0, 467, 468, 5, 75, 0, 0, 468, 469, 3, 50, 25, 0, 469, 97, 1, 0, 0, 0, 470, 471, 5, 16, 0, 0, 471, 474, 3, 42, 21, 0, 472, 473, 5, 60, 0, 0, 473, 475, 3, 14, 7, 0, 474, 472, 1, 0, 0, 0, 474, 475, 1, 0, 0, 0, 475, 99, 1, 0, 0, 0, 476, 477, 5, 4, 0, 0, 477, 480, 3, 46, 23, 0, 478, 479, 5, 75, 0, 0, 479, 481, 3, 46, 23, 0, 480, 478, 1, 0, 0, 0, 480, 481, 1, 0, 0, 0, 481, 487, 1, 0, 0, 0, 482, 483, 5, 57, 0, 0, 483, 484, 3, 46, 23, 0, 484, 485, 5, 63, 0, 0, 485, 486, 3, 46, 23, 0, 486, 488, 1, 0, 0, 0, 487, 482, 1, 0, 0, 0, 487, 488, 1, 0, 0, 0, 488, 101, 1, 0, 0, 0, 489, 490, 5, 30, 0, 0, 490, 491, 3, 50, 25, 0, 491, 103, 1, 0, 0, 0, 492, 493, 5, 21, 0, 0, 493, 494, 3, 106, 53, 0, 494, 105, 1, 0, 0, 0, 495, 497, 3, 108, 54, 0, 496, 495, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 496, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 107, 1, 0, 0, 0, 500, 501, 5, 100, 0, 0, 501, 502, 3, 110, 55, 0, 502, 503, 5, 101, 0, 0, 503, 109, 1, 0, 0, 0, 504, 505, 6, 55, -1, 0, 505, 506, 3, 112, 56, 0, 506, 512, 1, 0, 0, 0, 507, 508, 10, 1, 0, 0, 508, 509, 5, 52, 0, 0, 509, 511, 3, 112, 56, 0, 510, 507, 1, 0, 0, 0, 511, 514, 1, 0, 0, 0, 512, 510, 1, 0, 0, 0, 512, 513, 1, 0, 0, 0, 513, 111, 1, 0, 0, 0, 514, 512, 1, 0, 0, 0, 515, 522, 3, 38, 19, 0, 516, 522, 3, 8, 4, 0, 517, 522, 3, 62, 31, 0, 518, 522, 3, 40, 20, 0, 519, 522, 3, 64, 32, 0, 520, 522, 3, 76, 38, 0, 521, 515, 1, 0, 0, 0, 521, 516, 1, 0, 0, 0, 521, 517, 1, 0, 0, 0, 521, 518, 1, 0, 0, 0, 521, 519, 1, 0, 0, 0, 521, 520, 1, 0, 0, 0, 522, 113, 1, 0, 0, 0, 523, 524, 5, 31, 0, 0, 524, 115, 1, 0, 0, 0, 525, 526, 5, 17, 0, 0, 526, 527, 3, 142, 71, 0, 527, 528, 5, 75, 0, 0, 528, 529, 3, 18, 9, 0, 529, 530, 5, 80, 0, 0, 530, 531, 3, 60, 30, 0, 531, 117, 1, 0, 0, 0, 532, 533, 5, 15, 0, 0, 533, 534, 3, 132, 66, 0, 534, 535, 5, 80, 0, 0, 535, 538, 3, 60, 30, 0, 536, 537, 5, 57, 0, 0, 537, 539, 3, 46, 23, 0, 538, 536, 1, 0, 0, 0, 538, 539, 1, 0, 0, 0, 539, 119, 1, 0, 0, 0, 540, 541, 5, 18, 0, 0, 541, 543, 3, 148, 74, 0, 542, 544, 3, 150, 75, 0, 543, 542, 1, 0, 0, 0, 543, 544, 1, 0, 0, 0, 544, 121, 1, 0, 0, 0, 545, 546, 6, 61, -1, 0, 546, 547, 5, 72, 0, 0, 547, 575, 3, 122, 61, 8, 548, 575, 3, 128, 64, 0, 549, 575, 3, 124, 62, 0, 550, 552, 3, 128, 64, 0, 551, 553, 5, 72, 0, 0, 552, 551, 1, 0, 0, 0, 552, 553, 1, 0, 0, 0, 553, 554, 1, 0, 0, 0, 554, 555, 5, 68, 0, 0, 555, 556, 5, 100, 0, 0, 556, 561, 3, 128, 64, 0, 557, 558, 5, 63, 0, 0, 558, 560, 3, 128, 64, 0, 559, 557, 1, 0, 0, 0, 560, 563, 1, 0, 0, 0, 561, 559, 1, 0, 0, 0, 561, 562, 1, 0, 0, 0, 562, 564, 1, 0, 0, 0, 563, 561, 1, 0, 0, 0, 564, 565, 5, 101, 0, 0, 565, 575, 1, 0, 0, 0, 566, 567, 3, 128, 64, 0, 567, 569, 5, 69, 0, 0, 568, 570, 5, 72, 0, 0, 569, 568, 1, 0, 0, 0, 569, 570, 1, 0, 0, 0, 570, 571, 1, 0, 0, 0, 571, 572, 5, 73, 0, 0, 572, 575, 1, 0, 0, 0, 573, 575, 3, 126, 63, 0, 574, 545, 1, 0, 0, 0, 574, 548, 1, 0, 0, 0, 574, 549, 1, 0, 0, 0, 574, 550, 1, 0, 0, 0, 574, 566, 1, 0, 0, 0, 574, 573, 1, 0, 0, 0, 575, 584, 1, 0, 0, 0, 576, 577, 10, 5, 0, 0, 577, 578, 5, 56, 0, 0, 578, 583, 3, 122, 61, 6, 579, 580, 10, 4, 0, 0, 580, 581, 5, 76, 0, 0, 581, 583, 3, 122, 61, 5, 582, 576, 1, 0, 0, 0, 582, 579, 1, 0, 0, 0, 583, 586, 1, 0, 0, 0, 584, 582, 1, 0, 0, 0, 584, 585, 1, 0, 0, 0, 585, 123, 1, 0, 0, 0, 586, 584, 1, 0, 0, 0, 587, 589, 3, 128, 64, 0, 588, 590, 5, 72, 0, 0, 589, 588, 1, 0, 0, 0, 589, 590, 1, 0, 0, 0, 590, 591, 1, 0, 0, 0, 591, 592, 5, 71, 0, 0, 592, 593, 3, 152, 76, 0, 593, 602, 1, 0, 0, 0, 594, 596, 3, 128, 64, 0, 595, 597, 5, 72, 0, 0, 596, 595, 1, 0, 0, 0, 596, 597, 1, 0, 0, 0, 597, 598, 1, 0, 0, 0, 598, 599, 5, 78, 0, 0, 599, 600, 3, 152, 76, 0, 600, 602, 1, 0, 0, 0, 601, 587, 1, 0, 0, 0, 601, 594, 1, 0, 0, 0, 602, 125, 1, 0, 0, 0, 603, 606, 3, 46, 23, 0, 604, 605, 5, 61, 0, 0, 605, 607, 3, 10, 5, 0, 606, 604, 1, 0, 0, 0, 606, 607, 1, 0, 0, 0, 607, 608, 1, 0, 0, 0, 608, 609, 5, 62, 0, 0, 609, 610, 3, 142, 71, 0, 610, 127, 1, 0, 0, 0, 611, 617, 3, 130, 65, 0, 612, 613, 3, 130, 65, 0, 613, 614, 3, 154, 77, 0, 614, 615, 3, 130, 65, 0, 615, 617, 1, 0, 0, 0, 616, 611, 1, 0, 0, 0, 616, 612, 1, 0, 0, 0, 617, 129, 1, 0, 0, 0, 618, 619, 6, 65, -1, 0, 619, 623, 3, 132, 66, 0, 620, 621, 7, 4, 0, 0, 621, 623, 3, 130, 65, 3, 622, 618, 1, 0, 0, 0, 622, 620, 1, 0, 0, 0, 623, 632, 1, 0, 0, 0, 624, 625, 10, 2, 0, 0, 625, 626, 7, 5, 0, 0, 626, 631, 3, 130, 65, 3, 627, 628, 10, 1, 0, 0, 628, 629, 7, 4, 0, 0, 629, 631, 3, 130, 65, 2, 630, 624, 1, 0, 0, 0, 630, 627, 1, 0, 0, 0, 631, 634, 1, 0, 0, 0, 632, 630, 1, 0, 0, 0, 632, 633, 1, 0, 0, 0, 633, 131, 1, 0, 0, 0, 634, 632, 1, 0, 0, 0, 635, 636, 6, 66, -1, 0, 636, 644, 3, 142, 71, 0, 637, 644, 3, 46, 23, 0, 638, 644, 3, 134, 67, 0, 639, 640, 5, 100, 0, 0, 640, 641, 3, 122, 61, 0, 641, 642, 5, 101, 0, 0, 642, 644, 1, 0, 0, 0, 643, 635, 1, 0, 0, 0, 643, 637, 1, 0, 0, 0, 643, 638, 1, 0, 0, 0, 643, 639, 1, 0, 0, 0, 644, 650, 1, 0, 0, 0, 645, 646, 10, 1, 0, 0, 646, 647, 5, 61, 0, 0, 647, 649, 3, 10, 5, 0, 648, 645, 1, 0, 0, 0, 649, 652, 1, 0, 0, 0, 650, 648, 1, 0, 0, 0, 650, 651, 1, 0, 0, 0, 651, 133, 1, 0, 0, 0, 652, 650, 1, 0, 0, 0, 653, 654, 3, 136, 68, 0, 654, 668, 5, 100, 0, 0, 655, 669, 5, 90, 0, 0, 656, 661, 3, 122, 61, 0, 657, 658, 5, 63, 0, 0, 658, 660, 3, 122, 61, 0, 659, 657, 1, 0, 0, 0, 660, 663, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 661, 662, 1, 0, 0, 0, 662, 666, 1, 0, 0, 0, 663, 661, 1, 0, 0, 0, 664, 665, 5, 63, 0, 0, 665, 667, 3, 138, 69, 0, 666, 664, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 669, 1, 0, 0, 0, 668, 655, 1, 0, 0, 0, 668, 656, 1, 0, 0, 0, 668, 669, 1, 0, 0, 0, 669, 670, 1, 0, 0, 0, 670, 671, 5, 101, 0, 0, 671, 135, 1, 0, 0, 0, 672, 673, 3, 60, 30, 0, 673, 137, 1, 0, 0, 0, 674, 675, 5, 93, 0, 0, 675, 680, 3, 140, 70, 0, 676, 677, 5, 63, 0, 0, 677, 679, 3, 140, 70, 0, 678, 676, 1, 0, 0, 0, 679, 682, 1, 0, 0, 0, 680, 678, 1, 0, 0, 0, 680, 681, 1, 0, 0, 0, 681, 683, 1, 0, 0, 0, 682, 680, 1, 0, 0, 0, 683, 684, 5, 94, 0, 0, 684, 139, 1, 0, 0, 0, 685, 686, 3, 152, 76, 0, 686, 687, 5, 62, 0, 0, 687, 688, 3, 142, 71, 0, 688, 141, 1, 0, 0, 0, 689, 732, 5, 73, 0, 0, 690, 691, 3, 150, 75, 0, 691, 692, 5, 102, 0, 0, 692, 732, 1, 0, 0, 0, 693, 732, 3, 148, 74, 0, 694, 732, 3, 150, 75, 0, 695, 732, 3, 144, 72, 0, 696, 732, 3, 56, 28, 0, 697, 732, 3, 152, 76, 0, 698, 699, 5, 98, 0, 0, 699, 704, 3, 146, 73, 0, 700, 701, 5, 63, 0, 0, 701, 703, 3, 146, 73, 0, 702, 700, 1, 0, 0, 0, 703, 706, 1, 0, 0, 0, 704, 702, 1, 0, 0, 0, 704, 705, 1, 0, 0, 0, 705, 707, 1, 0, 0, 0, 706, 704, 1, 0, 0, 0, 707, 708, 5, 99, 0, 0, 708, 732, 1, 0, 0, 0, 709, 710, 5, 98, 0, 0, 710, 715, 3, 144, 72, 0, 711, 712, 5, 63, 0, 0, 712, 714, 3, 144, 72, 0, 713, 711, 1, 0, 0, 0, 714, 717, 1, 0, 0, 0, 715, 713, 1, 0, 0, 0, 715, 716, 1, 0, 0, 0, 716, 718, 1, 0, 0, 0, 717, 715, 1, 0, 0, 0, 718, 719, 5, 99, 0, 0, 719, 732, 1, 0, 0, 0, 720, 721, 5, 98, 0, 0, 721, 726, 3, 152, 76, 0, 722, 723, 5, 63, 0, 0, 723, 725, 3, 152, 76, 0, 724, 722, 1, 0, 0, 0, 725, 728, 1, 0, 0, 0, 726, 724, 1, 0, 0, 0, 726, 727, 1, 0, 0, 0, 727, 729, 1, 0, 0, 0, 728, 726, 1, 0, 0, 0, 729, 730, 5, 99, 0, 0, 730, 732, 1, 0, 0, 0, 731, 689, 1, 0, 0, 0, 731, 690, 1, 0, 0, 0, 731, 693, 1, 0, 0, 0, 731, 694, 1, 0, 0, 0, 731, 695, 1, 0, 0, 0, 731, 696, 1, 0, 0, 0, 731, 697, 1, 0, 0, 0, 731, 698, 1, 0, 0, 0, 731, 709, 1, 0, 0, 0, 731, 720, 1, 0, 0, 0, 732, 143, 1, 0, 0, 0, 733, 734, 7, 6, 0, 0, 734, 145, 1, 0, 0, 0, 735, 738, 3, 148, 74, 0, 736, 738, 3, 150, 75, 0, 737, 735, 1, 0, 0, 0, 737, 736, 1, 0, 0, 0, 738, 147, 1, 0, 0, 0, 739, 741, 7, 4, 0, 0, 740, 739, 1, 0, 0, 0, 740, 741, 1, 0, 0, 0, 741, 742, 1, 0, 0, 0, 742, 743, 5, 55, 0, 0, 743, 149, 1, 0, 0, 0, 744, 746, 7, 4, 0, 0, 745, 744, 1, 0, 0, 0, 745, 746, 1, 0, 0, 0, 746, 747, 1, 0, 0, 0, 747, 748, 5, 54, 0, 0, 748, 151, 1, 0, 0, 0, 749, 750, 5, 53, 0, 0, 750, 153, 1, 0, 0, 0, 751, 752, 7, 7, 0, 0, 752, 155, 1, 0, 0, 0, 753, 754, 7, 8, 0, 0, 754, 755, 5, 115, 0, 0, 755, 756, 3, 158, 79, 0, 756, 757, 3, 160, 80, 0, 757, 157, 1, 0, 0, 0, 758, 759, 3, 28, 14, 0, 759, 159, 1, 0, 0, 0, 760, 761, 5, 75, 0, 0, 761, 766, 3, 162, 81, 0, 762, 763, 5, 63, 0, 0, 763, 765, 3, 162, 81, 0, 764, 762, 1, 0, 0, 0, 765, 768, 1, 0, 0, 0, 766, 764, 1, 0, 0, 0, 766, 767, 1, 0, 0, 0, 767, 161, 1, 0, 0, 0, 768, 766, 1, 0, 0, 0, 769, 770, 3, 128, 64, 0, 770, 163, 1, 0, 0, 0, 70, 175, 184, 216, 231, 237, 246, 252, 265, 269, 274, 280, 282, 296, 304, 308, 315, 321, 328, 336, 344, 352, 356, 360, 365, 376, 381, 385, 399, 410, 424, 445, 453, 456, 461, 474, 480, 487, 498, 512, 521, 538, 543, 552, 561, 569, 574, 582, 584, 589, 596, 601, 606, 616, 622, 630, 632, 643, 650, 661, 666, 668, 680, 704, 715, 726, 731, 737, 740, 745, 766] \ No newline at end of file diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java index 1ffe9eb44617e..e9e792206e76a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.java @@ -25,83 +25,83 @@ public class EsqlBaseParser extends ParserConfig { protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); public static final int - LINE_COMMENT=1, MULTILINE_COMMENT=2, WS=3, CHANGE_POINT=4, ENRICH=5, EXPLAIN=6, - DISSECT=7, EVAL=8, GROK=9, LIMIT=10, ROW=11, SORT=12, STATS=13, WHERE=14, - DEV_COMPLETION=15, DEV_INLINESTATS=16, DEV_RERANK=17, DEV_SAMPLE=18, FROM=19, - DEV_TIME_SERIES=20, DEV_FORK=21, JOIN_LOOKUP=22, DEV_JOIN_FULL=23, DEV_JOIN_LEFT=24, - DEV_JOIN_RIGHT=25, DEV_LOOKUP=26, MV_EXPAND=27, DROP=28, KEEP=29, DEV_INSIST=30, - DEV_RRF=31, RENAME=32, SHOW=33, UNKNOWN_CMD=34, CHANGE_POINT_LINE_COMMENT=35, - CHANGE_POINT_MULTILINE_COMMENT=36, CHANGE_POINT_WS=37, ENRICH_POLICY_NAME=38, - ENRICH_LINE_COMMENT=39, ENRICH_MULTILINE_COMMENT=40, ENRICH_WS=41, ENRICH_FIELD_LINE_COMMENT=42, - ENRICH_FIELD_MULTILINE_COMMENT=43, ENRICH_FIELD_WS=44, SETTING=45, SETTING_LINE_COMMENT=46, - SETTTING_MULTILINE_COMMENT=47, SETTING_WS=48, EXPLAIN_WS=49, EXPLAIN_LINE_COMMENT=50, - EXPLAIN_MULTILINE_COMMENT=51, PIPE=52, QUOTED_STRING=53, INTEGER_LITERAL=54, - DECIMAL_LITERAL=55, AND=56, AS=57, ASC=58, ASSIGN=59, BY=60, CAST_OP=61, - COLON=62, COMMA=63, DESC=64, DOT=65, FALSE=66, FIRST=67, IN=68, IS=69, - LAST=70, LIKE=71, NOT=72, NULL=73, NULLS=74, ON=75, OR=76, PARAM=77, RLIKE=78, - TRUE=79, WITH=80, EQ=81, CIEQ=82, NEQ=83, LT=84, LTE=85, GT=86, GTE=87, - PLUS=88, MINUS=89, ASTERISK=90, SLASH=91, PERCENT=92, LEFT_BRACES=93, - RIGHT_BRACES=94, DOUBLE_PARAMS=95, NAMED_OR_POSITIONAL_PARAM=96, NAMED_OR_POSITIONAL_DOUBLE_PARAMS=97, - OPENING_BRACKET=98, CLOSING_BRACKET=99, LP=100, RP=101, UNQUOTED_IDENTIFIER=102, - QUOTED_IDENTIFIER=103, EXPR_LINE_COMMENT=104, EXPR_MULTILINE_COMMENT=105, - EXPR_WS=106, METADATA=107, UNQUOTED_SOURCE=108, FROM_LINE_COMMENT=109, - FROM_MULTILINE_COMMENT=110, FROM_WS=111, FORK_WS=112, FORK_LINE_COMMENT=113, - FORK_MULTILINE_COMMENT=114, JOIN=115, USING=116, JOIN_LINE_COMMENT=117, - JOIN_MULTILINE_COMMENT=118, JOIN_WS=119, LOOKUP_LINE_COMMENT=120, LOOKUP_MULTILINE_COMMENT=121, - LOOKUP_WS=122, LOOKUP_FIELD_LINE_COMMENT=123, LOOKUP_FIELD_MULTILINE_COMMENT=124, - LOOKUP_FIELD_WS=125, MVEXPAND_LINE_COMMENT=126, MVEXPAND_MULTILINE_COMMENT=127, - MVEXPAND_WS=128, ID_PATTERN=129, PROJECT_LINE_COMMENT=130, PROJECT_MULTILINE_COMMENT=131, - PROJECT_WS=132, RENAME_LINE_COMMENT=133, RENAME_MULTILINE_COMMENT=134, - RENAME_WS=135, INFO=136, SHOW_LINE_COMMENT=137, SHOW_MULTILINE_COMMENT=138, + LINE_COMMENT=1, MULTILINE_COMMENT=2, WS=3, CHANGE_POINT=4, ENRICH=5, EXPLAIN=6, + DISSECT=7, EVAL=8, GROK=9, LIMIT=10, ROW=11, SORT=12, STATS=13, WHERE=14, + DEV_COMPLETION=15, DEV_INLINESTATS=16, DEV_RERANK=17, DEV_SAMPLE=18, FROM=19, + DEV_TIME_SERIES=20, DEV_FORK=21, JOIN_LOOKUP=22, DEV_JOIN_FULL=23, DEV_JOIN_LEFT=24, + DEV_JOIN_RIGHT=25, DEV_LOOKUP=26, MV_EXPAND=27, DROP=28, KEEP=29, DEV_INSIST=30, + DEV_RRF=31, RENAME=32, SHOW=33, UNKNOWN_CMD=34, CHANGE_POINT_LINE_COMMENT=35, + CHANGE_POINT_MULTILINE_COMMENT=36, CHANGE_POINT_WS=37, ENRICH_POLICY_NAME=38, + ENRICH_LINE_COMMENT=39, ENRICH_MULTILINE_COMMENT=40, ENRICH_WS=41, ENRICH_FIELD_LINE_COMMENT=42, + ENRICH_FIELD_MULTILINE_COMMENT=43, ENRICH_FIELD_WS=44, SETTING=45, SETTING_LINE_COMMENT=46, + SETTTING_MULTILINE_COMMENT=47, SETTING_WS=48, EXPLAIN_WS=49, EXPLAIN_LINE_COMMENT=50, + EXPLAIN_MULTILINE_COMMENT=51, PIPE=52, QUOTED_STRING=53, INTEGER_LITERAL=54, + DECIMAL_LITERAL=55, AND=56, AS=57, ASC=58, ASSIGN=59, BY=60, CAST_OP=61, + COLON=62, COMMA=63, DESC=64, DOT=65, FALSE=66, FIRST=67, IN=68, IS=69, + LAST=70, LIKE=71, NOT=72, NULL=73, NULLS=74, ON=75, OR=76, PARAM=77, RLIKE=78, + TRUE=79, WITH=80, EQ=81, CIEQ=82, NEQ=83, LT=84, LTE=85, GT=86, GTE=87, + PLUS=88, MINUS=89, ASTERISK=90, SLASH=91, PERCENT=92, LEFT_BRACES=93, + RIGHT_BRACES=94, DOUBLE_PARAMS=95, NAMED_OR_POSITIONAL_PARAM=96, NAMED_OR_POSITIONAL_DOUBLE_PARAMS=97, + OPENING_BRACKET=98, CLOSING_BRACKET=99, LP=100, RP=101, UNQUOTED_IDENTIFIER=102, + QUOTED_IDENTIFIER=103, EXPR_LINE_COMMENT=104, EXPR_MULTILINE_COMMENT=105, + EXPR_WS=106, METADATA=107, UNQUOTED_SOURCE=108, FROM_LINE_COMMENT=109, + FROM_MULTILINE_COMMENT=110, FROM_WS=111, FORK_WS=112, FORK_LINE_COMMENT=113, + FORK_MULTILINE_COMMENT=114, JOIN=115, USING=116, JOIN_LINE_COMMENT=117, + JOIN_MULTILINE_COMMENT=118, JOIN_WS=119, LOOKUP_LINE_COMMENT=120, LOOKUP_MULTILINE_COMMENT=121, + LOOKUP_WS=122, LOOKUP_FIELD_LINE_COMMENT=123, LOOKUP_FIELD_MULTILINE_COMMENT=124, + LOOKUP_FIELD_WS=125, MVEXPAND_LINE_COMMENT=126, MVEXPAND_MULTILINE_COMMENT=127, + MVEXPAND_WS=128, ID_PATTERN=129, PROJECT_LINE_COMMENT=130, PROJECT_MULTILINE_COMMENT=131, + PROJECT_WS=132, RENAME_LINE_COMMENT=133, RENAME_MULTILINE_COMMENT=134, + RENAME_WS=135, INFO=136, SHOW_LINE_COMMENT=137, SHOW_MULTILINE_COMMENT=138, SHOW_WS=139; public static final int - RULE_singleStatement = 0, RULE_query = 1, RULE_sourceCommand = 2, RULE_processingCommand = 3, - RULE_whereCommand = 4, RULE_dataType = 5, RULE_rowCommand = 6, RULE_fields = 7, - RULE_field = 8, RULE_rerankFields = 9, RULE_rerankField = 10, RULE_fromCommand = 11, - RULE_timeSeriesCommand = 12, RULE_indexPatternAndMetadataFields = 13, - RULE_indexPattern = 14, RULE_clusterString = 15, RULE_selectorString = 16, - RULE_indexString = 17, RULE_metadata = 18, RULE_evalCommand = 19, RULE_statsCommand = 20, - RULE_aggFields = 21, RULE_aggField = 22, RULE_qualifiedName = 23, RULE_qualifiedNamePattern = 24, - RULE_qualifiedNamePatterns = 25, RULE_identifier = 26, RULE_identifierPattern = 27, - RULE_parameter = 28, RULE_doubleParameter = 29, RULE_identifierOrParameter = 30, - RULE_limitCommand = 31, RULE_sortCommand = 32, RULE_orderExpression = 33, - RULE_keepCommand = 34, RULE_dropCommand = 35, RULE_renameCommand = 36, - RULE_renameClause = 37, RULE_dissectCommand = 38, RULE_grokCommand = 39, - RULE_mvExpandCommand = 40, RULE_commandOptions = 41, RULE_commandOption = 42, - RULE_explainCommand = 43, RULE_subqueryExpression = 44, RULE_showCommand = 45, - RULE_enrichCommand = 46, RULE_enrichWithClause = 47, RULE_lookupCommand = 48, - RULE_inlinestatsCommand = 49, RULE_changePointCommand = 50, RULE_insistCommand = 51, - RULE_forkCommand = 52, RULE_forkSubQueries = 53, RULE_forkSubQuery = 54, - RULE_forkSubQueryCommand = 55, RULE_forkSubQueryProcessingCommand = 56, - RULE_rrfCommand = 57, RULE_rerankCommand = 58, RULE_completionCommand = 59, - RULE_sampleCommand = 60, RULE_booleanExpression = 61, RULE_regexBooleanExpression = 62, - RULE_matchBooleanExpression = 63, RULE_valueExpression = 64, RULE_operatorExpression = 65, - RULE_primaryExpression = 66, RULE_functionExpression = 67, RULE_functionName = 68, - RULE_mapExpression = 69, RULE_entryExpression = 70, RULE_constant = 71, - RULE_booleanValue = 72, RULE_numericValue = 73, RULE_decimalValue = 74, - RULE_integerValue = 75, RULE_string = 76, RULE_comparisonOperator = 77, - RULE_joinCommand = 78, RULE_joinTarget = 79, RULE_joinCondition = 80, + RULE_singleStatement = 0, RULE_query = 1, RULE_sourceCommand = 2, RULE_processingCommand = 3, + RULE_whereCommand = 4, RULE_dataType = 5, RULE_rowCommand = 6, RULE_fields = 7, + RULE_field = 8, RULE_rerankFields = 9, RULE_rerankField = 10, RULE_fromCommand = 11, + RULE_timeSeriesCommand = 12, RULE_indexPatternAndMetadataFields = 13, + RULE_indexPattern = 14, RULE_clusterString = 15, RULE_selectorString = 16, + RULE_indexString = 17, RULE_metadata = 18, RULE_evalCommand = 19, RULE_statsCommand = 20, + RULE_aggFields = 21, RULE_aggField = 22, RULE_qualifiedName = 23, RULE_qualifiedNamePattern = 24, + RULE_qualifiedNamePatterns = 25, RULE_identifier = 26, RULE_identifierPattern = 27, + RULE_parameter = 28, RULE_doubleParameter = 29, RULE_identifierOrParameter = 30, + RULE_limitCommand = 31, RULE_sortCommand = 32, RULE_orderExpression = 33, + RULE_keepCommand = 34, RULE_dropCommand = 35, RULE_renameCommand = 36, + RULE_renameClause = 37, RULE_dissectCommand = 38, RULE_grokCommand = 39, + RULE_mvExpandCommand = 40, RULE_commandOptions = 41, RULE_commandOption = 42, + RULE_explainCommand = 43, RULE_subqueryExpression = 44, RULE_showCommand = 45, + RULE_enrichCommand = 46, RULE_enrichWithClause = 47, RULE_lookupCommand = 48, + RULE_inlinestatsCommand = 49, RULE_changePointCommand = 50, RULE_insistCommand = 51, + RULE_forkCommand = 52, RULE_forkSubQueries = 53, RULE_forkSubQuery = 54, + RULE_forkSubQueryCommand = 55, RULE_forkSubQueryProcessingCommand = 56, + RULE_rrfCommand = 57, RULE_rerankCommand = 58, RULE_completionCommand = 59, + RULE_sampleCommand = 60, RULE_booleanExpression = 61, RULE_regexBooleanExpression = 62, + RULE_matchBooleanExpression = 63, RULE_valueExpression = 64, RULE_operatorExpression = 65, + RULE_primaryExpression = 66, RULE_functionExpression = 67, RULE_functionName = 68, + RULE_mapExpression = 69, RULE_entryExpression = 70, RULE_constant = 71, + RULE_booleanValue = 72, RULE_numericValue = 73, RULE_decimalValue = 74, + RULE_integerValue = 75, RULE_string = 76, RULE_comparisonOperator = 77, + RULE_joinCommand = 78, RULE_joinTarget = 79, RULE_joinCondition = 80, RULE_joinPredicate = 81; private static String[] makeRuleNames() { return new String[] { - "singleStatement", "query", "sourceCommand", "processingCommand", "whereCommand", - "dataType", "rowCommand", "fields", "field", "rerankFields", "rerankField", - "fromCommand", "timeSeriesCommand", "indexPatternAndMetadataFields", - "indexPattern", "clusterString", "selectorString", "indexString", "metadata", - "evalCommand", "statsCommand", "aggFields", "aggField", "qualifiedName", - "qualifiedNamePattern", "qualifiedNamePatterns", "identifier", "identifierPattern", - "parameter", "doubleParameter", "identifierOrParameter", "limitCommand", - "sortCommand", "orderExpression", "keepCommand", "dropCommand", "renameCommand", - "renameClause", "dissectCommand", "grokCommand", "mvExpandCommand", "commandOptions", - "commandOption", "explainCommand", "subqueryExpression", "showCommand", - "enrichCommand", "enrichWithClause", "lookupCommand", "inlinestatsCommand", - "changePointCommand", "insistCommand", "forkCommand", "forkSubQueries", - "forkSubQuery", "forkSubQueryCommand", "forkSubQueryProcessingCommand", - "rrfCommand", "rerankCommand", "completionCommand", "sampleCommand", - "booleanExpression", "regexBooleanExpression", "matchBooleanExpression", - "valueExpression", "operatorExpression", "primaryExpression", "functionExpression", - "functionName", "mapExpression", "entryExpression", "constant", "booleanValue", - "numericValue", "decimalValue", "integerValue", "string", "comparisonOperator", + "singleStatement", "query", "sourceCommand", "processingCommand", "whereCommand", + "dataType", "rowCommand", "fields", "field", "rerankFields", "rerankField", + "fromCommand", "timeSeriesCommand", "indexPatternAndMetadataFields", + "indexPattern", "clusterString", "selectorString", "indexString", "metadata", + "evalCommand", "statsCommand", "aggFields", "aggField", "qualifiedName", + "qualifiedNamePattern", "qualifiedNamePatterns", "identifier", "identifierPattern", + "parameter", "doubleParameter", "identifierOrParameter", "limitCommand", + "sortCommand", "orderExpression", "keepCommand", "dropCommand", "renameCommand", + "renameClause", "dissectCommand", "grokCommand", "mvExpandCommand", "commandOptions", + "commandOption", "explainCommand", "subqueryExpression", "showCommand", + "enrichCommand", "enrichWithClause", "lookupCommand", "inlinestatsCommand", + "changePointCommand", "insistCommand", "forkCommand", "forkSubQueries", + "forkSubQuery", "forkSubQueryCommand", "forkSubQueryProcessingCommand", + "rrfCommand", "rerankCommand", "completionCommand", "sampleCommand", + "booleanExpression", "regexBooleanExpression", "matchBooleanExpression", + "valueExpression", "operatorExpression", "primaryExpression", "functionExpression", + "functionName", "mapExpression", "entryExpression", "constant", "booleanValue", + "numericValue", "decimalValue", "integerValue", "string", "comparisonOperator", "joinCommand", "joinTarget", "joinCondition", "joinPredicate" }; } @@ -109,52 +109,52 @@ private static String[] makeRuleNames() { private static String[] makeLiteralNames() { return new String[] { - null, null, null, null, "'change_point'", "'enrich'", "'explain'", "'dissect'", - "'eval'", "'grok'", "'limit'", "'row'", "'sort'", "'stats'", "'where'", - null, null, null, null, "'from'", null, null, "'lookup'", null, null, - null, null, "'mv_expand'", "'drop'", "'keep'", null, null, "'rename'", - "'show'", null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, "'|'", null, null, null, - "'and'", "'as'", "'asc'", "'='", "'by'", "'::'", "':'", "','", "'desc'", - "'.'", "'false'", "'first'", "'in'", "'is'", "'last'", "'like'", "'not'", - "'null'", "'nulls'", "'on'", "'or'", "'?'", "'rlike'", "'true'", "'with'", - "'=='", "'=~'", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", - "'/'", "'%'", "'{'", "'}'", "'??'", null, null, null, "']'", null, "')'", - null, null, null, null, null, "'metadata'", null, null, null, null, null, - null, null, "'join'", "'USING'", null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, "'change_point'", "'enrich'", "'explain'", "'dissect'", + "'eval'", "'grok'", "'limit'", "'row'", "'sort'", "'stats'", "'where'", + null, null, null, null, "'from'", null, null, "'lookup'", null, null, + null, null, "'mv_expand'", "'drop'", "'keep'", null, null, "'rename'", + "'show'", null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, "'|'", null, null, null, + "'and'", "'as'", "'asc'", "'='", "'by'", "'::'", "':'", "','", "'desc'", + "'.'", "'false'", "'first'", "'in'", "'is'", "'last'", "'like'", "'not'", + "'null'", "'nulls'", "'on'", "'or'", "'?'", "'rlike'", "'true'", "'with'", + "'=='", "'=~'", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", + "'/'", "'%'", "'{'", "'}'", "'??'", null, null, null, "']'", null, "')'", + null, null, null, null, null, "'metadata'", null, null, null, null, null, + null, null, "'join'", "'USING'", null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, null, "'info'" }; } private static final String[] _LITERAL_NAMES = makeLiteralNames(); private static String[] makeSymbolicNames() { return new String[] { - null, "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "CHANGE_POINT", "ENRICH", - "EXPLAIN", "DISSECT", "EVAL", "GROK", "LIMIT", "ROW", "SORT", "STATS", - "WHERE", "DEV_COMPLETION", "DEV_INLINESTATS", "DEV_RERANK", "DEV_SAMPLE", - "FROM", "DEV_TIME_SERIES", "DEV_FORK", "JOIN_LOOKUP", "DEV_JOIN_FULL", - "DEV_JOIN_LEFT", "DEV_JOIN_RIGHT", "DEV_LOOKUP", "MV_EXPAND", "DROP", - "KEEP", "DEV_INSIST", "DEV_RRF", "RENAME", "SHOW", "UNKNOWN_CMD", "CHANGE_POINT_LINE_COMMENT", - "CHANGE_POINT_MULTILINE_COMMENT", "CHANGE_POINT_WS", "ENRICH_POLICY_NAME", - "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", - "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "SETTING", "SETTING_LINE_COMMENT", - "SETTTING_MULTILINE_COMMENT", "SETTING_WS", "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", - "EXPLAIN_MULTILINE_COMMENT", "PIPE", "QUOTED_STRING", "INTEGER_LITERAL", - "DECIMAL_LITERAL", "AND", "AS", "ASC", "ASSIGN", "BY", "CAST_OP", "COLON", - "COMMA", "DESC", "DOT", "FALSE", "FIRST", "IN", "IS", "LAST", "LIKE", - "NOT", "NULL", "NULLS", "ON", "OR", "PARAM", "RLIKE", "TRUE", "WITH", - "EQ", "CIEQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK", - "SLASH", "PERCENT", "LEFT_BRACES", "RIGHT_BRACES", "DOUBLE_PARAMS", "NAMED_OR_POSITIONAL_PARAM", - "NAMED_OR_POSITIONAL_DOUBLE_PARAMS", "OPENING_BRACKET", "CLOSING_BRACKET", - "LP", "RP", "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", - "EXPR_MULTILINE_COMMENT", "EXPR_WS", "METADATA", "UNQUOTED_SOURCE", "FROM_LINE_COMMENT", - "FROM_MULTILINE_COMMENT", "FROM_WS", "FORK_WS", "FORK_LINE_COMMENT", - "FORK_MULTILINE_COMMENT", "JOIN", "USING", "JOIN_LINE_COMMENT", "JOIN_MULTILINE_COMMENT", - "JOIN_WS", "LOOKUP_LINE_COMMENT", "LOOKUP_MULTILINE_COMMENT", "LOOKUP_WS", - "LOOKUP_FIELD_LINE_COMMENT", "LOOKUP_FIELD_MULTILINE_COMMENT", "LOOKUP_FIELD_WS", - "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", "MVEXPAND_WS", - "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", "PROJECT_WS", - "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", "RENAME_WS", "INFO", + null, "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "CHANGE_POINT", "ENRICH", + "EXPLAIN", "DISSECT", "EVAL", "GROK", "LIMIT", "ROW", "SORT", "STATS", + "WHERE", "DEV_COMPLETION", "DEV_INLINESTATS", "DEV_RERANK", "DEV_SAMPLE", + "FROM", "DEV_TIME_SERIES", "DEV_FORK", "JOIN_LOOKUP", "DEV_JOIN_FULL", + "DEV_JOIN_LEFT", "DEV_JOIN_RIGHT", "DEV_LOOKUP", "MV_EXPAND", "DROP", + "KEEP", "DEV_INSIST", "DEV_RRF", "RENAME", "SHOW", "UNKNOWN_CMD", "CHANGE_POINT_LINE_COMMENT", + "CHANGE_POINT_MULTILINE_COMMENT", "CHANGE_POINT_WS", "ENRICH_POLICY_NAME", + "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_LINE_COMMENT", + "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "SETTING", "SETTING_LINE_COMMENT", + "SETTTING_MULTILINE_COMMENT", "SETTING_WS", "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", + "EXPLAIN_MULTILINE_COMMENT", "PIPE", "QUOTED_STRING", "INTEGER_LITERAL", + "DECIMAL_LITERAL", "AND", "AS", "ASC", "ASSIGN", "BY", "CAST_OP", "COLON", + "COMMA", "DESC", "DOT", "FALSE", "FIRST", "IN", "IS", "LAST", "LIKE", + "NOT", "NULL", "NULLS", "ON", "OR", "PARAM", "RLIKE", "TRUE", "WITH", + "EQ", "CIEQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", "ASTERISK", + "SLASH", "PERCENT", "LEFT_BRACES", "RIGHT_BRACES", "DOUBLE_PARAMS", "NAMED_OR_POSITIONAL_PARAM", + "NAMED_OR_POSITIONAL_DOUBLE_PARAMS", "OPENING_BRACKET", "CLOSING_BRACKET", + "LP", "RP", "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", + "EXPR_MULTILINE_COMMENT", "EXPR_WS", "METADATA", "UNQUOTED_SOURCE", "FROM_LINE_COMMENT", + "FROM_MULTILINE_COMMENT", "FROM_WS", "FORK_WS", "FORK_LINE_COMMENT", + "FORK_MULTILINE_COMMENT", "JOIN", "USING", "JOIN_LINE_COMMENT", "JOIN_MULTILINE_COMMENT", + "JOIN_WS", "LOOKUP_LINE_COMMENT", "LOOKUP_MULTILINE_COMMENT", "LOOKUP_WS", + "LOOKUP_FIELD_LINE_COMMENT", "LOOKUP_FIELD_MULTILINE_COMMENT", "LOOKUP_FIELD_WS", + "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", "MVEXPAND_WS", + "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", "PROJECT_WS", + "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", "RENAME_WS", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", "SHOW_WS" }; } @@ -266,7 +266,7 @@ public QueryContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_query; } - + @SuppressWarnings("this-escape") public QueryContext() { } public void copyFrom(QueryContext ctx) { @@ -362,7 +362,7 @@ private QueryContext query(int _p) throws RecognitionException { setState(172); processingCommand(); } - } + } } setState(177); _errHandler.sync(this); @@ -809,7 +809,7 @@ public DataTypeContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_dataType; } - + @SuppressWarnings("this-escape") public DataTypeContext() { } public void copyFrom(DataTypeContext ctx) { @@ -962,7 +962,7 @@ public final FieldsContext fields() throws RecognitionException { setState(228); field(); } - } + } } setState(233); _errHandler.sync(this); @@ -1330,7 +1330,7 @@ public final IndexPatternAndMetadataFieldsContext indexPatternAndMetadataFields( setState(262); indexPattern(); } - } + } } setState(267); _errHandler.sync(this); @@ -1666,7 +1666,7 @@ public final MetadataContext metadata() throws RecognitionException { setState(293); match(UNQUOTED_SOURCE); } - } + } } setState(298); _errHandler.sync(this); @@ -1862,7 +1862,7 @@ public final AggFieldsContext aggFields() throws RecognitionException { setState(312); aggField(); } - } + } } setState(317); _errHandler.sync(this); @@ -1996,7 +1996,7 @@ public final QualifiedNameContext qualifiedName() throws RecognitionException { setState(325); identifierOrParameter(); } - } + } } setState(330); _errHandler.sync(this); @@ -2068,7 +2068,7 @@ public final QualifiedNamePatternContext qualifiedNamePattern() throws Recogniti setState(333); identifierPattern(); } - } + } } setState(338); _errHandler.sync(this); @@ -2140,7 +2140,7 @@ public final QualifiedNamePatternsContext qualifiedNamePatterns() throws Recogni setState(341); qualifiedNamePattern(); } - } + } } setState(346); _errHandler.sync(this); @@ -2294,7 +2294,7 @@ public ParameterContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_parameter; } - + @SuppressWarnings("this-escape") public ParameterContext() { } public void copyFrom(ParameterContext ctx) { @@ -2385,7 +2385,7 @@ public DoubleParameterContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_doubleParameter; } - + @SuppressWarnings("this-escape") public DoubleParameterContext() { } public void copyFrom(DoubleParameterContext ctx) { @@ -2649,7 +2649,7 @@ public final SortCommandContext sortCommand() throws RecognitionException { setState(373); orderExpression(); } - } + } } setState(378); _errHandler.sync(this); @@ -2916,7 +2916,7 @@ public final RenameCommandContext renameCommand() throws RecognitionException { setState(396); renameClause(); } - } + } } setState(401); _errHandler.sync(this); @@ -3214,7 +3214,7 @@ public final CommandOptionsContext commandOptions() throws RecognitionException setState(421); commandOption(); } - } + } } setState(426); _errHandler.sync(this); @@ -3395,7 +3395,7 @@ public ShowCommandContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_showCommand; } - + @SuppressWarnings("this-escape") public ShowCommandContext() { } public void copyFrom(ShowCommandContext ctx) { @@ -3532,7 +3532,7 @@ public final EnrichCommandContext enrichCommand() throws RecognitionException { setState(450); enrichWithClause(); } - } + } } setState(455); _errHandler.sync(this); @@ -3964,7 +3964,7 @@ public final ForkSubQueriesContext forkSubQueries() throws RecognitionException int _alt; enterOuterAlt(_localctx, 1); { - setState(496); + setState(496); _errHandler.sync(this); _alt = 1; do { @@ -3980,7 +3980,7 @@ public final ForkSubQueriesContext forkSubQueries() throws RecognitionException default: throw new NoViableAltException(this); } - setState(498); + setState(498); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,37,_ctx); } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); @@ -4056,7 +4056,7 @@ public ForkSubQueryCommandContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_forkSubQueryCommand; } - + @SuppressWarnings("this-escape") public ForkSubQueryCommandContext() { } public void copyFrom(ForkSubQueryCommandContext ctx) { @@ -4152,7 +4152,7 @@ private ForkSubQueryCommandContext forkSubQueryCommand(int _p) throws Recognitio setState(509); forkSubQueryProcessingCommand(); } - } + } } setState(514); _errHandler.sync(this); @@ -4533,7 +4533,7 @@ public BooleanExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_booleanExpression; } - + @SuppressWarnings("this-escape") public BooleanExpressionContext() { } public void copyFrom(BooleanExpressionContext ctx) { @@ -4875,7 +4875,7 @@ private BooleanExpressionContext booleanExpression(int _p) throws RecognitionExc } break; } - } + } } setState(586); _errHandler.sync(this); @@ -5071,7 +5071,7 @@ public ValueExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_valueExpression; } - + @SuppressWarnings("this-escape") public ValueExpressionContext() { } public void copyFrom(ValueExpressionContext ctx) { @@ -5176,7 +5176,7 @@ public OperatorExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_operatorExpression; } - + @SuppressWarnings("this-escape") public OperatorExpressionContext() { } public void copyFrom(OperatorExpressionContext ctx) { @@ -5368,7 +5368,7 @@ private OperatorExpressionContext operatorExpression(int _p) throws RecognitionE } break; } - } + } } setState(634); _errHandler.sync(this); @@ -5394,7 +5394,7 @@ public PrimaryExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_primaryExpression; } - + @SuppressWarnings("this-escape") public PrimaryExpressionContext() { } public void copyFrom(PrimaryExpressionContext ctx) { @@ -5592,7 +5592,7 @@ private PrimaryExpressionContext primaryExpression(int _p) throws RecognitionExc setState(647); dataType(); } - } + } } setState(652); _errHandler.sync(this); @@ -5706,7 +5706,7 @@ public final FunctionExpressionContext functionExpression() throws RecognitionEx setState(658); booleanExpression(0); } - } + } } setState(663); _errHandler.sync(this); @@ -5932,7 +5932,7 @@ public ConstantContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @Override public int getRuleIndex() { return RULE_constant; } - + @SuppressWarnings("this-escape") public ConstantContext() { } public void copyFrom(ConstantContext ctx) { @@ -6860,7 +6860,7 @@ public final JoinConditionContext joinCondition() throws RecognitionException { setState(763); joinPredicate(); } - } + } } setState(768); _errHandler.sync(this); From 1c0b575a63175cd2d3302f384b3a9fe4e8474c8c Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 5 Jun 2025 16:41:36 +0200 Subject: [PATCH 26/58] spotless --- .../elasticsearch/xpack/esql/analysis/VerifierTests.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java index efe8d53f6ac92..62ddd3343269a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java @@ -1374,7 +1374,13 @@ private void checkFullTextFunctionsOnlyAllowedInWhere(String functionName, Strin throws Exception { assertThat( error("from test | eval y = " + functionInvocation, fullTextAnalyzer), - containsString("[" + functionName + "] " + functionType + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function") + containsString( + "[" + + functionName + + "] " + + functionType + + " is only supported in WHERE and STATS commands, or in EVAL within score(.) function" + ) ); assertThat( error("from test | sort " + functionInvocation + " asc", fullTextAnalyzer), From 52f8b3ee97e4dc22d1d2cb1f6f9b1aeb89e3f692 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 5 Jun 2025 18:25:44 +0200 Subject: [PATCH 27/58] csv tests, minor adjustments --- .../main/resources/score-function.csv-spec | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec new file mode 100644 index 0000000000000..7f646889d30ee --- /dev/null +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec @@ -0,0 +1,125 @@ +############################################### +# Tests for Score function +# + +scoreSingle +required_capability: metadata_score +required_capability: score_function + +// tag::score-single[] +FROM books METADATA _score +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL first_score = score(match(title, "Return")) +// end::score-single[] +| KEEP book_no, author, _score, first_score +| SORT book_no +| LIMIT 5 +; + +// tag::score-single-result[] +book_no:keyword | author:text | _score:double | first _score:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 0 | 0 +7350 | Return of the Shadow | 0 | 0 +// end::score-single-result[] +; + +scoreSingleNoMetadata +required_capability: metadata_score +required_capability: score_function + +FROM books +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL first_score = score(match(title, "Return")) +| KEEP book_no, author, first_score +| SORT book_no +| LIMIT 5 +; + +book_no:keyword | author:text | first _score:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 0 +7350 | Return of the Shadow | 0 +; + +scoreWithQueryExpressions +required_capability: score_function +required_capability: metadata_score + +from books +FROM books METADATA _score +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL first_score = score(match(title, CONCAT("Return ", " King"))) +| keep book_no, title; +ignoreOrder:true + +book_no:keyword | title:text | _score:double | first _score:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 0 | 0 +7350 | Return of the Shadow | 0 | 0 +; + +scoreAfterEval +required_capability: score_function +required_capability: metadata_score + +from books METADATA _score +| eval stars = to_long(ratings / 2.0) +| eval s1 = score(match(author, "William")) +| where match(author, "Faulkner") +| sort book_no +| keep book_no, author, stars, s1 +| limit 5; + +book_no:keyword | author:text | stars:long | s1:double +2378 | [Carol Faulkner, Holly Byers Ochoa, Lucretia Mott] | 3 | 0.0 +2713 | William Faulkner | 2 | 0.9 +2847 | Colleen Faulkner | 3 | 0.0 +2883 | William Faulkner | 2 | 0.9 +3293 | Danny Faulkner | 2 | 0.0 +; + +matchWithConjunction +required_capability: score_function +required_capability: metadata_score + +from books +| eval s1 = score(match(title, "Rings") and ratings > 4.6) +| keep book_no, title, s1; +ignoreOrder:true + +book_no:keyword | title:text |s1:double +4023 |A Tolkien Compass: Including J. R. R. Tolkien's Guide to the Names in The Lord of the Rings | 0.0 +7140 |The Lord of the Rings Poster Collection: Six Paintings by Alan Lee (No. 1) | 0.0 +; + +scoreWithDisjunction +required_capability: metadata_score +required_capability: score_function + +from books +| eval s1 = score(match(author, "Vonnegut") or match(author, "Guinane")) +| where match(author, "Vonnegut") +| keep book_no, author, s1; +ignoreOrder:true + +book_no:keyword | author:text | s1:double +2464 | Kurt Vonnegut | 0.0 +6970 | Edith Vonnegut | 0.0 +8956 | Kurt Vonnegut | 0.0 +3950 | Kurt Vonnegut | 0.0 +; + +matchWithDisjunctionAndFiltersConjunction +required_capability: match_function +required_capability: full_text_functions_disjunctions + +from books +| eval s1 = score((match(author, "Vonnegut") or match(author, "Guinane")) and year > 1997) +| where match(author, "Vonnegut") +| keep book_no, author, year, s1; +ignoreOrder:true + +book_no:keyword | author:text | year:integer | s1:double +2464 | Kurt Vonnegut | 1998 | 0.0 +6970 | Edith Vonnegut | 1998 | 0.0 +8956 | Kurt Vonnegut | 1998 | 0.0 +3950 | Kurt Vonnegut | 1998 | 0.0 +; From cce6f980a1b7be37f5945af417ba36c89c484a8e Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 5 Jun 2025 18:25:47 +0200 Subject: [PATCH 28/58] csv tests, minor adjustments --- .../xpack/esql/plugin/ScoreFunctionIT.java | 79 +------------------ .../function/fulltext/FullTextFunction.java | 1 - 2 files changed, 1 insertion(+), 79 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index cab7956ada472..7267d04b03501 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -16,7 +16,6 @@ import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; import org.elasticsearch.xpack.kql.KqlPlugin; import org.junit.Before; -import org.junit.Ignore; import java.util.Collection; import java.util.List; @@ -74,7 +73,7 @@ public void testScoreInWhereWithMatch() { """; var error = expectThrows(VerificationException.class, () -> run(query)); - assertThat(error.getMessage(), containsString("Condition expression needs to be boolean, found [DOUBLE]")); + assertThat(error.getMessage(), containsString("[MATCH] function can't be used with SCORE")); } public void testScoreInWhereWithFilter() { @@ -87,82 +86,6 @@ public void testScoreInWhereWithFilter() { assertThat(error.getMessage(), containsString("Condition expression needs to be boolean, found [DOUBLE]")); } - public void testMatchScoreFilter() { - var query = """ - FROM test - | WHERE score(match(content, "brown")) > 0 - | KEEP id - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id")); - assertColumnTypes(resp.columns(), List.of("integer")); - assertValues(resp.values(), List.of(List.of(1), List.of(2), List.of(3), List.of(4), List.of(6))); - } - } - - public void testKqlScoreFilter() { - var query = """ - FROM test - | WHERE score(kql("brown")) > 0 - | KEEP id - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id")); - assertColumnTypes(resp.columns(), List.of("integer")); - assertValues(resp.values(), List.of(List.of(1), List.of(2), List.of(3), List.of(4), List.of(6))); - } - } - - public void testQstrScoreFilter() { - var query = """ - FROM test - | WHERE score(qstr("brown")) > 0 - | KEEP id - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id")); - assertColumnTypes(resp.columns(), List.of("integer")); - assertValues(resp.values(), List.of(List.of(1), List.of(2), List.of(3), List.of(4), List.of(6))); - } - } - - public void testMultipleFTFScoreFilter() { - var query = """ - FROM test - | WHERE score(match(content, "brown")) > 0.4 OR score(match(content, "fox")) > 0.2 - | KEEP id - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id")); - assertColumnTypes(resp.columns(), List.of("integer")); - assertValues(resp.values(), List.of(List.of(1), List.of(6))); - } - } - - public void testMultipleHybridScoreFilter() { - var query = """ - FROM test - | WHERE score(match(content, "brown")) > 0.2 AND id > 2 - | KEEP id - | SORT id - """; - - try (var resp = run(query)) { - assertColumnNames(resp.columns(), List.of("id")); - assertColumnTypes(resp.columns(), List.of("integer")); - assertValues(resp.values(), List.of(List.of(3), List.of(6))); - } - } - - @Ignore("it's meaningless but it passes o_O") public void testScoreMeaninglessFunction() { var query = """ FROM test diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index f6ed780ec0e1d..87599201c1a53 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -295,7 +295,6 @@ private static void checkFullTextFunctionsParents(Expression condition, Failures if ((parent instanceof FullTextFunction == false) && (parent instanceof BinaryLogic == false) && (parent instanceof EsqlBinaryComparison == false) - && (parent instanceof Score == false) // e.g., WHERE score($ftf) > ... && (parent instanceof Not == false)) { failures.add( fail( From 4237ac71e8a223a623ca243f96330fb267e9683e Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 5 Jun 2025 18:52:12 +0200 Subject: [PATCH 29/58] Update docs/changelog/127551.yaml --- docs/changelog/127551.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/changelog/127551.yaml diff --git a/docs/changelog/127551.yaml b/docs/changelog/127551.yaml new file mode 100644 index 0000000000000..aa2bce70a971d --- /dev/null +++ b/docs/changelog/127551.yaml @@ -0,0 +1,6 @@ +pr: 127551 +summary: "Retain the scores of portions of an ES|QL query, via a score function" +area: ES|QL +type: enhancement +issues: + - 120082 From 80cf204341398acace99f7ad9b5cdd8781450d88 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 5 Jun 2025 19:08:37 +0200 Subject: [PATCH 30/58] dropped old todo --- .../esql/expression/function/fulltext/FullTextFunction.java | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index 87599201c1a53..c9d3a16e8b65a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -220,7 +220,6 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu } else if (plan instanceof Aggregate agg) { checkFullTextFunctionsInAggs(agg, failures); } else { - // TODO : improve this check, as this is not so nice :( List scoredFTFs = new ArrayList<>(); plan.forEachExpression(Score.class, scoreFunction -> { plan.forEachExpression(FullTextFunction.class, scoredFTFs::add); }); plan.forEachExpression(FullTextFunction.class, ftf -> { From 9e01d7b84705926be7ccd8d59e710ef08f6ffb72 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Tue, 10 Jun 2025 13:30:44 +0200 Subject: [PATCH 31/58] reset --- .../org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp index 6d345d866700f..30994e3f1ba88 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/parser/EsqlBaseParser.interp @@ -368,4 +368,4 @@ joinPredicate atn: -[4, 1, 139, 770, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 174, 8, 1, 10, 1, 12, 1, 177, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 185, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 216, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 5, 7, 229, 8, 7, 10, 7, 12, 7, 232, 9, 7, 1, 8, 1, 8, 1, 8, 3, 8, 237, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 5, 9, 244, 8, 9, 10, 9, 12, 9, 247, 9, 9, 1, 10, 1, 10, 1, 10, 3, 10, 252, 8, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 263, 8, 13, 10, 13, 12, 13, 266, 9, 13, 1, 13, 3, 13, 269, 8, 13, 1, 14, 1, 14, 1, 14, 3, 14, 274, 8, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 280, 8, 14, 3, 14, 282, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 294, 8, 18, 10, 18, 12, 18, 297, 9, 18, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 3, 20, 304, 8, 20, 1, 20, 1, 20, 3, 20, 308, 8, 20, 1, 21, 1, 21, 1, 21, 5, 21, 313, 8, 21, 10, 21, 12, 21, 316, 9, 21, 1, 22, 1, 22, 1, 22, 3, 22, 321, 8, 22, 1, 23, 1, 23, 1, 23, 5, 23, 326, 8, 23, 10, 23, 12, 23, 329, 9, 23, 1, 24, 1, 24, 1, 24, 5, 24, 334, 8, 24, 10, 24, 12, 24, 337, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 342, 8, 25, 10, 25, 12, 25, 345, 9, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 3, 27, 352, 8, 27, 1, 28, 1, 28, 3, 28, 356, 8, 28, 1, 29, 1, 29, 3, 29, 360, 8, 29, 1, 30, 1, 30, 1, 30, 3, 30, 365, 8, 30, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 374, 8, 32, 10, 32, 12, 32, 377, 9, 32, 1, 33, 1, 33, 3, 33, 381, 8, 33, 1, 33, 1, 33, 3, 33, 385, 8, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 397, 8, 36, 10, 36, 12, 36, 400, 9, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 410, 8, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 5, 41, 422, 8, 41, 10, 41, 12, 41, 425, 9, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 445, 8, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 451, 8, 46, 10, 46, 12, 46, 454, 9, 46, 3, 46, 456, 8, 46, 1, 47, 1, 47, 1, 47, 3, 47, 461, 8, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 474, 8, 49, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 480, 8, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 487, 8, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 4, 53, 496, 8, 53, 11, 53, 12, 53, 497, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 5, 55, 510, 8, 55, 10, 55, 12, 55, 513, 9, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 3, 56, 521, 8, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 3, 58, 531, 8, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, 59, 539, 8, 59, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 551, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 558, 8, 61, 10, 61, 12, 61, 561, 9, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 568, 8, 61, 1, 61, 1, 61, 1, 61, 3, 61, 573, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 581, 8, 61, 10, 61, 12, 61, 584, 9, 61, 1, 62, 1, 62, 3, 62, 588, 8, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 3, 62, 595, 8, 62, 1, 62, 1, 62, 1, 62, 3, 62, 600, 8, 62, 1, 63, 1, 63, 1, 63, 3, 63, 605, 8, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 3, 64, 615, 8, 64, 1, 65, 1, 65, 1, 65, 1, 65, 3, 65, 621, 8, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 5, 65, 629, 8, 65, 10, 65, 12, 65, 632, 9, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 3, 66, 642, 8, 66, 1, 66, 1, 66, 1, 66, 5, 66, 647, 8, 66, 10, 66, 12, 66, 650, 9, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 5, 67, 658, 8, 67, 10, 67, 12, 67, 661, 9, 67, 1, 67, 1, 67, 3, 67, 665, 8, 67, 3, 67, 667, 8, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 5, 69, 677, 8, 69, 10, 69, 12, 69, 680, 9, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 701, 8, 71, 10, 71, 12, 71, 704, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 712, 8, 71, 10, 71, 12, 71, 715, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 723, 8, 71, 10, 71, 12, 71, 726, 9, 71, 1, 71, 1, 71, 3, 71, 730, 8, 71, 1, 72, 1, 72, 1, 73, 1, 73, 3, 73, 736, 8, 73, 1, 74, 3, 74, 739, 8, 74, 1, 74, 1, 74, 1, 75, 3, 75, 744, 8, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 5, 80, 763, 8, 80, 10, 80, 12, 80, 766, 9, 80, 1, 81, 1, 81, 1, 81, 0, 5, 2, 110, 122, 130, 132, 82, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 0, 9, 2, 0, 53, 53, 108, 108, 1, 0, 102, 103, 2, 0, 58, 58, 64, 64, 2, 0, 67, 67, 70, 70, 1, 0, 88, 89, 1, 0, 90, 92, 2, 0, 66, 66, 79, 79, 2, 0, 81, 81, 83, 87, 2, 0, 22, 22, 24, 25, 801, 0, 164, 1, 0, 0, 0, 2, 167, 1, 0, 0, 0, 4, 184, 1, 0, 0, 0, 6, 215, 1, 0, 0, 0, 8, 217, 1, 0, 0, 0, 10, 220, 1, 0, 0, 0, 12, 222, 1, 0, 0, 0, 14, 225, 1, 0, 0, 0, 16, 236, 1, 0, 0, 0, 18, 240, 1, 0, 0, 0, 20, 248, 1, 0, 0, 0, 22, 253, 1, 0, 0, 0, 24, 256, 1, 0, 0, 0, 26, 259, 1, 0, 0, 0, 28, 281, 1, 0, 0, 0, 30, 283, 1, 0, 0, 0, 32, 285, 1, 0, 0, 0, 34, 287, 1, 0, 0, 0, 36, 289, 1, 0, 0, 0, 38, 298, 1, 0, 0, 0, 40, 301, 1, 0, 0, 0, 42, 309, 1, 0, 0, 0, 44, 317, 1, 0, 0, 0, 46, 322, 1, 0, 0, 0, 48, 330, 1, 0, 0, 0, 50, 338, 1, 0, 0, 0, 52, 346, 1, 0, 0, 0, 54, 351, 1, 0, 0, 0, 56, 355, 1, 0, 0, 0, 58, 359, 1, 0, 0, 0, 60, 364, 1, 0, 0, 0, 62, 366, 1, 0, 0, 0, 64, 369, 1, 0, 0, 0, 66, 378, 1, 0, 0, 0, 68, 386, 1, 0, 0, 0, 70, 389, 1, 0, 0, 0, 72, 392, 1, 0, 0, 0, 74, 401, 1, 0, 0, 0, 76, 405, 1, 0, 0, 0, 78, 411, 1, 0, 0, 0, 80, 415, 1, 0, 0, 0, 82, 418, 1, 0, 0, 0, 84, 426, 1, 0, 0, 0, 86, 430, 1, 0, 0, 0, 88, 433, 1, 0, 0, 0, 90, 437, 1, 0, 0, 0, 92, 440, 1, 0, 0, 0, 94, 460, 1, 0, 0, 0, 96, 464, 1, 0, 0, 0, 98, 469, 1, 0, 0, 0, 100, 475, 1, 0, 0, 0, 102, 488, 1, 0, 0, 0, 104, 491, 1, 0, 0, 0, 106, 495, 1, 0, 0, 0, 108, 499, 1, 0, 0, 0, 110, 503, 1, 0, 0, 0, 112, 520, 1, 0, 0, 0, 114, 522, 1, 0, 0, 0, 116, 524, 1, 0, 0, 0, 118, 532, 1, 0, 0, 0, 120, 540, 1, 0, 0, 0, 122, 572, 1, 0, 0, 0, 124, 599, 1, 0, 0, 0, 126, 601, 1, 0, 0, 0, 128, 614, 1, 0, 0, 0, 130, 620, 1, 0, 0, 0, 132, 641, 1, 0, 0, 0, 134, 651, 1, 0, 0, 0, 136, 670, 1, 0, 0, 0, 138, 672, 1, 0, 0, 0, 140, 683, 1, 0, 0, 0, 142, 729, 1, 0, 0, 0, 144, 731, 1, 0, 0, 0, 146, 735, 1, 0, 0, 0, 148, 738, 1, 0, 0, 0, 150, 743, 1, 0, 0, 0, 152, 747, 1, 0, 0, 0, 154, 749, 1, 0, 0, 0, 156, 751, 1, 0, 0, 0, 158, 756, 1, 0, 0, 0, 160, 758, 1, 0, 0, 0, 162, 767, 1, 0, 0, 0, 164, 165, 3, 2, 1, 0, 165, 166, 5, 0, 0, 1, 166, 1, 1, 0, 0, 0, 167, 168, 6, 1, -1, 0, 168, 169, 3, 4, 2, 0, 169, 175, 1, 0, 0, 0, 170, 171, 10, 1, 0, 0, 171, 172, 5, 52, 0, 0, 172, 174, 3, 6, 3, 0, 173, 170, 1, 0, 0, 0, 174, 177, 1, 0, 0, 0, 175, 173, 1, 0, 0, 0, 175, 176, 1, 0, 0, 0, 176, 3, 1, 0, 0, 0, 177, 175, 1, 0, 0, 0, 178, 185, 3, 86, 43, 0, 179, 185, 3, 22, 11, 0, 180, 185, 3, 12, 6, 0, 181, 185, 3, 90, 45, 0, 182, 183, 4, 2, 1, 0, 183, 185, 3, 24, 12, 0, 184, 178, 1, 0, 0, 0, 184, 179, 1, 0, 0, 0, 184, 180, 1, 0, 0, 0, 184, 181, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 5, 1, 0, 0, 0, 186, 216, 3, 38, 19, 0, 187, 216, 3, 8, 4, 0, 188, 216, 3, 68, 34, 0, 189, 216, 3, 62, 31, 0, 190, 216, 3, 40, 20, 0, 191, 216, 3, 64, 32, 0, 192, 216, 3, 70, 35, 0, 193, 216, 3, 72, 36, 0, 194, 216, 3, 76, 38, 0, 195, 216, 3, 78, 39, 0, 196, 216, 3, 92, 46, 0, 197, 216, 3, 80, 40, 0, 198, 216, 3, 156, 78, 0, 199, 216, 3, 100, 50, 0, 200, 216, 3, 118, 59, 0, 201, 202, 4, 3, 2, 0, 202, 216, 3, 98, 49, 0, 203, 204, 4, 3, 3, 0, 204, 216, 3, 96, 48, 0, 205, 206, 4, 3, 4, 0, 206, 216, 3, 102, 51, 0, 207, 208, 4, 3, 5, 0, 208, 216, 3, 104, 52, 0, 209, 210, 4, 3, 6, 0, 210, 216, 3, 116, 58, 0, 211, 212, 4, 3, 7, 0, 212, 216, 3, 114, 57, 0, 213, 214, 4, 3, 8, 0, 214, 216, 3, 120, 60, 0, 215, 186, 1, 0, 0, 0, 215, 187, 1, 0, 0, 0, 215, 188, 1, 0, 0, 0, 215, 189, 1, 0, 0, 0, 215, 190, 1, 0, 0, 0, 215, 191, 1, 0, 0, 0, 215, 192, 1, 0, 0, 0, 215, 193, 1, 0, 0, 0, 215, 194, 1, 0, 0, 0, 215, 195, 1, 0, 0, 0, 215, 196, 1, 0, 0, 0, 215, 197, 1, 0, 0, 0, 215, 198, 1, 0, 0, 0, 215, 199, 1, 0, 0, 0, 215, 200, 1, 0, 0, 0, 215, 201, 1, 0, 0, 0, 215, 203, 1, 0, 0, 0, 215, 205, 1, 0, 0, 0, 215, 207, 1, 0, 0, 0, 215, 209, 1, 0, 0, 0, 215, 211, 1, 0, 0, 0, 215, 213, 1, 0, 0, 0, 216, 7, 1, 0, 0, 0, 217, 218, 5, 15, 0, 0, 218, 219, 3, 122, 61, 0, 219, 9, 1, 0, 0, 0, 220, 221, 3, 52, 26, 0, 221, 11, 1, 0, 0, 0, 222, 223, 5, 12, 0, 0, 223, 224, 3, 14, 7, 0, 224, 13, 1, 0, 0, 0, 225, 230, 3, 16, 8, 0, 226, 227, 5, 63, 0, 0, 227, 229, 3, 16, 8, 0, 228, 226, 1, 0, 0, 0, 229, 232, 1, 0, 0, 0, 230, 228, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 15, 1, 0, 0, 0, 232, 230, 1, 0, 0, 0, 233, 234, 3, 46, 23, 0, 234, 235, 5, 59, 0, 0, 235, 237, 1, 0, 0, 0, 236, 233, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 239, 3, 122, 61, 0, 239, 17, 1, 0, 0, 0, 240, 245, 3, 20, 10, 0, 241, 242, 5, 63, 0, 0, 242, 244, 3, 20, 10, 0, 243, 241, 1, 0, 0, 0, 244, 247, 1, 0, 0, 0, 245, 243, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 246, 19, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 248, 251, 3, 46, 23, 0, 249, 250, 5, 59, 0, 0, 250, 252, 3, 122, 61, 0, 251, 249, 1, 0, 0, 0, 251, 252, 1, 0, 0, 0, 252, 21, 1, 0, 0, 0, 253, 254, 5, 19, 0, 0, 254, 255, 3, 26, 13, 0, 255, 23, 1, 0, 0, 0, 256, 257, 5, 20, 0, 0, 257, 258, 3, 26, 13, 0, 258, 25, 1, 0, 0, 0, 259, 264, 3, 28, 14, 0, 260, 261, 5, 63, 0, 0, 261, 263, 3, 28, 14, 0, 262, 260, 1, 0, 0, 0, 263, 266, 1, 0, 0, 0, 264, 262, 1, 0, 0, 0, 264, 265, 1, 0, 0, 0, 265, 268, 1, 0, 0, 0, 266, 264, 1, 0, 0, 0, 267, 269, 3, 36, 18, 0, 268, 267, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 27, 1, 0, 0, 0, 270, 271, 3, 30, 15, 0, 271, 272, 5, 62, 0, 0, 272, 274, 1, 0, 0, 0, 273, 270, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 282, 3, 34, 17, 0, 276, 279, 3, 34, 17, 0, 277, 278, 5, 61, 0, 0, 278, 280, 3, 32, 16, 0, 279, 277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 282, 1, 0, 0, 0, 281, 273, 1, 0, 0, 0, 281, 276, 1, 0, 0, 0, 282, 29, 1, 0, 0, 0, 283, 284, 7, 0, 0, 0, 284, 31, 1, 0, 0, 0, 285, 286, 7, 0, 0, 0, 286, 33, 1, 0, 0, 0, 287, 288, 7, 0, 0, 0, 288, 35, 1, 0, 0, 0, 289, 290, 5, 107, 0, 0, 290, 295, 5, 108, 0, 0, 291, 292, 5, 63, 0, 0, 292, 294, 5, 108, 0, 0, 293, 291, 1, 0, 0, 0, 294, 297, 1, 0, 0, 0, 295, 293, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 37, 1, 0, 0, 0, 297, 295, 1, 0, 0, 0, 298, 299, 5, 9, 0, 0, 299, 300, 3, 14, 7, 0, 300, 39, 1, 0, 0, 0, 301, 303, 5, 14, 0, 0, 302, 304, 3, 42, 21, 0, 303, 302, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 307, 1, 0, 0, 0, 305, 306, 5, 60, 0, 0, 306, 308, 3, 14, 7, 0, 307, 305, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308, 41, 1, 0, 0, 0, 309, 314, 3, 44, 22, 0, 310, 311, 5, 63, 0, 0, 311, 313, 3, 44, 22, 0, 312, 310, 1, 0, 0, 0, 313, 316, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 314, 315, 1, 0, 0, 0, 315, 43, 1, 0, 0, 0, 316, 314, 1, 0, 0, 0, 317, 320, 3, 16, 8, 0, 318, 319, 5, 15, 0, 0, 319, 321, 3, 122, 61, 0, 320, 318, 1, 0, 0, 0, 320, 321, 1, 0, 0, 0, 321, 45, 1, 0, 0, 0, 322, 327, 3, 60, 30, 0, 323, 324, 5, 65, 0, 0, 324, 326, 3, 60, 30, 0, 325, 323, 1, 0, 0, 0, 326, 329, 1, 0, 0, 0, 327, 325, 1, 0, 0, 0, 327, 328, 1, 0, 0, 0, 328, 47, 1, 0, 0, 0, 329, 327, 1, 0, 0, 0, 330, 335, 3, 54, 27, 0, 331, 332, 5, 65, 0, 0, 332, 334, 3, 54, 27, 0, 333, 331, 1, 0, 0, 0, 334, 337, 1, 0, 0, 0, 335, 333, 1, 0, 0, 0, 335, 336, 1, 0, 0, 0, 336, 49, 1, 0, 0, 0, 337, 335, 1, 0, 0, 0, 338, 343, 3, 48, 24, 0, 339, 340, 5, 63, 0, 0, 340, 342, 3, 48, 24, 0, 341, 339, 1, 0, 0, 0, 342, 345, 1, 0, 0, 0, 343, 341, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, 344, 51, 1, 0, 0, 0, 345, 343, 1, 0, 0, 0, 346, 347, 7, 1, 0, 0, 347, 53, 1, 0, 0, 0, 348, 352, 5, 129, 0, 0, 349, 352, 3, 56, 28, 0, 350, 352, 3, 58, 29, 0, 351, 348, 1, 0, 0, 0, 351, 349, 1, 0, 0, 0, 351, 350, 1, 0, 0, 0, 352, 55, 1, 0, 0, 0, 353, 356, 5, 77, 0, 0, 354, 356, 5, 96, 0, 0, 355, 353, 1, 0, 0, 0, 355, 354, 1, 0, 0, 0, 356, 57, 1, 0, 0, 0, 357, 360, 5, 95, 0, 0, 358, 360, 5, 97, 0, 0, 359, 357, 1, 0, 0, 0, 359, 358, 1, 0, 0, 0, 360, 59, 1, 0, 0, 0, 361, 365, 3, 52, 26, 0, 362, 365, 3, 56, 28, 0, 363, 365, 3, 58, 29, 0, 364, 361, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 364, 363, 1, 0, 0, 0, 365, 61, 1, 0, 0, 0, 366, 367, 5, 11, 0, 0, 367, 368, 3, 142, 71, 0, 368, 63, 1, 0, 0, 0, 369, 370, 5, 13, 0, 0, 370, 375, 3, 66, 33, 0, 371, 372, 5, 63, 0, 0, 372, 374, 3, 66, 33, 0, 373, 371, 1, 0, 0, 0, 374, 377, 1, 0, 0, 0, 375, 373, 1, 0, 0, 0, 375, 376, 1, 0, 0, 0, 376, 65, 1, 0, 0, 0, 377, 375, 1, 0, 0, 0, 378, 380, 3, 122, 61, 0, 379, 381, 7, 2, 0, 0, 380, 379, 1, 0, 0, 0, 380, 381, 1, 0, 0, 0, 381, 384, 1, 0, 0, 0, 382, 383, 5, 74, 0, 0, 383, 385, 7, 3, 0, 0, 384, 382, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 385, 67, 1, 0, 0, 0, 386, 387, 5, 29, 0, 0, 387, 388, 3, 50, 25, 0, 388, 69, 1, 0, 0, 0, 389, 390, 5, 28, 0, 0, 390, 391, 3, 50, 25, 0, 391, 71, 1, 0, 0, 0, 392, 393, 5, 32, 0, 0, 393, 398, 3, 74, 37, 0, 394, 395, 5, 63, 0, 0, 395, 397, 3, 74, 37, 0, 396, 394, 1, 0, 0, 0, 397, 400, 1, 0, 0, 0, 398, 396, 1, 0, 0, 0, 398, 399, 1, 0, 0, 0, 399, 73, 1, 0, 0, 0, 400, 398, 1, 0, 0, 0, 401, 402, 3, 48, 24, 0, 402, 403, 5, 57, 0, 0, 403, 404, 3, 48, 24, 0, 404, 75, 1, 0, 0, 0, 405, 406, 5, 8, 0, 0, 406, 407, 3, 132, 66, 0, 407, 409, 3, 152, 76, 0, 408, 410, 3, 82, 41, 0, 409, 408, 1, 0, 0, 0, 409, 410, 1, 0, 0, 0, 410, 77, 1, 0, 0, 0, 411, 412, 5, 10, 0, 0, 412, 413, 3, 132, 66, 0, 413, 414, 3, 152, 76, 0, 414, 79, 1, 0, 0, 0, 415, 416, 5, 27, 0, 0, 416, 417, 3, 46, 23, 0, 417, 81, 1, 0, 0, 0, 418, 423, 3, 84, 42, 0, 419, 420, 5, 63, 0, 0, 420, 422, 3, 84, 42, 0, 421, 419, 1, 0, 0, 0, 422, 425, 1, 0, 0, 0, 423, 421, 1, 0, 0, 0, 423, 424, 1, 0, 0, 0, 424, 83, 1, 0, 0, 0, 425, 423, 1, 0, 0, 0, 426, 427, 3, 52, 26, 0, 427, 428, 5, 59, 0, 0, 428, 429, 3, 142, 71, 0, 429, 85, 1, 0, 0, 0, 430, 431, 5, 6, 0, 0, 431, 432, 3, 88, 44, 0, 432, 87, 1, 0, 0, 0, 433, 434, 5, 98, 0, 0, 434, 435, 3, 2, 1, 0, 435, 436, 5, 99, 0, 0, 436, 89, 1, 0, 0, 0, 437, 438, 5, 33, 0, 0, 438, 439, 5, 136, 0, 0, 439, 91, 1, 0, 0, 0, 440, 441, 5, 5, 0, 0, 441, 444, 5, 38, 0, 0, 442, 443, 5, 75, 0, 0, 443, 445, 3, 48, 24, 0, 444, 442, 1, 0, 0, 0, 444, 445, 1, 0, 0, 0, 445, 455, 1, 0, 0, 0, 446, 447, 5, 80, 0, 0, 447, 452, 3, 94, 47, 0, 448, 449, 5, 63, 0, 0, 449, 451, 3, 94, 47, 0, 450, 448, 1, 0, 0, 0, 451, 454, 1, 0, 0, 0, 452, 450, 1, 0, 0, 0, 452, 453, 1, 0, 0, 0, 453, 456, 1, 0, 0, 0, 454, 452, 1, 0, 0, 0, 455, 446, 1, 0, 0, 0, 455, 456, 1, 0, 0, 0, 456, 93, 1, 0, 0, 0, 457, 458, 3, 48, 24, 0, 458, 459, 5, 59, 0, 0, 459, 461, 1, 0, 0, 0, 460, 457, 1, 0, 0, 0, 460, 461, 1, 0, 0, 0, 461, 462, 1, 0, 0, 0, 462, 463, 3, 48, 24, 0, 463, 95, 1, 0, 0, 0, 464, 465, 5, 26, 0, 0, 465, 466, 3, 28, 14, 0, 466, 467, 5, 75, 0, 0, 467, 468, 3, 50, 25, 0, 468, 97, 1, 0, 0, 0, 469, 470, 5, 16, 0, 0, 470, 473, 3, 42, 21, 0, 471, 472, 5, 60, 0, 0, 472, 474, 3, 14, 7, 0, 473, 471, 1, 0, 0, 0, 473, 474, 1, 0, 0, 0, 474, 99, 1, 0, 0, 0, 475, 476, 5, 4, 0, 0, 476, 479, 3, 46, 23, 0, 477, 478, 5, 75, 0, 0, 478, 480, 3, 46, 23, 0, 479, 477, 1, 0, 0, 0, 479, 480, 1, 0, 0, 0, 480, 486, 1, 0, 0, 0, 481, 482, 5, 57, 0, 0, 482, 483, 3, 46, 23, 0, 483, 484, 5, 63, 0, 0, 484, 485, 3, 46, 23, 0, 485, 487, 1, 0, 0, 0, 486, 481, 1, 0, 0, 0, 486, 487, 1, 0, 0, 0, 487, 101, 1, 0, 0, 0, 488, 489, 5, 30, 0, 0, 489, 490, 3, 50, 25, 0, 490, 103, 1, 0, 0, 0, 491, 492, 5, 21, 0, 0, 492, 493, 3, 106, 53, 0, 493, 105, 1, 0, 0, 0, 494, 496, 3, 108, 54, 0, 495, 494, 1, 0, 0, 0, 496, 497, 1, 0, 0, 0, 497, 495, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 107, 1, 0, 0, 0, 499, 500, 5, 100, 0, 0, 500, 501, 3, 110, 55, 0, 501, 502, 5, 101, 0, 0, 502, 109, 1, 0, 0, 0, 503, 504, 6, 55, -1, 0, 504, 505, 3, 112, 56, 0, 505, 511, 1, 0, 0, 0, 506, 507, 10, 1, 0, 0, 507, 508, 5, 52, 0, 0, 508, 510, 3, 112, 56, 0, 509, 506, 1, 0, 0, 0, 510, 513, 1, 0, 0, 0, 511, 509, 1, 0, 0, 0, 511, 512, 1, 0, 0, 0, 512, 111, 1, 0, 0, 0, 513, 511, 1, 0, 0, 0, 514, 521, 3, 38, 19, 0, 515, 521, 3, 8, 4, 0, 516, 521, 3, 62, 31, 0, 517, 521, 3, 40, 20, 0, 518, 521, 3, 64, 32, 0, 519, 521, 3, 76, 38, 0, 520, 514, 1, 0, 0, 0, 520, 515, 1, 0, 0, 0, 520, 516, 1, 0, 0, 0, 520, 517, 1, 0, 0, 0, 520, 518, 1, 0, 0, 0, 520, 519, 1, 0, 0, 0, 521, 113, 1, 0, 0, 0, 522, 523, 5, 31, 0, 0, 523, 115, 1, 0, 0, 0, 524, 525, 5, 17, 0, 0, 525, 526, 3, 142, 71, 0, 526, 527, 5, 75, 0, 0, 527, 530, 3, 18, 9, 0, 528, 529, 5, 80, 0, 0, 529, 531, 3, 60, 30, 0, 530, 528, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, 531, 117, 1, 0, 0, 0, 532, 533, 5, 7, 0, 0, 533, 534, 3, 132, 66, 0, 534, 535, 5, 80, 0, 0, 535, 538, 3, 60, 30, 0, 536, 537, 5, 57, 0, 0, 537, 539, 3, 46, 23, 0, 538, 536, 1, 0, 0, 0, 538, 539, 1, 0, 0, 0, 539, 119, 1, 0, 0, 0, 540, 541, 5, 18, 0, 0, 541, 542, 3, 148, 74, 0, 542, 121, 1, 0, 0, 0, 543, 544, 6, 61, -1, 0, 544, 545, 5, 72, 0, 0, 545, 573, 3, 122, 61, 8, 546, 573, 3, 128, 64, 0, 547, 573, 3, 124, 62, 0, 548, 550, 3, 128, 64, 0, 549, 551, 5, 72, 0, 0, 550, 549, 1, 0, 0, 0, 550, 551, 1, 0, 0, 0, 551, 552, 1, 0, 0, 0, 552, 553, 5, 68, 0, 0, 553, 554, 5, 100, 0, 0, 554, 559, 3, 128, 64, 0, 555, 556, 5, 63, 0, 0, 556, 558, 3, 128, 64, 0, 557, 555, 1, 0, 0, 0, 558, 561, 1, 0, 0, 0, 559, 557, 1, 0, 0, 0, 559, 560, 1, 0, 0, 0, 560, 562, 1, 0, 0, 0, 561, 559, 1, 0, 0, 0, 562, 563, 5, 101, 0, 0, 563, 573, 1, 0, 0, 0, 564, 565, 3, 128, 64, 0, 565, 567, 5, 69, 0, 0, 566, 568, 5, 72, 0, 0, 567, 566, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 569, 1, 0, 0, 0, 569, 570, 5, 73, 0, 0, 570, 573, 1, 0, 0, 0, 571, 573, 3, 126, 63, 0, 572, 543, 1, 0, 0, 0, 572, 546, 1, 0, 0, 0, 572, 547, 1, 0, 0, 0, 572, 548, 1, 0, 0, 0, 572, 564, 1, 0, 0, 0, 572, 571, 1, 0, 0, 0, 573, 582, 1, 0, 0, 0, 574, 575, 10, 5, 0, 0, 575, 576, 5, 56, 0, 0, 576, 581, 3, 122, 61, 6, 577, 578, 10, 4, 0, 0, 578, 579, 5, 76, 0, 0, 579, 581, 3, 122, 61, 5, 580, 574, 1, 0, 0, 0, 580, 577, 1, 0, 0, 0, 581, 584, 1, 0, 0, 0, 582, 580, 1, 0, 0, 0, 582, 583, 1, 0, 0, 0, 583, 123, 1, 0, 0, 0, 584, 582, 1, 0, 0, 0, 585, 587, 3, 128, 64, 0, 586, 588, 5, 72, 0, 0, 587, 586, 1, 0, 0, 0, 587, 588, 1, 0, 0, 0, 588, 589, 1, 0, 0, 0, 589, 590, 5, 71, 0, 0, 590, 591, 3, 152, 76, 0, 591, 600, 1, 0, 0, 0, 592, 594, 3, 128, 64, 0, 593, 595, 5, 72, 0, 0, 594, 593, 1, 0, 0, 0, 594, 595, 1, 0, 0, 0, 595, 596, 1, 0, 0, 0, 596, 597, 5, 78, 0, 0, 597, 598, 3, 152, 76, 0, 598, 600, 1, 0, 0, 0, 599, 585, 1, 0, 0, 0, 599, 592, 1, 0, 0, 0, 600, 125, 1, 0, 0, 0, 601, 604, 3, 46, 23, 0, 602, 603, 5, 61, 0, 0, 603, 605, 3, 10, 5, 0, 604, 602, 1, 0, 0, 0, 604, 605, 1, 0, 0, 0, 605, 606, 1, 0, 0, 0, 606, 607, 5, 62, 0, 0, 607, 608, 3, 142, 71, 0, 608, 127, 1, 0, 0, 0, 609, 615, 3, 130, 65, 0, 610, 611, 3, 130, 65, 0, 611, 612, 3, 154, 77, 0, 612, 613, 3, 130, 65, 0, 613, 615, 1, 0, 0, 0, 614, 609, 1, 0, 0, 0, 614, 610, 1, 0, 0, 0, 615, 129, 1, 0, 0, 0, 616, 617, 6, 65, -1, 0, 617, 621, 3, 132, 66, 0, 618, 619, 7, 4, 0, 0, 619, 621, 3, 130, 65, 3, 620, 616, 1, 0, 0, 0, 620, 618, 1, 0, 0, 0, 621, 630, 1, 0, 0, 0, 622, 623, 10, 2, 0, 0, 623, 624, 7, 5, 0, 0, 624, 629, 3, 130, 65, 3, 625, 626, 10, 1, 0, 0, 626, 627, 7, 4, 0, 0, 627, 629, 3, 130, 65, 2, 628, 622, 1, 0, 0, 0, 628, 625, 1, 0, 0, 0, 629, 632, 1, 0, 0, 0, 630, 628, 1, 0, 0, 0, 630, 631, 1, 0, 0, 0, 631, 131, 1, 0, 0, 0, 632, 630, 1, 0, 0, 0, 633, 634, 6, 66, -1, 0, 634, 642, 3, 142, 71, 0, 635, 642, 3, 46, 23, 0, 636, 642, 3, 134, 67, 0, 637, 638, 5, 100, 0, 0, 638, 639, 3, 122, 61, 0, 639, 640, 5, 101, 0, 0, 640, 642, 1, 0, 0, 0, 641, 633, 1, 0, 0, 0, 641, 635, 1, 0, 0, 0, 641, 636, 1, 0, 0, 0, 641, 637, 1, 0, 0, 0, 642, 648, 1, 0, 0, 0, 643, 644, 10, 1, 0, 0, 644, 645, 5, 61, 0, 0, 645, 647, 3, 10, 5, 0, 646, 643, 1, 0, 0, 0, 647, 650, 1, 0, 0, 0, 648, 646, 1, 0, 0, 0, 648, 649, 1, 0, 0, 0, 649, 133, 1, 0, 0, 0, 650, 648, 1, 0, 0, 0, 651, 652, 3, 136, 68, 0, 652, 666, 5, 100, 0, 0, 653, 667, 5, 90, 0, 0, 654, 659, 3, 122, 61, 0, 655, 656, 5, 63, 0, 0, 656, 658, 3, 122, 61, 0, 657, 655, 1, 0, 0, 0, 658, 661, 1, 0, 0, 0, 659, 657, 1, 0, 0, 0, 659, 660, 1, 0, 0, 0, 660, 664, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 662, 663, 5, 63, 0, 0, 663, 665, 3, 138, 69, 0, 664, 662, 1, 0, 0, 0, 664, 665, 1, 0, 0, 0, 665, 667, 1, 0, 0, 0, 666, 653, 1, 0, 0, 0, 666, 654, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 668, 1, 0, 0, 0, 668, 669, 5, 101, 0, 0, 669, 135, 1, 0, 0, 0, 670, 671, 3, 60, 30, 0, 671, 137, 1, 0, 0, 0, 672, 673, 5, 93, 0, 0, 673, 678, 3, 140, 70, 0, 674, 675, 5, 63, 0, 0, 675, 677, 3, 140, 70, 0, 676, 674, 1, 0, 0, 0, 677, 680, 1, 0, 0, 0, 678, 676, 1, 0, 0, 0, 678, 679, 1, 0, 0, 0, 679, 681, 1, 0, 0, 0, 680, 678, 1, 0, 0, 0, 681, 682, 5, 94, 0, 0, 682, 139, 1, 0, 0, 0, 683, 684, 3, 152, 76, 0, 684, 685, 5, 62, 0, 0, 685, 686, 3, 142, 71, 0, 686, 141, 1, 0, 0, 0, 687, 730, 5, 73, 0, 0, 688, 689, 3, 150, 75, 0, 689, 690, 5, 102, 0, 0, 690, 730, 1, 0, 0, 0, 691, 730, 3, 148, 74, 0, 692, 730, 3, 150, 75, 0, 693, 730, 3, 144, 72, 0, 694, 730, 3, 56, 28, 0, 695, 730, 3, 152, 76, 0, 696, 697, 5, 98, 0, 0, 697, 702, 3, 146, 73, 0, 698, 699, 5, 63, 0, 0, 699, 701, 3, 146, 73, 0, 700, 698, 1, 0, 0, 0, 701, 704, 1, 0, 0, 0, 702, 700, 1, 0, 0, 0, 702, 703, 1, 0, 0, 0, 703, 705, 1, 0, 0, 0, 704, 702, 1, 0, 0, 0, 705, 706, 5, 99, 0, 0, 706, 730, 1, 0, 0, 0, 707, 708, 5, 98, 0, 0, 708, 713, 3, 144, 72, 0, 709, 710, 5, 63, 0, 0, 710, 712, 3, 144, 72, 0, 711, 709, 1, 0, 0, 0, 712, 715, 1, 0, 0, 0, 713, 711, 1, 0, 0, 0, 713, 714, 1, 0, 0, 0, 714, 716, 1, 0, 0, 0, 715, 713, 1, 0, 0, 0, 716, 717, 5, 99, 0, 0, 717, 730, 1, 0, 0, 0, 718, 719, 5, 98, 0, 0, 719, 724, 3, 152, 76, 0, 720, 721, 5, 63, 0, 0, 721, 723, 3, 152, 76, 0, 722, 720, 1, 0, 0, 0, 723, 726, 1, 0, 0, 0, 724, 722, 1, 0, 0, 0, 724, 725, 1, 0, 0, 0, 725, 727, 1, 0, 0, 0, 726, 724, 1, 0, 0, 0, 727, 728, 5, 99, 0, 0, 728, 730, 1, 0, 0, 0, 729, 687, 1, 0, 0, 0, 729, 688, 1, 0, 0, 0, 729, 691, 1, 0, 0, 0, 729, 692, 1, 0, 0, 0, 729, 693, 1, 0, 0, 0, 729, 694, 1, 0, 0, 0, 729, 695, 1, 0, 0, 0, 729, 696, 1, 0, 0, 0, 729, 707, 1, 0, 0, 0, 729, 718, 1, 0, 0, 0, 730, 143, 1, 0, 0, 0, 731, 732, 7, 6, 0, 0, 732, 145, 1, 0, 0, 0, 733, 736, 3, 148, 74, 0, 734, 736, 3, 150, 75, 0, 735, 733, 1, 0, 0, 0, 735, 734, 1, 0, 0, 0, 736, 147, 1, 0, 0, 0, 737, 739, 7, 4, 0, 0, 738, 737, 1, 0, 0, 0, 738, 739, 1, 0, 0, 0, 739, 740, 1, 0, 0, 0, 740, 741, 5, 55, 0, 0, 741, 149, 1, 0, 0, 0, 742, 744, 7, 4, 0, 0, 743, 742, 1, 0, 0, 0, 743, 744, 1, 0, 0, 0, 744, 745, 1, 0, 0, 0, 745, 746, 5, 54, 0, 0, 746, 151, 1, 0, 0, 0, 747, 748, 5, 53, 0, 0, 748, 153, 1, 0, 0, 0, 749, 750, 7, 7, 0, 0, 750, 155, 1, 0, 0, 0, 751, 752, 7, 8, 0, 0, 752, 753, 5, 115, 0, 0, 753, 754, 3, 158, 79, 0, 754, 755, 3, 160, 80, 0, 755, 157, 1, 0, 0, 0, 756, 757, 3, 28, 14, 0, 757, 159, 1, 0, 0, 0, 758, 759, 5, 75, 0, 0, 759, 764, 3, 162, 81, 0, 760, 761, 5, 63, 0, 0, 761, 763, 3, 162, 81, 0, 762, 760, 1, 0, 0, 0, 763, 766, 1, 0, 0, 0, 764, 762, 1, 0, 0, 0, 764, 765, 1, 0, 0, 0, 765, 161, 1, 0, 0, 0, 766, 764, 1, 0, 0, 0, 767, 768, 3, 128, 64, 0, 768, 163, 1, 0, 0, 0, 70, 175, 184, 215, 230, 236, 245, 251, 264, 268, 273, 279, 281, 295, 303, 307, 314, 320, 327, 335, 343, 351, 355, 359, 364, 375, 380, 384, 398, 409, 423, 444, 452, 455, 460, 473, 479, 486, 497, 511, 520, 530, 538, 550, 559, 567, 572, 580, 582, 587, 594, 599, 604, 614, 620, 628, 630, 641, 648, 659, 664, 666, 678, 702, 713, 724, 729, 735, 738, 743, 764] +[4, 1, 139, 770, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 174, 8, 1, 10, 1, 12, 1, 177, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 185, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 216, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 5, 7, 229, 8, 7, 10, 7, 12, 7, 232, 9, 7, 1, 8, 1, 8, 1, 8, 3, 8, 237, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 5, 9, 244, 8, 9, 10, 9, 12, 9, 247, 9, 9, 1, 10, 1, 10, 1, 10, 3, 10, 252, 8, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 263, 8, 13, 10, 13, 12, 13, 266, 9, 13, 1, 13, 3, 13, 269, 8, 13, 1, 14, 1, 14, 1, 14, 3, 14, 274, 8, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 280, 8, 14, 3, 14, 282, 8, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 294, 8, 18, 10, 18, 12, 18, 297, 9, 18, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 3, 20, 304, 8, 20, 1, 20, 1, 20, 3, 20, 308, 8, 20, 1, 21, 1, 21, 1, 21, 5, 21, 313, 8, 21, 10, 21, 12, 21, 316, 9, 21, 1, 22, 1, 22, 1, 22, 3, 22, 321, 8, 22, 1, 23, 1, 23, 1, 23, 5, 23, 326, 8, 23, 10, 23, 12, 23, 329, 9, 23, 1, 24, 1, 24, 1, 24, 5, 24, 334, 8, 24, 10, 24, 12, 24, 337, 9, 24, 1, 25, 1, 25, 1, 25, 5, 25, 342, 8, 25, 10, 25, 12, 25, 345, 9, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 3, 27, 352, 8, 27, 1, 28, 1, 28, 3, 28, 356, 8, 28, 1, 29, 1, 29, 3, 29, 360, 8, 29, 1, 30, 1, 30, 1, 30, 3, 30, 365, 8, 30, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 374, 8, 32, 10, 32, 12, 32, 377, 9, 32, 1, 33, 1, 33, 3, 33, 381, 8, 33, 1, 33, 1, 33, 3, 33, 385, 8, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 397, 8, 36, 10, 36, 12, 36, 400, 9, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 410, 8, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 5, 41, 422, 8, 41, 10, 41, 12, 41, 425, 9, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 3, 46, 445, 8, 46, 1, 46, 1, 46, 1, 46, 1, 46, 5, 46, 451, 8, 46, 10, 46, 12, 46, 454, 9, 46, 3, 46, 456, 8, 46, 1, 47, 1, 47, 1, 47, 3, 47, 461, 8, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 474, 8, 49, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 480, 8, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 487, 8, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 4, 53, 496, 8, 53, 11, 53, 12, 53, 497, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 5, 55, 510, 8, 55, 10, 55, 12, 55, 513, 9, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 3, 56, 521, 8, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 3, 58, 531, 8, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 3, 59, 539, 8, 59, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 551, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 558, 8, 61, 10, 61, 12, 61, 561, 9, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 3, 61, 568, 8, 61, 1, 61, 1, 61, 1, 61, 3, 61, 573, 8, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 5, 61, 581, 8, 61, 10, 61, 12, 61, 584, 9, 61, 1, 62, 1, 62, 3, 62, 588, 8, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 3, 62, 595, 8, 62, 1, 62, 1, 62, 1, 62, 3, 62, 600, 8, 62, 1, 63, 1, 63, 1, 63, 3, 63, 605, 8, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 3, 64, 615, 8, 64, 1, 65, 1, 65, 1, 65, 1, 65, 3, 65, 621, 8, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 5, 65, 629, 8, 65, 10, 65, 12, 65, 632, 9, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 3, 66, 642, 8, 66, 1, 66, 1, 66, 1, 66, 5, 66, 647, 8, 66, 10, 66, 12, 66, 650, 9, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 5, 67, 658, 8, 67, 10, 67, 12, 67, 661, 9, 67, 1, 67, 1, 67, 3, 67, 665, 8, 67, 3, 67, 667, 8, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 5, 69, 677, 8, 69, 10, 69, 12, 69, 680, 9, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 701, 8, 71, 10, 71, 12, 71, 704, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 712, 8, 71, 10, 71, 12, 71, 715, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 723, 8, 71, 10, 71, 12, 71, 726, 9, 71, 1, 71, 1, 71, 3, 71, 730, 8, 71, 1, 72, 1, 72, 1, 73, 1, 73, 3, 73, 736, 8, 73, 1, 74, 3, 74, 739, 8, 74, 1, 74, 1, 74, 1, 75, 3, 75, 744, 8, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 5, 80, 763, 8, 80, 10, 80, 12, 80, 766, 9, 80, 1, 81, 1, 81, 1, 81, 0, 5, 2, 110, 122, 130, 132, 82, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 0, 9, 2, 0, 53, 53, 108, 108, 1, 0, 102, 103, 2, 0, 58, 58, 64, 64, 2, 0, 67, 67, 70, 70, 1, 0, 88, 89, 1, 0, 90, 92, 2, 0, 66, 66, 79, 79, 2, 0, 81, 81, 83, 87, 2, 0, 22, 22, 24, 25, 801, 0, 164, 1, 0, 0, 0, 2, 167, 1, 0, 0, 0, 4, 184, 1, 0, 0, 0, 6, 215, 1, 0, 0, 0, 8, 217, 1, 0, 0, 0, 10, 220, 1, 0, 0, 0, 12, 222, 1, 0, 0, 0, 14, 225, 1, 0, 0, 0, 16, 236, 1, 0, 0, 0, 18, 240, 1, 0, 0, 0, 20, 248, 1, 0, 0, 0, 22, 253, 1, 0, 0, 0, 24, 256, 1, 0, 0, 0, 26, 259, 1, 0, 0, 0, 28, 281, 1, 0, 0, 0, 30, 283, 1, 0, 0, 0, 32, 285, 1, 0, 0, 0, 34, 287, 1, 0, 0, 0, 36, 289, 1, 0, 0, 0, 38, 298, 1, 0, 0, 0, 40, 301, 1, 0, 0, 0, 42, 309, 1, 0, 0, 0, 44, 317, 1, 0, 0, 0, 46, 322, 1, 0, 0, 0, 48, 330, 1, 0, 0, 0, 50, 338, 1, 0, 0, 0, 52, 346, 1, 0, 0, 0, 54, 351, 1, 0, 0, 0, 56, 355, 1, 0, 0, 0, 58, 359, 1, 0, 0, 0, 60, 364, 1, 0, 0, 0, 62, 366, 1, 0, 0, 0, 64, 369, 1, 0, 0, 0, 66, 378, 1, 0, 0, 0, 68, 386, 1, 0, 0, 0, 70, 389, 1, 0, 0, 0, 72, 392, 1, 0, 0, 0, 74, 401, 1, 0, 0, 0, 76, 405, 1, 0, 0, 0, 78, 411, 1, 0, 0, 0, 80, 415, 1, 0, 0, 0, 82, 418, 1, 0, 0, 0, 84, 426, 1, 0, 0, 0, 86, 430, 1, 0, 0, 0, 88, 433, 1, 0, 0, 0, 90, 437, 1, 0, 0, 0, 92, 440, 1, 0, 0, 0, 94, 460, 1, 0, 0, 0, 96, 464, 1, 0, 0, 0, 98, 469, 1, 0, 0, 0, 100, 475, 1, 0, 0, 0, 102, 488, 1, 0, 0, 0, 104, 491, 1, 0, 0, 0, 106, 495, 1, 0, 0, 0, 108, 499, 1, 0, 0, 0, 110, 503, 1, 0, 0, 0, 112, 520, 1, 0, 0, 0, 114, 522, 1, 0, 0, 0, 116, 524, 1, 0, 0, 0, 118, 532, 1, 0, 0, 0, 120, 540, 1, 0, 0, 0, 122, 572, 1, 0, 0, 0, 124, 599, 1, 0, 0, 0, 126, 601, 1, 0, 0, 0, 128, 614, 1, 0, 0, 0, 130, 620, 1, 0, 0, 0, 132, 641, 1, 0, 0, 0, 134, 651, 1, 0, 0, 0, 136, 670, 1, 0, 0, 0, 138, 672, 1, 0, 0, 0, 140, 683, 1, 0, 0, 0, 142, 729, 1, 0, 0, 0, 144, 731, 1, 0, 0, 0, 146, 735, 1, 0, 0, 0, 148, 738, 1, 0, 0, 0, 150, 743, 1, 0, 0, 0, 152, 747, 1, 0, 0, 0, 154, 749, 1, 0, 0, 0, 156, 751, 1, 0, 0, 0, 158, 756, 1, 0, 0, 0, 160, 758, 1, 0, 0, 0, 162, 767, 1, 0, 0, 0, 164, 165, 3, 2, 1, 0, 165, 166, 5, 0, 0, 1, 166, 1, 1, 0, 0, 0, 167, 168, 6, 1, -1, 0, 168, 169, 3, 4, 2, 0, 169, 175, 1, 0, 0, 0, 170, 171, 10, 1, 0, 0, 171, 172, 5, 52, 0, 0, 172, 174, 3, 6, 3, 0, 173, 170, 1, 0, 0, 0, 174, 177, 1, 0, 0, 0, 175, 173, 1, 0, 0, 0, 175, 176, 1, 0, 0, 0, 176, 3, 1, 0, 0, 0, 177, 175, 1, 0, 0, 0, 178, 185, 3, 86, 43, 0, 179, 185, 3, 22, 11, 0, 180, 185, 3, 12, 6, 0, 181, 185, 3, 90, 45, 0, 182, 183, 4, 2, 1, 0, 183, 185, 3, 24, 12, 0, 184, 178, 1, 0, 0, 0, 184, 179, 1, 0, 0, 0, 184, 180, 1, 0, 0, 0, 184, 181, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 5, 1, 0, 0, 0, 186, 216, 3, 38, 19, 0, 187, 216, 3, 8, 4, 0, 188, 216, 3, 68, 34, 0, 189, 216, 3, 62, 31, 0, 190, 216, 3, 40, 20, 0, 191, 216, 3, 64, 32, 0, 192, 216, 3, 70, 35, 0, 193, 216, 3, 72, 36, 0, 194, 216, 3, 76, 38, 0, 195, 216, 3, 78, 39, 0, 196, 216, 3, 92, 46, 0, 197, 216, 3, 80, 40, 0, 198, 216, 3, 156, 78, 0, 199, 216, 3, 100, 50, 0, 200, 216, 3, 118, 59, 0, 201, 202, 4, 3, 2, 0, 202, 216, 3, 98, 49, 0, 203, 204, 4, 3, 3, 0, 204, 216, 3, 96, 48, 0, 205, 206, 4, 3, 4, 0, 206, 216, 3, 102, 51, 0, 207, 208, 4, 3, 5, 0, 208, 216, 3, 104, 52, 0, 209, 210, 4, 3, 6, 0, 210, 216, 3, 116, 58, 0, 211, 212, 4, 3, 7, 0, 212, 216, 3, 114, 57, 0, 213, 214, 4, 3, 8, 0, 214, 216, 3, 120, 60, 0, 215, 186, 1, 0, 0, 0, 215, 187, 1, 0, 0, 0, 215, 188, 1, 0, 0, 0, 215, 189, 1, 0, 0, 0, 215, 190, 1, 0, 0, 0, 215, 191, 1, 0, 0, 0, 215, 192, 1, 0, 0, 0, 215, 193, 1, 0, 0, 0, 215, 194, 1, 0, 0, 0, 215, 195, 1, 0, 0, 0, 215, 196, 1, 0, 0, 0, 215, 197, 1, 0, 0, 0, 215, 198, 1, 0, 0, 0, 215, 199, 1, 0, 0, 0, 215, 200, 1, 0, 0, 0, 215, 201, 1, 0, 0, 0, 215, 203, 1, 0, 0, 0, 215, 205, 1, 0, 0, 0, 215, 207, 1, 0, 0, 0, 215, 209, 1, 0, 0, 0, 215, 211, 1, 0, 0, 0, 215, 213, 1, 0, 0, 0, 216, 7, 1, 0, 0, 0, 217, 218, 5, 15, 0, 0, 218, 219, 3, 122, 61, 0, 219, 9, 1, 0, 0, 0, 220, 221, 3, 52, 26, 0, 221, 11, 1, 0, 0, 0, 222, 223, 5, 12, 0, 0, 223, 224, 3, 14, 7, 0, 224, 13, 1, 0, 0, 0, 225, 230, 3, 16, 8, 0, 226, 227, 5, 63, 0, 0, 227, 229, 3, 16, 8, 0, 228, 226, 1, 0, 0, 0, 229, 232, 1, 0, 0, 0, 230, 228, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 15, 1, 0, 0, 0, 232, 230, 1, 0, 0, 0, 233, 234, 3, 46, 23, 0, 234, 235, 5, 59, 0, 0, 235, 237, 1, 0, 0, 0, 236, 233, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 239, 3, 122, 61, 0, 239, 17, 1, 0, 0, 0, 240, 245, 3, 20, 10, 0, 241, 242, 5, 63, 0, 0, 242, 244, 3, 20, 10, 0, 243, 241, 1, 0, 0, 0, 244, 247, 1, 0, 0, 0, 245, 243, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 246, 19, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 248, 251, 3, 46, 23, 0, 249, 250, 5, 59, 0, 0, 250, 252, 3, 122, 61, 0, 251, 249, 1, 0, 0, 0, 251, 252, 1, 0, 0, 0, 252, 21, 1, 0, 0, 0, 253, 254, 5, 19, 0, 0, 254, 255, 3, 26, 13, 0, 255, 23, 1, 0, 0, 0, 256, 257, 5, 20, 0, 0, 257, 258, 3, 26, 13, 0, 258, 25, 1, 0, 0, 0, 259, 264, 3, 28, 14, 0, 260, 261, 5, 63, 0, 0, 261, 263, 3, 28, 14, 0, 262, 260, 1, 0, 0, 0, 263, 266, 1, 0, 0, 0, 264, 262, 1, 0, 0, 0, 264, 265, 1, 0, 0, 0, 265, 268, 1, 0, 0, 0, 266, 264, 1, 0, 0, 0, 267, 269, 3, 36, 18, 0, 268, 267, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 27, 1, 0, 0, 0, 270, 271, 3, 30, 15, 0, 271, 272, 5, 62, 0, 0, 272, 274, 1, 0, 0, 0, 273, 270, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 282, 3, 34, 17, 0, 276, 279, 3, 34, 17, 0, 277, 278, 5, 61, 0, 0, 278, 280, 3, 32, 16, 0, 279, 277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 282, 1, 0, 0, 0, 281, 273, 1, 0, 0, 0, 281, 276, 1, 0, 0, 0, 282, 29, 1, 0, 0, 0, 283, 284, 7, 0, 0, 0, 284, 31, 1, 0, 0, 0, 285, 286, 7, 0, 0, 0, 286, 33, 1, 0, 0, 0, 287, 288, 7, 0, 0, 0, 288, 35, 1, 0, 0, 0, 289, 290, 5, 107, 0, 0, 290, 295, 5, 108, 0, 0, 291, 292, 5, 63, 0, 0, 292, 294, 5, 108, 0, 0, 293, 291, 1, 0, 0, 0, 294, 297, 1, 0, 0, 0, 295, 293, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 37, 1, 0, 0, 0, 297, 295, 1, 0, 0, 0, 298, 299, 5, 9, 0, 0, 299, 300, 3, 14, 7, 0, 300, 39, 1, 0, 0, 0, 301, 303, 5, 14, 0, 0, 302, 304, 3, 42, 21, 0, 303, 302, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 307, 1, 0, 0, 0, 305, 306, 5, 60, 0, 0, 306, 308, 3, 14, 7, 0, 307, 305, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308, 41, 1, 0, 0, 0, 309, 314, 3, 44, 22, 0, 310, 311, 5, 63, 0, 0, 311, 313, 3, 44, 22, 0, 312, 310, 1, 0, 0, 0, 313, 316, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 314, 315, 1, 0, 0, 0, 315, 43, 1, 0, 0, 0, 316, 314, 1, 0, 0, 0, 317, 320, 3, 16, 8, 0, 318, 319, 5, 15, 0, 0, 319, 321, 3, 122, 61, 0, 320, 318, 1, 0, 0, 0, 320, 321, 1, 0, 0, 0, 321, 45, 1, 0, 0, 0, 322, 327, 3, 60, 30, 0, 323, 324, 5, 65, 0, 0, 324, 326, 3, 60, 30, 0, 325, 323, 1, 0, 0, 0, 326, 329, 1, 0, 0, 0, 327, 325, 1, 0, 0, 0, 327, 328, 1, 0, 0, 0, 328, 47, 1, 0, 0, 0, 329, 327, 1, 0, 0, 0, 330, 335, 3, 54, 27, 0, 331, 332, 5, 65, 0, 0, 332, 334, 3, 54, 27, 0, 333, 331, 1, 0, 0, 0, 334, 337, 1, 0, 0, 0, 335, 333, 1, 0, 0, 0, 335, 336, 1, 0, 0, 0, 336, 49, 1, 0, 0, 0, 337, 335, 1, 0, 0, 0, 338, 343, 3, 48, 24, 0, 339, 340, 5, 63, 0, 0, 340, 342, 3, 48, 24, 0, 341, 339, 1, 0, 0, 0, 342, 345, 1, 0, 0, 0, 343, 341, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, 344, 51, 1, 0, 0, 0, 345, 343, 1, 0, 0, 0, 346, 347, 7, 1, 0, 0, 347, 53, 1, 0, 0, 0, 348, 352, 5, 129, 0, 0, 349, 352, 3, 56, 28, 0, 350, 352, 3, 58, 29, 0, 351, 348, 1, 0, 0, 0, 351, 349, 1, 0, 0, 0, 351, 350, 1, 0, 0, 0, 352, 55, 1, 0, 0, 0, 353, 356, 5, 77, 0, 0, 354, 356, 5, 96, 0, 0, 355, 353, 1, 0, 0, 0, 355, 354, 1, 0, 0, 0, 356, 57, 1, 0, 0, 0, 357, 360, 5, 95, 0, 0, 358, 360, 5, 97, 0, 0, 359, 357, 1, 0, 0, 0, 359, 358, 1, 0, 0, 0, 360, 59, 1, 0, 0, 0, 361, 365, 3, 52, 26, 0, 362, 365, 3, 56, 28, 0, 363, 365, 3, 58, 29, 0, 364, 361, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 364, 363, 1, 0, 0, 0, 365, 61, 1, 0, 0, 0, 366, 367, 5, 11, 0, 0, 367, 368, 3, 142, 71, 0, 368, 63, 1, 0, 0, 0, 369, 370, 5, 13, 0, 0, 370, 375, 3, 66, 33, 0, 371, 372, 5, 63, 0, 0, 372, 374, 3, 66, 33, 0, 373, 371, 1, 0, 0, 0, 374, 377, 1, 0, 0, 0, 375, 373, 1, 0, 0, 0, 375, 376, 1, 0, 0, 0, 376, 65, 1, 0, 0, 0, 377, 375, 1, 0, 0, 0, 378, 380, 3, 122, 61, 0, 379, 381, 7, 2, 0, 0, 380, 379, 1, 0, 0, 0, 380, 381, 1, 0, 0, 0, 381, 384, 1, 0, 0, 0, 382, 383, 5, 74, 0, 0, 383, 385, 7, 3, 0, 0, 384, 382, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 385, 67, 1, 0, 0, 0, 386, 387, 5, 29, 0, 0, 387, 388, 3, 50, 25, 0, 388, 69, 1, 0, 0, 0, 389, 390, 5, 28, 0, 0, 390, 391, 3, 50, 25, 0, 391, 71, 1, 0, 0, 0, 392, 393, 5, 32, 0, 0, 393, 398, 3, 74, 37, 0, 394, 395, 5, 63, 0, 0, 395, 397, 3, 74, 37, 0, 396, 394, 1, 0, 0, 0, 397, 400, 1, 0, 0, 0, 398, 396, 1, 0, 0, 0, 398, 399, 1, 0, 0, 0, 399, 73, 1, 0, 0, 0, 400, 398, 1, 0, 0, 0, 401, 402, 3, 48, 24, 0, 402, 403, 5, 57, 0, 0, 403, 404, 3, 48, 24, 0, 404, 75, 1, 0, 0, 0, 405, 406, 5, 8, 0, 0, 406, 407, 3, 132, 66, 0, 407, 409, 3, 152, 76, 0, 408, 410, 3, 82, 41, 0, 409, 408, 1, 0, 0, 0, 409, 410, 1, 0, 0, 0, 410, 77, 1, 0, 0, 0, 411, 412, 5, 10, 0, 0, 412, 413, 3, 132, 66, 0, 413, 414, 3, 152, 76, 0, 414, 79, 1, 0, 0, 0, 415, 416, 5, 27, 0, 0, 416, 417, 3, 46, 23, 0, 417, 81, 1, 0, 0, 0, 418, 423, 3, 84, 42, 0, 419, 420, 5, 63, 0, 0, 420, 422, 3, 84, 42, 0, 421, 419, 1, 0, 0, 0, 422, 425, 1, 0, 0, 0, 423, 421, 1, 0, 0, 0, 423, 424, 1, 0, 0, 0, 424, 83, 1, 0, 0, 0, 425, 423, 1, 0, 0, 0, 426, 427, 3, 52, 26, 0, 427, 428, 5, 59, 0, 0, 428, 429, 3, 142, 71, 0, 429, 85, 1, 0, 0, 0, 430, 431, 5, 6, 0, 0, 431, 432, 3, 88, 44, 0, 432, 87, 1, 0, 0, 0, 433, 434, 5, 98, 0, 0, 434, 435, 3, 2, 1, 0, 435, 436, 5, 99, 0, 0, 436, 89, 1, 0, 0, 0, 437, 438, 5, 33, 0, 0, 438, 439, 5, 136, 0, 0, 439, 91, 1, 0, 0, 0, 440, 441, 5, 5, 0, 0, 441, 444, 5, 38, 0, 0, 442, 443, 5, 75, 0, 0, 443, 445, 3, 48, 24, 0, 444, 442, 1, 0, 0, 0, 444, 445, 1, 0, 0, 0, 445, 455, 1, 0, 0, 0, 446, 447, 5, 80, 0, 0, 447, 452, 3, 94, 47, 0, 448, 449, 5, 63, 0, 0, 449, 451, 3, 94, 47, 0, 450, 448, 1, 0, 0, 0, 451, 454, 1, 0, 0, 0, 452, 450, 1, 0, 0, 0, 452, 453, 1, 0, 0, 0, 453, 456, 1, 0, 0, 0, 454, 452, 1, 0, 0, 0, 455, 446, 1, 0, 0, 0, 455, 456, 1, 0, 0, 0, 456, 93, 1, 0, 0, 0, 457, 458, 3, 48, 24, 0, 458, 459, 5, 59, 0, 0, 459, 461, 1, 0, 0, 0, 460, 457, 1, 0, 0, 0, 460, 461, 1, 0, 0, 0, 461, 462, 1, 0, 0, 0, 462, 463, 3, 48, 24, 0, 463, 95, 1, 0, 0, 0, 464, 465, 5, 26, 0, 0, 465, 466, 3, 28, 14, 0, 466, 467, 5, 75, 0, 0, 467, 468, 3, 50, 25, 0, 468, 97, 1, 0, 0, 0, 469, 470, 5, 16, 0, 0, 470, 473, 3, 42, 21, 0, 471, 472, 5, 60, 0, 0, 472, 474, 3, 14, 7, 0, 473, 471, 1, 0, 0, 0, 473, 474, 1, 0, 0, 0, 474, 99, 1, 0, 0, 0, 475, 476, 5, 4, 0, 0, 476, 479, 3, 46, 23, 0, 477, 478, 5, 75, 0, 0, 478, 480, 3, 46, 23, 0, 479, 477, 1, 0, 0, 0, 479, 480, 1, 0, 0, 0, 480, 486, 1, 0, 0, 0, 481, 482, 5, 57, 0, 0, 482, 483, 3, 46, 23, 0, 483, 484, 5, 63, 0, 0, 484, 485, 3, 46, 23, 0, 485, 487, 1, 0, 0, 0, 486, 481, 1, 0, 0, 0, 486, 487, 1, 0, 0, 0, 487, 101, 1, 0, 0, 0, 488, 489, 5, 30, 0, 0, 489, 490, 3, 50, 25, 0, 490, 103, 1, 0, 0, 0, 491, 492, 5, 21, 0, 0, 492, 493, 3, 106, 53, 0, 493, 105, 1, 0, 0, 0, 494, 496, 3, 108, 54, 0, 495, 494, 1, 0, 0, 0, 496, 497, 1, 0, 0, 0, 497, 495, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 107, 1, 0, 0, 0, 499, 500, 5, 100, 0, 0, 500, 501, 3, 110, 55, 0, 501, 502, 5, 101, 0, 0, 502, 109, 1, 0, 0, 0, 503, 504, 6, 55, -1, 0, 504, 505, 3, 112, 56, 0, 505, 511, 1, 0, 0, 0, 506, 507, 10, 1, 0, 0, 507, 508, 5, 52, 0, 0, 508, 510, 3, 112, 56, 0, 509, 506, 1, 0, 0, 0, 510, 513, 1, 0, 0, 0, 511, 509, 1, 0, 0, 0, 511, 512, 1, 0, 0, 0, 512, 111, 1, 0, 0, 0, 513, 511, 1, 0, 0, 0, 514, 521, 3, 38, 19, 0, 515, 521, 3, 8, 4, 0, 516, 521, 3, 62, 31, 0, 517, 521, 3, 40, 20, 0, 518, 521, 3, 64, 32, 0, 519, 521, 3, 76, 38, 0, 520, 514, 1, 0, 0, 0, 520, 515, 1, 0, 0, 0, 520, 516, 1, 0, 0, 0, 520, 517, 1, 0, 0, 0, 520, 518, 1, 0, 0, 0, 520, 519, 1, 0, 0, 0, 521, 113, 1, 0, 0, 0, 522, 523, 5, 31, 0, 0, 523, 115, 1, 0, 0, 0, 524, 525, 5, 17, 0, 0, 525, 526, 3, 142, 71, 0, 526, 527, 5, 75, 0, 0, 527, 530, 3, 18, 9, 0, 528, 529, 5, 80, 0, 0, 529, 531, 3, 60, 30, 0, 530, 528, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, 531, 117, 1, 0, 0, 0, 532, 533, 5, 7, 0, 0, 533, 534, 3, 132, 66, 0, 534, 535, 5, 80, 0, 0, 535, 538, 3, 60, 30, 0, 536, 537, 5, 57, 0, 0, 537, 539, 3, 46, 23, 0, 538, 536, 1, 0, 0, 0, 538, 539, 1, 0, 0, 0, 539, 119, 1, 0, 0, 0, 540, 541, 5, 18, 0, 0, 541, 542, 3, 148, 74, 0, 542, 121, 1, 0, 0, 0, 543, 544, 6, 61, -1, 0, 544, 545, 5, 72, 0, 0, 545, 573, 3, 122, 61, 8, 546, 573, 3, 128, 64, 0, 547, 573, 3, 124, 62, 0, 548, 550, 3, 128, 64, 0, 549, 551, 5, 72, 0, 0, 550, 549, 1, 0, 0, 0, 550, 551, 1, 0, 0, 0, 551, 552, 1, 0, 0, 0, 552, 553, 5, 68, 0, 0, 553, 554, 5, 100, 0, 0, 554, 559, 3, 128, 64, 0, 555, 556, 5, 63, 0, 0, 556, 558, 3, 128, 64, 0, 557, 555, 1, 0, 0, 0, 558, 561, 1, 0, 0, 0, 559, 557, 1, 0, 0, 0, 559, 560, 1, 0, 0, 0, 560, 562, 1, 0, 0, 0, 561, 559, 1, 0, 0, 0, 562, 563, 5, 101, 0, 0, 563, 573, 1, 0, 0, 0, 564, 565, 3, 128, 64, 0, 565, 567, 5, 69, 0, 0, 566, 568, 5, 72, 0, 0, 567, 566, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 569, 1, 0, 0, 0, 569, 570, 5, 73, 0, 0, 570, 573, 1, 0, 0, 0, 571, 573, 3, 126, 63, 0, 572, 543, 1, 0, 0, 0, 572, 546, 1, 0, 0, 0, 572, 547, 1, 0, 0, 0, 572, 548, 1, 0, 0, 0, 572, 564, 1, 0, 0, 0, 572, 571, 1, 0, 0, 0, 573, 582, 1, 0, 0, 0, 574, 575, 10, 5, 0, 0, 575, 576, 5, 56, 0, 0, 576, 581, 3, 122, 61, 6, 577, 578, 10, 4, 0, 0, 578, 579, 5, 76, 0, 0, 579, 581, 3, 122, 61, 5, 580, 574, 1, 0, 0, 0, 580, 577, 1, 0, 0, 0, 581, 584, 1, 0, 0, 0, 582, 580, 1, 0, 0, 0, 582, 583, 1, 0, 0, 0, 583, 123, 1, 0, 0, 0, 584, 582, 1, 0, 0, 0, 585, 587, 3, 128, 64, 0, 586, 588, 5, 72, 0, 0, 587, 586, 1, 0, 0, 0, 587, 588, 1, 0, 0, 0, 588, 589, 1, 0, 0, 0, 589, 590, 5, 71, 0, 0, 590, 591, 3, 152, 76, 0, 591, 600, 1, 0, 0, 0, 592, 594, 3, 128, 64, 0, 593, 595, 5, 72, 0, 0, 594, 593, 1, 0, 0, 0, 594, 595, 1, 0, 0, 0, 595, 596, 1, 0, 0, 0, 596, 597, 5, 78, 0, 0, 597, 598, 3, 152, 76, 0, 598, 600, 1, 0, 0, 0, 599, 585, 1, 0, 0, 0, 599, 592, 1, 0, 0, 0, 600, 125, 1, 0, 0, 0, 601, 604, 3, 46, 23, 0, 602, 603, 5, 61, 0, 0, 603, 605, 3, 10, 5, 0, 604, 602, 1, 0, 0, 0, 604, 605, 1, 0, 0, 0, 605, 606, 1, 0, 0, 0, 606, 607, 5, 62, 0, 0, 607, 608, 3, 142, 71, 0, 608, 127, 1, 0, 0, 0, 609, 615, 3, 130, 65, 0, 610, 611, 3, 130, 65, 0, 611, 612, 3, 154, 77, 0, 612, 613, 3, 130, 65, 0, 613, 615, 1, 0, 0, 0, 614, 609, 1, 0, 0, 0, 614, 610, 1, 0, 0, 0, 615, 129, 1, 0, 0, 0, 616, 617, 6, 65, -1, 0, 617, 621, 3, 132, 66, 0, 618, 619, 7, 4, 0, 0, 619, 621, 3, 130, 65, 3, 620, 616, 1, 0, 0, 0, 620, 618, 1, 0, 0, 0, 621, 630, 1, 0, 0, 0, 622, 623, 10, 2, 0, 0, 623, 624, 7, 5, 0, 0, 624, 629, 3, 130, 65, 3, 625, 626, 10, 1, 0, 0, 626, 627, 7, 4, 0, 0, 627, 629, 3, 130, 65, 2, 628, 622, 1, 0, 0, 0, 628, 625, 1, 0, 0, 0, 629, 632, 1, 0, 0, 0, 630, 628, 1, 0, 0, 0, 630, 631, 1, 0, 0, 0, 631, 131, 1, 0, 0, 0, 632, 630, 1, 0, 0, 0, 633, 634, 6, 66, -1, 0, 634, 642, 3, 142, 71, 0, 635, 642, 3, 46, 23, 0, 636, 642, 3, 134, 67, 0, 637, 638, 5, 100, 0, 0, 638, 639, 3, 122, 61, 0, 639, 640, 5, 101, 0, 0, 640, 642, 1, 0, 0, 0, 641, 633, 1, 0, 0, 0, 641, 635, 1, 0, 0, 0, 641, 636, 1, 0, 0, 0, 641, 637, 1, 0, 0, 0, 642, 648, 1, 0, 0, 0, 643, 644, 10, 1, 0, 0, 644, 645, 5, 61, 0, 0, 645, 647, 3, 10, 5, 0, 646, 643, 1, 0, 0, 0, 647, 650, 1, 0, 0, 0, 648, 646, 1, 0, 0, 0, 648, 649, 1, 0, 0, 0, 649, 133, 1, 0, 0, 0, 650, 648, 1, 0, 0, 0, 651, 652, 3, 136, 68, 0, 652, 666, 5, 100, 0, 0, 653, 667, 5, 90, 0, 0, 654, 659, 3, 122, 61, 0, 655, 656, 5, 63, 0, 0, 656, 658, 3, 122, 61, 0, 657, 655, 1, 0, 0, 0, 658, 661, 1, 0, 0, 0, 659, 657, 1, 0, 0, 0, 659, 660, 1, 0, 0, 0, 660, 664, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 662, 663, 5, 63, 0, 0, 663, 665, 3, 138, 69, 0, 664, 662, 1, 0, 0, 0, 664, 665, 1, 0, 0, 0, 665, 667, 1, 0, 0, 0, 666, 653, 1, 0, 0, 0, 666, 654, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 668, 1, 0, 0, 0, 668, 669, 5, 101, 0, 0, 669, 135, 1, 0, 0, 0, 670, 671, 3, 60, 30, 0, 671, 137, 1, 0, 0, 0, 672, 673, 5, 93, 0, 0, 673, 678, 3, 140, 70, 0, 674, 675, 5, 63, 0, 0, 675, 677, 3, 140, 70, 0, 676, 674, 1, 0, 0, 0, 677, 680, 1, 0, 0, 0, 678, 676, 1, 0, 0, 0, 678, 679, 1, 0, 0, 0, 679, 681, 1, 0, 0, 0, 680, 678, 1, 0, 0, 0, 681, 682, 5, 94, 0, 0, 682, 139, 1, 0, 0, 0, 683, 684, 3, 152, 76, 0, 684, 685, 5, 62, 0, 0, 685, 686, 3, 142, 71, 0, 686, 141, 1, 0, 0, 0, 687, 730, 5, 73, 0, 0, 688, 689, 3, 150, 75, 0, 689, 690, 5, 102, 0, 0, 690, 730, 1, 0, 0, 0, 691, 730, 3, 148, 74, 0, 692, 730, 3, 150, 75, 0, 693, 730, 3, 144, 72, 0, 694, 730, 3, 56, 28, 0, 695, 730, 3, 152, 76, 0, 696, 697, 5, 98, 0, 0, 697, 702, 3, 146, 73, 0, 698, 699, 5, 63, 0, 0, 699, 701, 3, 146, 73, 0, 700, 698, 1, 0, 0, 0, 701, 704, 1, 0, 0, 0, 702, 700, 1, 0, 0, 0, 702, 703, 1, 0, 0, 0, 703, 705, 1, 0, 0, 0, 704, 702, 1, 0, 0, 0, 705, 706, 5, 99, 0, 0, 706, 730, 1, 0, 0, 0, 707, 708, 5, 98, 0, 0, 708, 713, 3, 144, 72, 0, 709, 710, 5, 63, 0, 0, 710, 712, 3, 144, 72, 0, 711, 709, 1, 0, 0, 0, 712, 715, 1, 0, 0, 0, 713, 711, 1, 0, 0, 0, 713, 714, 1, 0, 0, 0, 714, 716, 1, 0, 0, 0, 715, 713, 1, 0, 0, 0, 716, 717, 5, 99, 0, 0, 717, 730, 1, 0, 0, 0, 718, 719, 5, 98, 0, 0, 719, 724, 3, 152, 76, 0, 720, 721, 5, 63, 0, 0, 721, 723, 3, 152, 76, 0, 722, 720, 1, 0, 0, 0, 723, 726, 1, 0, 0, 0, 724, 722, 1, 0, 0, 0, 724, 725, 1, 0, 0, 0, 725, 727, 1, 0, 0, 0, 726, 724, 1, 0, 0, 0, 727, 728, 5, 99, 0, 0, 728, 730, 1, 0, 0, 0, 729, 687, 1, 0, 0, 0, 729, 688, 1, 0, 0, 0, 729, 691, 1, 0, 0, 0, 729, 692, 1, 0, 0, 0, 729, 693, 1, 0, 0, 0, 729, 694, 1, 0, 0, 0, 729, 695, 1, 0, 0, 0, 729, 696, 1, 0, 0, 0, 729, 707, 1, 0, 0, 0, 729, 718, 1, 0, 0, 0, 730, 143, 1, 0, 0, 0, 731, 732, 7, 6, 0, 0, 732, 145, 1, 0, 0, 0, 733, 736, 3, 148, 74, 0, 734, 736, 3, 150, 75, 0, 735, 733, 1, 0, 0, 0, 735, 734, 1, 0, 0, 0, 736, 147, 1, 0, 0, 0, 737, 739, 7, 4, 0, 0, 738, 737, 1, 0, 0, 0, 738, 739, 1, 0, 0, 0, 739, 740, 1, 0, 0, 0, 740, 741, 5, 55, 0, 0, 741, 149, 1, 0, 0, 0, 742, 744, 7, 4, 0, 0, 743, 742, 1, 0, 0, 0, 743, 744, 1, 0, 0, 0, 744, 745, 1, 0, 0, 0, 745, 746, 5, 54, 0, 0, 746, 151, 1, 0, 0, 0, 747, 748, 5, 53, 0, 0, 748, 153, 1, 0, 0, 0, 749, 750, 7, 7, 0, 0, 750, 155, 1, 0, 0, 0, 751, 752, 7, 8, 0, 0, 752, 753, 5, 115, 0, 0, 753, 754, 3, 158, 79, 0, 754, 755, 3, 160, 80, 0, 755, 157, 1, 0, 0, 0, 756, 757, 3, 28, 14, 0, 757, 159, 1, 0, 0, 0, 758, 759, 5, 75, 0, 0, 759, 764, 3, 162, 81, 0, 760, 761, 5, 63, 0, 0, 761, 763, 3, 162, 81, 0, 762, 760, 1, 0, 0, 0, 763, 766, 1, 0, 0, 0, 764, 762, 1, 0, 0, 0, 764, 765, 1, 0, 0, 0, 765, 161, 1, 0, 0, 0, 766, 764, 1, 0, 0, 0, 767, 768, 3, 128, 64, 0, 768, 163, 1, 0, 0, 0, 70, 175, 184, 215, 230, 236, 245, 251, 264, 268, 273, 279, 281, 295, 303, 307, 314, 320, 327, 335, 343, 351, 355, 359, 364, 375, 380, 384, 398, 409, 423, 444, 452, 455, 460, 473, 479, 486, 497, 511, 520, 530, 538, 550, 559, 567, 572, 580, 582, 587, 594, 599, 604, 614, 620, 628, 630, 641, 648, 659, 664, 666, 678, 702, 713, 724, 729, 735, 738, 743, 764] \ No newline at end of file From 141ec720b1712caabe557800b9b6913ec2997c79 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Tue, 10 Jun 2025 13:31:54 +0200 Subject: [PATCH 32/58] Delete docs/changelog/127551.yaml --- docs/changelog/127551.yaml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 docs/changelog/127551.yaml diff --git a/docs/changelog/127551.yaml b/docs/changelog/127551.yaml deleted file mode 100644 index aa2bce70a971d..0000000000000 --- a/docs/changelog/127551.yaml +++ /dev/null @@ -1,6 +0,0 @@ -pr: 127551 -summary: "Retain the scores of portions of an ES|QL query, via a score function" -area: ES|QL -type: enhancement -issues: - - 120082 From ac3b0011e39a62e3dbbf2fffac34407c64e50366 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Tue, 10 Jun 2025 13:32:00 +0200 Subject: [PATCH 33/58] removed changelog (unneeded) --- docs/changelog/127551.yaml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 docs/changelog/127551.yaml diff --git a/docs/changelog/127551.yaml b/docs/changelog/127551.yaml deleted file mode 100644 index aa2bce70a971d..0000000000000 --- a/docs/changelog/127551.yaml +++ /dev/null @@ -1,6 +0,0 @@ -pr: 127551 -summary: "Retain the scores of portions of an ES|QL query, via a score function" -area: ES|QL -type: enhancement -issues: - - 120082 From 31db011a0c9816c38e684349b9bf2dac3ae7e118 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 26 Jun 2025 10:58:39 +0200 Subject: [PATCH 34/58] Update x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java Co-authored-by: Carlos Delgado <6339205+carlosdelest@users.noreply.github.com> --- .../xpack/esql/expression/function/fulltext/Score.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index 7c0f28f30be37..5d639eca924f1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -43,7 +43,7 @@ public class Score extends Function implements EvaluatorMapper { @FunctionInfo( returnType = "double", preview = true, - description = "Scores a full text function. Returns scores for all the resulting docs.", + description = "Scores an expression. Only full text functions will be scored. Returns scores for all the resulting docs.", examples = { @Example(file = "score-function", tag = "score-single") } ) public Score( From 36959c805d5afab2aa0190bfdfcc11deb5a72eb1 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 26 Jun 2025 10:59:00 +0200 Subject: [PATCH 35/58] Update x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java Co-authored-by: Carlos Delgado <6339205+carlosdelest@users.noreply.github.com> --- .../org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index 7267d04b03501..5aeea714c6c70 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -86,7 +86,7 @@ public void testScoreInWhereWithFilter() { assertThat(error.getMessage(), containsString("Condition expression needs to be boolean, found [DOUBLE]")); } - public void testScoreMeaninglessFunction() { + public void testScoreNonFullTextFunction() { var query = """ FROM test | EVAL meaningless = score(abs(-0.1)) From df01c8a4afffdd5ee8f6ee0afc265e9f752e7d8e Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Tue, 1 Jul 2025 12:10:42 +0200 Subject: [PATCH 36/58] revert unwanted changes --- .../_snippets/functions/description/knn.md | 6 ++++ .../esql/_snippets/functions/examples/knn.md | 30 +++++++++++++++++++ .../functions/functionNamedParams/knn.md | 19 ++++++++++++ .../esql/_snippets/functions/layout/knn.md | 30 +++++++++++++++++++ .../_snippets/functions/parameters/knn.md | 13 ++++++++ 5 files changed, 98 insertions(+) create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/knn.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/knn.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/knn.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/knn.md b/docs/reference/query-languages/esql/_snippets/functions/description/knn.md new file mode 100644 index 0000000000000..c39604bbf1fa6 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/knn.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +**Description** + +Finds the k nearest vectors to a query vector, as measured by a similarity metric. knn function finds nearest vectors through approximate search on indexed dense_vectors. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md b/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md new file mode 100644 index 0000000000000..2a474d7bfef13 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md @@ -0,0 +1,30 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +**Examples** + +```esql +from colors metadata _score +| where knn(rgb_vector, [0, 120, 0]) +| sort _score desc, color asc +``` + +| color:text | rgb_vector:dense_vector | +| --- | --- | +| green | [0.0, 128.0, 0.0] | +| black | [0.0, 0.0, 0.0] | +| olive | [128.0, 128.0, 0.0] | +| teal | [0.0, 128.0, 128.0] | +| lime | [0.0, 255.0, 0.0] | +| sienna | [160.0, 82.0, 45.0] | +| maroon | [128.0, 0.0, 0.0] | +| navy | [0.0, 0.0, 128.0] | +| gray | [128.0, 128.0, 128.0] | +| chartreuse | [127.0, 255.0, 0.0] | + +```esql +from colors metadata _score +| where knn(rgb_vector, [0,255,255], {"k": 4}) +| sort _score desc, color asc +``` + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md b/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md new file mode 100644 index 0000000000000..d663e403f8a42 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md @@ -0,0 +1,19 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +**Supported function named parameters** + +`num_candidates` +: (integer) The number of nearest neighbor candidates to consider per shard while doing knn search. Cannot exceed 10,000. Increasing num_candidates tends to improve the accuracy of the final results. Defaults to 1.5 * k + +`boost` +: (float) Floating point number used to decrease or increase the relevance scores of the query.Defaults to 1.0. + +`k` +: (integer) The number of nearest neighbors to return from each shard. Elasticsearch collects k results from each shard, then merges them to find the global top results. This value must be less than or equal to num_candidates. Defaults to 10. + +`rescore_oversample` +: (double) Applies the specified oversampling for rescoring quantized vectors. See [oversampling and rescoring quantized vectors](docs-content://solutions/search/vector/knn.md#dense-vector-knn-search-rescoring) for details. + +`similarity` +: (double) The minimum similarity required for a document to be considered a match. The similarity value calculated relates to the raw similarity used, not the document score. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/knn.md b/docs/reference/query-languages/esql/_snippets/functions/layout/knn.md new file mode 100644 index 0000000000000..dae08f95757b9 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/knn.md @@ -0,0 +1,30 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +## `KNN` [esql-knn] +```{applies_to} +stack: development +serverless: preview +``` + +**Syntax** + +:::{image} ../../../images/functions/knn.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/knn.md +::: + +:::{include} ../description/knn.md +::: + +:::{include} ../types/knn.md +::: + +:::{include} ../functionNamedParams/knn.md +::: + +:::{include} ../examples/knn.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md new file mode 100644 index 0000000000000..fb1b98a1e8a7a --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md @@ -0,0 +1,13 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`field` +: Field that the query will target. + +`query` +: Vector value to find top nearest neighbours for. + +`options` +: (Optional) kNN additional options as [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params). See [knn query](/reference/query-languages/query-dsl/query-dsl-match-query.md#query-dsl-knn-query) for more information. + From ee51465318d358ae3c62e4d799aaca36d91951d0 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Tue, 1 Jul 2025 12:20:25 +0200 Subject: [PATCH 37/58] restore --- .../_snippets/functions/description/knn.md | 6 -- .../esql/_snippets/functions/examples/knn.md | 30 -------- .../functions/functionNamedParams/knn.md | 19 ----- .../esql/_snippets/functions/layout/knn.md | 30 -------- .../_snippets/functions/parameters/knn.md | 13 ---- .../_snippets/operators/types/is_not_null.md | 3 + .../esql/_snippets/operators/types/is_null.md | 3 + .../definition/functions/st_geohash.json | 2 +- .../definition/functions/st_geohex.json | 2 +- .../functions/st_geohex_to_long.json | 2 +- .../functions/st_geohex_to_string.json | 2 +- .../definition/functions/st_geotile.json | 2 +- .../functions/st_geotile_to_long.json | 2 +- .../functions/st_geotile_to_string.json | 2 +- .../definition/operators/is_not_null.json | 72 ++++++++++++++----- .../kibana/definition/operators/is_null.json | 72 ++++++++++++++----- .../esql/kibana/docs/operators/is_not_null.md | 8 +-- .../esql/kibana/docs/operators/is_null.md | 7 +- 18 files changed, 123 insertions(+), 154 deletions(-) delete mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/knn.md delete mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/knn.md delete mode 100644 docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md delete mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/knn.md delete mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/knn.md b/docs/reference/query-languages/esql/_snippets/functions/description/knn.md deleted file mode 100644 index c39604bbf1fa6..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/description/knn.md +++ /dev/null @@ -1,6 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -**Description** - -Finds the k nearest vectors to a query vector, as measured by a similarity metric. knn function finds nearest vectors through approximate search on indexed dense_vectors. - diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md b/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md deleted file mode 100644 index 2a474d7bfef13..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md +++ /dev/null @@ -1,30 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -**Examples** - -```esql -from colors metadata _score -| where knn(rgb_vector, [0, 120, 0]) -| sort _score desc, color asc -``` - -| color:text | rgb_vector:dense_vector | -| --- | --- | -| green | [0.0, 128.0, 0.0] | -| black | [0.0, 0.0, 0.0] | -| olive | [128.0, 128.0, 0.0] | -| teal | [0.0, 128.0, 128.0] | -| lime | [0.0, 255.0, 0.0] | -| sienna | [160.0, 82.0, 45.0] | -| maroon | [128.0, 0.0, 0.0] | -| navy | [0.0, 0.0, 128.0] | -| gray | [128.0, 128.0, 128.0] | -| chartreuse | [127.0, 255.0, 0.0] | - -```esql -from colors metadata _score -| where knn(rgb_vector, [0,255,255], {"k": 4}) -| sort _score desc, color asc -``` - - diff --git a/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md b/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md deleted file mode 100644 index d663e403f8a42..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md +++ /dev/null @@ -1,19 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -**Supported function named parameters** - -`num_candidates` -: (integer) The number of nearest neighbor candidates to consider per shard while doing knn search. Cannot exceed 10,000. Increasing num_candidates tends to improve the accuracy of the final results. Defaults to 1.5 * k - -`boost` -: (float) Floating point number used to decrease or increase the relevance scores of the query.Defaults to 1.0. - -`k` -: (integer) The number of nearest neighbors to return from each shard. Elasticsearch collects k results from each shard, then merges them to find the global top results. This value must be less than or equal to num_candidates. Defaults to 10. - -`rescore_oversample` -: (double) Applies the specified oversampling for rescoring quantized vectors. See [oversampling and rescoring quantized vectors](docs-content://solutions/search/vector/knn.md#dense-vector-knn-search-rescoring) for details. - -`similarity` -: (double) The minimum similarity required for a document to be considered a match. The similarity value calculated relates to the raw similarity used, not the document score. - diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/knn.md b/docs/reference/query-languages/esql/_snippets/functions/layout/knn.md deleted file mode 100644 index dae08f95757b9..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/knn.md +++ /dev/null @@ -1,30 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -## `KNN` [esql-knn] -```{applies_to} -stack: development -serverless: preview -``` - -**Syntax** - -:::{image} ../../../images/functions/knn.svg -:alt: Embedded -:class: text-center -::: - - -:::{include} ../parameters/knn.md -::: - -:::{include} ../description/knn.md -::: - -:::{include} ../types/knn.md -::: - -:::{include} ../functionNamedParams/knn.md -::: - -:::{include} ../examples/knn.md -::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md deleted file mode 100644 index fb1b98a1e8a7a..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md +++ /dev/null @@ -1,13 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -**Parameters** - -`field` -: Field that the query will target. - -`query` -: Vector value to find top nearest neighbours for. - -`options` -: (Optional) kNN additional options as [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params). See [knn query](/reference/query-languages/query-dsl/query-dsl-match-query.md#query-dsl-knn-query) for more information. - diff --git a/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md b/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md index 19fc0a9465976..f2b65a11de81e 100644 --- a/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md +++ b/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md @@ -7,6 +7,9 @@ | boolean | boolean | | cartesian_point | boolean | | cartesian_shape | boolean | +| counter_double | boolean | +| counter_integer | boolean | +| counter_long | boolean | | date | boolean | | date_nanos | boolean | | double | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md b/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md index 19fc0a9465976..f2b65a11de81e 100644 --- a/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md +++ b/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md @@ -7,6 +7,9 @@ | boolean | boolean | | cartesian_point | boolean | | cartesian_shape | boolean | +| counter_double | boolean | +| counter_integer | boolean | +| counter_long | boolean | | date | boolean | | date_nanos | boolean | | double | boolean | diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json index 43633b336453a..d2fc83008c150 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json @@ -52,4 +52,4 @@ ], "preview" : true, "snapshot_only" : true -} +} \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json index f29db14ed50e7..9a3a04cb0a7f8 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json @@ -55,4 +55,4 @@ ], "preview" : true, "snapshot_only" : true -} +} \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json index d582739620024..52c7918a0c3ad 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json @@ -34,4 +34,4 @@ ], "preview" : true, "snapshot_only" : true -} +} \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json index a1abce7c75adb..612b13691d40c 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json @@ -34,4 +34,4 @@ ], "preview" : true, "snapshot_only" : true -} +} \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json index d728f186fc5ae..06df5e3076fea 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json @@ -52,4 +52,4 @@ ], "preview" : true, "snapshot_only" : true -} +} \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json index b2c7c01aea606..2eb49b5c320f9 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json @@ -34,4 +34,4 @@ ], "preview" : true, "snapshot_only" : true -} +} \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json index 5a327c2c50976..df8e91514dc7b 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json @@ -34,4 +34,4 @@ ], "preview" : true, "snapshot_only" : true -} +} \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json b/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json index 2eba6c6c6730f..3722fbfaddeb8 100644 --- a/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json +++ b/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json @@ -3,7 +3,8 @@ "type" : "operator", "operator" : "IS NOT NULL", "name" : "is_not_null", - "description" : "Use `IS NOT NULL` to filter data based on whether the field exists or not.", + "description" : "Returns `false` if the value is `NULL`, `true` otherwise.", + "note" : "If a field is only in some documents it will be `NULL` in the documents that did not contain it.", "signatures" : [ { "params" : [ @@ -11,7 +12,7 @@ "name" : "field", "type" : "boolean", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -23,7 +24,7 @@ "name" : "field", "type" : "cartesian_point", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -35,7 +36,43 @@ "name" : "field", "type" : "cartesian_shape", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "counter_double", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "counter_integer", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "counter_long", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -47,7 +84,7 @@ "name" : "field", "type" : "date", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -59,7 +96,7 @@ "name" : "field", "type" : "date_nanos", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -71,7 +108,7 @@ "name" : "field", "type" : "double", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -83,7 +120,7 @@ "name" : "field", "type" : "geo_point", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -95,7 +132,7 @@ "name" : "field", "type" : "geo_shape", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -107,7 +144,7 @@ "name" : "field", "type" : "integer", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -119,7 +156,7 @@ "name" : "field", "type" : "ip", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -131,7 +168,7 @@ "name" : "field", "type" : "keyword", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -143,7 +180,7 @@ "name" : "field", "type" : "long", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -155,7 +192,7 @@ "name" : "field", "type" : "text", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -167,7 +204,7 @@ "name" : "field", "type" : "unsigned_long", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -179,16 +216,13 @@ "name" : "field", "type" : "version", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, "returnType" : "boolean" } ], - "examples" : [ - "FROM employees\n| WHERE is_rehired IS NOT NULL\n| STATS COUNT(emp_no)" - ], "preview" : false, "snapshot_only" : false } diff --git a/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json b/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json index 6eda2b9db776e..0f6e70f8a0b91 100644 --- a/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json +++ b/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json @@ -3,7 +3,8 @@ "type" : "operator", "operator" : "IS NULL", "name" : "is_null", - "description" : "Use `IS NULL` to filter data based on whether the field exists or not.", + "description" : "Returns `true` if the value is `NULL`, `false` otherwise.", + "note" : "If a field is only in some documents it will be `NULL` in the documents that did not contain it.", "signatures" : [ { "params" : [ @@ -11,7 +12,7 @@ "name" : "field", "type" : "boolean", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -23,7 +24,7 @@ "name" : "field", "type" : "cartesian_point", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -35,7 +36,43 @@ "name" : "field", "type" : "cartesian_shape", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "counter_double", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "counter_integer", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "counter_long", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -47,7 +84,7 @@ "name" : "field", "type" : "date", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -59,7 +96,7 @@ "name" : "field", "type" : "date_nanos", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -71,7 +108,7 @@ "name" : "field", "type" : "double", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -83,7 +120,7 @@ "name" : "field", "type" : "geo_point", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -95,7 +132,7 @@ "name" : "field", "type" : "geo_shape", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -107,7 +144,7 @@ "name" : "field", "type" : "integer", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -119,7 +156,7 @@ "name" : "field", "type" : "ip", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -131,7 +168,7 @@ "name" : "field", "type" : "keyword", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -143,7 +180,7 @@ "name" : "field", "type" : "long", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -155,7 +192,7 @@ "name" : "field", "type" : "text", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -167,7 +204,7 @@ "name" : "field", "type" : "unsigned_long", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, @@ -179,16 +216,13 @@ "name" : "field", "type" : "version", "optional" : false, - "description" : "Input value. The input can be a single- or multi-valued column or an expression." + "description" : "Value to check. It can be a single- or multi-valued column or an expression." } ], "variadic" : false, "returnType" : "boolean" } ], - "examples" : [ - "FROM employees\n| WHERE birth_date IS NULL" - ], "preview" : false, "snapshot_only" : false } diff --git a/docs/reference/query-languages/esql/kibana/docs/operators/is_not_null.md b/docs/reference/query-languages/esql/kibana/docs/operators/is_not_null.md index 2dd2dc0902746..25157e2bb7af2 100644 --- a/docs/reference/query-languages/esql/kibana/docs/operators/is_not_null.md +++ b/docs/reference/query-languages/esql/kibana/docs/operators/is_not_null.md @@ -1,10 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. ### IS NOT NULL -Use `IS NOT NULL` to filter data based on whether the field exists or not. +Returns `false` if the value is `NULL`, `true` otherwise. -```esql -FROM employees -| WHERE is_rehired IS NOT NULL -| STATS COUNT(emp_no) -``` +Note: If a field is only in some documents it will be `NULL` in the documents that did not contain it. diff --git a/docs/reference/query-languages/esql/kibana/docs/operators/is_null.md b/docs/reference/query-languages/esql/kibana/docs/operators/is_null.md index 8a21704a6a70b..625b819935332 100644 --- a/docs/reference/query-languages/esql/kibana/docs/operators/is_null.md +++ b/docs/reference/query-languages/esql/kibana/docs/operators/is_null.md @@ -1,9 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. ### IS NULL -Use `IS NULL` to filter data based on whether the field exists or not. +Returns `true` if the value is `NULL`, `false` otherwise. -```esql -FROM employees -| WHERE birth_date IS NULL -``` +Note: If a field is only in some documents it will be `NULL` in the documents that did not contain it. From 25e9d4cd8fb4463b3ef11585f0addc30b73f8ebe Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Wed, 2 Jul 2025 17:27:28 +0200 Subject: [PATCH 38/58] only run esql spec IT --- .../main/resources/score-function.csv-spec | 1 + .../xpack/esql/plugin/ScoreFunctionIT.java | 22 ++++++++++++++++++- .../elasticsearch/xpack/esql/CsvTests.java | 4 ++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec index f0e471901e000..518ce28e6c027 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec @@ -109,6 +109,7 @@ book_no:keyword | author:text | s1:double matchWithDisjunctionAndFiltersConjunction required_capability: match_function required_capability: full_text_functions_disjunctions +required_capability: score_function from books | eval s1 = score((match(author, "Vonnegut") or match(author, "Guinane")) and year > 1997) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index 5aeea714c6c70..b09396f991f0e 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.CollectionUtils; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; import org.elasticsearch.xpack.kql.KqlPlugin; @@ -23,7 +24,7 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.hamcrest.CoreMatchers.containsString; -//@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") +@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") public class ScoreFunctionIT extends AbstractEsqlIntegTestCase { @Before @@ -31,6 +32,25 @@ public void setupIndex() { createAndPopulateIndex(); } + public void testScoreSingleNoMetadata() { + var query = """ + FROM test + | WHERE match(content, "fox") AND match(content, "brown") + | EVAL first_score = score(match(content, "fox")) + | KEEP id, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues( + resp.values(), + List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624)) + ); + } + } + public void testScoreDifferentWhereMatch() { var query = """ FROM test METADATA _score diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index 6935a1efac2ae..cef9ccce994f0 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -276,6 +276,10 @@ public final void test() throws Throwable { "can't use match in csv tests", testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.MATCH_OPERATOR_COLON.capabilityName()) ); + assumeFalse( + "can't use score function in csv tests", + testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.SCORE_FUNCTION.capabilityName()) + ); assumeFalse( "can't load metrics in csv tests", testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.METRICS_COMMAND.capabilityName()) From df3f8ac64a845c55c4f9d90623a0d1aeeb520ece Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 3 Jul 2025 10:59:33 +0200 Subject: [PATCH 39/58] csv test fixes --- .../src/main/resources/score-function.csv-spec | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec index 518ce28e6c027..37f8a2ed0e321 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec @@ -17,7 +17,7 @@ FROM books METADATA _score ; // tag::score-single-result[] -book_no:keyword | title:text | _score:double | first _score:double +book_no:keyword | title:text | _score:double | first_score:double 2714 | Return of the King Being the Third Part of The Lord of the Rings | 0 | 0 7350 | Return of the Shadow | 0 | 0 // end::score-single-result[] @@ -34,7 +34,7 @@ FROM books | LIMIT 5 ; -book_no:keyword | author:text | first _score:double +book_no:keyword | author:text | first_score:double 2714 | Return of the King Being the Third Part of The Lord of the Rings | 0 7350 | Return of the Shadow | 0 ; @@ -75,7 +75,7 @@ book_no:keyword | author:text | stars: 3293 | Danny Faulkner | 2 | 0.0 ; -matchWithConjunction +scoreMatchWithConjunction required_capability: score_function required_capability: metadata_score @@ -89,7 +89,7 @@ book_no:keyword | title:text 7140 |The Lord of the Rings Poster Collection: Six Paintings by Alan Lee (No. 1) | 0.0 ; -scoreWithDisjunction +scoreMatchWithDisjunction required_capability: metadata_score required_capability: score_function @@ -106,7 +106,7 @@ book_no:keyword | author:text | s1:double 3950 | Kurt Vonnegut | 0.0 ; -matchWithDisjunctionAndFiltersConjunction +scoreMatchWithDisjunctionAndFiltersConjunction required_capability: match_function required_capability: full_text_functions_disjunctions required_capability: score_function From 0c46574261944c63b85cdd80f2ecca76f0214921 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Thu, 3 Jul 2025 09:08:35 +0000 Subject: [PATCH 40/58] [CI] Auto commit changes from spotless --- .../org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index b09396f991f0e..26c844f277a5e 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -44,10 +44,7 @@ public void testScoreSingleNoMetadata() { try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("id", "first_score")); assertColumnTypes(resp.columns(), List.of("integer", "double")); - assertValues( - resp.values(), - List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624)) - ); + assertValues(resp.values(), List.of(List.of(1, 1.156558871269226), List.of(6, 0.9114001989364624))); } } From 28848db63957717da43a0dd24412d9e0727838a2 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 3 Jul 2025 11:18:51 +0200 Subject: [PATCH 41/58] csv test fixes --- .../main/resources/score-function.csv-spec | 94 +------------------ 1 file changed, 5 insertions(+), 89 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec index 37f8a2ed0e321..a3d6b1edf1cbd 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec @@ -17,9 +17,9 @@ FROM books METADATA _score ; // tag::score-single-result[] -book_no:keyword | title:text | _score:double | first_score:double -2714 | Return of the King Being the Third Part of The Lord of the Rings | 0 | 0 -7350 | Return of the Shadow | 0 | 0 +book_no:keyword | title:text | _score:double | first_score:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 3.1309072971343994 | 1.9245924949645996 +7350 | Return of the Shadow | 4.8434343338012695 | 3.5432329177856445 // end::score-single-result[] ; @@ -35,91 +35,7 @@ FROM books ; book_no:keyword | author:text | first_score:double -2714 | Return of the King Being the Third Part of The Lord of the Rings | 0 -7350 | Return of the Shadow | 0 +2714 | J. R. R. Tolkien | 1.9245924949645996 +7350 | [Christopher Tolkien, John Ronald Reuel Tolkien] | 3.5432329177856445 ; -scoreWithQueryExpressions -required_capability: score_function -required_capability: metadata_score - -from books -FROM books METADATA _score -| WHERE match(title, "Return") AND match(author, "Tolkien") -| EVAL first_score = score(match(title, CONCAT("Return ", " King"))) -| keep book_no, title; -ignoreOrder:true - -book_no:keyword | title:text | _score:double | first _score:double -2714 | Return of the King Being the Third Part of The Lord of the Rings | 0 | 0 -7350 | Return of the Shadow | 0 | 0 -; - -scoreAfterEval -required_capability: score_function -required_capability: metadata_score - -from books METADATA _score -| eval stars = to_long(ratings / 2.0) -| eval s1 = score(match(author, "William")) -| where match(author, "Faulkner") -| sort book_no -| keep book_no, author, stars, s1 -| limit 5; - -book_no:keyword | author:text | stars:long | s1:double -2378 | [Carol Faulkner, Holly Byers Ochoa, Lucretia Mott] | 3 | 0.0 -2713 | William Faulkner | 2 | 0.9 -2847 | Colleen Faulkner | 3 | 0.0 -2883 | William Faulkner | 2 | 0.9 -3293 | Danny Faulkner | 2 | 0.0 -; - -scoreMatchWithConjunction -required_capability: score_function -required_capability: metadata_score - -from books METADATA _score -| eval s1 = score(match(title, "Rings") and ratings > 4.6) -| keep book_no, title, s1; -ignoreOrder:true - -book_no:keyword | title:text |s1:double -4023 |A Tolkien Compass: Including J. R. R. Tolkien's Guide to the Names in The Lord of the Rings | 0.0 -7140 |The Lord of the Rings Poster Collection: Six Paintings by Alan Lee (No. 1) | 0.0 -; - -scoreMatchWithDisjunction -required_capability: metadata_score -required_capability: score_function - -from books METADATA _score -| eval s1 = score(match(author, "Vonnegut") or match(author, "Guinane")) -| where match(author, "Vonnegut") -| keep book_no, author, s1; -ignoreOrder:true - -book_no:keyword | author:text | s1:double -2464 | Kurt Vonnegut | 0.0 -6970 | Edith Vonnegut | 0.0 -8956 | Kurt Vonnegut | 0.0 -3950 | Kurt Vonnegut | 0.0 -; - -scoreMatchWithDisjunctionAndFiltersConjunction -required_capability: match_function -required_capability: full_text_functions_disjunctions -required_capability: score_function - -from books -| eval s1 = score((match(author, "Vonnegut") or match(author, "Guinane")) and year > 1997) -| where match(author, "Vonnegut") -| keep book_no, author, year, s1; -ignoreOrder:true - -book_no:keyword | author:text | year:integer | s1:double -2464 | Kurt Vonnegut | 1998 | 0.0 -6970 | Edith Vonnegut | 1998 | 0.0 -8956 | Kurt Vonnegut | 1998 | 0.0 -3950 | Kurt Vonnegut | 1998 | 0.0 -; From 177b9f3c161d8371c8d8ec32e79bf208effeeda4 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 3 Jul 2025 11:47:03 +0200 Subject: [PATCH 42/58] csv test fixes --- .../main/resources/score-function.csv-spec | 19 +++++++++++++++++++ .../xpack/esql/plugin/ScoreFunctionIT.java | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec index a3d6b1edf1cbd..3f6256b9da2f3 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec @@ -39,3 +39,22 @@ book_no:keyword | author:text | first_score:double 7350 | [Christopher Tolkien, John Ronald Reuel Tolkien] | 3.5432329177856445 ; +scoreAfterEval +required_capability: score_function +required_capability: metadata_score + +FROM books METADATA _score +| EVAL stars = to_long(ratings / 2.0) +| EVAL s1 = score(match(author, "William")) +| WHERE match(author, "Faulkner") +| SORT book_no +| KEEP book_no, author, stars, s1 +| limit 5; + +book_no:keyword | author:text | stars:long | s1:double +2378 | [Carol Faulkner, Holly Byers Ochoa, Lucretia Mott] | 3 | 0.0 +2713 | William Faulkner | 2 | 1.9043500423431396 +2847 | Colleen Faulkner | 3 | 0.0 +2883 | William Faulkner | 2 | 1.9043500423431396 +3293 | Danny Faulkner | 2 | 0.0 +; diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index 26c844f277a5e..dd95df8bbdbbd 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -48,6 +48,22 @@ public void testScoreSingleNoMetadata() { } } + public void testDisjunctionWithFiltersNoMetadata() { + var query = """ + FROM test + | EVAL first_score = score((match(content, "fox") OR match(content, "brown")) AND id > 1) + | WHERE match(content, "fox") AND match(content, "brown") + | KEEP id, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of(List.of(1, 1.4274532496929169), List.of(6, 1.1248724162578583))); + } + } + public void testScoreDifferentWhereMatch() { var query = """ FROM test METADATA _score From 1bec8d6a45d2a67635324db30bead41edb86ee13 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 3 Jul 2025 13:31:10 +0200 Subject: [PATCH 43/58] csv test fixes --- .../main/resources/score-function.csv-spec | 74 ++++++++++++++++++- .../xpack/esql/plugin/ScoreFunctionIT.java | 19 ++++- .../expression/function/fulltext/Score.java | 2 +- 3 files changed, 88 insertions(+), 7 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec index 3f6256b9da2f3..cd095793064a6 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec @@ -5,6 +5,7 @@ scoreSingle required_capability: metadata_score required_capability: score_function +required_capability: match_function // tag::score-single[] FROM books METADATA _score @@ -25,23 +26,25 @@ book_no:keyword | title:text scoreSingleNoMetadata required_capability: score_function +required_capability: match_function FROM books | WHERE match(title, "Return") AND match(author, "Tolkien") | EVAL first_score = score(match(title, "Return")) -| KEEP book_no, author, first_score +| KEEP book_no, title, first_score | SORT book_no | LIMIT 5 ; -book_no:keyword | author:text | first_score:double -2714 | J. R. R. Tolkien | 1.9245924949645996 -7350 | [Christopher Tolkien, John Ronald Reuel Tolkien] | 3.5432329177856445 +book_no:keyword | title:text | first_score:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 1.9245924949645996 +7350 | Return of the Shadow | 3.5432329177856445 ; scoreAfterEval required_capability: score_function required_capability: metadata_score +required_capability: match_function FROM books METADATA _score | EVAL stars = to_long(ratings / 2.0) @@ -58,3 +61,66 @@ book_no:keyword | author:text | stars:lon 2883 | William Faulkner | 2 | 1.9043500423431396 3293 | Danny Faulkner | 2 | 0.0 ; + +scoreWithQueryExpressions + +FROM books METADATA _score +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL s2 = score(match(title, concat("Return ", "King"))) +| KEEP book_no, title, _score, s2 +| SORT book_no +| LIMIT 5 +; + +book_no:keyword | title:text | _score:double | s2:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 3.1309072971343994 | 3.849184989929199 +7350 | Return of the Shadow | 4.8434343338012695 | 3.5432329177856445 +; + +scoreMatchWithFilterConjunction +required_capability: score_function +required_capability: match_function + +FROM books +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL s1 = score(match(title, "Rings") and ratings > 4.6) +| KEEP book_no, title, s1 +| SORT book_no +| LIMIT 5; + +book_no:keyword | title:text | s1:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 1.9245924949645996 +7350 | Return of the Shadow | 0.0 +; + +scoreMatchWithDisjunction +required_capability: score_function +required_capability: match_function + +FROM books +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL s1 = score(match(title, "Rings") or match(title, "Shadow")) +| KEEP book_no, title, s1 +| SORT book_no +| LIMIT 5; + +book_no:keyword | title:text | s1:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 1.9245924949645996 +7350 | Return of the Shadow | 3.5432329177856445 +; + +scoreMatchWithDisjunctionAndFilter +required_capability: score_function +required_capability: match_function + +FROM books +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL s1 = score(match(title, "Rings") or match(title, "Shadow") and ratings > 4.6) +| KEEP book_no, title, s1 +| SORT book_no +| LIMIT 5; + +book_no:keyword | title:text | s1:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 1.9245924949645996 +7350 | Return of the Shadow | 3.5432329177856445 +; diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index dd95df8bbdbbd..f6395dea70d9c 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -12,7 +12,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.CollectionUtils; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; import org.elasticsearch.xpack.kql.KqlPlugin; @@ -24,7 +23,7 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.hamcrest.CoreMatchers.containsString; -@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") +//@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE,org.elasticsearch.compute:TRACE", reason = "debug") public class ScoreFunctionIT extends AbstractEsqlIntegTestCase { @Before @@ -48,6 +47,22 @@ public void testScoreSingleNoMetadata() { } } + public void testScoreQueryExpressions() { + var query = """ + FROM test METADATA _score + | WHERE match(content, "fox") AND match(content, "brown") + | EVAL first_score = score(match(content, CONCAT("brown ", " fox"))) + | KEEP id, first_score + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of(List.of(1, 1.4274532794952393), List.of(6, 1.1248724460601807))); + } + } + public void testDisjunctionWithFiltersNoMetadata() { var query = """ FROM test diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index b4456a06d4ceb..cd63b2f18467f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -48,7 +48,7 @@ public class Score extends Function implements EvaluatorMapper { ) public Score( Source source, - @Param(name = "query", type = { "boolean" }, description = "full text function.") Expression scorableQuery + @Param(name = "query", type = { "boolean", "keyword", "text" }, description = "full text function.") Expression scorableQuery ) { this(source, List.of(scorableQuery)); } From d91cf1038bbd12359274c193fdd3914683af73dc Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 3 Jul 2025 13:32:42 +0200 Subject: [PATCH 44/58] data type fix --- .../xpack/esql/expression/function/fulltext/Score.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index cd63b2f18467f..c7e596c1de458 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -48,7 +48,7 @@ public class Score extends Function implements EvaluatorMapper { ) public Score( Source source, - @Param(name = "query", type = { "boolean", "keyword", "text" }, description = "full text function.") Expression scorableQuery + @Param(name = "query", type = { "boolean" }, description = "(combinations of) full text function(s).") Expression scorableQuery ) { this(source, List.of(scorableQuery)); } From d1210427838006fc447487546799ad496c3d9ce3 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Thu, 3 Jul 2025 15:08:28 +0200 Subject: [PATCH 45/58] dropped test --- .../src/main/resources/score-function.csv-spec | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec index cd095793064a6..37eddeb883f61 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec @@ -62,21 +62,6 @@ book_no:keyword | author:text | stars:lon 3293 | Danny Faulkner | 2 | 0.0 ; -scoreWithQueryExpressions - -FROM books METADATA _score -| WHERE match(title, "Return") AND match(author, "Tolkien") -| EVAL s2 = score(match(title, concat("Return ", "King"))) -| KEEP book_no, title, _score, s2 -| SORT book_no -| LIMIT 5 -; - -book_no:keyword | title:text | _score:double | s2:double -2714 | Return of the King Being the Third Part of The Lord of the Rings | 3.1309072971343994 | 3.849184989929199 -7350 | Return of the Shadow | 4.8434343338012695 | 3.5432329177856445 -; - scoreMatchWithFilterConjunction required_capability: score_function required_capability: match_function From 10edc0596bf5a23ee77661b2fda975913c2cb97a Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 11 Jul 2025 14:07:58 +0200 Subject: [PATCH 46/58] improved checks and tests --- .../xpack/esql/plugin/ScoreFunctionIT.java | 4 +++- .../expression/function/fulltext/FullTextFunction.java | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index f6395dea70d9c..4db8674f9b712 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -14,6 +14,7 @@ import org.elasticsearch.plugins.Plugin; import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; import org.elasticsearch.xpack.kql.KqlPlugin; import org.junit.Before; @@ -28,6 +29,7 @@ public class ScoreFunctionIT extends AbstractEsqlIntegTestCase { @Before public void setupIndex() { + assumeTrue("can run this only when score() function is enabled", EsqlCapabilities.Cap.SCORE_FUNCTION.isEnabled()); createAndPopulateIndex(); } @@ -121,7 +123,7 @@ public void testScoreInWhereWithMatch() { """; var error = expectThrows(VerificationException.class, () -> run(query)); - assertThat(error.getMessage(), containsString("[MATCH] function can't be used with SCORE")); + assertThat(error.getMessage(), containsString("[SCORE] function can't be used in WHERE")); } public void testScoreInWhereWithFilter() { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index 1831025ef12cf..4308e1fffd10f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -16,6 +16,7 @@ import org.elasticsearch.compute.operator.ScoreOperator; import org.elasticsearch.index.IndexMode; import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; import org.elasticsearch.xpack.esql.capabilities.PostAnalysisPlanVerificationAware; import org.elasticsearch.xpack.esql.capabilities.TranslationAware; import org.elasticsearch.xpack.esql.common.Failures; @@ -197,6 +198,12 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu if (plan instanceof Filter f) { Expression condition = f.condition(); + if (condition instanceof Score) { + failures.add( + fail(condition, "[SCORE] function can't be used in WHERE") + ); + } + List.of(QueryString.class, Kql.class).forEach(functionClass -> { // Check for limitations of QSTR and KQL function. checkCommandsBeforeExpression( @@ -228,7 +235,8 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu failures.add( fail( ftf, - "[{}] {} is only supported in WHERE and STATS commands, or in EVAL within score(.) function", + "[{}] {} is only supported in WHERE and STATS commands" + + (EsqlCapabilities.Cap.SCORE_FUNCTION.isEnabled() ? ", or in EVAL within score(.) function" : ""), ftf.functionName(), ftf.functionType() ) From afc1287fce638a1f8cf8d4b27d80bcc6d87074db Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Fri, 11 Jul 2025 12:15:43 +0000 Subject: [PATCH 47/58] [CI] Auto commit changes from spotless --- .../esql/expression/function/fulltext/FullTextFunction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index 4308e1fffd10f..ef3b3c0e76b34 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -199,9 +199,7 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu Expression condition = f.condition(); if (condition instanceof Score) { - failures.add( - fail(condition, "[SCORE] function can't be used in WHERE") - ); + failures.add(fail(condition, "[SCORE] function can't be used in WHERE")); } List.of(QueryString.class, Kql.class).forEach(functionClass -> { From f0cd4021158532529ba7b03ca9de346378affe78 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 11 Jul 2025 14:26:08 +0200 Subject: [PATCH 48/58] check score is always used before limit, aggs, etc. --- .../xpack/esql/plugin/ScoreFunctionIT.java | 31 +++++++++++++++++++ .../function/fulltext/FullTextFunction.java | 15 ++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java index 4db8674f9b712..6c60c0334eddd 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoreFunctionIT.java @@ -49,6 +49,37 @@ public void testScoreSingleNoMetadata() { } } + public void testScoreWithLimit() { + var query = """ + FROM test + | WHERE match(content, "fox") AND match(content, "brown") + | EVAL first_score = score(match(content, "fox")) + | KEEP id, first_score + | SORT id + | LIMIT 1 + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id", "first_score")); + assertColumnTypes(resp.columns(), List.of("integer", "double")); + assertValues(resp.values(), List.of(List.of(1, 1.156558871269226))); + } + } + + public void testScoreAfterLimit() { + var query = """ + FROM test + | WHERE match(content, "fox") AND match(content, "brown") + | LIMIT 1 + | EVAL first_score = score(match(content, "fox")) + | KEEP id, first_score + | SORT id + """; + + var error = expectThrows(VerificationException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("[SCORE] function cannot be used after LIMIT")); + } + public void testScoreQueryExpressions() { var query = """ FROM test METADATA _score diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index 4308e1fffd10f..a90d7ddc643ca 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -229,7 +229,9 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu checkFullTextFunctionsInAggs(agg, failures); } else { List scoredFTFs = new ArrayList<>(); - plan.forEachExpression(Score.class, scoreFunction -> { plan.forEachExpression(FullTextFunction.class, scoredFTFs::add); }); + plan.forEachExpression(Score.class, scoreFunction -> { + checkScoreFunction(plan, failures, scoreFunction); + plan.forEachExpression(FullTextFunction.class, scoredFTFs::add); }); plan.forEachExpression(FullTextFunction.class, ftf -> { if (scoredFTFs.remove(ftf) == false) { failures.add( @@ -246,6 +248,17 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu } } + private static void checkScoreFunction(LogicalPlan plan, Failures failures, Score scoreFunction) { + checkCommandsBeforeExpression( + plan, + scoreFunction.canonical(), + Score.class, + lp -> (lp instanceof Limit == false) && (lp instanceof Aggregate == false), + m -> "[" + m.functionName() + "] function", + failures + ); + } + private static void checkFullTextFunctionsInAggs(Aggregate agg, Failures failures) { agg.groupings().forEach(exp -> { exp.forEachDown(e -> { From b96431362255b288c5cea3ef7e1bf93fe4f6fd6c Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 11 Jul 2025 14:27:13 +0200 Subject: [PATCH 49/58] spotless --- .../esql/expression/function/fulltext/FullTextFunction.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java index 66b3adf82a715..d499e29079963 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextFunction.java @@ -229,7 +229,8 @@ private static void checkFullTextQueryFunctions(LogicalPlan plan, Failures failu List scoredFTFs = new ArrayList<>(); plan.forEachExpression(Score.class, scoreFunction -> { checkScoreFunction(plan, failures, scoreFunction); - plan.forEachExpression(FullTextFunction.class, scoredFTFs::add); }); + plan.forEachExpression(FullTextFunction.class, scoredFTFs::add); + }); plan.forEachExpression(FullTextFunction.class, ftf -> { if (scoredFTFs.remove(ftf) == false) { failures.add( From f4dfa0a4fca0df41f408e4716013df05351213b8 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 11 Jul 2025 14:40:02 +0200 Subject: [PATCH 50/58] non pushable disjunction csv test --- .../src/main/resources/score-function.csv-spec | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec index 37eddeb883f61..a4165a197e935 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec @@ -109,3 +109,19 @@ book_no:keyword | title:text 2714 | Return of the King Being the Third Part of The Lord of the Rings | 1.9245924949645996 7350 | Return of the Shadow | 3.5432329177856445 ; + +scoreMatchDisjunctionNonPushable +required_capability: score_function +required_capability: match_function + +FROM books +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL s1 = score(match(title, "Rings") or ratings > 4.6) +| KEEP book_no, title, s1 +| SORT book_no +| LIMIT 5; + +book_no:keyword | title:text | s1:double +2714 | Return of the King Being the Third Part of The Lord of the Rings | 1.9245924949645996 +7350 | Return of the Shadow | 0.0 +; From 88997d9a9c7f2463bea037c166d22f8792be432b Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 11 Jul 2025 16:50:35 +0200 Subject: [PATCH 51/58] minor fix --- .../xpack/esql/expression/function/fulltext/Score.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index c7e596c1de458..e36aad8df8a1c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -22,6 +22,8 @@ import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesTo; +import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; import org.elasticsearch.xpack.esql.expression.function.Param; import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; @@ -43,6 +45,7 @@ public class Score extends Function implements EvaluatorMapper { @FunctionInfo( returnType = "double", preview = true, + appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.DEVELOPMENT) }, description = "Scores an expression. Only full text functions will be scored. Returns scores for all the resulting docs.", examples = { @Example(file = "score-function", tag = "score-single") } ) From 97822b3fe16e07d5ef56b3f53c6b2c805925d7a8 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 11 Jul 2025 17:00:05 +0200 Subject: [PATCH 52/58] minor fix --- .../expression/function/EsqlFunctionRegistry.java | 3 ++- .../esql/expression/function/fulltext/Score.java | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index fd7f853eec089..9669cd7e9c2fa 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -489,7 +489,8 @@ private static FunctionDefinition[][] snapshotFunctions() { def(StGeotileToString.class, StGeotileToString::new, "st_geotile_to_string"), def(StGeohex.class, StGeohex::new, "st_geohex"), def(StGeohexToLong.class, StGeohexToLong::new, "st_geohex_to_long"), - def(StGeohexToString.class, StGeohexToString::new, "st_geohex_to_string") } }; + def(StGeohexToString.class, StGeohexToString::new, "st_geohex_to_string"), + def(Score.class, Score::new, "score") } }; } public EsqlFunctionRegistry snapshotRegistry() { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index e36aad8df8a1c..0a630b0631140 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.util.List; +import java.util.Objects; /** * A function to be used to score specific portions of an ES|QL query e.g., in conjunction with @@ -120,4 +121,16 @@ public Block eval(Page page) { }; } } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + Score score = (Score) o; + return super.equals(o) && score.children().equals(children()); + } + + @Override + public int hashCode() { + return Objects.hash(children()); + } } From 86287a9ae7e896dc4fc04dd42ab35c6a96aed2f5 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 11 Jul 2025 17:03:18 +0200 Subject: [PATCH 53/58] minor fix --- .../xpack/esql/expression/function/EsqlFunctionRegistry.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index 9669cd7e9c2fa..fd7f853eec089 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -489,8 +489,7 @@ private static FunctionDefinition[][] snapshotFunctions() { def(StGeotileToString.class, StGeotileToString::new, "st_geotile_to_string"), def(StGeohex.class, StGeohex::new, "st_geohex"), def(StGeohexToLong.class, StGeohexToLong::new, "st_geohex_to_long"), - def(StGeohexToString.class, StGeohexToString::new, "st_geohex_to_string"), - def(Score.class, Score::new, "score") } }; + def(StGeohexToString.class, StGeohexToString::new, "st_geohex_to_string") } }; } public EsqlFunctionRegistry snapshotRegistry() { From 852fb22dbac181bc7d425a5ff99ecac1010ff0bf Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Fri, 11 Jul 2025 17:23:35 +0200 Subject: [PATCH 54/58] minor fix --- .../esql/_snippets/functions/description/md5.md | 2 +- .../esql/_snippets/functions/examples/knn.md | 10 ++-------- .../_snippets/functions/functionNamedParams/knn.md | 3 --- .../esql/_snippets/functions/parameters/knn.md | 3 +++ .../esql/kibana/definition/commands/rrf.json | 6 ------ .../esql/kibana/definition/functions/md5.json | 2 +- .../query-languages/esql/kibana/docs/functions/knn.md | 2 +- .../query-languages/esql/kibana/docs/functions/md5.md | 2 +- .../src/main/resources/score-function.csv-spec | 4 ++-- .../xpack/esql/expression/function/fulltext/Score.java | 2 +- 10 files changed, 12 insertions(+), 24 deletions(-) delete mode 100644 docs/reference/query-languages/esql/kibana/definition/commands/rrf.json diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/md5.md b/docs/reference/query-languages/esql/_snippets/functions/description/md5.md index 976d3e48a6bfa..cf702ee523749 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/md5.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/md5.md @@ -2,5 +2,5 @@ **Description** -Computes the MD5 hash of the input. +Computes the MD5 hash of the input (if the MD5 hash is available on the JVM). diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md b/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md index 2a474d7bfef13..df15bde7deb55 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md @@ -1,10 +1,10 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. -**Examples** +**Example** ```esql from colors metadata _score -| where knn(rgb_vector, [0, 120, 0]) +| where knn(rgb_vector, [0, 120, 0], 10) | sort _score desc, color asc ``` @@ -21,10 +21,4 @@ from colors metadata _score | gray | [128.0, 128.0, 128.0] | | chartreuse | [127.0, 255.0, 0.0] | -```esql -from colors metadata _score -| where knn(rgb_vector, [0,255,255], {"k": 4}) -| sort _score desc, color asc -``` - diff --git a/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md b/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md index d663e403f8a42..1e87271707676 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md +++ b/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md @@ -8,9 +8,6 @@ `boost` : (float) Floating point number used to decrease or increase the relevance scores of the query.Defaults to 1.0. -`k` -: (integer) The number of nearest neighbors to return from each shard. Elasticsearch collects k results from each shard, then merges them to find the global top results. This value must be less than or equal to num_candidates. Defaults to 10. - `rescore_oversample` : (double) Applies the specified oversampling for rescoring quantized vectors. See [oversampling and rescoring quantized vectors](docs-content://solutions/search/vector/knn.md#dense-vector-knn-search-rescoring) for details. diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md index fb1b98a1e8a7a..e33acabbd014f 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md @@ -8,6 +8,9 @@ `query` : Vector value to find top nearest neighbours for. +`k` +: The number of nearest neighbors to return from each shard. Elasticsearch collects k results from each shard, then merges them to find the global top results. This value must be less than or equal to num_candidates. + `options` : (Optional) kNN additional options as [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params). See [knn query](/reference/query-languages/query-dsl/query-dsl-match-query.md#query-dsl-knn-query) for more information. diff --git a/docs/reference/query-languages/esql/kibana/definition/commands/rrf.json b/docs/reference/query-languages/esql/kibana/definition/commands/rrf.json deleted file mode 100644 index 0db41f5f4016f..0000000000000 --- a/docs/reference/query-languages/esql/kibana/definition/commands/rrf.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "comment" : "This is generated by ESQL’s DocsV3Support. Do not edit it. See ../README.md for how to regenerate it.", - "type" : "command", - "name" : "rrf", - "license" : "ENTERPRISE" -} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/md5.json b/docs/reference/query-languages/esql/kibana/definition/functions/md5.json index b3d320ad838b4..b08d3681e6169 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/md5.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/md5.json @@ -2,7 +2,7 @@ "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.", "type" : "scalar", "name" : "md5", - "description" : "Computes the MD5 hash of the input.", + "description" : "Computes the MD5 hash of the input (if the MD5 hash is available on the JVM).", "signatures" : [ { "params" : [ diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/knn.md b/docs/reference/query-languages/esql/kibana/docs/functions/knn.md index c7af797488ba4..f32319b080dbb 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/knn.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/knn.md @@ -1,4 +1,4 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. ### KNN Finds the k nearest vectors to a query vector, as measured by a similarity metric. knn function finds nearest vectors through approximate search on indexed dense_vectors. diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/md5.md b/docs/reference/query-languages/esql/kibana/docs/functions/md5.md index 4229afca7398a..e96666870dc97 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/md5.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/md5.md @@ -1,7 +1,7 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. ### MD5 -Computes the MD5 hash of the input. +Computes the MD5 hash of the input (if the MD5 hash is available on the JVM). ```esql FROM sample_data diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec index a4165a197e935..1a39418e9a28d 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/score-function.csv-spec @@ -7,11 +7,11 @@ required_capability: metadata_score required_capability: score_function required_capability: match_function -// tag::score-single[] +// tag::score-function[] FROM books METADATA _score | WHERE match(title, "Return") AND match(author, "Tolkien") | EVAL first_score = score(match(title, "Return")) -// end::score-single[] +// end::score-function[] | KEEP book_no, title, _score, first_score | SORT book_no | LIMIT 5 diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index 0a630b0631140..1a6984056d072 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -48,7 +48,7 @@ public class Score extends Function implements EvaluatorMapper { preview = true, appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.DEVELOPMENT) }, description = "Scores an expression. Only full text functions will be scored. Returns scores for all the resulting docs.", - examples = { @Example(file = "score-function", tag = "score-single") } + examples = { @Example(file = "score-function", tag = "score-function") } ) public Score( Source source, From e888da206ab14be04b1d474b35ea3038eb738e9f Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Mon, 14 Jul 2025 17:44:04 +0200 Subject: [PATCH 55/58] ScoreTests and docs --- .../_snippets/functions/description/score.md | 6 ++ .../_snippets/functions/examples/score.md | 11 +++ .../esql/_snippets/functions/layout/score.md | 27 +++++++ .../_snippets/functions/parameters/score.md | 7 ++ .../esql/_snippets/functions/types/score.md | 8 +++ .../esql/images/functions/score.svg | 1 + .../kibana/definition/functions/score.json | 25 +++++++ .../esql/kibana/docs/functions/score.md | 10 +++ .../function/fulltext/ScoreTests.java | 72 +++++++++++++++++++ 9 files changed, 167 insertions(+) create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/score.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/score.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/score.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/score.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/score.md create mode 100644 docs/reference/query-languages/esql/images/functions/score.svg create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/score.json create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/score.md create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreTests.java diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/score.md b/docs/reference/query-languages/esql/_snippets/functions/description/score.md new file mode 100644 index 0000000000000..82426283b03a0 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/score.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +**Description** + +Scores an expression. Only full text functions will be scored. Returns scores for all the resulting docs. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/score.md b/docs/reference/query-languages/esql/_snippets/functions/examples/score.md new file mode 100644 index 0000000000000..86691e4e941a8 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/score.md @@ -0,0 +1,11 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +FROM books METADATA _score +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL first_score = score(match(title, "Return")) +``` + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/score.md b/docs/reference/query-languages/esql/_snippets/functions/layout/score.md new file mode 100644 index 0000000000000..b2fa5e09baeac --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/score.md @@ -0,0 +1,27 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +## `SCORE` [esql-score] +```{applies_to} +stack: development +serverless: preview +``` + +**Syntax** + +:::{image} ../../../images/functions/score.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/score.md +::: + +:::{include} ../description/score.md +::: + +:::{include} ../types/score.md +::: + +:::{include} ../examples/score.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/score.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/score.md new file mode 100644 index 0000000000000..511ced1094f91 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/score.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`query` +: (combinations of) full text function(s). + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/score.md b/docs/reference/query-languages/esql/_snippets/functions/types/score.md new file mode 100644 index 0000000000000..ab4532fd069a5 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/score.md @@ -0,0 +1,8 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| query | result | +| --- | --- | +| boolean | double | + diff --git a/docs/reference/query-languages/esql/images/functions/score.svg b/docs/reference/query-languages/esql/images/functions/score.svg new file mode 100644 index 0000000000000..9662976dd6db1 --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/score.svg @@ -0,0 +1 @@ +SCORE(query) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/score.json b/docs/reference/query-languages/esql/kibana/definition/functions/score.json new file mode 100644 index 0000000000000..c9b5e22a02e4c --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/score.json @@ -0,0 +1,25 @@ +{ + "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "score", + "description" : "Scores an expression. Only full text functions will be scored. Returns scores for all the resulting docs.", + "signatures" : [ + { + "params" : [ + { + "name" : "query", + "type" : "boolean", + "optional" : false, + "description" : "(combinations of) full text function(s)." + } + ], + "variadic" : false, + "returnType" : "double" + } + ], + "examples" : [ + "FROM books METADATA _score\n| WHERE match(title, \"Return\") AND match(author, \"Tolkien\")\n| EVAL first_score = score(match(title, \"Return\"))" + ], + "preview" : true, + "snapshot_only" : true +} diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/score.md b/docs/reference/query-languages/esql/kibana/docs/functions/score.md new file mode 100644 index 0000000000000..865a7b0758ba9 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/score.md @@ -0,0 +1,10 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +### SCORE +Scores an expression. Only full text functions will be scored. Returns scores for all the resulting docs. + +```esql +FROM books METADATA _score +| WHERE match(title, "Return") AND match(author, "Tolkien") +| EVAL first_score = score(match(title, "Return")) +``` diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreTests.java new file mode 100644 index 0000000000000..346b1cafa02f4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/ScoreTests.java @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; +import org.elasticsearch.xpack.esql.io.stream.PlanStreamOutput; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.SerializationTestUtils.serializeDeserialize; +import static org.elasticsearch.xpack.esql.core.type.DataType.BOOLEAN; +import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; +import static org.hamcrest.Matchers.equalTo; + +@FunctionName("score") +public class ScoreTests extends AbstractMatchFullTextFunctionTests { + + public ScoreTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + List suppliers = new ArrayList<>(); + suppliers.add( + new TestCaseSupplier( + List.of(BOOLEAN), + () -> new TestCaseSupplier.TestCase( + List.of(new TestCaseSupplier.TypedData(randomBoolean(), BOOLEAN, "query")), + equalTo("ScoreEvaluator" + ScoreTests.class.getSimpleName()), + DOUBLE, + equalTo(true) + ) + ) + ); + + return parameterSuppliersFromTypedData(suppliers); + } + + @Override + protected Expression build(Source source, List args) { + return new Score(source, args.getFirst()); + } + + /** + * Copy of the overridden method that doesn't check for children size, as the {@code options} child isn't serialized in Match. + */ + @Override + protected Expression serializeDeserializeExpression(Expression expression) { + Expression newExpression = serializeDeserialize( + expression, + PlanStreamOutput::writeNamedWriteable, + in -> in.readNamedWriteable(Expression.class), + testCase.getConfiguration() // The configuration query should be == to the source text of the function for this to work + ); + // Fields use synthetic sources, which can't be serialized. So we use the originals instead. + return newExpression.replaceChildren(expression.children()); + } +} From 398aa7c07862c8686c8eeec8ae97b80c9cd5eb15 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Mon, 14 Jul 2025 17:48:35 +0200 Subject: [PATCH 56/58] revert --- .../esql/_snippets/functions/description/md5.md | 2 +- .../esql/_snippets/functions/examples/knn.md | 10 ++++++++-- .../_snippets/functions/functionNamedParams/knn.md | 3 +++ .../esql/_snippets/functions/parameters/knn.md | 3 --- .../esql/kibana/definition/commands/rrf.json | 6 ++++++ .../esql/kibana/definition/functions/md5.json | 2 +- .../query-languages/esql/kibana/docs/functions/knn.md | 2 +- .../query-languages/esql/kibana/docs/functions/md5.md | 2 +- 8 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 docs/reference/query-languages/esql/kibana/definition/commands/rrf.json diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/md5.md b/docs/reference/query-languages/esql/_snippets/functions/description/md5.md index cf702ee523749..976d3e48a6bfa 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/md5.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/md5.md @@ -2,5 +2,5 @@ **Description** -Computes the MD5 hash of the input (if the MD5 hash is available on the JVM). +Computes the MD5 hash of the input. diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md b/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md index df15bde7deb55..2a474d7bfef13 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/knn.md @@ -1,10 +1,10 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. -**Example** +**Examples** ```esql from colors metadata _score -| where knn(rgb_vector, [0, 120, 0], 10) +| where knn(rgb_vector, [0, 120, 0]) | sort _score desc, color asc ``` @@ -21,4 +21,10 @@ from colors metadata _score | gray | [128.0, 128.0, 128.0] | | chartreuse | [127.0, 255.0, 0.0] | +```esql +from colors metadata _score +| where knn(rgb_vector, [0,255,255], {"k": 4}) +| sort _score desc, color asc +``` + diff --git a/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md b/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md index 1e87271707676..d663e403f8a42 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md +++ b/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/knn.md @@ -8,6 +8,9 @@ `boost` : (float) Floating point number used to decrease or increase the relevance scores of the query.Defaults to 1.0. +`k` +: (integer) The number of nearest neighbors to return from each shard. Elasticsearch collects k results from each shard, then merges them to find the global top results. This value must be less than or equal to num_candidates. Defaults to 10. + `rescore_oversample` : (double) Applies the specified oversampling for rescoring quantized vectors. See [oversampling and rescoring quantized vectors](docs-content://solutions/search/vector/knn.md#dense-vector-knn-search-rescoring) for details. diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md index e33acabbd014f..fb1b98a1e8a7a 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/knn.md @@ -8,9 +8,6 @@ `query` : Vector value to find top nearest neighbours for. -`k` -: The number of nearest neighbors to return from each shard. Elasticsearch collects k results from each shard, then merges them to find the global top results. This value must be less than or equal to num_candidates. - `options` : (Optional) kNN additional options as [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params). See [knn query](/reference/query-languages/query-dsl/query-dsl-match-query.md#query-dsl-knn-query) for more information. diff --git a/docs/reference/query-languages/esql/kibana/definition/commands/rrf.json b/docs/reference/query-languages/esql/kibana/definition/commands/rrf.json new file mode 100644 index 0000000000000..0db41f5f4016f --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/commands/rrf.json @@ -0,0 +1,6 @@ +{ + "comment" : "This is generated by ESQL’s DocsV3Support. Do not edit it. See ../README.md for how to regenerate it.", + "type" : "command", + "name" : "rrf", + "license" : "ENTERPRISE" +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/md5.json b/docs/reference/query-languages/esql/kibana/definition/functions/md5.json index b08d3681e6169..b3d320ad838b4 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/md5.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/md5.json @@ -2,7 +2,7 @@ "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.", "type" : "scalar", "name" : "md5", - "description" : "Computes the MD5 hash of the input (if the MD5 hash is available on the JVM).", + "description" : "Computes the MD5 hash of the input.", "signatures" : [ { "params" : [ diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/knn.md b/docs/reference/query-languages/esql/kibana/docs/functions/knn.md index f32319b080dbb..c7af797488ba4 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/knn.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/knn.md @@ -1,4 +1,4 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. ### KNN Finds the k nearest vectors to a query vector, as measured by a similarity metric. knn function finds nearest vectors through approximate search on indexed dense_vectors. diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/md5.md b/docs/reference/query-languages/esql/kibana/docs/functions/md5.md index e96666870dc97..4229afca7398a 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/md5.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/md5.md @@ -1,7 +1,7 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. ### MD5 -Computes the MD5 hash of the input (if the MD5 hash is available on the JVM). +Computes the MD5 hash of the input. ```esql FROM sample_data From 18df6f0534bc992dee48e1b50c9db3035c1ad902 Mon Sep 17 00:00:00 2001 From: Tommaso Teofili Date: Tue, 15 Jul 2025 09:23:39 +0200 Subject: [PATCH 57/58] Update x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java Co-authored-by: Carlos Delgado <6339205+carlosdelest@users.noreply.github.com> --- .../xpack/esql/expression/function/fulltext/Score.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index 1a6984056d072..ff62f1341406a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -52,7 +52,7 @@ public class Score extends Function implements EvaluatorMapper { ) public Score( Source source, - @Param(name = "query", type = { "boolean" }, description = "(combinations of) full text function(s).") Expression scorableQuery + @Param(name = "query", type = { "boolean" }, description = "Boolean expression that contains full text function(s) to be scored.") Expression scorableQuery ) { this(source, List.of(scorableQuery)); } From c0e6258855e8b7a6ec2dcf9410c9343c28224362 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine Date: Tue, 15 Jul 2025 07:33:02 +0000 Subject: [PATCH 58/58] [CI] Auto commit changes from spotless --- .../xpack/esql/expression/function/fulltext/Score.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java index ff62f1341406a..1b471931eaa0e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Score.java @@ -52,7 +52,11 @@ public class Score extends Function implements EvaluatorMapper { ) public Score( Source source, - @Param(name = "query", type = { "boolean" }, description = "Boolean expression that contains full text function(s) to be scored.") Expression scorableQuery + @Param( + name = "query", + type = { "boolean" }, + description = "Boolean expression that contains full text function(s) to be scored." + ) Expression scorableQuery ) { this(source, List.of(scorableQuery)); }