Skip to content

Commit

Permalink
backupccl: fix bug when restoring a table with existing UDT
Browse files Browse the repository at this point in the history
This change fixes a nil pointer exception, when restoring tables that
point to existing types. Particularly tables that have column expressions
(computed, default etc) that reference the UDT.

When updating the back references of the existing types in
the restoring cluster, we would index into a map keyed on pre-rewrite
IDs using a post rewrite ID. This change fixes the map to be
keyed on post rewrite IDs.

Informs: #71145

Release note: None
  • Loading branch information
adityamaru authored and dt committed Oct 11, 2021
1 parent 26f11c0 commit 78b2673
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 5 deletions.
23 changes: 23 additions & 0 deletions pkg/ccl/backupccl/backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8759,3 +8759,26 @@ DROP TABLE foo;
defer cleanupEmptyCluster()
sqlDBRestore.Exec(t, "RESTORE FROM $1 AS OF SYSTEM TIME "+aost, LocalFoo)
}

// TestRestoreRemappingOfExistingUDTInColExpr is a regression test for a nil
// pointer exception when restoring tables that point to existing types. When
// updating the back references of the existing types we would index into a map
// keyed on pre-rewrite IDs using a post rewrite ID.
func TestRestoreRemappingOfExistingUDTInColExpr(t *testing.T) {
defer leaktest.AfterTest(t)()
defer log.Scope(t).Close(t)

const numAccounts = 1
_, _, sqlDB, _, cleanupFn := BackupRestoreTestSetup(t, singleNode, numAccounts, InitManualReplication)
defer cleanupFn()

sqlDB.Exec(t, `
CREATE TYPE status AS ENUM ('open', 'closed', 'inactive');
CREATE TABLE foo (id INT PRIMARY KEY, what status default 'open');
BACKUP DATABASE data to 'nodelocal://0/foo';
DROP TABLE foo CASCADE;
DROP TYPE status;
CREATE TYPE status AS ENUM ('open', 'closed', 'inactive');
RESTORE TABLE foo FROM 'nodelocal://0/foo';
`)
}
23 changes: 20 additions & 3 deletions pkg/ccl/backupccl/restore_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -1142,8 +1142,21 @@ func createImportingDescriptors(
}
}

// Assign new IDs to all of the type descriptors that need to be written.
if err := rewriteTypeDescs(typesToWrite, details.DescriptorRewrites); err != nil {
// Perform rewrites on ALL type descriptors that are present in the rewrite
// mapping.
//
// `types` contains a mix of existing type descriptors in the restoring
// cluster, and new type descriptors we will write from the backup.
//
// New type descriptors need to be rewritten with their generated IDs before
// they are written out to disk.
//
// Existing type descriptors need to be rewritten to the type ID of the type
// they are referring to in the restoring cluster. This ID is different from
// the ID the descriptor had when it was backed up. Changes to existing type
// descriptors will not be written to disk, and is only for accurate,
// in-memory resolution hereon out.
if err := rewriteTypeDescs(types, details.DescriptorRewrites); err != nil {
return nil, nil, err
}

Expand Down Expand Up @@ -1316,7 +1329,11 @@ func createImportingDescriptors(
return err
}
typeIDs, _, err := table.GetAllReferencedTypeIDs(dbDesc, func(id descpb.ID) (catalog.TypeDescriptor, error) {
return typesByID[id], nil
t, ok := typesByID[id]
if !ok {
return nil, errors.AssertionFailedf("type with id %d was not found in rewritten type mapping", id)
}
return t, nil
})
if err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions pkg/ccl/backupccl/restore_planning.go
Original file line number Diff line number Diff line change
Expand Up @@ -666,8 +666,8 @@ func allocateDescriptorRewrites(

if parentDB.IsMultiRegion() && table.GetLocalityConfig() != nil {
// We're restoring a table and not its parent database. We may block
// restoring multi-region tables to multi-region databases since regions
// may mismatch.
// restoring multi-region tables to multi-region databases since
// regions may mismatch.
if err := checkMultiRegionCompatible(ctx, txn, p.ExecCfg().Codec, table, parentDB); err != nil {
return pgerror.WithCandidateCode(err, pgcode.FeatureNotSupported)
}
Expand Down

0 comments on commit 78b2673

Please sign in to comment.