Skip to content

Commit 9b3b2bc

Browse files
craig[bot]spilchen
andcommitted
Merge #147766
147766: sql: handle dropped schemas in crdb_internal.table_spans r=spilchen a=spilchen Previously, crdb_internal.table_spans returned spans for all tables not yet GC'd, including those from dropped tables. This could cause a lookup failure when trying to resolve the schema descriptor of a dropped schema during virtual table row construction. This change updates the forEachTableDescFromDescriptors helper to tolerate missing schema descriptors if the table is dropped. When the includeDropped flag is set, such tables now return a nil schema descriptor instead of causing an error. Fixes #147717 Epic: none Release note (bug fix): Fixed an error in crdb_internal.table_spans when a table's schema had been dropped. Co-authored-by: Matt Spilchen <[email protected]>
2 parents 52cf477 + 2c1aca5 commit 9b3b2bc

File tree

3 files changed

+34
-11
lines changed

3 files changed

+34
-11
lines changed

pkg/sql/information_schema.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"github.com/cockroachdb/cockroach/pkg/sql/sem/semenumpb"
3535
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
3636
"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
37+
"github.com/cockroachdb/cockroach/pkg/sql/sqlerrors"
3738
"github.com/cockroachdb/cockroach/pkg/sql/types"
3839
"github.com/cockroachdb/cockroach/pkg/sql/vtable"
3940
"github.com/cockroachdb/cockroach/pkg/util/collatedstring"
@@ -2671,10 +2672,6 @@ func forEachTypeDesc(
26712672
if err != nil {
26722673
continue
26732674
}
2674-
sc, err := lCtx.getSchemaByID(typ.GetParentSchemaID())
2675-
if err != nil {
2676-
return err
2677-
}
26782675
canSeeDescriptor, err := userCanSeeDescriptor(
26792676
ctx, p, typ, dbDesc, false /* allowAdding */, false /* includeDropped */)
26802677
if err != nil {
@@ -2683,6 +2680,10 @@ func forEachTypeDesc(
26832680
if !canSeeDescriptor {
26842681
continue
26852682
}
2683+
sc, err := lCtx.getSchemaByID(typ.GetParentSchemaID())
2684+
if err != nil {
2685+
return err
2686+
}
26862687
if err := fn(ctx, dbDesc, sc, typ); err != nil {
26872688
return err
26882689
}
@@ -2809,9 +2810,16 @@ func forEachTableDescFromDescriptors(
28092810
}
28102811
var sc catalog.SchemaDescriptor
28112812
if parentExists {
2812-
sc, err = lCtx.getSchemaByID(table.GetParentSchemaID())
2813-
if err != nil && !table.IsTemporary() {
2814-
return err
2813+
// The schema may not exist if the table is temporary or belongs to a
2814+
// dropped schema. If the schema is dropped and we're configured to
2815+
// tolerate that (includeDropped is true), then the schema descriptor (sc)
2816+
// will intentionally remain nil.
2817+
schemaID := table.GetParentSchemaID()
2818+
if lCtx.hasSchemaWithID(schemaID) {
2819+
sc, err = lCtx.getSchemaByID(schemaID)
2820+
if err != nil {
2821+
return err
2822+
}
28152823
} else if table.IsTemporary() {
28162824
// Look up the schemas for this database if we discover that there is a
28172825
// missing temporary schema name. Temporary schemas have namespace
@@ -2836,6 +2844,8 @@ func forEachTableDescFromDescriptors(
28362844
if sc == nil {
28372845
sc = schemadesc.NewTemporarySchema(catconstants.PgTempSchemaName, table.GetParentSchemaID(), dbDesc.GetID())
28382846
}
2847+
} else if !opts.includeDropped {
2848+
return sqlerrors.NewUndefinedSchemaError(fmt.Sprintf("[%d]", schemaID))
28392849
}
28402850
}
28412851
if err := fn(ctx, tableDescContext{dbDesc, sc, table, lCtx}); err != nil {

pkg/sql/logictest/testdata/logic_test/crdb_internal

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,7 +1675,10 @@ statement ok
16751675
CREATE TABLE foo (a INT PRIMARY KEY, INDEX idx(a)); INSERT INTO foo VALUES(1);
16761676

16771677
statement ok
1678-
CREATE TABLE bar (a INT PRIMARY KEY, INDEX idx(a));
1678+
CREATE SCHEMA droptest;
1679+
1680+
statement ok
1681+
CREATE TABLE droptest.bar (a INT PRIMARY KEY, INDEX idx(a));
16791682

16801683
query TB rowsort
16811684
SELECT name, dropped
@@ -1686,7 +1689,7 @@ foo false
16861689
bar false
16871690

16881691
statement ok
1689-
DROP TABLE bar
1692+
DROP SCHEMA droptest CASCADE
16901693

16911694
query TB rowsort
16921695
SELECT name, dropped
@@ -1744,13 +1747,13 @@ CREATE TYPE other_db.public.enum1 AS ENUM ('yo');
17441747
query ITTITTT
17451748
SELECT * FROM "".crdb_internal.create_type_statements WHERE descriptor_name = 'enum1' and database_name = 'other_db'
17461749
----
1747-
124 other_db public 154 enum1 CREATE TYPE public.enum1 AS ENUM ('yo') {yo}
1750+
124 other_db public 155 enum1 CREATE TYPE public.enum1 AS ENUM ('yo') {yo}
17481751

17491752
# This uses the virtual index. descriptor_id is an int in the vtable.
17501753
query ITTITTT
17511754
SELECT * FROM "".crdb_internal.create_type_statements WHERE descriptor_id = (('other_db.public.enum1'::regtype::int) - 100000)
17521755
----
1753-
124 other_db public 154 enum1 CREATE TYPE public.enum1 AS ENUM ('yo') {yo}
1756+
124 other_db public 155 enum1 CREATE TYPE public.enum1 AS ENUM ('yo') {yo}
17541757

17551758
# Repeat above two queries but apply only for the current database. We do this by omitting the "".
17561759
# This one uses the full table scan.

pkg/sql/resolver.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,16 @@ func (l *internalLookupCtx) getTypeByID(id descpb.ID) (catalog.TypeDescriptor, e
969969
return typ, nil
970970
}
971971

972+
// hasSchemaWithID reports whether a schema with the given ID exists in the
973+
// lookup context.
974+
func (l *internalLookupCtx) hasSchemaWithID(id descpb.ID) bool {
975+
if id == keys.SystemPublicSchemaID {
976+
return true
977+
}
978+
_, ok := l.schemaDescs[id]
979+
return ok
980+
}
981+
972982
func (l *internalLookupCtx) getSchemaByID(id descpb.ID) (catalog.SchemaDescriptor, error) {
973983
sc, ok := l.schemaDescs[id]
974984
if !ok {

0 commit comments

Comments
 (0)