blob: 15af4998a5cfda84a7c787ab80d301fe07bc7a49 [file]
package backup
/*
* This file contains structs and functions related to backing up type
* metadata on the coordinator that needs to be restored before data is restored.
*/
import (
"fmt"
"strings"
"github.com/apache/cloudberry-backup/toc"
"github.com/apache/cloudberry-backup/utils"
"github.com/apache/cloudberry-go-libs/gplog"
"github.com/pkg/errors"
)
/*
* Functions to print to the predata file
*/
func PrintCreateShellTypeStatements(metadataFile *utils.FileWithByteCount, tocfile *toc.TOC, shellTypes []ShellType, baseTypes []BaseType, rangeTypes []RangeType) {
metadataFile.MustPrintf("\n\n")
types := make([]toc.TOCObjectWithMetadata, 0)
for _, shellType := range shellTypes {
types = append(types, toc.TOCObjectWithMetadata(shellType))
}
for _, baseType := range baseTypes {
types = append(types, toc.TOCObjectWithMetadata(baseType))
}
for _, rangeType := range rangeTypes {
types = append(types, toc.TOCObjectWithMetadata(rangeType))
}
for _, typ := range types {
start := metadataFile.ByteCount
metadataFile.MustPrintf("CREATE TYPE %s;\n", typ.FQN())
section, entry := typ.GetMetadataEntry()
tocfile.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
}
}
func PrintCreateDomainStatement(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, domain Domain, typeMetadata ObjectMetadata, constraints []Constraint) {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\nCREATE DOMAIN %s AS %s", domain.FQN(), domain.BaseType)
if domain.DefaultVal != "" {
metadataFile.MustPrintf(" DEFAULT %s", domain.DefaultVal)
}
if domain.Collation != "" {
metadataFile.MustPrintf(" COLLATE %s", domain.Collation)
}
if domain.NotNull {
metadataFile.MustPrintf(" NOT NULL")
}
for _, constraint := range constraints {
metadataFile.MustPrintf("\n\tCONSTRAINT %s %s", constraint.Name, constraint.Def.String)
}
metadataFile.MustPrintln(";")
section, entry := domain.GetMetadataEntry()
tier := globalTierMap[domain.GetUniqueID()]
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, tier)
PrintObjectMetadata(metadataFile, objToc, typeMetadata, domain, "", tier)
}
func PrintCreateBaseTypeStatement(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, base BaseType, typeMetadata ObjectMetadata) {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\n\nCREATE TYPE %s (\n", base.FQN())
// All of the following functions are stored in quoted form and don't need to be quoted again
metadataFile.MustPrintf("\tINPUT = %s,\n\tOUTPUT = %s", base.Input, base.Output)
if base.Receive != "" {
metadataFile.MustPrintf(",\n\tRECEIVE = %s", base.Receive)
}
if base.Send != "" {
metadataFile.MustPrintf(",\n\tSEND = %s", base.Send)
}
if base.ModIn != "" {
metadataFile.MustPrintf(",\n\tTYPMOD_IN = %s", base.ModIn)
}
if base.ModOut != "" {
metadataFile.MustPrintf(",\n\tTYPMOD_OUT = %s", base.ModOut)
}
if base.InternalLength > 0 {
metadataFile.MustPrintf(",\n\tINTERNALLENGTH = %d", base.InternalLength)
}
if base.IsPassedByValue {
metadataFile.MustPrintf(",\n\tPASSEDBYVALUE")
}
if base.Alignment != "" {
switch base.Alignment {
case "d":
metadataFile.MustPrintf(",\n\tALIGNMENT = double")
case "i":
metadataFile.MustPrintf(",\n\tALIGNMENT = int4")
case "s":
metadataFile.MustPrintf(",\n\tALIGNMENT = int2")
case "c": // Default case, don't print anything else
}
}
if base.Storage != "" {
switch base.Storage {
case "e":
metadataFile.MustPrintf(",\n\tSTORAGE = external")
case "m":
metadataFile.MustPrintf(",\n\tSTORAGE = main")
case "x":
metadataFile.MustPrintf(",\n\tSTORAGE = extended")
case "p": // Default case, don't print anything else
}
}
if base.DefaultVal != "" {
metadataFile.MustPrintf(",\n\tDEFAULT = '%s'", base.DefaultVal)
}
if base.Element != "" {
metadataFile.MustPrintf(",\n\tELEMENT = %s", base.Element)
}
if base.Subscript != "" {
metadataFile.MustPrintf(",\n\tSUBSCRIPT = %s", base.Subscript)
}
if base.Delimiter != "" {
metadataFile.MustPrintf(",\n\tDELIMITER = '%s'", base.Delimiter)
}
if base.Category != "U" {
metadataFile.MustPrintf(",\n\tCATEGORY = '%s'", base.Category)
}
if base.Preferred {
metadataFile.MustPrintf(",\n\tPREFERRED = true")
}
if base.Collatable {
metadataFile.MustPrintf(",\n\tCOLLATABLE = true")
}
metadataFile.MustPrintln("\n);")
if base.StorageOptions != "" {
metadataFile.MustPrintf("\nALTER TYPE %s\n\tSET DEFAULT ENCODING (%s);", base.FQN(), base.StorageOptions)
}
section, entry := base.GetMetadataEntry()
tier := globalTierMap[base.GetUniqueID()]
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, tier)
PrintObjectMetadata(metadataFile, objToc, typeMetadata, base, "", tier)
}
func PrintCreateCompositeTypeStatement(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, composite CompositeType, typeMetadata ObjectMetadata) {
var attributeList []string
for _, att := range composite.Attributes {
collationStr := ""
if att.Collation != "" {
collationStr = fmt.Sprintf(" COLLATE %s", att.Collation)
}
attributeList = append(attributeList, fmt.Sprintf("\t%s %s%s", att.Name, att.Type, collationStr))
}
start := metadataFile.ByteCount
metadataFile.MustPrintf("\n\nCREATE TYPE %s AS (\n", composite.FQN())
metadataFile.MustPrintln(strings.Join(attributeList, ",\n"))
metadataFile.MustPrintf(");")
section, entry := composite.GetMetadataEntry()
tier := globalTierMap[composite.GetUniqueID()]
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, tier)
printPostCreateCompositeTypeStatement(metadataFile, objToc, composite, typeMetadata, tier)
}
func printPostCreateCompositeTypeStatement(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, composite CompositeType, typeMetadata ObjectMetadata, tier []uint32) {
PrintObjectMetadata(metadataFile, objToc, typeMetadata, composite, "", tier)
statements := make([]string, 0)
for _, att := range composite.Attributes {
if att.Comment != "" {
statements = append(statements, fmt.Sprintf("COMMENT ON COLUMN %s.%s IS %s;", composite.FQN(), att.Name, att.Comment))
}
}
PrintStatements(metadataFile, objToc, composite, statements, tier)
}
func PrintCreateEnumTypeStatements(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, enums []EnumType, typeMetadata MetadataMap) {
for _, enum := range enums {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\n\nCREATE TYPE %s AS ENUM (\n\t%s\n);\n", enum.FQN(), enum.EnumLabels)
section, entry := enum.GetMetadataEntry()
tier := globalTierMap[enum.GetUniqueID()]
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, tier)
PrintObjectMetadata(metadataFile, objToc, typeMetadata[enum.GetUniqueID()], enum, "", tier)
}
}
func PrintCreateRangeTypeStatement(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, rangeType RangeType, typeMetadata ObjectMetadata) {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\n\nCREATE TYPE %s AS RANGE (\n\tSUBTYPE = %s", rangeType.FQN(), rangeType.SubType)
if rangeType.SubTypeOpClass != "" {
metadataFile.MustPrintf(",\n\tSUBTYPE_OPCLASS = %s", rangeType.SubTypeOpClass)
}
if rangeType.Collation != "" {
metadataFile.MustPrintf(",\n\tCOLLATION = %s", rangeType.Collation)
}
if rangeType.Canonical != "" {
metadataFile.MustPrintf(",\n\tCANONICAL = %s", rangeType.Canonical)
}
if rangeType.SubTypeDiff != "" {
metadataFile.MustPrintf(",\n\tSUBTYPE_DIFF = %s", rangeType.SubTypeDiff)
}
metadataFile.MustPrintf("\n);\n")
section, entry := rangeType.GetMetadataEntry()
tier := globalTierMap[rangeType.GetUniqueID()]
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, tier)
PrintObjectMetadata(metadataFile, objToc, typeMetadata, rangeType, "", tier)
}
func PrintCreateCollationStatements(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, collations []Collation, collationMetadata MetadataMap) {
for _, collation := range collations {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\nCREATE COLLATION %s (LC_COLLATE = '%s', LC_CTYPE = '%s'", collation.FQN(), collation.Collate, collation.Ctype)
if collation.Provider != "" {
providerOption := ""
switch collation.Provider {
case "c":
providerOption = "libc"
case "i":
providerOption = "icu"
case "d":
providerOption = "default"
default:
gplog.Fatal(errors.Errorf("Unexpected collation provider: expected 'c|i|d' got '%s'\n", collation.Provider), "")
}
metadataFile.MustPrintf(", PROVIDER = '%s'", providerOption)
}
if collation.IsDeterministic == "f" {
metadataFile.MustPrintf(", DETERMINISTIC = 'false'")
}
metadataFile.MustPrintf(");")
section, entry := collation.GetMetadataEntry()
tier := globalTierMap[collation.GetUniqueID()]
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, tier)
PrintObjectMetadata(metadataFile, objToc, collationMetadata[collation.GetUniqueID()], collation, "", tier)
}
}