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.
REL8_3_STABLE
Tom Lane 13 years ago
parent 613a9ed76f
commit 2383d6d132
  1. 11
      src/backend/parser/parse_relation.c
  2. 22
      src/test/regress/expected/rules.out
  3. 15
      src/test/regress/sql/rules.sql

@ -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 */

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

@ -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
--

Loading…
Cancel
Save