diff --git a/core/src/main/java/org/apache/calcite/rex/RexUtil.java b/core/src/main/java/org/apache/calcite/rex/RexUtil.java index cbb8985d092b..d2a95fa51909 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java +++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java @@ -380,7 +380,7 @@ public static boolean isDeterministic(RexNode e) { if (!call.getOperator().isDeterministic()) { throw Util.FoundOne.NULL; } - return null; + return super.visitCall(call); } }; e.accept(visitor); 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 72a36e265579..8f63e2519386 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexExecutorTest.java @@ -26,7 +26,13 @@ import org.apache.calcite.schema.SchemaPlus; import org.apache.calcite.schema.Schemas; import org.apache.calcite.server.CalciteServerStatement; +import org.apache.calcite.sql.SqlBinaryOperator; +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.fun.SqlMonotonicBinaryOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.type.InferTypes; +import org.apache.calcite.sql.type.OperandTypes; +import org.apache.calcite.sql.type.ReturnTypes; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.tools.Frameworks; import org.apache.calcite.util.NlsString; @@ -213,6 +219,58 @@ public void check(RexBuilder rexBuilder, RexExecutorImpl executor) { }); } + @Test public void testDeterministic1() throws Exception { + check(new Action() { + public void check(RexBuilder rexBuilder, RexExecutorImpl executor) { + final RexNode plus = + rexBuilder.makeCall(SqlStdOperatorTable.PLUS, + rexBuilder.makeExactLiteral(BigDecimal.ONE), + rexBuilder.makeExactLiteral(BigDecimal.ONE)); + assertThat(RexUtil.isDeterministic(plus), equalTo(true)); + } + }); + } + + @Test public void testDeterministic2() throws Exception { + check(new Action() { + public void check(RexBuilder rexBuilder, RexExecutorImpl executor) { + final RexNode plus = + rexBuilder.makeCall(PLUS_RANDOM, + rexBuilder.makeExactLiteral(BigDecimal.ONE), + rexBuilder.makeExactLiteral(BigDecimal.ONE)); + assertThat(RexUtil.isDeterministic(plus), equalTo(false)); + } + }); + } + + @Test public void testDeterministic3() throws Exception { + check(new Action() { + public void check(RexBuilder rexBuilder, RexExecutorImpl executor) { + final RexNode plus = + rexBuilder.makeCall(SqlStdOperatorTable.PLUS, + rexBuilder.makeCall(PLUS_RANDOM, + rexBuilder.makeExactLiteral(BigDecimal.ONE), + rexBuilder.makeExactLiteral(BigDecimal.ONE)), + rexBuilder.makeExactLiteral(BigDecimal.ONE)); + assertThat(RexUtil.isDeterministic(plus), equalTo(false)); + } + }); + } + + private static final SqlBinaryOperator PLUS_RANDOM = + new SqlMonotonicBinaryOperator( + "+", + SqlKind.PLUS, + 40, + true, + ReturnTypes.NULLABLE_SUM, + InferTypes.FIRST_KNOWN, + OperandTypes.PLUS_OPERATOR) { + @Override public boolean isDeterministic() { + return false; + } + }; + /** Test case for * [CALCITE-1009] * SelfPopulatingList is not thread-safe. */