Skip to content

Commit

Permalink
ADBDEV-2901 Fix order of restoring metadata (#23)
Browse files Browse the repository at this point in the history
Initially, gpbackup created consistent copies of databases, ordering
all object by oid, which created a correct sequence of objects. But in
ADBDEV-1973 (#9) the backup order was changed and the objects started to be
sorted by their size, which broke the logic of backup process. This
patch restores ordering by oid, but doesn't break order based on relation
size, because gpbackup stores two different lists of metadata and data
objects. This patch reorders metadata only, so all objects can be correclty
restored, but doesn't alter data objects order, so the data can be recovered
in any desired way.
  • Loading branch information
dnskvlnk authored Aug 24, 2022
1 parent b55652d commit 11da7e0
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 1 deletion.
2 changes: 1 addition & 1 deletion backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,10 @@ func backupPredata(metadataFile *utils.FileWithByteCount, tables []Table, tableO
objects := make([]Sortable, 0)
metadataMap := make(MetadataMap)

objects = append(objects, convertToSortableSlice(tables)...)
if !tableOnly {
functions, funcInfoMap = retrieveFunctions(&objects, metadataMap)
}
objects = append(objects, convertToSortableSlice(tables)...)
relationMetadata := GetMetadataForObjectType(connectionPool, TYPE_RELATION)
addToMetadataMap(relationMetadata, metadataMap)

Expand Down
19 changes: 19 additions & 0 deletions backup/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package backup

import (
"fmt"
"sort"
"strings"

"github.com/greenplum-db/gp-common-go-libs/dbconn"
Expand Down Expand Up @@ -85,6 +86,24 @@ type Sortable interface {
GetUniqueID() UniqueID
}

type Sortables []Sortable

func (s Sortables) Len() int {
return len(s)
}
func (s Sortables) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s Sortables) Less(i, j int) bool {
return s[i].GetUniqueID().Oid < s[j].GetUniqueID().Oid
}

func SortByOid(sortables []Sortable) []Sortable {
s := Sortables(sortables)
sort.Sort(s)
return []Sortable(s)
}

func TopologicalSort(slice []Sortable, dependencies DependencyMap) []Sortable {
inDegrees := make(map[UniqueID]int)
dependencyIndexes := make(map[UniqueID]int)
Expand Down
1 change: 1 addition & 0 deletions backup/wrappers.go
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ func backupDependentObjects(metadataFile *utils.FileWithByteCount, tables []Tabl

gplog.Verbose("Writing CREATE statements for dependent objects to metadata file")

sortables = SortByOid(sortables)
backupSet := createBackupSet(sortables)
relevantDeps := GetDependencies(connectionPool, backupSet)
if connectionPool.Version.Is("4") && !tableOnly {
Expand Down
25 changes: 25 additions & 0 deletions end_to_end/end_to_end_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,31 @@ var _ = Describe("backup and restore end to end tests", func() {

assertArtifactsCleaned(restoreConn, timestamp)
})
It("runs gpbackup and gprestore to backup functions depending on table row's type", func() {
skipIfOldBackupVersionBefore("1.19.0")

testhelper.AssertQueryRuns(backupConn, "CREATE TABLE table_provides_type (n int);")
defer testhelper.AssertQueryRuns(backupConn, "DROP TABLE table_provides_type;")

testhelper.AssertQueryRuns(backupConn, "INSERT INTO table_provides_type values (1);")
testhelper.AssertQueryRuns(backupConn, "CREATE OR REPLACE FUNCTION func_depends_on_row_type(arg table_provides_type[]) RETURNS void AS $$ BEGIN; SELECT NULL; END; $$ LANGUAGE SQL;")

defer testhelper.AssertQueryRuns(backupConn, "DROP FUNCTION func_depends_on_row_type(arg table_provides_type[]);")

timestamp := gpbackup(gpbackupPath, backupHelperPath)
gprestore(gprestorePath, restoreHelperPath, timestamp,
"--redirect-db", "restoredb")

assertRelationsCreated(restoreConn, TOTAL_RELATIONS+1) // for 1 new table
assertDataRestored(restoreConn, schema2TupleCounts)
assertDataRestored(restoreConn, map[string]int{
"public.foo": 40000,
"public.holds": 50000,
"public.sales": 13,
"public.table_provides_type": 1})

assertArtifactsCleaned(restoreConn, timestamp)
})
It("Can restore xml with xmloption set to document", func() {
testutils.SkipIfBefore6(backupConn)
// Set up the XML table that contains XML content
Expand Down

0 comments on commit 11da7e0

Please sign in to comment.