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 ba9c840b75 [CALCITE-6168] RexExecutor can throw during compilation
ba9c840b75 is described below
commit ba9c840b7516acaccee20d778726c818928c40e2
Author: Mihai Budiu <[email protected]>
AuthorDate: Thu Jan 25 15:57:42 2024 -0800
[CALCITE-6168] RexExecutor can throw during compilation
Signed-off-by: Mihai Budiu <[email protected]>
---
.../org/apache/calcite/rex/RexExecutorImpl.java | 16 ++++++++++++----
.../org/apache/calcite/rex/RexExecutorTest.java | 22 ++++++++++++++++++++++
.../java/org/apache/calcite/sql/test/SqlTests.java | 20 ++++++++++++++++++++
3 files changed, 54 insertions(+), 4 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
b/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
index eaa3c7dd46..b32399b02f 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexExecutorImpl.java
@@ -129,10 +129,18 @@ public class RexExecutorImpl implements RexExecutor {
*/
@Override public void reduce(RexBuilder rexBuilder, List<RexNode> constExps,
List<RexNode> reducedValues) {
- final String code =
- compile(rexBuilder, constExps, (list, index, storageType) -> {
- throw new UnsupportedOperationException();
- });
+ String code;
+ try {
+ code = compile(rexBuilder, constExps, (list, index, storageType) -> {
+ throw new UnsupportedOperationException();
+ });
+ } catch (RuntimeException ex) {
+ // Give up on reduction and return expressions unchanged.
+ // This effectively moves the error from compile time to runtime.
+ // We could give a warning here if there was a mechanism for warnings.
+ reducedValues.addAll(constExps);
+ return;
+ }
final RexExecutable executable = new RexExecutable(code, constExps);
executable.setDataContext(dataContext);
diff --git a/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java
b/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java
index 74c51229f2..b4631eee0b 100644
--- a/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java
+++ b/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java
@@ -402,4 +402,26 @@ class RexExecutorTest {
assertThat(reducedValues.get(1), instanceOf(RexCall.class));
});
}
+
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6168">[CALCITE-6168]
+ * RexExecutor can throw during compilation</a>. */
+ @Test void testCompileTimeException() {
+ check((rexBuilder, executor) -> {
+ final List<RexNode> reducedValues = new ArrayList<>();
+ final RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
+ // CAST(200 as TINYINT)
+ final RelDataType tinyint =
+ typeFactory.createSqlType(SqlTypeName.TINYINT);
+ final RelDataType integer =
+ typeFactory.createSqlType(SqlTypeName.INTEGER);
+ final RexNode cast =
+ rexBuilder.makeCast(tinyint,
+ rexBuilder.makeLiteral(200, integer, true));
+ executor.reduce(rexBuilder, ImmutableList.of(cast),
+ reducedValues);
+ assertThat(reducedValues, hasSize(1));
+ assertThat(reducedValues.get(0), instanceOf(RexCall.class));
+ });
+ }
}
diff --git a/testkit/src/main/java/org/apache/calcite/sql/test/SqlTests.java
b/testkit/src/main/java/org/apache/calcite/sql/test/SqlTests.java
index bb33212d97..7d9a633618 100644
--- a/testkit/src/main/java/org/apache/calcite/sql/test/SqlTests.java
+++ b/testkit/src/main/java/org/apache/calcite/sql/test/SqlTests.java
@@ -265,6 +265,20 @@ public abstract class SqlTests {
}
}
+ // Search for an IllegalStateException somewhere in the stack.
+ // These are thrown by the enumerable implementors when evaluating
+ // an expression that produces an error.
+ IllegalStateException ise = null;
+ for (Throwable x = ex; x != null; x = x.getCause()) {
+ if (x instanceof IllegalStateException) {
+ ise = (IllegalStateException) x;
+ break;
+ }
+ if (x.getCause() == x) {
+ break;
+ }
+ }
+
// Search for a SqlParseException -- with its position set -- somewhere
// in the stack.
SqlParseException spe = null;
@@ -297,6 +311,12 @@ public abstract class SqlTests {
actualException = spe.getCause();
actualMessage = actualException.getMessage();
}
+ } else if (ise != null) {
+ Throwable[] suppressed = ise.getSuppressed();
+ if (suppressed.length > 0) {
+ actualException = suppressed[0];
+ actualMessage = actualException.getMessage();
+ }
} else {
actualMessage = ex.getMessage();
if (ex instanceof NumberFormatException) {