github.com/tuhaihe/gpbackup@v1.0.3/integration/predata_acl_queries_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 6 "github.com/tuhaihe/gp-common-go-libs/structmatcher" 7 "github.com/tuhaihe/gp-common-go-libs/testhelper" 8 "github.com/tuhaihe/gpbackup/backup" 9 "github.com/tuhaihe/gpbackup/options" 10 "github.com/tuhaihe/gpbackup/testutils" 11 12 . "github.com/onsi/ginkgo/v2" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("backup integration tests", func() { 17 Describe("GetMetadataForObjectType", func() { 18 Context("default metadata for all objects of one type", func() { 19 It("returns a slice of metadata with modified privileges", func() { 20 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.foo(i int)") 21 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.foo") 22 testhelper.AssertQueryRuns(connectionPool, "REVOKE DELETE ON TABLE public.foo FROM testrole") 23 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.bar(i int)") 24 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.bar") 25 testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON TABLE public.bar FROM testrole") 26 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.baz(i int)") 27 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.baz") 28 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLE public.baz TO anothertestrole") 29 30 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 31 32 fooUniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "foo", backup.TYPE_RELATION) 33 barUniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "bar", backup.TYPE_RELATION) 34 bazUniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "baz", backup.TYPE_RELATION) 35 expectedFoo := backup.ObjectMetadata{ObjectType: "RELATION", Privileges: []backup.ACL{testutils.DefaultACLWithout("testrole", "TABLE", "DELETE")}, Owner: "testrole"} 36 expectedBar := backup.ObjectMetadata{ObjectType: "RELATION", Privileges: []backup.ACL{{Grantee: "GRANTEE"}}, Owner: "testrole"} 37 expectedBaz := backup.ObjectMetadata{ObjectType: "RELATION", Privileges: []backup.ACL{testutils.DefaultACLForType("anothertestrole", "TABLE"), testutils.DefaultACLForType("testrole", "TABLE")}, Owner: "testrole"} 38 Expect(resultMetadataMap).To(HaveLen(3)) 39 resultFoo := resultMetadataMap[fooUniqueID] 40 resultBar := resultMetadataMap[barUniqueID] 41 resultBaz := resultMetadataMap[bazUniqueID] 42 structmatcher.ExpectStructsToMatch(&resultFoo, &expectedFoo) 43 structmatcher.ExpectStructsToMatch(&resultBar, &expectedBar) 44 structmatcher.ExpectStructsToMatch(&resultBaz, &expectedBaz) 45 }) 46 It("returns a slice of default metadata for a database", func() { 47 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON DATABASE testdb TO anothertestrole") 48 defer testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON DATABASE testdb FROM anothertestRole") 49 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON DATABASE testdb IS 'This is a database comment.'") 50 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "DATABASE", "testdb") 51 expectedMetadata := backup.ObjectMetadata{ 52 ObjectType: "DATABASE", Privileges: []backup.ACL{ 53 {Grantee: "", Temporary: true, Connect: true}, 54 {Grantee: "anothertestrole", Create: true, Temporary: true, Connect: true}, 55 }, Owner: "anothertestrole", Comment: "This is a database comment."} 56 if includeSecurityLabels { 57 expectedMetadata.SecurityLabelProvider = "dummy" 58 expectedMetadata.SecurityLabel = "unclassified" 59 } 60 61 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_DATABASE) 62 63 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testdb", backup.TYPE_DATABASE) 64 resultMetadata := resultMetadataMap[uniqueID] 65 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid", "schema") 66 }) 67 It("returns a slice of default metadata for a role", func() { 68 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_ROLE) 69 numRoles := len(resultMetadataMap) 70 71 testhelper.AssertQueryRuns(connectionPool, `CREATE ROLE testuser`) 72 defer testhelper.AssertQueryRuns(connectionPool, "DROP ROLE testuser") 73 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON ROLE testuser IS 'This is a role comment.'") 74 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "ROLE", "testuser") 75 76 resultMetadataMap = backup.GetMetadataForObjectType(connectionPool, backup.TYPE_ROLE) 77 78 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testuser", backup.TYPE_ROLE) 79 expectedMetadata := testutils.DefaultMetadata("ROLE", false, false, true, includeSecurityLabels) 80 81 Expect(resultMetadataMap).To(HaveLen(numRoles + 1)) 82 resultMetadata := resultMetadataMap[uniqueID] 83 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 84 }) 85 It("returns a slice of metadata with the owner in quotes", func() { 86 testhelper.AssertQueryRuns(connectionPool, `CREATE ROLE "Role1"`) 87 defer testhelper.AssertQueryRuns(connectionPool, `DROP ROLE "Role1"`) 88 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.testtable(i int)") 89 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable") 90 testhelper.AssertQueryRuns(connectionPool, `ALTER TABLE public.testtable OWNER TO "Role1"`) 91 92 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 93 94 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testtable", backup.TYPE_RELATION) 95 expectedMetadata := backup.ObjectMetadata{ObjectType: "RELATION", Privileges: []backup.ACL{}, Owner: `"Role1"`} 96 Expect(resultMetadataMap).To(HaveLen(1)) 97 resultMetadata := resultMetadataMap[uniqueID] 98 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 99 }) 100 It("returns a slice of default metadata for a table", func() { 101 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.testtable(i int)") 102 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable") 103 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLE public.testtable TO testrole") 104 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TABLE public.testtable IS 'This is a table comment.'") 105 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "TABLE", "public.testtable") 106 107 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 108 109 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testtable", backup.TYPE_RELATION) 110 expectedMetadata := testutils.DefaultMetadata("TABLE", true, true, true, includeSecurityLabels) 111 Expect(resultMetadataMap).To(HaveLen(1)) 112 resultMetadata := resultMetadataMap[uniqueID] 113 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 114 }) 115 It("returns a slice of default metadata for a sequence", func() { 116 testhelper.AssertQueryRuns(connectionPool, "CREATE SEQUENCE public.testsequence") 117 defer testhelper.AssertQueryRuns(connectionPool, "DROP SEQUENCE public.testsequence") 118 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON SEQUENCE public.testsequence TO testrole") 119 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON SEQUENCE public.testsequence IS 'This is a sequence comment.'") 120 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "SEQUENCE", "public.testsequence") 121 122 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 123 124 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testsequence", backup.TYPE_RELATION) 125 expectedMetadata := testutils.DefaultMetadata("SEQUENCE", true, true, true, includeSecurityLabels) 126 Expect(resultMetadataMap).To(HaveLen(1)) 127 resultMetadata := resultMetadataMap[uniqueID] 128 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 129 }) 130 It("returns a slice of default metadata for a procedural language", func() { 131 plpythonString := "plpythonu" 132 if true { 133 plpythonString = "plpython3u" 134 } 135 testhelper.AssertQueryRuns(connectionPool, fmt.Sprintf("CREATE LANGUAGE %s", plpythonString)) 136 defer testhelper.AssertQueryRuns(connectionPool, fmt.Sprintf("DROP LANGUAGE %s", plpythonString)) 137 testhelper.AssertQueryRuns(connectionPool, fmt.Sprintf("COMMENT ON LANGUAGE %s IS 'This is a language comment.'", plpythonString)) 138 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "LANGUAGE", plpythonString) 139 140 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_PROCLANGUAGE) 141 142 var expectedMetadata backup.ObjectMetadata 143 if false { 144 langOwner := testutils.GetUserByID(connectionPool, 10) 145 expectedMetadata = backup.ObjectMetadata{ObjectType: "LANGUAGE", Privileges: []backup.ACL{}, Owner: langOwner, Comment: "This is a language comment."} 146 } else { 147 expectedMetadata = testutils.DefaultMetadata("LANGUAGE", false, true, true, includeSecurityLabels) 148 } 149 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", plpythonString, backup.TYPE_PROCLANGUAGE) 150 resultMetadata := resultMetadataMap[uniqueID] 151 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 152 }) 153 It("returns metadata for an empty {} ACL (not NULL)", func() { 154 testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.add(integer, integer) RETURNS integer 155 AS 'SELECT $1 + $2' 156 LANGUAGE SQL`) 157 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.add(integer, integer)") 158 testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON FUNCTION public.add(integer, integer) FROM public") 159 testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON FUNCTION public.add(integer, integer) FROM testrole") 160 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "FUNCTION", "public.add(integer, integer)") 161 162 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FUNCTION) 163 Expect(resultMetadataMap).To(HaveLen(1)) 164 165 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "add", backup.TYPE_FUNCTION) 166 resultMetadata := resultMetadataMap[uniqueID] 167 168 // important: in the case where SQL reports ACL list = {}, and not null, 169 // we expect there to be a default ACL with ALL BOOLEANS FALSE, which prints as 170 // just the 2 default "REVOKE" and no additional grant because all booleans false. 171 Expect(resultMetadata.Privileges).To(HaveLen(1)) 172 173 slabel := "" 174 slabelProvider := "" 175 if true { 176 slabel = "unclassified" 177 slabelProvider = "dummy" 178 } 179 expectedMetadata := backup.ObjectMetadata{ObjectType: "FUNCTION", Privileges: []backup.ACL{{Grantee: "GRANTEE"}}, Owner: "testrole", SecurityLabel: slabel, SecurityLabelProvider: slabelProvider} 180 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 181 }) 182 It("returns metadata for a function with a grant and revoke", func() { 183 testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.add(integer, integer) RETURNS integer 184 AS 'SELECT $1 + $2' 185 LANGUAGE SQL`) 186 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.add(integer, integer)") 187 // for Function objects: 188 // `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. 189 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON FUNCTION public.add(integer, integer) TO testrole") 190 testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON FUNCTION public.add(integer, integer) FROM PUBLIC") 191 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON FUNCTION public.add(integer, integer) IS 'This is a function comment.'") 192 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "FUNCTION", "public.add(integer, integer)") 193 194 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FUNCTION) 195 Expect(resultMetadataMap).To(HaveLen(1)) 196 197 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "add", backup.TYPE_FUNCTION) 198 resultMetadata := resultMetadataMap[uniqueID] 199 Expect(resultMetadata.Privileges).To(HaveLen(1)) 200 201 expectedMetadata := testutils.DefaultMetadata("FUNCTION", true, true, true, includeSecurityLabels) 202 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 203 }) 204 It("returns a slice of default metadata for a view", func() { 205 testhelper.AssertQueryRuns(connectionPool, `CREATE VIEW public.testview AS SELECT * FROM pg_class`) 206 defer testhelper.AssertQueryRuns(connectionPool, "DROP VIEW public.testview") 207 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON public.testview TO testrole") 208 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON VIEW public.testview IS 'This is a view comment.'") 209 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "VIEW", "public.testview") 210 211 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 212 213 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testview", backup.TYPE_RELATION) 214 expectedMetadata := testutils.DefaultMetadata("VIEW", true, true, true, includeSecurityLabels) 215 Expect(resultMetadataMap).To(HaveLen(1)) 216 resultMetadata := resultMetadataMap[uniqueID] 217 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 218 }) 219 It("returns a slice of default metadata for a materialized view", func() { 220 testhelper.AssertQueryRuns(connectionPool, `CREATE MATERIALIZED VIEW public.testmview AS SELECT * FROM pg_class`) 221 defer testhelper.AssertQueryRuns(connectionPool, "DROP MATERIALIZED VIEW public.testmview") 222 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON public.testmview TO testrole") 223 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON MATERIALIZED VIEW public.testmview IS 'This is a materialized view comment.'") 224 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "MATERIALIZED VIEW", "public.testmview") 225 226 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 227 228 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testmview", backup.TYPE_RELATION) 229 expectedMetadata := testutils.DefaultMetadata("MATERIALIZED VIEW", true, true, true, includeSecurityLabels) 230 Expect(resultMetadataMap).To(HaveLen(1)) 231 resultMetadata := resultMetadataMap[uniqueID] 232 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 233 }) 234 It("returns a slice of default metadata for a schema", func() { 235 testhelper.AssertQueryRuns(connectionPool, `CREATE SCHEMA testschema`) 236 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 237 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON SCHEMA testschema TO testrole") 238 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON SCHEMA testschema IS 'This is a schema comment.'") 239 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "SCHEMA", "testschema") 240 241 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_SCHEMA) 242 243 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testschema", backup.TYPE_SCHEMA) 244 expectedMetadata := testutils.DefaultMetadata("SCHEMA", true, true, true, includeSecurityLabels) 245 resultMetadata := resultMetadataMap[uniqueID] 246 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 247 }) 248 It("returns a slice of default metadata for an aggregate", func() { 249 testhelper.AssertQueryRuns(connectionPool, ` 250 CREATE FUNCTION public.mysfunc_accum(numeric, numeric, numeric) 251 RETURNS numeric 252 AS 'select $1 + $2 + $3' 253 LANGUAGE SQL 254 IMMUTABLE 255 RETURNS NULL ON NULL INPUT; 256 `) 257 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mysfunc_accum(numeric, numeric, numeric)") 258 testhelper.AssertQueryRuns(connectionPool, ` 259 CREATE FUNCTION public.mypre_accum(numeric, numeric) 260 RETURNS numeric 261 AS 'select $1 + $2' 262 LANGUAGE SQL 263 IMMUTABLE 264 RETURNS NULL ON NULL INPUT; 265 `) 266 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mypre_accum(numeric, numeric)") 267 testhelper.AssertQueryRuns(connectionPool, `CREATE AGGREGATE public.agg_prefunc(numeric, numeric) ( 268 SFUNC = public.mysfunc_accum, 269 STYPE = numeric, 270 PREFUNC = public.mypre_accum, 271 INITCOND = '0' 272 );`) 273 defer testhelper.AssertQueryRuns(connectionPool, "DROP AGGREGATE public.agg_prefunc(numeric, numeric)") 274 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON AGGREGATE public.agg_prefunc(numeric, numeric) IS 'This is an aggregate comment.'") 275 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "AGGREGATE", "public.agg_prefunc(numeric, numeric)") 276 277 testhelper.AssertQueryRuns(connectionPool, ` 278 GRANT ALL ON FUNCTION public.agg_prefunc(numeric, numeric) 279 to testrole`) 280 testhelper.AssertQueryRuns(connectionPool, ` 281 REVOKE ALL ON FUNCTION public.agg_prefunc(numeric, numeric) FROM public`) 282 283 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_AGGREGATE) 284 285 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "agg_prefunc", backup.TYPE_AGGREGATE) 286 expectedMetadata := testutils.DefaultMetadata("AGGREGATE", true, true, true, includeSecurityLabels) 287 resultMetadata := resultMetadataMap[uniqueID] 288 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 289 }) 290 It("returns a slice of default metadata for a type", func() { 291 testhelper.AssertQueryRuns(connectionPool, `CREATE TYPE public.testtype AS (name text, num numeric)`) 292 defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE public.testtype") 293 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TYPE public.testtype IS 'This is a type comment.'") 294 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "TYPE", "public.testtype") 295 296 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TYPE) 297 298 typeUniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testtype", backup.TYPE_TYPE) 299 expectedMetadata := testutils.DefaultMetadata("TYPE", false, true, true, includeSecurityLabels) 300 resultMetadata := resultMetadataMap[typeUniqueID] 301 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 302 }) 303 It("returns a slice of default metadata for a domain", func() { 304 testhelper.AssertQueryRuns(connectionPool, `CREATE DOMAIN public.domain_type AS numeric`) 305 defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE public.domain_type") 306 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON DOMAIN public.domain_type IS 'This is a domain comment.'") 307 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "DOMAIN", "public.domain_type") 308 309 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TYPE) 310 311 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "domain_type", backup.TYPE_TYPE) 312 expectedMetadata := testutils.DefaultMetadata("DOMAIN", false, true, true, includeSecurityLabels) 313 resultMetadata := resultMetadataMap[uniqueID] 314 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 315 }) 316 It("returns a slice of default metadata for an external protocol", func() { 317 testhelper.AssertQueryRuns(connectionPool, `CREATE OR REPLACE FUNCTION public.read_from_s3() RETURNS integer AS '$libdir/gps3ext.so', 's3_import' LANGUAGE C STABLE;`) 318 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.read_from_s3()") 319 testhelper.AssertQueryRuns(connectionPool, `CREATE TRUSTED PROTOCOL s3_read (readfunc = public.read_from_s3);`) 320 defer testhelper.AssertQueryRuns(connectionPool, "DROP PROTOCOL s3_read") 321 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON PROTOCOL s3_read TO testrole") 322 323 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_PROTOCOL) 324 325 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "s3_read", backup.TYPE_PROTOCOL) 326 expectedMetadata := testutils.DefaultMetadata("PROTOCOL", true, true, false, false) 327 resultMetadata := resultMetadataMap[uniqueID] 328 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 329 }) 330 It("returns a slice of default metadata for a tablespace", func() { 331 if false { 332 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLESPACE test_tablespace FILESPACE test_dir") 333 } else { 334 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLESPACE test_tablespace LOCATION '/tmp/test_dir'") 335 } 336 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLESPACE test_tablespace") 337 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TABLESPACE test_tablespace IS 'This is a tablespace comment.'") 338 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLESPACE test_tablespace TO testrole") 339 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "TABLESPACE", "test_tablespace") 340 341 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TABLESPACE) 342 343 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "test_tablespace", backup.TYPE_TABLESPACE) 344 expectedMetadata := testutils.DefaultMetadata("TABLESPACE", true, true, true, includeSecurityLabels) 345 resultMetadata := resultMetadataMap[uniqueID] 346 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 347 }) 348 It("returns a slice of default metadata for an operator", func() { 349 testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR public.#### (LEFTARG = bigint, PROCEDURE = numeric_fac)") 350 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR public.#### (bigint, NONE)") 351 352 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR public.#### (bigint, NONE) IS 'This is an operator comment.'") 353 354 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATOR) 355 356 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "####", backup.TYPE_OPERATOR) 357 expectedMetadata := testutils.DefaultMetadata("OPERATOR", false, true, true, false) 358 resultMetadata := resultMetadataMap[uniqueID] 359 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 360 }) 361 It("returns a slice of default metadata for an operator family", func() { 362 testutils.SkipIfBefore5(connectionPool) 363 testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR FAMILY public.testfam USING hash") 364 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY public.testfam USING hash") 365 366 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR FAMILY public.testfam USING hash IS 'This is an operator family comment.'") 367 368 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATORFAMILY) 369 370 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testfam", backup.TYPE_OPERATORFAMILY) 371 expectedMetadata := testutils.DefaultMetadata("OPERATOR FAMILY", false, true, true, false) 372 resultMetadata := resultMetadataMap[uniqueID] 373 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 374 }) 375 It("returns a slice of default metadata for an operator class", func() { 376 testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR CLASS public.testclass FOR TYPE int USING hash AS STORAGE int") 377 if false { 378 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR CLASS public.testclass USING hash") 379 } else { 380 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY public.testclass USING hash") 381 } 382 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR CLASS public.testclass USING hash IS 'This is an operator class comment.'") 383 384 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATORCLASS) 385 386 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testclass", backup.TYPE_OPERATORCLASS) 387 expectedMetadata := testutils.DefaultMetadata("OPERATOR CLASS", false, true, true, false) 388 resultMetadata := resultMetadataMap[uniqueID] 389 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 390 }) 391 It("returns a slice of default metadata for a text search dictionary", func() { 392 testutils.SkipIfBefore5(connectionPool) 393 testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH DICTIONARY public.testdictionary(TEMPLATE = snowball, LANGUAGE = 'russian', STOPWORDS = 'russian');") 394 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH DICTIONARY public.testdictionary") 395 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH DICTIONARY public.testdictionary IS 'This is a text search dictionary comment.'") 396 397 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TSDICTIONARY) 398 399 Expect(resultMetadataMap).To(HaveLen(1)) 400 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testdictionary", backup.TYPE_TSDICTIONARY) 401 dictionaryMetadata := testutils.DefaultMetadata("TEXT SEARCH DICTIONARY", false, true, true, false) 402 resultMetadata := resultMetadataMap[uniqueID] 403 structmatcher.ExpectStructsToMatch(&dictionaryMetadata, &resultMetadata) 404 }) 405 It("returns a slice of default metadata for a text search configuration", func() { 406 testutils.SkipIfBefore5(connectionPool) 407 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TSCONFIGURATION) 408 configurationMetadata := testutils.DefaultMetadata("TEXT SEARCH CONFIGURATION", false, true, true, false) 409 410 testhelper.AssertQueryRuns(connectionPool, `CREATE TEXT SEARCH CONFIGURATION public.testconfiguration (PARSER = pg_catalog."default");`) 411 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH CONFIGURATION public.testconfiguration") 412 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH CONFIGURATION public.testconfiguration IS 'This is a text search configuration comment.'") 413 414 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testconfiguration", backup.TYPE_TSCONFIGURATION) 415 resultMetadataMap = backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TSCONFIGURATION) 416 417 Expect(resultMetadataMap).To(HaveLen(1)) 418 resultMetadata := resultMetadataMap[uniqueID] 419 structmatcher.ExpectStructsToMatch(&configurationMetadata, &resultMetadata) 420 }) 421 It("returns a slice of default metadata for a foreign data wrapper", func() { 422 testutils.SkipIfBefore6(connectionPool) 423 testhelper.AssertQueryRuns(connectionPool, "CREATE FOREIGN DATA WRAPPER foreignwrapper") 424 defer testhelper.AssertQueryRuns(connectionPool, "DROP FOREIGN DATA WRAPPER foreignwrapper") 425 426 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON FOREIGN DATA WRAPPER foreignwrapper TO testrole") 427 428 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FOREIGNDATAWRAPPER) 429 430 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "foreignwrapper", backup.TYPE_FOREIGNDATAWRAPPER) 431 expectedMetadata := testutils.DefaultMetadata("FOREIGN DATA WRAPPER", true, true, false, false) 432 resultMetadata := resultMetadataMap[uniqueID] 433 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 434 }) 435 It("returns a slice of default metadata for a foreign server", func() { 436 testutils.SkipIfBefore6(connectionPool) 437 testhelper.AssertQueryRuns(connectionPool, "CREATE FOREIGN DATA WRAPPER foreignwrapper") 438 defer testhelper.AssertQueryRuns(connectionPool, "DROP FOREIGN DATA WRAPPER foreignwrapper CASCADE") 439 testhelper.AssertQueryRuns(connectionPool, "CREATE SERVER foreignserver FOREIGN DATA WRAPPER foreignwrapper") 440 441 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON FOREIGN SERVER foreignserver TO testrole") 442 443 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FOREIGNSERVER) 444 445 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "foreignserver", backup.TYPE_FOREIGNSERVER) 446 expectedMetadata := testutils.DefaultMetadata("FOREIGN SERVER", true, true, false, false) 447 resultMetadata := resultMetadataMap[uniqueID] 448 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 449 }) 450 It("returns a slice of default metadata for a collation", func() { 451 testutils.SkipIfBefore6(connectionPool) 452 testhelper.AssertQueryRuns(connectionPool, `CREATE COLLATION public.some_coll (lc_collate = 'POSIX', lc_ctype = 'POSIX');`) 453 defer testhelper.AssertQueryRuns(connectionPool, "DROP COLLATION public.some_coll") 454 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON COLLATION public.some_coll IS 'This is a collation comment.'") 455 456 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_COLLATION) 457 458 Expect(resultMetadataMap).To(HaveLen(1)) 459 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "some_coll", backup.TYPE_COLLATION) 460 collationMetadata := testutils.DefaultMetadata("COLLATION", false, true, true, false) 461 resultMetadata := resultMetadataMap[uniqueID] 462 structmatcher.ExpectStructsToMatch(&collationMetadata, &resultMetadata) 463 }) 464 It("returns a slice of default metadata for an event trigger", func() { 465 testutils.SkipIfBefore6(connectionPool) 466 testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION abort_any_command() 467 RETURNS event_trigger LANGUAGE plpgsql 468 AS $$ BEGIN RAISE EXCEPTION 'exception'; END; $$;`) 469 defer testhelper.AssertQueryRuns(connectionPool, `DROP FUNCTION abort_any_command()`) 470 testhelper.AssertQueryRuns(connectionPool, "CREATE EVENT TRIGGER test_event_trigger ON ddl_command_start EXECUTE PROCEDURE abort_any_command();") 471 defer testhelper.AssertQueryRuns(connectionPool, "DROP EVENT TRIGGER test_event_trigger") 472 testutils.CreateSecurityLabelIfGPDB6(connectionPool, "EVENT TRIGGER", "test_event_trigger") 473 474 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON EVENT TRIGGER test_event_trigger IS 'This is an event trigger comment.'") 475 476 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_EVENTTRIGGER) 477 478 Expect(resultMetadataMap).To(HaveLen(1)) 479 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "test_event_trigger", backup.TYPE_EVENTTRIGGER) 480 eventTriggerMetadata := testutils.DefaultMetadata("EVENT TRIGGER", false, true, true, true) 481 resultMetadata := resultMetadataMap[uniqueID] 482 structmatcher.ExpectStructsToMatch(&eventTriggerMetadata, &resultMetadata) 483 }) 484 It("returns ACL information for a newly declared TYPE_TYPE object", func() { 485 testutils.SkipIfBefore6(connectionPool) 486 testhelper.AssertQueryRuns(connectionPool, `CREATE TYPE public.my_type AS (i int)`) 487 defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE public.my_type") 488 testhelper.AssertQueryRuns(connectionPool, `GRANT USAGE ON TYPE public.my_type TO testrole`) 489 defer testhelper.AssertQueryRuns(connectionPool, "REVOKE usage on type public.my_type from testrole") 490 // public usage creates an entry in the ACL with GRANTEE="" . We revoke this for ease of testing. 491 testhelper.AssertQueryRuns(connectionPool, "REVOKE usage on type public.my_type from public") 492 493 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TYPE) 494 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "my_type", backup.TYPE_TYPE) 495 resultMetadata := resultMetadataMap[uniqueID] 496 497 // (1) the 'my_type' obj ... (2) the implicit 'i INT' type, created when instantiating 'my_type' 498 Expect(resultMetadataMap).To(HaveLen(2)) 499 500 expectedMetadata := testutils.DefaultMetadata("TYPE", true, true, false, false) 501 expectedMetadata.Privileges[0].Usage = true 502 Expect(&resultMetadata).To(Equal(&expectedMetadata)) 503 }) 504 }) 505 Context("metadata for objects in a specific schema", func() { 506 It("returns a slice of default metadata for a table in a specific schema", func() { 507 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.testtable(i int)") 508 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable") 509 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 510 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 511 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE testschema.testtable(i int)") 512 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE testschema.testtable") 513 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLE testschema.testtable TO testrole") 514 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TABLE testschema.testtable IS 'This is a table comment.'") 515 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 516 517 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 518 519 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtable", backup.TYPE_RELATION) 520 expectedMetadata := testutils.DefaultMetadata("TABLE", true, true, true, false) 521 Expect(resultMetadataMap).To(HaveLen(1)) 522 resultMetadata := resultMetadataMap[uniqueID] 523 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 524 }) 525 It("returns a slice of default metadata for a table not in a specific schema", func() { 526 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.testtable(i int)") 527 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable") 528 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 529 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 530 testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE testschema.testtable(i int)") 531 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE testschema.testtable") 532 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON TABLE testschema.testtable TO testrole") 533 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TABLE testschema.testtable IS 'This is a table comment.'") 534 _ = backupCmdFlags.Set(options.EXCLUDE_SCHEMA, "public") 535 536 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 537 538 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtable", backup.TYPE_RELATION) 539 expectedMetadata := testutils.DefaultMetadata("TABLE", true, true, true, false) 540 Expect(resultMetadataMap).To(HaveLen(1)) 541 resultMetadata := resultMetadataMap[uniqueID] 542 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 543 }) 544 It("returns a slice of default metadata for a function in a specific schema", func() { 545 testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.add(integer, integer) RETURNS integer 546 AS 'SELECT $1 + $2' 547 LANGUAGE SQL`) 548 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.add(integer, integer)") 549 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 550 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 551 testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION testschema.add(integer, integer) RETURNS integer 552 AS 'SELECT $1 + $2' 553 LANGUAGE SQL`) 554 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION testschema.add(integer, integer)") 555 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON FUNCTION testschema.add(integer, integer) TO testrole") 556 testhelper.AssertQueryRuns(connectionPool, "REVOKE ALL ON FUNCTION testschema.add(integer, integer) FROM PUBLIC") 557 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON FUNCTION testschema.add(integer, integer) IS 'This is a function comment.'") 558 559 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 560 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_FUNCTION) 561 562 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "add", backup.TYPE_FUNCTION) 563 expectedMetadata := testutils.DefaultMetadata("FUNCTION", true, true, true, false) 564 Expect(resultMetadataMap).To(HaveLen(1)) 565 resultMetadata := resultMetadataMap[uniqueID] 566 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 567 }) 568 It("returns a slice of default metadata for a view in a specific schema", func() { 569 testhelper.AssertQueryRuns(connectionPool, `CREATE VIEW public.testview AS SELECT * FROM pg_class`) 570 defer testhelper.AssertQueryRuns(connectionPool, "DROP VIEW public.testview") 571 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 572 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 573 testhelper.AssertQueryRuns(connectionPool, `CREATE VIEW testschema.testview AS SELECT * FROM pg_class`) 574 defer testhelper.AssertQueryRuns(connectionPool, "DROP VIEW testschema.testview") 575 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON testschema.testview TO testrole") 576 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON VIEW testschema.testview IS 'This is a view comment.'") 577 578 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 579 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 580 581 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testview", backup.TYPE_RELATION) 582 expectedMetadata := testutils.DefaultMetadata("VIEW", true, true, true, false) 583 Expect(resultMetadataMap).To(HaveLen(1)) 584 resultMetadata := resultMetadataMap[uniqueID] 585 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 586 }) 587 It("returns a slice of default metadata for a materialized view in a specific schema", func() { 588 if false { 589 Skip("Test only applicable to GPDB 6.2 and above") 590 } 591 testhelper.AssertQueryRuns(connectionPool, `CREATE MATERIALIZED VIEW public.testmview AS SELECT * FROM pg_class`) 592 defer testhelper.AssertQueryRuns(connectionPool, "DROP MATERIALIZED VIEW public.testmview") 593 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 594 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 595 testhelper.AssertQueryRuns(connectionPool, `CREATE MATERIALIZED VIEW testschema.testmview AS SELECT * FROM pg_class`) 596 defer testhelper.AssertQueryRuns(connectionPool, "DROP MATERIALIZED VIEW testschema.testmview") 597 testhelper.AssertQueryRuns(connectionPool, "GRANT ALL ON testschema.testmview TO testrole") 598 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON MATERIALIZED VIEW testschema.testmview IS 'This is a materialized view comment.'") 599 600 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 601 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_RELATION) 602 603 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testmview", backup.TYPE_RELATION) 604 expectedMetadata := testutils.DefaultMetadata("MATERIALIZED VIEW", true, true, true, false) 605 Expect(resultMetadataMap).To(HaveLen(1)) 606 resultMetadata := resultMetadataMap[uniqueID] 607 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 608 }) 609 It("returns a slice of default metadata for an aggregate in a specific schema", func() { 610 testhelper.AssertQueryRuns(connectionPool, ` 611 CREATE FUNCTION public.mysfunc_accum(numeric, numeric, numeric) 612 RETURNS numeric 613 AS 'select $1 + $2 + $3' 614 LANGUAGE SQL 615 IMMUTABLE 616 RETURNS NULL ON NULL INPUT; 617 `) 618 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mysfunc_accum(numeric, numeric, numeric)") 619 testhelper.AssertQueryRuns(connectionPool, ` 620 CREATE FUNCTION public.mypre_accum(numeric, numeric) 621 RETURNS numeric 622 AS 'select $1 + $2' 623 LANGUAGE SQL 624 IMMUTABLE 625 RETURNS NULL ON NULL INPUT; 626 `) 627 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.mypre_accum(numeric, numeric)") 628 testhelper.AssertQueryRuns(connectionPool, `CREATE AGGREGATE public.agg_prefunc(numeric, numeric) ( 629 SFUNC = public.mysfunc_accum, 630 STYPE = numeric, 631 PREFUNC = public.mypre_accum, 632 INITCOND = '0' 633 );`) 634 defer testhelper.AssertQueryRuns(connectionPool, "DROP AGGREGATE public.agg_prefunc(numeric, numeric)") 635 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON AGGREGATE public.agg_prefunc(numeric, numeric) IS 'This is an aggregate comment.'") 636 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 637 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 638 testhelper.AssertQueryRuns(connectionPool, `CREATE AGGREGATE testschema.agg_prefunc(numeric, numeric) ( 639 SFUNC = public.mysfunc_accum, 640 STYPE = numeric, 641 PREFUNC = public.mypre_accum, 642 INITCOND = '0' 643 );`) 644 defer testhelper.AssertQueryRuns(connectionPool, "DROP AGGREGATE testschema.agg_prefunc(numeric, numeric)") 645 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON AGGREGATE testschema.agg_prefunc(numeric, numeric) IS 'This is an aggregate comment.'") 646 647 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 648 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_AGGREGATE) 649 650 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "agg_prefunc", backup.TYPE_AGGREGATE) 651 expectedMetadata := testutils.DefaultMetadata("AGGREGATE", false, true, true, false) 652 Expect(resultMetadataMap).To(HaveLen(1)) 653 resultMetadata := resultMetadataMap[uniqueID] 654 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 655 }) 656 It("returns a slice of default metadata for a type in a specific schema", func() { 657 testhelper.AssertQueryRuns(connectionPool, `CREATE TYPE public.testtype`) 658 defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE public.testtype") 659 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 660 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 661 testhelper.AssertQueryRuns(connectionPool, `CREATE TYPE testschema.testtype AS (name text)`) 662 defer testhelper.AssertQueryRuns(connectionPool, "DROP TYPE testschema.testtype") 663 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TYPE testschema.testtype IS 'This is a type comment.'") 664 665 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 666 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TYPE) 667 668 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtype", backup.TYPE_TYPE) 669 expectedMetadata := testutils.DefaultMetadata("TYPE", false, true, true, false) 670 resultMetadata := resultMetadataMap[uniqueID] 671 if false { 672 // In 4.3, creating testtype does not generate a "_testtype" entry in pg_type 673 Expect(resultMetadataMap).To(HaveLen(1)) 674 } else { 675 // In 5, creating testtype generates 2 entries in pg_type, "testtype" and "_testtype" 676 Expect(resultMetadataMap).To(HaveLen(2)) 677 } 678 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 679 }) 680 It("returns a slice of default metadata for an operator in a specific schema", func() { 681 testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR public.#### (LEFTARG = bigint, PROCEDURE = numeric_fac)") 682 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR public.#### (bigint, NONE)") 683 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 684 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 685 testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR testschema.#### (LEFTARG = bigint, PROCEDURE = numeric_fac)") 686 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR testschema.#### (bigint, NONE)") 687 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR testschema.#### (bigint, NONE) IS 'This is an operator comment.'") 688 689 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 690 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATOR) 691 692 Expect(resultMetadataMap).To(HaveLen(1)) 693 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "####", backup.TYPE_OPERATOR) 694 expectedMetadata := testutils.DefaultMetadata("OPERATOR", false, true, true, false) 695 resultMetadata := resultMetadataMap[uniqueID] 696 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 697 }) 698 It("returns a slice of default metadata for an operator family in a specific schema", func() { 699 testutils.SkipIfBefore5(connectionPool) 700 testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR FAMILY public.testfam USING hash") 701 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY public.testfam USING hash") 702 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 703 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 704 testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR FAMILY testschema.testfam USING hash") 705 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY testschema.testfam USING hash") 706 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR FAMILY testschema.testfam USING hash IS 'This is an operator family comment.'") 707 708 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 709 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATORFAMILY) 710 711 Expect(resultMetadataMap).To(HaveLen(1)) 712 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testfam", backup.TYPE_OPERATORFAMILY) 713 expectedMetadata := testutils.DefaultMetadata("OPERATOR FAMILY", false, true, true, false) 714 resultMetadata := resultMetadataMap[uniqueID] 715 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 716 }) 717 It("returns a slice of default metadata for an operator class in a specific schema", func() { 718 testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR CLASS public.testclass FOR TYPE int4 USING hash AS STORAGE int4") 719 if false { 720 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR CLASS public.testclass USING hash CASCADE") 721 } else { 722 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY public.testclass USING hash CASCADE") 723 } 724 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 725 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 726 testhelper.AssertQueryRuns(connectionPool, "CREATE OPERATOR CLASS testschema.testclass FOR TYPE int4 USING hash AS STORAGE int4") 727 if false { 728 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR CLASS testschema.testclass USING hash CASCADE") 729 } else { 730 defer testhelper.AssertQueryRuns(connectionPool, "DROP OPERATOR FAMILY testschema.testclass USING hash CASCADE") 731 } 732 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON OPERATOR CLASS testschema.testclass USING hash IS 'This is an operator class comment.'") 733 734 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 735 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_OPERATORCLASS) 736 737 Expect(resultMetadataMap).To(HaveLen(1)) 738 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testclass", backup.TYPE_OPERATORCLASS) 739 expectedMetadata := testutils.DefaultMetadata("OPERATOR CLASS", false, true, true, false) 740 resultMetadata := resultMetadataMap[uniqueID] 741 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 742 }) 743 It("returns a slice of default metadata for a text search dictionary in a specific schema", func() { 744 testutils.SkipIfBefore5(connectionPool) 745 testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH DICTIONARY public.testdictionary(TEMPLATE = snowball, LANGUAGE = 'russian', STOPWORDS = 'russian');") 746 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH DICTIONARY public.testdictionary") 747 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 748 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 749 testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH DICTIONARY testschema.testdictionary(TEMPLATE = snowball, LANGUAGE = 'russian', STOPWORDS = 'russian');") 750 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH DICTIONARY testschema.testdictionary") 751 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH DICTIONARY testschema.testdictionary IS 'This is a text search dictionary comment.'") 752 753 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 754 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TSDICTIONARY) 755 756 Expect(resultMetadataMap).To(HaveLen(1)) 757 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testdictionary", backup.TYPE_TSDICTIONARY) 758 dictionaryMetadata := testutils.DefaultMetadata("TEXT SEARCH DICTIONARY", false, true, true, false) 759 resultMetadata := resultMetadataMap[uniqueID] 760 structmatcher.ExpectStructsToMatch(&dictionaryMetadata, &resultMetadata) 761 }) 762 It("returns a slice of default metadata for a text search configuration in a specific schema", func() { 763 testutils.SkipIfBefore5(connectionPool) 764 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TSCONFIGURATION) 765 configurationMetadata := testutils.DefaultMetadata("TEXT SEARCH CONFIGURATION", false, true, true, false) 766 767 testhelper.AssertQueryRuns(connectionPool, `CREATE TEXT SEARCH CONFIGURATION public.testconfiguration (PARSER = pg_catalog."default");`) 768 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH CONFIGURATION public.testconfiguration") 769 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 770 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 771 testhelper.AssertQueryRuns(connectionPool, `CREATE TEXT SEARCH CONFIGURATION testschema.testconfiguration (PARSER = pg_catalog."default");`) 772 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH CONFIGURATION testschema.testconfiguration") 773 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH CONFIGURATION testschema.testconfiguration IS 'This is a text search configuration comment.'") 774 775 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 776 resultMetadataMap = backup.GetMetadataForObjectType(connectionPool, backup.TYPE_TSCONFIGURATION) 777 778 Expect(resultMetadataMap).To(HaveLen(1)) 779 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testconfiguration", backup.TYPE_TSCONFIGURATION) 780 resultMetadata := resultMetadataMap[uniqueID] 781 structmatcher.ExpectStructsToMatch(&configurationMetadata, &resultMetadata) 782 }) 783 It("returns a slice of default metadata for a collation in a specific schema", func() { 784 testutils.SkipIfBefore6(connectionPool) 785 testhelper.AssertQueryRuns(connectionPool, `CREATE COLLATION public.some_coll (lc_collate = 'POSIX', lc_ctype = 'POSIX');`) 786 defer testhelper.AssertQueryRuns(connectionPool, "DROP COLLATION public.some_coll") 787 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 788 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 789 testhelper.AssertQueryRuns(connectionPool, `CREATE COLLATION testschema.some_coll (lc_collate = 'POSIX', lc_ctype = 'POSIX');`) 790 defer testhelper.AssertQueryRuns(connectionPool, "DROP COLLATION testschema.some_coll") 791 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON COLLATION testschema.some_coll IS 'This is a collation comment.'") 792 793 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 794 resultMetadataMap := backup.GetMetadataForObjectType(connectionPool, backup.TYPE_COLLATION) 795 796 Expect(resultMetadataMap).To(HaveLen(1)) 797 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "some_coll", backup.TYPE_COLLATION) 798 collationMetadata := testutils.DefaultMetadata("COLLATION", false, true, true, false) 799 resultMetadata := resultMetadataMap[uniqueID] 800 structmatcher.ExpectStructsToMatch(&collationMetadata, &resultMetadata) 801 }) 802 }) 803 }) 804 Describe("GetDefaultPrivileges", func() { 805 BeforeEach(func() { 806 testutils.SkipIfBefore6(connectionPool) 807 }) 808 It("returns default privileges with single privilege", func() { 809 testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES REVOKE USAGE ON SEQUENCES FROM testrole;") 810 defer testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES GRANT USAGE ON SEQUENCES TO testrole;") 811 812 resultDefaultPrivileges := backup.GetDefaultPrivileges(connectionPool) 813 814 privs := []backup.ACL{{Grantee: "testrole", Update: true, Select: true}} 815 expectedDefaultPrivileges := backup.DefaultPrivileges{Schema: "", Privileges: privs, ObjectType: "S", Owner: "testrole"} 816 Expect(resultDefaultPrivileges).To(HaveLen(1)) 817 structmatcher.ExpectStructsToMatchExcluding(&expectedDefaultPrivileges, &resultDefaultPrivileges[0], "Oid") 818 }) 819 It("returns default privileges with multiple privileges", func() { 820 testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES TO PUBLIC;") 821 defer testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES REVOKE SELECT ON TABLES FROM PUBLIC;") 822 823 resultDefaultPrivileges := backup.GetDefaultPrivileges(connectionPool) 824 825 privs := []backup.ACL{{Grantee: "", Select: true}, testutils.DefaultACLForType("testrole", "TABLE")} 826 expectedDefaultPrivileges := backup.DefaultPrivileges{Schema: "", Privileges: privs, ObjectType: "r", Owner: "testrole"} 827 Expect(resultDefaultPrivileges).To(HaveLen(1)) 828 structmatcher.ExpectStructsToMatchExcluding(&expectedDefaultPrivileges, &resultDefaultPrivileges[0], "Oid") 829 }) 830 It("returns default privileges for role", func() { 831 testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES FOR ROLE anothertestrole GRANT USAGE ON SEQUENCES TO testrole;") 832 defer testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES FOR ROLE anothertestrole REVOKE USAGE ON SEQUENCES FROM testrole;") 833 834 resultDefaultPrivileges := backup.GetDefaultPrivileges(connectionPool) 835 836 privs := []backup.ACL{{Grantee: "anothertestrole", Select: true, Update: true, Usage: true}, {Grantee: "testrole", Usage: true}} 837 expectedDefaultPrivileges := backup.DefaultPrivileges{Schema: "", Privileges: privs, ObjectType: "S", Owner: "anothertestrole"} 838 Expect(resultDefaultPrivileges).To(HaveLen(1)) 839 structmatcher.ExpectStructsToMatchExcluding(&expectedDefaultPrivileges, &resultDefaultPrivileges[0], "Oid") 840 }) 841 It("returns default privileges in schema", func() { 842 testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE ON SEQUENCES TO testrole;") 843 defer testhelper.AssertQueryRuns(connectionPool, "ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE USAGE ON SEQUENCES FROM testrole;") 844 845 resultDefaultPrivileges := backup.GetDefaultPrivileges(connectionPool) 846 847 privs := []backup.ACL{{Grantee: "testrole", Usage: true}} 848 expectedDefaultPrivileges := backup.DefaultPrivileges{Schema: "public", Privileges: privs, ObjectType: "S", Owner: "testrole"} 849 Expect(resultDefaultPrivileges).To(HaveLen(1)) 850 structmatcher.ExpectStructsToMatchExcluding(&expectedDefaultPrivileges, &resultDefaultPrivileges[0], "Oid") 851 }) 852 853 }) 854 Describe("GetCommentsForObjectType", func() { 855 Context("comments for all objects of one type", func() { 856 It("returns a slice of default metadata for an index", func() { 857 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_INDEX) 858 numIndexes := len(resultMetadataMap) 859 860 testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int)`) 861 testhelper.AssertQueryRuns(connectionPool, `CREATE INDEX testindex ON public.testtable USING btree(i)`) 862 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable") 863 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON INDEX public.testindex IS 'This is an index comment.'") 864 865 resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_INDEX) 866 867 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testindex", backup.TYPE_INDEX) 868 expectedMetadata := testutils.DefaultMetadata("INDEX", false, false, true, false) 869 870 Expect(resultMetadataMap).To(HaveLen(numIndexes + 1)) 871 resultMetadata := resultMetadataMap[uniqueID] 872 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 873 }) 874 It("returns a slice of default metadata for a rule", func() { 875 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_RULE) 876 numRules := len(resultMetadataMap) 877 878 testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int)`) 879 testhelper.AssertQueryRuns(connectionPool, `CREATE RULE update_notify AS ON UPDATE TO public.testtable DO NOTIFY testtable`) 880 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable") 881 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON RULE update_notify ON public.testtable IS 'This is a rule comment.'") 882 883 resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_RULE) 884 885 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "update_notify", backup.TYPE_RULE) 886 expectedMetadata := testutils.DefaultMetadata("RULE", false, false, true, false) 887 888 Expect(resultMetadataMap).To(HaveLen(numRules + 1)) 889 resultMetadata := resultMetadataMap[uniqueID] 890 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 891 }) 892 It("returns a slice of default metadata for a trigger", func() { 893 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TRIGGER) 894 numTriggers := len(resultMetadataMap) 895 896 testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int)`) 897 if false { 898 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"()`) 899 } else { 900 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"()`) 901 } 902 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable") 903 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TRIGGER sync_testtable ON public.testtable IS 'This is a trigger comment.'") 904 905 resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TRIGGER) 906 907 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "sync_testtable", backup.TYPE_TRIGGER) 908 expectedMetadata := testutils.DefaultMetadata("TRIGGER", false, false, true, false) 909 910 Expect(resultMetadataMap).To(HaveLen(numTriggers + 1)) 911 resultMetadata := resultMetadataMap[uniqueID] 912 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 913 }) 914 It("returns a slice of default metadata for a cast in 4.3", func() { 915 testutils.SkipIfNot4(connectionPool) 916 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_CAST) 917 numCasts := len(resultMetadataMap) 918 919 testhelper.AssertQueryRuns(connectionPool, "CREATE FUNCTION public.casttotext(bool) RETURNS text STRICT IMMUTABLE LANGUAGE PLPGSQL AS $$ BEGIN IF $1 IS TRUE THEN RETURN 'true'; ELSE RETURN 'false'; END IF; END; $$;") 920 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.casttotext(bool) CASCADE") 921 testhelper.AssertQueryRuns(connectionPool, "CREATE CAST (bool AS text) WITH FUNCTION public.casttotext(bool) AS ASSIGNMENT") 922 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON CAST (bool AS text) IS 'This is a cast comment.'") 923 924 resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_CAST) 925 926 boolOid := testutils.OidFromObjectName(connectionPool, "", "bool", backup.TYPE_TYPE) 927 textOid := testutils.OidFromObjectName(connectionPool, "", "text", backup.TYPE_TYPE) 928 oid := testutils.OidFromCast(connectionPool, boolOid, textOid) 929 expectedMetadata := testutils.DefaultMetadata("CAST", false, false, true, false) 930 931 Expect(resultMetadataMap).To(HaveLen(numCasts + 1)) 932 resultMetadata := resultMetadataMap[backup.UniqueID{ClassID: backup.PG_CAST_OID, Oid: oid}] 933 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 934 }) 935 It("returns a slice of default metadata for a cast in 5", func() { 936 testutils.SkipIfBefore5(connectionPool) 937 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_CAST) 938 numCasts := len(resultMetadataMap) 939 940 testhelper.AssertQueryRuns(connectionPool, `CREATE FUNCTION public.casttoint(text) RETURNS integer STRICT IMMUTABLE LANGUAGE SQL AS 'SELECT cast($1 as integer);'`) 941 defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.casttoint(text) CASCADE") 942 testhelper.AssertQueryRuns(connectionPool, "CREATE CAST (text AS int) WITH FUNCTION public.casttoint(text) AS ASSIGNMENT;") 943 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON CAST (text AS int) IS 'This is a cast comment.'") 944 945 resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_CAST) 946 947 textOid := testutils.OidFromObjectName(connectionPool, "", "text", backup.TYPE_TYPE) 948 intOid := testutils.OidFromObjectName(connectionPool, "", "int4", backup.TYPE_TYPE) 949 oid := testutils.OidFromCast(connectionPool, textOid, intOid) 950 expectedMetadata := testutils.DefaultMetadata("CAST", false, false, true, false) 951 952 Expect(resultMetadataMap).To(HaveLen(numCasts + 1)) 953 resultMetadata := resultMetadataMap[backup.UniqueID{ClassID: backup.PG_CAST_OID, Oid: oid}] 954 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 955 }) 956 It("returns a slice of default metadata for a resource queue", func() { 957 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_RESOURCEQUEUE) 958 numResQueues := len(resultMetadataMap) 959 960 testhelper.AssertQueryRuns(connectionPool, `CREATE RESOURCE QUEUE res_queue WITH (MAX_COST=32.8);`) 961 defer testhelper.AssertQueryRuns(connectionPool, "DROP RESOURCE QUEUE res_queue") 962 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON RESOURCE QUEUE res_queue IS 'This is a resource queue comment.'") 963 964 resultMetadataMap = backup.GetCommentsForObjectType(connectionPool, backup.TYPE_RESOURCEQUEUE) 965 966 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "res_queue", backup.TYPE_RESOURCEQUEUE) 967 expectedMetadata := testutils.DefaultMetadata("RESOURCE QUEUE", false, false, true, false) 968 969 Expect(resultMetadataMap).To(HaveLen(numResQueues + 1)) 970 resultMetadata := resultMetadataMap[uniqueID] 971 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 972 }) 973 It("returns a slice of default metadata for a text search parser", func() { 974 testutils.SkipIfBefore5(connectionPool) 975 parserMetadata := testutils.DefaultMetadata("TEXT SEARCH PARSER", false, false, true, false) 976 977 testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH PARSER public.testparser(START = prsd_start, GETTOKEN = prsd_nexttoken, END = prsd_end, LEXTYPES = prsd_lextype);") 978 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH PARSER public.testparser") 979 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH PARSER public.testparser IS 'This is a text search parser comment.'") 980 981 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testparser", backup.TYPE_TSPARSER) 982 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TSPARSER) 983 984 Expect(resultMetadataMap).To(HaveLen(1)) 985 resultMetadata := resultMetadataMap[uniqueID] 986 structmatcher.ExpectStructsToMatch(&parserMetadata, &resultMetadata) 987 }) 988 It("returns a slice of default metadata for a text search template", func() { 989 testutils.SkipIfBefore5(connectionPool) 990 templateMetadata := testutils.DefaultMetadata("TEXT SEARCH TEMPLATE", false, false, true, false) 991 992 testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH TEMPLATE public.testtemplate(LEXIZE = dsimple_lexize);") 993 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH TEMPLATE public.testtemplate") 994 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH TEMPLATE public.testtemplate IS 'This is a text search template comment.'") 995 996 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "public", "testtemplate", backup.TYPE_TSTEMPLATE) 997 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TSTEMPLATE) 998 999 Expect(resultMetadataMap).To(HaveLen(1)) 1000 resultMetadata := resultMetadataMap[uniqueID] 1001 structmatcher.ExpectStructsToMatch(&templateMetadata, &resultMetadata) 1002 }) 1003 It("returns a slice of default metadata for an extension", func() { 1004 testutils.SkipIfBefore5(connectionPool) 1005 extensionMetadata := testutils.DefaultMetadata("EXTENSION", false, false, true, false) 1006 1007 testhelper.AssertQueryRuns(connectionPool, "CREATE EXTENSION plperl;") 1008 defer testhelper.AssertQueryRuns(connectionPool, "DROP EXTENSION plperl") 1009 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON EXTENSION plperl IS 'This is an extension comment.'") 1010 1011 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "plperl", backup.TYPE_EXTENSION) 1012 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_EXTENSION) 1013 1014 Expect(resultMetadataMap).To(HaveLen(1)) 1015 resultMetadata := resultMetadataMap[uniqueID] 1016 structmatcher.ExpectStructsToMatch(&extensionMetadata, &resultMetadata) 1017 }) 1018 }) 1019 Context("comments for objects in a specific schema", func() { 1020 It("returns a slice of default metadata for an index in a specific schema", func() { 1021 1022 testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int)`) 1023 testhelper.AssertQueryRuns(connectionPool, `CREATE INDEX testindex ON public.testtable USING btree(i)`) 1024 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable") 1025 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 1026 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 1027 testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE testschema.testtable(i int)`) 1028 testhelper.AssertQueryRuns(connectionPool, `CREATE INDEX testindex1 ON testschema.testtable USING btree(i)`) 1029 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE testschema.testtable") 1030 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON INDEX testschema.testindex1 IS 'This is an index comment.'") 1031 1032 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 1033 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_INDEX) 1034 1035 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "", "testindex1", backup.TYPE_INDEX) 1036 expectedMetadata := testutils.DefaultMetadata("INDEX", false, false, true, false) 1037 1038 resultMetadata := resultMetadataMap[uniqueID] 1039 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 1040 }) 1041 It("returns a slice of default metadata for a constraint in a specific schema", func() { 1042 testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE public.testtable(i int UNIQUE)`) 1043 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.testtable") 1044 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON CONSTRAINT testtable_i_key ON public.testtable IS 'This is a constraint comment.'") 1045 1046 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 1047 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 1048 testhelper.AssertQueryRuns(connectionPool, `CREATE TABLE testschema.testtable(i int UNIQUE)`) 1049 defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE testschema.testtable") 1050 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON CONSTRAINT testtable_i_key ON testschema.testtable IS 'This is a constraint comment.'") 1051 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 1052 1053 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_CONSTRAINT) 1054 1055 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtable_i_key", backup.TYPE_CONSTRAINT) 1056 expectedMetadata := testutils.DefaultMetadata("CONSTRAINT", false, false, true, false) 1057 1058 Expect(resultMetadataMap).To(HaveLen(1)) 1059 resultMetadata := resultMetadataMap[uniqueID] 1060 structmatcher.ExpectStructsToMatchExcluding(&expectedMetadata, &resultMetadata, "Oid") 1061 }) 1062 It("returns a slice of default metadata for a text search parser in a specific schema", func() { 1063 testutils.SkipIfBefore5(connectionPool) 1064 parserMetadata := testutils.DefaultMetadata("TEXT SEARCH PARSER", false, false, true, false) 1065 1066 testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH PARSER public.testparser(START = prsd_start, GETTOKEN = prsd_nexttoken, END = prsd_end, LEXTYPES = prsd_lextype);") 1067 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH PARSER public.testparser") 1068 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 1069 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 1070 testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH PARSER testschema.testparser(START = prsd_start, GETTOKEN = prsd_nexttoken, END = prsd_end, LEXTYPES = prsd_lextype);") 1071 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH PARSER testschema.testparser") 1072 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH PARSER testschema.testparser IS 'This is a text search parser comment.'") 1073 1074 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testparser", backup.TYPE_TSPARSER) 1075 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 1076 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TSPARSER) 1077 1078 Expect(resultMetadataMap).To(HaveLen(1)) 1079 resultMetadata := resultMetadataMap[uniqueID] 1080 structmatcher.ExpectStructsToMatch(&parserMetadata, &resultMetadata) 1081 }) 1082 It("returns a slice of default metadata for a text search template in a specific schema", func() { 1083 testutils.SkipIfBefore5(connectionPool) 1084 templateMetadata := testutils.DefaultMetadata("TEXT SEARCH TEMPLATE", false, false, true, false) 1085 1086 testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH TEMPLATE public.testtemplate(LEXIZE = dsimple_lexize);") 1087 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH TEMPLATE public.testtemplate") 1088 testhelper.AssertQueryRuns(connectionPool, "CREATE SCHEMA testschema") 1089 defer testhelper.AssertQueryRuns(connectionPool, "DROP SCHEMA testschema") 1090 testhelper.AssertQueryRuns(connectionPool, "CREATE TEXT SEARCH TEMPLATE testschema.testtemplate(LEXIZE = dsimple_lexize);") 1091 defer testhelper.AssertQueryRuns(connectionPool, "DROP TEXT SEARCH TEMPLATE testschema.testtemplate") 1092 testhelper.AssertQueryRuns(connectionPool, "COMMENT ON TEXT SEARCH TEMPLATE testschema.testtemplate IS 'This is a text search template comment.'") 1093 1094 uniqueID := testutils.UniqueIDFromObjectName(connectionPool, "testschema", "testtemplate", backup.TYPE_TSTEMPLATE) 1095 _ = backupCmdFlags.Set(options.INCLUDE_SCHEMA, "testschema") 1096 resultMetadataMap := backup.GetCommentsForObjectType(connectionPool, backup.TYPE_TSTEMPLATE) 1097 1098 Expect(resultMetadataMap).To(HaveLen(1)) 1099 resultMetadata := resultMetadataMap[uniqueID] 1100 structmatcher.ExpectStructsToMatch(&templateMetadata, &resultMetadata) 1101 }) 1102 }) 1103 }) 1104 })