Skip to content

Commit 1102cb2

Browse files
committed
Detect long (BIGINT) arithmetic overflow instead of silently wrapping
PPL/SQL long arithmetic (+, -, *) in eval/SELECT expressions silently wrapped on overflow in the Calcite engine (e.g. long_field * 999...9 wrapped to a negative value with HTTP 200). SqlStdOperatorTable.PLUS/MINUS/MULTIPLY generate plain Java +/-/* in the Enumerable code path, which wrap. Rewrite long +/-/* to their overflow-checked variants (CHECKED_PLUS / CHECKED_MINUS / CHECKED_MULTIPLY), which generate Math.addExact etc. and throw ArithmeticException on overflow. The exception is caught in QueryService and surfaced as a 4xx client error instead of wrapping or falling back to V2. Scoped to BIGINT operands only: narrower integer arithmetic (byte/short/int) is widened to a type that cannot overflow before this rewrite runs (PPLFuncImpTable promotes byte/short to INT and any int/long to BIGINT for +/-/*), so long — which has no wider integer type — is the sole remaining overflow case on the Calcite engine. Float/double/decimal follow IEEE 754 / decimal semantics and have no CHECKED_* runtime, so they are left untouched. The rewrite runs after the analytics-engine fork, so only the Calcite path is affected (the DataFusion backend handles its own overflow). The rewrite runs before pushdown so both coordinator-executed and pushed-down (script) arithmetic are checked; PPLAggregateConvertRule, OpenSearchRelOptUtil, and ExtendedRelJson recognize the CHECKED_* kinds so aggregate/sort pushdown and script serialization keep working. Adds a REST yaml test (issues/5164.yml) and updates the affected explain fixtures. Resolves #5164 Signed-off-by: Kai Huang <ahkcs@amazon.com>
1 parent 4985a39 commit 1102cb2

16 files changed

Lines changed: 304 additions & 18 deletions

File tree

core/src/main/java/org/opensearch/sql/calcite/plan/rule/PPLAggregateConvertRule.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ public void apply(RelOptRuleCall call, LogicalAggregate aggregate, LogicalProjec
135135
final Function<RelNode, Function<RexNode, RexNode>> literalConverterProvider;
136136
RexCall rexCall = (RexCall) project.getProjects().get(aggCall.getArgList().getFirst());
137137
if (rexCall.getOperator().kind == SqlKind.PLUS
138-
|| rexCall.getOperator().kind == SqlKind.MINUS) {
138+
|| rexCall.getOperator().kind == SqlKind.MINUS
139+
|| rexCall.getOperator().kind == SqlKind.CHECKED_PLUS
140+
|| rexCall.getOperator().kind == SqlKind.CHECKED_MINUS) {
139141
AggregateCall countCall =
140142
AggregateCall.create(
141143
aggCall.getParserPosition(),
@@ -280,7 +282,12 @@ private static boolean isCallWithLiteral(RexNode node) {
280282

281283
List<SqlKind> CONVERTABLE_FUNCTIONS =
282284
List.of(
283-
SqlKind.PLUS, SqlKind.MINUS, SqlKind.TIMES
285+
SqlKind.PLUS,
286+
SqlKind.MINUS,
287+
SqlKind.TIMES,
288+
SqlKind.CHECKED_PLUS,
289+
SqlKind.CHECKED_MINUS,
290+
SqlKind.CHECKED_TIMES
284291
// Don't support division because of the issue of integer division
285292
// e.g. (2000 / 3) * 3 = 1998 while 2000 * 3 / 3 = 2000
286293
// SqlKind.DIVIDE

core/src/main/java/org/opensearch/sql/executor/QueryService.java

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@
1616
import org.apache.calcite.plan.RelTraitDef;
1717
import org.apache.calcite.rel.RelCollation;
1818
import org.apache.calcite.rel.RelCollations;
19+
import org.apache.calcite.rel.RelHomogeneousShuttle;
1920
import org.apache.calcite.rel.RelNode;
2021
import org.apache.calcite.rel.core.Sort;
2122
import org.apache.calcite.rel.logical.LogicalSort;
23+
import org.apache.calcite.rex.RexCall;
24+
import org.apache.calcite.rex.RexNode;
25+
import org.apache.calcite.rex.RexShuttle;
2226
import org.apache.calcite.schema.SchemaPlus;
27+
import org.apache.calcite.sql.SqlOperator;
28+
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
2329
import org.apache.calcite.sql.parser.SqlParser;
2430
import org.apache.calcite.tools.FrameworkConfig;
2531
import org.apache.calcite.tools.Frameworks;
@@ -174,7 +180,9 @@ public void executeWithCalcite(
174180
RelNode calcitePlan =
175181
StageErrorHandler.executeStage(
176182
QueryProcessingStage.PLAN_CONVERSION,
177-
() -> convertToCalcitePlan(relNode, context),
183+
() ->
184+
withCheckedArithmetic(
185+
convertToCalcitePlan(relNode, context), context),
178186
"while converting the query to an executable plan");
179187

180188
analyzeMetric.set(System.nanoTime() - analyzeStart);
@@ -187,7 +195,15 @@ public void executeWithCalcite(
187195
},
188196
QueryService.class);
189197
} catch (Throwable t) {
190-
if (isCalciteFallbackAllowed(t) && !(t instanceof NonFallbackCalciteException)) {
198+
ArithmeticException overflow = findArithmeticOverflow(t);
199+
if (overflow != null) {
200+
// Checked arithmetic detected integer/long overflow. Surface as a client error
201+
// instead of wrapping (silently) or falling back to the V2 engine.
202+
propagateCalciteError(
203+
new NonFallbackCalciteException(
204+
"Arithmetic overflow: " + overflow.getMessage(), overflow),
205+
listener);
206+
} else if (isCalciteFallbackAllowed(t) && !(t instanceof NonFallbackCalciteException)) {
191207
log.warn("Fallback to V2 query engine since got exception", t);
192208
executeWithLegacy(plan, queryType, listener, Optional.of(t));
193209
} else {
@@ -227,7 +243,8 @@ public void explainWithCalcite(
227243
context.run(
228244
() -> {
229245
RelNode relNode = analyze(plan, context);
230-
RelNode calcitePlan = convertToCalcitePlan(relNode, context);
246+
RelNode calcitePlan =
247+
withCheckedArithmetic(convertToCalcitePlan(relNode, context), context);
231248
if (format != null) {
232249
executionEngine.explain(calcitePlan, mode, format, context, listener);
233250
} else {
@@ -383,6 +400,91 @@ private boolean isCalciteEnabled(Settings settings) {
383400
}
384401
}
385402

403+
/**
404+
* Rewrite {@code +}/{@code -}/{@code *} to their overflow-checked variants ({@code CHECKED_PLUS}
405+
* / {@code CHECKED_MINUS} / {@code CHECKED_MULTIPLY}) so integer and long arithmetic overflow
406+
* throws {@link ArithmeticException} (via {@code Math.addExact} etc.) instead of silently
407+
* wrapping. Applied before pushdown so both coordinator-executed and pushed-down (script)
408+
* arithmetic are checked. Floating-point arithmetic is unchanged (IEEE 754).
409+
*
410+
* <p>This does the same rewrite as Calcite's {@code ConvertToChecked} but preserves each call's
411+
* originally inferred type (via {@code makeCall(type, op, operands)}) and touches only the three
412+
* arithmetic operators, so it does not re-derive the types of unrelated calls (e.g. {@code
413+
* CEIL}/{@code DIVIDE}) the way {@code ConvertToChecked} does.
414+
*/
415+
private static RelNode withCheckedArithmetic(RelNode calcitePlan, CalcitePlanContext context) {
416+
RexShuttle checkedShuttle =
417+
new RexShuttle() {
418+
@Override
419+
public RexNode visitCall(RexCall call) {
420+
RexNode visited = super.visitCall(call);
421+
if (!(visited instanceof RexCall rexCall)) {
422+
return visited;
423+
}
424+
SqlOperator checked =
425+
switch (rexCall.getOperator().getKind()) {
426+
case PLUS -> SqlStdOperatorTable.CHECKED_PLUS;
427+
case MINUS -> SqlStdOperatorTable.CHECKED_MINUS;
428+
case TIMES -> SqlStdOperatorTable.CHECKED_MULTIPLY;
429+
default -> null;
430+
};
431+
// Only integer/long arithmetic can overflow silently and has a checked
432+
// implementation (Math.addExact etc.). Float/double/decimal have no checked variant
433+
// (SqlFunctions.checkedMultiply(double,double) does not exist) and follow IEEE 754, so
434+
// leave them untouched.
435+
if (checked == null || !isCheckableIntegerArithmetic(rexCall)) {
436+
return visited;
437+
}
438+
return context.rexBuilder.makeCall(rexCall.getType(), checked, rexCall.getOperands());
439+
}
440+
};
441+
return calcitePlan.accept(
442+
new RelHomogeneousShuttle() {
443+
@Override
444+
public RelNode visit(RelNode other) {
445+
RelNode visited = super.visitChildren(other);
446+
return visited.accept(checkedShuttle);
447+
}
448+
});
449+
}
450+
451+
/**
452+
* Checked arithmetic is applied to BIGINT ({@code long}) operands only. Narrower integer
453+
* arithmetic (byte/short/int) is already widened to a type that cannot overflow before this
454+
* rewrite runs — {@code PPLFuncImpTable} promotes byte/short to INT and any int/long operand to
455+
* BIGINT for {@code +}/{@code -}/{@code *} — so the sole remaining overflow case that reaches the
456+
* Calcite engine is {@code long} arithmetic, which has no wider integer type to widen into.
457+
* Float/double/decimal follow IEEE 754 (or decimal semantics) and have no {@code CHECKED_*}
458+
* runtime (e.g. {@code SqlFunctions.checkedMultiply(double, double)} does not exist), so they are
459+
* left untouched. Require both the result and every operand to be BIGINT.
460+
*/
461+
private static boolean isCheckableIntegerArithmetic(RexCall call) {
462+
if (!isCheckableLongType(call.getType())) {
463+
return false;
464+
}
465+
return call.getOperands().stream().allMatch(op -> isCheckableLongType(op.getType()));
466+
}
467+
468+
private static boolean isCheckableLongType(org.apache.calcite.rel.type.RelDataType type) {
469+
return type.getSqlTypeName() == org.apache.calcite.sql.type.SqlTypeName.BIGINT;
470+
}
471+
472+
/**
473+
* Walk the cause chain to find an {@link ArithmeticException} raised by checked arithmetic. Row-
474+
* level overflow surfaces wrapped (SQLException -&gt; RuntimeException -&gt; ErrorReport), so a
475+
* top-level {@code catch (ArithmeticException)} is insufficient.
476+
*/
477+
private static ArithmeticException findArithmeticOverflow(@Nullable Throwable t) {
478+
for (Throwable cause = t;
479+
cause != null && cause != cause.getCause();
480+
cause = cause.getCause()) {
481+
if (cause instanceof ArithmeticException arithmeticException) {
482+
return arithmeticException;
483+
}
484+
}
485+
return null;
486+
}
487+
386488
// TODO https://github.com/opensearch-project/sql/issues/3457
387489
// Calcite is not available for SQL query now. Maybe release in 3.1.0?
388490
private boolean shouldUseCalcite(QueryType queryType) {

docs/user/ppl/functions/expressions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ Arithmetic expressions are formed by combining numeric literals and binary arith
1111
4. `/`: Division. When [`plugins.ppl.syntax.legacy.preferred`](../admin/settings.md) is `true` (default), integer operands follow the legacy truncating result. When the setting is `false`, the operands are promoted to floating-point, preserving the fractional part. Division by zero returns `NULL`.
1212
5. `%`: Modulo. This operator can only be used with integers and returns the remainder of the division.
1313

14+
### Overflow behavior
15+
16+
Integer and long arithmetic operations (`+`, `-`, `*`) in `eval` expressions detect overflow and return an error instead of silently wrapping. For example, `eval x = int_field + 1` where `int_field` is `2147483647` (integer max) returns an error rather than `-2147483648`. Floating-point (`float`, `double`) arithmetic follows IEEE 754 and does not produce overflow errors.
17+
1418
### Precedence
1519

1620
You can use parentheses to control the precedence of arithmetic operators. Otherwise, operators with higher precedence are performed first.

integ-test/src/test/resources/expectedOutput/calcite/explain_agg_counts_by6.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ calcite:
66
LogicalProject(gender=[$4], b_1=[+($3, 1)], $f3=[POWER($3, 2)])
77
CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]])
88
physical: |
9-
CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]], PushDownContext=[[AGGREGATION->rel#:LogicalAggregate.NONE.[](input=RelSubset#,group={0},count(b_1)=COUNT($1),c3=COUNT($2)), PROJECT->[count(b_1), c3, gender], LIMIT->10000], OpenSearchRequestBuilder(sourceBuilder={"from":0,"size":0,"timeout":"1m","aggregations":{"composite_buckets":{"composite":{"size":1000,"sources":[{"gender":{"terms":{"field":"gender.keyword","missing_bucket":true,"missing_order":"first","order":"asc"}}}]},"aggregations":{"count(b_1)":{"value_count":{"script":{"source":"{\"langType\":\"calcite\",\"script\":\"rO0ABXQBQ3sKICAib3AiOiB7CiAgICAibmFtZSI6ICIrIiwKICAgICJraW5kIjogIlBMVVMiLAogICAgInN5bnRheCI6ICJCSU5BUlkiCiAgfSwKICAib3BlcmFuZHMiOiBbCiAgICB7CiAgICAgICJkeW5hbWljUGFyYW0iOiAwLAogICAgICAidHlwZSI6IHsKICAgICAgICAidHlwZSI6ICJCSUdJTlQiLAogICAgICAgICJudWxsYWJsZSI6IHRydWUKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgImR5bmFtaWNQYXJhbSI6IDEsCiAgICAgICJ0eXBlIjogewogICAgICAgICJ0eXBlIjogIkJJR0lOVCIsCiAgICAgICAgIm51bGxhYmxlIjogdHJ1ZQogICAgICB9CiAgICB9CiAgXQp9\"}","lang":"opensearch_compounded_script","params":{"utcTimestamp": 0,"SOURCES":[0,2],"DIGESTS":["balance",1]}}}},"c3":{"value_count":{"script":{"source":"{\"langType\":\"calcite\",\"script\":\"rO0ABXQBVHsKICAib3AiOiB7CiAgICAibmFtZSI6ICJQT1dFUiIsCiAgICAia2luZCI6ICJPVEhFUl9GVU5DVElPTiIsCiAgICAic3ludGF4IjogIkZVTkNUSU9OIgogIH0sCiAgIm9wZXJhbmRzIjogWwogICAgewogICAgICAiZHluYW1pY1BhcmFtIjogMCwKICAgICAgInR5cGUiOiB7CiAgICAgICAgInR5cGUiOiAiQklHSU5UIiwKICAgICAgICAibnVsbGFibGUiOiB0cnVlCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJkeW5hbWljUGFyYW0iOiAxLAogICAgICAidHlwZSI6IHsKICAgICAgICAidHlwZSI6ICJJTlRFR0VSIiwKICAgICAgICAibnVsbGFibGUiOiB0cnVlCiAgICAgIH0KICAgIH0KICBdCn0=\"}","lang":"opensearch_compounded_script","params":{"utcTimestamp": 0,"SOURCES":[0,2],"DIGESTS":["balance",2]}}}}}}}}, requestedTotalSize=10000, pageSize=null, startFrom=0)])
9+
CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]], PushDownContext=[[AGGREGATION->rel#:LogicalAggregate.NONE.[](input=RelSubset#,group={0},count(b_1)=COUNT($1),c3=COUNT($2)), PROJECT->[count(b_1), c3, gender], LIMIT->10000], OpenSearchRequestBuilder(sourceBuilder={"from":0,"size":0,"timeout":"1m","aggregations":{"composite_buckets":{"composite":{"size":1000,"sources":[{"gender":{"terms":{"field":"gender.keyword","missing_bucket":true,"missing_order":"first","order":"asc"}}}]},"aggregations":{"count(b_1)":{"value_count":{"script":{"source":"{\"langType\":\"calcite\",\"script\":\"rO0ABXQBS3sKICAib3AiOiB7CiAgICAibmFtZSI6ICIrIiwKICAgICJraW5kIjogIkNIRUNLRURfUExVUyIsCiAgICAic3ludGF4IjogIkJJTkFSWSIKICB9LAogICJvcGVyYW5kcyI6IFsKICAgIHsKICAgICAgImR5bmFtaWNQYXJhbSI6IDAsCiAgICAgICJ0eXBlIjogewogICAgICAgICJ0eXBlIjogIkJJR0lOVCIsCiAgICAgICAgIm51bGxhYmxlIjogdHJ1ZQogICAgICB9CiAgICB9LAogICAgewogICAgICAiZHluYW1pY1BhcmFtIjogMSwKICAgICAgInR5cGUiOiB7CiAgICAgICAgInR5cGUiOiAiQklHSU5UIiwKICAgICAgICAibnVsbGFibGUiOiB0cnVlCiAgICAgIH0KICAgIH0KICBdCn0=\"}","lang":"opensearch_compounded_script","params":{"utcTimestamp": 0,"SOURCES":[0,2],"DIGESTS":["balance",1]}}}},"c3":{"value_count":{"script":{"source":"{\"langType\":\"calcite\",\"script\":\"rO0ABXQBVHsKICAib3AiOiB7CiAgICAibmFtZSI6ICJQT1dFUiIsCiAgICAia2luZCI6ICJPVEhFUl9GVU5DVElPTiIsCiAgICAic3ludGF4IjogIkZVTkNUSU9OIgogIH0sCiAgIm9wZXJhbmRzIjogWwogICAgewogICAgICAiZHluYW1pY1BhcmFtIjogMCwKICAgICAgInR5cGUiOiB7CiAgICAgICAgInR5cGUiOiAiQklHSU5UIiwKICAgICAgICAibnVsbGFibGUiOiB0cnVlCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJkeW5hbWljUGFyYW0iOiAxLAogICAgICAidHlwZSI6IHsKICAgICAgICAidHlwZSI6ICJJTlRFR0VSIiwKICAgICAgICAibnVsbGFibGUiOiB0cnVlCiAgICAgIH0KICAgIH0KICBdCn0=\"}","lang":"opensearch_compounded_script","params":{"utcTimestamp": 0,"SOURCES":[0,2],"DIGESTS":["balance",2]}}}}}}}}, requestedTotalSize=10000, pageSize=null, startFrom=0)])

integ-test/src/test/resources/expectedOutput/calcite/explain_complex_sort_expr_no_expr_output_push.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ calcite:
66
LogicalProject(account_number=[$0], firstname=[$1], address=[$2], birthdate=[$3], gender=[$4], city=[$5], lastname=[$6], balance=[$7], employer=[$8], state=[$9], age=[$10], email=[$11], male=[$12], _id=[$13], _index=[$14], _score=[$15], _maxscore=[$16], _sort=[$17], _routing=[$18], age2=[+(CAST($10):BIGINT, $7)])
77
CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]])
88
physical: |
9-
CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]], PushDownContext=[[PROJECT->[age, balance], SORT_EXPR->[+(CAST($0):BIGINT, $1) ASCENDING NULLS_FIRST], LIMIT->10000, PROJECT->[age]], OpenSearchRequestBuilder(sourceBuilder={"from":0,"size":10000,"timeout":"1m","_source":{"includes":["age"]},"sort":[{"_script":{"script":{"source":"{\"langType\":\"calcite\",\"script\":\"rO0ABXQCN3sKICAib3AiOiB7CiAgICAibmFtZSI6ICIrIiwKICAgICJraW5kIjogIlBMVVMiLAogICAgInN5bnRheCI6ICJCSU5BUlkiCiAgfSwKICAib3BlcmFuZHMiOiBbCiAgICB7CiAgICAgICJvcCI6IHsKICAgICAgICAibmFtZSI6ICJDQVNUIiwKICAgICAgICAia2luZCI6ICJDQVNUIiwKICAgICAgICAic3ludGF4IjogIlNQRUNJQUwiCiAgICAgIH0sCiAgICAgICJvcGVyYW5kcyI6IFsKICAgICAgICB7CiAgICAgICAgICAiZHluYW1pY1BhcmFtIjogMCwKICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAidHlwZSI6ICJJTlRFR0VSIiwKICAgICAgICAgICAgIm51bGxhYmxlIjogdHJ1ZQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgXSwKICAgICAgInR5cGUiOiB7CiAgICAgICAgInR5cGUiOiAiQklHSU5UIiwKICAgICAgICAibnVsbGFibGUiOiB0cnVlCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJkeW5hbWljUGFyYW0iOiAxLAogICAgICAidHlwZSI6IHsKICAgICAgICAidHlwZSI6ICJCSUdJTlQiLAogICAgICAgICJudWxsYWJsZSI6IHRydWUKICAgICAgfQogICAgfQogIF0KfQ==\"}","lang":"opensearch_compounded_script","params":{"MISSING_MAX":false,"utcTimestamp": 0,"SOURCES":[0,0],"DIGESTS":["age","balance"]}},"type":"number","order":"asc"}}]}, requestedTotalSize=10000, pageSize=null, startFrom=0)])
9+
CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]], PushDownContext=[[PROJECT->[age, balance], SORT_EXPR->[+(CAST($0):BIGINT, $1) ASCENDING NULLS_FIRST], LIMIT->10000, PROJECT->[age]], OpenSearchRequestBuilder(sourceBuilder={"from":0,"size":10000,"timeout":"1m","_source":{"includes":["age"]},"sort":[{"_script":{"script":{"source":"{\"langType\":\"calcite\",\"script\":\"rO0ABXQCP3sKICAib3AiOiB7CiAgICAibmFtZSI6ICIrIiwKICAgICJraW5kIjogIkNIRUNLRURfUExVUyIsCiAgICAic3ludGF4IjogIkJJTkFSWSIKICB9LAogICJvcGVyYW5kcyI6IFsKICAgIHsKICAgICAgIm9wIjogewogICAgICAgICJuYW1lIjogIkNBU1QiLAogICAgICAgICJraW5kIjogIkNBU1QiLAogICAgICAgICJzeW50YXgiOiAiU1BFQ0lBTCIKICAgICAgfSwKICAgICAgIm9wZXJhbmRzIjogWwogICAgICAgIHsKICAgICAgICAgICJkeW5hbWljUGFyYW0iOiAwLAogICAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAgICJ0eXBlIjogIklOVEVHRVIiLAogICAgICAgICAgICAibnVsbGFibGUiOiB0cnVlCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICBdLAogICAgICAidHlwZSI6IHsKICAgICAgICAidHlwZSI6ICJCSUdJTlQiLAogICAgICAgICJudWxsYWJsZSI6IHRydWUKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgImR5bmFtaWNQYXJhbSI6IDEsCiAgICAgICJ0eXBlIjogewogICAgICAgICJ0eXBlIjogIkJJR0lOVCIsCiAgICAgICAgIm51bGxhYmxlIjogdHJ1ZQogICAgICB9CiAgICB9CiAgXQp9\"}","lang":"opensearch_compounded_script","params":{"MISSING_MAX":false,"utcTimestamp": 0,"SOURCES":[0,0],"DIGESTS":["age","balance"]}},"type":"number","order":"asc"}}]}, requestedTotalSize=10000, pageSize=null, startFrom=0)])

integ-test/src/test/resources/expectedOutput/calcite/explain_complex_sort_expr_project_then_sort.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ calcite:
66
CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]])
77
physical: |
88
EnumerableCalc(expr#0..1=[{inputs}], expr#2=[CAST($t0):BIGINT], expr#3=[+($t2, $t1)], age=[$t0], age2=[$t3])
9-
CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]], PushDownContext=[[PROJECT->[age, balance], SORT_EXPR->[+(CAST($0):BIGINT, $1) ASCENDING NULLS_FIRST], LIMIT->10000], OpenSearchRequestBuilder(sourceBuilder={"from":0,"size":10000,"timeout":"1m","_source":{"includes":["age","balance"]},"sort":[{"_script":{"script":{"source":"{\"langType\":\"calcite\",\"script\":\"rO0ABXQCN3sKICAib3AiOiB7CiAgICAibmFtZSI6ICIrIiwKICAgICJraW5kIjogIlBMVVMiLAogICAgInN5bnRheCI6ICJCSU5BUlkiCiAgfSwKICAib3BlcmFuZHMiOiBbCiAgICB7CiAgICAgICJvcCI6IHsKICAgICAgICAibmFtZSI6ICJDQVNUIiwKICAgICAgICAia2luZCI6ICJDQVNUIiwKICAgICAgICAic3ludGF4IjogIlNQRUNJQUwiCiAgICAgIH0sCiAgICAgICJvcGVyYW5kcyI6IFsKICAgICAgICB7CiAgICAgICAgICAiZHluYW1pY1BhcmFtIjogMCwKICAgICAgICAgICJ0eXBlIjogewogICAgICAgICAgICAidHlwZSI6ICJJTlRFR0VSIiwKICAgICAgICAgICAgIm51bGxhYmxlIjogdHJ1ZQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgXSwKICAgICAgInR5cGUiOiB7CiAgICAgICAgInR5cGUiOiAiQklHSU5UIiwKICAgICAgICAibnVsbGFibGUiOiB0cnVlCiAgICAgIH0KICAgIH0sCiAgICB7CiAgICAgICJkeW5hbWljUGFyYW0iOiAxLAogICAgICAidHlwZSI6IHsKICAgICAgICAidHlwZSI6ICJCSUdJTlQiLAogICAgICAgICJudWxsYWJsZSI6IHRydWUKICAgICAgfQogICAgfQogIF0KfQ==\"}","lang":"opensearch_compounded_script","params":{"MISSING_MAX":false,"utcTimestamp": 0,"SOURCES":[0,0],"DIGESTS":["age","balance"]}},"type":"number","order":"asc"}}]}, requestedTotalSize=10000, pageSize=null, startFrom=0)])
9+
CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]], PushDownContext=[[PROJECT->[age, balance], SORT_EXPR->[+(CAST($0):BIGINT, $1) ASCENDING NULLS_FIRST], LIMIT->10000], OpenSearchRequestBuilder(sourceBuilder={"from":0,"size":10000,"timeout":"1m","_source":{"includes":["age","balance"]},"sort":[{"_script":{"script":{"source":"{\"langType\":\"calcite\",\"script\":\"rO0ABXQCP3sKICAib3AiOiB7CiAgICAibmFtZSI6ICIrIiwKICAgICJraW5kIjogIkNIRUNLRURfUExVUyIsCiAgICAic3ludGF4IjogIkJJTkFSWSIKICB9LAogICJvcGVyYW5kcyI6IFsKICAgIHsKICAgICAgIm9wIjogewogICAgICAgICJuYW1lIjogIkNBU1QiLAogICAgICAgICJraW5kIjogIkNBU1QiLAogICAgICAgICJzeW50YXgiOiAiU1BFQ0lBTCIKICAgICAgfSwKICAgICAgIm9wZXJhbmRzIjogWwogICAgICAgIHsKICAgICAgICAgICJkeW5hbWljUGFyYW0iOiAwLAogICAgICAgICAgInR5cGUiOiB7CiAgICAgICAgICAgICJ0eXBlIjogIklOVEVHRVIiLAogICAgICAgICAgICAibnVsbGFibGUiOiB0cnVlCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICBdLAogICAgICAidHlwZSI6IHsKICAgICAgICAidHlwZSI6ICJCSUdJTlQiLAogICAgICAgICJudWxsYWJsZSI6IHRydWUKICAgICAgfQogICAgfSwKICAgIHsKICAgICAgImR5bmFtaWNQYXJhbSI6IDEsCiAgICAgICJ0eXBlIjogewogICAgICAgICJ0eXBlIjogIkJJR0lOVCIsCiAgICAgICAgIm51bGxhYmxlIjogdHJ1ZQogICAgICB9CiAgICB9CiAgXQp9\"}","lang":"opensearch_compounded_script","params":{"MISSING_MAX":false,"utcTimestamp": 0,"SOURCES":[0,0],"DIGESTS":["age","balance"]}},"type":"number","order":"asc"}}]}, requestedTotalSize=10000, pageSize=null, startFrom=0)])

0 commit comments

Comments
 (0)