Skip to content

Commit

Permalink
Merge #34804
Browse files Browse the repository at this point in the history
34804: sql: prevent UPDATE from crashing if subquery returns no rows r=knz a=knz

Fixes #32054.

Note: only the heuristic planner was affected. The CBO was handling
this case fine already.

Release note (bug fix): When using `UPDATE SET (a,b)
= (...subquery...)`, CockroachDb will not crash any more if the
subquery returns no rows.

Co-authored-by: Raphael 'kena' Poss <[email protected]>
  • Loading branch information
craig[bot] and knz committed Feb 12, 2019
2 parents ebcc758 + 28beb94 commit b80d241
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
17 changes: 17 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/update
Original file line number Diff line number Diff line change
Expand Up @@ -510,3 +510,20 @@ UPDATE t32477 SET x = rank(x) OVER ()

statement error generator functions are not allowed in UPDATE SET
UPDATE t32477 SET x = generate_series(1,2)

#regression test for #32054
subtest empty_update_subquery

statement ok
CREATE TABLE t32054(x,y) AS SELECT 1,2

statement ok
CREATE TABLE t32054_empty(x INT, y INT)

statement ok
UPDATE t32054 SET (x,y) = (SELECT x,y FROM t32054_empty)

query II
SELECT * FROM t32054
----
NULL NULL
15 changes: 13 additions & 2 deletions pkg/sql/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,15 @@ func (p *planner) Update(

colIdx := render.addOrReuseRender(col, expr, false)

sourceSlots = append(sourceSlots, tupleSlot{
tSlot := tupleSlot{
columns: updateCols[currentUpdateIdx : currentUpdateIdx+len(setExpr.Names)],
emptySlot: make(tree.Datums, len(setExpr.Names)),
sourceIndex: colIdx,
})
}
for i := range tSlot.emptySlot {
tSlot.emptySlot[i] = tree.DNull
}
sourceSlots = append(sourceSlots, tSlot)
currentUpdateIdx += len(setExpr.Names)

default:
Expand Down Expand Up @@ -762,9 +767,15 @@ type sourceSlot interface {
type tupleSlot struct {
columns []sqlbase.ColumnDescriptor
sourceIndex int
// emptySlot is to be returned when the source subquery
// returns no rows.
emptySlot tree.Datums
}

func (ts tupleSlot) extractValues(row tree.Datums) tree.Datums {
if row[ts.sourceIndex] == tree.DNull {
return ts.emptySlot
}
return row[ts.sourceIndex].(*tree.DTuple).D
}

Expand Down

0 comments on commit b80d241

Please sign in to comment.