blob: ff6e1f7629cdc68f2289ef944e5cda96aed62732 [file]
package backup
/*
* This file contains structs and functions related to backing up "post-data" metadata
* on the coordinator, which is any metadata that needs to be restored after data is
* restored, such as indexes and rules.
*/
import (
"strings"
"github.com/apache/cloudberry-backup/toc"
"github.com/apache/cloudberry-backup/utils"
"github.com/apache/cloudberry-go-libs/gplog"
"github.com/pkg/errors"
)
func PrintCreateIndexStatements(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, indexes []IndexDefinition, indexMetadata MetadataMap) {
for _, index := range indexes {
start := metadataFile.ByteCount
if !index.SupportsConstraint {
section, entry := index.GetMetadataEntry()
metadataFile.MustPrintf("\n\n%s;", index.Def.String)
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
// Start INDEX metadata
entry.ReferenceObject = index.FQN()
entry.ObjectType = "INDEX METADATA"
if index.Tablespace != "" {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\nALTER INDEX %s SET TABLESPACE %s;", index.FQN(), index.Tablespace)
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
}
if index.ParentIndexFQN != "" && ((connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB()) {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\nALTER INDEX %s ATTACH PARTITION %s;", index.ParentIndexFQN, index.FQN())
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
}
tableFQN := utils.MakeFQN(index.OwningSchema, index.OwningTable)
if index.IsClustered {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\nALTER TABLE %s CLUSTER ON %s;", tableFQN, index.Name)
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
}
if index.IsReplicaIdentity {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\nALTER TABLE %s REPLICA IDENTITY USING INDEX %s;", tableFQN, index.Name)
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
}
if index.StatisticsColumns != "" && index.StatisticsValues != "" {
cols := strings.Split(index.StatisticsColumns, ",")
vals := strings.Split(index.StatisticsValues, ",")
if len(cols) != len(vals) {
gplog.Fatal(errors.Errorf("Index StatisticsColumns(%d) and StatisticsValues(%d) count don't match\n", len(cols), len(vals)), "")
}
for i := 0; i < len(cols); i++ {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\nALTER INDEX %s ALTER COLUMN %s SET STATISTICS %s;", index.FQN(), cols[i], vals[i])
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
}
}
}
PrintObjectMetadata(metadataFile, objToc, indexMetadata[index.GetUniqueID()], index, "", []uint32{0, 0})
}
}
func PrintCreateRuleStatements(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, rules []RuleDefinition, ruleMetadata MetadataMap) {
for _, rule := range rules {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\n\n%s", rule.Def.String)
section, entry := rule.GetMetadataEntry()
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
tableFQN := utils.MakeFQN(rule.OwningSchema, rule.OwningTable)
PrintObjectMetadata(metadataFile, objToc, ruleMetadata[rule.GetUniqueID()], rule, tableFQN, []uint32{0, 0})
}
}
func PrintCreateTriggerStatements(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, triggers []TriggerDefinition, triggerMetadata MetadataMap) {
for _, trigger := range triggers {
start := metadataFile.ByteCount
metadataFile.MustPrintf("\n\n%s;", trigger.Def.String)
section, entry := trigger.GetMetadataEntry()
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
tableFQN := utils.MakeFQN(trigger.OwningSchema, trigger.OwningTable)
PrintObjectMetadata(metadataFile, objToc, triggerMetadata[trigger.GetUniqueID()], trigger, tableFQN, []uint32{0, 0})
}
}
func PrintCreateEventTriggerStatements(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, eventTriggers []EventTrigger, eventTriggerMetadata MetadataMap) {
for _, eventTrigger := range eventTriggers {
start := metadataFile.ByteCount
section, entry := eventTrigger.GetMetadataEntry()
metadataFile.MustPrintf("\n\nCREATE EVENT TRIGGER %s\nON %s", eventTrigger.Name, eventTrigger.Event)
if eventTrigger.EventTags != "" {
metadataFile.MustPrintf("\nWHEN TAG IN (%s)", eventTrigger.EventTags)
}
if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() {
metadataFile.MustPrintf("\nEXECUTE FUNCTION %s();", eventTrigger.FunctionName)
} else {
metadataFile.MustPrintf("\nEXECUTE PROCEDURE %s();", eventTrigger.FunctionName)
}
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
// Start EVENT TRIGGER metadata
entry.ReferenceObject = eventTrigger.Name
entry.ObjectType = toc.OBJ_EVENT_TRIGGER + " METADATA"
if eventTrigger.Enabled != "O" {
var enableOption string
switch eventTrigger.Enabled {
case "D":
enableOption = "DISABLE"
case "A":
enableOption = "ENABLE ALWAYS"
case "R":
enableOption = "ENABLE REPLICA"
default:
enableOption = "ENABLE"
}
start := metadataFile.ByteCount
metadataFile.MustPrintf("\nALTER EVENT TRIGGER %s %s;", eventTrigger.Name, enableOption)
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
}
PrintObjectMetadata(metadataFile, objToc, eventTriggerMetadata[eventTrigger.GetUniqueID()], eventTrigger, "", []uint32{0, 0})
}
}
func PrintCreatePolicyStatements(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, policies []RLSPolicy, policyMetadata MetadataMap) {
for _, policy := range policies {
start := metadataFile.ByteCount
section, entry := policy.GetMetadataEntry()
tableFQN := utils.MakeFQN(policy.Schema, policy.Table)
metadataFile.MustPrintf("\n\nALTER TABLE %s ENABLE ROW LEVEL SECURITY;", tableFQN)
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
permissiveOption := ""
if policy.Permissive == "false" {
permissiveOption = " AS RESTRICTIVE"
}
cmdOption := ""
if policy.Cmd != "" {
switch policy.Cmd {
case "*":
cmdOption = ""
case "r":
cmdOption = " FOR SELECT"
case "a":
cmdOption = " FOR INSERT"
case "w":
cmdOption = " FOR UPDATE"
case "d":
cmdOption = " FOR DELETE"
default:
gplog.Fatal(errors.Errorf("Unexpected policy command: expected '*|r|a|w|d' got '%s'\n", policy.Cmd), "")
}
}
start = metadataFile.ByteCount
metadataFile.MustPrintf("\nCREATE POLICY %s\nON %s%s%s", policy.Name, tableFQN, permissiveOption, cmdOption)
if policy.Roles != "" {
metadataFile.MustPrintf("\n TO %s", policy.Roles)
}
if policy.Qual != "" {
metadataFile.MustPrintf("\n USING (%s)", policy.Qual)
}
if policy.WithCheck != "" {
metadataFile.MustPrintf("\n WITH CHECK (%s)", policy.WithCheck)
}
metadataFile.MustPrintf(";\n")
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
PrintObjectMetadata(metadataFile, objToc, policyMetadata[policy.GetUniqueID()], policy, "", []uint32{0, 0})
}
}
func PrintCreateExtendedStatistics(metadataFile *utils.FileWithByteCount, objToc *toc.TOC, statExtObjects []StatisticExt, statMetadata MetadataMap) {
for _, stat := range statExtObjects {
start := metadataFile.ByteCount
metadataFile.MustPrintln()
metadataFile.MustPrintf("\n%s;", stat.Definition)
section, entry := stat.GetMetadataEntry()
objToc.AddMetadataEntry(section, entry, start, metadataFile.ByteCount, []uint32{0, 0})
PrintObjectMetadata(metadataFile, objToc, statMetadata[stat.GetUniqueID()], stat, "", []uint32{0, 0})
}
}