Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/changelog/130914.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 130914
summary: Fix LIMIT NPE with null value
area: ES|QL
type: bug
issues:
- 130908
1 change: 1 addition & 0 deletions x-pack/plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ tasks.named("yamlRestCompatTestTransform").configure({ task ->
task.skipTest("esql/191_lookup_join_on_datastreams/data streams not supported in LOOKUP JOIN", "Added support for aliases in JOINs")
task.skipTest("esql/190_lookup_join/non-lookup index", "Error message changed")
task.skipTest("esql/192_lookup_join_on_aliases/alias-pattern-multiple", "Error message changed")
task.skipTest("esql/10_basic/Test wrong LIMIT parameter", "Error message changed")
})

tasks.named('yamlRestCompatTest').configure {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,11 @@ public enum Cap {
*/
PARAMETER_FOR_LIMIT,

/**
* Changed and normalized the LIMIT error message.
*/
NORMALIZED_LIMIT_ERROR_MESSAGE,

/**
* Dense vector field type support
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,21 +391,22 @@ public PlanFactory visitWhereCommand(EsqlBaseParser.WhereCommandContext ctx) {
public PlanFactory visitLimitCommand(EsqlBaseParser.LimitCommandContext ctx) {
Source source = source(ctx);
Object val = expression(ctx.constant()).fold(FoldContext.small() /* TODO remove me */);
if (val instanceof Integer i) {
if (i < 0) {
throw new ParsingException(source, "Invalid value for LIMIT [" + i + "], expecting a non negative integer");
}
if (val instanceof Integer i && i >= 0) {
return input -> new Limit(source, new Literal(source, i, DataType.INTEGER), input);
} else {
throw new ParsingException(
source,
"Invalid value for LIMIT ["
+ BytesRefs.toString(val)
+ ": "
+ (expression(ctx.constant()).dataType() == KEYWORD ? "String" : val.getClass().getSimpleName())
+ "], expecting a non negative integer"
);
}

String valueType = expression(ctx.constant()).dataType().typeName();

throw new ParsingException(
source,
"value of ["
+ source.text()
+ "] must be a non negative integer, found value ["
+ ctx.constant().getText()
+ "] type ["
+ valueType
+ "]"
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
import org.elasticsearch.xpack.esql.index.EsIndex;
import org.elasticsearch.xpack.esql.index.IndexResolution;
import org.elasticsearch.xpack.esql.parser.EsqlParser;
import org.elasticsearch.xpack.esql.parser.ParserUtils;
import org.elasticsearch.xpack.esql.parser.ParsingException;
import org.elasticsearch.xpack.esql.parser.QueryParam;
import org.elasticsearch.xpack.esql.parser.QueryParams;
import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan;
import org.elasticsearch.xpack.esql.plan.logical.Row;
import org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter;
Expand Down Expand Up @@ -157,9 +160,34 @@ public void testJoinTwiceOnTheSameField_TwoLookups() {
}

public void testInvalidLimit() {
assertEquals("1:13: Invalid value for LIMIT [foo: String], expecting a non negative integer", error("row a = 1 | limit \"foo\""));
assertEquals("1:13: Invalid value for LIMIT [1.2: Double], expecting a non negative integer", error("row a = 1 | limit 1.2"));
assertEquals("1:13: Invalid value for LIMIT [-1], expecting a non negative integer", error("row a = 1 | limit -1"));
assertLimitWithAndWithoutParams("foo", "\"foo\"", DataType.KEYWORD);
assertLimitWithAndWithoutParams(1.2, "1.2", DataType.DOUBLE);
assertLimitWithAndWithoutParams(-1, "-1", DataType.INTEGER);
assertLimitWithAndWithoutParams(true, "true", DataType.BOOLEAN);
assertLimitWithAndWithoutParams(false, "false", DataType.BOOLEAN);
assertLimitWithAndWithoutParams(null, "null", DataType.NULL);
}

private void assertLimitWithAndWithoutParams(Object value, String valueText, DataType type) {
assertEquals(
"1:13: value of [limit "
+ valueText
+ "] must be a non negative integer, found value ["
+ valueText
+ "] type ["
+ type.typeName()
+ "]",
error("row a = 1 | limit " + valueText)
);

assertEquals(
"1:13: value of [limit ?param] must be a non negative integer, found value [?param] type [" + type.typeName() + "]",
error(
"row a = 1 | limit ?param",
new QueryParams(List.of(new QueryParam("param", value, type, ParserUtils.ParamClassification.VALUE)))
)
);

}

public void testInvalidSample() {
Expand All @@ -181,13 +209,17 @@ public void testInvalidSample() {
);
}

private String error(String query) {
ParsingException e = expectThrows(ParsingException.class, () -> defaultAnalyzer.analyze(parser.createStatement(query)));
private String error(String query, QueryParams params) {
ParsingException e = expectThrows(ParsingException.class, () -> defaultAnalyzer.analyze(parser.createStatement(query, params)));
String message = e.getMessage();
assertTrue(message.startsWith("line "));
return message.substring("line ".length());
}

private String error(String query) {
return error(query, new QueryParams());
}

private static IndexResolution loadIndexResolution(String name) {
return IndexResolution.valid(new EsIndex(INDEX_NAME, LoadMapping.loadMapping(name)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,10 +945,6 @@ public void testBasicLimitCommand() {
assertThat(limit.children().get(0).children().get(0), instanceOf(UnresolvedRelation.class));
}

public void testLimitConstraints() {
expectError("from text | limit -1", "line 1:13: Invalid value for LIMIT [-1], expecting a non negative integer");
}

public void testBasicSortCommand() {
LogicalPlan plan = statement("from text | where true | sort a+b asc nulls first, x desc nulls last | sort y asc | sort z desc");
assertThat(plan, instanceOf(OrderBy.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,11 +555,11 @@ FROM EVAL SORT LIMIT with documents_found:
- method: POST
path: /_query
parameters: [ ]
capabilities: [ parameter_for_limit ]
capabilities: [ normalized_limit_error_message ]
reason: "named or positional parameters for field names"

- do:
catch: "/Invalid value for LIMIT \\[foo: String\\], expecting a non negative integer/"
catch: "/value of \\[limit \\?l\\] must be a non negative integer, found value \\[\\?l\\] type \\[keyword\\]/"
esql.query:
body:
query: 'from test | limit ?l'
Expand Down
Loading