Skip to content

Commit 2e631d5

Browse files
authored
ESQL: Fix sorts containing _source (#116980) (#117191)
This fixes sorts containing the a `_source` field. It can use the standard encoder for `BytesRef`s. You can't sort *by* a `_source` field, but that doesn't really make sense ayway.
1 parent da914e5 commit 2e631d5

File tree

4 files changed

+53
-3
lines changed

4 files changed

+53
-3
lines changed

docs/changelog/116980.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 116980
2+
summary: "ESQL: Fix sorts containing `_source`"
3+
area: ES|QL
4+
type: bug
5+
issues:
6+
- 116659

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,12 @@ public enum Cap {
424424
*/
425425
SORTING_ON_SOURCE_AND_COUNTERS_FORBIDDEN,
426426

427+
/**
428+
* Fix {@code SORT} when the {@code _source} field is not a sort key but
429+
* <strong>is</strong> being returned.
430+
*/
431+
SORT_RETURNING_SOURCE_OK,
432+
427433
/**
428434
* Allow filter per individual aggregation.
429435
*/

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/LocalExecutionPlanner.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,10 @@ private PhysicalOperation planTopN(TopNExec topNExec, LocalExecutionPlannerConte
362362
case VERSION -> TopNEncoder.VERSION;
363363
case BOOLEAN, NULL, BYTE, SHORT, INTEGER, LONG, DOUBLE, FLOAT, HALF_FLOAT, DATETIME, DATE_NANOS, DATE_PERIOD, TIME_DURATION,
364364
OBJECT, SCALED_FLOAT, UNSIGNED_LONG, DOC_DATA_TYPE, TSID_DATA_TYPE -> TopNEncoder.DEFAULT_SORTABLE;
365-
case GEO_POINT, CARTESIAN_POINT, GEO_SHAPE, CARTESIAN_SHAPE, COUNTER_LONG, COUNTER_INTEGER, COUNTER_DOUBLE ->
365+
case GEO_POINT, CARTESIAN_POINT, GEO_SHAPE, CARTESIAN_SHAPE, COUNTER_LONG, COUNTER_INTEGER, COUNTER_DOUBLE, SOURCE ->
366366
TopNEncoder.DEFAULT_UNSORTABLE;
367367
// unsupported fields are encoded as BytesRef, we'll use the same encoder; all values should be null at this point
368368
case PARTIAL_AGG, UNSUPPORTED -> TopNEncoder.UNSUPPORTED;
369-
case SOURCE -> throw new EsqlIllegalArgumentException("No TopN sorting encoder for type " + inverse.get(channel).type());
370369
};
371370
}
372371
List<TopNOperator.SortOrder> orders = topNExec.order().stream().map(order -> {

x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/140_metadata.yml

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,43 @@ setup:
170170
catch: /cannot sort on _source/
171171
esql.query:
172172
body:
173-
query: 'FROM test metadata _source | sort _source'
173+
query: 'FROM test metadata _source | SORT _source'
174+
175+
---
176+
"sort returning _source is allowed":
177+
- requires:
178+
test_runner_features: [capabilities]
179+
capabilities:
180+
- method: POST
181+
path: /_query
182+
parameters: []
183+
capabilities: [sort_returning_source_ok]
184+
reason: "Sorts returning _source should be ok, but weren't in older versions"
185+
- do:
186+
esql.query:
187+
body:
188+
query: 'FROM test METADATA _source | SORT case ASC | KEEP case, _source | LIMIT 5'
189+
- length: { columns: 2 }
190+
- length: { values: 3 }
191+
- match: {columns.0.name: "case"}
192+
- match: {columns.0.type: "keyword"}
193+
- match: {columns.1.name: "_source"}
194+
- match: {columns.1.type: "_source"}
195+
- match: {values.0.0: "all_ignored"}
196+
- match: {values.0.1: {
197+
"integer" : "not-an-integer",
198+
"keyword" : "long-keyword",
199+
"case" : "all_ignored"
200+
}}
201+
- match: {values.1.0: "integer_ignored"}
202+
- match: {values.1.1: {
203+
"integer" : "not-an-integer",
204+
"keyword" : "ok",
205+
"case" : "integer_ignored"
206+
}}
207+
- match: {values.2.0: "ok"}
208+
- match: {values.2.1: {
209+
"integer" : 10,
210+
"keyword" : "ok",
211+
"case" : "ok"
212+
}}

0 commit comments

Comments
 (0)