diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index a89a8bde5da..5c974b762f3 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -149,6 +149,7 @@ typedef struct _restoreOptions bool single_txn; bool *idWanted; /* array showing which dump IDs to emit */ + int binary_upgrade; } RestoreOptions; typedef void (*SetupWorkerPtr) (Archive *AH, RestoreOptions *ropt); diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index f156325d03e..0bae989c4c1 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -2557,7 +2557,17 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt) /* Mask it if we only want schema */ if (ropt->schemaOnly) - res = res & REQ_SCHEMA; + { + /* + * In binary-upgrade mode, even with schema-only set, we do not mask + * out large objects. Only large object definitions, comments and + * other information should be generated in binary-upgrade mode (not + * the actual data). + */ + if (!(ropt->binary_upgrade && strcmp(te->desc,"BLOB") == 0) && + !(ropt->binary_upgrade && strncmp(te->tag,"LARGE OBJECT ", 13) == 0)) + res = res & REQ_SCHEMA; + } /* Mask it if we only want data */ if (ropt->dataOnly) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index bc55ba79780..a9ea3700090 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -771,7 +771,15 @@ main(int argc, char **argv) getTableDataFKConstraints(); } - if (outputBlobs) + /* + * In binary-upgrade mode, we do not have to worry about the actual blob + * data or the associated metadata that resides in the pg_largeobject and + * pg_largeobject_metadata tables, respectivly. + * + * However, we do need to collect blob information as there may be + * comments or other information on blobs that we do need to dump out. + */ + if (outputBlobs || binary_upgrade) getBlobs(fout); /* @@ -844,6 +852,7 @@ main(int argc, char **argv) ropt->noTablespace = outputNoTablespaces; ropt->disable_triggers = disable_triggers; ropt->use_setsessauth = use_setsessauth; + ropt->binary_upgrade = binary_upgrade; if (compressLevel == -1) ropt->compression = 0; @@ -2771,8 +2780,14 @@ dumpBlob(Archive *fout, BlobInfo *binfo) NULL, binfo->rolname, binfo->dobj.catId, 0, binfo->dobj.dumpId); - /* Dump ACL if any */ - if (binfo->blobacl) + /* + * Dump ACL if any + * + * Do not dump the ACL in binary-upgrade mode, however, as the ACL will be + * copied over by pg_upgrade as it is part of the pg_largeobject_metadata + * table. + */ + if (binfo->blobacl && !binary_upgrade) dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT", binfo->dobj.name, NULL, cquery->data, NULL, binfo->rolname, binfo->blobacl); @@ -2797,6 +2812,13 @@ dumpBlobs(Archive *fout, void *arg) int i; int cnt; + /* + * Do not dump out blob data in binary-upgrade mode, pg_upgrade will copy + * the pg_largeobject table over entirely from the old cluster. + */ + if (binary_upgrade) + return 1; + if (g_verbose) write_msg(NULL, "saving large objects\n"); @@ -7514,7 +7536,8 @@ dumpComment(Archive *fout, const char *target, } else { - if (schemaOnly) + /* We do dump blob comments in binary-upgrade mode */ + if (schemaOnly && !binary_upgrade) return; } @@ -12504,7 +12527,8 @@ dumpSecLabel(Archive *fout, const char *target, } else { - if (schemaOnly) + /* We do dump blob security labels in binary-upgrade mode */ + if (schemaOnly && !binary_upgrade) return; } diff --git a/src/test/regress/expected/large_object.out b/src/test/regress/expected/large_object.out new file mode 100644 index 00000000000..b00d47cc75e --- /dev/null +++ b/src/test/regress/expected/large_object.out @@ -0,0 +1,15 @@ +-- This is more-or-less DROP IF EXISTS LARGE OBJECT 3001; +WITH unlink AS (SELECT lo_unlink(loid) FROM pg_largeobject WHERE loid = 3001) SELECT 1; + ?column? +---------- + 1 +(1 row) + +-- Test creation of a large object and leave it for testing pg_upgrade +SELECT lo_create(3001); + lo_create +----------- + 3001 +(1 row) + +COMMENT ON LARGE OBJECT 3001 IS 'testing comments'; diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index f4aae91eedc..16b1ea7f250 100644 --- a/src/test/regress/expected/privileges.out +++ b/src/test/regress/expected/privileges.out @@ -12,7 +12,7 @@ DROP ROLE IF EXISTS regressuser3; DROP ROLE IF EXISTS regressuser4; DROP ROLE IF EXISTS regressuser5; DROP ROLE IF EXISTS regressuser6; -SELECT lo_unlink(oid) FROM pg_largeobject_metadata; +SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid; lo_unlink ----------- (0 rows) @@ -1143,11 +1143,11 @@ SELECT lo_unlink(2002); \c - -- confirm ACL setting -SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata; +SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid; oid | ownername | lomacl ------+--------------+------------------------------------------------------------------------------------------ - 1002 | regressuser1 | 1001 | regressuser1 | {regressuser1=rw/regressuser1,=rw/regressuser1} + 1002 | regressuser1 | 1003 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r/regressuser1} 1004 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=rw/regressuser1} 1005 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r*w/regressuser1,regressuser3=r/regressuser2} @@ -1488,7 +1488,7 @@ DROP TABLE atest6; DROP TABLE atestc; DROP TABLE atestp1; DROP TABLE atestp2; -SELECT lo_unlink(oid) FROM pg_largeobject_metadata; +SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid; lo_unlink ----------- 1 diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 4c6ce9702c5..b8984088bb1 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -83,7 +83,7 @@ test: select_into select_distinct select_distinct_on select_implicit select_havi # ---------- # Another group of parallel tests # ---------- -test: privileges security_label collate matview +test: privileges security_label collate matview large_object # ---------- # Another group of parallel tests diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 57fc93d3cda..dee345a5dfb 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -96,6 +96,7 @@ test: privileges test: security_label test: collate test: matview +test: large_object test: alter_generic test: misc test: psql diff --git a/src/test/regress/sql/large_object.sql b/src/test/regress/sql/large_object.sql new file mode 100644 index 00000000000..c06b393dd36 --- /dev/null +++ b/src/test/regress/sql/large_object.sql @@ -0,0 +1,7 @@ +-- This is more-or-less DROP IF EXISTS LARGE OBJECT 3001; +WITH unlink AS (SELECT lo_unlink(loid) FROM pg_largeobject WHERE loid = 3001) SELECT 1; + +-- Test creation of a large object and leave it for testing pg_upgrade +SELECT lo_create(3001); + +COMMENT ON LARGE OBJECT 3001 IS 'testing comments'; diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql index 1dc44d46a84..e71ade178de 100644 --- a/src/test/regress/sql/privileges.sql +++ b/src/test/regress/sql/privileges.sql @@ -17,7 +17,7 @@ DROP ROLE IF EXISTS regressuser4; DROP ROLE IF EXISTS regressuser5; DROP ROLE IF EXISTS regressuser6; -SELECT lo_unlink(oid) FROM pg_largeobject_metadata; +SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid; RESET client_min_messages; @@ -712,7 +712,7 @@ SELECT lo_unlink(2002); \c - -- confirm ACL setting -SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata; +SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid; SET SESSION AUTHORIZATION regressuser3; @@ -916,7 +916,7 @@ DROP TABLE atestc; DROP TABLE atestp1; DROP TABLE atestp2; -SELECT lo_unlink(oid) FROM pg_largeobject_metadata; +SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid; DROP GROUP regressgroup1; DROP GROUP regressgroup2;