diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 40c77af540..e1ac16079c 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -671,11 +671,11 @@ RestoreArchive(Archive *AHX) { /* * In serial mode, process everything in three phases: normal items, - * then ACLs, then matview refresh items. We might be able to skip - * one or both extra phases in some cases, eg data-only restores. + * then ACLs, then post-ACL items. We might be able to skip one or + * both extra phases in some cases, eg data-only restores. */ bool haveACL = false; - bool haveRefresh = false; + bool havePostACL = false; for (te = AH->toc->next; te != AH->toc; te = te->next) { @@ -690,8 +690,8 @@ RestoreArchive(Archive *AHX) case RESTORE_PASS_ACL: haveACL = true; break; - case RESTORE_PASS_REFRESH: - haveRefresh = true; + case RESTORE_PASS_POST_ACL: + havePostACL = true; break; } } @@ -706,12 +706,12 @@ RestoreArchive(Archive *AHX) } } - if (haveRefresh) + if (havePostACL) { for (te = AH->toc->next; te != AH->toc; te = te->next) { if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0 && - _tocEntryRestorePass(te) == RESTORE_PASS_REFRESH) + _tocEntryRestorePass(te) == RESTORE_PASS_POST_ACL) (void) restore_toc_entry(AH, te, false); } } @@ -3088,8 +3088,9 @@ _tocEntryRestorePass(TocEntry *te) strcmp(te->desc, "ACL LANGUAGE") == 0 || strcmp(te->desc, "DEFAULT ACL") == 0) return RESTORE_PASS_ACL; - if (strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0) - return RESTORE_PASS_REFRESH; + if (strcmp(te->desc, "EVENT TRIGGER") == 0 || + strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0) + return RESTORE_PASS_POST_ACL; return RESTORE_PASS_MAIN; } diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index db13507b47..aca03381dd 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -211,10 +211,14 @@ typedef enum * data restore failures. On the other hand, matview REFRESH commands should * come out after ACLs, as otherwise non-superuser-owned matviews might not * be able to execute. (If the permissions at the time of dumping would not - * allow a REFRESH, too bad; we won't fix that for you.) These considerations - * force us to make three passes over the TOC, restoring the appropriate - * subset of items in each pass. We assume that the dependency sort resulted - * in an appropriate ordering of items within each subset. + * allow a REFRESH, too bad; we won't fix that for you.) We also want event + * triggers to be restored after ACLs, so that they can't mess those up. + * + * These considerations force us to make three passes over the TOC, + * restoring the appropriate subset of items in each pass. We assume that + * the dependency sort resulted in an appropriate ordering of items within + * each subset. + * * XXX This mechanism should be superseded by tracking dependencies on ACLs * properly; but we'll still need it for old dump files even after that. */ @@ -222,9 +226,9 @@ typedef enum { RESTORE_PASS_MAIN = 0, /* Main pass (most TOC item types) */ RESTORE_PASS_ACL, /* ACL item types */ - RESTORE_PASS_REFRESH /* Matview REFRESH items */ + RESTORE_PASS_POST_ACL /* Event trigger and matview refresh items */ -#define RESTORE_PASS_LAST RESTORE_PASS_REFRESH +#define RESTORE_PASS_LAST RESTORE_PASS_POST_ACL } RestorePass; typedef enum diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index b87f8da8ae..398e984cef 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -25,8 +25,15 @@ * Sort priority for database object types. * Objects are sorted by type, and within a type by name. * - * Because materialized views can potentially reference system views, - * DO_REFRESH_MATVIEW should always be the last thing on the list. + * Triggers, event triggers, and materialized views are intentionally sorted + * late. Triggers must be restored after all data modifications, so that + * they don't interfere with loading data. Event triggers are restored + * next-to-last so that they don't interfere with object creations of any + * kind. Matview refreshes are last because they should execute in the + * database's normal state (e.g., they must come after all ACLs are restored; + * also, if they choose to look at system catalogs, they should see the final + * restore state). If you think to change this, see also the RestorePass + * mechanism in pg_backup_archiver.c. * * NOTE: object-type priorities must match the section assignments made in * pg_dump.c; that is, PRE_DATA objects must sort before DO_PRE_DATA_BOUNDARY, @@ -67,18 +74,18 @@ static const int dbObjectTypePriority[] = 15, /* DO_TSCONFIG */ 16, /* DO_FDW */ 17, /* DO_FOREIGN_SERVER */ - 33, /* DO_DEFAULT_ACL */ + 38, /* DO_DEFAULT_ACL --- done in ACL pass */ 3, /* DO_TRANSFORM */ 21, /* DO_BLOB */ 25, /* DO_BLOB_DATA */ 22, /* DO_PRE_DATA_BOUNDARY */ 26, /* DO_POST_DATA_BOUNDARY */ - 34, /* DO_EVENT_TRIGGER */ - 39, /* DO_REFRESH_MATVIEW */ - 35, /* DO_POLICY */ - 36, /* DO_PUBLICATION */ - 37, /* DO_PUBLICATION_REL */ - 38 /* DO_SUBSCRIPTION */ + 39, /* DO_EVENT_TRIGGER --- next to last! */ + 40, /* DO_REFRESH_MATVIEW --- last! */ + 34, /* DO_POLICY */ + 35, /* DO_PUBLICATION */ + 36, /* DO_PUBLICATION_REL */ + 37 /* DO_SUBSCRIPTION */ }; static DumpId preDataBoundId;