package integration

import (
	"fmt"

	"github.com/apache/cloudberry-backup/backup"
	"github.com/apache/cloudberry-backup/options"
	"github.com/apache/cloudberry-backup/testutils"
	"github.com/apache/cloudberry-backup/toc"
	"github.com/apache/cloudberry-go-libs/structmatcher"
	"github.com/apache/cloudberry-go-libs/testhelper"

	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)

var _ = Describe("backup integration tests", func() {
	Describe("GetMetadataForObjectType", func() {
		Context("default metadata for all objects of one type", func() {
			It("returns a slice of metadata with modified privileges", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.foo(i int)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.foo")
				testhelper.AssertQueryRuns(connectionPool, "REVOKE DELETE ON TABLE public.foo FROM testrole")
				testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.bar(i int)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.bar")
				testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON TABLE public.bar FROM testrole")
				testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.baz(i int)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.baz")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLE public.baz TO anothertestrole")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				fooUniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "foo", backup.TYPE_RELATION)
				barUniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "bar", backup.TYPE_RELATION)
				bazUniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "baz", backup.TYPE_RELATION)
				expectedFoo := backup.ObjectMetadata{ObjectType: toc.OBJ_RELATION, Privileges: []backup.ACL{testutils.DefaultACLWithout("testrole", toc.OBJ_TABLE, "DELETE")}, Owner: "testrole"}
				expectedBar := backup.ObjectMetadata{ObjectType: toc.OBJ_RELATION, Privileges: []backup.ACL{{Grantee: "GRANTEE"}}, Owner: "testrole"}
				expectedBaz := backup.ObjectMetadata{ObjectType: toc.OBJ_RELATION, Privileges: []backup.ACL{testutils.DefaultACLForType("anothertestrole", toc.OBJ_TABLE), testutils.DefaultACLForType("testrole", toc.OBJ_TABLE)}, Owner: "testrole"}
				Expect(resultMetadataMap).To(HaveLen(3))
				resultFoo := resultMetadataMap[fooUniqueID]
				resultBar := resultMetadataMap[barUniqueID]
				resultBaz := resultMetadataMap[bazUniqueID]
				structmatcher.ExpectStructsToMatch(&resultFoo, &expectedFoo)
				structmatcher.ExpectStructsToMatch(&resultBar, &expectedBar)
				structmatcher.ExpectStructsToMatch(&resultBaz, &expectedBaz)
			})
			It("returns a slice of default metadata for a database", func() {
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON DATABASE testdb TO anothertestrole")
				defer testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON DATABASE testdb FROM anothertestRole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON DATABASE testdb IS 'This is a database comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_DATABASE, "testdb")
				expectedMetadata := backup.ObjectMetadata{
					ObjectType: toc.OBJ_DATABASE, Privileges: []backup.ACL{
						{Grantee: "", Temporary: true, Connect: true},
						{Grantee: "anothertestrole", Create: true, Temporary: true, Connect: true},
					}, Owner: "anothertestrole", Comment: "This is a database comment."}
				if includeSecurityLabels {
					expectedMetadata.SecurityLabelProvider = "dummy"
					expectedMetadata.SecurityLabel = "unclassified"
				}

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_DATABASE)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testdb", backup.TYPE_DATABASE)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid", "schema")
			})
			It("returns a slice of default metadata for a role", func() {
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_ROLE)
				numRoles := len(resultMetadataMap)

				testhelper.AssertQueryRuns(connectionPool, `CREATE ROLE testuser`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP ROLE testuser")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON ROLE testuser IS 'This is a role comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_ROLE, "testuser")

				resultMetadataMap = backup.GetMetadataForObjectType(connectionPool, backup.TYPE_ROLE)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testuser", backup.TYPE_ROLE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_ROLE, false, false, true, includeSecurityLabels)

				Expect(resultMetadataMap).To(HaveLen(numRoles + 1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of metadata with the owner in quotes", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE ROLE "Role1"`)
				defer testhelper.AssertQueryRuns(connectionPool, `DROP ROLE "Role1"`)
				testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.testtable(i int)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable")
				testhelper.AssertQueryRuns(connectionPool, `ALTER TABLE public.testtable OWNER TO "Role1"`)

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testtable", backup.TYPE_RELATION)
				expectedMetadata := backup.ObjectMetadata{ObjectType: toc.OBJ_RELATION, Privileges: []backup.ACL{}, Owner: `"Role1"`}
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a table", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.testtable(i int)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLE public.testtable TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TABLE public.testtable IS 'This is a table comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_TABLE, "public.testtable")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testtable", backup.TYPE_RELATION)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_TABLE, true, true, true, includeSecurityLabels)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a sequence", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE SEQUENCE public.testsequence")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SEQUENCE public.testsequence")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON SEQUENCE public.testsequence TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON SEQUENCE public.testsequence IS 'This is a sequence comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_SEQUENCE, "public.testsequence")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testsequence", backup.TYPE_RELATION)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_SEQUENCE, true, true, true, includeSecurityLabels)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a procedural language", func() {
				plpythonString := "plpythonu"
				if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() {
					plpythonString = "plpython3u"
				}
				testhelper.AssertQueryRuns(connectionPool, fmt.Sprintf("CREATE LANGUAGE %s", plpythonString))
				// In Cloudberry (based on PG 14), CREATE LANGUAGE is a wrapper around CREATE EXTENSION.
				// To clean up, we must DROP THE EXTENSION, not the language itself.
				// For older GPDB versions, we still need to DROP THE LANGUAGE.
				if connectionPool.Version.IsCBDB() {
					defer testhelper.AssertQueryRuns(connectionPool, fmt.Sprintf("DROP EXTENSION %s", plpythonString))
				} else {
					defer testhelper.AssertQueryRuns(connectionPool, fmt.Sprintf("DROP LANGUAGE %s", plpythonString))
				}
				testhelper.AssertQueryRuns(connectionPool, fmt.Sprintf("COMMENT ON LANGUAGE %s IS 'This is a language comment.'", plpythonString))
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_LANGUAGE, plpythonString)

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_PROC_LANGUAGE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_LANGUAGE, false, true, true, includeSecurityLabels)
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", plpythonString, backup.TYPE_PROC_LANGUAGE)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns metadata for an empty {} ACL (not NULL)", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.add(integer, integer) RETURNS integer
AS 'SELECT $1 + $2'
LANGUAGE SQL`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.add(integer, integer)")
				testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON FUNCTION public.add(integer, integer) FROM public")
				testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON FUNCTION public.add(integer, integer) FROM testrole")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_FUNCTION, "public.add(integer, integer)")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FUNCTION)
				Expect(resultMetadataMap).To(HaveLen(1))

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "add", backup.TYPE_FUNCTION)
				resultMetadata := resultMetadataMap[uniqueID]

				// important: in the case where SQL reports ACL list = {}, and not null,
				// we expect there to be a default ACL with ALL BOOLEANS FALSE, which prints as
				// just the 2 default "REVOKE" and no additional grant because all booleans false.
				Expect(resultMetadata.Privileges).To(HaveLen(1))

				slabel := ""
				slabelProvider := ""
				if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("6.0.0")) || connectionPool.Version.IsCBDB() {
					slabel = "unclassified"
					slabelProvider = "dummy"
				}
				expectedMetadata := backup.ObjectMetadata{ObjectType: toc.OBJ_FUNCTION, Privileges: []backup.ACL{{Grantee: "GRANTEE"}}, Owner: "testrole", SecurityLabel: slabel, SecurityLabelProvider: slabelProvider}
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns metadata for a function with a grant and revoke", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.add(integer, integer) RETURNS integer
AS 'SELECT $1 + $2'
LANGUAGE SQL`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.add(integer, integer)")
				// for Function objects:
				// `public` and the user that created the function (`testrole`) exist in the ACL by default. However, the ACL is not explicitly represented unless these defaults are modified.
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON FUNCTION public.add(integer, integer) TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON FUNCTION public.add(integer, integer) FROM PUBLIC")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON FUNCTION public.add(integer, integer) IS 'This is a function comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_FUNCTION, "public.add(integer, integer)")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FUNCTION)
				Expect(resultMetadataMap).To(HaveLen(1))

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "add", backup.TYPE_FUNCTION)
				resultMetadata := resultMetadataMap[uniqueID]
				Expect(resultMetadata.Privileges).To(HaveLen(1))

				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_FUNCTION, true, true, true, includeSecurityLabels)
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns metadata for an aggregate with a grant and revoke", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.mysfunc_accum(numeric, numeric, numeric) RETURNS numeric AS 'SELECT $1 + $2 + $3' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT`)
				testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.mycombine_accum(numeric, numeric) RETURNS numeric AS 'select $1 + $2' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT`)
				testhelper.AssertQueryRuns(connectionPool, `CREATE AGGREGATE public.agg_prefunc(numeric, numeric) (SFUNC = public.mysfunc_accum, STYPE = numeric, COMBINEFUNC = public.mycombine_accum, INITCOND = '0')`)

				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mysfunc_accum(numeric, numeric, numeric)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mycombine_accum(numeric, numeric)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP AGGREGATE public.agg_prefunc(numeric, numeric)")

				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON FUNCTION public.agg_prefunc(numeric, numeric) TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON FUNCTION public.agg_prefunc(numeric, numeric) FROM PUBLIC")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON AGGREGATE public.agg_prefunc(numeric, numeric) IS 'This is an aggregate comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_FUNCTION, "public.agg_prefunc(numeric, numeric)")

				// for Aggregate objects:
				// `public` and the user that created the aggregate (`testrole`) exist in the ACL by default. However, the ACL is not explicitly represented unless these defaults are modified.
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_AGGREGATE)
				Expect(resultMetadataMap).To(HaveLen(1))

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "agg_prefunc", backup.TYPE_AGGREGATE)
				resultMetadata := resultMetadataMap[uniqueID]
				Expect(resultMetadata.Privileges).To(HaveLen(1))

				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_AGGREGATE, true, true, true, includeSecurityLabels)
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a view", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE VIEW public.testview AS SELECT * FROM pg_class`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP VIEW public.testview")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON public.testview TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON VIEW public.testview IS 'This is a view comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_VIEW, "public.testview")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testview", backup.TYPE_RELATION)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_VIEW, true, true, true, includeSecurityLabels)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a materialized view", func() {
				if connectionPool.Version.IsGPDB() && connectionPool.Version.Before("6.2") {
					Skip("Test only applicable to GPDB 6.2 and above")
				}
				testhelper.AssertQueryRuns(connectionPool, `CREATE MATERIALIZED VIEW public.testmview AS SELECT * FROM pg_class`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP MATERIALIZED VIEW public.testmview")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON public.testmview TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON MATERIALIZED VIEW public.testmview IS 'This is a materialized view comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_MATERIALIZED_VIEW, "public.testmview")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testmview", backup.TYPE_RELATION)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_MATERIALIZED_VIEW, true, true, true, includeSecurityLabels)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a schema", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE SCHEMA testschema`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON SCHEMA testschema TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON SCHEMA testschema IS 'This is a schema comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_SCHEMA, "testschema")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_SCHEMA)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testschema", backup.TYPE_SCHEMA)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_SCHEMA, true, true, true, includeSecurityLabels)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for an aggregate", func() {
				testhelper.AssertQueryRuns(connectionPool, `
			CREATE FUNCTION public.mysfunc_accum(numeric, numeric, numeric)
			   RETURNS numeric
			   AS 'select $1 + $2 + $3'
			   LANGUAGE SQL
			   IMMUTABLE
			   RETURNS NULL ON NULL INPUT;
			`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mysfunc_accum(numeric, numeric, numeric)")
				testhelper.AssertQueryRuns(connectionPool, `
			CREATE FUNCTION public.mypre_accum(numeric, numeric)
			   RETURNS numeric
			   AS 'select $1 + $2'
			   LANGUAGE SQL
			   IMMUTABLE
			   RETURNS NULL ON NULL INPUT;
			`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mypre_accum(numeric, numeric)")
				testhelper.AssertQueryRuns(connectionPool, `CREATE AGGREGATE public.agg_prefunc(numeric, numeric) (
	SFUNC = public.mysfunc_accum,
	STYPE = numeric,
	PREFUNC = public.mypre_accum,
	INITCOND = '0'
);`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP AGGREGATE public.agg_prefunc(numeric, numeric)")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON AGGREGATE public.agg_prefunc(numeric, numeric) IS 'This is an aggregate comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_AGGREGATE, "public.agg_prefunc(numeric, numeric)")

				testhelper.AssertQueryRuns(connectionPool, `
				GRANT ALL ON FUNCTION public.agg_prefunc(numeric, numeric)
				  to testrole`)
				testhelper.AssertQueryRuns(connectionPool, `
				REVOKE ALL ON FUNCTION public.agg_prefunc(numeric, numeric) FROM public`)

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_AGGREGATE)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "agg_prefunc", backup.TYPE_AGGREGATE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_AGGREGATE, true, true, true, includeSecurityLabels)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a type", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE TYPE public.testtype AS (name text, num numeric)`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE public.testtype")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TYPE public.testtype IS 'This is a type comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_TYPE, "public.testtype")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TYPE)

				typeUniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testtype", backup.TYPE_TYPE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_TYPE, false, true, true, includeSecurityLabels)
				resultMetadata := resultMetadataMap[typeUniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a domain", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE DOMAIN public.domain_type AS numeric`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE public.domain_type")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON DOMAIN public.domain_type IS 'This is a domain comment.'")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_DOMAIN, "public.domain_type")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TYPE)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "domain_type", backup.TYPE_TYPE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_DOMAIN, false, true, true, includeSecurityLabels)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for an external protocol", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE OR REPLACE FUNCTION public.read_from_s3() RETURNS integer AS '$libdir/gps3ext.so', 's3_import' LANGUAGE C STABLE;`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.read_from_s3()")
				testhelper.AssertQueryRuns(connectionPool, `CREATE TRUSTED PROTOCOL s3_read (readfunc = public.read_from_s3);`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP PROTOCOL s3_read")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON PROTOCOL s3_read TO testrole")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_PROTOCOL)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "s3_read", backup.TYPE_PROTOCOL)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_PROTOCOL, true, true, false, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a tablespace", func() {
				if connectionPool.Version.IsGPDB() && connectionPool.Version.Before("6") {
					testhelper.AssertQueryRuns(connectionPool, "CREATE TABLESPACE test_tablespace FILESPACE test_dir")
				} else {
					testhelper.AssertQueryRuns(connectionPool, "CREATE TABLESPACE test_tablespace LOCATION '/tmp/test_dir'")
				}
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLESPACE test_tablespace")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TABLESPACE test_tablespace IS 'This is a tablespace comment.'")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLESPACE test_tablespace TO testrole")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_TABLESPACE, "test_tablespace")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TABLESPACE)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "test_tablespace", backup.TYPE_TABLESPACE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_TABLESPACE, true, true, true, includeSecurityLabels)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for an operator", func() {
				// Cloudberry does not support user-defined unary operators (based on PostgreSQL 14).
				// To ensure this test runs on all platforms, we use a binary operator,
				// which is supported by both Greenplum and Cloudberry.
				testhelper.AssertQueryRuns(connectionPool, "CREATE FUNCTION public.binary_op_func(bigint, bigint) RETURNS bigint AS 'SELECT $1 + $2' LANGUAGE SQL IMMUTABLE;")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.binary_op_func(bigint, bigint);")

				testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR public.#### (LEFTARG = bigint, RIGHTARG = bigint, PROCEDURE = public.binary_op_func)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR public.#### (bigint, bigint)")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR public.#### (bigint, bigint) IS 'This is an operator comment.'")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATOR)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "####", backup.TYPE_OPERATOR)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_OPERATOR, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for an operator family", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR FAMILY public.testfam USING hash")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY public.testfam USING hash")

				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR FAMILY public.testfam USING hash IS 'This is an operator family comment.'")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATOR_FAMILY)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testfam", backup.TYPE_OPERATOR_FAMILY)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_OPERATOR_FAMILY, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for an operator class", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR CLASS public.testclass FOR TYPE int USING hash AS STORAGE int")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY public.testclass USING hash")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR CLASS public.testclass USING hash IS 'This is an operator class comment.'")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATOR_CLASS)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testclass", backup.TYPE_OPERATOR_CLASS)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_OPERATOR_CLASS, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a text search dictionary", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH DICTIONARY public.testdictionary(TEMPLATE = snowball, LANGUAGE = 'russian', STOPWORDS = 'russian');")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH DICTIONARY public.testdictionary")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH DICTIONARY public.testdictionary IS 'This is a text search dictionary comment.'")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TS_DICTIONARY)

				Expect(resultMetadataMap).To(HaveLen(1))
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testdictionary", backup.TYPE_TS_DICTIONARY)
				dictionaryMetadata := testutils.DefaultMetadata(toc.OBJ_TEXT_SEARCH_DICTIONARY, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&dictionaryMetadata, &resultMetadata)
			})
			It("returns a slice of default metadata for a text search configuration", func() {
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TS_CONFIGURATION)
				configurationMetadata := testutils.DefaultMetadata(toc.OBJ_TEXT_SEARCH_CONFIGURATION, false, true, true, false)

				testhelper.AssertQueryRuns(connectionPool, `CREATE TEXT SEARCH CONFIGURATION public.testconfiguration (PARSER = pg_catalog."default");`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH CONFIGURATION public.testconfiguration")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH CONFIGURATION public.testconfiguration IS 'This is a text search configuration comment.'")

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testconfiguration", backup.TYPE_TS_CONFIGURATION)
				resultMetadataMap = backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TS_CONFIGURATION)

				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&configurationMetadata, &resultMetadata)
			})
			It("returns a slice of default metadata for a foreign data wrapper", func() {
				testutils.SkipIfBefore6(connectionPool)
				testhelper.AssertQueryRuns(connectionPool, "CREATE FOREIGN DATA WRAPPER foreignwrapper")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FOREIGN DATA WRAPPER foreignwrapper")

				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON FOREIGN DATA WRAPPER foreignwrapper TO testrole")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FOREIGN_DATA_WRAPPER)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "foreignwrapper", backup.TYPE_FOREIGN_DATA_WRAPPER)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_FOREIGN_DATA_WRAPPER, true, true, false, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a foreign server", func() {
				testutils.SkipIfBefore6(connectionPool)
				testhelper.AssertQueryRuns(connectionPool, "CREATE FOREIGN DATA WRAPPER foreignwrapper")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FOREIGN DATA WRAPPER foreignwrapper CASCADE")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SERVER foreignserver FOREIGN DATA WRAPPER foreignwrapper")

				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON FOREIGN SERVER foreignserver TO testrole")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FOREIGN_SERVER)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "foreignserver", backup.TYPE_FOREIGN_SERVER)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_FOREIGN_SERVER, true, true, false, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a collation", func() {
				testutils.SkipIfBefore6(connectionPool)
				testhelper.AssertQueryRuns(connectionPool, `CREATE COLLATION public.some_coll (lc_collate = 'POSIX', lc_ctype = 'POSIX');`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP COLLATION public.some_coll")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON COLLATION public.some_coll IS 'This is a collation comment.'")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_COLLATION)

				Expect(resultMetadataMap).To(HaveLen(1))
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "some_coll", backup.TYPE_COLLATION)
				collationMetadata := testutils.DefaultMetadata(toc.OBJ_COLLATION, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&collationMetadata, &resultMetadata)
			})
			It("returns a slice of default metadata for an event trigger", func() {
				testutils.SkipIfBefore6(connectionPool)
				testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION abort_any_command()
RETURNS event_trigger LANGUAGE plpgsql
AS $$ BEGIN RAISE EXCEPTION 'exception'; END; $$;`)
				defer testhelper.AssertQueryRuns(connectionPool, `DROP FUNCTION abort_any_command()`)
				testhelper.AssertQueryRuns(connectionPool, "CREATE EVENT TRIGGER test_event_trigger ON ddl_command_start EXECUTE PROCEDURE abort_any_command();")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP EVENT TRIGGER test_event_trigger")
				testutils.CreateSecurityLabelIfGPDB6(connectionPool, toc.OBJ_EVENT_TRIGGER, "test_event_trigger")

				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON EVENT TRIGGER test_event_trigger IS 'This is an event trigger comment.'")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_EVENT_TRIGGER)

				Expect(resultMetadataMap).To(HaveLen(1))
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "test_event_trigger", backup.TYPE_EVENT_TRIGGER)
				eventTriggerMetadata := testutils.DefaultMetadata(toc.OBJ_EVENT_TRIGGER, false, true, true, true)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&eventTriggerMetadata, &resultMetadata)
			})
			It("returns ACL information for a newly declared TYPE_TYPE object", func() {
				testutils.SkipIfBefore6(connectionPool)
				testhelper.AssertQueryRuns(connectionPool, `CREATE TYPE public.my_type AS (i int)`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE public.my_type")
				testhelper.AssertQueryRuns(connectionPool, `GRANT USAGE ON TYPE public.my_type TO testrole`)
				defer testhelper.AssertQueryRuns(connectionPool, "REVOKE usage on type public.my_type from testrole")
				// public usage creates an entry in the ACL with GRANTEE="" . We revoke this for ease of testing.
				testhelper.AssertQueryRuns(connectionPool, "REVOKE usage on type public.my_type from public")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TYPE)
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "my_type", backup.TYPE_TYPE)
				resultMetadata := resultMetadataMap[uniqueID]

				// (1) the 'my_type' obj   ...  (2) the implicit 'i INT' type, created when instantiating 'my_type'
				Expect(resultMetadataMap).To(HaveLen(2))

				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_TYPE, true, true, false, false)
				expectedMetadata.Privileges[0].Usage = true
				Expect(&resultMetadata).To(Equal(&expectedMetadata))
			})
		})
		Context("metadata for objects in a specific schema", func() {
			It("returns a slice of default metadata for a table in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.testtable(i int)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE testschema.testtable(i int)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE testschema.testtable")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLE testschema.testtable TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TABLE testschema.testtable IS 'This is a table comment.'")
				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtable", backup.TYPE_RELATION)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_TABLE, true, true, true, false)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a table not in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.testtable(i int)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE testschema.testtable(i int)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE testschema.testtable")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLE testschema.testtable TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TABLE testschema.testtable IS 'This is a table comment.'")
				_ = backupCmdFlags.Set(options.EXCLUDE_SCHEMA, "public")

				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtable", backup.TYPE_RELATION)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_TABLE, true, true, true, false)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a function in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.add(integer, integer) RETURNS integer
AS 'SELECT $1 + $2'
LANGUAGE SQL`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.add(integer, integer)")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION testschema.add(integer, integer) RETURNS integer
AS 'SELECT $1 + $2'
LANGUAGE SQL`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION testschema.add(integer, integer)")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON FUNCTION testschema.add(integer, integer) TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON FUNCTION testschema.add(integer, integer) FROM PUBLIC")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON FUNCTION testschema.add(integer, integer) IS 'This is a function comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FUNCTION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "add", backup.TYPE_FUNCTION)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_FUNCTION, true, true, true, false)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a view in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE VIEW public.testview AS SELECT * FROM pg_class`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP VIEW public.testview")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, `CREATE VIEW testschema.testview AS SELECT * FROM pg_class`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP VIEW testschema.testview")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON testschema.testview TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON VIEW testschema.testview IS 'This is a view comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testview", backup.TYPE_RELATION)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_VIEW, true, true, true, false)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a materialized view in a specific schema", func() {
				if connectionPool.Version.IsGPDB() && connectionPool.Version.Before("6.2") {
					Skip("Test only applicable to GPDB 6.2 and above")
				}
				testhelper.AssertQueryRuns(connectionPool, `CREATE MATERIALIZED VIEW public.testmview AS SELECT * FROM pg_class`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP MATERIALIZED VIEW public.testmview")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, `CREATE MATERIALIZED VIEW testschema.testmview AS SELECT * FROM pg_class`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP MATERIALIZED VIEW testschema.testmview")
				testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON testschema.testmview TO testrole")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON MATERIALIZED VIEW testschema.testmview IS 'This is a materialized view comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testmview", backup.TYPE_RELATION)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_MATERIALIZED_VIEW, true, true, true, false)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for an aggregate in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, `
			CREATE FUNCTION public.mysfunc_accum(numeric, numeric, numeric)
			   RETURNS numeric
			   AS 'select $1 + $2 + $3'
			   LANGUAGE SQL
			   IMMUTABLE
			   RETURNS NULL ON NULL INPUT;
			`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mysfunc_accum(numeric, numeric, numeric)")
				testhelper.AssertQueryRuns(connectionPool, `
			CREATE FUNCTION public.mypre_accum(numeric, numeric)
			   RETURNS numeric
			   AS 'select $1 + $2'
			   LANGUAGE SQL
			   IMMUTABLE
			   RETURNS NULL ON NULL INPUT;
			`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mypre_accum(numeric, numeric)")
				testhelper.AssertQueryRuns(connectionPool, `CREATE AGGREGATE public.agg_prefunc(numeric, numeric) (
	SFUNC = public.mysfunc_accum,
	STYPE = numeric,
	PREFUNC = public.mypre_accum,
	INITCOND = '0'
);`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP AGGREGATE public.agg_prefunc(numeric, numeric)")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON AGGREGATE public.agg_prefunc(numeric, numeric) IS 'This is an aggregate comment.'")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, `CREATE AGGREGATE testschema.agg_prefunc(numeric, numeric) (
	SFUNC = public.mysfunc_accum,
	STYPE = numeric,
	PREFUNC = public.mypre_accum,
	INITCOND = '0'
);`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP AGGREGATE testschema.agg_prefunc(numeric, numeric)")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON AGGREGATE testschema.agg_prefunc(numeric, numeric) IS 'This is an aggregate comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_AGGREGATE)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "agg_prefunc", backup.TYPE_AGGREGATE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_AGGREGATE, false, true, true, false)
				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a type in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE TYPE public.testtype`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE public.testtype")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, `CREATE TYPE testschema.testtype AS (name text)`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE testschema.testtype")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TYPE testschema.testtype IS 'This is a type comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TYPE)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtype", backup.TYPE_TYPE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_TYPE, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				Expect(resultMetadataMap).To(HaveLen(2))
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for an operator in a specific schema", func() {
				// Cloudberry does not support postfix operators, which this test originally required.
				// To ensure this test for schema filtering runs on all platforms, we refactor it
				// to use a binary operator, which is supported by both Greenplum and Cloudberry.
				testhelper.AssertQueryRuns(connectionPool, "CREATE FUNCTION public.binary_op_func(bigint, bigint) RETURNS bigint AS 'SELECT $1 + $2' LANGUAGE SQL IMMUTABLE;")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.binary_op_func(bigint, bigint);")

				testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR public.#### (LEFTARG = bigint, RIGHTARG = bigint, PROCEDURE = public.binary_op_func)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR public.#### (bigint, bigint)")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR testschema.#### (LEFTARG = bigint, RIGHTARG = bigint, PROCEDURE = public.binary_op_func)")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR testschema.#### (bigint, bigint)")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR testschema.#### (bigint, bigint) IS 'This is an operator comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATOR)

				Expect(resultMetadataMap).To(HaveLen(1))
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "####", backup.TYPE_OPERATOR)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_OPERATOR, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for an operator family in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR FAMILY public.testfam USING hash")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY public.testfam USING hash")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR FAMILY testschema.testfam USING hash")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY testschema.testfam USING hash")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR FAMILY testschema.testfam USING hash IS 'This is an operator family comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATOR_FAMILY)

				Expect(resultMetadataMap).To(HaveLen(1))
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testfam", backup.TYPE_OPERATOR_FAMILY)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_OPERATOR_FAMILY, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for an operator class in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR CLASS public.testclass FOR TYPE int4 USING hash AS STORAGE int4")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY public.testclass USING hash CASCADE")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR CLASS testschema.testclass FOR TYPE int4 USING hash AS STORAGE int4")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY testschema.testclass USING hash CASCADE")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR CLASS testschema.testclass USING hash IS 'This is an operator class comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATOR_CLASS)

				Expect(resultMetadataMap).To(HaveLen(1))
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testclass", backup.TYPE_OPERATOR_CLASS)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_OPERATOR_CLASS, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a text search dictionary in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH DICTIONARY public.testdictionary(TEMPLATE = snowball, LANGUAGE = 'russian', STOPWORDS = 'russian');")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH DICTIONARY public.testdictionary")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH DICTIONARY testschema.testdictionary(TEMPLATE = snowball, LANGUAGE = 'russian', STOPWORDS = 'russian');")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH DICTIONARY testschema.testdictionary")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH DICTIONARY testschema.testdictionary IS 'This is a text search dictionary comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TS_DICTIONARY)

				Expect(resultMetadataMap).To(HaveLen(1))
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testdictionary", backup.TYPE_TS_DICTIONARY)
				dictionaryMetadata := testutils.DefaultMetadata(toc.OBJ_TEXT_SEARCH_DICTIONARY, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&dictionaryMetadata, &resultMetadata)
			})
			It("returns a slice of default metadata for a text search configuration in a specific schema", func() {
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TS_CONFIGURATION)
				configurationMetadata := testutils.DefaultMetadata(toc.OBJ_TEXT_SEARCH_CONFIGURATION, false, true, true, false)

				testhelper.AssertQueryRuns(connectionPool, `CREATE TEXT SEARCH CONFIGURATION public.testconfiguration (PARSER = pg_catalog."default");`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH CONFIGURATION public.testconfiguration")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, `CREATE TEXT SEARCH CONFIGURATION testschema.testconfiguration (PARSER = pg_catalog."default");`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH CONFIGURATION testschema.testconfiguration")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH CONFIGURATION testschema.testconfiguration IS 'This is a text search configuration comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap = backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TS_CONFIGURATION)

				Expect(resultMetadataMap).To(HaveLen(1))
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testconfiguration", backup.TYPE_TS_CONFIGURATION)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&configurationMetadata, &resultMetadata)
			})
			It("returns a slice of default metadata for a collation in a specific schema", func() {
				testutils.SkipIfBefore6(connectionPool)
				testhelper.AssertQueryRuns(connectionPool, `CREATE COLLATION public.some_coll (lc_collate = 'POSIX', lc_ctype = 'POSIX');`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP COLLATION public.some_coll")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, `CREATE COLLATION testschema.some_coll (lc_collate = 'POSIX', lc_ctype = 'POSIX');`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP COLLATION testschema.some_coll")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON COLLATION testschema.some_coll IS 'This is a collation comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_COLLATION)

				Expect(resultMetadataMap).To(HaveLen(1))
				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "some_coll", backup.TYPE_COLLATION)
				collationMetadata := testutils.DefaultMetadata(toc.OBJ_COLLATION, false, true, true, false)
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&collationMetadata, &resultMetadata)
			})
		})
	})
	Describe("GetDefaultPrivileges", func() {
		BeforeEach(func() {
			testutils.SkipIfBefore6(connectionPool)
		})
		It("returns default privileges with single privilege", func() {
			testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES REVOKE USAGE ON SEQUENCES FROM testrole;")
			defer testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES GRANT USAGE ON SEQUENCES TO testrole;")

			resultDefaultPrivileges := backup.GetDefaultPrivileges(connectionPool)

			privs := []backup.ACL{{Grantee: "testrole", Update: true, Select: true}}
			expectedDefaultPrivileges := backup.DefaultPrivileges{Schema: "", Privileges: privs, ObjectType: "S", Owner: "testrole"}
			Expect(resultDefaultPrivileges).To(HaveLen(1))
			structmatcher.ExpectStructsToMatchExcluding(&expectedDefaultPrivileges, &resultDefaultPrivileges[0], "Oid")
		})
		It("returns default privileges with multiple privileges", func() {
			testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES TO PUBLIC;")
			defer testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES REVOKE SELECT ON TABLES FROM PUBLIC;")

			resultDefaultPrivileges := backup.GetDefaultPrivileges(connectionPool)

			privs := []backup.ACL{{Grantee: "", Select: true}, testutils.DefaultACLForType("testrole", toc.OBJ_TABLE)}
			expectedDefaultPrivileges := backup.DefaultPrivileges{Schema: "", Privileges: privs, ObjectType: "r", Owner: "testrole"}
			Expect(resultDefaultPrivileges).To(HaveLen(1))
			structmatcher.ExpectStructsToMatchExcluding(&expectedDefaultPrivileges, &resultDefaultPrivileges[0], "Oid")
		})
		It("returns default privileges for role", func() {
			testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES FOR ROLE anothertestrole GRANT USAGE ON SEQUENCES TO testrole;")
			defer testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES FOR ROLE anothertestrole REVOKE USAGE ON SEQUENCES FROM testrole;")

			resultDefaultPrivileges := backup.GetDefaultPrivileges(connectionPool)

			privs := []backup.ACL{{Grantee: "anothertestrole", Select: true, Update: true, Usage: true}, {Grantee: "testrole", Usage: true}}
			expectedDefaultPrivileges := backup.DefaultPrivileges{Schema: "", Privileges: privs, ObjectType: "S", Owner: "anothertestrole"}
			Expect(resultDefaultPrivileges).To(HaveLen(1))
			structmatcher.ExpectStructsToMatchExcluding(&expectedDefaultPrivileges, &resultDefaultPrivileges[0], "Oid")
		})
		It("returns default privileges in schema", func() {
			testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE ON SEQUENCES TO testrole;")
			defer testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE USAGE ON SEQUENCES FROM testrole;")

			resultDefaultPrivileges := backup.GetDefaultPrivileges(connectionPool)

			privs := []backup.ACL{{Grantee: "testrole", Usage: true}}
			expectedDefaultPrivileges := backup.DefaultPrivileges{Schema: "public", Privileges: privs, ObjectType: "S", Owner: "testrole"}
			Expect(resultDefaultPrivileges).To(HaveLen(1))
			structmatcher.ExpectStructsToMatchExcluding(&expectedDefaultPrivileges, &resultDefaultPrivileges[0], "Oid")
		})

	})
	Describe("GetCommentsForObjectType", func() {
		Context("comments for all objects of one type", func() {
			It("returns a slice of default metadata for an index", func() {
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_INDEX)
				numIndexes := len(resultMetadataMap)

				testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int)`)
				testhelper.AssertQueryRuns(connectionPool, `CREATE INDEX testindex ON public.testtable USING btree(i)`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON INDEX public.testindex IS 'This is an index comment.'")

				resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_INDEX)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testindex", backup.TYPE_INDEX)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_INDEX, false, false, true, false)

				Expect(resultMetadataMap).To(HaveLen(numIndexes + 1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a rule", func() {
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_RULE)
				numRules := len(resultMetadataMap)

				testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int)`)
				testhelper.AssertQueryRuns(connectionPool, `CREATE RULE update_notify AS ON UPDATE TO public.testtable DO NOTIFY testtable`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON RULE update_notify ON public.testtable IS 'This is a rule comment.'")

				resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_RULE)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "update_notify", backup.TYPE_RULE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_RULE, false, false, true, false)

				Expect(resultMetadataMap).To(HaveLen(numRules + 1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a trigger", func() {
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TRIGGER)
				numTriggers := len(resultMetadataMap)

				testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int)`)
				if connectionPool.Version.IsGPDB() && connectionPool.Version.Before("7") {
					testhelper.AssertQueryRuns(connectionPool, `CREATE TRIGGER sync_testtable AFTER INSERT OR DELETE OR UPDATE ON public.testtable FOR EACH STATEMENT EXECUTE PROCEDURE "RI_FKey_check_ins"()`)
				} else {
					testhelper.AssertQueryRuns(connectionPool, `CREATE TRIGGER sync_testtable AFTER INSERT OR DELETE OR UPDATE ON public.testtable FOR EACH ROW EXECUTE FUNCTION "RI_FKey_check_ins"()`)
				}
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TRIGGER sync_testtable ON public.testtable IS 'This is a trigger comment.'")

				resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TRIGGER)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "sync_testtable", backup.TYPE_TRIGGER)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_TRIGGER, false, false, true, false)

				Expect(resultMetadataMap).To(HaveLen(numTriggers + 1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a cast in 5", func() {
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_CAST)
				numCasts := len(resultMetadataMap)

				testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.casttoint(text) RETURNS integer STRICT IMMUTABLE LANGUAGE SQL AS 'SELECT cast($1 as integer);'`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.casttoint(text) CASCADE")
				testhelper.AssertQueryRuns(connectionPool, "CREATE CAST (text AS int) WITH FUNCTION public.casttoint(text) AS ASSIGNMENT;")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON CAST (text AS int) IS 'This is a cast comment.'")

				resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_CAST)

				textOid := testutils.OidFromObjectName(connectionPool, "", "text", backup.TYPE_TYPE)
				intOid := testutils.OidFromObjectName(connectionPool, "", "int4", backup.TYPE_TYPE)
				oid := testutils.OidFromCast(connectionPool, textOid, intOid)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_CAST, false, false, true, false)

				Expect(resultMetadataMap).To(HaveLen(numCasts + 1))
				resultMetadata := resultMetadataMap[backup.UniqueID{ClassID: backup.PG_CAST_OID, Oid: oid}]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a resource queue", func() {
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_RESOURCE_QUEUE)
				numResQueues := len(resultMetadataMap)

				testhelper.AssertQueryRuns(connectionPool, `CREATE RESOURCE QUEUE res_queue WITH (MAX_COST=32.8);`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP RESOURCE QUEUE res_queue")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON RESOURCE QUEUE res_queue IS 'This is a resource queue comment.'")

				resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_RESOURCE_QUEUE)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "res_queue", backup.TYPE_RESOURCE_QUEUE)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_RESOURCE_QUEUE, false, false, true, false)

				Expect(resultMetadataMap).To(HaveLen(numResQueues + 1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a text search parser", func() {
				parserMetadata := testutils.DefaultMetadata(toc.OBJ_TEXT_SEARCH_PARSER, false, false, true, false)

				testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH PARSER public.testparser(START = prsd_start, GETTOKEN = prsd_nexttoken, END = prsd_end, LEXTYPES = prsd_lextype);")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH PARSER public.testparser")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH PARSER public.testparser IS 'This is a text search parser comment.'")

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testparser", backup.TYPE_TS_PARSER)
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TS_PARSER)

				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&parserMetadata, &resultMetadata)
			})
			It("returns a slice of default metadata for a text search template", func() {
				templateMetadata := testutils.DefaultMetadata(toc.OBJ_TEXT_SEARCH_TEMPLATE, false, false, true, false)

				testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH TEMPLATE public.testtemplate(LEXIZE = dsimple_lexize);")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH TEMPLATE public.testtemplate")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH TEMPLATE public.testtemplate IS 'This is a text search template comment.'")

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testtemplate", backup.TYPE_TS_TEMPLATE)
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TS_TEMPLATE)

				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&templateMetadata, &resultMetadata)
			})
			It("returns a slice of default metadata for an extension", func() {
				extensionMetadata := testutils.DefaultMetadata(toc.OBJ_EXTENSION, false, false, true, false)

				testhelper.AssertQueryRuns(connectionPool, "CREATE EXTENSION plperl;")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP EXTENSION plperl")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON EXTENSION plperl IS 'This is an extension comment.'")

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "plperl", backup.TYPE_EXTENSION)
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_EXTENSION)

				if connectionPool.Version.IsGPDB() && connectionPool.Version.Before("7") {
					Expect(resultMetadataMap).To(HaveLen(1))
				} else {
					// gp_toolkit is installed by default as an extension in GPDB7+
					Expect(resultMetadataMap).To(HaveLen(2))
				}
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&extensionMetadata, &resultMetadata)
			})
		})
		Context("comments for objects in a specific schema", func() {
			It("returns a slice of default metadata for an index in a specific schema", func() {

				testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int)`)
				testhelper.AssertQueryRuns(connectionPool, `CREATE INDEX testindex ON public.testtable USING btree(i)`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE testschema.testtable(i int)`)
				testhelper.AssertQueryRuns(connectionPool, `CREATE INDEX testindex1 ON testschema.testtable USING btree(i)`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE testschema.testtable")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON INDEX testschema.testindex1 IS 'This is an index comment.'")

				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_INDEX)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testindex1", backup.TYPE_INDEX)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_INDEX, false, false, true, false)

				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a constraint in a specific schema", func() {
				testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int UNIQUE)`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON CONSTRAINT testtable_i_key ON public.testtable IS 'This is a constraint comment.'")

				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE testschema.testtable(i int UNIQUE)`)
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE testschema.testtable")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON CONSTRAINT testtable_i_key ON testschema.testtable IS 'This is a constraint comment.'")
				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")

				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_CONSTRAINT)

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtable_i_key", backup.TYPE_CONSTRAINT)
				expectedMetadata := testutils.DefaultMetadata(toc.OBJ_CONSTRAINT, false, false, true, false)

				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid")
			})
			It("returns a slice of default metadata for a text search parser in a specific schema", func() {
				parserMetadata := testutils.DefaultMetadata(toc.OBJ_TEXT_SEARCH_PARSER, false, false, true, false)

				testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH PARSER public.testparser(START = prsd_start, GETTOKEN = prsd_nexttoken, END = prsd_end, LEXTYPES = prsd_lextype);")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH PARSER public.testparser")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH PARSER testschema.testparser(START = prsd_start, GETTOKEN = prsd_nexttoken, END = prsd_end, LEXTYPES = prsd_lextype);")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH PARSER testschema.testparser")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH PARSER testschema.testparser IS 'This is a text search parser comment.'")

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testparser", backup.TYPE_TS_PARSER)
				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TS_PARSER)

				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&parserMetadata, &resultMetadata)
			})
			It("returns a slice of default metadata for a text search template in a specific schema", func() {
				templateMetadata := testutils.DefaultMetadata(toc.OBJ_TEXT_SEARCH_TEMPLATE, false, false, true, false)

				testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH TEMPLATE public.testtemplate(LEXIZE = dsimple_lexize);")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH TEMPLATE public.testtemplate")
				testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema")
				testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH TEMPLATE testschema.testtemplate(LEXIZE = dsimple_lexize);")
				defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH TEMPLATE testschema.testtemplate")
				testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH TEMPLATE testschema.testtemplate IS 'This is a text search template comment.'")

				uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtemplate", backup.TYPE_TS_TEMPLATE)
				_ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema")
				resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TS_TEMPLATE)

				Expect(resultMetadataMap).To(HaveLen(1))
				resultMetadata := resultMetadataMap[uniqueID]
				structmatcher.ExpectStructsToMatch(&templateMetadata, &resultMetadata)
			})
		})
	})
})
