From ca2eea3ac89a4ea16ab069cb681510d05de5285f Mon Sep 17 00:00:00 2001 From: Jeff Davis Date: Wed, 31 Jul 2024 16:42:19 -0700 Subject: [PATCH] Add is_create parameter to RefreshMatviewByOid(). RefreshMatviewByOid is used for both REFRESH and CREATE MATERIALIZED VIEW. This flag is currently just used for handling internal error messages, but also aimed to improve code-readability. Author: Yugo Nagata Discussion: https://postgr.es/m/20240726122630.70e889f63a4d7e26f8549de8@sraoss.co.jp --- src/backend/commands/createas.c | 5 +--- src/backend/commands/matview.c | 42 +++++++++++++++++++++++---------- src/include/commands/matview.h | 5 ++-- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 6fb92a312bb..36e192b79b2 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -346,11 +346,8 @@ ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, */ if (do_refresh) { - RefreshMatViewByOid(address.objectId, false, false, + RefreshMatViewByOid(address.objectId, true, false, false, pstate->p_sourcetext, qc); - - if (qc) - qc->commandTag = CMDTAG_SELECT; } return address; diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index 45a2a80181d..91f0fd6ea3e 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -60,7 +60,7 @@ static bool transientrel_receive(TupleTableSlot *slot, DestReceiver *self); static void transientrel_shutdown(DestReceiver *self); static void transientrel_destroy(DestReceiver *self); static uint64 refresh_matview_datafill(DestReceiver *dest, Query *query, - const char *queryString); + const char *queryString, bool is_create); static char *make_temptable_name_n(char *tempname, int n); static void refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner, int save_sec_context); @@ -135,8 +135,8 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, RangeVarCallbackMaintainsTable, NULL); - return RefreshMatViewByOid(matviewOid, stmt->skipData, stmt->concurrent, - queryString, qc); + return RefreshMatViewByOid(matviewOid, false, stmt->skipData, + stmt->concurrent, queryString, qc); } /* @@ -157,10 +157,14 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, * * The matview's "populated" state is changed based on whether the contents * reflect the result set of the materialized view's query. + * + * This is also used to populate the materialized view created by CREATE + * MATERIALIZED VIEW command. */ ObjectAddress -RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, - const char *queryString, QueryCompletion *qc) +RefreshMatViewByOid(Oid matviewOid, bool is_create, bool skipData, + bool concurrent, const char *queryString, + QueryCompletion *qc) { Relation matviewRel; RewriteRule *rule; @@ -169,7 +173,6 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, Oid tableSpace; Oid relowner; Oid OIDNewHeap; - DestReceiver *dest; uint64 processed = 0; char relpersistence; Oid save_userid; @@ -248,6 +251,8 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, ListCell *indexoidscan; bool hasUniqueIndex = false; + Assert(!is_create); + foreach(indexoidscan, indexoidlist) { Oid indexoid = lfirst_oid(indexoidscan); @@ -284,7 +289,9 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, * NB: We count on this to protect us against problems with refreshing the * data using TABLE_INSERT_FROZEN. */ - CheckTableNotInUse(matviewRel, "REFRESH MATERIALIZED VIEW"); + CheckTableNotInUse(matviewRel, + is_create ? "CREATE MATERIALIZED VIEW" : + "REFRESH MATERIALIZED VIEW"); /* * Tentatively mark the matview as populated or not (this will roll back @@ -313,11 +320,16 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, matviewRel->rd_rel->relam, relpersistence, ExclusiveLock); LockRelationOid(OIDNewHeap, AccessExclusiveLock); - dest = CreateTransientRelDestReceiver(OIDNewHeap); /* Generate the data, if wanted. */ if (!skipData) - processed = refresh_matview_datafill(dest, dataQuery, queryString); + { + DestReceiver *dest; + + dest = CreateTransientRelDestReceiver(OIDNewHeap); + processed = refresh_matview_datafill(dest, dataQuery, queryString, + is_create); + } /* Make the matview match the newly generated data. */ if (concurrent) @@ -369,9 +381,14 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, * i.e., the display_rowcount flag of CMDTAG_REFRESH_MATERIALIZED_VIEW * command tag is left false in cmdtaglist.h. Otherwise, the change of * completion tag output might break applications using it. + * + * When called from CREATE MATERIALIZED VIEW comand, the rowcount is + * displayed with the command tag CMDTAG_SELECT. */ if (qc) - SetQueryCompletion(qc, CMDTAG_REFRESH_MATERIALIZED_VIEW, processed); + SetQueryCompletion(qc, + is_create ? CMDTAG_SELECT : CMDTAG_REFRESH_MATERIALIZED_VIEW, + processed); return address; } @@ -386,7 +403,7 @@ RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, */ static uint64 refresh_matview_datafill(DestReceiver *dest, Query *query, - const char *queryString) + const char *queryString, bool is_create) { List *rewritten; PlannedStmt *plan; @@ -401,7 +418,8 @@ refresh_matview_datafill(DestReceiver *dest, Query *query, /* SELECT should never rewrite to more or less than one SELECT query */ if (list_length(rewritten) != 1) - elog(ERROR, "unexpected rewrite result for REFRESH MATERIALIZED VIEW"); + elog(ERROR, "unexpected rewrite result for %s", + is_create ? "CREATE MATERIALIZED VIEW " : "REFRESH MATERIALIZED VIEW"); query = (Query *) linitial(rewritten); /* Check for user-requested abort. */ diff --git a/src/include/commands/matview.h b/src/include/commands/matview.h index 7916df30393..c8811e8fc71 100644 --- a/src/include/commands/matview.h +++ b/src/include/commands/matview.h @@ -25,8 +25,9 @@ extern void SetMatViewPopulatedState(Relation relation, bool newstate); extern ObjectAddress ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, QueryCompletion *qc); -extern ObjectAddress RefreshMatViewByOid(Oid matviewOid, bool skipData, bool concurrent, - const char *queryString, QueryCompletion *qc); +extern ObjectAddress RefreshMatViewByOid(Oid matviewOid, bool is_create, bool skipData, + bool concurrent, const char *queryString, + QueryCompletion *qc); extern DestReceiver *CreateTransientRelDestReceiver(Oid transientoid);