]> granicus.if.org Git - postgresql/commitdiff
Don't reject ROW_MARK_REFERENCE rowmarks for materialized views.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 6 Mar 2014 16:37:04 +0000 (11:37 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 6 Mar 2014 16:37:04 +0000 (11:37 -0500)
We should allow this so that matviews can be referenced in UPDATE/DELETE
statements in READ COMMITTED isolation level.  The requirement for that
is that a re-fetch by TID will see the same row version the query saw
earlier, which is true of matviews, so there's no reason for the
restriction.  Per bug #9398.

Michael Paquier, after a suggestion by me

src/backend/executor/execMain.c
src/test/regress/expected/matview.out
src/test/regress/sql/matview.sql

index 9240b44dc8d7cefb52a5ae2e7c5b863bdd8a12b3..a9c8140581b07db436704f176358a739fe1a23b8 100644 (file)
@@ -1100,14 +1100,15 @@ CheckValidRowMarkRel(Relation rel, RowMarkType markType)
                                                        RelationGetRelationName(rel))));
                        break;
                case RELKIND_MATVIEW:
-                       /* Should not get here */
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                                        errmsg("cannot lock rows in materialized view \"%s\"",
-                                                       RelationGetRelationName(rel))));
+                       /* Allow referencing a matview, but not actual locking clauses */
+                       if (markType != ROW_MARK_REFERENCE)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                                          errmsg("cannot lock rows in materialized view \"%s\"",
+                                                         RelationGetRelationName(rel))));
                        break;
                case RELKIND_FOREIGN_TABLE:
-                       /* Should not get here */
+                       /* Should not get here; planner should have used ROW_MARK_COPY */
                        ereport(ERROR,
                                        (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                         errmsg("cannot lock rows in foreign table \"%s\"",
index c61232fc891d3c29d95b564226fbe60ebbc28234..0dc574b75cf4fd736c895c809d910975afcae0b9 100644 (file)
@@ -412,3 +412,29 @@ SELECT * FROM mv_v;
 
 DROP TABLE v CASCADE;
 NOTICE:  drop cascades to materialized view mv_v
+-- make sure that matview rows can be referenced as source rows (bug #9398)
+CREATE TABLE v AS SELECT generate_series(1,10) AS a;
+CREATE MATERIALIZED VIEW mv_v AS SELECT a FROM v WHERE a <= 5;
+DELETE FROM v WHERE EXISTS ( SELECT * FROM mv_v WHERE mv_v.a = v.a );
+SELECT * FROM v;
+ a  
+----
+  6
+  7
+  8
+  9
+ 10
+(5 rows)
+
+SELECT * FROM mv_v;
+ a 
+---
+ 1
+ 2
+ 3
+ 4
+ 5
+(5 rows)
+
+DROP TABLE v CASCADE;
+NOTICE:  drop cascades to materialized view mv_v
index 8b1e7349fb24a8f1066554d674168757637c1fbe..e9af757d609d6bcd777fe07aade45ca0ddd4cc0e 100644 (file)
@@ -141,3 +141,11 @@ REFRESH MATERIALIZED VIEW mv_v;
 SELECT * FROM v;
 SELECT * FROM mv_v;
 DROP TABLE v CASCADE;
+
+-- make sure that matview rows can be referenced as source rows (bug #9398)
+CREATE TABLE v AS SELECT generate_series(1,10) AS a;
+CREATE MATERIALIZED VIEW mv_v AS SELECT a FROM v WHERE a <= 5;
+DELETE FROM v WHERE EXISTS ( SELECT * FROM mv_v WHERE mv_v.a = v.a );
+SELECT * FROM v;
+SELECT * FROM mv_v;
+DROP TABLE v CASCADE;