Skip to content

Commit 7f831f0

Browse files
committed
pg_upgrade: Fix large object COMMENTS, SECURITY LABELS
When performing a pg_upgrade, we copy the files behind pg_largeobject and pg_largeobject_metadata, allowing us to avoid having to dump out and reload the actual data for large objects and their ACLs. Unfortunately, that isn't all of the information which can be associated with large objects. Currently, we also support COMMENTs and SECURITY LABELs with large objects and these were being silently dropped during a pg_upgrade as pg_dump would skip everything having to do with a large object and pg_upgrade only copied the tables mentioned to the new cluster. As the file copies happen after the catalog dump and reload, we can't simply include the COMMENTs and SECURITY LABELs in pg_dump's binary-mode output but we also have to include the actual large object definition as well. With the definition, comments, and security labels in the pg_dump output and the file copies performed by pg_upgrade, all of the data and metadata associated with large objects is able to be successfully pulled forward across a pg_upgrade. In 9.6 and master, we can simply adjust the dump bitmask to indicate which components we don't want. In 9.5 and earlier, we have to put explciit checks in in dumpBlob() and dumpBlobs() to not include the ACL or the data when in binary-upgrade mode. Adjustments made to the privileges regression test to allow another test (large_object.sql) to be added which explicitly leaves a large object with a comment in place to provide coverage of that case with pg_upgrade. Back-patch to all supported branches. Discussion: https://postgr.es/m/20170221162655.GE9812@tamriel.snowman.net
1 parent 6987277 commit 7f831f0

File tree

9 files changed

+72
-14
lines changed

9 files changed

+72
-14
lines changed

src/bin/pg_dump/pg_backup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ typedef struct _restoreOptions
149149
bool single_txn;
150150

151151
bool *idWanted; /* array showing which dump IDs to emit */
152+
int binary_upgrade;
152153
} RestoreOptions;
153154

154155
typedef void (*SetupWorkerPtr) (Archive *AH, RestoreOptions *ropt);

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2557,7 +2557,17 @@ _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt)
25572557

25582558
/* Mask it if we only want schema */
25592559
if (ropt->schemaOnly)
2560-
res = res & REQ_SCHEMA;
2560+
{
2561+
/*
2562+
* In binary-upgrade mode, even with schema-only set, we do not mask
2563+
* out large objects. Only large object definitions, comments and
2564+
* other information should be generated in binary-upgrade mode (not
2565+
* the actual data).
2566+
*/
2567+
if (!(ropt->binary_upgrade && strcmp(te->desc,"BLOB") == 0) &&
2568+
!(ropt->binary_upgrade && strncmp(te->tag,"LARGE OBJECT ", 13) == 0))
2569+
res = res & REQ_SCHEMA;
2570+
}
25612571

25622572
/* Mask it if we only want data */
25632573
if (ropt->dataOnly)

src/bin/pg_dump/pg_dump.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,15 @@ main(int argc, char **argv)
771771
getTableDataFKConstraints();
772772
}
773773

774-
if (outputBlobs)
774+
/*
775+
* In binary-upgrade mode, we do not have to worry about the actual blob
776+
* data or the associated metadata that resides in the pg_largeobject and
777+
* pg_largeobject_metadata tables, respectivly.
778+
*
779+
* However, we do need to collect blob information as there may be
780+
* comments or other information on blobs that we do need to dump out.
781+
*/
782+
if (outputBlobs || binary_upgrade)
775783
getBlobs(fout);
776784

777785
/*
@@ -844,6 +852,7 @@ main(int argc, char **argv)
844852
ropt->noTablespace = outputNoTablespaces;
845853
ropt->disable_triggers = disable_triggers;
846854
ropt->use_setsessauth = use_setsessauth;
855+
ropt->binary_upgrade = binary_upgrade;
847856

848857
if (compressLevel == -1)
849858
ropt->compression = 0;
@@ -2771,8 +2780,14 @@ dumpBlob(Archive *fout, BlobInfo *binfo)
27712780
NULL, binfo->rolname,
27722781
binfo->dobj.catId, 0, binfo->dobj.dumpId);
27732782

2774-
/* Dump ACL if any */
2775-
if (binfo->blobacl)
2783+
/*
2784+
* Dump ACL if any
2785+
*
2786+
* Do not dump the ACL in binary-upgrade mode, however, as the ACL will be
2787+
* copied over by pg_upgrade as it is part of the pg_largeobject_metadata
2788+
* table.
2789+
*/
2790+
if (binfo->blobacl && !binary_upgrade)
27762791
dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
27772792
binfo->dobj.name, NULL, cquery->data,
27782793
NULL, binfo->rolname, binfo->blobacl);
@@ -2797,6 +2812,13 @@ dumpBlobs(Archive *fout, void *arg)
27972812
int i;
27982813
int cnt;
27992814

2815+
/*
2816+
* Do not dump out blob data in binary-upgrade mode, pg_upgrade will copy
2817+
* the pg_largeobject table over entirely from the old cluster.
2818+
*/
2819+
if (binary_upgrade)
2820+
return 1;
2821+
28002822
if (g_verbose)
28012823
write_msg(NULL, "saving large objects\n");
28022824

@@ -7514,7 +7536,8 @@ dumpComment(Archive *fout, const char *target,
75147536
}
75157537
else
75167538
{
7517-
if (schemaOnly)
7539+
/* We do dump blob comments in binary-upgrade mode */
7540+
if (schemaOnly && !binary_upgrade)
75187541
return;
75197542
}
75207543

@@ -12504,7 +12527,8 @@ dumpSecLabel(Archive *fout, const char *target,
1250412527
}
1250512528
else
1250612529
{
12507-
if (schemaOnly)
12530+
/* We do dump blob security labels in binary-upgrade mode */
12531+
if (schemaOnly && !binary_upgrade)
1250812532
return;
1250912533
}
1251012534

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- This is more-or-less DROP IF EXISTS LARGE OBJECT 3001;
2+
WITH unlink AS (SELECT lo_unlink(loid) FROM pg_largeobject WHERE loid = 3001) SELECT 1;
3+
?column?
4+
----------
5+
1
6+
(1 row)
7+
8+
-- Test creation of a large object and leave it for testing pg_upgrade
9+
SELECT lo_create(3001);
10+
lo_create
11+
-----------
12+
3001
13+
(1 row)
14+
15+
COMMENT ON LARGE OBJECT 3001 IS 'testing comments';

src/test/regress/expected/privileges.out

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ DROP ROLE IF EXISTS regressuser3;
1212
DROP ROLE IF EXISTS regressuser4;
1313
DROP ROLE IF EXISTS regressuser5;
1414
DROP ROLE IF EXISTS regressuser6;
15-
SELECT lo_unlink(oid) FROM pg_largeobject_metadata;
15+
SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid;
1616
lo_unlink
1717
-----------
1818
(0 rows)
@@ -1143,11 +1143,11 @@ SELECT lo_unlink(2002);
11431143

11441144
\c -
11451145
-- confirm ACL setting
1146-
SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata;
1146+
SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid;
11471147
oid | ownername | lomacl
11481148
------+--------------+------------------------------------------------------------------------------------------
1149-
1002 | regressuser1 |
11501149
1001 | regressuser1 | {regressuser1=rw/regressuser1,=rw/regressuser1}
1150+
1002 | regressuser1 |
11511151
1003 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r/regressuser1}
11521152
1004 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=rw/regressuser1}
11531153
1005 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r*w/regressuser1,regressuser3=r/regressuser2}
@@ -1488,7 +1488,7 @@ DROP TABLE atest6;
14881488
DROP TABLE atestc;
14891489
DROP TABLE atestp1;
14901490
DROP TABLE atestp2;
1491-
SELECT lo_unlink(oid) FROM pg_largeobject_metadata;
1491+
SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid;
14921492
lo_unlink
14931493
-----------
14941494
1

src/test/regress/parallel_schedule

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ test: select_into select_distinct select_distinct_on select_implicit select_havi
8383
# ----------
8484
# Another group of parallel tests
8585
# ----------
86-
test: privileges security_label collate matview
86+
test: privileges security_label collate matview large_object
8787

8888
# ----------
8989
# Another group of parallel tests

src/test/regress/serial_schedule

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ test: privileges
9696
test: security_label
9797
test: collate
9898
test: matview
99+
test: large_object
99100
test: alter_generic
100101
test: misc
101102
test: psql

src/test/regress/sql/large_object.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- This is more-or-less DROP IF EXISTS LARGE OBJECT 3001;
2+
WITH unlink AS (SELECT lo_unlink(loid) FROM pg_largeobject WHERE loid = 3001) SELECT 1;
3+
4+
-- Test creation of a large object and leave it for testing pg_upgrade
5+
SELECT lo_create(3001);
6+
7+
COMMENT ON LARGE OBJECT 3001 IS 'testing comments';

src/test/regress/sql/privileges.sql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ DROP ROLE IF EXISTS regressuser4;
1717
DROP ROLE IF EXISTS regressuser5;
1818
DROP ROLE IF EXISTS regressuser6;
1919

20-
SELECT lo_unlink(oid) FROM pg_largeobject_metadata;
20+
SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid;
2121

2222
RESET client_min_messages;
2323

@@ -712,7 +712,7 @@ SELECT lo_unlink(2002);
712712

713713
\c -
714714
-- confirm ACL setting
715-
SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata;
715+
SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid;
716716

717717
SET SESSION AUTHORIZATION regressuser3;
718718

@@ -916,7 +916,7 @@ DROP TABLE atestc;
916916
DROP TABLE atestp1;
917917
DROP TABLE atestp2;
918918

919-
SELECT lo_unlink(oid) FROM pg_largeobject_metadata;
919+
SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid;
920920

921921
DROP GROUP regressgroup1;
922922
DROP GROUP regressgroup2;

0 commit comments

Comments
 (0)