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);
         }

Reply via email to