This is an automated email from the ASF dual-hosted git repository.
rubenql 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 d08b5cf73f [CALCITE-5691] IN sub-query inside FILTER clause throws
IndexOutOfBoundsException
d08b5cf73f is described below
commit d08b5cf73f9bb438f282d2089dd92f6d380c0c47
Author: Runkang He <[email protected]>
AuthorDate: Thu May 11 08:59:29 2023 +0800
[CALCITE-5691] IN sub-query inside FILTER clause throws
IndexOutOfBoundsException
---
.../apache/calcite/plan/RelOptPredicateList.java | 10 +++---
.../apache/calcite/test/SqlToRelConverterTest.java | 13 ++++++++
.../apache/calcite/test/SqlToRelConverterTest.xml | 32 ++++++++++++++++++
core/src/test/resources/sql/sub-query.iq | 38 ++++++++++++++++++++++
4 files changed, 89 insertions(+), 4 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/plan/RelOptPredicateList.java
b/core/src/main/java/org/apache/calcite/plan/RelOptPredicateList.java
index 405ac30b91..d6f1de5ce1 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptPredicateList.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptPredicateList.java
@@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableMap;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collection;
+import java.util.List;
import java.util.Objects;
/**
@@ -236,10 +237,11 @@ public class RelOptPredicateList {
if (SqlKind.COMPARISON.contains(e.getKind())) {
// A comparison with a (non-null) literal, such as 'ref < 10', is not
null if 'ref'
// is not null.
- RexCall call = (RexCall) e;
- if (call.getOperands().get(1) instanceof RexLiteral
- && !((RexLiteral) call.getOperands().get(1)).isNull()) {
- return isEffectivelyNotNull(call.getOperands().get(0));
+ List<RexNode> operands = ((RexCall) e).getOperands();
+ // We can have just one operand in case e.g. of a RexSubQuery with IN
operator.
+ if (operands.size() > 1 && operands.get(1) instanceof RexLiteral
+ && !((RexLiteral) operands.get(1)).isNull()) {
+ return isEffectivelyNotNull(operands.get(0));
}
}
return false;
diff --git
a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
index 3d36135ec6..546b222056 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -667,6 +667,13 @@ class SqlToRelConverterTest extends SqlToRelTestBase {
sql(sql).ok();
}
+ @Test void testAggFilterWithInSubQuery() {
+ final String sql = "select\n"
+ + " count(*) filter (where empno in (select deptno from
empnullables))\n"
+ + "from empnullables";
+ sql(sql).withExpand(false).ok();
+ }
+
@Test void testFakeStar() {
sql("SELECT * FROM (VALUES (0, 0)) AS T(A, \"*\")").ok();
}
@@ -4652,6 +4659,12 @@ class SqlToRelConverterTest extends SqlToRelTestBase {
sql(sql).ok();
}
+ @Test void testProjectInSubQueryWithIsTruePredicate() {
+ final String sql = "select deptno in (select deptno from empnullables) is
true\n"
+ + "from empnullables";
+ sql(sql).withExpand(false).ok();
+ }
+
@Test void testProjectAggregatesIgnoreNullsAndNot() {
final String sql = "select lead(sal, 4) IGNORE NULLS, lead(sal, 4) over
(w)\n"
+ "from emp window w as (order by empno)";
diff --git
a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index d1581c2922..68aeb4885c 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -86,6 +86,23 @@ group by deptno]]>
LogicalAggregate(group=[{0}], EXPR$1=[SUM($1) FILTER $2], EXPR$2=[COUNT()])
LogicalProject(DEPTNO=[$7], $f1=[*($5, 2)], $f2=[SEARCH($0, Sarg[(-∞..1),
(1..2), (2..+∞)])])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testAggFilterWithInSubQuery">
+ <Resource name="sql">
+ <![CDATA[select
+ count(*) filter (where empno in (select deptno from empnullables))
+from empnullables]]>
+ </Resource>
+ <Resource name="plan">
+ <![CDATA[
+LogicalAggregate(group=[{}], EXPR$0=[COUNT() FILTER $0])
+ LogicalProject($f0=[IS TRUE(IN($0, {
+LogicalProject(DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMPNULLABLES]])
+}))])
+ LogicalTableScan(table=[[CATALOG, SALES, EMPNULLABLES]])
]]>
</Resource>
</TestCase>
@@ -5871,6 +5888,21 @@ GROUP BY empno]]>
LogicalAggregate(group=[{0}], EXPR$1=[COUNT(DISTINCT $1)],
EXPR$2=[COUNT(APPROXIMATE DISTINCT $1)])
LogicalProject(EMPNO=[$0], ENAME=[$1])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testProjectInSubQueryWithIsTruePredicate">
+ <Resource name="sql">
+ <![CDATA[select deptno in (select deptno from empnullables) is true
+from empnullables]]>
+ </Resource>
+ <Resource name="plan">
+ <![CDATA[
+LogicalProject(EXPR$0=[IS TRUE(IN($7, {
+LogicalProject(DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMPNULLABLES]])
+}))])
+ LogicalTableScan(table=[[CATALOG, SALES, EMPNULLABLES]])
]]>
</Resource>
</TestCase>
diff --git a/core/src/test/resources/sql/sub-query.iq
b/core/src/test/resources/sql/sub-query.iq
index 1cd28283c9..007e52cce0 100644
--- a/core/src/test/resources/sql/sub-query.iq
+++ b/core/src/test/resources/sql/sub-query.iq
@@ -3573,4 +3573,42 @@ or 20 in (
!ok
+# Test case for [CALCITE-5691] IN sub-query inside FILTER clause throws
IndexOutOfBoundsException
+select
+ count(*) filter (where empno in (select deptno from emp))
+from emp;
++--------+
+| EXPR$0 |
++--------+
+| 0 |
++--------+
+(1 row)
+
+!ok
+
+# Test case for [CALCITE-5691] IN sub-query inside FILTER clause throws
IndexOutOfBoundsException
+select deptno in (select deptno from emp) is true
+from emp;
++--------+
+| EXPR$0 |
++--------+
+| true |
+| true |
+| true |
+| true |
+| true |
+| true |
+| true |
+| true |
+| true |
+| true |
+| true |
+| true |
+| true |
+| true |
++--------+
+(14 rows)
+
+!ok
+
# End sub-query.iq