From 08b1714dad14d08eac3da09dd3eac23b99302220 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy 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