diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 40b565a11d6ddf40b3cd8e692e625efe1f6dc3a7..3292278774f15851f3ad7ae000139278c3f94fd8 100644
*** a/src/backend/utils/adt/ruleutils.c
--- b/src/backend/utils/adt/ruleutils.c
*************** typedef struct
*** 235,240 ****
--- 235,241 ----
  	 * child RTE's attno and rightattnos[i] is zero; and conversely for a
  	 * column of the right child.  But for merged columns produced by JOIN
  	 * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero.
+ 	 * Also, if the column has been dropped, both are zero.
  	 *
  	 * If it's a JOIN USING, usingNames holds the alias names selected for the
  	 * merged columns (these might be different from the original USING list,
*************** set_join_column_names(deparse_namespace 
*** 3053,3058 ****
--- 3054,3066 ----
  		char	   *colname = colinfo->colnames[i];
  		char	   *real_colname;
  
+ 		/* Ignore dropped column (only possible for non-merged column) */
+ 		if (colinfo->leftattnos[i] == 0 && colinfo->rightattnos[i] == 0)
+ 		{
+ 			Assert(colname == NULL);
+ 			continue;
+ 		}
+ 
  		/* Get the child column name */
  		if (colinfo->leftattnos[i] > 0)
  			real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1];
*************** set_join_column_names(deparse_namespace 
*** 3061,3075 ****
  		else
  		{
  			/* We're joining system columns --- use eref name */
! 			real_colname = (char *) list_nth(rte->eref->colnames, i);
! 		}
! 
! 		/* Ignore dropped columns (only possible for non-merged column) */
! 		if (real_colname == NULL)
! 		{
! 			Assert(colname == NULL);
! 			continue;
  		}
  
  		/* In an unnamed join, just report child column names as-is */
  		if (rte->alias == NULL)
--- 3069,3077 ----
  		else
  		{
  			/* We're joining system columns --- use eref name */
! 			real_colname = strVal(list_nth(rte->eref->colnames, i));
  		}
+ 		Assert(real_colname != NULL);
  
  		/* In an unnamed join, just report child column names as-is */
  		if (rte->alias == NULL)
*************** identify_join_columns(JoinExpr *j, Range
*** 3402,3407 ****
--- 3404,3412 ----
  	{
  		Var		   *aliasvar = (Var *) lfirst(lc);
  
+ 		/* get rid of any implicit coercion above the Var */
+ 		aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar);
+ 
  		if (IsA(aliasvar, Var))
  		{
  			Assert(aliasvar->varlevelsup == 0);
*************** identify_join_columns(JoinExpr *j, Range
*** 3421,3436 ****
  			 * let the code below identify the merged columns.
  			 */
  		}
! 		else
  		{
! 			/*
! 			 * Although NULL constants can appear in joinaliasvars lists
! 			 * during planning, we shouldn't see any here, since the Query
! 			 * tree hasn't been through AcquireRewriteLocks().
! 			 */
  			elog(ERROR, "unrecognized node type in join alias vars: %d",
  				 (int) nodeTag(aliasvar));
- 		}
  
  		i++;
  	}
--- 3426,3438 ----
  			 * let the code below identify the merged columns.
  			 */
  		}
! 		else if (IsA(aliasvar, Const))
  		{
! 			/* It's a dropped column; nothing to do here */
! 		}
! 		else
  			elog(ERROR, "unrecognized node type in join alias vars: %d",
  				 (int) nodeTag(aliasvar));
  
  		i++;
  	}
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 9415e2c636eab741e2216e6c23dc929e7f4f9494..ce8007b950e3c629d9d3c83509cd030a600d8e63 100644
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
*************** typedef struct RangeTblEntry
*** 731,743 ****
  	/*
  	 * Fields valid for a join RTE (else NULL/zero):
  	 *
! 	 * joinaliasvars is a list of Vars or COALESCE expressions corresponding
! 	 * to the columns of the join result.  An alias Var referencing column K
! 	 * of the join result can be replaced by the K'th element of joinaliasvars
! 	 * --- but to simplify the task of reverse-listing aliases correctly, we
! 	 * do not do that until planning time.	In a Query loaded from a stored
! 	 * rule, it is also possible for joinaliasvars items to be NULL Consts,
! 	 * denoting columns dropped since the rule was made.
  	 */
  	JoinType	jointype;		/* type of join */
  	List	   *joinaliasvars;	/* list of alias-var expansions */
--- 731,748 ----
  	/*
  	 * Fields valid for a join RTE (else NULL/zero):
  	 *
! 	 * joinaliasvars is a list of (usually) Vars corresponding to the columns
! 	 * of the join result.	An alias Var referencing column K of the join
! 	 * result can be replaced by the K'th element of joinaliasvars --- but to
! 	 * simplify the task of reverse-listing aliases correctly, we do not do
! 	 * that until planning time.  In detail: an element of joinaliasvars can
! 	 * be a Var of one of the join's input relations, or such a Var with an
! 	 * implicit coercion to the join's output column type, or a COALESCE
! 	 * expression containing the two input column Vars (possibly coerced).
! 	 * Within a Query loaded from a stored rule, it is also possible for
! 	 * joinaliasvars items to be NULL Consts, denoting columns dropped since
! 	 * the rule was made.  Also, once planning begins, joinaliasvars items can
! 	 * be almost anything, as a result of subquery-flattening substitutions.
  	 */
  	JoinType	jointype;		/* type of join */
  	List	   *joinaliasvars;	/* list of alias-var expansions */
diff --git a/src/test/regress/expected/create_view.out b/src/test/regress/expected/create_view.out
index 4fa774950345808d9455abf06fddbed15933dfaf..8b451429674a6153dcf914ab2753787365cd6cb8 100644
*** a/src/test/regress/expected/create_view.out
--- b/src/test/regress/expected/create_view.out
*************** select pg_get_viewdef('vv4', true);
*** 1243,1248 ****
--- 1243,1275 ----
      FULL JOIN tt8 tt8y(x_1, z, z2) USING (x_1);
  (1 row)
  
+ --
+ -- Also check dropping a column that existed when the view was made
+ --
+ create table tt9 (x int, xx int, y int);
+ create table tt10 (x int, z int);
+ create view vv5 as select x,y,z from tt9 join tt10 using(x);
+ select pg_get_viewdef('vv5', true);
+      pg_get_viewdef      
+ -------------------------
+   SELECT tt9.x,         +
+      tt9.y,             +
+      tt10.z             +
+     FROM tt9            +
+     JOIN tt10 USING (x);
+ (1 row)
+ 
+ alter table tt9 drop column xx;
+ select pg_get_viewdef('vv5', true);
+      pg_get_viewdef      
+ -------------------------
+   SELECT tt9.x,         +
+      tt9.y,             +
+      tt10.z             +
+     FROM tt9            +
+     JOIN tt10 USING (x);
+ (1 row)
+ 
  -- clean up all the random objects we made above
  set client_min_messages = warning;
  DROP SCHEMA temp_view_test CASCADE;
diff --git a/src/test/regress/sql/create_view.sql b/src/test/regress/sql/create_view.sql
index 3d85d9cfdc50b454fb38d8a742770eda1e119a41..4fbd5a5e6f8baa3d41f1a201fbb99ad4bc3bf3da 100644
*** a/src/test/regress/sql/create_view.sql
--- b/src/test/regress/sql/create_view.sql
*************** select pg_get_viewdef('vv2', true);
*** 389,394 ****
--- 389,409 ----
  select pg_get_viewdef('vv3', true);
  select pg_get_viewdef('vv4', true);
  
+ --
+ -- Also check dropping a column that existed when the view was made
+ --
+ 
+ create table tt9 (x int, xx int, y int);
+ create table tt10 (x int, z int);
+ 
+ create view vv5 as select x,y,z from tt9 join tt10 using(x);
+ 
+ select pg_get_viewdef('vv5', true);
+ 
+ alter table tt9 drop column xx;
+ 
+ select pg_get_viewdef('vv5', true);
+ 
  -- clean up all the random objects we made above
  set client_min_messages = warning;
  DROP SCHEMA temp_view_test CASCADE;
