diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 0b47106..6be17a9 100644
*** a/src/backend/executor/execMain.c
--- b/src/backend/executor/execMain.c
*************** static void ExecutePlan(EState *estate, 
*** 83,88 ****
--- 83,89 ----
  static bool ExecCheckRTEPerms(RangeTblEntry *rte);
  static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt);
  static char *ExecBuildSlotValueDescription(TupleTableSlot *slot,
+ 							  TupleDesc tupdesc,
  							  int maxfieldlen);
  static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
  				  Plan *planTree);
*************** ExecConstraints(ResultRelInfo *resultRel
*** 1586,1610 ****
  				TupleTableSlot *slot, EState *estate)
  {
  	Relation	rel = resultRelInfo->ri_RelationDesc;
! 	TupleConstr *constr = rel->rd_att->constr;
  
  	Assert(constr);
  
  	if (constr->has_not_null)
  	{
! 		int			natts = rel->rd_att->natts;
  		int			attrChk;
  
  		for (attrChk = 1; attrChk <= natts; attrChk++)
  		{
! 			if (rel->rd_att->attrs[attrChk - 1]->attnotnull &&
  				slot_attisnull(slot, attrChk))
  				ereport(ERROR,
  						(errcode(ERRCODE_NOT_NULL_VIOLATION),
  						 errmsg("null value in column \"%s\" violates not-null constraint",
! 						  NameStr(rel->rd_att->attrs[attrChk - 1]->attname)),
  						 errdetail("Failing row contains %s.",
! 								   ExecBuildSlotValueDescription(slot, 64)),
  						 errtablecol(rel, attrChk)));
  		}
  	}
--- 1587,1614 ----
  				TupleTableSlot *slot, EState *estate)
  {
  	Relation	rel = resultRelInfo->ri_RelationDesc;
! 	TupleDesc	tupdesc = RelationGetDescr(rel);
! 	TupleConstr *constr = tupdesc->constr;
  
  	Assert(constr);
  
  	if (constr->has_not_null)
  	{
! 		int			natts = tupdesc->natts;
  		int			attrChk;
  
  		for (attrChk = 1; attrChk <= natts; attrChk++)
  		{
! 			if (tupdesc->attrs[attrChk - 1]->attnotnull &&
  				slot_attisnull(slot, attrChk))
  				ereport(ERROR,
  						(errcode(ERRCODE_NOT_NULL_VIOLATION),
  						 errmsg("null value in column \"%s\" violates not-null constraint",
! 							  NameStr(tupdesc->attrs[attrChk - 1]->attname)),
  						 errdetail("Failing row contains %s.",
! 								   ExecBuildSlotValueDescription(slot,
! 																 tupdesc,
! 																 64)),
  						 errtablecol(rel, attrChk)));
  		}
  	}
*************** ExecConstraints(ResultRelInfo *resultRel
*** 1619,1625 ****
  					 errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
  							RelationGetRelationName(rel), failed),
  					 errdetail("Failing row contains %s.",
! 							   ExecBuildSlotValueDescription(slot, 64)),
  					 errtableconstraint(rel, failed)));
  	}
  }
--- 1623,1631 ----
  					 errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
  							RelationGetRelationName(rel), failed),
  					 errdetail("Failing row contains %s.",
! 							   ExecBuildSlotValueDescription(slot,
! 															 tupdesc,
! 															 64)),
  					 errtableconstraint(rel, failed)));
  	}
  }
*************** ExecWithCheckOptions(ResultRelInfo *resu
*** 1663,1669 ****
  					 errmsg("new row violates WITH CHECK OPTION for view \"%s\"",
  							wco->viewname),
  					 errdetail("Failing row contains %s.",
! 							   ExecBuildSlotValueDescription(slot, 64))));
  	}
  }
  
--- 1669,1677 ----
  					 errmsg("new row violates WITH CHECK OPTION for view \"%s\"",
  							wco->viewname),
  					 errdetail("Failing row contains %s.",
! 							   ExecBuildSlotValueDescription(slot,
! 							RelationGetDescr(resultRelInfo->ri_RelationDesc),
! 															 64))));
  	}
  }
  
*************** ExecWithCheckOptions(ResultRelInfo *resu
*** 1671,1685 ****
   * ExecBuildSlotValueDescription -- construct a string representing a tuple
   *
   * This is intentionally very similar to BuildIndexValueDescription, but
!  * unlike that function, we truncate long field values.  That seems necessary
!  * here since heap field values could be very long, whereas index entries
!  * typically aren't so wide.
   */
  static char *
! ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
  {
  	StringInfoData buf;
! 	TupleDesc	tupdesc = slot->tts_tupleDescriptor;
  	int			i;
  
  	/* Make sure the tuple is fully deconstructed */
--- 1679,1700 ----
   * ExecBuildSlotValueDescription -- construct a string representing a tuple
   *
   * This is intentionally very similar to BuildIndexValueDescription, but
!  * unlike that function, we truncate long field values (to at most maxfieldlen
!  * bytes).	That seems necessary here since heap field values could be very
!  * long, whereas index entries typically aren't so wide.
!  *
!  * Also, unlike the case with index entries, we need to be prepared to ignore
!  * dropped columns.  We used to use the slot's tuple descriptor to decode the
!  * data, but the slot's descriptor doesn't identify dropped columns, so we
!  * now need to be passed the relation's descriptor.
   */
  static char *
! ExecBuildSlotValueDescription(TupleTableSlot *slot,
! 							  TupleDesc tupdesc,
! 							  int maxfieldlen)
  {
  	StringInfoData buf;
! 	bool		write_comma = false;
  	int			i;
  
  	/* Make sure the tuple is fully deconstructed */
*************** ExecBuildSlotValueDescription(TupleTable
*** 1694,1699 ****
--- 1709,1718 ----
  		char	   *val;
  		int			vallen;
  
+ 		/* ignore dropped columns */
+ 		if (tupdesc->attrs[i]->attisdropped)
+ 			continue;
+ 
  		if (slot->tts_isnull[i])
  			val = "null";
  		else
*************** ExecBuildSlotValueDescription(TupleTable
*** 1706,1713 ****
  			val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
  		}
  
! 		if (i > 0)
  			appendStringInfoString(&buf, ", ");
  
  		/* truncate if needed */
  		vallen = strlen(val);
--- 1725,1734 ----
  			val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
  		}
  
! 		if (write_comma)
  			appendStringInfoString(&buf, ", ");
+ 		else
+ 			write_comma = true;
  
  		/* truncate if needed */
  		vallen = strlen(val);
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 7cc0084..7366392 100644
*** a/src/test/regress/expected/alter_table.out
--- b/src/test/regress/expected/alter_table.out
*************** select * from atacc1;
*** 1197,1202 ****
--- 1197,1216 ----
  (1 row)
  
  drop table atacc1;
+ -- test constraint error reporting in presence of dropped columns
+ create table atacc1 (id serial primary key, value int check (value < 10));
+ insert into atacc1(value) values (100);
+ ERROR:  new row for relation "atacc1" violates check constraint "atacc1_value_check"
+ DETAIL:  Failing row contains (1, 100).
+ alter table atacc1 drop column value;
+ alter table atacc1 add column value int check (value < 10);
+ insert into atacc1(value) values (100);
+ ERROR:  new row for relation "atacc1" violates check constraint "atacc1_value_check"
+ DETAIL:  Failing row contains (2, 100).
+ insert into atacc1(id, value) values (null, 0);
+ ERROR:  null value in column "id" violates not-null constraint
+ DETAIL:  Failing row contains (null, 0).
+ drop table atacc1;
  -- test inheritance
  create table parent (a int, b int, c int);
  insert into parent values (1, 2, 3);
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index a546ba7..0d3b79b 100644
*** a/src/test/regress/sql/alter_table.sql
--- b/src/test/regress/sql/alter_table.sql
*************** select * from atacc1;
*** 874,879 ****
--- 874,888 ----
  
  drop table atacc1;
  
+ -- test constraint error reporting in presence of dropped columns
+ create table atacc1 (id serial primary key, value int check (value < 10));
+ insert into atacc1(value) values (100);
+ alter table atacc1 drop column value;
+ alter table atacc1 add column value int check (value < 10);
+ insert into atacc1(value) values (100);
+ insert into atacc1(id, value) values (null, 0);
+ drop table atacc1;
+ 
  -- test inheritance
  create table parent (a int, b int, c int);
  insert into parent values (1, 2, 3);
