blob: 1a8be23d7b37d77534c46bbf09de6302ac81160f [file]
package toc_test
import (
"bytes"
"testing"
"github.com/apache/cloudberry-backup/testutils"
"github.com/apache/cloudberry-backup/toc"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gbytes"
)
var (
buffer *Buffer
tocfile *toc.TOC
)
func TestTOC(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "TOC Suite")
}
var _ = Describe("utils/toc tests", func() {
table1 := toc.StatementWithType{Schema: "schema", Name: "table1", ObjectType: toc.OBJ_TABLE, Statement: "CREATE TABLE schema.table1", Tier: []uint32{0, 0}}
table1Len := uint64(len(table1.Statement))
capsTable := toc.StatementWithType{Schema: "schema", Name: "TABLE_CAPS", ObjectType: toc.OBJ_TABLE, Statement: "CREATE TABLE schema.TABLE_CAPS", Tier: []uint32{0, 0}}
capsTableLen := uint64(len(capsTable.Statement))
table2 := toc.StatementWithType{Schema: "schema2", Name: "table2", ObjectType: toc.OBJ_TABLE, Statement: "CREATE TABLE schema2.table2", Tier: []uint32{0, 0}}
table2Len := uint64(len(table2.Statement))
view := toc.StatementWithType{Schema: "schema", Name: "view", ObjectType: toc.OBJ_VIEW, Statement: "CREATE VIEW schema.view", Tier: []uint32{0, 0}}
viewLen := uint64(len(view.Statement))
matView := toc.StatementWithType{Schema: "schema", Name: "matView", ObjectType: toc.OBJ_MATERIALIZED_VIEW, Statement: "CREATE MATERIALIZED VIEW schema.mat_view", Tier: []uint32{0, 0}}
matViewLen := uint64(len(matView.Statement))
sequence := toc.StatementWithType{Schema: "schema", Name: "sequence", ObjectType: toc.OBJ_SEQUENCE, Statement: "CREATE SEQUENCE schema.sequence START 100", Tier: []uint32{0, 0}}
sequenceLen := uint64(len(sequence.Statement))
index := toc.StatementWithType{Schema: "schema2", Name: "someindex", ObjectType: toc.OBJ_INDEX, Statement: "CREATE INDEX someindex ON schema2.table2(i)", ReferenceObject: "schema2.table2", Tier: []uint32{0, 0}}
indexLen := uint64(len(index.Statement))
BeforeEach(func() {
tocfile, _ = testutils.InitializeTestTOC(buffer, "predata")
})
Describe("GetSQLStatementForObjectTypes", func() {
// Dummy variables to help clarify which arguments are non-empty in a given test
var noInObj, noExObj, noInSchema, noExSchema, noInRelation, noExRelation []string
var metadataFile *bytes.Reader
BeforeEach(func() {
startCount := uint64(0)
endCount := table1Len
tocfile.AddMetadataEntry("predata", toc.MetadataEntry{Schema: "schema", Name: "table1", ObjectType: toc.OBJ_TABLE}, startCount, endCount, []uint32{0, 0})
startCount = endCount
endCount += capsTableLen
tocfile.AddMetadataEntry("predata", toc.MetadataEntry{Schema: "schema", Name: "TABLE_CAPS", ObjectType: toc.OBJ_TABLE}, startCount, endCount, []uint32{0, 0})
startCount = endCount
endCount += table2Len
tocfile.AddMetadataEntry("predata", toc.MetadataEntry{Schema: "schema2", Name: "table2", ObjectType: toc.OBJ_TABLE}, startCount, endCount, []uint32{0, 0})
startCount = endCount
endCount += viewLen
tocfile.AddMetadataEntry("predata", toc.MetadataEntry{Schema: "schema", Name: "view", ObjectType: toc.OBJ_VIEW}, startCount, endCount, []uint32{0, 0})
startCount = endCount
endCount += matViewLen
tocfile.AddMetadataEntry("predata", toc.MetadataEntry{Schema: "schema", Name: "matView", ObjectType: toc.OBJ_MATERIALIZED_VIEW}, startCount, endCount, []uint32{0, 0})
startCount = endCount
endCount += sequenceLen
tocfile.AddMetadataEntry("predata", toc.MetadataEntry{Schema: "schema", Name: "sequence", ObjectType: toc.OBJ_SEQUENCE}, startCount, endCount, []uint32{0, 0})
startCount = endCount
endCount += indexLen
tocfile.AddMetadataEntry("predata", toc.MetadataEntry{Schema: "schema2", Name: "someindex", ObjectType: toc.OBJ_INDEX, ReferenceObject: "schema2.table2"}, startCount, endCount, []uint32{0, 0})
metadataFile = bytes.NewReader([]byte(table1.Statement + capsTable.Statement + table2.Statement + view.Statement + matView.Statement + sequence.Statement + index.Statement))
})
It("returns statement for a single object type", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, []string{toc.OBJ_VIEW}, noExObj, noInSchema, noExSchema, noInRelation, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{view}))
})
It("returns statement for multiple object types", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, []string{toc.OBJ_TABLE, toc.OBJ_VIEW}, noExObj, noInSchema, noExSchema, noInRelation, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{table1, capsTable, table2, view}))
})
It("does not return a statement type listed in the exclude list", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, []string{toc.OBJ_TABLE}, noInSchema, noExSchema, noInRelation, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{view, matView, sequence, index}))
})
It("returns empty statement when no object types are found", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, []string{toc.OBJ_FUNCTION}, noExObj, noInSchema, noExSchema, noInRelation, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{}))
})
It("returns statement for a single object type with matching schema", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, []string{toc.OBJ_TABLE}, noExObj, []string{"schema2"}, noExSchema, noInRelation, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{table2}))
})
It("returns statement for any object type in the include schema", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, []string{"schema"}, noExSchema, noInRelation, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{table1, capsTable, view, matView, sequence}))
})
It("returns statement for any object type not in the exclude schema", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, []string{"schema2"}, noInRelation, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{table1, capsTable, view, matView, sequence}))
})
It("returns statement for a table matching an included table", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, []string{"schema.table1"}, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{table1}))
})
It("returns statement for a table matching an included table in caps", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, []string{"schema.TABLE_CAPS"}, noExRelation)
tableCaps := toc.StatementWithType{Schema: "schema", Name: "TABLE_CAPS", ObjectType: toc.OBJ_TABLE, Statement: "CREATE TABLE schema.TABLE_CAPS", Tier: []uint32{0, 0}}
Expect(statements).To(Equal([]toc.StatementWithType{tableCaps}))
})
It("returns statement for a view matching an included view", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, []string{"schema.view"}, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{view}))
})
It("returns statement for a materialized view matching an included materialized view", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, []string{"schema.matView"}, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{matView}))
})
It("returns no statements for an excluded view, materialized view or sequence", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, noInRelation, []string{"schema.view", "schema.matView", "schema.sequence"})
Expect(statements).To(Equal([]toc.StatementWithType{table1, capsTable, table2, index}))
})
It("returns no statements for a non-relation object with matching name from relation list", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, []string{"schema.someindex"}, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{}))
})
Context("With reference object", func() {
sequenceTable := toc.StatementWithType{Schema: "schema", Name: "sequence_table", ObjectType: toc.OBJ_TABLE,
Statement: "CREATE TABLE schema.sequence_table", Tier: []uint32{0, 0}}
sequenceTableLen := uint64(len(sequenceTable.Statement))
sequenceOwner := toc.StatementWithType{Schema: "schema", Name: "sequence", ObjectType: toc.OBJ_SEQUENCE_OWNER,
Statement: "ALTER SEQUENCE schema.sequence OWNED BY schema.sequence_table", ReferenceObject: "schema.sequence_table", Tier: []uint32{0, 0}}
sequenceOwnerLen := uint64(len(sequenceOwner.Statement))
BeforeEach(func() {
startCount := table1Len + capsTableLen + table2Len + viewLen + matViewLen + sequenceLen + indexLen
endCount := startCount + sequenceTableLen
tocfile.AddMetadataEntry("predata", toc.MetadataEntry{Schema: "schema", Name: "sequence_table", ObjectType: toc.OBJ_TABLE}, startCount, endCount, []uint32{0, 0})
startCount = endCount
endCount += sequenceOwnerLen
tocfile.AddMetadataEntry("predata", toc.MetadataEntry{Schema: "schema", Name: "sequence", ObjectType: toc.OBJ_SEQUENCE_OWNER, ReferenceObject: "schema.sequence_table"}, startCount, endCount, []uint32{0, 0})
metadataFile = bytes.NewReader([]byte(table1.Statement + capsTable.Statement + table2.Statement + view.Statement + matView.Statement + sequence.Statement + index.Statement + sequenceTable.Statement + sequenceOwner.Statement))
})
It("does not return sequence owner statement when owning table is not included", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, []string{"schema.sequence"}, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{sequence}))
})
It("does not return sequence owner statement when sequence is not included", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, []string{"schema.sequence_table"}, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{sequenceTable}))
})
It("returns sequence owner statement when owning table and sequence are both included", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, []string{"schema.sequence_table", "schema.sequence"}, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{sequence, sequenceTable, sequenceOwner}))
})
It("returns statement for non sequence-owners with matching reference object", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, []string{"schema2.table2"}, noExRelation)
Expect(statements).To(Equal([]toc.StatementWithType{table2, index}))
})
It("returns statement for any object type or reference object not matching an excluded table", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, noInRelation, []string{"schema.table1"})
Expect(statements).To(Equal([]toc.StatementWithType{capsTable, table2, view, matView, sequence, index, sequenceTable, sequenceOwner}))
})
It("returns no statements for any object type with reference object matching an excluded table", func() {
statements := tocfile.GetSQLStatementForObjectTypes("predata", metadataFile, noInObj, noExObj, noInSchema, noExSchema, noInRelation, []string{"schema2.table2"})
Expect(statements).To(Equal([]toc.StatementWithType{table1, capsTable, view, matView, sequence, sequenceTable, sequenceOwner}))
})
})
})
Describe("GetDataEntriesMatching", func() {
BeforeEach(func() {
tocfile.AddCoordinatorDataEntry("schema1", "table1", 1, "(i)", 0, "", "", false)
tocfile.AddCoordinatorDataEntry("schema2", "table2", 1, "(i)", 0, "", "", false)
tocfile.AddCoordinatorDataEntry("schema3", "table3", 1, "(i)", 0, "", "", false)
tocfile.AddCoordinatorDataEntry("schema3", "table3_partition1", 1, "(i)", 0, "table3", "", false)
tocfile.AddCoordinatorDataEntry("schema3", "table3_partition2", 1, "(i)", 0, "table3", "", false)
})
Context("Non-empty restore plan", func() {
restorePlanTableFQNs := []string{"schema1.table1", "schema2.table2", "schema3.table3", "schema3.table3_partition1", "schema3.table3_partition2"}
It("returns matching entry on include schema", func() {
includeSchemas := []string{"schema1"}
matchingEntries := tocfile.GetDataEntriesMatching(includeSchemas, []string{},
[]string{}, []string{}, restorePlanTableFQNs)
Expect(matchingEntries).To(Equal(
[]toc.CoordinatorDataEntry{
{Schema: "schema1", Name: "table1", Oid: 1, AttributeString: "(i)"},
},
))
})
It("returns matching entry on exclude schema", func() {
excludeSchemas := []string{"schema2"}
matchingEntries := tocfile.GetDataEntriesMatching([]string{}, excludeSchemas,
[]string{}, []string{}, restorePlanTableFQNs)
Expect(matchingEntries).To(ConsistOf(
[]toc.CoordinatorDataEntry{
{Schema: "schema1", Name: "table1", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3_partition1", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
{Schema: "schema3", Name: "table3_partition2", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
},
))
})
It("returns matching entry on include table", func() {
includeTables := []string{"schema1.table1"}
matchingEntries := tocfile.GetDataEntriesMatching([]string{}, []string{},
includeTables, []string{}, restorePlanTableFQNs)
Expect(matchingEntries).To(Equal(
[]toc.CoordinatorDataEntry{
{Schema: "schema1", Name: "table1", Oid: 1, AttributeString: "(i)"},
},
))
})
It("returns matching entry on exclude table", func() {
excludeTables := []string{"schema2.table2"}
matchingEntries := tocfile.GetDataEntriesMatching([]string{}, []string{},
[]string{}, excludeTables, restorePlanTableFQNs)
Expect(matchingEntries).To(ConsistOf(
[]toc.CoordinatorDataEntry{
{Schema: "schema1", Name: "table1", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3_partition1", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
{Schema: "schema3", Name: "table3_partition2", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
},
))
})
It("returns all entries when not schema-filtered or table-filtered", func() {
matchingEntries := tocfile.GetDataEntriesMatching([]string{}, []string{},
[]string{}, []string{}, restorePlanTableFQNs)
Expect(matchingEntries).To(ConsistOf(
[]toc.CoordinatorDataEntry{
{Schema: "schema1", Name: "table1", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema2", Name: "table2", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3_partition1", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
{Schema: "schema3", Name: "table3_partition2", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
},
))
})
It("returns matching entry and its leaf partitions on include table", func() {
includeTables := []string{"schema3.table3"}
matchingEntries := tocfile.GetDataEntriesMatching([]string{}, []string{},
includeTables, []string{}, restorePlanTableFQNs)
Expect(matchingEntries).To(ConsistOf(
[]toc.CoordinatorDataEntry{
{Schema: "schema3", Name: "table3", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3_partition1", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
{Schema: "schema3", Name: "table3_partition2", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
},
))
})
It("does not return leaf partitions in include tables but not in the restore plan", func() {
includeTables := []string{"schema3.table3"}
customRestorePlanTableFQNs := []string{"schema1.table1", "schema2.table2", "schema3.table3", "schema3.table3_partition1"}
matchingEntries := tocfile.GetDataEntriesMatching([]string{}, []string{},
includeTables, []string{}, customRestorePlanTableFQNs)
Expect(matchingEntries).To(ConsistOf(
[]toc.CoordinatorDataEntry{
{Schema: "schema3", Name: "table3", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3_partition1", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
},
))
})
It("returns matching entry on exclude root partition table", func() {
excludeTables := []string{"schema3.table3"}
matchingEntries := tocfile.GetDataEntriesMatching([]string{}, []string{},
[]string{}, excludeTables, restorePlanTableFQNs)
Expect(matchingEntries).To(Equal(
[]toc.CoordinatorDataEntry{
{Schema: "schema1", Name: "table1", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema2", Name: "table2", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
},
))
})
It("returns matching entry on exclude leaf partition table", func() {
excludeTables := []string{"schema3.table3_partition2"}
matchingEntries := tocfile.GetDataEntriesMatching([]string{}, []string{},
[]string{}, excludeTables, restorePlanTableFQNs)
Expect(matchingEntries).To(Equal(
[]toc.CoordinatorDataEntry{
{Schema: "schema1", Name: "table1", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema2", Name: "table2", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3", Oid: 1, AttributeString: "(i)", PartitionRoot: ""},
{Schema: "schema3", Name: "table3_partition1", Oid: 1, AttributeString: "(i)", PartitionRoot: "table3"},
},
))
})
})
Context("Empty restore plan", func() {
restorePlanTableFQNs := make([]string, 0)
Specify("That there are no matching entries", func() {
matchingEntries := tocfile.GetDataEntriesMatching([]string{}, []string{},
[]string{}, []string{}, restorePlanTableFQNs)
Expect(matchingEntries).To(BeEmpty())
})
})
})
Describe("SubstituteRedirectDatabaseInStatements", func() {
create := toc.StatementWithType{Schema: "", Name: "somedatabase", ObjectType: toc.OBJ_DATABASE, Statement: "CREATE DATABASE somedatabase TEMPLATE template0;\n"}
wrongCreate := toc.StatementWithType{ObjectType: toc.OBJ_TABLE, Statement: "CREATE DATABASE somedatabase;\n"}
encoding := toc.StatementWithType{ObjectType: toc.OBJ_DATABASE, Statement: "CREATE DATABASE somedatabase TEMPLATE template0 ENCODING 'UTF8';\n"}
gucs := toc.StatementWithType{ObjectType: toc.OBJ_DATABASE_GUC, Statement: "ALTER DATABASE somedatabase SET fsync TO off;\n"}
metadata := toc.StatementWithType{ObjectType: toc.OBJ_DATABASE_METADATA, Statement: "ALTER DATABASE somedatabase OWNER TO testrole;\n\nREVOKE ALL ON DATABASE somedatabase FROM public;\nGRANT ALL ON DATABASE somedatabase TO gpadmin;"}
oldSpecial := toc.StatementWithType{ObjectType: toc.OBJ_DATABASE, Statement: `CREATE DATABASE "db-special-chär$" TEMPLATE template0 TABLESPACE test_tablespace;
COMMENT ON DATABASE "db-special-chär$" IS 'this is a database comment';`}
It("can substitute a database name in a CREATE DATABASE statement", func() {
statements := toc.SubstituteRedirectDatabaseInStatements([]toc.StatementWithType{create}, "somedatabase", "newdatabase")
Expect(statements[0].Statement).To(Equal("CREATE DATABASE newdatabase TEMPLATE template0;\n"))
})
It("can substitute a database name in a CREATE DATABASE statement with encoding", func() {
statements := toc.SubstituteRedirectDatabaseInStatements([]toc.StatementWithType{encoding}, "somedatabase", "newdatabase")
Expect(statements[0].Statement).To(Equal("CREATE DATABASE newdatabase TEMPLATE template0 ENCODING 'UTF8';\n"))
})
It("can substitute a database name in an ALTER DATABASE OWNER statement", func() {
statements := toc.SubstituteRedirectDatabaseInStatements([]toc.StatementWithType{metadata}, "somedatabase", "newdatabase")
Expect(statements[0].Statement).To(Equal("ALTER DATABASE newdatabase OWNER TO testrole;\n\nREVOKE ALL ON DATABASE newdatabase FROM public;\nGRANT ALL ON DATABASE newdatabase TO gpadmin;"))
})
It("can substitute a database name in a database GUC statement", func() {
statements := toc.SubstituteRedirectDatabaseInStatements([]toc.StatementWithType{gucs}, "somedatabase", "newdatabase")
Expect(statements[0].Statement).To(Equal("ALTER DATABASE newdatabase SET fsync TO off;\n"))
})
It("can substitute a database name in a database GUC statement", func() {
statements := toc.SubstituteRedirectDatabaseInStatements([]toc.StatementWithType{gucs}, "somedatabase", "newdatabase")
Expect(statements[0].Statement).To(Equal("ALTER DATABASE newdatabase SET fsync TO off;\n"))
})
It("doesn't modify a statement of the wrong type", func() {
statements := toc.SubstituteRedirectDatabaseInStatements([]toc.StatementWithType{wrongCreate}, "somedatabase", "newdatabase")
Expect(statements[0].Statement).To(Equal("CREATE DATABASE somedatabase;\n"))
})
It("can substitute a database name if the old name contained special characters with a tablespace and comment", func() {
statements := toc.SubstituteRedirectDatabaseInStatements([]toc.StatementWithType{oldSpecial}, `"db-special-chär$"`, "newdatabase")
Expect(statements[0].Statement).To(Equal("CREATE DATABASE newdatabase TEMPLATE template0 TABLESPACE test_tablespace;\n\nCOMMENT ON DATABASE newdatabase IS 'this is a database comment';"))
})
It("can substitute a database name if the new name contained special characters", func() {
statements := toc.SubstituteRedirectDatabaseInStatements([]toc.StatementWithType{create}, "somedatabase", `"db-special-chär$"`)
Expect(statements[0].Statement).To(Equal(`CREATE DATABASE "db-special-chär$" TEMPLATE template0;
`))
})
})
Describe("RemoveActiveRoles", func() {
user1 := toc.StatementWithType{Name: "user1", ObjectType: toc.OBJ_ROLE, Statement: "CREATE ROLE user1 SUPERUSER;\n"}
user2 := toc.StatementWithType{Name: "user2", ObjectType: toc.OBJ_ROLE, Statement: "CREATE ROLE user2;\n"}
It("Removes current user from the list of roles to restore", func() {
resultStatements := toc.RemoveActiveRole("user1", []toc.StatementWithType{user1, user2})
Expect(resultStatements).To(Equal([]toc.StatementWithType{user2}))
})
It("Returns the same list if current user is not in it", func() {
resultStatements := toc.RemoveActiveRole("user3", []toc.StatementWithType{user1, user2})
Expect(resultStatements).To(Equal([]toc.StatementWithType{user1, user2}))
})
})
Describe("GetIncludedPartitionRoots", func() {
It("does not return anything if relations are not leaf partitions", func() {
tocfile.AddCoordinatorDataEntry("schema0", "name0", 0, "attribute0", 1, "", "", false)
tocfile.AddCoordinatorDataEntry("schema1", "name1", 1, "attribute0", 1, "", "", false)
roots := toc.GetIncludedPartitionRoots(tocfile.DataEntries, []string{"schema0.name0", "schema1.name1"})
Expect(roots).To(BeEmpty())
})
It("returns root parition of leaf partitions", func() {
tocfile.AddCoordinatorDataEntry("schema0", "name0", 2, "attribute0", 1, "root0", "", false)
tocfile.AddCoordinatorDataEntry("schema1", "name1", 3, "attribute0", 1, "root1", "", false)
roots := toc.GetIncludedPartitionRoots(tocfile.DataEntries, []string{"schema0.name0", "schema1.name1"})
Expect(roots).To(ConsistOf("schema0.root0", "schema1.root1"))
})
It("only returns root partitions of leaf partitions", func() {
tocfile.AddCoordinatorDataEntry("schema0", "name0", 0, "attribute0", 1, "", "", false)
tocfile.AddCoordinatorDataEntry("schema1", "name1", 1, "attribute0", 1, "", "", false)
tocfile.AddCoordinatorDataEntry("schema2", "name2", 2, "attribute0", 1, "root2", "", false)
tocfile.AddCoordinatorDataEntry("schema3", "name3", 3, "attribute0", 1, "root3", "", false)
roots := toc.GetIncludedPartitionRoots(tocfile.DataEntries, []string{"schema2.name2", "schema3.name3"})
Expect(roots).To(ConsistOf("schema2.root2", "schema3.root3"))
})
It("returns nothing if toc data entries are empty", func() {
roots := toc.GetIncludedPartitionRoots(tocfile.DataEntries, []string{"schema2.name2", "schema3.name3"})
Expect(roots).To(BeEmpty())
})
It("returns nothing if relation is not part of TOC data entries", func() {
tocfile.AddCoordinatorDataEntry("schema0", "name0", 0, "attribute0", 1, "", "", false)
tocfile.AddCoordinatorDataEntry("schema1", "name1", 1, "attribute0", 1, "", "", false)
tocfile.AddCoordinatorDataEntry("schema2", "name2", 2, "attribute0", 1, "root2", "", false)
tocfile.AddCoordinatorDataEntry("schema3", "name3", 3, "attribute0", 1, "root3", "", false)
roots := toc.GetIncludedPartitionRoots(tocfile.DataEntries, []string{"schema4.name4", "schema5.name5"})
Expect(roots).To(BeEmpty())
})
It("returns empty if no relations are passed in", func() {
tocfile.AddCoordinatorDataEntry("schema0", "name0", 0, "attribute0", 1, "", "", false)
tocfile.AddCoordinatorDataEntry("schema1", "name1", 1, "attribute0", 1, "", "", false)
tocfile.AddCoordinatorDataEntry("schema2", "name2", 2, "attribute0", 1, "root2", "", false)
tocfile.AddCoordinatorDataEntry("schema3", "name3", 3, "attribute0", 1, "root3", "", false)
roots := toc.GetIncludedPartitionRoots(tocfile.DataEntries, []string{})
Expect(roots).To(BeEmpty())
})
})
})