Skip to content

Commit 6be8647

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 420d9ec commit 6be8647

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
@@ -116,6 +116,7 @@ typedef struct _restoreOptions
116116

117117
bool *idWanted; /* array showing which dump IDs to emit */
118118
int enable_row_security;
119+
int binary_upgrade;
119120
} RestoreOptions;
120121

121122
typedef struct _dumpOptions

src/bin/pg_dump/pg_backup_archiver.c

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

27812781
/* Mask it if we only want schema */
27822782
if (ropt->schemaOnly)
2783-
res = res & REQ_SCHEMA;
2783+
{
2784+
/*
2785+
* In binary-upgrade mode, even with schema-only set, we do not mask
2786+
* out large objects. Only large object definitions, comments and
2787+
* other information should be generated in binary-upgrade mode (not
2788+
* the actual data).
2789+
*/
2790+
if (!(ropt->binary_upgrade && strcmp(te->desc,"BLOB") == 0) &&
2791+
!(ropt->binary_upgrade && strncmp(te->tag,"LARGE OBJECT ", 13) == 0))
2792+
res = res & REQ_SCHEMA;
2793+
}
27842794

27852795
/* Mask it if we only want data */
27862796
if (ropt->dataOnly)

src/bin/pg_dump/pg_dump.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,15 @@ main(int argc, char **argv)
747747
getTableDataFKConstraints();
748748
}
749749

750-
if (dopt.outputBlobs)
750+
/*
751+
* In binary-upgrade mode, we do not have to worry about the actual blob
752+
* data or the associated metadata that resides in the pg_largeobject and
753+
* pg_largeobject_metadata tables, respectivly.
754+
*
755+
* However, we do need to collect blob information as there may be
756+
* comments or other information on blobs that we do need to dump out.
757+
*/
758+
if (dopt.outputBlobs || dopt.binary_upgrade)
751759
getBlobs(fout);
752760

753761
/*
@@ -830,6 +838,7 @@ main(int argc, char **argv)
830838
ropt->lockWaitTimeout = dopt.lockWaitTimeout;
831839
ropt->include_everything = dopt.include_everything;
832840
ropt->enable_row_security = dopt.enable_row_security;
841+
ropt->binary_upgrade = dopt.binary_upgrade;
833842

834843
if (compressLevel == -1)
835844
ropt->compression = 0;
@@ -2825,8 +2834,14 @@ dumpBlob(Archive *fout, BlobInfo *binfo)
28252834
NULL, binfo->rolname,
28262835
binfo->dobj.catId, 0, binfo->dobj.dumpId);
28272836

2828-
/* Dump ACL if any */
2829-
if (binfo->blobacl)
2837+
/*
2838+
* Dump ACL if any
2839+
*
2840+
* Do not dump the ACL in binary-upgrade mode, however, as the ACL will be
2841+
* copied over by pg_upgrade as it is part of the pg_largeobject_metadata
2842+
* table.
2843+
*/
2844+
if (binfo->blobacl && !fout->dopt->binary_upgrade)
28302845
dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
28312846
binfo->dobj.name, NULL, cquery->data,
28322847
NULL, binfo->rolname, binfo->blobacl);
@@ -2851,6 +2866,13 @@ dumpBlobs(Archive *fout, void *arg)
28512866
int i;
28522867
int cnt;
28532868

2869+
/*
2870+
* Do not dump out blob data in binary-upgrade mode, pg_upgrade will copy
2871+
* the pg_largeobject table over entirely from the old cluster.
2872+
*/
2873+
if (fout->dopt->binary_upgrade)
2874+
return 1;
2875+
28542876
if (g_verbose)
28552877
write_msg(NULL, "saving large objects\n");
28562878

@@ -8113,7 +8135,8 @@ dumpComment(Archive *fout, const char *target,
81138135
}
81148136
else
81158137
{
8116-
if (dopt->schemaOnly)
8138+
/* We do dump blob comments in binary-upgrade mode */
8139+
if (dopt->schemaOnly && !dopt->binary_upgrade)
81178140
return;
81188141
}
81198142

@@ -13496,7 +13519,8 @@ dumpSecLabel(Archive *fout, const char *target,
1349613519
}
1349713520
else
1349813521
{
13499-
if (dopt->schemaOnly)
13522+
/* We do dump blob security labels in binary-upgrade mode */
13523+
if (dopt->schemaOnly && !dopt->binary_upgrade)
1350013524
return;
1350113525
}
1350213526

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)
@@ -1174,11 +1174,11 @@ SELECT lo_unlink(2002);
11741174

11751175
\c -
11761176
-- confirm ACL setting
1177-
SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata;
1177+
SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid;
11781178
oid | ownername | lomacl
11791179
------+--------------+------------------------------------------------------------------------------------------
1180-
1002 | regressuser1 |
11811180
1001 | regressuser1 | {regressuser1=rw/regressuser1,=rw/regressuser1}
1181+
1002 | regressuser1 |
11821182
1003 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r/regressuser1}
11831183
1004 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=rw/regressuser1}
11841184
1005 | regressuser1 | {regressuser1=rw/regressuser1,regressuser2=r*w/regressuser1,regressuser3=r/regressuser2}
@@ -1547,7 +1547,7 @@ DROP TABLE atest6;
15471547
DROP TABLE atestc;
15481548
DROP TABLE atestp1;
15491549
DROP TABLE atestp2;
1550-
SELECT lo_unlink(oid) FROM pg_largeobject_metadata;
1550+
SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid;
15511551
lo_unlink
15521552
-----------
15531553
1

src/test/regress/parallel_schedule

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ test: select_into select_distinct select_distinct_on select_implicit select_havi
8484
# ----------
8585
# Another group of parallel tests
8686
# ----------
87-
test: brin gin gist spgist privileges security_label collate matview lock replica_identity rowsecurity object_address tablesample groupingsets
87+
test: brin gin gist spgist privileges security_label collate matview lock replica_identity rowsecurity object_address tablesample groupingsets large_object
8888

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

src/test/regress/serial_schedule

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ test: replica_identity
112112
test: rowsecurity
113113
test: object_address
114114
test: tablesample
115+
test: large_object
115116
test: alter_generic
116117
test: misc
117118
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

@@ -729,7 +729,7 @@ SELECT lo_unlink(2002);
729729

730730
\c -
731731
-- confirm ACL setting
732-
SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata;
732+
SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid;
733733

734734
SET SESSION AUTHORIZATION regressuser3;
735735

@@ -960,7 +960,7 @@ DROP TABLE atestc;
960960
DROP TABLE atestp1;
961961
DROP TABLE atestp2;
962962

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

965965
DROP GROUP regressgroup1;
966966
DROP GROUP regressgroup2;

0 commit comments

Comments
 (0)