diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 0338e4e1ad..4643257982 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -1223,6 +1223,11 @@ searchForDefault(RangeTblEntry *rte) * in the multi-VALUES case. The targetlist will contain simple Vars * referencing the VALUES RTE, and therefore process_matched_tle() will * reject any such attempt with "multiple assignments to same column". + * + * If target relation is a view and the default value for a given column + * is NULL, then we defer replacing the corresponding DEFAULT item in the + * VALUES list to when the list is rewritten with the underlying table as + * the target relation. */ static void rewriteValuesRTE(RangeTblEntry *rte, Relation target_relation, List *attrnos) @@ -1268,8 +1273,17 @@ rewriteValuesRTE(RangeTblEntry *rte, Relation target_relation, List *attrnos) /* * If there is no default (ie, default is effectively NULL), - * we've got to explicitly set the column to NULL. + * we've got to explicitly set the column to NULL. But if + * the target relation is a view, we should not finalize the + * value just yet. */ + if (!new_expr && + target_relation->rd_rel->relkind == RELKIND_VIEW) + { + newList = lappend(newList, col); + continue; + } + if (!new_expr) { new_expr = (Node *) makeConst(att_tup->atttypid, diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out index 420c5a54f2..be608e891e 100644 --- a/src/test/regress/expected/updatable_views.out +++ b/src/test/regress/expected/updatable_views.out @@ -2772,3 +2772,45 @@ drop view rw_view1; drop table base_tbl; drop user regress_view_user1; drop user regress_view_user2; +-- test that default values of underlying table are properly applied +-- when inserting via a view over the table +create table base_tab_def (a int, b int default 0); +create view base_tab_def_view as select * from base_tab_def; +-- will insert 0 for b +insert into base_tab_def_view values (1); +insert into base_tab_def_view values (2), (3); +insert into base_tab_def_view values (4, default), (5, default); +select * from base_tab_def; + a | b +---+--- + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 +(5 rows) + +alter view base_tab_def_view alter b set default 1000; +-- will insert 1000 for b +insert into base_tab_def_view values (6), (7); +insert into base_tab_def_view values (8, default), (9, default); +-- will insert 0 for b +insert into base_tab_def values (8), (9); +select * from base_tab_def; + a | b +---+------ + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 1000 + 7 | 1000 + 8 | 1000 + 9 | 1000 + 8 | 0 + 9 | 0 +(11 rows) + +drop table base_tab_def cascade; +NOTICE: drop cascades to view base_tab_def_view diff --git a/src/test/regress/sql/updatable_views.sql b/src/test/regress/sql/updatable_views.sql index dc6d5cbe35..7e559ffe57 100644 --- a/src/test/regress/sql/updatable_views.sql +++ b/src/test/regress/sql/updatable_views.sql @@ -1379,3 +1379,21 @@ drop view rw_view1; drop table base_tbl; drop user regress_view_user1; drop user regress_view_user2; + +-- test that default values of underlying table are properly applied +-- when inserting via a view over the table +create table base_tab_def (a int, b int default 0); +create view base_tab_def_view as select * from base_tab_def; +-- will insert 0 for b +insert into base_tab_def_view values (1); +insert into base_tab_def_view values (2), (3); +insert into base_tab_def_view values (4, default), (5, default); +select * from base_tab_def; +alter view base_tab_def_view alter b set default 1000; +-- will insert 1000 for b +insert into base_tab_def_view values (6), (7); +insert into base_tab_def_view values (8, default), (9, default); +-- will insert 0 for b +insert into base_tab_def values (8), (9); +select * from base_tab_def; +drop table base_tab_def cascade;