mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-28 01:22:26 -04:00
ESQL: ROUND_TO function (#128278)
Creates a `ROUND_TO` function that rounds it's input to one of the provided values. Like so: ``` ROUND_TO(v, 0, 5000, 10000, 20000, 40000, 100000) v | ROUND_TO 0 | 0 100 | 0 6000 | 5000 45001 | 40000 999999 | 100000 ``` For some sequences of numbers you could do this with the `/` operator - but for arbitrary sequences of numbers you needed `CASE` which is quite slow. And hard to read! Rewriting the example above would look like: ``` CASE ( v < 5000, 0, v < 10000, 5000, v < 20000, 10000, v < 40000, 20000, v < 100000, 40000, 100000 ) ``` Even better, this is *fast*: ``` (operation) Mode Cnt Score Error Units round_to_4_via_case avgt 7 138.124 ± 0.738 ns/op round_to_4 avgt 7 0.805 ± 0.011 ns/op round_to_3 avgt 7 0.739 ± 0.011 ns/op round_to_2 avgt 7 0.651 ± 0.009 ns/op date_trunc avgt 7 2.425 ± 0.018 ns/op ``` I've included a comparison to `DATE_TRUNC` above because we should be able to rewrite `DATE_TRUNC` into `ROUND_TO` when we know the date range of the index. This doesn't do it now, but it should be possible.
This commit is contained in:
parent
0c3d47de10
commit
45bfaab448
42 changed files with 4082 additions and 4 deletions
|
@ -13,6 +13,7 @@ import org.apache.lucene.util.BytesRef;
|
|||
import org.elasticsearch.common.breaker.NoopCircuitBreaker;
|
||||
import org.elasticsearch.common.logging.LogConfigurator;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||
import org.elasticsearch.common.util.BigArrays;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.BlockFactory;
|
||||
|
@ -44,6 +45,7 @@ import org.elasticsearch.xpack.esql.evaluator.EvalMapper;
|
|||
import org.elasticsearch.xpack.esql.expression.function.scalar.conditional.Case;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.date.DateTrunc;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Abs;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.RoundTo;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvMin;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.nulls.Coalesce;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.string.RLike;
|
||||
|
@ -51,6 +53,7 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.string.ToLower;
|
|||
import org.elasticsearch.xpack.esql.expression.function.scalar.string.ToUpper;
|
||||
import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Add;
|
||||
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.Equals;
|
||||
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.LessThan;
|
||||
import org.elasticsearch.xpack.esql.planner.Layout;
|
||||
import org.elasticsearch.xpack.esql.plugin.EsqlPlugin;
|
||||
import org.elasticsearch.xpack.esql.session.Configuration;
|
||||
|
@ -128,6 +131,10 @@ public class EvalBenchmark {
|
|||
"long_equal_to_int",
|
||||
"mv_min",
|
||||
"mv_min_ascending",
|
||||
"round_to_4_via_case",
|
||||
"round_to_2",
|
||||
"round_to_3",
|
||||
"round_to_4",
|
||||
"rlike",
|
||||
"to_lower",
|
||||
"to_lower_ords",
|
||||
|
@ -240,6 +247,65 @@ public class EvalBenchmark {
|
|||
RLike rlike = new RLike(Source.EMPTY, keywordField, new RLikePattern(".ar"));
|
||||
yield EvalMapper.toEvaluator(FOLD_CONTEXT, rlike, layout(keywordField)).get(driverContext);
|
||||
}
|
||||
case "round_to_4_via_case" -> {
|
||||
FieldAttribute f = longField();
|
||||
|
||||
Expression ltkb = new LessThan(Source.EMPTY, f, kb());
|
||||
Expression ltmb = new LessThan(Source.EMPTY, f, mb());
|
||||
Expression ltgb = new LessThan(Source.EMPTY, f, gb());
|
||||
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
|
||||
FOLD_CONTEXT,
|
||||
new Case(Source.EMPTY, ltkb, List.of(b(), ltmb, kb(), ltgb, mb(), gb())),
|
||||
layout(f)
|
||||
).get(driverContext);
|
||||
String desc = "CaseLazyEvaluator";
|
||||
if (evaluator.toString().contains(desc) == false) {
|
||||
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
|
||||
}
|
||||
yield evaluator;
|
||||
}
|
||||
case "round_to_2" -> {
|
||||
FieldAttribute f = longField();
|
||||
|
||||
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
|
||||
FOLD_CONTEXT,
|
||||
new RoundTo(Source.EMPTY, f, List.of(b(), kb())),
|
||||
layout(f)
|
||||
).get(driverContext);
|
||||
String desc = "RoundToLong2";
|
||||
if (evaluator.toString().contains(desc) == false) {
|
||||
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
|
||||
}
|
||||
yield evaluator;
|
||||
}
|
||||
case "round_to_3" -> {
|
||||
FieldAttribute f = longField();
|
||||
|
||||
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
|
||||
FOLD_CONTEXT,
|
||||
new RoundTo(Source.EMPTY, f, List.of(b(), kb(), mb())),
|
||||
layout(f)
|
||||
).get(driverContext);
|
||||
String desc = "RoundToLong3";
|
||||
if (evaluator.toString().contains(desc) == false) {
|
||||
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
|
||||
}
|
||||
yield evaluator;
|
||||
}
|
||||
case "round_to_4" -> {
|
||||
FieldAttribute f = longField();
|
||||
|
||||
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
|
||||
FOLD_CONTEXT,
|
||||
new RoundTo(Source.EMPTY, f, List.of(b(), kb(), mb(), gb())),
|
||||
layout(f)
|
||||
).get(driverContext);
|
||||
String desc = "RoundToLong4";
|
||||
if (evaluator.toString().contains(desc) == false) {
|
||||
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
|
||||
}
|
||||
yield evaluator;
|
||||
}
|
||||
case "to_lower", "to_lower_ords" -> {
|
||||
FieldAttribute keywordField = keywordField();
|
||||
ToLower toLower = new ToLower(Source.EMPTY, keywordField, configuration());
|
||||
|
@ -419,6 +485,69 @@ public class EvalBenchmark {
|
|||
}
|
||||
}
|
||||
}
|
||||
case "round_to_4_via_case", "round_to_4" -> {
|
||||
long b = 1;
|
||||
long kb = ByteSizeUnit.KB.toBytes(1);
|
||||
long mb = ByteSizeUnit.MB.toBytes(1);
|
||||
long gb = ByteSizeUnit.GB.toBytes(1);
|
||||
|
||||
LongVector f = actual.<LongBlock>getBlock(0).asVector();
|
||||
LongVector result = actual.<LongBlock>getBlock(1).asVector();
|
||||
for (int i = 0; i < BLOCK_LENGTH; i++) {
|
||||
long expected = f.getLong(i);
|
||||
if (expected < kb) {
|
||||
expected = b;
|
||||
} else if (expected < mb) {
|
||||
expected = kb;
|
||||
} else if (expected < gb) {
|
||||
expected = mb;
|
||||
} else {
|
||||
expected = gb;
|
||||
}
|
||||
if (result.getLong(i) != expected) {
|
||||
throw new AssertionError("[" + operation + "] expected [" + expected + "] but was [" + result.getLong(i) + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
case "round_to_3" -> {
|
||||
long b = 1;
|
||||
long kb = ByteSizeUnit.KB.toBytes(1);
|
||||
long mb = ByteSizeUnit.MB.toBytes(1);
|
||||
|
||||
LongVector f = actual.<LongBlock>getBlock(0).asVector();
|
||||
LongVector result = actual.<LongBlock>getBlock(1).asVector();
|
||||
for (int i = 0; i < BLOCK_LENGTH; i++) {
|
||||
long expected = f.getLong(i);
|
||||
if (expected < kb) {
|
||||
expected = b;
|
||||
} else if (expected < mb) {
|
||||
expected = kb;
|
||||
} else {
|
||||
expected = mb;
|
||||
}
|
||||
if (result.getLong(i) != expected) {
|
||||
throw new AssertionError("[" + operation + "] expected [" + expected + "] but was [" + result.getLong(i) + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
case "round_to_2" -> {
|
||||
long b = 1;
|
||||
long kb = ByteSizeUnit.KB.toBytes(1);
|
||||
|
||||
LongVector f = actual.<LongBlock>getBlock(0).asVector();
|
||||
LongVector result = actual.<LongBlock>getBlock(1).asVector();
|
||||
for (int i = 0; i < BLOCK_LENGTH; i++) {
|
||||
long expected = f.getLong(i);
|
||||
if (expected < kb) {
|
||||
expected = b;
|
||||
} else {
|
||||
expected = kb;
|
||||
}
|
||||
if (result.getLong(i) != expected) {
|
||||
throw new AssertionError("[" + operation + "] expected [" + expected + "] but was [" + result.getLong(i) + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
case "to_lower" -> checkBytes(operation, actual, false, new BytesRef[] { new BytesRef("foo"), new BytesRef("bar") });
|
||||
case "to_lower_ords" -> checkBytes(operation, actual, true, new BytesRef[] { new BytesRef("foo"), new BytesRef("bar") });
|
||||
case "to_upper" -> checkBytes(operation, actual, false, new BytesRef[] { new BytesRef("FOO"), new BytesRef("BAR") });
|
||||
|
@ -450,7 +579,7 @@ public class EvalBenchmark {
|
|||
|
||||
private static Page page(String operation) {
|
||||
return switch (operation) {
|
||||
case "abs", "add", "date_trunc", "equal_to_const" -> {
|
||||
case "abs", "add", "date_trunc", "equal_to_const", "round_to_4_via_case", "round_to_2", "round_to_3", "round_to_4" -> {
|
||||
var builder = blockFactory.newLongBlockBuilder(BLOCK_LENGTH);
|
||||
for (int i = 0; i < BLOCK_LENGTH; i++) {
|
||||
builder.appendLong(i * 100_000);
|
||||
|
@ -540,6 +669,26 @@ public class EvalBenchmark {
|
|||
};
|
||||
}
|
||||
|
||||
private static Literal b() {
|
||||
return lit(1L);
|
||||
}
|
||||
|
||||
private static Literal kb() {
|
||||
return lit(ByteSizeUnit.KB.toBytes(1));
|
||||
}
|
||||
|
||||
private static Literal mb() {
|
||||
return lit(ByteSizeUnit.MB.toBytes(1));
|
||||
}
|
||||
|
||||
private static Literal gb() {
|
||||
return lit(ByteSizeUnit.GB.toBytes(1));
|
||||
}
|
||||
|
||||
private static Literal lit(long v) {
|
||||
return new Literal(Source.EMPTY, v, DataType.LONG);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@OperationsPerInvocation(1024 * BLOCK_LENGTH)
|
||||
public void run() {
|
||||
|
|
5
docs/changelog/128278.yaml
Normal file
5
docs/changelog/128278.yaml
Normal file
|
@ -0,0 +1,5 @@
|
|||
pr: 128278
|
||||
summary: ROUND_TO function
|
||||
area: ES|QL
|
||||
type: enhancement
|
||||
issues: []
|
6
docs/reference/query-languages/esql/_snippets/functions/description/round_to.md
generated
Normal file
6
docs/reference/query-languages/esql/_snippets/functions/description/round_to.md
generated
Normal file
|
@ -0,0 +1,6 @@
|
|||
% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
|
||||
|
||||
**Description**
|
||||
|
||||
Rounds down to one of a list of fixed points.
|
||||
|
29
docs/reference/query-languages/esql/_snippets/functions/examples/round_to.md
generated
Normal file
29
docs/reference/query-languages/esql/_snippets/functions/examples/round_to.md
generated
Normal file
|
@ -0,0 +1,29 @@
|
|||
% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
|
||||
|
||||
**Example**
|
||||
|
||||
```esql
|
||||
required_capability: round_to
|
||||
FROM employees
|
||||
| STATS COUNT(*) BY birth_window=ROUND_TO(
|
||||
birth_date,
|
||||
"1900-01-01T00:00:00Z"::DATETIME,
|
||||
"1950-01-01T00:00:00Z"::DATETIME,
|
||||
"1955-01-01T00:00:00Z"::DATETIME,
|
||||
"1960-01-01T00:00:00Z"::DATETIME,
|
||||
"1965-01-01T00:00:00Z"::DATETIME,
|
||||
"1970-01-01T00:00:00Z"::DATETIME,
|
||||
"1975-01-01T00:00:00Z"::DATETIME
|
||||
)
|
||||
| SORT birth_window ASC
|
||||
```
|
||||
|
||||
| COUNT(*):long | birth_window:datetime |
|
||||
| --- | --- |
|
||||
| 27 | 1950-01-01T00:00:00Z |
|
||||
| 29 | 1955-01-01T00:00:00Z |
|
||||
| 33 | 1960-01-01T00:00:00Z |
|
||||
| 1 | 1965-01-01T00:00:00Z |
|
||||
| 10 | null |
|
||||
|
||||
|
23
docs/reference/query-languages/esql/_snippets/functions/layout/round_to.md
generated
Normal file
23
docs/reference/query-languages/esql/_snippets/functions/layout/round_to.md
generated
Normal file
|
@ -0,0 +1,23 @@
|
|||
% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
|
||||
|
||||
## `ROUND_TO` [esql-round_to]
|
||||
|
||||
**Syntax**
|
||||
|
||||
:::{image} ../../../images/functions/round_to.svg
|
||||
:alt: Embedded
|
||||
:class: text-center
|
||||
:::
|
||||
|
||||
|
||||
:::{include} ../parameters/round_to.md
|
||||
:::
|
||||
|
||||
:::{include} ../description/round_to.md
|
||||
:::
|
||||
|
||||
:::{include} ../types/round_to.md
|
||||
:::
|
||||
|
||||
:::{include} ../examples/round_to.md
|
||||
:::
|
10
docs/reference/query-languages/esql/_snippets/functions/parameters/round_to.md
generated
Normal file
10
docs/reference/query-languages/esql/_snippets/functions/parameters/round_to.md
generated
Normal file
|
@ -0,0 +1,10 @@
|
|||
% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
|
||||
|
||||
**Parameters**
|
||||
|
||||
`field`
|
||||
: The numeric value to round. If `null`, the function returns `null`.
|
||||
|
||||
`points`
|
||||
: Remaining rounding points. Must be constants.
|
||||
|
18
docs/reference/query-languages/esql/_snippets/functions/types/round_to.md
generated
Normal file
18
docs/reference/query-languages/esql/_snippets/functions/types/round_to.md
generated
Normal file
|
@ -0,0 +1,18 @@
|
|||
% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
|
||||
|
||||
**Supported types**
|
||||
|
||||
| field | points | result |
|
||||
| --- | --- | --- |
|
||||
| date | date | date |
|
||||
| date_nanos | date_nanos | date_nanos |
|
||||
| double | double | double |
|
||||
| double | integer | double |
|
||||
| double | long | double |
|
||||
| integer | double | double |
|
||||
| integer | integer | integer |
|
||||
| integer | long | long |
|
||||
| long | double | double |
|
||||
| long | integer | long |
|
||||
| long | long | long |
|
||||
|
1
docs/reference/query-languages/esql/images/functions/round_to.svg
generated
Normal file
1
docs/reference/query-languages/esql/images/functions/round_to.svg
generated
Normal file
|
@ -0,0 +1 @@
|
|||
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="484" height="61" viewbox="0 0 484 61"><defs><style type="text/css">.c{fill:none;stroke:#222222;}.k{fill:#000000;font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-size:20px;}.s{fill:#e4f4ff;stroke:#222222;}.syn{fill:#8D8D8D;font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-size:20px;}</style></defs><path class="c" d="M0 46h5m116 0h10m32 0h10m80 0h30m-5 0q-5 0-5-5v-26q0-5 5-5h144q5 0 5 5v26q0 5-5 5m-107 0h10m92 0h30m32 0h5"/><rect class="s" x="5" y="20" width="116" height="36"/><text class="k" x="15" y="46">ROUND_TO</text><rect class="s" x="131" y="20" width="32" height="36" rx="7"/><text class="syn" x="141" y="46">(</text><rect class="s" x="173" y="20" width="80" height="36" rx="7"/><text class="k" x="183" y="46">field</text><rect class="s" x="283" y="20" width="32" height="36" rx="7"/><text class="syn" x="293" y="46">,</text><rect class="s" x="325" y="20" width="92" height="36" rx="7"/><text class="k" x="335" y="46">points</text><rect class="s" x="447" y="20" width="32" height="36" rx="7"/><text class="syn" x="457" y="46">)</text></svg>
|
After Width: | Height: | Size: 1.3 KiB |
211
docs/reference/query-languages/esql/kibana/definition/functions/round_to.json
generated
Normal file
211
docs/reference/query-languages/esql/kibana/definition/functions/round_to.json
generated
Normal file
|
@ -0,0 +1,211 @@
|
|||
{
|
||||
"comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.",
|
||||
"type" : "scalar",
|
||||
"name" : "round_to",
|
||||
"description" : "Rounds down to one of a list of fixed points.",
|
||||
"signatures" : [
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "date",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "date",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "date"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "date_nanos",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "date_nanos",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "date_nanos"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "double",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "double",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "double"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "double",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "integer",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "double"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "double",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "long",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "double"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "integer",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "double",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "double"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "integer",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "integer",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "integer"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "integer",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "long",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "long"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "long",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "double",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "double"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "long",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "integer",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "long"
|
||||
},
|
||||
{
|
||||
"params" : [
|
||||
{
|
||||
"name" : "field",
|
||||
"type" : "long",
|
||||
"optional" : false,
|
||||
"description" : "The numeric value to round. If `null`, the function returns `null`."
|
||||
},
|
||||
{
|
||||
"name" : "points",
|
||||
"type" : "long",
|
||||
"optional" : false,
|
||||
"description" : "Remaining rounding points. Must be constants."
|
||||
}
|
||||
],
|
||||
"variadic" : true,
|
||||
"returnType" : "long"
|
||||
}
|
||||
],
|
||||
"examples" : [
|
||||
"required_capability: round_to\nFROM employees\n| STATS COUNT(*) BY birth_window=ROUND_TO(\n birth_date,\n \"1900-01-01T00:00:00Z\"::DATETIME,\n \"1950-01-01T00:00:00Z\"::DATETIME,\n \"1955-01-01T00:00:00Z\"::DATETIME,\n \"1960-01-01T00:00:00Z\"::DATETIME,\n \"1965-01-01T00:00:00Z\"::DATETIME,\n \"1970-01-01T00:00:00Z\"::DATETIME,\n \"1975-01-01T00:00:00Z\"::DATETIME\n)\n| SORT birth_window ASC"
|
||||
],
|
||||
"preview" : false,
|
||||
"snapshot_only" : false
|
||||
}
|
20
docs/reference/query-languages/esql/kibana/docs/functions/round_to.md
generated
Normal file
20
docs/reference/query-languages/esql/kibana/docs/functions/round_to.md
generated
Normal file
|
@ -0,0 +1,20 @@
|
|||
% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
|
||||
|
||||
### ROUND TO
|
||||
Rounds down to one of a list of fixed points.
|
||||
|
||||
```esql
|
||||
required_capability: round_to
|
||||
FROM employees
|
||||
| STATS COUNT(*) BY birth_window=ROUND_TO(
|
||||
birth_date,
|
||||
"1900-01-01T00:00:00Z"::DATETIME,
|
||||
"1950-01-01T00:00:00Z"::DATETIME,
|
||||
"1955-01-01T00:00:00Z"::DATETIME,
|
||||
"1960-01-01T00:00:00Z"::DATETIME,
|
||||
"1965-01-01T00:00:00Z"::DATETIME,
|
||||
"1970-01-01T00:00:00Z"::DATETIME,
|
||||
"1975-01-01T00:00:00Z"::DATETIME
|
||||
)
|
||||
| SORT birth_window ASC
|
||||
```
|
|
@ -449,4 +449,21 @@ tasks.named('stringTemplates').configure {
|
|||
it.inputFile = coalesceInputFile
|
||||
it.outputFile = "org/elasticsearch/xpack/esql/expression/function/scalar/nulls/CoalesceBytesRefEvaluator.java"
|
||||
}
|
||||
|
||||
File roundToInput = file("src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/X-RoundTo.java.st")
|
||||
template {
|
||||
it.properties = intProperties
|
||||
it.inputFile = roundToInput
|
||||
it.outputFile = "org/elasticsearch/xpack/esql/expression/function/scalar/math/RoundToInt.java"
|
||||
}
|
||||
template {
|
||||
it.properties = longProperties
|
||||
it.inputFile = roundToInput
|
||||
it.outputFile = "org/elasticsearch/xpack/esql/expression/function/scalar/math/RoundToLong.java"
|
||||
}
|
||||
template {
|
||||
it.properties = doubleProperties
|
||||
it.inputFile = roundToInput
|
||||
it.outputFile = "org/elasticsearch/xpack/esql/expression/function/scalar/math/RoundToDouble.java"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -793,6 +793,146 @@ ul:ul
|
|||
null
|
||||
;
|
||||
|
||||
roundToInt
|
||||
required_capability: round_to
|
||||
ROW v = 1
|
||||
| EVAL r1 = ROUND_TO(v, 0, 1, 2)
|
||||
, r2 = ROUND_TO(v, 2, 3)
|
||||
, r3 = ROUND_TO(v, 0, 10, 20, 30, 40, 50, 60, 70, 90)
|
||||
, rl = ROUND_TO(v, 0::LONG, 100)
|
||||
, rd = ROUND_TO(v, 0, 1.1, 2.2);
|
||||
|
||||
v:integer | r1:integer | r2:integer | r3:integer | rl:long | rd:double
|
||||
1 | 1 | 2 | 0 | 0 | 0.0
|
||||
;
|
||||
|
||||
roundToLong
|
||||
required_capability: round_to
|
||||
ROW v = 1000000000000::LONG
|
||||
| EVAL r1 = ROUND_TO(v, 0, 1000000000000, 2000000000000)
|
||||
, r2 = ROUND_TO(v, 2000000000000, 3000000000000)
|
||||
, r3 = ROUND_TO(v, 0, 1000000000000, 2000000000000, 3000000000000, 4000000000000, 5000000000000, 6000000000000)
|
||||
, rd = ROUND_TO(v, 0, 1.1, 2.2);
|
||||
|
||||
v:long | r1:long | r2:long | r3:long | rd:double
|
||||
1000000000000 | 1000000000000 | 2000000000000 | 1000000000000 | 2.2
|
||||
;
|
||||
|
||||
roundToDouble
|
||||
required_capability: round_to
|
||||
ROW v = 1.1
|
||||
| EVAL r1 = ROUND_TO(v, 0, 1, 2)
|
||||
, r2 = ROUND_TO(v, 2, 3)
|
||||
, r3 = ROUND_TO(v, 0, 10, 20, 30, 40, 50, 60, 70, 90)
|
||||
, rl = ROUND_TO(v, 0::LONG, 100)
|
||||
, rd = ROUND_TO(v, 0, 1.1, 2.2);
|
||||
|
||||
v:double | r1:double | r2:double | r3:double | rl:double | rd:double
|
||||
1.1 | 1.0 | 2.0 | 0.0 | 0.0 | 1.1
|
||||
;
|
||||
|
||||
roundToDate
|
||||
required_capability: round_to
|
||||
ROW v = "2025-02-02T01:00:00Z"::DATE
|
||||
| EVAL r1 = ROUND_TO(v, "2025-01-01T00:00:00Z"::DATE, "2025-02-01T00:00:00Z"::DATE, "2025-03-01T00:00:00Z"::DATE)
|
||||
, r2 = ROUND_TO(v, "2025-04-01T00:00:00Z"::DATE, "2025-05-01T00:00:00Z"::DATE, "2025-06-01T00:00:00Z"::DATE)
|
||||
, r3 = ROUND_TO(v, "2025-01-01T00:00:00Z"::DATE, "2025-02-01T00:00:00Z"::DATE, "2025-03-01T00:00:00Z"::DATE, "2025-04-01T00:00:00Z"::DATE, "2025-05-01T00:00:00Z"::DATE, "2025-06-01T00:00:00Z"::DATE);
|
||||
|
||||
v:date | r1:date | r2:date | r3:date
|
||||
2025-02-02T01:00:00Z | 2025-02-01T00:00:00Z | 2025-04-01T00:00:00Z | 2025-02-01T00:00:00Z
|
||||
;
|
||||
|
||||
roundToDateNanos
|
||||
required_capability: round_to
|
||||
ROW v = "2025-02-02T01:00:00.543123456Z"::DATE_NANOS
|
||||
| EVAL r1 = ROUND_TO(v, "2025-01-01T00:00:00Z"::DATE_NANOS, "2025-02-01T00:00:00Z"::DATE_NANOS, "2025-03-01T00:00:00Z"::DATE_NANOS)
|
||||
, r2 = ROUND_TO(v, "2025-04-01T00:00:00Z"::DATE_NANOS, "2025-05-01T00:00:00Z"::DATE_NANOS, "2025-06-01T00:00:00Z"::DATE_NANOS)
|
||||
, r3 = ROUND_TO(v, "2025-01-01T00:00:00Z"::DATE_NANOS, "2025-02-01T00:00:00Z"::DATE_NANOS, "2025-03-01T00:00:00Z"::DATE_NANOS, "2025-04-01T00:00:00Z"::DATE_NANOS, "2025-05-01T00:00:00Z"::DATE_NANOS, "2025-06-01T00:00:00Z"::DATE_NANOS);
|
||||
|
||||
v:date_nanos | r1:date_nanos | r2:date_nanos | r3:date_nanos
|
||||
2025-02-02T01:00:00.543123456Z | 2025-02-01T00:00:00.000000000Z | 2025-04-01T00:00:00.000000000Z | 2025-02-01T00:00:00.000000000Z
|
||||
;
|
||||
|
||||
roundToBirthWindow
|
||||
// tag::round_to[]
|
||||
required_capability: round_to
|
||||
FROM employees
|
||||
| STATS COUNT(*) BY birth_window=ROUND_TO(
|
||||
birth_date,
|
||||
"1900-01-01T00:00:00Z"::DATETIME,
|
||||
"1950-01-01T00:00:00Z"::DATETIME,
|
||||
"1955-01-01T00:00:00Z"::DATETIME,
|
||||
"1960-01-01T00:00:00Z"::DATETIME,
|
||||
"1965-01-01T00:00:00Z"::DATETIME,
|
||||
"1970-01-01T00:00:00Z"::DATETIME,
|
||||
"1975-01-01T00:00:00Z"::DATETIME
|
||||
)
|
||||
| SORT birth_window ASC
|
||||
// end::round_to[]
|
||||
;
|
||||
|
||||
// tag::round_to-result[]
|
||||
COUNT(*):long | birth_window:datetime
|
||||
27 | 1950-01-01T00:00:00Z
|
||||
29 | 1955-01-01T00:00:00Z
|
||||
33 | 1960-01-01T00:00:00Z
|
||||
1 | 1965-01-01T00:00:00Z
|
||||
10 | null
|
||||
// end::round_to-result[]
|
||||
;
|
||||
|
||||
roundToSalaryWindow
|
||||
required_capability: round_to
|
||||
FROM employees
|
||||
| STATS COUNT(*) BY salary=ROUND_TO(
|
||||
salary,
|
||||
0,
|
||||
20000,
|
||||
25000,
|
||||
30000,
|
||||
40000,
|
||||
50000,
|
||||
70000,
|
||||
90000
|
||||
)
|
||||
| SORT salary ASC
|
||||
;
|
||||
|
||||
COUNT(*):long | salary:integer
|
||||
9 | 25000
|
||||
27 | 30000
|
||||
22 | 40000
|
||||
34 | 50000
|
||||
8 | 70000
|
||||
;
|
||||
|
||||
roundToNanos
|
||||
required_capability: round_to
|
||||
FROM sample_data_ts_nanos
|
||||
| STATS COUNT(*) BY @timestamp=ROUND_TO(
|
||||
@timestamp,
|
||||
"2023-10-23T13:33:34.937123456Z"::DATE_NANOS,
|
||||
"2023-10-23T13:52:55.015123456Z"::DATE_NANOS,
|
||||
"2023-10-23T13:55:01.543123456Z"::DATE_NANOS
|
||||
)
|
||||
| SORT @timestamp ASC
|
||||
;
|
||||
|
||||
COUNT(*):long | @timestamp:date_nanos
|
||||
4 | 2023-10-23T13:33:34.937123456Z
|
||||
2 | 2023-10-23T13:52:55.015123456Z
|
||||
1 | 2023-10-23T13:55:01.543123456Z
|
||||
;
|
||||
|
||||
roundToUnsorted
|
||||
required_capability: round_to
|
||||
ROW v = 1
|
||||
| EVAL r = ROUND_TO(v, 2, -1, 9, 0, 100);
|
||||
|
||||
v:integer | r:integer
|
||||
1 | 0
|
||||
;
|
||||
|
||||
mvAvg
|
||||
from employees | where emp_no > 10008 | eval salary_change = mv_avg(salary_change) | sort emp_no | keep emp_no, salary_change.int, salary_change | limit 7;
|
||||
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
// begin generated imports
|
||||
import org.elasticsearch.compute.ann.Evaluator;
|
||||
import org.elasticsearch.compute.ann.Fixed;
|
||||
|
||||
import java.util.Arrays;
|
||||
// end generated imports
|
||||
|
||||
/**
|
||||
* Implementations of {@link RoundTo} for specific types.
|
||||
* <p>
|
||||
* We have specializations for when there are very few rounding points because
|
||||
* those are very fast and quite common.
|
||||
* </p>
|
||||
* This class is generated. Edit {@code X-RoundTo.java.st} instead.
|
||||
*/
|
||||
class RoundToDouble {
|
||||
static final RoundTo.Build BUILD = (source, field, points) -> {
|
||||
double[] f = points.stream().mapToDouble(p -> ((Number) p).doubleValue()).toArray();
|
||||
Arrays.sort(f);
|
||||
return switch (f.length) {
|
||||
// TODO should be a consistent way to do the 0 version - is CASE(MV_COUNT(f) == 1, f[0])
|
||||
case 1 -> new RoundToDouble1Evaluator.Factory(source, field, f[0]);
|
||||
/*
|
||||
* These hand-unrolled implementations are even faster than the linear scan implementations.
|
||||
*/
|
||||
case 2 -> new RoundToDouble2Evaluator.Factory(source, field, f[0], f[1]);
|
||||
case 3 -> new RoundToDouble3Evaluator.Factory(source, field, f[0], f[1], f[2]);
|
||||
case 4 -> new RoundToDouble4Evaluator.Factory(source, field, f[0], f[1], f[2], f[3]);
|
||||
/*
|
||||
* Break point of 10 experimentally derived on Nik's laptop (13th Gen Intel(R) Core(TM) i7-1370P)
|
||||
* on 2025-05-22.
|
||||
*/
|
||||
case 5, 6, 7, 8, 9, 10 -> new RoundToDoubleLinearSearchEvaluator.Factory(source, field, f);
|
||||
default -> new RoundToDoubleBinarySearchEvaluator.Factory(source, field, f);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Search the points array for the match linearly. This is faster for smaller arrays even
|
||||
* when finding a position late in the array. Presumably because this is super-SIMD-able.
|
||||
*/
|
||||
@Evaluator(extraName = "LinearSearch")
|
||||
static double processLinear(double field, @Fixed(includeInToString = false) double[] points) {
|
||||
// points is always longer than 3 or we use one of the specialized methods below
|
||||
for (int i = 1; i < points.length; i++) {
|
||||
if (field < points[i]) {
|
||||
return points[i - 1];
|
||||
}
|
||||
}
|
||||
return points[points.length - 1];
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "BinarySearch")
|
||||
static double process(double field, @Fixed(includeInToString = false) double[] points) {
|
||||
int idx = Arrays.binarySearch(points, field);
|
||||
return points[idx >= 0 ? idx : Math.max(0, -idx - 2)];
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "1")
|
||||
static double process(double field, @Fixed double p0) {
|
||||
return p0;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "2")
|
||||
static double process(double field, @Fixed double p0, @Fixed double p1) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "3")
|
||||
static double process(double field, @Fixed double p0, @Fixed double p1, @Fixed double p2) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
if (field < p2) {
|
||||
return p1;
|
||||
}
|
||||
return p2;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "4")
|
||||
static double process(double field, @Fixed double p0, @Fixed double p1, @Fixed double p2, @Fixed double p3) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
if (field < p2) {
|
||||
return p1;
|
||||
}
|
||||
if (field < p3) {
|
||||
return p2;
|
||||
}
|
||||
return p3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
// begin generated imports
|
||||
import org.elasticsearch.compute.ann.Evaluator;
|
||||
import org.elasticsearch.compute.ann.Fixed;
|
||||
|
||||
import java.util.Arrays;
|
||||
// end generated imports
|
||||
|
||||
/**
|
||||
* Implementations of {@link RoundTo} for specific types.
|
||||
* <p>
|
||||
* We have specializations for when there are very few rounding points because
|
||||
* those are very fast and quite common.
|
||||
* </p>
|
||||
* This class is generated. Edit {@code X-RoundTo.java.st} instead.
|
||||
*/
|
||||
class RoundToInt {
|
||||
static final RoundTo.Build BUILD = (source, field, points) -> {
|
||||
int[] f = points.stream().mapToInt(p -> ((Number) p).intValue()).toArray();
|
||||
Arrays.sort(f);
|
||||
return switch (f.length) {
|
||||
// TODO should be a consistent way to do the 0 version - is CASE(MV_COUNT(f) == 1, f[0])
|
||||
case 1 -> new RoundToInt1Evaluator.Factory(source, field, f[0]);
|
||||
/*
|
||||
* These hand-unrolled implementations are even faster than the linear scan implementations.
|
||||
*/
|
||||
case 2 -> new RoundToInt2Evaluator.Factory(source, field, f[0], f[1]);
|
||||
case 3 -> new RoundToInt3Evaluator.Factory(source, field, f[0], f[1], f[2]);
|
||||
case 4 -> new RoundToInt4Evaluator.Factory(source, field, f[0], f[1], f[2], f[3]);
|
||||
/*
|
||||
* Break point of 10 experimentally derived on Nik's laptop (13th Gen Intel(R) Core(TM) i7-1370P)
|
||||
* on 2025-05-22.
|
||||
*/
|
||||
case 5, 6, 7, 8, 9, 10 -> new RoundToIntLinearSearchEvaluator.Factory(source, field, f);
|
||||
default -> new RoundToIntBinarySearchEvaluator.Factory(source, field, f);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Search the points array for the match linearly. This is faster for smaller arrays even
|
||||
* when finding a position late in the array. Presumably because this is super-SIMD-able.
|
||||
*/
|
||||
@Evaluator(extraName = "LinearSearch")
|
||||
static int processLinear(int field, @Fixed(includeInToString = false) int[] points) {
|
||||
// points is always longer than 3 or we use one of the specialized methods below
|
||||
for (int i = 1; i < points.length; i++) {
|
||||
if (field < points[i]) {
|
||||
return points[i - 1];
|
||||
}
|
||||
}
|
||||
return points[points.length - 1];
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "BinarySearch")
|
||||
static int process(int field, @Fixed(includeInToString = false) int[] points) {
|
||||
int idx = Arrays.binarySearch(points, field);
|
||||
return points[idx >= 0 ? idx : Math.max(0, -idx - 2)];
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "1")
|
||||
static int process(int field, @Fixed int p0) {
|
||||
return p0;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "2")
|
||||
static int process(int field, @Fixed int p0, @Fixed int p1) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "3")
|
||||
static int process(int field, @Fixed int p0, @Fixed int p1, @Fixed int p2) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
if (field < p2) {
|
||||
return p1;
|
||||
}
|
||||
return p2;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "4")
|
||||
static int process(int field, @Fixed int p0, @Fixed int p1, @Fixed int p2, @Fixed int p3) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
if (field < p2) {
|
||||
return p1;
|
||||
}
|
||||
if (field < p3) {
|
||||
return p2;
|
||||
}
|
||||
return p3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
// begin generated imports
|
||||
import org.elasticsearch.compute.ann.Evaluator;
|
||||
import org.elasticsearch.compute.ann.Fixed;
|
||||
|
||||
import java.util.Arrays;
|
||||
// end generated imports
|
||||
|
||||
/**
|
||||
* Implementations of {@link RoundTo} for specific types.
|
||||
* <p>
|
||||
* We have specializations for when there are very few rounding points because
|
||||
* those are very fast and quite common.
|
||||
* </p>
|
||||
* This class is generated. Edit {@code X-RoundTo.java.st} instead.
|
||||
*/
|
||||
class RoundToLong {
|
||||
static final RoundTo.Build BUILD = (source, field, points) -> {
|
||||
long[] f = points.stream().mapToLong(p -> ((Number) p).longValue()).toArray();
|
||||
Arrays.sort(f);
|
||||
return switch (f.length) {
|
||||
// TODO should be a consistent way to do the 0 version - is CASE(MV_COUNT(f) == 1, f[0])
|
||||
case 1 -> new RoundToLong1Evaluator.Factory(source, field, f[0]);
|
||||
/*
|
||||
* These hand-unrolled implementations are even faster than the linear scan implementations.
|
||||
*/
|
||||
case 2 -> new RoundToLong2Evaluator.Factory(source, field, f[0], f[1]);
|
||||
case 3 -> new RoundToLong3Evaluator.Factory(source, field, f[0], f[1], f[2]);
|
||||
case 4 -> new RoundToLong4Evaluator.Factory(source, field, f[0], f[1], f[2], f[3]);
|
||||
/*
|
||||
* Break point of 10 experimentally derived on Nik's laptop (13th Gen Intel(R) Core(TM) i7-1370P)
|
||||
* on 2025-05-22.
|
||||
*/
|
||||
case 5, 6, 7, 8, 9, 10 -> new RoundToLongLinearSearchEvaluator.Factory(source, field, f);
|
||||
default -> new RoundToLongBinarySearchEvaluator.Factory(source, field, f);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Search the points array for the match linearly. This is faster for smaller arrays even
|
||||
* when finding a position late in the array. Presumably because this is super-SIMD-able.
|
||||
*/
|
||||
@Evaluator(extraName = "LinearSearch")
|
||||
static long processLinear(long field, @Fixed(includeInToString = false) long[] points) {
|
||||
// points is always longer than 3 or we use one of the specialized methods below
|
||||
for (int i = 1; i < points.length; i++) {
|
||||
if (field < points[i]) {
|
||||
return points[i - 1];
|
||||
}
|
||||
}
|
||||
return points[points.length - 1];
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "BinarySearch")
|
||||
static long process(long field, @Fixed(includeInToString = false) long[] points) {
|
||||
int idx = Arrays.binarySearch(points, field);
|
||||
return points[idx >= 0 ? idx : Math.max(0, -idx - 2)];
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "1")
|
||||
static long process(long field, @Fixed long p0) {
|
||||
return p0;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "2")
|
||||
static long process(long field, @Fixed long p0, @Fixed long p1) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "3")
|
||||
static long process(long field, @Fixed long p0, @Fixed long p1, @Fixed long p2) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
if (field < p2) {
|
||||
return p1;
|
||||
}
|
||||
return p2;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "4")
|
||||
static long process(long field, @Fixed long p0, @Fixed long p1, @Fixed long p2, @Fixed long p3) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
if (field < p2) {
|
||||
return p1;
|
||||
}
|
||||
if (field < p3) {
|
||||
return p2;
|
||||
}
|
||||
return p3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.DoubleBlock;
|
||||
import org.elasticsearch.compute.data.DoubleVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToDouble}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToDouble1Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final double p0;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToDouble1Evaluator(Source source, EvalOperator.ExpressionEvaluator field, double p0,
|
||||
DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (DoubleBlock fieldBlock = (DoubleBlock) field.eval(page)) {
|
||||
DoubleVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleBlock eval(int positionCount, DoubleBlock fieldBlock) {
|
||||
try(DoubleBlock.Builder result = driverContext.blockFactory().newDoubleBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendDouble(RoundToDouble.process(fieldBlock.getDouble(fieldBlock.getFirstValueIndex(p)), this.p0));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleVector eval(int positionCount, DoubleVector fieldVector) {
|
||||
try(DoubleVector.FixedBuilder result = driverContext.blockFactory().newDoubleVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendDouble(p, RoundToDouble.process(fieldVector.getDouble(p), this.p0));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDouble1Evaluator[" + "field=" + field + ", p0=" + p0 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final double p0;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, double p0) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToDouble1Evaluator get(DriverContext context) {
|
||||
return new RoundToDouble1Evaluator(source, field.get(context), p0, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDouble1Evaluator[" + "field=" + field + ", p0=" + p0 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.DoubleBlock;
|
||||
import org.elasticsearch.compute.data.DoubleVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToDouble}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToDouble2Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final double p0;
|
||||
|
||||
private final double p1;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToDouble2Evaluator(Source source, EvalOperator.ExpressionEvaluator field, double p0,
|
||||
double p1, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (DoubleBlock fieldBlock = (DoubleBlock) field.eval(page)) {
|
||||
DoubleVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleBlock eval(int positionCount, DoubleBlock fieldBlock) {
|
||||
try(DoubleBlock.Builder result = driverContext.blockFactory().newDoubleBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendDouble(RoundToDouble.process(fieldBlock.getDouble(fieldBlock.getFirstValueIndex(p)), this.p0, this.p1));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleVector eval(int positionCount, DoubleVector fieldVector) {
|
||||
try(DoubleVector.FixedBuilder result = driverContext.blockFactory().newDoubleVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendDouble(p, RoundToDouble.process(fieldVector.getDouble(p), this.p0, this.p1));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDouble2Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final double p0;
|
||||
|
||||
private final double p1;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, double p0,
|
||||
double p1) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToDouble2Evaluator get(DriverContext context) {
|
||||
return new RoundToDouble2Evaluator(source, field.get(context), p0, p1, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDouble2Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.DoubleBlock;
|
||||
import org.elasticsearch.compute.data.DoubleVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToDouble}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToDouble3Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final double p0;
|
||||
|
||||
private final double p1;
|
||||
|
||||
private final double p2;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToDouble3Evaluator(Source source, EvalOperator.ExpressionEvaluator field, double p0,
|
||||
double p1, double p2, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (DoubleBlock fieldBlock = (DoubleBlock) field.eval(page)) {
|
||||
DoubleVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleBlock eval(int positionCount, DoubleBlock fieldBlock) {
|
||||
try(DoubleBlock.Builder result = driverContext.blockFactory().newDoubleBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendDouble(RoundToDouble.process(fieldBlock.getDouble(fieldBlock.getFirstValueIndex(p)), this.p0, this.p1, this.p2));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleVector eval(int positionCount, DoubleVector fieldVector) {
|
||||
try(DoubleVector.FixedBuilder result = driverContext.blockFactory().newDoubleVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendDouble(p, RoundToDouble.process(fieldVector.getDouble(p), this.p0, this.p1, this.p2));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDouble3Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final double p0;
|
||||
|
||||
private final double p1;
|
||||
|
||||
private final double p2;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, double p0,
|
||||
double p1, double p2) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToDouble3Evaluator get(DriverContext context) {
|
||||
return new RoundToDouble3Evaluator(source, field.get(context), p0, p1, p2, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDouble3Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.DoubleBlock;
|
||||
import org.elasticsearch.compute.data.DoubleVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToDouble}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToDouble4Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final double p0;
|
||||
|
||||
private final double p1;
|
||||
|
||||
private final double p2;
|
||||
|
||||
private final double p3;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToDouble4Evaluator(Source source, EvalOperator.ExpressionEvaluator field, double p0,
|
||||
double p1, double p2, double p3, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p3 = p3;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (DoubleBlock fieldBlock = (DoubleBlock) field.eval(page)) {
|
||||
DoubleVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleBlock eval(int positionCount, DoubleBlock fieldBlock) {
|
||||
try(DoubleBlock.Builder result = driverContext.blockFactory().newDoubleBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendDouble(RoundToDouble.process(fieldBlock.getDouble(fieldBlock.getFirstValueIndex(p)), this.p0, this.p1, this.p2, this.p3));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleVector eval(int positionCount, DoubleVector fieldVector) {
|
||||
try(DoubleVector.FixedBuilder result = driverContext.blockFactory().newDoubleVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendDouble(p, RoundToDouble.process(fieldVector.getDouble(p), this.p0, this.p1, this.p2, this.p3));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDouble4Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + ", p3=" + p3 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final double p0;
|
||||
|
||||
private final double p1;
|
||||
|
||||
private final double p2;
|
||||
|
||||
private final double p3;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, double p0,
|
||||
double p1, double p2, double p3) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p3 = p3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToDouble4Evaluator get(DriverContext context) {
|
||||
return new RoundToDouble4Evaluator(source, field.get(context), p0, p1, p2, p3, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDouble4Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + ", p3=" + p3 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.DoubleBlock;
|
||||
import org.elasticsearch.compute.data.DoubleVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToDouble}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToDoubleBinarySearchEvaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final double[] points;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToDoubleBinarySearchEvaluator(Source source, EvalOperator.ExpressionEvaluator field,
|
||||
double[] points, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (DoubleBlock fieldBlock = (DoubleBlock) field.eval(page)) {
|
||||
DoubleVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleBlock eval(int positionCount, DoubleBlock fieldBlock) {
|
||||
try(DoubleBlock.Builder result = driverContext.blockFactory().newDoubleBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendDouble(RoundToDouble.process(fieldBlock.getDouble(fieldBlock.getFirstValueIndex(p)), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleVector eval(int positionCount, DoubleVector fieldVector) {
|
||||
try(DoubleVector.FixedBuilder result = driverContext.blockFactory().newDoubleVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendDouble(p, RoundToDouble.process(fieldVector.getDouble(p), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDoubleBinarySearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final double[] points;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, double[] points) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToDoubleBinarySearchEvaluator get(DriverContext context) {
|
||||
return new RoundToDoubleBinarySearchEvaluator(source, field.get(context), points, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDoubleBinarySearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.DoubleBlock;
|
||||
import org.elasticsearch.compute.data.DoubleVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToDouble}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToDoubleLinearSearchEvaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final double[] points;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToDoubleLinearSearchEvaluator(Source source, EvalOperator.ExpressionEvaluator field,
|
||||
double[] points, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (DoubleBlock fieldBlock = (DoubleBlock) field.eval(page)) {
|
||||
DoubleVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleBlock eval(int positionCount, DoubleBlock fieldBlock) {
|
||||
try(DoubleBlock.Builder result = driverContext.blockFactory().newDoubleBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendDouble(RoundToDouble.processLinear(fieldBlock.getDouble(fieldBlock.getFirstValueIndex(p)), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleVector eval(int positionCount, DoubleVector fieldVector) {
|
||||
try(DoubleVector.FixedBuilder result = driverContext.blockFactory().newDoubleVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendDouble(p, RoundToDouble.processLinear(fieldVector.getDouble(p), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDoubleLinearSearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final double[] points;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, double[] points) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToDoubleLinearSearchEvaluator get(DriverContext context) {
|
||||
return new RoundToDoubleLinearSearchEvaluator(source, field.get(context), points, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToDoubleLinearSearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.IntBlock;
|
||||
import org.elasticsearch.compute.data.IntVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToInt}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToInt1Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final int p0;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToInt1Evaluator(Source source, EvalOperator.ExpressionEvaluator field, int p0,
|
||||
DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (IntBlock fieldBlock = (IntBlock) field.eval(page)) {
|
||||
IntVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public IntBlock eval(int positionCount, IntBlock fieldBlock) {
|
||||
try(IntBlock.Builder result = driverContext.blockFactory().newIntBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendInt(RoundToInt.process(fieldBlock.getInt(fieldBlock.getFirstValueIndex(p)), this.p0));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public IntVector eval(int positionCount, IntVector fieldVector) {
|
||||
try(IntVector.FixedBuilder result = driverContext.blockFactory().newIntVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendInt(p, RoundToInt.process(fieldVector.getInt(p), this.p0));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToInt1Evaluator[" + "field=" + field + ", p0=" + p0 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final int p0;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, int p0) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToInt1Evaluator get(DriverContext context) {
|
||||
return new RoundToInt1Evaluator(source, field.get(context), p0, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToInt1Evaluator[" + "field=" + field + ", p0=" + p0 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.IntBlock;
|
||||
import org.elasticsearch.compute.data.IntVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToInt}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToInt2Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final int p0;
|
||||
|
||||
private final int p1;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToInt2Evaluator(Source source, EvalOperator.ExpressionEvaluator field, int p0, int p1,
|
||||
DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (IntBlock fieldBlock = (IntBlock) field.eval(page)) {
|
||||
IntVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public IntBlock eval(int positionCount, IntBlock fieldBlock) {
|
||||
try(IntBlock.Builder result = driverContext.blockFactory().newIntBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendInt(RoundToInt.process(fieldBlock.getInt(fieldBlock.getFirstValueIndex(p)), this.p0, this.p1));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public IntVector eval(int positionCount, IntVector fieldVector) {
|
||||
try(IntVector.FixedBuilder result = driverContext.blockFactory().newIntVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendInt(p, RoundToInt.process(fieldVector.getInt(p), this.p0, this.p1));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToInt2Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final int p0;
|
||||
|
||||
private final int p1;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, int p0, int p1) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToInt2Evaluator get(DriverContext context) {
|
||||
return new RoundToInt2Evaluator(source, field.get(context), p0, p1, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToInt2Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.IntBlock;
|
||||
import org.elasticsearch.compute.data.IntVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToInt}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToInt3Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final int p0;
|
||||
|
||||
private final int p1;
|
||||
|
||||
private final int p2;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToInt3Evaluator(Source source, EvalOperator.ExpressionEvaluator field, int p0, int p1,
|
||||
int p2, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (IntBlock fieldBlock = (IntBlock) field.eval(page)) {
|
||||
IntVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public IntBlock eval(int positionCount, IntBlock fieldBlock) {
|
||||
try(IntBlock.Builder result = driverContext.blockFactory().newIntBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendInt(RoundToInt.process(fieldBlock.getInt(fieldBlock.getFirstValueIndex(p)), this.p0, this.p1, this.p2));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public IntVector eval(int positionCount, IntVector fieldVector) {
|
||||
try(IntVector.FixedBuilder result = driverContext.blockFactory().newIntVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendInt(p, RoundToInt.process(fieldVector.getInt(p), this.p0, this.p1, this.p2));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToInt3Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final int p0;
|
||||
|
||||
private final int p1;
|
||||
|
||||
private final int p2;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, int p0, int p1,
|
||||
int p2) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToInt3Evaluator get(DriverContext context) {
|
||||
return new RoundToInt3Evaluator(source, field.get(context), p0, p1, p2, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToInt3Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.IntBlock;
|
||||
import org.elasticsearch.compute.data.IntVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToInt}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToInt4Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final int p0;
|
||||
|
||||
private final int p1;
|
||||
|
||||
private final int p2;
|
||||
|
||||
private final int p3;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToInt4Evaluator(Source source, EvalOperator.ExpressionEvaluator field, int p0, int p1,
|
||||
int p2, int p3, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p3 = p3;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (IntBlock fieldBlock = (IntBlock) field.eval(page)) {
|
||||
IntVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public IntBlock eval(int positionCount, IntBlock fieldBlock) {
|
||||
try(IntBlock.Builder result = driverContext.blockFactory().newIntBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendInt(RoundToInt.process(fieldBlock.getInt(fieldBlock.getFirstValueIndex(p)), this.p0, this.p1, this.p2, this.p3));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public IntVector eval(int positionCount, IntVector fieldVector) {
|
||||
try(IntVector.FixedBuilder result = driverContext.blockFactory().newIntVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendInt(p, RoundToInt.process(fieldVector.getInt(p), this.p0, this.p1, this.p2, this.p3));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToInt4Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + ", p3=" + p3 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final int p0;
|
||||
|
||||
private final int p1;
|
||||
|
||||
private final int p2;
|
||||
|
||||
private final int p3;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, int p0, int p1,
|
||||
int p2, int p3) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p3 = p3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToInt4Evaluator get(DriverContext context) {
|
||||
return new RoundToInt4Evaluator(source, field.get(context), p0, p1, p2, p3, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToInt4Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + ", p3=" + p3 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.IntBlock;
|
||||
import org.elasticsearch.compute.data.IntVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToInt}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToIntBinarySearchEvaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final int[] points;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToIntBinarySearchEvaluator(Source source, EvalOperator.ExpressionEvaluator field,
|
||||
int[] points, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (IntBlock fieldBlock = (IntBlock) field.eval(page)) {
|
||||
IntVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public IntBlock eval(int positionCount, IntBlock fieldBlock) {
|
||||
try(IntBlock.Builder result = driverContext.blockFactory().newIntBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendInt(RoundToInt.process(fieldBlock.getInt(fieldBlock.getFirstValueIndex(p)), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public IntVector eval(int positionCount, IntVector fieldVector) {
|
||||
try(IntVector.FixedBuilder result = driverContext.blockFactory().newIntVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendInt(p, RoundToInt.process(fieldVector.getInt(p), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToIntBinarySearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final int[] points;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, int[] points) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToIntBinarySearchEvaluator get(DriverContext context) {
|
||||
return new RoundToIntBinarySearchEvaluator(source, field.get(context), points, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToIntBinarySearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.IntBlock;
|
||||
import org.elasticsearch.compute.data.IntVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToInt}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToIntLinearSearchEvaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final int[] points;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToIntLinearSearchEvaluator(Source source, EvalOperator.ExpressionEvaluator field,
|
||||
int[] points, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (IntBlock fieldBlock = (IntBlock) field.eval(page)) {
|
||||
IntVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public IntBlock eval(int positionCount, IntBlock fieldBlock) {
|
||||
try(IntBlock.Builder result = driverContext.blockFactory().newIntBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendInt(RoundToInt.processLinear(fieldBlock.getInt(fieldBlock.getFirstValueIndex(p)), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public IntVector eval(int positionCount, IntVector fieldVector) {
|
||||
try(IntVector.FixedBuilder result = driverContext.blockFactory().newIntVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendInt(p, RoundToInt.processLinear(fieldVector.getInt(p), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToIntLinearSearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final int[] points;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, int[] points) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToIntLinearSearchEvaluator get(DriverContext context) {
|
||||
return new RoundToIntLinearSearchEvaluator(source, field.get(context), points, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToIntLinearSearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.LongBlock;
|
||||
import org.elasticsearch.compute.data.LongVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToLong}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToLong1Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final long p0;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToLong1Evaluator(Source source, EvalOperator.ExpressionEvaluator field, long p0,
|
||||
DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (LongBlock fieldBlock = (LongBlock) field.eval(page)) {
|
||||
LongVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public LongBlock eval(int positionCount, LongBlock fieldBlock) {
|
||||
try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendLong(RoundToLong.process(fieldBlock.getLong(fieldBlock.getFirstValueIndex(p)), this.p0));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public LongVector eval(int positionCount, LongVector fieldVector) {
|
||||
try(LongVector.FixedBuilder result = driverContext.blockFactory().newLongVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendLong(p, RoundToLong.process(fieldVector.getLong(p), this.p0));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLong1Evaluator[" + "field=" + field + ", p0=" + p0 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final long p0;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, long p0) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToLong1Evaluator get(DriverContext context) {
|
||||
return new RoundToLong1Evaluator(source, field.get(context), p0, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLong1Evaluator[" + "field=" + field + ", p0=" + p0 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.LongBlock;
|
||||
import org.elasticsearch.compute.data.LongVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToLong}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToLong2Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final long p0;
|
||||
|
||||
private final long p1;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToLong2Evaluator(Source source, EvalOperator.ExpressionEvaluator field, long p0,
|
||||
long p1, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (LongBlock fieldBlock = (LongBlock) field.eval(page)) {
|
||||
LongVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public LongBlock eval(int positionCount, LongBlock fieldBlock) {
|
||||
try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendLong(RoundToLong.process(fieldBlock.getLong(fieldBlock.getFirstValueIndex(p)), this.p0, this.p1));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public LongVector eval(int positionCount, LongVector fieldVector) {
|
||||
try(LongVector.FixedBuilder result = driverContext.blockFactory().newLongVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendLong(p, RoundToLong.process(fieldVector.getLong(p), this.p0, this.p1));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLong2Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final long p0;
|
||||
|
||||
private final long p1;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, long p0,
|
||||
long p1) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToLong2Evaluator get(DriverContext context) {
|
||||
return new RoundToLong2Evaluator(source, field.get(context), p0, p1, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLong2Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.LongBlock;
|
||||
import org.elasticsearch.compute.data.LongVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToLong}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToLong3Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final long p0;
|
||||
|
||||
private final long p1;
|
||||
|
||||
private final long p2;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToLong3Evaluator(Source source, EvalOperator.ExpressionEvaluator field, long p0,
|
||||
long p1, long p2, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (LongBlock fieldBlock = (LongBlock) field.eval(page)) {
|
||||
LongVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public LongBlock eval(int positionCount, LongBlock fieldBlock) {
|
||||
try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendLong(RoundToLong.process(fieldBlock.getLong(fieldBlock.getFirstValueIndex(p)), this.p0, this.p1, this.p2));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public LongVector eval(int positionCount, LongVector fieldVector) {
|
||||
try(LongVector.FixedBuilder result = driverContext.blockFactory().newLongVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendLong(p, RoundToLong.process(fieldVector.getLong(p), this.p0, this.p1, this.p2));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLong3Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final long p0;
|
||||
|
||||
private final long p1;
|
||||
|
||||
private final long p2;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, long p0, long p1,
|
||||
long p2) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToLong3Evaluator get(DriverContext context) {
|
||||
return new RoundToLong3Evaluator(source, field.get(context), p0, p1, p2, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLong3Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.LongBlock;
|
||||
import org.elasticsearch.compute.data.LongVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToLong}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToLong4Evaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final long p0;
|
||||
|
||||
private final long p1;
|
||||
|
||||
private final long p2;
|
||||
|
||||
private final long p3;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToLong4Evaluator(Source source, EvalOperator.ExpressionEvaluator field, long p0,
|
||||
long p1, long p2, long p3, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p3 = p3;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (LongBlock fieldBlock = (LongBlock) field.eval(page)) {
|
||||
LongVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public LongBlock eval(int positionCount, LongBlock fieldBlock) {
|
||||
try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendLong(RoundToLong.process(fieldBlock.getLong(fieldBlock.getFirstValueIndex(p)), this.p0, this.p1, this.p2, this.p3));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public LongVector eval(int positionCount, LongVector fieldVector) {
|
||||
try(LongVector.FixedBuilder result = driverContext.blockFactory().newLongVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendLong(p, RoundToLong.process(fieldVector.getLong(p), this.p0, this.p1, this.p2, this.p3));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLong4Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + ", p3=" + p3 + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final long p0;
|
||||
|
||||
private final long p1;
|
||||
|
||||
private final long p2;
|
||||
|
||||
private final long p3;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, long p0, long p1,
|
||||
long p2, long p3) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.p0 = p0;
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p3 = p3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToLong4Evaluator get(DriverContext context) {
|
||||
return new RoundToLong4Evaluator(source, field.get(context), p0, p1, p2, p3, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLong4Evaluator[" + "field=" + field + ", p0=" + p0 + ", p1=" + p1 + ", p2=" + p2 + ", p3=" + p3 + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.LongBlock;
|
||||
import org.elasticsearch.compute.data.LongVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToLong}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToLongBinarySearchEvaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final long[] points;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToLongBinarySearchEvaluator(Source source, EvalOperator.ExpressionEvaluator field,
|
||||
long[] points, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (LongBlock fieldBlock = (LongBlock) field.eval(page)) {
|
||||
LongVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public LongBlock eval(int positionCount, LongBlock fieldBlock) {
|
||||
try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendLong(RoundToLong.process(fieldBlock.getLong(fieldBlock.getFirstValueIndex(p)), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public LongVector eval(int positionCount, LongVector fieldVector) {
|
||||
try(LongVector.FixedBuilder result = driverContext.blockFactory().newLongVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendLong(p, RoundToLong.process(fieldVector.getLong(p), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLongBinarySearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final long[] points;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, long[] points) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToLongBinarySearchEvaluator get(DriverContext context) {
|
||||
return new RoundToLongBinarySearchEvaluator(source, field.get(context), points, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLongBinarySearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
// or more contributor license agreements. Licensed under the Elastic License
|
||||
// 2.0; you may not use this file except in compliance with the Elastic License
|
||||
// 2.0.
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.Override;
|
||||
import java.lang.String;
|
||||
import org.elasticsearch.compute.data.Block;
|
||||
import org.elasticsearch.compute.data.LongBlock;
|
||||
import org.elasticsearch.compute.data.LongVector;
|
||||
import org.elasticsearch.compute.data.Page;
|
||||
import org.elasticsearch.compute.operator.DriverContext;
|
||||
import org.elasticsearch.compute.operator.EvalOperator;
|
||||
import org.elasticsearch.compute.operator.Warnings;
|
||||
import org.elasticsearch.core.Releasables;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
|
||||
/**
|
||||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link RoundToLong}.
|
||||
* This class is generated. Edit {@code EvaluatorImplementer} instead.
|
||||
*/
|
||||
public final class RoundToLongLinearSearchEvaluator implements EvalOperator.ExpressionEvaluator {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator field;
|
||||
|
||||
private final long[] points;
|
||||
|
||||
private final DriverContext driverContext;
|
||||
|
||||
private Warnings warnings;
|
||||
|
||||
public RoundToLongLinearSearchEvaluator(Source source, EvalOperator.ExpressionEvaluator field,
|
||||
long[] points, DriverContext driverContext) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
this.driverContext = driverContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block eval(Page page) {
|
||||
try (LongBlock fieldBlock = (LongBlock) field.eval(page)) {
|
||||
LongVector fieldVector = fieldBlock.asVector();
|
||||
if (fieldVector == null) {
|
||||
return eval(page.getPositionCount(), fieldBlock);
|
||||
}
|
||||
return eval(page.getPositionCount(), fieldVector).asBlock();
|
||||
}
|
||||
}
|
||||
|
||||
public LongBlock eval(int positionCount, LongBlock fieldBlock) {
|
||||
try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
if (fieldBlock.isNull(p)) {
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
if (fieldBlock.getValueCount(p) != 1) {
|
||||
if (fieldBlock.getValueCount(p) > 1) {
|
||||
warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value"));
|
||||
}
|
||||
result.appendNull();
|
||||
continue position;
|
||||
}
|
||||
result.appendLong(RoundToLong.processLinear(fieldBlock.getLong(fieldBlock.getFirstValueIndex(p)), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
public LongVector eval(int positionCount, LongVector fieldVector) {
|
||||
try(LongVector.FixedBuilder result = driverContext.blockFactory().newLongVectorFixedBuilder(positionCount)) {
|
||||
position: for (int p = 0; p < positionCount; p++) {
|
||||
result.appendLong(p, RoundToLong.processLinear(fieldVector.getLong(p), this.points));
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLongLinearSearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Releasables.closeExpectNoException(field);
|
||||
}
|
||||
|
||||
private Warnings warnings() {
|
||||
if (warnings == null) {
|
||||
this.warnings = Warnings.createWarnings(
|
||||
driverContext.warningsMode(),
|
||||
source.source().getLineNumber(),
|
||||
source.source().getColumnNumber(),
|
||||
source.text()
|
||||
);
|
||||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
static class Factory implements EvalOperator.ExpressionEvaluator.Factory {
|
||||
private final Source source;
|
||||
|
||||
private final EvalOperator.ExpressionEvaluator.Factory field;
|
||||
|
||||
private final long[] points;
|
||||
|
||||
public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory field, long[] points) {
|
||||
this.source = source;
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoundToLongLinearSearchEvaluator get(DriverContext context) {
|
||||
return new RoundToLongLinearSearchEvaluator(source, field.get(context), points, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RoundToLongLinearSearchEvaluator[" + "field=" + field + "]";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1102,7 +1102,12 @@ public class EsqlCapabilities {
|
|||
* Avid GROK and DISSECT attributes being removed when resolving fields.
|
||||
* see <a href="https://github.com/elastic/elasticsearch/issues/127468"> ES|QL: Grok only supports KEYWORD or TEXT values, found expression [type] type [INTEGER] #127468 </a>
|
||||
*/
|
||||
KEEP_REGEX_EXTRACT_ATTRIBUTES;
|
||||
KEEP_REGEX_EXTRACT_ATTRIBUTES,
|
||||
|
||||
/**
|
||||
* The {@code ROUND_TO} function.
|
||||
*/
|
||||
ROUND_TO;
|
||||
|
||||
private final boolean enabled;
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.math.Log10;
|
|||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pi;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pow;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Round;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.RoundTo;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Scalb;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Signum;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Sin;
|
||||
|
@ -326,6 +327,7 @@ public class EsqlFunctionRegistry {
|
|||
def(Pi.class, Pi::new, "pi"),
|
||||
def(Pow.class, Pow::new, "pow"),
|
||||
def(Round.class, Round::new, "round"),
|
||||
def(RoundTo.class, RoundTo::new, "round_to"),
|
||||
def(Scalb.class, Scalb::new, "scalb"),
|
||||
def(Signum.class, Signum::new, "signum"),
|
||||
def(Sin.class, Sin::new, "sin"),
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.math.Log;
|
|||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pi;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Pow;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Round;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.RoundTo;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Tau;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.nulls.Coalesce;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.string.BitLength;
|
||||
|
@ -94,6 +95,7 @@ public class ScalarFunctionWritables {
|
|||
entries.add(Replace.ENTRY);
|
||||
entries.add(Reverse.ENTRY);
|
||||
entries.add(Round.ENTRY);
|
||||
entries.add(RoundTo.ENTRY);
|
||||
entries.add(Sha1.ENTRY);
|
||||
entries.add(Sha256.ENTRY);
|
||||
entries.add(Split.ENTRY);
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import org.elasticsearch.common.collect.Iterators;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.compute.operator.EvalOperator.ExpressionEvaluator;
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.expression.Foldables;
|
||||
import org.elasticsearch.xpack.esql.core.expression.Nullability;
|
||||
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions;
|
||||
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.Example;
|
||||
import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
|
||||
import org.elasticsearch.xpack.esql.expression.function.Param;
|
||||
import org.elasticsearch.xpack.esql.expression.function.scalar.EsqlScalarFunction;
|
||||
import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.common.logging.LoggerMessageFormat.format;
|
||||
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isFoldable;
|
||||
import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME;
|
||||
import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS;
|
||||
import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE;
|
||||
import static org.elasticsearch.xpack.esql.core.type.DataType.INTEGER;
|
||||
import static org.elasticsearch.xpack.esql.core.type.DataType.LONG;
|
||||
import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG;
|
||||
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.commonType;
|
||||
|
||||
/**
|
||||
* Round down to one of a list of values.
|
||||
*/
|
||||
public class RoundTo extends EsqlScalarFunction {
|
||||
public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "RoundTo", RoundTo::new);
|
||||
|
||||
private final Expression field;
|
||||
private final List<Expression> points;
|
||||
|
||||
private DataType resultType;
|
||||
|
||||
@FunctionInfo(returnType = { "double", "integer", "long", "date", "date_nanos" }, description = """
|
||||
Rounds down to one of a list of fixed points.""", examples = @Example(file = "math", tag = "round_to"))
|
||||
public RoundTo(
|
||||
Source source,
|
||||
@Param(
|
||||
name = "field",
|
||||
type = { "double", "integer", "long", "date", "date_nanos" },
|
||||
description = "The numeric value to round. If `null`, the function returns `null`."
|
||||
) Expression field,
|
||||
@Param(
|
||||
name = "points",
|
||||
type = { "double", "integer", "long", "date", "date_nanos" },
|
||||
description = "Remaining rounding points. Must be constants."
|
||||
) List<Expression> points
|
||||
) {
|
||||
super(source, Iterators.toList(Iterators.concat(Iterators.single(field), points.iterator())));
|
||||
this.field = field;
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
private RoundTo(StreamInput in) throws IOException {
|
||||
this(
|
||||
Source.readFrom((PlanStreamInput) in),
|
||||
in.readNamedWriteable(Expression.class),
|
||||
in.readNamedWriteableCollectionAsList(Expression.class)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
source().writeTo(out);
|
||||
out.writeNamedWriteable(field);
|
||||
out.writeNamedWriteableCollection(points);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWriteableName() {
|
||||
return ENTRY.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeResolution resolveType() {
|
||||
if (childrenResolved() == false) {
|
||||
return new TypeResolution("Unresolved children");
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
for (Expression f : points) {
|
||||
if (f.dataType() == DataType.NULL) {
|
||||
continue;
|
||||
}
|
||||
TypeResolution resolution = isFoldable(f, sourceText(), TypeResolutions.ParamOrdinal.fromIndex(index));
|
||||
if (resolution.unresolved()) {
|
||||
return resolution;
|
||||
}
|
||||
}
|
||||
|
||||
DataType dataType = dataType();
|
||||
if (dataType == null || SIGNATURES.containsKey(dataType) == false) {
|
||||
return new TypeResolution(format(null, "all arguments must be numeric, date, or data_nanos"));
|
||||
}
|
||||
|
||||
return TypeResolution.TYPE_RESOLVED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType dataType() {
|
||||
if (resultType != null) {
|
||||
return resultType;
|
||||
}
|
||||
resultType = field.dataType();
|
||||
for (Expression f : points) {
|
||||
if (resultType == DataType.UNSIGNED_LONG || resultType == null || f.dataType() == UNSIGNED_LONG) {
|
||||
return null;
|
||||
}
|
||||
resultType = commonType(resultType, f.dataType());
|
||||
}
|
||||
return resultType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
for (Expression c : children()) {
|
||||
if (c.foldable() == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nullability nullable() {
|
||||
return Nullability.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Expression replaceChildren(List<Expression> newChildren) {
|
||||
return new RoundTo(source(), newChildren.get(0), newChildren.subList(1, newChildren.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeInfo<? extends Expression> info() {
|
||||
return NodeInfo.create(this, RoundTo::new, field(), points());
|
||||
}
|
||||
|
||||
public Expression field() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public List<Expression> points() {
|
||||
return points;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) {
|
||||
DataType dataType = dataType();
|
||||
Build build = SIGNATURES.get(dataType);
|
||||
if (build == null) {
|
||||
throw new IllegalStateException("unsupported type");
|
||||
}
|
||||
|
||||
ExpressionEvaluator.Factory field = toEvaluator.apply(field());
|
||||
field = Cast.cast(source(), field().dataType(), dataType, field);
|
||||
List<Object> points = Iterators.toList(Iterators.map(points().iterator(), p -> Foldables.valueOf(toEvaluator.foldCtx(), p)));
|
||||
return build.build(source(), field, points);
|
||||
}
|
||||
|
||||
interface Build {
|
||||
ExpressionEvaluator.Factory build(Source source, ExpressionEvaluator.Factory field, List<Object> points);
|
||||
}
|
||||
|
||||
private static final Map<DataType, Build> SIGNATURES = Map.ofEntries(
|
||||
Map.entry(DATETIME, RoundToLong.BUILD),
|
||||
Map.entry(DATE_NANOS, RoundToLong.BUILD),
|
||||
Map.entry(INTEGER, RoundToInt.BUILD),
|
||||
Map.entry(LONG, RoundToLong.BUILD),
|
||||
Map.entry(DOUBLE, RoundToDouble.BUILD)
|
||||
);
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
// begin generated imports
|
||||
import org.elasticsearch.compute.ann.Evaluator;
|
||||
import org.elasticsearch.compute.ann.Fixed;
|
||||
|
||||
import java.util.Arrays;
|
||||
// end generated imports
|
||||
|
||||
/**
|
||||
* Implementations of {@link RoundTo} for specific types.
|
||||
* <p>
|
||||
* We have specializations for when there are very few rounding points because
|
||||
* those are very fast and quite common.
|
||||
* </p>
|
||||
* This class is generated. Edit {@code X-RoundTo.java.st} instead.
|
||||
*/
|
||||
class RoundTo$Type$ {
|
||||
static final RoundTo.Build BUILD = (source, field, points) -> {
|
||||
$type$[] f = points.stream().mapTo$Type$(p -> ((Number) p).$type$Value()).toArray();
|
||||
Arrays.sort(f);
|
||||
return switch (f.length) {
|
||||
// TODO should be a consistent way to do the 0 version - is CASE(MV_COUNT(f) == 1, f[0])
|
||||
case 1 -> new RoundTo$Type$1Evaluator.Factory(source, field, f[0]);
|
||||
/*
|
||||
* These hand-unrolled implementations are even faster than the linear scan implementations.
|
||||
*/
|
||||
case 2 -> new RoundTo$Type$2Evaluator.Factory(source, field, f[0], f[1]);
|
||||
case 3 -> new RoundTo$Type$3Evaluator.Factory(source, field, f[0], f[1], f[2]);
|
||||
case 4 -> new RoundTo$Type$4Evaluator.Factory(source, field, f[0], f[1], f[2], f[3]);
|
||||
/*
|
||||
* Break point of 10 experimentally derived on Nik's laptop (13th Gen Intel(R) Core(TM) i7-1370P)
|
||||
* on 2025-05-22.
|
||||
*/
|
||||
case 5, 6, 7, 8, 9, 10 -> new RoundTo$Type$LinearSearchEvaluator.Factory(source, field, f);
|
||||
default -> new RoundTo$Type$BinarySearchEvaluator.Factory(source, field, f);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Search the points array for the match linearly. This is faster for smaller arrays even
|
||||
* when finding a position late in the array. Presumably because this is super-SIMD-able.
|
||||
*/
|
||||
@Evaluator(extraName = "LinearSearch")
|
||||
static $type$ processLinear($type$ field, @Fixed(includeInToString = false) $type$[] points) {
|
||||
// points is always longer than 3 or we use one of the specialized methods below
|
||||
for (int i = 1; i < points.length; i++) {
|
||||
if (field < points[i]) {
|
||||
return points[i - 1];
|
||||
}
|
||||
}
|
||||
return points[points.length - 1];
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "BinarySearch")
|
||||
static $type$ process($type$ field, @Fixed(includeInToString = false) $type$[] points) {
|
||||
int idx = Arrays.binarySearch(points, field);
|
||||
return points[idx >= 0 ? idx : Math.max(0, -idx - 2)];
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "1")
|
||||
static $type$ process($type$ field, @Fixed $type$ p0) {
|
||||
return p0;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "2")
|
||||
static $type$ process($type$ field, @Fixed $type$ p0, @Fixed $type$ p1) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "3")
|
||||
static $type$ process($type$ field, @Fixed $type$ p0, @Fixed $type$ p1, @Fixed $type$ p2) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
if (field < p2) {
|
||||
return p1;
|
||||
}
|
||||
return p2;
|
||||
}
|
||||
|
||||
@Evaluator(extraName = "4")
|
||||
static $type$ process($type$ field, @Fixed $type$ p0, @Fixed $type$ p1, @Fixed $type$ p2, @Fixed $type$ p3) {
|
||||
if (field < p1) {
|
||||
return p0;
|
||||
}
|
||||
if (field < p2) {
|
||||
return p1;
|
||||
}
|
||||
if (field < p3) {
|
||||
return p2;
|
||||
}
|
||||
return p3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class RoundToErrorTests extends ErrorsForCasesWithoutExamplesTestCase {
|
||||
@Override
|
||||
protected List<TestCaseSupplier> cases() {
|
||||
return paramsToSuppliers(RoundToTests.parameters()).stream()
|
||||
/*
|
||||
* We pick the common type across all parameters, but we don't
|
||||
* test mixes with more than three parameters. We test cases
|
||||
* with more than three parameters - just not mixes with more
|
||||
* than three.
|
||||
*/
|
||||
.filter(s -> s.types().size() < 3)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new RoundTo(source, args.getFirst(), args.subList(1, args.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
|
||||
return equalTo("all arguments must be numeric, date, or data_nanos");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.expression.ReferenceAttribute;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.AbstractExpressionSerializationTests;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomLiteral;
|
||||
|
||||
public class RoundToSerializationTests extends AbstractExpressionSerializationTests<RoundTo> {
|
||||
@Override
|
||||
protected RoundTo createTestInstance() {
|
||||
Source source = randomSource();
|
||||
DataType type = randomFrom(DataType.INTEGER, DataType.LONG, DataType.DOUBLE, DataType.DATETIME, DataType.DATE_NANOS);
|
||||
Expression field = randomField(type);
|
||||
List<Expression> points = randomPoints(type);
|
||||
return new RoundTo(source, field, points);
|
||||
}
|
||||
|
||||
private Expression randomField(DataType type) {
|
||||
return new ReferenceAttribute(Source.EMPTY, randomAlphanumericOfLength(4), randomLiteral(type).dataType());
|
||||
}
|
||||
|
||||
private List<Expression> randomPoints(DataType type) {
|
||||
int length = between(1, 100);
|
||||
List<Expression> points = new ArrayList<>(length);
|
||||
while (points.size() < length) {
|
||||
points.add(randomLiteral(type));
|
||||
}
|
||||
;
|
||||
return points;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RoundTo mutateInstance(RoundTo instance) throws IOException {
|
||||
Source source = instance.source();
|
||||
Expression field = instance.field();
|
||||
List<Expression> points = instance.points();
|
||||
DataType type = field.dataType();
|
||||
if (randomBoolean()) {
|
||||
field = randomValueOtherThan(field, () -> randomField(type));
|
||||
} else {
|
||||
points = randomValueOtherThan(points, () -> randomPoints(type));
|
||||
}
|
||||
return new RoundTo(source, field, points);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.esql.expression.function.scalar.math;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.esql.core.expression.Expression;
|
||||
import org.elasticsearch.xpack.esql.core.tree.Source;
|
||||
import org.elasticsearch.xpack.esql.core.type.DataType;
|
||||
import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase;
|
||||
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
public class RoundToTests extends AbstractScalarFunctionTestCase {
|
||||
public RoundToTests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCaseSupplier) {
|
||||
this.testCase = testCaseSupplier.get();
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() {
|
||||
List<TestCaseSupplier> suppliers = new ArrayList<>();
|
||||
|
||||
for (int p = 1; p < 20; p++) {
|
||||
int points = p;
|
||||
suppliers.add(
|
||||
doubles(
|
||||
"<double, " + points + " doubles>",
|
||||
DataType.DOUBLE,
|
||||
() -> randomDoubleBetween(-Double.MAX_VALUE, Double.MAX_VALUE, true),
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.DOUBLE).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> randomDoubleBetween(-Double.MAX_VALUE, Double.MAX_VALUE, true)).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
doubles(
|
||||
"<double, " + points + " longs>",
|
||||
DataType.DOUBLE,
|
||||
() -> randomDoubleBetween(-Double.MAX_VALUE, Double.MAX_VALUE, true),
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.LONG).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> (double) randomLong()).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
doubles(
|
||||
"<double, " + points + " ints>",
|
||||
DataType.DOUBLE,
|
||||
() -> randomDoubleBetween(-Double.MAX_VALUE, Double.MAX_VALUE, true),
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.INTEGER).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> (double) randomInt()).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
doubles(
|
||||
"<long, " + points + " doubles>",
|
||||
DataType.LONG,
|
||||
ESTestCase::randomLong,
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.DOUBLE).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> randomDoubleBetween(-Double.MAX_VALUE, Double.MAX_VALUE, true)).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
doubles(
|
||||
"<int, " + points + " doubles>",
|
||||
DataType.INTEGER,
|
||||
ESTestCase::randomInt,
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.DOUBLE).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> randomDoubleBetween(-Double.MAX_VALUE, Double.MAX_VALUE, true)).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
longs(
|
||||
"<long, " + points + " longs>",
|
||||
DataType.LONG,
|
||||
ESTestCase::randomLong,
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.LONG).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> randomLong()).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
longs(
|
||||
"<int, " + points + " longs>",
|
||||
DataType.INTEGER,
|
||||
ESTestCase::randomInt,
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.LONG).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> randomLong()).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
longs(
|
||||
"<date, " + points + " dates>",
|
||||
DataType.DATETIME,
|
||||
ESTestCase::randomMillisUpToYear9999,
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.DATETIME).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> randomMillisUpToYear9999()).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
longs(
|
||||
"<date_nanos, " + points + " date_nanos>",
|
||||
DataType.DATE_NANOS,
|
||||
() -> randomLongBetween(0, Long.MAX_VALUE),
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.DATE_NANOS).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> randomLongBetween(0, Long.MAX_VALUE)).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
longs(
|
||||
"<long, " + points + " ints>",
|
||||
DataType.LONG,
|
||||
ESTestCase::randomLong,
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.INTEGER).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> (long) randomInt()).toList()
|
||||
)
|
||||
);
|
||||
suppliers.add(
|
||||
ints(
|
||||
"<int, " + points + " ints>",
|
||||
DataType.INTEGER,
|
||||
ESTestCase::randomInt,
|
||||
IntStream.range(0, points).mapToObj(i -> DataType.INTEGER).toList(),
|
||||
() -> IntStream.range(0, points).mapToObj(i -> randomInt()).toList()
|
||||
)
|
||||
);
|
||||
}
|
||||
suppliers.add(supplier(1.0, 0.0, 0.0, 100.0));
|
||||
suppliers.add(supplier(1.0, 1.0, 0.0, 1.0, 100.0));
|
||||
suppliers.add(supplier(0.5, 0.0, 0.0, 1.0, 100.0));
|
||||
suppliers.add(supplier(1.5, 1.0, 0.0, 1.0, 100.0));
|
||||
suppliers.add(supplier(200, 100, 0.0, 1.0, 100.0));
|
||||
|
||||
return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(
|
||||
(int nullPosition, DataType nullValueDataType, TestCaseSupplier.TestCase original) -> {
|
||||
if (nullValueDataType != DataType.NULL) {
|
||||
return original.expectedType();
|
||||
}
|
||||
List<DataType> types = original.getData().stream().map(TestCaseSupplier.TypedData::type).collect(Collectors.toList());
|
||||
types.set(nullPosition, DataType.NULL);
|
||||
return expectedType(types);
|
||||
},
|
||||
(int nullPosition, TestCaseSupplier.TypedData nullData, Matcher<String> original) -> {
|
||||
if (nullPosition == 0) {
|
||||
return original;
|
||||
}
|
||||
return equalTo("LiteralsEvaluator[lit=null]");
|
||||
},
|
||||
randomizeBytesRefsOffset(suppliers)
|
||||
);
|
||||
}
|
||||
|
||||
private static TestCaseSupplier supplier(double f, double expected, double... points) {
|
||||
StringBuilder name = new StringBuilder("round(");
|
||||
name.append(f);
|
||||
for (double p : points) {
|
||||
name.append(", ").append(p);
|
||||
}
|
||||
name.append(") -> ").append(expected);
|
||||
return supplier(
|
||||
name.toString(),
|
||||
DataType.DOUBLE,
|
||||
() -> f,
|
||||
IntStream.range(0, points.length).mapToObj(i -> DataType.DOUBLE).toList(),
|
||||
() -> Arrays.stream(points).boxed().toList(),
|
||||
(value, de) -> expected
|
||||
);
|
||||
}
|
||||
|
||||
private static TestCaseSupplier doubles(
|
||||
String name,
|
||||
DataType fieldType,
|
||||
Supplier<Number> fieldSupplier,
|
||||
List<DataType> pointsTypes,
|
||||
Supplier<List<Double>> pointsSupplier
|
||||
) {
|
||||
return supplier(name, fieldType, fieldSupplier, pointsTypes, pointsSupplier, (f, p) -> {
|
||||
double max = p.stream().mapToDouble(d -> d).min().getAsDouble();
|
||||
for (double d : p) {
|
||||
if (d > max && f.doubleValue() > d) {
|
||||
max = d;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
});
|
||||
}
|
||||
|
||||
private static TestCaseSupplier longs(
|
||||
String name,
|
||||
DataType fieldType,
|
||||
Supplier<Number> fieldSupplier,
|
||||
List<DataType> pointsTypes,
|
||||
Supplier<List<Long>> pointsSupplier
|
||||
) {
|
||||
return supplier(name, fieldType, fieldSupplier, pointsTypes, pointsSupplier, (f, p) -> {
|
||||
long max = p.stream().mapToLong(l -> l).min().getAsLong();
|
||||
for (long l : p) {
|
||||
if (l > max && f.doubleValue() > l) {
|
||||
max = l;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
});
|
||||
}
|
||||
|
||||
private static TestCaseSupplier ints(
|
||||
String name,
|
||||
DataType fieldType,
|
||||
Supplier<Number> fieldSupplier,
|
||||
List<DataType> pointsTypes,
|
||||
Supplier<List<Integer>> pointsSupplier
|
||||
) {
|
||||
return supplier(name, fieldType, fieldSupplier, pointsTypes, pointsSupplier, (f, p) -> {
|
||||
int max = p.stream().mapToInt(i -> i).min().getAsInt();
|
||||
for (int l : p) {
|
||||
if (l > max && f.doubleValue() > l) {
|
||||
max = l;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
});
|
||||
}
|
||||
|
||||
private static <P> TestCaseSupplier supplier(
|
||||
String name,
|
||||
DataType fieldType,
|
||||
Supplier<Number> fieldSupplier,
|
||||
List<DataType> pointsTypes,
|
||||
Supplier<List<P>> pointsSupplier,
|
||||
BiFunction<Number, List<P>, Number> expected
|
||||
) {
|
||||
List<DataType> types = new ArrayList<>(pointsTypes.size() + 1);
|
||||
types.add(fieldType);
|
||||
types.addAll(pointsTypes);
|
||||
return new TestCaseSupplier(name, types, () -> {
|
||||
Number field = fieldSupplier.get();
|
||||
List<P> points = pointsSupplier.get();
|
||||
|
||||
List<TestCaseSupplier.TypedData> params = new ArrayList<>(1 + points.size());
|
||||
params.add(new TestCaseSupplier.TypedData(field, fieldType, "field"));
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
params.add(new TestCaseSupplier.TypedData(points.get(i), pointsTypes.get(i), "point" + i).forceLiteral());
|
||||
}
|
||||
|
||||
DataType expectedType = expectedType(types);
|
||||
String type = switch (expectedType) {
|
||||
case DOUBLE -> "Double";
|
||||
case INTEGER -> "Int";
|
||||
case DATETIME, DATE_NANOS, LONG -> "Long";
|
||||
default -> throw new UnsupportedOperationException();
|
||||
};
|
||||
Matcher<String> expectedEvaluatorName = startsWith("RoundTo" + type + specialization(points.size()) + "Evaluator");
|
||||
return new TestCaseSupplier.TestCase(params, expectedEvaluatorName, expectedType, equalTo(expected.apply(field, points)));
|
||||
});
|
||||
}
|
||||
|
||||
private static String specialization(int pointsSize) {
|
||||
if (pointsSize < 5) {
|
||||
return Integer.toString(pointsSize);
|
||||
}
|
||||
if (pointsSize < 11) {
|
||||
return "LinearSearch";
|
||||
}
|
||||
return "BinarySearch";
|
||||
}
|
||||
|
||||
private static DataType expectedType(List<DataType> types) {
|
||||
if (types.stream().anyMatch(t -> t == DataType.DOUBLE)) {
|
||||
return DataType.DOUBLE;
|
||||
}
|
||||
if (types.stream().anyMatch(t -> t == DataType.LONG)) {
|
||||
return DataType.LONG;
|
||||
}
|
||||
if (types.stream().anyMatch(t -> t == DataType.INTEGER)) {
|
||||
return DataType.INTEGER;
|
||||
}
|
||||
if (types.stream().anyMatch(t -> t == DataType.DATETIME)) {
|
||||
return DataType.DATETIME;
|
||||
}
|
||||
if (types.stream().anyMatch(t -> t == DataType.DATE_NANOS)) {
|
||||
return DataType.DATE_NANOS;
|
||||
}
|
||||
throw new UnsupportedOperationException("can't build expected types for " + types);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expression build(Source source, List<Expression> args) {
|
||||
return new RoundTo(source, args.getFirst(), args.subList(1, args.size()));
|
||||
}
|
||||
}
|
|
@ -123,7 +123,7 @@ setup:
|
|||
- match: {esql.functions.coalesce: $functions_coalesce}
|
||||
- gt: {esql.functions.categorize: $functions_categorize}
|
||||
# Testing for the entire function set isn't feasible, so we just check that we return the correct count as an approximation.
|
||||
- length: {esql.functions: 142} # check the "sister" test below for a likely update to the same esql.functions length check
|
||||
- length: {esql.functions: 143} # check the "sister" test below for a likely update to the same esql.functions length check
|
||||
|
||||
---
|
||||
"Basic ESQL usage output (telemetry) non-snapshot version":
|
||||
|
@ -221,7 +221,7 @@ setup:
|
|||
- gt: {esql.functions.to_long: $functions_to_long}
|
||||
- match: {esql.functions.coalesce: $functions_coalesce}
|
||||
- gt: {esql.functions.categorize: $functions_categorize}
|
||||
- length: {esql.functions: 133} # check the "sister" test above for a likely update to the same esql.functions length check
|
||||
- length: {esql.functions: 134} # check the "sister" test above for a likely update to the same esql.functions length check
|
||||
|
||||
---
|
||||
took:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue