diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 0338e4e1ad..7abaeda000 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,19 @@ 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 and the query will be
+				 * rewritten to be executed on the base table, we should
+				 * not finalize the value just yet.
 				 */
+				if (!new_expr &&
+					target_relation->rd_rel->relkind == RELKIND_VIEW &&
+					!view_has_instead_trigger(target_relation, CMD_INSERT))
+				{
+					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..f5ad5630d9 100644
--- a/src/test/regress/expected/updatable_views.out
+++ b/src/test/regress/expected/updatable_views.out
@@ -2772,3 +2772,78 @@ 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 order by 1;
+ 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 (10), (11);
+select * from base_tab_def order by 1;
+ a  |  b   
+----+------
+  1 |    0
+  2 |    0
+  3 |    0
+  4 |    0
+  5 |    0
+  6 | 1000
+  7 | 1000
+  8 | 1000
+  9 | 1000
+ 10 |    0
+ 11 |    0
+(11 rows)
+
+alter view base_tab_def_view alter b drop default;
+create function base_tab_def_view_instrig_func() returns trigger
+as
+$$
+begin
+  insert into base_tab_def values (new.a, new.b);
+  return new;
+end;
+$$
+language plpgsql;
+create trigger base_tab_def_view_instrig instead of insert on base_tab_def_view
+  for each row execute function base_tab_def_view_instrig_func();
+-- will insert null, the view's default value, for b
+insert into base_tab_def_view values (12, default), (13, default);
+select * from base_tab_def order by 1;
+ a  |  b   
+----+------
+  1 |    0
+  2 |    0
+  3 |    0
+  4 |    0
+  5 |    0
+  6 | 1000
+  7 | 1000
+  8 | 1000
+  9 | 1000
+ 10 |    0
+ 11 |    0
+ 12 |     
+ 13 |     
+(13 rows)
+
+drop table base_tab_def cascade;
+NOTICE:  drop cascades to view base_tab_def_view
+drop function base_tab_def_view_instrig_func;
diff --git a/src/test/regress/sql/updatable_views.sql b/src/test/regress/sql/updatable_views.sql
index dc6d5cbe35..7cfab2de38 100644
--- a/src/test/regress/sql/updatable_views.sql
+++ b/src/test/regress/sql/updatable_views.sql
@@ -1379,3 +1379,37 @@ 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 order by 1;
+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 (10), (11);
+select * from base_tab_def order by 1;
+alter view base_tab_def_view alter b drop default;
+create function base_tab_def_view_instrig_func() returns trigger
+as
+$$
+begin
+  insert into base_tab_def values (new.a, new.b);
+  return new;
+end;
+$$
+language plpgsql;
+create trigger base_tab_def_view_instrig instead of insert on base_tab_def_view
+  for each row execute function base_tab_def_view_instrig_func();
+-- will insert null, the view's default value, for b
+insert into base_tab_def_view values (12, default), (13, default);
+select * from base_tab_def order by 1;
+drop table base_tab_def cascade;
+drop function base_tab_def_view_instrig_func;
