]> granicus.if.org Git - postgresql/commitdiff
Fix breakage of MV column name list usage.
authorKevin Grittner <kgrittn@postgresql.org>
Mon, 4 Nov 2013 20:31:07 +0000 (14:31 -0600)
committerKevin Grittner <kgrittn@postgresql.org>
Mon, 4 Nov 2013 20:31:07 +0000 (14:31 -0600)
Per bug report from Tomonari Katsumata.

Back-patch to 9.3.

src/backend/rewrite/rewriteDefine.c
src/test/regress/expected/matview.out
src/test/regress/sql/matview.sql

index 9c4a5d47e28ecca46d38e872a239a77c390715c8..2eca531749aacb432019d0c1d0c886f6338519d5 100644 (file)
@@ -44,7 +44,7 @@
 
 
 static void checkRuleResultList(List *targetList, TupleDesc resultDesc,
-                                       bool isSelect);
+                                       bool isSelect, bool requireColumnNameMatch);
 static bool setRuleCheckAsUser_walker(Node *node, Oid *context);
 static void setRuleCheckAsUser_Query(Query *qry, Oid userid);
 
@@ -355,7 +355,9 @@ DefineQueryRewrite(char *rulename,
                 */
                checkRuleResultList(query->targetList,
                                                        RelationGetDescr(event_relation),
-                                                       true);
+                                                       true,
+                                                       event_relation->rd_rel->relkind !=
+                                                               RELKIND_MATVIEW);
 
                /*
                 * ... there must not be another ON SELECT rule already ...
@@ -484,7 +486,7 @@ DefineQueryRewrite(char *rulename,
                                                 errmsg("RETURNING lists are not supported in non-INSTEAD rules")));
                        checkRuleResultList(query->returningList,
                                                                RelationGetDescr(event_relation),
-                                                               false);
+                                                               false, false);
                }
        }
 
@@ -613,15 +615,20 @@ DefineQueryRewrite(char *rulename,
  *             Verify that targetList produces output compatible with a tupledesc
  *
  * The targetList might be either a SELECT targetlist, or a RETURNING list;
- * isSelect tells which.  (This is mostly used for choosing error messages,
- * but also we don't enforce column name matching for RETURNING.)
+ * isSelect tells which.  This is used for choosing error messages.
+ *
+ * A SELECT targetlist may optionally require that column names match.
  */
 static void
-checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect)
+checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect,
+                                       bool requireColumnNameMatch)
 {
        ListCell   *tllist;
        int                     i;
 
+       /* Only a SELECT may require a column name match. */
+       Assert(isSelect || !requireColumnNameMatch);
+
        i = 0;
        foreach(tllist, targetList)
        {
@@ -657,7 +664,7 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect)
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                         errmsg("cannot convert relation containing dropped columns to view")));
 
-               if (isSelect && strcmp(tle->resname, attname) != 0)
+               if (requireColumnNameMatch && strcmp(tle->resname, attname) != 0)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                         errmsg("SELECT rule's target entry %d has different column name from \"%s\"", i, attname)));
index 24f8b796dfb2c882861805d037fe4b0cdc038b44..edbc6f6121e0901e23f2eded6cf454c9f09b6464 100644 (file)
@@ -450,3 +450,26 @@ SELECT * FROM boxmv ORDER BY id;
 
 DROP TABLE boxes CASCADE;
 NOTICE:  drop cascades to materialized view boxmv
+-- make sure that column names are handled correctly
+CREATE TABLE v (i int, j int);
+CREATE MATERIALIZED VIEW mv_v (ii) AS SELECT i, j AS jj FROM v;
+ALTER TABLE v RENAME COLUMN i TO x;
+INSERT INTO v values (1, 2);
+CREATE UNIQUE INDEX mv_v_ii ON mv_v (ii);
+REFRESH MATERIALIZED VIEW mv_v;
+UPDATE v SET j = 3 WHERE x = 1;
+REFRESH MATERIALIZED VIEW CONCURRENTLY mv_v;
+SELECT * FROM v;
+ x | j 
+---+---
+ 1 | 3
+(1 row)
+
+SELECT * FROM mv_v;
+ ii | jj 
+----+----
+  1 |  3
+(1 row)
+
+DROP TABLE v CASCADE;
+NOTICE:  drop cascades to materialized view mv_v
index 93e7a42480e7b55f98e6da3ded70330a027595f3..8d03d331cffc7cacdcff95475a88f401a0b9f199 100644 (file)
@@ -173,3 +173,16 @@ UPDATE boxes SET b = '(2,2),(1,1)' WHERE id = 2;
 REFRESH MATERIALIZED VIEW CONCURRENTLY boxmv;
 SELECT * FROM boxmv ORDER BY id;
 DROP TABLE boxes CASCADE;
+
+-- make sure that column names are handled correctly
+CREATE TABLE v (i int, j int);
+CREATE MATERIALIZED VIEW mv_v (ii) AS SELECT i, j AS jj FROM v;
+ALTER TABLE v RENAME COLUMN i TO x;
+INSERT INTO v values (1, 2);
+CREATE UNIQUE INDEX mv_v_ii ON mv_v (ii);
+REFRESH MATERIALIZED VIEW mv_v;
+UPDATE v SET j = 3 WHERE x = 1;
+REFRESH MATERIALIZED VIEW CONCURRENTLY mv_v;
+SELECT * FROM v;
+SELECT * FROM mv_v;
+DROP TABLE v CASCADE;