Skip to content

Commit 9619fdc

Browse files
committed
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.
1 parent 586250c commit 9619fdc

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

src/backend/parser/parse_relation.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,10 +501,17 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname,
501501
attnum = specialAttNum(colname);
502502
if (attnum != InvalidAttrNumber)
503503
{
504-
/* now check to see if column actually is defined */
504+
/*
505+
* Now check to see if column actually is defined. Because of
506+
* an ancient oversight in DefineQueryRewrite, it's possible that
507+
* pg_attribute contains entries for system columns for a view,
508+
* even though views should not have such --- so we also check
509+
* the relkind. This kluge will not be needed in 9.3 and later.
510+
*/
505511
if (SearchSysCacheExists2(ATTNUM,
506512
ObjectIdGetDatum(rte->relid),
507-
Int16GetDatum(attnum)))
513+
Int16GetDatum(attnum)) &&
514+
get_rel_relkind(rte->relid) != RELKIND_VIEW)
508515
{
509516
var = make_var(pstate, rte, attnum, location);
510517
/* Require read access to the column */

src/test/regress/expected/rules.out

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,28 @@ ERROR: cannot drop rule _RETURN on view fooview because view fooview requires i
14521452
HINT: You can drop view fooview instead.
14531453
drop view fooview;
14541454
--
1455+
-- test conversion of table to view (needed to load some pg_dump files)
1456+
--
1457+
create table fooview (x int, y text);
1458+
select xmin, * from fooview;
1459+
xmin | x | y
1460+
------+---+---
1461+
(0 rows)
1462+
1463+
create rule "_RETURN" as on select to fooview do instead
1464+
select 1 as x, 'aaa'::text as y;
1465+
select * from fooview;
1466+
x | y
1467+
---+-----
1468+
1 | aaa
1469+
(1 row)
1470+
1471+
select xmin, * from fooview; -- fail, views don't have such a column
1472+
ERROR: column "xmin" does not exist
1473+
LINE 1: select xmin, * from fooview;
1474+
^
1475+
drop view fooview;
1476+
--
14551477
-- check for planner problems with complex inherited UPDATES
14561478
--
14571479
create table id (id serial primary key, name text);

src/test/regress/sql/rules.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,21 @@ create view fooview as select 'foo'::text;
859859
drop rule "_RETURN" on fooview;
860860
drop view fooview;
861861

862+
--
863+
-- test conversion of table to view (needed to load some pg_dump files)
864+
--
865+
866+
create table fooview (x int, y text);
867+
select xmin, * from fooview;
868+
869+
create rule "_RETURN" as on select to fooview do instead
870+
select 1 as x, 'aaa'::text as y;
871+
872+
select * from fooview;
873+
select xmin, * from fooview; -- fail, views don't have such a column
874+
875+
drop view fooview;
876+
862877
--
863878
-- check for planner problems with complex inherited UPDATES
864879
--

0 commit comments

Comments
 (0)