blob: 5572f54005d4fb500e563882dc86a2861a603e97 [file]
package backup_test
import (
"database/sql"
"database/sql/driver"
"github.com/DATA-DOG/go-sqlmock"
"github.com/apache/cloudberry-backup/backup"
"github.com/apache/cloudberry-go-libs/structmatcher"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("backup/queries_postdata tests", func() {
Describe("GetIndexes", func() {
It("GetIndexes properly handles NULL index definitions", func() {
if connectionPool.Version.IsGPDB() && connectionPool.Version.Before("6") {
implicitIndexNamesHeader := []string{"string"}
implicitIndexNamesFakeRows := sqlmock.NewRows(implicitIndexNamesHeader)
mock.ExpectQuery(`SELECT (.*)`).WillReturnRows(implicitIndexNamesFakeRows)
}
header := []string{"oid", "name", "owningschema", "owningtable", "tablespace", "def", "isclustered", "supportsconstraint", "isreplicaidentity"}
rowOne := []driver.Value{"1", "mock_index", "mock_schema", "mock_table", "mock_tablespace", "mock_def", false, false, false}
rowTwo := []driver.Value{"1", "mock_index2", "mock_schema2", "mock_table2", "mock_tablespace2", nil, false, false, false}
fakeRows := sqlmock.NewRows(header).AddRow(rowOne...).AddRow(rowTwo...)
mock.ExpectQuery(`SELECT (.*)`).WillReturnRows(fakeRows)
result := backup.GetIndexes(connectionPool)
// Expect the GetIndexes function to return only the 1st row since the 2nd row has a NULL index definition
expectedResult := []backup.IndexDefinition{{Oid: 1, Name: "mock_index", OwningSchema: "mock_schema", OwningTable: "mock_table",
Tablespace: "mock_tablespace", Def: sql.NullString{String: "mock_def", Valid: true}, IsClustered: false,
SupportsConstraint: false, IsReplicaIdentity: false}}
Expect(result).To(HaveLen(1))
structmatcher.ExpectStructsToMatch(&expectedResult[0], &result[0])
})
})
Describe("RenameExchangedPartitionIndexes", func() {
It("RenameExchangedPartitionIndexes properly renames exchanged indexes to match their owning tables", func() {
if !(connectionPool.Version.IsGPDB() && connectionPool.Version.Is("6")) {
Skip("Test only applies to GPDB version 6")
}
indexes := []backup.IndexDefinition{
{Oid: 1, Name: "mock_index", OwningSchema: "mock_schema", OwningTable: "mock_table",
Tablespace: "mock_tablespace", Def: sql.NullString{String: "CREATE INDEX mock_index ON mock_schema.mock_table", Valid: true}, IsClustered: false,
SupportsConstraint: false, IsReplicaIdentity: false},
{Oid: 2, Name: "realTableName_c_idx", OwningSchema: "mock_schema", OwningTable: "pt_heap_tab_1_prt_pqr",
Tablespace: "mock_tablespace", Def: sql.NullString{String: "CREATE INDEX realTableName_c_idx ON mock_schema.pt_heap_tab_1_prt_pqr", Valid: true}, IsClustered: false,
SupportsConstraint: false, IsReplicaIdentity: false},
{Oid: 3, Name: "pt_heap_tab_1_prt_pqr_a_idx", OwningSchema: "mock_schema", OwningTable: "realTableName",
Tablespace: "mock_tablespace", Def: sql.NullString{String: "CREATE INDEX pt_heap_tab_1_prt_pqr_a_idx ON mock_schema.realTableName", Valid: true}, IsClustered: false,
SupportsConstraint: false, IsReplicaIdentity: false}}
header := []string{"indexname", "tablename", "relispartition"}
rowOne := []driver.Value{"mock_index", "mock_table", "false"}
rowTwo := []driver.Value{"pt_heap_tab_1_prt_pqr_a_idx", "realTableName", "false"}
rowThree := []driver.Value{"realTableName_c_idx", "pt_heap_tab", "true"}
fakeRows := sqlmock.NewRows(header).AddRow(rowOne...).AddRow(rowTwo...).AddRow(rowThree...)
mock.ExpectQuery(`SELECT (.*)`).WillReturnRows(fakeRows)
backup.RenameExchangedPartitionIndexes(connectionPool, &indexes)
Expect(indexes).To(HaveLen(3))
for _, idx := range indexes {
switch idx.Oid {
case 1:
Expect(idx.Name).To(Equal("mock_index"))
Expect(idx.Def.String).To(Equal("CREATE INDEX mock_index ON mock_schema.mock_table"))
case 2:
// We do not rename the partition leaf index here, as it will be
// system-generated correctly when we apply the index to the partition root table.
Expect(idx.Name).To(Equal("realTableName_c_idx"))
Expect(idx.Def.String).To(Equal("CREATE INDEX realTableName_c_idx ON mock_schema.pt_heap_tab_1_prt_pqr"))
case 3:
Expect(idx.Name).To(Equal("realTableName_c_idx"))
Expect(idx.Def.String).To(Equal("CREATE INDEX realTableName_c_idx ON mock_schema.realTableName"))
default:
Fail("Unexpected index OID found")
}
}
})
})
Describe("GetRules", func() {
It("GetRules properly handles NULL rule definitions", func() {
header := []string{"oid", "name", "owningschema", "owningtable", "def"}
rowOne := []driver.Value{"1", "mock_rule", "mock_schema", "mock_table", "mock_def"}
rowTwo := []driver.Value{"2", "mock_rule2", "mock_schema2", "mock_table2", nil}
fakeRows := sqlmock.NewRows(header).AddRow(rowOne...).AddRow(rowTwo...)
mock.ExpectQuery(`SELECT (.*)`).WillReturnRows(fakeRows)
result := backup.GetRules(connectionPool)
// Expect the GetRules function to return only the 1st row since the 2nd row has a NULL rule definition
expectedResult := []backup.RuleDefinition{{Oid: 1, Name: "mock_rule", OwningSchema: "mock_schema", OwningTable: "mock_table", Def: sql.NullString{String: "mock_def", Valid: true}}}
Expect(result).To(HaveLen(1))
structmatcher.ExpectStructsToMatch(&expectedResult[0], &result[0])
})
})
Describe("GetTriggers", func() {
It("GetTriggers properly handles NULL trigger definitions", func() {
header := []string{"oid", "name", "owningschema", "owningtable", "def"}
rowOne := []driver.Value{"1", "mock_trigger", "mock_schema", "mock_table", "mock_def"}
rowTwo := []driver.Value{"2", "mock_trigger2", "mock_schema2", "mock_table2", nil}
fakeRows := sqlmock.NewRows(header).AddRow(rowOne...).AddRow(rowTwo...)
mock.ExpectQuery(`SELECT (.*)`).WillReturnRows(fakeRows)
result := backup.GetTriggers(connectionPool)
// Expect the GetTriggers function to return only the 1st row since the 2nd row has a NULL trigger definition
expectedResult := []backup.TriggerDefinition{{Oid: 1, Name: "mock_trigger", OwningSchema: "mock_schema", OwningTable: "mock_table", Def: sql.NullString{String: "mock_def", Valid: true}}}
Expect(result).To(HaveLen(1))
structmatcher.ExpectStructsToMatch(&expectedResult[0], &result[0])
})
})
})