@@ -537,9 +537,12 @@ transientrel_destroy(DestReceiver *self)
537537/*
538538 * Given a qualified temporary table name, append an underscore followed by
539539 * the given integer, to make a new table name based on the old one.
540+ * The result is a palloc'd string.
540541 *
541- * This leaks memory through palloc(), which won't be cleaned up until the
542- * current memory context is freed.
542+ * As coded, this would fail to make a valid SQL name if the given name were,
543+ * say, "FOO"."BAR". Currently, the table name portion of the input will
544+ * never be double-quoted because it's of the form "pg_temp_NNN", cf
545+ * make_new_heap(). But we might have to work harder someday.
543546 */
544547static char *
545548make_temptable_name_n (char * tempname ,int n )
@@ -627,16 +630,20 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
627630 * that in a way that allows showing the first duplicated row found. Even
628631 * after we pass this test, a unique index on the materialized view may
629632 * find a duplicate key problem.
633+ *
634+ * Note: here and below, we use "tablename.*::tablerowtype" as a hack to
635+ * keep ".*" from being expanded into multiple columns in a SELECT list.
636+ * Compare ruleutils.c's get_variable().
630637 */
631638resetStringInfo (& querybuf );
632639appendStringInfo (& querybuf ,
633- "SELECT_$ newdata FROM %s_$ newdata "
634- "WHERE_$ newdata IS NOT NULL AND EXISTS "
635- "(SELECT 1 FROM %s_$ newdata2 WHERE_$ newdata2 IS NOT NULL "
636- "AND_$ newdata2 OPERATOR(pg_catalog.*=)_$ newdata "
637- "AND_$ newdata2.ctid OPERATOR(pg_catalog.<>) "
638- "_$ newdata.ctid)" ,
639- tempname ,tempname );
640+ "SELECT newdata.*::%s FROM %s newdata "
641+ "WHERE newdata.* IS NOT NULL AND EXISTS "
642+ "(SELECT 1 FROM %s newdata2 WHERE newdata2.* IS NOT NULL "
643+ "AND newdata2.* OPERATOR(pg_catalog.*=) newdata.* "
644+ "AND newdata2.ctid OPERATOR(pg_catalog.<>) "
645+ "newdata.ctid)" ,
646+ tempname ,tempname , tempname );
640647if (SPI_execute (querybuf .data , false,1 )!= SPI_OK_SELECT )
641648elog (ERROR ,"SPI_exec failed: %s" ,querybuf .data );
642649if (SPI_processed > 0 )
@@ -663,9 +670,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
663670resetStringInfo (& querybuf );
664671appendStringInfo (& querybuf ,
665672"CREATE TEMP TABLE %s AS "
666- "SELECT_$ mv.ctid AS tid,_$ newdata "
667- "FROM %s_$ mv FULL JOIN %s_$ newdata ON (" ,
668- diffname ,matviewname ,tempname );
673+ "SELECT mv.ctid AS tid,newdata.*::%s AS newdata "
674+ "FROM %s mv FULL JOIN %s newdata ON (" ,
675+ diffname ,tempname , matviewname ,tempname );
669676
670677/*
671678 * Get the list of index OIDs for the table from the relcache, and look up
@@ -757,9 +764,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
757764if (foundUniqueIndex )
758765appendStringInfoString (& querybuf ," AND " );
759766
760- leftop = quote_qualified_identifier ("_$ newdata" ,
767+ leftop = quote_qualified_identifier ("newdata" ,
761768NameStr (attr -> attname ));
762- rightop = quote_qualified_identifier ("_$ mv" ,
769+ rightop = quote_qualified_identifier ("mv" ,
763770NameStr (attr -> attname ));
764771
765772generate_operator_clause (& querybuf ,
@@ -787,8 +794,8 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
787794Assert (foundUniqueIndex );
788795
789796appendStringInfoString (& querybuf ,
790- " AND_$ newdata OPERATOR(pg_catalog.*=)_$mv ) "
791- "WHERE_$ newdata IS NULL OR_$mv IS NULL "
797+ " AND newdata.* OPERATOR(pg_catalog.*=)mv.* ) "
798+ "WHERE newdata.* IS NULL ORmv.* IS NULL "
792799"ORDER BY tid" );
793800
794801/* Create the temporary "diff" table. */
@@ -814,19 +821,19 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
814821/* Deletes must come before inserts; do them first. */
815822resetStringInfo (& querybuf );
816823appendStringInfo (& querybuf ,
817- "DELETE FROM %s_$ mv WHERE ctid OPERATOR(pg_catalog.=) ANY "
818- "(SELECT_$ diff.tid FROM %s_$ diff "
819- "WHERE_$ diff.tid IS NOT NULL "
820- "AND_$ diff._$ newdata IS NULL)" ,
824+ "DELETE FROM %s mv WHERE ctid OPERATOR(pg_catalog.=) ANY "
825+ "(SELECT diff.tid FROM %s diff "
826+ "WHERE diff.tid IS NOT NULL "
827+ "AND diff.newdata IS NULL)" ,
821828matviewname ,diffname );
822829if (SPI_exec (querybuf .data ,0 )!= SPI_OK_DELETE )
823830elog (ERROR ,"SPI_exec failed: %s" ,querybuf .data );
824831
825832/* Inserts go last. */
826833resetStringInfo (& querybuf );
827834appendStringInfo (& querybuf ,
828- "INSERT INTO %s SELECT (_$ diff._$ newdata).* "
829- "FROM %s_$ diff WHERE tid IS NULL" ,
835+ "INSERT INTO %s SELECT (diff.newdata).* "
836+ "FROM %s diff WHERE tid IS NULL" ,
830837matviewname ,diffname );
831838if (SPI_exec (querybuf .data ,0 )!= SPI_OK_INSERT )
832839elog (ERROR ,"SPI_exec failed: %s" ,querybuf .data );