Fix breakage of MV column name list usage.

Per bug report from Tomonari Katsumata.

Back-patch to 9.3.
This commit is contained in:
Kevin Grittner 2013-11-04 14:31:07 -06:00
parent dddc34408a
commit 732758db4c
3 changed files with 50 additions and 7 deletions

View 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)));

View 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

View 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;