From 73c62e85d151f21375bf7813f977434b89869357 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Tue, 1 Jun 2021 06:39:32 -0700
Subject: [PATCH v3] Avoid alias name collisions in REFRESH MATERIALIZED VIEW

There are alias names such as "mv", "newdata", "newdata2",
"diff" used in REFRESH MATERIALIZED VIEW .. CONCURRENTLY
code. These names are so common that users can have them
in the queries and refreshing materialized view can fail.

This patch randomizes the alias names with MyProcPid.
---
 src/backend/commands/matview.c | 62 ++++++++++++++++++++--------------
 1 file changed, 37 insertions(+), 25 deletions(-)

diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index 172ec6e982..9d54ccefb9 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -599,6 +599,10 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 	ListCell   *indexoidscan;
 	int16		relnatts;
 	Oid		   *opUsedForQual;
+	char 	   *matviewalias;
+	char 	   *newdataalias;
+	char 	   *newdata2alias;
+	char 	   *diffalias;
 
 	initStringInfo(&querybuf);
 	matviewRel = table_open(matviewOid, NoLock);
@@ -608,7 +612,10 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 	tempname = quote_qualified_identifier(get_namespace_name(RelationGetNamespace(tempRel)),
 										  RelationGetRelationName(tempRel));
 	diffname = make_temptable_name_n(tempname, 2);
-
+	matviewalias = make_temptable_name_n("pg_matview_", MyProcPid);
+	newdataalias = make_temptable_name_n("pg_newdata_", MyProcPid);
+	newdata2alias = make_temptable_name_n("pg_newdata2_", MyProcPid);
+	diffalias = make_temptable_name_n("pg_diff_", MyProcPid);
 	relnatts = RelationGetNumberOfAttributes(matviewRel);
 
 	/* Open SPI context. */
@@ -629,13 +636,15 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 	 */
 	resetStringInfo(&querybuf);
 	appendStringInfo(&querybuf,
-					 "SELECT newdata FROM %s newdata "
-					 "WHERE newdata IS NOT NULL AND EXISTS "
-					 "(SELECT 1 FROM %s newdata2 WHERE newdata2 IS NOT NULL "
-					 "AND newdata2 OPERATOR(pg_catalog.*=) newdata "
-					 "AND newdata2.ctid OPERATOR(pg_catalog.<>) "
-					 "newdata.ctid)",
-					 tempname, tempname);
+					 "SELECT %s FROM %s %s "
+					 "WHERE %s IS NOT NULL AND EXISTS "
+					 "(SELECT 1 FROM %s %s WHERE %s IS NOT NULL "
+					 "AND %s OPERATOR(pg_catalog.*=) %s "
+					 "AND %s.ctid OPERATOR(pg_catalog.<>) "
+					 "%s.ctid)",
+					 newdataalias, tempname, newdataalias, newdataalias,
+					 tempname, newdata2alias, newdata2alias, newdata2alias,
+					 newdataalias, newdata2alias, newdataalias);
 	if (SPI_execute(querybuf.data, false, 1) != SPI_OK_SELECT)
 		elog(ERROR, "SPI_exec failed: %s", querybuf.data);
 	if (SPI_processed > 0)
@@ -662,9 +671,10 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 	resetStringInfo(&querybuf);
 	appendStringInfo(&querybuf,
 					 "CREATE TEMP TABLE %s AS "
-					 "SELECT mv.ctid AS tid, newdata "
-					 "FROM %s mv FULL JOIN %s newdata ON (",
-					 diffname, matviewname, tempname);
+					 "SELECT %s.ctid AS tid, %s "
+					 "FROM %s %s FULL JOIN %s %s ON (",
+					 diffname, matviewalias, newdataalias, matviewname,
+					 matviewalias, tempname, newdataalias);
 
 	/*
 	 * Get the list of index OIDs for the table from the relcache, and look up
@@ -756,9 +766,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 				if (foundUniqueIndex)
 					appendStringInfoString(&querybuf, " AND ");
 
-				leftop = quote_qualified_identifier("newdata",
+				leftop = quote_qualified_identifier(newdataalias,
 													NameStr(attr->attname));
-				rightop = quote_qualified_identifier("mv",
+				rightop = quote_qualified_identifier(matviewalias,
 													 NameStr(attr->attname));
 
 				generate_operator_clause(&querybuf,
@@ -785,10 +795,10 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 	 */
 	Assert(foundUniqueIndex);
 
-	appendStringInfoString(&querybuf,
-						   " AND newdata OPERATOR(pg_catalog.*=) mv) "
-						   "WHERE newdata IS NULL OR mv IS NULL "
-						   "ORDER BY tid");
+	appendStringInfo(&querybuf,
+					 " AND %s OPERATOR(pg_catalog.*=) %s) "
+					 "WHERE %s IS NULL OR %s IS NULL ORDER BY tid",
+					 newdataalias, matviewalias, newdataalias, matviewalias);
 
 	/* Create the temporary "diff" table. */
 	if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY)
@@ -813,20 +823,22 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
 	/* Deletes must come before inserts; do them first. */
 	resetStringInfo(&querybuf);
 	appendStringInfo(&querybuf,
-					 "DELETE FROM %s mv WHERE ctid OPERATOR(pg_catalog.=) ANY "
-					 "(SELECT diff.tid FROM %s diff "
-					 "WHERE diff.tid IS NOT NULL "
-					 "AND diff.newdata IS NULL)",
-					 matviewname, diffname);
+					 "DELETE FROM %s %s WHERE ctid OPERATOR(pg_catalog.=) ANY "
+					 "(SELECT %s.tid FROM %s %s "
+					 "WHERE %s.tid IS NOT NULL "
+					 "AND %s.%s IS NULL)",
+					 matviewname, matviewalias, diffalias, diffname,
+					 diffalias, diffalias, diffalias, newdataalias);
 	if (SPI_exec(querybuf.data, 0) != SPI_OK_DELETE)
 		elog(ERROR, "SPI_exec failed: %s", querybuf.data);
 
 	/* Inserts go last. */
 	resetStringInfo(&querybuf);
 	appendStringInfo(&querybuf,
-					 "INSERT INTO %s SELECT (diff.newdata).* "
-					 "FROM %s diff WHERE tid IS NULL",
-					 matviewname, diffname);
+					 "INSERT INTO %s SELECT (%s.%s).* "
+					 "FROM %s %s WHERE tid IS NULL",
+					 matviewname, diffalias, newdataalias,
+					 diffname, diffalias);
 	if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT)
 		elog(ERROR, "SPI_exec failed: %s", querybuf.data);
 
-- 
2.25.1

