Skip to content

Commit 3682fa3

Browse files
craig[bot]yuzefovich
andcommitted
Merge #151563
151563: sql: fix "rows affected" for deleteRange with multiple column families r=yuzefovich a=yuzefovich In 807c1f2 we began paginating DelRange requests that are used by the deleteRangeNode. Namely, we now delete at most 600 keys via a single BatchRequest. That change introduced a minor bug that when we have multiple column families AND the pagination stops in the middle of a SQL row, then we would count that row twice for the purposes of "rows affected" counter. This bug is now fixed by maintaining the row prefix across BatchRequests. Fixes: #151505. Release note (bug fix): CockroachDB could previously elevate the number of rows deleted on table with multiple column families in some cases. The bug has been present since 19.2 version and is now fixed. Note that the data was deleted correctly, just "rows affected" number was wrong. Co-authored-by: Yahor Yuzefovich <[email protected]>
2 parents 2328e64 + 59a28ec commit 3682fa3

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

pkg/sql/delete_range.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ type deleteRangeNode struct {
4747

4848
// rowCount will be set to the count of rows deleted.
4949
rowCount int
50+
51+
// curRowPrefix is the prefix for all KVs (i.e. for all column families) of
52+
// the SQL row that increased rowCount last. It is maintained across
53+
// different BatchRequests in order to not double count the same SQL row.
54+
curRowPrefix []byte
5055
}
5156

5257
var _ planNode = &deleteRangeNode{}
@@ -194,10 +199,12 @@ func (d *deleteRangeNode) processResults(
194199
results []kv.Result, resumeSpans []roachpb.Span,
195200
) (roachpb.Spans, error) {
196201
for _, r := range results {
197-
var prev []byte
202+
// TODO(yuzefovich): when the table has 1 column family, we don't need
203+
// to compare the key prefixes since each deleted key corresponds to a
204+
// different deleted row.
198205
for _, keyBytes := range r.Keys {
199206
// If prefix is same, don't bother decoding key.
200-
if len(prev) > 0 && bytes.HasPrefix(keyBytes, prev) {
207+
if len(d.curRowPrefix) > 0 && bytes.HasPrefix(keyBytes, d.curRowPrefix) {
201208
continue
202209
}
203210

@@ -206,8 +213,8 @@ func (d *deleteRangeNode) processResults(
206213
return nil, err
207214
}
208215
k := keyBytes[:len(keyBytes)-len(after)]
209-
if !bytes.Equal(k, prev) {
210-
prev = k
216+
if !bytes.Equal(k, d.curRowPrefix) {
217+
d.curRowPrefix = k
211218
d.rowCount++
212219
}
213220
}

pkg/sql/logictest/testdata/logic_test/delete

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,3 +603,24 @@ statement error pgcode 42803 sum\(\): aggregate functions are not allowed in ORD
603603
DELETE FROM t108166 ORDER BY COALESCE(sum(a), 1) LIMIT 1;
604604

605605
subtest end
606+
607+
# Regression test for double-counting some rows for "rows affected" statistic in
608+
# deleteRange when a single SQL row is deleted via different KV batches.
609+
subtest regression_151505
610+
611+
statement ok
612+
CREATE TABLE t (
613+
k INT PRIMARY KEY,
614+
c INT,
615+
FAMILY (k),
616+
FAMILY (c)
617+
);
618+
619+
statement ok
620+
INSERT INTO t SELECT i, NULL FROM generate_series(1, 599) AS g(i);
621+
INSERT INTO t VALUES (600, 2);
622+
623+
statement count 600
624+
DELETE FROM t WHERE k > 0 AND k < 1000;
625+
626+
subtest end

0 commit comments

Comments
 (0)