@@ -536,9 +536,12 @@ transientrel_destroy(DestReceiver *self)
536
536
/*
537
537
* Given a qualified temporary table name, append an underscore followed by
538
538
* the given integer, to make a new table name based on the old one.
539
+ * The result is a palloc'd string.
539
540
*
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.
542
545
*/
543
546
static char *
544
547
make_temptable_name_n (char * tempname , int n )
@@ -626,16 +629,20 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
626
629
* that in a way that allows showing the first duplicated row found. Even
627
630
* after we pass this test, a unique index on the materialized view may
628
631
* 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().
629
636
*/
630
637
resetStringInfo (& querybuf );
631
638
appendStringInfo (& 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 );
639
646
if (SPI_execute (querybuf .data , false, 1 ) != SPI_OK_SELECT )
640
647
elog (ERROR , "SPI_exec failed: %s" , querybuf .data );
641
648
if (SPI_processed > 0 )
@@ -662,9 +669,9 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
662
669
resetStringInfo (& querybuf );
663
670
appendStringInfo (& querybuf ,
664
671
"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 );
668
675
669
676
/*
670
677
* 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,
756
763
if (foundUniqueIndex )
757
764
appendStringInfoString (& querybuf , " AND " );
758
765
759
- leftop = quote_qualified_identifier ("_$ newdata" ,
766
+ leftop = quote_qualified_identifier ("newdata" ,
760
767
NameStr (attr -> attname ));
761
- rightop = quote_qualified_identifier ("_$ mv" ,
768
+ rightop = quote_qualified_identifier ("mv" ,
762
769
NameStr (attr -> attname ));
763
770
764
771
generate_operator_clause (& querybuf ,
@@ -786,8 +793,8 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
786
793
Assert (foundUniqueIndex );
787
794
788
795
appendStringInfoString (& 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 OR mv.* IS NULL "
791
798
"ORDER BY tid" );
792
799
793
800
/* Create the temporary "diff" table. */
@@ -813,19 +820,19 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
813
820
/* Deletes must come before inserts; do them first. */
814
821
resetStringInfo (& querybuf );
815
822
appendStringInfo (& 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)" ,
820
827
matviewname , diffname );
821
828
if (SPI_exec (querybuf .data , 0 ) != SPI_OK_DELETE )
822
829
elog (ERROR , "SPI_exec failed: %s" , querybuf .data );
823
830
824
831
/* Inserts go last. */
825
832
resetStringInfo (& querybuf );
826
833
appendStringInfo (& 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" ,
829
836
matviewname , diffname );
830
837
if (SPI_exec (querybuf .data , 0 ) != SPI_OK_INSERT )
831
838
elog (ERROR , "SPI_exec failed: %s" , querybuf .data );
0 commit comments