summaryrefslogtreecommitdiffstats
path: root/src/backend/commands/matview.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/backend/commands/matview.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index d1ee106..a5f8972 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -656,13 +656,35 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1))));
}
+ /*
+ * Create the temporary "diff" table.
+ *
+ * Temporarily switch out of the SECURITY_RESTRICTED_OPERATION context,
+ * because you cannot create temp tables in SRO context. For extra
+ * paranoia, add the composite type column only after switching back to
+ * SRO context.
+ */
SetUserIdAndSecContext(relowner,
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
+ resetStringInfo(&querybuf);
+ appendStringInfo(&querybuf,
+ "CREATE TEMP TABLE %s (tid pg_catalog.tid)",
+ diffname);
+ if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY)
+ elog(ERROR, "SPI_exec failed: %s", querybuf.data);
+ SetUserIdAndSecContext(relowner,
+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
+ resetStringInfo(&querybuf);
+ appendStringInfo(&querybuf,
+ "ALTER TABLE %s ADD COLUMN newdata %s",
+ diffname, tempname);
+ if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY)
+ elog(ERROR, "SPI_exec failed: %s", querybuf.data);
- /* Start building the query for creating the diff table. */
+ /* Start building the query for populating the diff table. */
resetStringInfo(&querybuf);
appendStringInfo(&querybuf,
- "CREATE TEMP TABLE %s AS "
+ "INSERT INTO %s "
"SELECT mv.ctid AS tid, newdata.*::%s AS newdata "
"FROM %s mv FULL JOIN %s newdata ON (",
diffname, tempname, matviewname, tempname);
@@ -782,22 +804,22 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
*
* ExecRefreshMatView() checks that after taking the exclusive lock on the
* matview. So at least one unique index is guaranteed to exist here
- * because the lock is still being held; so an Assert seems sufficient.
+ * because the lock is still being held. (One known exception is if a
+ * function called as part of refreshing the matview drops the index.
+ * That's a pretty silly thing to do.)
*/
- Assert(foundUniqueIndex);
+ if (!foundUniqueIndex)
+ elog(ERROR, "could not find suitable unique index on materialized view");
appendStringInfoString(&querybuf,
" AND newdata.* OPERATOR(pg_catalog.*=) mv.*) "
"WHERE newdata.* IS NULL OR mv.* IS NULL "
"ORDER BY tid");
- /* Create the temporary "diff" table. */
- if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY)
+ /* Populate the temporary "diff" table. */
+ if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT)
elog(ERROR, "SPI_exec failed: %s", querybuf.data);
- SetUserIdAndSecContext(relowner,
- save_sec_context | SECURITY_RESTRICTED_OPERATION);
-
/*
* We have no further use for data from the "full-data" temp table, but we
* must keep it around because its type is referenced from the diff table.