Skip to content

Commit

Permalink
Create GPDB 7+ root partition
Browse files Browse the repository at this point in the history
In GPDB 7+, we no longer have large DDL commands to create a partition
table. The root partition must be constructed by itself first.
Information for the root partition can be found in the new
pg_partitioned_table catalog table and the partition key available from
using new pg_get_partkeydef() catalog function. Essentially, we just
need to get the partition key definition and attach it to the CREATE
TABLE statement.

Authored-by: Kevin Yeap <kyeap@vmware.com>
  • Loading branch information
kyeap-vmware authored and AJR-VMware committed Nov 22, 2022
1 parent ea1c002 commit ec770a6
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 0 deletions.
3 changes: 3 additions & 0 deletions backup/predata_relations.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ func PrintRegularTableCreateStatement(metadataFile *utils.FileWithByteCount, toc

printColumnDefinitions(metadataFile, table.ColumnDefs, table.TableType)
metadataFile.MustPrintf(") ")
if table.PartitionKeyDef != "" {
metadataFile.MustPrintf("PARTITION BY %s ", table.PartitionKeyDef)
}
if len(table.Inherits) != 0 {
dependencyList := strings.Join(table.Inherits, ", ")
metadataFile.MustPrintf("INHERITS (%s) ", dependencyList)
Expand Down
9 changes: 9 additions & 0 deletions backup/predata_relations_tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,15 @@ ALTER TABLE ONLY public.tablename ALTER COLUMN i SET (n_distinct=1);`)
j character varying(20)
) WITH (appendonly=true, orientation=column, fillfactor=42, compresstype=zlib, blocksize=32768, compresslevel=1) DISTRIBUTED BY (i, j);`)
})
It("is a GPDB 7+ root partition", func() {
testutils.SkipIfBefore7(connectionPool)
testTable.PartitionKeyDef = "RANGE (b)"
backup.PrintRegularTableCreateStatement(backupfile, tocfile, testTable)
testutils.AssertBufferContents(tocfile.PredataEntries, buffer, `CREATE TABLE public.tablename (
i integer,
j character varying(20)
) PARTITION BY RANGE (b) DISTRIBUTED RANDOMLY;`)
})
})
Context("Table partitioning", func() {
col := []backup.ColumnDefinition{rowOne, rowTwo}
Expand Down
29 changes: 29 additions & 0 deletions backup/queries_table_defs.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type TableDefinition struct {
ReplicaIdentity string
PartitionAlteredSchemas []AlteredPartitionRelation
AccessMethodName string
PartitionKeyDef string
}

/*
Expand All @@ -97,6 +98,7 @@ func ConstructDefinitionsForTables(connectionPool *dbconn.DBConn, tableRelations
inheritanceMap := GetTableInheritance(connectionPool, tableRelations)
replicaIdentityMap := GetTableReplicaIdentity(connectionPool)
partitionAlteredSchemaMap := GetPartitionAlteredSchema(connectionPool)
partitionKeyDefs := GetPartitionKeyDefs(connectionPool)

gplog.Verbose("Constructing table definition map")
for _, tableRel := range tableRelations {
Expand All @@ -118,6 +120,7 @@ func ConstructDefinitionsForTables(connectionPool *dbconn.DBConn, tableRelations
ReplicaIdentity: replicaIdentityMap[oid],
PartitionAlteredSchemas: partitionAlteredSchemaMap[oid],
AccessMethodName: accessMethodMap[oid],
PartitionKeyDef: partitionKeyDefs[oid],
}
if tableDef.Inherits == nil {
tableDef.Inherits = []string{}
Expand Down Expand Up @@ -555,6 +558,32 @@ func GetTableInheritance(connectionPool *dbconn.DBConn, tables []Relation) map[u
return resultMap
}

// Used to contruct root tables for GPDB 7+, because the root partition must be
// constructed by itself first.
func GetPartitionKeyDefs(connectionPool *dbconn.DBConn) map[uint32]string {
if connectionPool.Version.Before("7") {
return make(map[uint32]string, 0)
}
query := `
SELECT
partrelid AS oid,
pg_get_partkeydef(partrelid) AS keydef
FROM
pg_partitioned_table;`

var results []struct {
Oid uint32
Keydef string
}
err := connectionPool.Select(&results, query)
gplog.FatalOnError(err)
resultMap := make(map[uint32]string)
for _, result := range results {
resultMap[result.Oid] = result.Keydef
}
return resultMap
}

func selectAsOidToStringMap(connectionPool *dbconn.DBConn, query string) map[uint32]string {
var results []struct {
Oid uint32
Expand Down
16 changes: 16 additions & 0 deletions integration/predata_relations_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,22 @@ SET SUBPARTITION TEMPLATE ` + `
structmatcher.ExpectStructsToMatchExcluding(testTable.TableDefinition, resultTable.TableDefinition, "ColumnDefs.Oid", "ExtTableDef")

})
It("creates a GPDB 7+ root table", func() {
testTable.PartitionKeyDef = "RANGE (b)"
rowOne := backup.ColumnDefinition{Oid: 0, Num: 1, Name: "a", NotNull: false, HasDefault: false, Type: "int", Encoding: "", StatTarget: -1, StorageType: "", DefaultVal: "", Comment: ""}
rowTwo := backup.ColumnDefinition{Oid: 0, Num: 2, Name: "b", NotNull: false, HasDefault: false, Type: "int", Encoding: "", StatTarget: -1, StorageType: "", DefaultVal: "", Comment: ""}
testTable.ColumnDefs = []backup.ColumnDefinition{rowOne, rowTwo}

backup.PrintRegularTableCreateStatement(backupfile, tocfile, testTable)

fmt.Println(buffer.String())
testhelper.AssertQueryRuns(connectionPool, buffer.String())

testTable.PartitionLevelInfo.Oid = testutils.OidFromObjectName(connectionPool, "public", "testtable", backup.TYPE_RELATION)
testTable.Oid = testutils.OidFromObjectName(connectionPool, "public", "testtable", backup.TYPE_RELATION)
resultTable := backup.ConstructDefinitionsForTables(connectionPool, []backup.Relation{testTable.Relation})[0]
structmatcher.ExpectStructsToMatchExcluding(testTable.TableDefinition, resultTable.TableDefinition, "ColumnDefs.Oid", "ExtTableDef")
})
It("creates a table with a non-default tablespace", func() {
if connectionPool.Version.Before("6") {
testhelper.AssertQueryRuns(connectionPool, "CREATE TABLESPACE test_tablespace FILESPACE test_dir")
Expand Down

0 comments on commit ec770a6

Please sign in to comment.