varattno++;
Assert(varattno == te->resno);
+ /*
+ * In scenarios where columns have been added to a view
+ * since the outer query was originally parsed, there can
+ * be more items in the subquery tlist than the outer
+ * query expects. We should ignore such extra column(s)
+ * --- compare the behavior for composite-returning
+ * functions, in the RTE_FUNCTION case below.
+ */
+ if (!aliasp_item)
+ break;
+
if (colnames)
{
- /* Assume there is one alias per target item */
char *label = strVal(lfirst(aliasp_item));
*colnames = lappend(*colnames, makeString(pstrdup(label)));
"check_fk_presence_2_id_fkey" FOREIGN KEY (id) REFERENCES check_fk_presence_1(id)
DROP TABLE check_fk_presence_1, check_fk_presence_2;
+-- check column addition within a view (bug #14876)
+create table at_base_table(id int, stuff text);
+insert into at_base_table values (23, 'skidoo');
+create view at_view_1 as select * from at_base_table bt;
+create view at_view_2 as select *, v1 as j from at_view_1 v1;
+\d+ at_view_1
+ View "public.at_view_1"
+ Column | Type | Modifiers | Storage | Description
+--------+---------+-----------+----------+-------------
+ id | integer | | plain |
+ stuff | text | | extended |
+View definition:
+ SELECT bt.id, bt.stuff
+ FROM at_base_table bt;
+
+\d+ at_view_2
+ View "public.at_view_2"
+ Column | Type | Modifiers | Storage | Description
+--------+-----------+-----------+----------+-------------
+ id | integer | | plain |
+ stuff | text | | extended |
+ j | at_view_1 | | extended |
+View definition:
+ SELECT v1.id, v1.stuff, v1.*::at_view_1 AS j
+ FROM at_view_1 v1;
+
+explain (verbose, costs off) select * from at_view_2;
+ QUERY PLAN
+-------------------------------------------------
+ Seq Scan on public.at_base_table bt
+ Output: bt.id, bt.stuff, ROW(bt.id, bt.stuff)
+(2 rows)
+
+select * from at_view_2;
+ id | stuff | j
+----+--------+-------------
+ 23 | skidoo | (23,skidoo)
+(1 row)
+
+create or replace view at_view_1 as select *, 2+2 as more from at_base_table bt;
+\d+ at_view_1
+ View "public.at_view_1"
+ Column | Type | Modifiers | Storage | Description
+--------+---------+-----------+----------+-------------
+ id | integer | | plain |
+ stuff | text | | extended |
+ more | integer | | plain |
+View definition:
+ SELECT bt.id, bt.stuff, 2 + 2 AS more
+ FROM at_base_table bt;
+
+\d+ at_view_2
+ View "public.at_view_2"
+ Column | Type | Modifiers | Storage | Description
+--------+-----------+-----------+----------+-------------
+ id | integer | | plain |
+ stuff | text | | extended |
+ j | at_view_1 | | extended |
+View definition:
+ SELECT v1.id, v1.stuff, v1.*::at_view_1 AS j
+ FROM at_view_1 v1;
+
+explain (verbose, costs off) select * from at_view_2;
+ QUERY PLAN
+-------------------------------------------------------
+ Seq Scan on public.at_base_table bt
+ Output: bt.id, bt.stuff, ROW(bt.id, bt.stuff, NULL)
+(2 rows)
+
+select * from at_view_2;
+ id | stuff | j
+----+--------+--------------
+ 23 | skidoo | (23,skidoo,)
+(1 row)
+
+drop view at_view_2;
+drop view at_view_1;
+drop table at_base_table;
--
-- lock levels
--
\d check_fk_presence_2
DROP TABLE check_fk_presence_1, check_fk_presence_2;
+-- check column addition within a view (bug #14876)
+create table at_base_table(id int, stuff text);
+insert into at_base_table values (23, 'skidoo');
+create view at_view_1 as select * from at_base_table bt;
+create view at_view_2 as select *, v1 as j from at_view_1 v1;
+\d+ at_view_1
+\d+ at_view_2
+explain (verbose, costs off) select * from at_view_2;
+select * from at_view_2;
+
+create or replace view at_view_1 as select *, 2+2 as more from at_base_table bt;
+\d+ at_view_1
+\d+ at_view_2
+explain (verbose, costs off) select * from at_view_2;
+select * from at_view_2;
+
+drop view at_view_2;
+drop view at_view_1;
+drop table at_base_table;
+
--
-- lock levels
--