Prevent parser from believing that views have system columns.

Views should not have any pg_attribute entries for system columns.
However, we forgot to remove such entries when converting a table to a
view.  This could lead to crashes later on, if someone attempted to
reference such a column, as reported by Kohei KaiGai.

This problem is corrected properly in HEAD (by removing the pg_attribute
entries during conversion), but in the back branches we need to defend
against existing mis-converted views.  This fix costs us an extra syscache
lookup per system column reference, which is annoying but probably not
really measurable in the big scheme of things.
This commit is contained in:
Tom Lane 2012-10-24 14:54:17 -04:00
parent 613a9ed76f
commit 2383d6d132
3 changed files with 46 additions and 2 deletions

View File

@ -383,11 +383,18 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname,
attnum = specialAttNum(colname);
if (attnum != InvalidAttrNumber)
{
/* now check to see if column actually is defined */
/*
* Now check to see if column actually is defined. Because of
* an ancient oversight in DefineQueryRewrite, it's possible that
* pg_attribute contains entries for system columns for a view,
* even though views should not have such --- so we also check
* the relkind. This kluge will not be needed in 9.3 and later.
*/
if (SearchSysCacheExists(ATTNUM,
ObjectIdGetDatum(rte->relid),
Int16GetDatum(attnum),
0, 0))
0, 0) &&
get_rel_relkind(rte->relid) != RELKIND_VIEW)
{
result = (Node *) make_var(pstate, rte, attnum);
/* Require read access */

View File

@ -1442,6 +1442,28 @@ insert into rule_and_refint_t3 values (1, 13, 11, 'row8');
ERROR: insert or update on table "rule_and_refint_t3" violates foreign key constraint "rule_and_refint_t3_id3a_fkey"
DETAIL: Key (id3a,id3b)=(1,13) is not present in table "rule_and_refint_t1".
--
-- test conversion of table to view (needed to load some pg_dump files)
--
create table fooview (x int, y text);
select xmin, * from fooview;
xmin | x | y
------+---+---
(0 rows)
create rule "_RETURN" as on select to fooview do instead
select 1 as x, 'aaa'::text as y;
select * from fooview;
x | y
---+-----
1 | aaa
(1 row)
select xmin, * from fooview; -- fail, views don't have such a column
ERROR: column "xmin" does not exist
LINE 1: select xmin, * from fooview;
^
drop view fooview;
--
-- check for planner problems with complex inherited UPDATES
--
create table id (id serial primary key, name text);

View File

@ -851,6 +851,21 @@ create rule rule_and_refint_t3_ins as on insert to rule_and_refint_t3
insert into rule_and_refint_t3 values (1, 11, 13, 'row7');
insert into rule_and_refint_t3 values (1, 13, 11, 'row8');
--
-- test conversion of table to view (needed to load some pg_dump files)
--
create table fooview (x int, y text);
select xmin, * from fooview;
create rule "_RETURN" as on select to fooview do instead
select 1 as x, 'aaa'::text as y;
select * from fooview;
select xmin, * from fooview; -- fail, views don't have such a column
drop view fooview;
--
-- check for planner problems with complex inherited UPDATES
--