diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index e0c2bd3cb52..b049264caf1 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -144,6 +144,7 @@ typedef struct _restoreOptions int number_of_jobs; bool *idWanted; /* array showing which dump IDs to emit */ + int binary_upgrade; } RestoreOptions; /* diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 41cb89692a2..753f92e68f8 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -2576,7 +2576,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 2010d804b94..08841232d98 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -730,7 +730,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); /* @@ -799,6 +807,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; @@ -2423,8 +2432,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); @@ -2449,6 +2464,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"); @@ -7001,7 +7023,8 @@ dumpComment(Archive *fout, const char *target, } else { - if (schemaOnly) + /* We do dump blob comments in binary-upgrade mode */ + if (schemaOnly && !binary_upgrade) return; } @@ -11985,7 +12008,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 266a905066a..5af54576fe2 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) @@ -1125,11 +1125,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} @@ -1469,7 +1469,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 1b5560f9704..2292fd35338 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 +test: privileges security_label collate large_object test: misc # rules cannot run concurrently with any test that creates a view diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 355fe74a0bc..da3b46b8f86 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -94,6 +94,7 @@ test: prepared_xacts test: privileges test: security_label test: collate +test: large_object test: misc test: rules test: select_views 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 16786ffbdce..c856e497661 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; @@ -694,7 +694,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; @@ -897,7 +897,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;