From 08b1714dad14d08eac3da09dd3eac23b99302220 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Mon, 31 May 2021 21:30:53 -0700
Subject: [PATCH v2] Avoid alias name collisions in REFRESH MAT VIEW

---
 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..c97c4a6685 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

