[
https://issues.apache.org/jira/browse/CALCITE-7574?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18085169#comment-18085169
]
leishp edited comment on CALCITE-7574 at 6/1/26 9:28 AM:
---------------------------------------------------------
Hi [~jensen], thanks for the review.
I've simplified the test case to a minimal form. The nesting is unfortunately
necessary to reproduce the issue:
- The outer FROM must be an Aggregate-derived table, so that the correlated
condition references an aggregate result field (t.s = SUM(sal)) rather than a
group field.
- The subquery must contain COUNT to create a second Aggregate node in the
decorrelation plan.
- The correlation condition e.sal > t.s must reference this aggregate result
field.
Removing any of these three conditions makes the bug unreproducible. The
minimal SQL is:
{code:sql}
SELECT t.deptno,
(SELECT COUNT(*) FROM emp e
WHERE e.deptno = t.deptno AND e.sal > t.s)
FROM (SELECT deptno, SUM(sal) AS s FROM emp GROUP BY deptno) t
{code}
I've updated the PR with this minimal test case and also updated the JIRA
description accordingly.
was (Author: JIRAUSER313547):
Hi [~jensen], thanks for the review.
I've simplified the test case to a minimal form. The nesting is unfortunately
necessary to reproduce the issue:
- The outer FROM must be an Aggregate-derived table, so that the correlated
condition references an aggregate result field (t.s = SUM(sal)) rather than a
group field.
- The subquery must contain COUNT(*) to create a second Aggregate node in the
decorrelation plan.
- The correlation condition e.sal > t.s must reference this aggregate result
field.
Removing any of these three conditions makes the bug unreproducible. The
minimal SQL is:
{code:sql}
SELECT t.deptno,
(SELECT COUNT(*) FROM emp e
WHERE e.deptno = t.deptno AND e.sal > t.s)
FROM (SELECT deptno, SUM(sal) AS s FROM emp GROUP BY deptno) t
{code}
I've updated the PR with this minimal test case and also updated the JIRA
description accordingly.
> RelDecorrelator.isFieldNotNullRecursive throws IndexOutOfBoundsException when
> decorrelating correlated scalar subquery with Aggregate
> -------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CALCITE-7574
> URL: https://issues.apache.org/jira/browse/CALCITE-7574
> Project: Calcite
> Issue Type: Bug
> Components: core
> Affects Versions: 1.41.0, 1.42.0
> Reporter: leishp
> Assignee: leishp
> Priority: Major
> Labels: pull-request-available
>
> `RelDecorrelator.isFieldNotNullRecursive` throws `IndexOutOfBoundsException`
> when decorrelating a correlated scalar subquery that involves an Aggregate.
> The bug was introduced in CALCITE-6962 which added the
> `isFieldNotNull`/`isFieldNotNullRecursive` methods.
> h3. Root Cause
> In `RelDecorrelator.isFieldNotNullRecursive`, the Aggregate branch at line
> 3856:
>
> {code:java}
> } else if (rel instanceof Aggregate) {
> Aggregate agg = (Aggregate) rel;
> ImmutableBitSet groupSet = agg.getGroupSet();
> if (index >= groupSet.size())
> { // BUG: should be agg.getGroupCount() return false; }
> return isFieldNotNullRecursive(agg.getInput(),
> groupSet.asList().get(index));
> }
> {code}
>
> - `ImmutableBitSet.size()` returns the bitset {*}{{*}}capacity{{*}}{*}
> (`words.length * 64`), typically 64 or more
> - `groupSet.asList().get(index)` internally calls `nth(index)`, which
> requires `index < cardinality()`
> - `Aggregate.getGroupCount()` returns `groupSet.cardinality()`, the actual
> number of group keys
> When a field index corresponds to an aggregate result field (not a group
> field), the bounds check `index >= groupSet.size()` is too lenient (e.g., `1
> >= 64` is false), allowing execution to proceed to `nth(1)` which throws
> `IndexOutOfBoundsException` because the bitset has only 1 set bit.
> h3. h3. Reproduction SQL
> {code:sql}
> select t.deptno,
> (select count(*) from emp e
> where e.deptno = t.deptno and e.sal > t.s
> )
> from (select deptno, sum(sal) as s
> from emp group by deptno
> ) t{code}
> h3. h3. Exception
> {code:java}
> java.lang.IndexOutOfBoundsException: index out of range: 1
> at org.apache.calcite.util.ImmutableBitSet.nth(ImmutableBitSet.java:903)
> at org.apache.calcite.util.ImmutableBitSet$2.get(ImmutableBitSet.java:681)
> at org.apache.calcite.util.ImmutableBitSet$2.get(ImmutableBitSet.java:679)
> at
> org.apache.calcite.sql2rel.RelDecorrelator.isFieldNotNullRecursive(RelDecorrelator.java:3859)
> at
> org.apache.calcite.sql2rel.RelDecorrelator.isFieldNotNullRecursive(RelDecorrelator.java:3851)
> at
> org.apache.calcite.sql2rel.RelDecorrelator.isFieldNotNullRecursive(RelDecorrelator.java:3859)
> at
> org.apache.calcite.sql2rel.RelDecorrelator.isFieldNotNullRecursive(RelDecorrelator.java:3872)
> at
> org.apache.calcite.sql2rel.RelDecorrelator.isFieldNotNullRecursive(RelDecorrelator.java:3851)
> at
> org.apache.calcite.sql2rel.RelDecorrelator.isFieldNotNull(RelDecorrelator.java:3840)
> at
> org.apache.calcite.sql2rel.RelDecorrelator.decorrelateRel(RelDecorrelator.java:1902)
> ...
> {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)