This is an automated email from the ASF dual-hosted git repository.
mbudiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new fa0d559ae8 [CALCITE-6706] Checked arithmetic does not take effect in
subqueries
fa0d559ae8 is described below
commit fa0d559ae85228fad5e277fe68029a0668b9cf65
Author: Mihai Budiu <[email protected]>
AuthorDate: Tue Nov 26 18:40:15 2024 -0800
[CALCITE-6706] Checked arithmetic does not take effect in subqueries
Signed-off-by: Mihai Budiu <[email protected]>
---
.../apache/calcite/sql2rel/ConvertToChecked.java | 11 ++++++++---
.../org/apache/calcite/test/SqlOperatorTest.java | 22 ++++++++++++++++++++++
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/sql2rel/ConvertToChecked.java
b/core/src/main/java/org/apache/calcite/sql2rel/ConvertToChecked.java
index d612818d27..d7754b4801 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/ConvertToChecked.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/ConvertToChecked.java
@@ -22,6 +22,7 @@ import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexCall;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexShuttle;
+import org.apache.calcite.rex.RexSubQuery;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
@@ -50,13 +51,18 @@ public class ConvertToChecked extends RelHomogeneousShuttle
{
* Visitor which rewrites an expression tree such that all
* arithmetic operations that produce numeric values use checked arithmetic.
*/
- static class ConvertRexToChecked extends RexShuttle {
+ class ConvertRexToChecked extends RexShuttle {
private final RexBuilder builder;
ConvertRexToChecked(RexBuilder builder) {
this.builder = builder;
}
+ @Override public RexNode visitSubQuery(RexSubQuery subQuery) {
+ RelNode result = subQuery.rel.accept(ConvertToChecked.this);
+ return subQuery.clone(result);
+ }
+
@Override public RexNode visitCall(final RexCall call) {
boolean[] update = {false};
List<RexNode> clonedOperands = visitList(call.operands, update);
@@ -92,8 +98,7 @@ public class ConvertToChecked extends RelHomogeneousShuttle {
result = call;
}
return builder.makeCast(call.getType(), result);
- } else if (!SqlTypeName.EXACT_TYPES.contains(resultType)
- || (resultType == SqlTypeName.DECIMAL)) {
+ } else if (!SqlTypeName.EXACT_TYPES.contains(resultType)) {
// Do not rewrite operator if the type is e.g., DOUBLE or DATE
operator = call.getOperator();
}
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index c00b99ac87..1ddb005a29 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -3300,6 +3300,28 @@ public class SqlOperatorTest {
DECIMAL_OVERFLOW, true);
}
+ /** Test case for <a
href="https://issues.apache.org/jira/browse/CALCITE-6706">[CALCITE-6706]
+ * Checked arithmetic does not take effect in subqueries</a>. */
+ @Test void testCastOverflow() {
+ final SqlOperatorFixture f =
fixture().withConformance(SqlConformanceEnum.BIG_QUERY);
+ f.checkFails("SELECT -CAST(-32768 AS SMALLINT)",
+ "integer overflow: Value 32768 does not fit in a SMALLINT", true);
+ f.checkFails("SELECT CAST(32768 AS SMALLINT)",
+ "Value 32768 out of range", true);
+ f.checkFails("SELECT -CAST(32768 AS SMALLINT)",
+ "Value 32768 out of range", true);
+ final SqlOperatorFixture f0 = fixture();
+ // This query does not fail if checked arithmetic is not used
+ f0.checkScalar("SELECT -CAST(-32768 AS SMALLINT)",
+ "-32768", "SMALLINT");
+ // The last two queries should fail in any conformance level
+ // because the value "32768" cannot be represented as a SMALLINT
+ f0.checkFails("SELECT CAST(32768 AS SMALLINT)",
+ "Value 32768 out of range", true);
+ f0.checkFails("SELECT -CAST(32768 AS SMALLINT)",
+ "Value 32768 out of range", true);
+ }
+
@Test void testMinusIntervalOperator() {
final SqlOperatorFixture f = fixture();
f.setFor(SqlStdOperatorTable.MINUS, VmName.EXPAND);