@@ -536,9 +536,12 @@ transientrel_destroy(DestReceiver *self)
536536/*
537537 * Given a qualified temporary table name, append an underscore followed by
538538 * the given integer, to make a new table name based on the old one.
539+ * The result is a palloc'd string.
539540 *
540- * This leaks memory through palloc(), which won't be cleaned up until the
541- * current memory context is freed.
541+ * As coded, this would fail to make a valid SQL name if the given name were,
542+ * say, "FOO"."BAR". Currently, the table name portion of the input will
543+ * never be double-quoted because it's of the form "pg_temp_NNN", cf
544+ * make_new_heap(). But we might have to work harder someday.
542545 */
543546static char *
544547make_temptable_name_n (char * tempname ,int n )
@@ -626,16 +629,20 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
626629 * that in a way that allows showing the first duplicated row found. Even
627630 * after we pass this test, a unique index on the materialized view may
628631 * find a duplicate key problem.
632+ *
633+ * Note: here and below, we use "tablename.*::tablerowtype" as a hack to
634+ * keep ".*" from being expanded into multiple columns in a SELECT list.
635+ * Compare ruleutils.c's get_variable().
629636 */
630637resetStringInfo (& querybuf );
631638appendStringInfo (& querybuf ,
632- "SELECT_$ newdata FROM %s_$ newdata "
633- "WHERE_$ newdata IS NOT NULL AND EXISTS "
634- "(SELECT 1 FROM %s_$ newdata2 WHERE_$ newdata2 IS NOT NULL "
635- "AND_$ newdata2 OPERATOR(pg_catalog.*=)_$ newdata "
636- "AND_$ newdata2.ctid OPERATOR(pg_catalog.<>) "
637- "_$ newdata.ctid)" ,
638- tempname ,tempname );
639+ "SELECT newdata.*::%s FROM %s newdata "
640+ "WHERE newdata.* IS NOT NULL AND EXISTS "
641+ "(SELECT 1 FROM %s newdata2 WHERE newdata2.* IS NOT NULL "
642+ "AND newdata2.* OPERATOR(pg_catalog.*=) newdata.* "
643+ "AND newdata2.ctid OPERATOR(pg_catalog.<>) "
644+ "newdata.ctid)" ,
645+ tempname ,tempname , tempname );
639646if (SPI_execute (querybuf .data , false,1 )!= SPI_OK_SELECT )
640647elog (ERROR ,"SPI_exec failed: %s" ,querybuf .data );
641648if (SPI_processed > 0 )
@@ -662,9 +669,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
662669resetStringInfo (& querybuf );
663670appendStringInfo (& querybuf ,
664671"CREATE TEMP TABLE %s AS "
665- "SELECT_$ mv.ctid AS tid,_$ newdata "
666- "FROM %s_$ mv FULL JOIN %s_$ newdata ON (" ,
667- diffname ,matviewname ,tempname );
672+ "SELECT mv.ctid AS tid,newdata.*::%s AS newdata "
673+ "FROM %s mv FULL JOIN %s newdata ON (" ,
674+ diffname ,tempname , matviewname ,tempname );
668675
669676/*
670677 * Get the list of index OIDs for the table from the relcache, and look up
@@ -756,9 +763,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
756763if (foundUniqueIndex )
757764appendStringInfoString (& querybuf ," AND " );
758765
759- leftop = quote_qualified_identifier ("_$ newdata" ,
766+ leftop = quote_qualified_identifier ("newdata" ,
760767NameStr (attr -> attname ));
761- rightop = quote_qualified_identifier ("_$ mv" ,
768+ rightop = quote_qualified_identifier ("mv" ,
762769NameStr (attr -> attname ));
763770
764771generate_operator_clause (& querybuf ,
@@ -786,8 +793,8 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
786793Assert (foundUniqueIndex );
787794
788795appendStringInfoString (& querybuf ,
789- " AND_$ newdata OPERATOR(pg_catalog.*=)_$mv ) "
790- "WHERE_$ newdata IS NULL OR_$mv IS NULL "
796+ " AND newdata.* OPERATOR(pg_catalog.*=)mv.* ) "
797+ "WHERE newdata.* IS NULL ORmv.* IS NULL "
791798"ORDER BY tid" );
792799
793800/* Create the temporary "diff" table. */
@@ -813,19 +820,19 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
813820/* Deletes must come before inserts; do them first. */
814821resetStringInfo (& querybuf );
815822appendStringInfo (& querybuf ,
816- "DELETE FROM %s_$ mv WHERE ctid OPERATOR(pg_catalog.=) ANY "
817- "(SELECT_$ diff.tid FROM %s_$ diff "
818- "WHERE_$ diff.tid IS NOT NULL "
819- "AND_$ diff._$ newdata IS NULL)" ,
823+ "DELETE FROM %s mv WHERE ctid OPERATOR(pg_catalog.=) ANY "
824+ "(SELECT diff.tid FROM %s diff "
825+ "WHERE diff.tid IS NOT NULL "
826+ "AND diff.newdata IS NULL)" ,
820827matviewname ,diffname );
821828if (SPI_exec (querybuf .data ,0 )!= SPI_OK_DELETE )
822829elog (ERROR ,"SPI_exec failed: %s" ,querybuf .data );
823830
824831/* Inserts go last. */
825832resetStringInfo (& querybuf );
826833appendStringInfo (& querybuf ,
827- "INSERT INTO %s SELECT (_$ diff._$ newdata).* "
828- "FROM %s_$ diff WHERE tid IS NULL" ,
834+ "INSERT INTO %s SELECT (diff.newdata).* "
835+ "FROM %s diff WHERE tid IS NULL" ,
829836matviewname ,diffname );
830837if (SPI_exec (querybuf .data ,0 )!= SPI_OK_INSERT )
831838elog (ERROR ,"SPI_exec failed: %s" ,querybuf .data );