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 64cec27f1e [CALCITE-6751] Reduction of CAST from string to interval is
incorrect
64cec27f1e is described below
commit 64cec27f1efb68a1f5d5fb1c3f224e9e71b3ff87
Author: Mihai Budiu <[email protected]>
AuthorDate: Fri Dec 27 17:13:48 2024 -0800
[CALCITE-6751] Reduction of CAST from string to interval is incorrect
Signed-off-by: Mihai Budiu <[email protected]>
---
.../adapter/enumerable/RexToLixTranslator.java | 11 ++++--
.../org/apache/calcite/runtime/SqlFunctions.java | 4 +++
core/src/test/resources/sql/misc.iq | 42 ++++++++++++++++++++++
.../org/apache/calcite/test/CalciteAssert.java | 7 ++++
4 files changed, 61 insertions(+), 3 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
index f46cdad24c..b3e8c24446 100644
---
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
+++
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
@@ -304,8 +304,8 @@ public class RexToLixTranslator implements
RexVisitor<RexToLixTranslator.Result>
ConstantExpression format) {
Expression convert = getConvertExpression(sourceType, targetType, operand,
format);
Expression convert2 = checkExpressionPadTruncate(convert, sourceType,
targetType);
- Expression convert3 = expressionHandlingSafe(convert2, safe, targetType);
- return scaleValue(sourceType, targetType, convert3);
+ Expression convert3 = scaleValue(sourceType, targetType, convert2);
+ return expressionHandlingSafe(convert3, safe, targetType);
}
private Expression getConvertExpression(
@@ -1213,7 +1213,7 @@ public class RexToLixTranslator implements
RexVisitor<RexToLixTranslator.Result>
final SqlTypeFamily sourceFamily = sourceType.getSqlTypeName().getFamily();
if (targetFamily == SqlTypeFamily.NUMERIC
// multiplyDivide cannot handle DECIMALs, but for DECIMAL
- // destination types the result is already scaled.
+ // target types the result is already scaled.
&& targetType.getSqlTypeName() != SqlTypeName.DECIMAL
&& (sourceFamily == SqlTypeFamily.INTERVAL_YEAR_MONTH
|| sourceFamily == SqlTypeFamily.INTERVAL_DAY_TIME)) {
@@ -1223,6 +1223,11 @@ public class RexToLixTranslator implements
RexVisitor<RexToLixTranslator.Result>
sourceType.getSqlTypeName().getEndUnit().multiplier;
return RexImpTable.multiplyDivide(operand, multiplier, divider);
}
+ if (SqlTypeName.INTERVAL_TYPES.contains(targetType.getSqlTypeName())) {
+ final BigDecimal multiplier =
targetType.getSqlTypeName().getEndUnit().multiplier;
+ final BigDecimal divider = BigDecimal.ONE;
+ return RexImpTable.multiplyDivide(operand, multiplier, divider);
+ }
return operand;
}
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index 156508a5dd..e98aa2fcb0 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -4310,6 +4310,10 @@ public class SqlFunctions {
return v == null ? castNonNull(null) : toInt(v);
}
+ // Method tagged as non-deterministic because it can throw.
+ // The DeterministicCodeOptimizer may otherwise try to lift it out of
try-catch blocks.
+ // See https://issues.apache.org/jira/browse/CALCITE-6753
+ @NonDeterministic
public static int toInt(String s) {
return parseInt(s.trim());
}
diff --git a/core/src/test/resources/sql/misc.iq
b/core/src/test/resources/sql/misc.iq
index f8856e5ad9..83d045f1bd 100644
--- a/core/src/test/resources/sql/misc.iq
+++ b/core/src/test/resources/sql/misc.iq
@@ -18,6 +18,48 @@
!use post
!set outputformat mysql
+# [CALCITE-6751] Reduction of CAST from string to interval is incorrect
+SELECT TIME '10:00:00' + CAST('1' AS INTERVAL SECOND);
++----------+
+| EXPR$0 |
++----------+
+| 10:00:01 |
++----------+
+(1 row)
+
+!ok
+
+# Due to CALCITE-6752 the following test crashes:
+# SELECT TIME '10:00:00' + CAST('1.1' AS INTERVAL SECOND);
+# +------------+
+# | EXPR$0 |
+# +------------+
+# | 11:00:00.1 |
+# +------------+
+# (1 row)
+#
+# !ok
+
+SELECT TIME '10:00:00' + CAST('1' AS INTERVAL HOUR);
++----------+
+| EXPR$0 |
++----------+
+| 11:00:00 |
++----------+
+(1 row)
+
+!ok
+
+SELECT TIME '10:00:00' + CAST('1' AS INTERVAL MINUTE);
++----------+
+| EXPR$0 |
++----------+
+| 10:01:00 |
++----------+
+(1 row)
+
+!ok
+
SELECT UUID '123e4567-e89b-12d3-a456-426655440000';
+--------------------------------------+
| EXPR$0 |
diff --git a/testkit/src/main/java/org/apache/calcite/test/CalciteAssert.java
b/testkit/src/main/java/org/apache/calcite/test/CalciteAssert.java
index 8c484d4506..7931318df4 100644
--- a/testkit/src/main/java/org/apache/calcite/test/CalciteAssert.java
+++ b/testkit/src/main/java/org/apache/calcite/test/CalciteAssert.java
@@ -569,6 +569,13 @@ public class CalciteAssert {
try {
if (updateChecker == null) {
resultSet = statement.executeQuery(sql);
+ if (resultChecker == null && exceptionChecker != null) {
+ // Pull data from result set, otherwise exceptions that happen
during evaluation
+ // won't be triggered
+ while (resultSet.next()) {
+ // no need to do anything with the data
+ }
+ }
} else {
updateCount = statement.executeUpdate(sql);
}