Skip to content

Commit

Permalink
partitionccl: do not generate subzone spans for dropped tables
Browse files Browse the repository at this point in the history
This commit fixes a hazard posed by tables partitioned by user-defined types.
The bug being fixed involves code running in an index GC job which attempts
to re-write zone configs on a dropped table which was partitioned by a
now-dropped user-defined type. Before this change, we'd attempt to generate
subzone spans which we might not know how to populate.

Release note (bug fix): Fixed a bug from earlier alphas in 21.1 whereby
dropping an index on a table partitioned by a user-defined type and then
dropping the table and then dropping the type before the GC TTL for the
index has expired can result in a crash.
  • Loading branch information
ajwerner committed Mar 25, 2021
1 parent 2300690 commit 3f58646
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
53 changes: 53 additions & 0 deletions pkg/ccl/partitionccl/drop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,57 @@ SELECT job_id

waitForJobDone(t, tdb, "GC for DROP INDEX%idx")
})

// This is a regression test for a hazardous scenario whereby a drop index gc
// job may attempt to rewrite subzone spans for a dropped table which used types
// which no longer exist.
t.Run("drop table and type", func(t *testing.T) {

// Sketch of the test:
//
// * Set up a partitioned table and index which are partitioned by an enum.
// * Set a short GC TTL on the index.
// * Drop the index.
// * Drop the table.
// * Drop the type.
// * Wait for the index to be cleaned up, which would have crashed before the
// this fix.
// * Set a short GC TTL on everything.
// * Wait for the table to be cleaned up.
//

defer log.Scope(t).Close(t)
ctx := context.Background()
tc := testcluster.StartTestCluster(t, 1, base.TestClusterArgs{})
defer tc.Stopper().Stop(ctx)

tdb := sqlutils.MakeSQLRunner(tc.ServerConn(0))

tdb.Exec(t, `
CREATE TYPE typ AS ENUM ('a', 'b', 'c');
CREATE TABLE t (e typ PRIMARY KEY) PARTITION BY LIST (e) (
PARTITION a VALUES IN ('a'),
PARTITION b VALUES IN ('b'),
PARTITION c VALUES IN ('c')
);
CREATE INDEX idx
ON t (e)
PARTITION BY LIST (e)
(
PARTITION ai VALUES IN ('a'),
PARTITION bi VALUES IN ('b'),
PARTITION ci VALUES IN ('c')
);
ALTER PARTITION ai OF INDEX t@idx CONFIGURE ZONE USING range_min_bytes = 123456, range_max_bytes = 654321;
ALTER PARTITION a OF TABLE t CONFIGURE ZONE USING range_min_bytes = 123456, range_max_bytes = 654321;
ALTER INDEX t@idx CONFIGURE ZONE USING gc.ttlseconds = 1;
DROP INDEX t@idx;
DROP TABLE t;
DROP TYPE typ;
`)

waitForJobDone(t, tdb, "GC for DROP INDEX%idx")
tdb.Exec(t, `ALTER RANGE default CONFIGURE ZONE USING gc.ttlseconds = 1`)
waitForJobDone(t, tdb, "GC for DROP TABLE%t")
})
}
9 changes: 9 additions & 0 deletions pkg/sql/partition_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ func GenerateSubzoneSpans(
}
}

// We already completely avoid creating subzone spans for dropped indexes.
// Whether this was intentional is a different story, but it turns out to be
// pretty sane. Dropped elements may refer to dropped types and we aren't
// necessarily in a position to deal with those dropped types. Add a special
// case to avoid generating any subzone spans in the face of being dropped.
if tableDesc.Dropped() {
return nil, nil
}

a := &rowenc.DatumAlloc{}

subzoneIndexByIndexID := make(map[descpb.IndexID]int32)
Expand Down

0 comments on commit 3f58646

Please sign in to comment.