summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/parser/parse_relation.c12
-rw-r--r--src/test/regress/expected/alter_table.out78
-rw-r--r--src/test/regress/sql/alter_table.sql20
3 files changed, 109 insertions, 1 deletions
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index c2d1bb5ea68..b8307d5cf51 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1603,9 +1603,19 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
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)));
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 042cccec9bf..d07a2e3a401 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -2070,6 +2070,84 @@ Foreign-key constraints:
"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
--
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 59943434415..10d7186ddb7 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -1332,6 +1332,26 @@ ROLLBACK;
\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
--