Skip to content

Commit b4dfdc0

Browse files
craig[bot]DrewKimball
andcommitted
105931: colexec: don't infinite loop cross-join with zero-column left input r=DrewKimball a=DrewKimball Previously, the cross-joiner wouldn't advance its internal state when its left input projected no columns. This would result in an infinite loop as the right rows were repeatedly emitted. This patch advances the state when there are no left columns as if values from the left side were emitted. Fixes cockroachdb#105882 Release note (bug fix): Fixed a bug introduced in v22.1 that could cause a join to infinite-loop in rare cases when (1) the join filter is not an equality and (2) no columns from the left input are returned. Co-authored-by: Drew Kimball <[email protected]>
2 parents 3c9131b + 72c8fa1 commit b4dfdc0

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

pkg/sql/colexec/colexecjoin/crossjoiner.eg.go

Lines changed: 50 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/sql/colexec/colexecjoin/crossjoiner_tmpl.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,32 @@ func buildFromLeftBatch(b *crossJoinerBase, currentBatch coldata.Batch, sel []in
168168
colexecerror.InternalError(errors.AssertionFailedf("unhandled type %s", b.left.types[colIdx].String()))
169169
}
170170
}
171+
// If there are no columns projected from the left input, simply advance the
172+
// cross-joiner state according to the number of input rows.
173+
if len(b.left.types) == 0 {
174+
outStartIdx := destStartIdx
175+
for bs.curSrcStartIdx < leftSrcEndIdx && outStartIdx < outputCapacity {
176+
// Repeat each row leftNumRepeats times.
177+
// {{/* toAppend will always be positive. */}}
178+
toAppend := leftNumRepeats - bs.numRepeatsIdx
179+
if outStartIdx+toAppend > outputCapacity {
180+
// We don't have enough space to repeat the current
181+
// value the required number of times, so we'll have
182+
// to continue from here on the next call.
183+
toAppend = outputCapacity - outStartIdx
184+
bs.numRepeatsIdx += toAppend
185+
} else {
186+
// We fully processed the current tuple for the
187+
// current column, and before moving on to the next
188+
// one, we need to reset numRepeatsIdx (so that the
189+
// next tuple would be repeated leftNumRepeats
190+
// times).
191+
bs.curSrcStartIdx++
192+
bs.numRepeatsIdx = 0
193+
}
194+
outStartIdx += toAppend
195+
}
196+
}
171197
}
172198

173199
// buildFromLeftInput builds part of the output of a cross join that comes from

pkg/sql/logictest/testdata/logic_test/cross_join

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,18 @@ SELECT *
8181
)
8282
WHERE r < .01
8383
LIMIT 1
84+
85+
# Regression test for #105882 - don't infinite loop when the left input has
86+
# no columns.
87+
statement ok
88+
CREATE TABLE t105882 (c0 INT);
89+
UPSERT INTO t105882 (c0) VALUES(1);
90+
91+
query I
92+
SELECT (
93+
SELECT count(t2.rowid) FROM t105882 t2
94+
WHERE ((t1.rowid) IN (SELECT max(t3.rowid) FROM t105882 t3))
95+
)
96+
FROM t105882 t1;
97+
----
98+
1

0 commit comments

Comments
 (0)