Skip to content

Commit 10cc4df

Browse files
committed
sql/catalog: fix object renames for PCR reader catalogs
Previously, the PCR reader catalog would only delete namespace entries for a descriptor if it was not modified. This meant the reader catalog logic could leave behind stale entries in the system.namespace table after a object was renamed. To address this, this patch detects if an object is renamed, and allows the old namespace entry to be deleted. Fixes: #142828 Release note (bug fix): PCR reader catalogs could have orphan rows in system.namespace after a object is renamed.
1 parent c64db1a commit 10cc4df

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

pkg/sql/catalog/replication/reader_catalog.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ func SetupOrAdvanceStandbyReaderCatalog(
5252
// in the reader tenant, but not in the from tenant which we are
5353
// replicating).
5454
descriptorsUpdated := catalog.DescriptorIDSet{}
55+
descriptorsRenamed := catalog.DescriptorIDSet{}
5556
allExistingDescs, err := txn.Descriptors().GetAll(ctx, txn.KV())
5657
if err != nil {
5758
return err
@@ -112,6 +113,10 @@ func SetupOrAdvanceStandbyReaderCatalog(
112113
if err != nil {
113114
return err
114115
}
116+
// If the descriptor has been renamed then delete the old namespace entry.
117+
if existingDesc != nil && existingDesc.GetName() != fromDesc.GetName() {
118+
descriptorsRenamed.Add(existingDesc.GetID())
119+
}
115120
}
116121
return errors.Wrapf(txn.Descriptors().WriteDescToBatch(ctx, true, mut, b),
117122
"unable to create replicated descriptor: %d %T", mut.GetID(), mut)
@@ -146,9 +151,11 @@ func SetupOrAdvanceStandbyReaderCatalog(
146151
}
147152
// Figure out which namespaces should be deleted.
148153
if err := allExistingDescs.ForEachNamespaceEntry(func(e nstree.NamespaceEntry) error {
149-
// Skip descriptors that were updated above
154+
// Skip descriptors that were updated above that were
155+
// not renamed.
150156
if !shouldSetupForReader(e.GetID(), e.GetParentID()) ||
151-
descriptorsUpdated.Contains(e.GetID()) {
157+
(descriptorsUpdated.Contains(e.GetID()) &&
158+
!descriptorsRenamed.Contains(e.GetID())) {
152159
return nil
153160
}
154161
return errors.Wrapf(txn.Descriptors().DeleteNamespaceEntryToBatch(ctx, true, e, b),

pkg/sql/catalog/replication/reader_catalog_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -196,19 +196,25 @@ INSERT INTO t1(val) VALUES('closed');
196196
INSERT INTO t1(val) VALUES('inactive');
197197
CREATE VIEW v1 AS (SELECT n from t1);
198198
CREATE TABLE t2(n int);
199+
CREATE TABLE t3(n int); -- this will get renamed to t5.
200+
INSERT INTO t3(n) VALUES (1);
201+
INSERT INTO t3(n) VALUES (2);
202+
INSERT INTO t3(n) VALUES (3);
199203
`)
200204
require.NoError(t, r.advanceTS(ctx, r.ts.Clock().Now(), true))
201205

202206
// Validate tables and views match in the catalog reader
203207
r.compareEqual(t, "SELECT * FROM t1 ORDER BY n")
204208
r.compareEqual(t, "SELECT * FROM v1 ORDER BY 1")
205209
r.compareEqual(t, "SELECT * FROM t2 ORDER BY n")
210+
r.compareEqual(t, "SELECT * FROM t3 ORDER BY n")
206211

207212
// Validate that system tables are synced
208213
r.compareEqual(t, "SELECT * FROM system.users")
209214
r.compareEqual(t, "SELECT * FROM system.table_statistics")
210215
r.compareEqual(t, "SELECT * FROM system.role_options")
211216
r.compareEqual(t, "SELECT * FROM system.database_role_settings")
217+
r.compareEqual(t, "SELECT name FROM system.namespace ORDER BY name")
212218

213219
// Validate that sequences can be selected.
214220
r.compareEqual(t, "SELECT * FROM sq1")
@@ -223,6 +229,7 @@ CREATE TABLE t2(n int);
223229
"ALTER USER roacher2 SET timezone='America/New_York';",
224230
"CREATE TABLE t4(n int)",
225231
"INSERT INTO t4 VALUES (32)",
232+
"ALTER TABLE t3 RENAME TO t5",
226233
}
227234
for _, ddl := range ddlToExec {
228235
r.srcRunner.Exec(t, ddl)
@@ -235,6 +242,8 @@ CREATE TABLE t2(n int);
235242
r.compareEqual(t, "SELECT * FROM system.table_statistics")
236243
r.compareEqual(t, "SELECT * FROM system.role_options")
237244
r.compareEqual(t, "SELECT * FROM system.database_role_settings")
245+
r.compareEqual(t, "SELECT * FROM t3 ORDER BY n")
246+
r.compareEqual(t, "SELECT name FROM system.namespace ORDER BY name")
238247

239248
// Move the src timestamp into the future when comparing
240249
// values.
@@ -245,6 +254,7 @@ CREATE TABLE t2(n int);
245254
r.check(t, "SELECT * FROM system.users", false)
246255
r.check(t, "SELECT * FROM system.role_options", false)
247256
r.check(t, "SELECT * FROM system.database_role_settings", false)
257+
r.check(t, "SELECT name FROM system.namespace ORDER BY name", false)
248258

249259
// Move the timestamp up on the reader catalog, and confirm that everything matches.
250260
require.NoError(t, r.advanceTS(ctx, r.srcAOST, true))
@@ -257,6 +267,8 @@ CREATE TABLE t2(n int);
257267
r.compareEqual(t, "SELECT * FROM system.role_options")
258268
r.compareEqual(t, "SELECT * FROM system.database_role_settings")
259269
r.compareEqual(t, "SELECT * FROM t4 ORDER BY n")
270+
r.compareEqual(t, "SELECT * FROM t5 ORDER BY n")
271+
r.compareEqual(t, "SELECT name FROM system.namespace ORDER BY name")
260272

261273
// Validate that sequence operations are blocked.
262274
r.destRunner.ExpectErr(t, "cannot execute nextval\\(\\) in a read-only transaction", "SELECT nextval('sq1')")

0 commit comments

Comments
 (0)