Skip to content

Commit 625da5b

Browse files
committed
Add tests
1 parent 56d4317 commit 625da5b

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
119119
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
120120
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
121+
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
121122
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
122123
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
123124
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
@@ -2072,6 +2073,108 @@ public void testKnnWithoutExplicitLimit() {
20722073
assertThat(knnQuery.k(), is(config.resultTruncationDefaultSize()));
20732074
}
20742075

2076+
public void testKnnWithExplicitLimit() {
2077+
var query = """
2078+
from test
2079+
| where knn(dense_vector, [0, 1, 2])
2080+
| limit 10
2081+
""";
2082+
var analyzer = makeAnalyzer("mapping-all-types.json");
2083+
var plan = plannerOptimizer.plan(query, IS_SV_STATS, analyzer);
2084+
var limitExec = as(plan, LimitExec.class);
2085+
assertThat(limitExec.limit().fold(FoldContext.small()), is(10));
2086+
var exchangeExec = as(limitExec.child(), ExchangeExec.class);
2087+
var projectExec = as(exchangeExec.child(), ProjectExec.class);
2088+
var fieldExtractExec = as(projectExec.child(), FieldExtractExec.class);
2089+
var queryExec = as(fieldExtractExec.child(), EsQueryExec.class);
2090+
assertThat(queryExec.limit().fold(FoldContext.small()), is(10));
2091+
var knnQuery = as(queryExec.query(), KnnVectorQueryBuilder.class);
2092+
assertThat(knnQuery.k(), is(10));
2093+
}
2094+
2095+
public void testMultipleKnnQueriesLimit() {
2096+
var query = """
2097+
from test
2098+
| where knn(dense_vector, [0, 1, 2]) and (match(text, "example") or knn(dense_vector, [3, 4, 5]))
2099+
| limit 10
2100+
""";
2101+
var analyzer = makeAnalyzer("mapping-all-types.json");
2102+
var plan = plannerOptimizer.plan(query, IS_SV_STATS, analyzer);
2103+
var limitExec = as(plan, LimitExec.class);
2104+
assertThat(limitExec.limit().fold(FoldContext.small()), is(10));
2105+
var exchangeExec = as(limitExec.child(), ExchangeExec.class);
2106+
var projectExec = as(exchangeExec.child(), ProjectExec.class);
2107+
var fieldExtractExec = as(projectExec.child(), FieldExtractExec.class);
2108+
var queryExec = as(fieldExtractExec.child(), EsQueryExec.class);
2109+
assertThat(queryExec.limit().fold(FoldContext.small()), is(10));
2110+
var expectedQuery = boolQuery().must(new KnnVectorQueryBuilder("dense_vector", new float[] { 0f, 1f, 2f }, 10, null, null, null))
2111+
.must(
2112+
boolQuery().should(matchQuery("text", "example").lenient(true))
2113+
.should(new KnnVectorQueryBuilder("dense_vector", new float[] { 3f, 4f, 5f }, 10, null, null, null))
2114+
);
2115+
assertEquals(expectedQuery.toString(), queryExec.query().toString());
2116+
2117+
query = """
2118+
from test
2119+
| where knn(dense_vector, [0, 1, 2])
2120+
| where (match(text, "example") or knn(dense_vector, [3, 4, 5]))
2121+
| limit 10
2122+
""";
2123+
analyzer = makeAnalyzer("mapping-all-types.json");
2124+
plan = plannerOptimizer.plan(query, IS_SV_STATS, analyzer);
2125+
limitExec = as(plan, LimitExec.class);
2126+
assertThat(limitExec.limit().fold(FoldContext.small()), is(10));
2127+
exchangeExec = as(limitExec.child(), ExchangeExec.class);
2128+
projectExec = as(exchangeExec.child(), ProjectExec.class);
2129+
fieldExtractExec = as(projectExec.child(), FieldExtractExec.class);
2130+
queryExec = as(fieldExtractExec.child(), EsQueryExec.class);
2131+
assertThat(queryExec.limit().fold(FoldContext.small()), is(10));
2132+
expectedQuery = boolQuery().must(new KnnVectorQueryBuilder("dense_vector", new float[] { 0f, 1f, 2f }, 10, null, null, null))
2133+
.must(
2134+
boolQuery().should(matchQuery("text", "example").lenient(true))
2135+
.should(new KnnVectorQueryBuilder("dense_vector", new float[] { 3f, 4f, 5f }, 10, null, null, null))
2136+
);
2137+
assertEquals(expectedQuery.toString(), queryExec.query().toString());
2138+
}
2139+
2140+
public void testKnnWithCombinedLimits() {
2141+
var query = """
2142+
from test
2143+
| where knn(dense_vector, [0, 1, 2])
2144+
| limit 20
2145+
| limit 10
2146+
""";
2147+
var analyzer = makeAnalyzer("mapping-all-types.json");
2148+
var plan = plannerOptimizer.plan(query, IS_SV_STATS, analyzer);
2149+
var limitExec = as(plan, LimitExec.class);
2150+
assertThat(limitExec.limit().fold(FoldContext.small()), is(10));
2151+
var exchangeExec = as(limitExec.child(), ExchangeExec.class);
2152+
var projectExec = as(exchangeExec.child(), ProjectExec.class);
2153+
var fieldExtractExec = as(projectExec.child(), FieldExtractExec.class);
2154+
var queryExec = as(fieldExtractExec.child(), EsQueryExec.class);
2155+
assertThat(queryExec.limit().fold(FoldContext.small()), is(10));
2156+
var knnQuery = as(queryExec.query(), KnnVectorQueryBuilder.class);
2157+
assertThat(knnQuery.k(), is(10));
2158+
2159+
query = """
2160+
from test
2161+
| where knn(dense_vector, [0, 1, 2])
2162+
| limit 10
2163+
| limit 20
2164+
""";
2165+
analyzer = makeAnalyzer("mapping-all-types.json");
2166+
plan = plannerOptimizer.plan(query, IS_SV_STATS, analyzer);
2167+
limitExec = as(plan, LimitExec.class);
2168+
assertThat(limitExec.limit().fold(FoldContext.small()), is(10));
2169+
exchangeExec = as(limitExec.child(), ExchangeExec.class);
2170+
projectExec = as(exchangeExec.child(), ProjectExec.class);
2171+
fieldExtractExec = as(projectExec.child(), FieldExtractExec.class);
2172+
queryExec = as(fieldExtractExec.child(), EsQueryExec.class);
2173+
assertThat(queryExec.limit().fold(FoldContext.small()), is(10));
2174+
knnQuery = as(queryExec.query(), KnnVectorQueryBuilder.class);
2175+
assertThat(knnQuery.k(), is(10));
2176+
}
2177+
20752178
private boolean isMultiTypeEsField(Expression e) {
20762179
return e instanceof FieldAttribute fa && fa.field() instanceof MultiTypeEsField;
20772180
}

0 commit comments

Comments
 (0)