diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 796a0aa..6cc5cb2 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -73,6 +73,7 @@ static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te); static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te); static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt); static bool _tocEntryIsACL(TocEntry *te); +static bool _tocEntryIsACLorLater(TocEntry *te); static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te); static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te); static void buildTocEntryArrays(ArchiveHandle *AH); @@ -695,8 +696,8 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel) AH->currentTE = te; /* Work out what, if anything, we want from this entry */ - if (_tocEntryIsACL(te)) - reqs = 0; /* ACLs are never restored here */ + if (_tocEntryIsACLorLater(te)) + reqs = 0; /* ACLs and later are never restored here */ else reqs = te->reqs; @@ -2851,6 +2852,19 @@ _tocEntryIsACL(TocEntry *te) } /* + * Identify TOC entries that are ACLs or must follow ACLs for correct + * behavior. + */ +static bool +_tocEntryIsACLorLater(TocEntry *te) +{ + if (_tocEntryIsACL(te) || + strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0) + return true; + return false; +} + +/* * Issue SET commands for parameters that we want to have set the same way * at all times during execution of a restore script. */ @@ -3254,15 +3268,15 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData, bool acl_pass) { RestoreOptions *ropt = AH->public.ropt; - /* ACLs are dumped only during acl pass */ + /* ACLs and objects that depend on them are dumped only during acl pass */ if (acl_pass) { - if (!_tocEntryIsACL(te)) + if (!_tocEntryIsACLorLater(te)) return; } else { - if (_tocEntryIsACL(te)) + if (_tocEntryIsACLorLater(te)) return; } @@ -3808,7 +3822,7 @@ restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate, { /* If not to be restored, don't waste time launching a worker */ if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0 || - _tocEntryIsACL(next_work_item)) + _tocEntryIsACLorLater(next_work_item)) { ahlog(AH, 1, "skipping item %d %s %s\n", next_work_item->dumpId, diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index d87f08d..9711f16 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -67,15 +67,15 @@ static const int oldObjectTypePriority[] = 4, /* DO_TSCONFIG */ 4, /* DO_FDW */ 4, /* DO_FOREIGN_SERVER */ - 19, /* DO_DEFAULT_ACL */ + 20, /* DO_DEFAULT_ACL */ 4, /* DO_TRANSFORM */ 9, /* DO_BLOB */ 12, /* DO_BLOB_DATA */ 10, /* DO_PRE_DATA_BOUNDARY */ 13, /* DO_POST_DATA_BOUNDARY */ - 20, /* DO_EVENT_TRIGGER */ - 15, /* DO_REFRESH_MATVIEW */ - 21 /* DO_POLICY */ + 21, /* DO_EVENT_TRIGGER */ + 19, /* DO_REFRESH_MATVIEW */ + 22 /* DO_POLICY */ }; /* @@ -125,8 +125,8 @@ static const int newObjectTypePriority[] = 22, /* DO_PRE_DATA_BOUNDARY */ 25, /* DO_POST_DATA_BOUNDARY */ 32, /* DO_EVENT_TRIGGER */ - 33, /* DO_REFRESH_MATVIEW */ - 34 /* DO_POLICY */ + 34, /* DO_REFRESH_MATVIEW */ + 33 /* DO_POLICY */ }; static DumpId preDataBoundId; diff --git a/src/test/regress/expected/matview.out b/src/test/regress/expected/matview.out index 102bf1f..f1681df 100644 --- a/src/test/regress/expected/matview.out +++ b/src/test/regress/expected/matview.out @@ -515,6 +515,17 @@ create materialized view mvtest_error as select 1/0 as x with no data; refresh materialized view mvtest_error; -- fail here ERROR: division by zero drop materialized view mvtest_error; +-- leave objects for dump/restore tests, to ensure that permissions are set +-- in time for REFRESH execution (also bug #13907, and others) +CREATE ROLE regress_user_mvtest1; +CREATE ROLE regress_user_mvtest2; +CREATE TABLE mvtest_t1 AS SELECT i FROM generate_series(1, 10) i; +CREATE VIEW mvtest_v_t1 AS SELECT * FROM mvtest_t1; +ALTER TABLE mvtest_t1 OWNER TO regress_user_mvtest1; +ALTER VIEW mvtest_v_t1 OWNER TO regress_user_mvtest2; +GRANT SELECT ON mvtest_t1 TO regress_user_mvtest2; +CREATE MATERIALIZED VIEW mvtest_mv_v_t1 AS SELECT * FROM mvtest_v_t1; +ALTER MATERIALIZED VIEW mvtest_mv_v_t1 OWNER TO regress_user_mvtest2; -- make sure that matview rows can be referenced as source rows (bug #9398) CREATE TABLE mvtest_v AS SELECT generate_series(1,10) AS a; CREATE MATERIALIZED VIEW mvtest_mv_v AS SELECT a FROM mvtest_v WHERE a <= 5; diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index ad44ae2..30d051c 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1297,6 +1297,8 @@ mvtest_tvv| SELECT sum(mvtest_tv.totamt) AS grandtot FROM mvtest_tv; mvtest_tvvmv| SELECT mvtest_tvvm.grandtot FROM mvtest_tvvm; +mvtest_v_t1| SELECT mvtest_t1.i + FROM mvtest_t1; pg_available_extension_versions| SELECT e.name, e.version, (x.extname IS NOT NULL) AS installed, diff --git a/src/test/regress/output/misc.source b/src/test/regress/output/misc.source index 5c88aad..98cd12f 100644 --- a/src/test/regress/output/misc.source +++ b/src/test/regress/output/misc.source @@ -648,7 +648,9 @@ SELECT user_relns() AS user_relns main_table money_data mvtest_bb + mvtest_mv_v_t1 mvtest_t + mvtest_t1 mvtest_tm mvtest_tmm mvtest_tv @@ -657,6 +659,7 @@ SELECT user_relns() AS user_relns mvtest_tvv mvtest_tvvm mvtest_tvvmv + mvtest_v_t1 num_data num_exp_add num_exp_div @@ -710,7 +713,7 @@ SELECT user_relns() AS user_relns toyemp varchar_tbl xacttest -(132 rows) +(135 rows) SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))); name diff --git a/src/test/regress/sql/matview.sql b/src/test/regress/sql/matview.sql index a108b69..0c5840b 100644 --- a/src/test/regress/sql/matview.sql +++ b/src/test/regress/sql/matview.sql @@ -204,6 +204,18 @@ create materialized view mvtest_error as select 1/0 as x with no data; refresh materialized view mvtest_error; -- fail here drop materialized view mvtest_error; +-- leave objects for dump/restore tests, to ensure that permissions are set +-- in time for REFRESH execution (also bug #13907, and others) +CREATE ROLE regress_user_mvtest1; +CREATE ROLE regress_user_mvtest2; +CREATE TABLE mvtest_t1 AS SELECT i FROM generate_series(1, 10) i; +CREATE VIEW mvtest_v_t1 AS SELECT * FROM mvtest_t1; +ALTER TABLE mvtest_t1 OWNER TO regress_user_mvtest1; +ALTER VIEW mvtest_v_t1 OWNER TO regress_user_mvtest2; +GRANT SELECT ON mvtest_t1 TO regress_user_mvtest2; +CREATE MATERIALIZED VIEW mvtest_mv_v_t1 AS SELECT * FROM mvtest_v_t1; +ALTER MATERIALIZED VIEW mvtest_mv_v_t1 OWNER TO regress_user_mvtest2; + -- make sure that matview rows can be referenced as source rows (bug #9398) CREATE TABLE mvtest_v AS SELECT generate_series(1,10) AS a; CREATE MATERIALIZED VIEW mvtest_mv_v AS SELECT a FROM mvtest_v WHERE a <= 5;