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