diff options
author | Jeff Davis <jdavis@postgresql.org> | 2024-07-16 15:41:29 -0700 |
---|---|---|
committer | Jeff Davis <jdavis@postgresql.org> | 2024-07-16 15:41:29 -0700 |
commit | 4b74ebf726d444ba820830cad986a1f92f724649 (patch) | |
tree | 7b985099966a2649debd6628f4f416baf8467108 /src/backend/commands/createas.c | |
parent | 0a8ca122e511884d98a640cb3302866b74638688 (diff) | |
download | postgresql-4b74ebf726d444ba820830cad986a1f92f724649.tar.gz postgresql-4b74ebf726d444ba820830cad986a1f92f724649.zip |
When creating materialized views, use REFRESH to load data.
Previously, CREATE MATERIALIZED VIEW ... WITH DATA populated the MV
the same way as CREATE TABLE ... AS.
Instead, reuse the REFRESH logic, which locks down security-restricted
operations and restricts the search_path. This reduces the chance that
a subsequent refresh will fail.
Reported-by: Noah Misch
Backpatch-through: 17
Discussion: https://postgr.es/m/20240630222344.db.nmisch@google.com
Diffstat (limited to 'src/backend/commands/createas.c')
-rw-r--r-- | src/backend/commands/createas.c | 32 |
1 files changed, 15 insertions, 17 deletions
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 62050f4dc59..2c8a93b6e56 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -225,10 +225,8 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, Query *query = castNode(Query, stmt->query); IntoClause *into = stmt->into; bool is_matview = (into->viewQuery != NULL); + bool do_refresh = false; DestReceiver *dest; - Oid save_userid = InvalidOid; - int save_sec_context = 0; - int save_nestlevel = 0; ObjectAddress address; List *rewritten; PlannedStmt *plan; @@ -263,18 +261,13 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, Assert(query->commandType == CMD_SELECT); /* - * For materialized views, lock down security-restricted operations and - * arrange to make GUC variable changes local to this command. This is - * not necessary for security, but this keeps the behavior similar to - * REFRESH MATERIALIZED VIEW. Otherwise, one could create a materialized - * view not possible to refresh. + * For materialized views, always skip data during table creation, and use + * REFRESH instead (see below). */ if (is_matview) { - GetUserIdAndSecContext(&save_userid, &save_sec_context); - SetUserIdAndSecContext(save_userid, - save_sec_context | SECURITY_RESTRICTED_OPERATION); - save_nestlevel = NewGUCNestLevel(); + do_refresh = !into->skipData; + into->skipData = true; } if (into->skipData) @@ -346,13 +339,18 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, PopActiveSnapshot(); } - if (is_matview) + /* + * For materialized views, reuse the REFRESH logic, which locks down + * security-restricted operations and restricts the search_path. This + * reduces the chance that a subsequent refresh will fail. + */ + if (do_refresh) { - /* Roll back any GUC changes */ - AtEOXact_GUC(false, save_nestlevel); + RefreshMatViewByOid(address.objectId, false, false, + pstate->p_sourcetext, NULL, qc); - /* Restore userid and security context */ - SetUserIdAndSecContext(save_userid, save_sec_context); + if (qc) + qc->commandTag = CMDTAG_SELECT; } return address; |