Skip to content

Commit 8a24206

Browse files
Fix for sample function
1 parent 0f080a5 commit 8a24206

File tree

2 files changed

+46
-9
lines changed
  • x-pack/plugin
    • esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate
    • src/yamlRestTest/resources/rest-api-spec/test/esql

2 files changed

+46
-9
lines changed

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,32 @@
1717
import org.elasticsearch.compute.aggregation.SampleIntAggregatorFunctionSupplier;
1818
import org.elasticsearch.compute.aggregation.SampleLongAggregatorFunctionSupplier;
1919
import org.elasticsearch.xpack.esql.EsqlIllegalArgumentException;
20+
import org.elasticsearch.xpack.esql.capabilities.PostOptimizationVerificationAware;
21+
import org.elasticsearch.xpack.esql.common.Failures;
2022
import org.elasticsearch.xpack.esql.core.expression.Expression;
21-
import org.elasticsearch.xpack.esql.core.expression.FoldContext;
2223
import org.elasticsearch.xpack.esql.core.expression.Literal;
2324
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
2425
import org.elasticsearch.xpack.esql.core.tree.Source;
2526
import org.elasticsearch.xpack.esql.core.type.DataType;
2627
import org.elasticsearch.xpack.esql.expression.function.Example;
2728
import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
2829
import org.elasticsearch.xpack.esql.expression.function.FunctionType;
30+
import org.elasticsearch.xpack.esql.expression.function.FunctionUtils;
2931
import org.elasticsearch.xpack.esql.expression.function.Param;
3032
import org.elasticsearch.xpack.esql.planner.PlannerUtils;
3133
import org.elasticsearch.xpack.esql.planner.ToAggregator;
3234

3335
import java.io.IOException;
3436
import java.util.List;
3537

36-
import static org.elasticsearch.common.logging.LoggerMessageFormat.format;
3738
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST;
3839
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND;
39-
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNotNullAndFoldable;
40+
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNotNull;
4041
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType;
42+
import static org.elasticsearch.xpack.esql.expression.function.FunctionUtils.postOptimizationVerificationLimit;
43+
import static org.elasticsearch.xpack.esql.expression.function.FunctionUtils.resolveTypeLimit;
4144

42-
public class Sample extends AggregateFunction implements ToAggregator {
45+
public class Sample extends AggregateFunction implements ToAggregator, PostOptimizationVerificationAware {
4346
public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Sample", Sample::new);
4447

4548
@FunctionInfo(
@@ -110,14 +113,14 @@ protected TypeResolution resolveType() {
110113
return new TypeResolution("Unresolved children");
111114
}
112115
var typeResolution = isType(field(), dt -> dt != DataType.UNSIGNED_LONG, sourceText(), FIRST, "any type except unsigned_long").and(
113-
isNotNullAndFoldable(limitField(), sourceText(), SECOND)
116+
isNotNull(limitField(), sourceText(), SECOND)
114117
).and(isType(limitField(), dt -> dt == DataType.INTEGER, sourceText(), SECOND, "integer"));
115118
if (typeResolution.unresolved()) {
116119
return typeResolution;
117120
}
118-
int limit = limitValue();
119-
if (limit <= 0) {
120-
return new TypeResolution(format(null, "Limit must be greater than 0 in [{}], found [{}]", sourceText(), limit));
121+
TypeResolution result = resolveTypeLimit(limitField(), sourceText());
122+
if (result.equals(TypeResolution.TYPE_RESOLVED) == false) {
123+
return result;
121124
}
122125
return TypeResolution.TYPE_RESOLVED;
123126
}
@@ -164,11 +167,15 @@ Expression limitField() {
164167
}
165168

166169
private int limitValue() {
167-
return (int) limitField().fold(FoldContext.small() /* TODO remove me */);
170+
return FunctionUtils.limitValue(limitField(), sourceText());
168171
}
169172

170173
Expression uuid() {
171174
return parameters().get(1);
172175
}
173176

177+
@Override
178+
public void postOptimizationVerification(Failures failures) {
179+
postOptimizationVerificationLimit(failures, limitField(), sourceText());
180+
}
174181
}

x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/230_folding.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,33 @@ Top function with invalid sort order:
9595
| LIMIT 5
9696
- match: { error.type: "verification_exception" }
9797
- match: { error.reason: "Found 1 problem\nline 3:30: Invalid order value in [TOP(hire_date, 2, REVERSE(\"csed123\"))], expected [ASC, DESC] but got [321desc]" }
98+
99+
---
100+
101+
Sample function with constant folding:
102+
- do:
103+
esql.query:
104+
body:
105+
query: |
106+
FROM employees
107+
| STATS
108+
sample_salary = SAMPLE(salary, 1+2)
109+
| LIMIT 5
110+
- match: { columns.0.name: "sample_salary" }
111+
- length: { values: 1 }
112+
- length: { values.0: 1 }
113+
114+
---
115+
116+
Sample function with negative limit value after folding:
117+
- do:
118+
catch: bad_request
119+
esql.query:
120+
body:
121+
query: |
122+
FROM employees
123+
| STATS
124+
sample_salary = SAMPLE(salary, 2-5)
125+
| LIMIT 5
126+
- match: { error.type: "verification_exception" }
127+
- match: { error.reason: "Found 1 problem\nline 3:36: Limit must be greater than 0 in [SAMPLE(salary, 2-5)], found [-3]" }

0 commit comments

Comments
 (0)