Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 8728b2c

Browse files
committed
Fix pg_dump/pg_restore to restore event triggers later.
Previously, event triggers were restored just after regular triggers (and FK constraints, which are basically triggers). This is risky since an event trigger, once installed, could interfere with subsequent restore commands. Worse, because event triggers don't have any particular dependencies on any post-data objects, a parallel restore would consider them eligible to be restored the moment the post-data phase starts, allowing them to also interfere with restoration of a whole bunch of objects that would have been restored before them in a serial restore. There's no way to completely remove the risk of a misguided event trigger breaking the restore, since if nothing else it could break other event triggers. But we can certainly push them to later in the process to minimize the hazard. To fix, tweak the RestorePass mechanism introduced by commit 3eb9a5e so that event triggers are handled as part of the post-ACL processing pass (renaming the "REFRESH" pass to "POST_ACL" to reflect its more general use). This will cause them to restore after everything except matview refreshes, which seems OK since matview refreshes really ought to run in the post-restore state of the database. In a parallel restore, event triggers and matview refreshes might be intermixed, but that seems all right as well. Also update the code and comments in pg_dump_sort.c so that its idea of how things are sorted agrees with what actually happens due to the RestorePass mechanism. This is mostly cosmetic: it'll affect the order of objects in a dump's TOC, but not the actual restore order. But not changing that would be quite confusing to somebody reading the code. Back-patch to all supported branches. Fabrízio de Royes Mello, tweaked a bit by me Discussion: https://postgr.es/m/CAFcNs+ow1hmFox8P--3GSdtwz-S3Binb6ZmoP6Vk+Xg=K6eZNA@mail.gmail.com
1 parent 24d8595 commit 8728b2c

File tree

3 files changed

+36
-24
lines changed

3 files changed

+36
-24
lines changed

src/bin/pg_dump/pg_backup_archiver.c

+10-9
Original file line numberDiff line numberDiff line change
@@ -670,11 +670,11 @@ RestoreArchive(Archive *AHX)
670670
{
671671
/*
672672
* In serial mode, process everything in three phases: normal items,
673-
* then ACLs, then matview refresh items. We might be able to skip
674-
* one or both extra phases in some cases, eg data-only restores.
673+
* then ACLs, then post-ACL items. We might be able to skip one or
674+
* both extra phases in some cases, eg data-only restores.
675675
*/
676676
bool haveACL = false;
677-
bool haveRefresh = false;
677+
bool havePostACL = false;
678678

679679
for (te = AH->toc->next; te != AH->toc; te = te->next)
680680
{
@@ -689,8 +689,8 @@ RestoreArchive(Archive *AHX)
689689
case RESTORE_PASS_ACL:
690690
haveACL = true;
691691
break;
692-
case RESTORE_PASS_REFRESH:
693-
haveRefresh = true;
692+
case RESTORE_PASS_POST_ACL:
693+
havePostACL = true;
694694
break;
695695
}
696696
}
@@ -705,12 +705,12 @@ RestoreArchive(Archive *AHX)
705705
}
706706
}
707707

708-
if (haveRefresh)
708+
if (havePostACL)
709709
{
710710
for (te = AH->toc->next; te != AH->toc; te = te->next)
711711
{
712712
if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 &&
713-
_tocEntryRestorePass(te) == RESTORE_PASS_REFRESH)
713+
_tocEntryRestorePass(te) == RESTORE_PASS_POST_ACL)
714714
(void) restore_toc_entry(AH, te, false);
715715
}
716716
}
@@ -3082,8 +3082,9 @@ _tocEntryRestorePass(TocEntry *te)
30823082
strcmp(te->desc, "ACL LANGUAGE") == 0 ||
30833083
strcmp(te->desc, "DEFAULT ACL") == 0)
30843084
return RESTORE_PASS_ACL;
3085-
if (strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3086-
return RESTORE_PASS_REFRESH;
3085+
if (strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3086+
strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3087+
return RESTORE_PASS_POST_ACL;
30873088
return RESTORE_PASS_MAIN;
30883089
}
30893090

src/bin/pg_dump/pg_backup_archiver.h

+10-6
Original file line numberDiff line numberDiff line change
@@ -209,20 +209,24 @@ typedef enum
209209
* data restore failures. On the other hand, matview REFRESH commands should
210210
* come out after ACLs, as otherwise non-superuser-owned matviews might not
211211
* be able to execute. (If the permissions at the time of dumping would not
212-
* allow a REFRESH, too bad; we won't fix that for you.) These considerations
213-
* force us to make three passes over the TOC, restoring the appropriate
214-
* subset of items in each pass. We assume that the dependency sort resulted
215-
* in an appropriate ordering of items within each subset.
212+
* allow a REFRESH, too bad; we won't fix that for you.) We also want event
213+
* triggers to be restored after ACLs, so that they can't mess those up.
214+
*
215+
* These considerations force us to make three passes over the TOC,
216+
* restoring the appropriate subset of items in each pass. We assume that
217+
* the dependency sort resulted in an appropriate ordering of items within
218+
* each subset.
219+
*
216220
* XXX This mechanism should be superseded by tracking dependencies on ACLs
217221
* properly; but we'll still need it for old dump files even after that.
218222
*/
219223
typedef enum
220224
{
221225
RESTORE_PASS_MAIN = 0, /* Main pass (most TOC item types) */
222226
RESTORE_PASS_ACL, /* ACL item types */
223-
RESTORE_PASS_REFRESH /* Matview REFRESH items */
227+
RESTORE_PASS_POST_ACL /* Event trigger and matview refresh items */
224228

225-
#define RESTORE_PASS_LAST RESTORE_PASS_REFRESH
229+
#define RESTORE_PASS_LAST RESTORE_PASS_POST_ACL
226230
} RestorePass;
227231

228232
typedef enum

src/bin/pg_dump/pg_dump_sort.c

+16-9
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,15 @@
2424
* Sort priority for database object types.
2525
* Objects are sorted by type, and within a type by name.
2626
*
27-
* Because materialized views can potentially reference system views,
28-
* DO_REFRESH_MATVIEW should always be the last thing on the list.
27+
* Triggers, event triggers, and materialized views are intentionally sorted
28+
* late. Triggers must be restored after all data modifications, so that
29+
* they don't interfere with loading data. Event triggers are restored
30+
* next-to-last so that they don't interfere with object creations of any
31+
* kind. Matview refreshes are last because they should execute in the
32+
* database's normal state (e.g., they must come after all ACLs are restored;
33+
* also, if they choose to look at system catalogs, they should see the final
34+
* restore state). If you think to change this, see also the RestorePass
35+
* mechanism in pg_backup_archiver.c.
2936
*
3037
* NOTE: object-type priorities must match the section assignments made in
3138
* pg_dump.c; that is, PRE_DATA objects must sort before DO_PRE_DATA_BOUNDARY,
@@ -66,18 +73,18 @@ static const int dbObjectTypePriority[] =
6673
15, /* DO_TSCONFIG */
6774
16, /* DO_FDW */
6875
17, /* DO_FOREIGN_SERVER */
69-
33, /* DO_DEFAULT_ACL */
76+
38, /* DO_DEFAULT_ACL --- done in ACL pass */
7077
3, /* DO_TRANSFORM */
7178
21, /* DO_BLOB */
7279
25, /* DO_BLOB_DATA */
7380
22, /* DO_PRE_DATA_BOUNDARY */
7481
26, /* DO_POST_DATA_BOUNDARY */
75-
34, /* DO_EVENT_TRIGGER */
76-
39, /* DO_REFRESH_MATVIEW */
77-
35, /* DO_POLICY */
78-
36, /* DO_PUBLICATION */
79-
37, /* DO_PUBLICATION_REL */
80-
38 /* DO_SUBSCRIPTION */
82+
39, /* DO_EVENT_TRIGGER --- next to last! */
83+
40, /* DO_REFRESH_MATVIEW --- last! */
84+
34, /* DO_POLICY */
85+
35, /* DO_PUBLICATION */
86+
36, /* DO_PUBLICATION_REL */
87+
37 /* DO_SUBSCRIPTION */
8188
};
8289

8390
StaticAssertDecl(lengthof(dbObjectTypePriority) == (DO_SUBSCRIPTION + 1),

0 commit comments

Comments
 (0)