Summary
- Location:
src/query/service/src/pipelines/processors/transforms/range_join/ie_join_state.rs:483
- Panic message:
index out of bounds: the len is 0 but the index is 0
Likely trigger files
DuckDB source: test/sql/join/iejoin/iejoin_issue_6861.test
Converted file: sql/join/iejoin/iejoin_issue_6861.test
This file has an active query on an empty table with a BETWEEN range join:
CREATE TABLE test(x INT);
-- table is empty at this point
SELECT * FROM test AS a, test AS b WHERE (a.x BETWEEN b.x AND b.x);
Other iejoin files with gate=fail may also trigger this:
test/sql/join/iejoin/iejoin_issue_7278.test
test/sql/join/iejoin/test_iejoin_null_keys.test (LEFT JOIN with inequality, nullable output)
test/sql/join/iejoin/test_iejoin_east_west.test
Reproduction
The call chain is:
TransformRangeJoinLeft::process (transform_range_join.rs:138)
→ RangeJoinState::ie_join (ie_join_state.rs:183)
→ RangeJoinState::fill_outer (ie_join_state.rs:483) ← PANIC
Triggered by a range join (inequality join) query where one side produces zero rows. The fill_outer method indexes into an empty Vec<DataBlock> at position 0.
Key stack frames
| # |
Function |
File |
| 14 |
RangeJoinState::fill_outer |
ie_join_state.rs:483 |
| 15 |
RangeJoinState::ie_join |
ie_join_state.rs:183 |
| 16 |
TransformRangeJoinLeft::process |
transform_range_join.rs:138 |
Root cause
fill_outer does self.xxx[0] without checking if the vec is empty. Empty input is a valid edge case for outer joins.
Fix direction
Guard the index access with an emptiness check, or return an empty DataBlock directly when input is empty.
Summary
src/query/service/src/pipelines/processors/transforms/range_join/ie_join_state.rs:483index out of bounds: the len is 0 but the index is 0Likely trigger files
DuckDB source:
test/sql/join/iejoin/iejoin_issue_6861.testConverted file:
sql/join/iejoin/iejoin_issue_6861.testThis file has an active query on an empty table with a BETWEEN range join:
Other iejoin files with
gate=failmay also trigger this:test/sql/join/iejoin/iejoin_issue_7278.testtest/sql/join/iejoin/test_iejoin_null_keys.test(LEFT JOIN with inequality, nullable output)test/sql/join/iejoin/test_iejoin_east_west.testReproduction
The call chain is:
Triggered by a range join (inequality join) query where one side produces zero rows. The
fill_outermethod indexes into an emptyVec<DataBlock>at position 0.Key stack frames
RangeJoinState::fill_outerie_join_state.rs:483RangeJoinState::ie_joinie_join_state.rs:183TransformRangeJoinLeft::processtransform_range_join.rs:138Root cause
fill_outerdoesself.xxx[0]without checking if the vec is empty. Empty input is a valid edge case for outer joins.Fix direction
Guard the index access with an emptiness check, or return an empty DataBlock directly when input is empty.