Skip to content

Commit 3313790

Browse files
authored
SQL: Enhance message for PERCENTILE[_RANK] with field as 2nd arg (#36933)
Enhance error message for the case that the 2nd argument of PERCENTILE and PERCENTILE_RANK is not a foldable, as it doesn't make sense to have a dynamic value coming from a field. Fixes: #36903
1 parent 046f86f commit 3313790

File tree

4 files changed

+39
-10
lines changed

4 files changed

+39
-10
lines changed

docs/reference/sql/functions/aggs.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ PERCENTILE(field_name<1>, numeric_exp<2>)
192192
*Input*:
193193

194194
<1> a numeric field
195-
<2> a numeric expression
195+
<2> a numeric expression (must be a constant and not based on a field)
196196

197197
*Output*: `double` numeric value
198198

@@ -218,7 +218,7 @@ PERCENTILE_RANK(field_name<1>, numeric_exp<2>)
218218
*Input*:
219219

220220
<1> a numeric field
221-
<2> a numeric expression
221+
<2> a numeric expression (must be a constant and not based on a field)
222222

223223
*Output*: `double` numeric value
224224

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Percentile.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
package org.elasticsearch.xpack.sql.expression.function.aggregate;
77

8+
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
89
import org.elasticsearch.xpack.sql.expression.Expression;
910
import org.elasticsearch.xpack.sql.expression.Expressions;
1011
import org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
@@ -41,13 +42,17 @@ public Percentile replaceChildren(List<Expression> newChildren) {
4142

4243
@Override
4344
protected TypeResolution resolveType() {
44-
TypeResolution resolution = super.resolveType();
45+
if (!percent.foldable()) {
46+
throw new SqlIllegalArgumentException("2nd argument of PERCENTILE must be constant, received [{}]",
47+
Expressions.name(percent));
48+
}
4549

46-
if (TypeResolution.TYPE_RESOLVED.equals(resolution)) {
47-
resolution = Expressions.typeMustBeNumeric(percent(), functionName(), ParamOrdinal.DEFAULT);
50+
TypeResolution resolution = super.resolveType();
51+
if (resolution.unresolved()) {
52+
return resolution;
4853
}
4954

50-
return resolution;
55+
return Expressions.typeMustBeNumeric(percent, functionName(), ParamOrdinal.DEFAULT);
5156
}
5257

5358
public Expression percent() {

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/PercentileRank.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
package org.elasticsearch.xpack.sql.expression.function.aggregate;
77

8+
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
89
import org.elasticsearch.xpack.sql.expression.Expression;
910
import org.elasticsearch.xpack.sql.expression.Expressions;
1011
import org.elasticsearch.xpack.sql.expression.Expressions.ParamOrdinal;
@@ -41,6 +42,11 @@ public Expression replaceChildren(List<Expression> newChildren) {
4142

4243
@Override
4344
protected TypeResolution resolveType() {
45+
if (!value.foldable()) {
46+
throw new SqlIllegalArgumentException("2nd argument of PERCENTILE_RANK must be constant, received [{}]",
47+
Expressions.name(value));
48+
}
49+
4450
TypeResolution resolution = super.resolveType();
4551
if (resolution.unresolved()) {
4652
return resolution;

x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.elasticsearch.xpack.sql.analysis.analyzer;
77

88
import org.elasticsearch.test.ESTestCase;
9+
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
910
import org.elasticsearch.xpack.sql.TestUtils;
1011
import org.elasticsearch.xpack.sql.analysis.AnalysisException;
1112
import org.elasticsearch.xpack.sql.analysis.index.EsIndex;
@@ -26,12 +27,13 @@
2627
import java.util.Map;
2728

2829
public class VerifierErrorMessagesTests extends ESTestCase {
30+
2931
private SqlParser parser = new SqlParser();
32+
private IndexResolution indexResolution = IndexResolution.valid(new EsIndex("test",
33+
TypesTests.loadMapping("mapping-multi-field-with-nested.json")));
3034

3135
private String error(String sql) {
32-
Map<String, EsField> mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json");
33-
EsIndex test = new EsIndex("test", mapping);
34-
return error(IndexResolution.valid(test), sql);
36+
return error(indexResolution, sql);
3537
}
3638

3739
private String error(IndexResolution getIndexResult, String sql) {
@@ -504,4 +506,20 @@ public void testAggsInHistogram() {
504506
assertEquals("1:47: Cannot use an aggregate [MAX] for grouping",
505507
error("SELECT MAX(date) FROM test GROUP BY HISTOGRAM(MAX(int), 1)"));
506508
}
507-
}
509+
510+
public void testErrorMessageForPercentileWithSecondArgBasedOnAField() {
511+
Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new FunctionRegistry(), indexResolution, new Verifier(new Metrics()));
512+
SqlIllegalArgumentException e = expectThrows(SqlIllegalArgumentException.class, () -> analyzer.analyze(parser.createStatement(
513+
"SELECT PERCENTILE(int, ABS(int)) FROM test"), true));
514+
assertEquals("2nd argument of PERCENTILE must be constant, received [ABS(int)]",
515+
e.getMessage());
516+
}
517+
518+
public void testErrorMessageForPercentileRankWithSecondArgBasedOnAField() {
519+
Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new FunctionRegistry(), indexResolution, new Verifier(new Metrics()));
520+
SqlIllegalArgumentException e = expectThrows(SqlIllegalArgumentException.class, () -> analyzer.analyze(parser.createStatement(
521+
"SELECT PERCENTILE_RANK(int, ABS(int)) FROM test"), true));
522+
assertEquals("2nd argument of PERCENTILE_RANK must be constant, received [ABS(int)]",
523+
e.getMessage());
524+
}
525+
}

0 commit comments

Comments
 (0)