@@ -82,6 +82,7 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
82
82
static bool ExecCheckRTEPerms (RangeTblEntry * rte );
83
83
static void ExecCheckXactReadOnly (PlannedStmt * plannedstmt );
84
84
static char * ExecBuildSlotValueDescription (TupleTableSlot * slot ,
85
+ TupleDesc tupdesc ,
85
86
int maxfieldlen );
86
87
static void EvalPlanQualStart (EPQState * epqstate , EState * parentestate ,
87
88
Plan * planTree );
@@ -1584,25 +1585,28 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
1584
1585
TupleTableSlot * slot , EState * estate )
1585
1586
{
1586
1587
Relation rel = resultRelInfo -> ri_RelationDesc ;
1587
- TupleConstr * constr = rel -> rd_att -> constr ;
1588
+ TupleDesc tupdesc = RelationGetDescr (rel );
1589
+ TupleConstr * constr = tupdesc -> constr ;
1588
1590
1589
1591
Assert (constr );
1590
1592
1591
1593
if (constr -> has_not_null )
1592
1594
{
1593
- int natts = rel -> rd_att -> natts ;
1595
+ int natts = tupdesc -> natts ;
1594
1596
int attrChk ;
1595
1597
1596
1598
for (attrChk = 1 ; attrChk <= natts ; attrChk ++ )
1597
1599
{
1598
- if (rel -> rd_att -> attrs [attrChk - 1 ]-> attnotnull &&
1600
+ if (tupdesc -> attrs [attrChk - 1 ]-> attnotnull &&
1599
1601
slot_attisnull (slot , attrChk ))
1600
1602
ereport (ERROR ,
1601
1603
(errcode (ERRCODE_NOT_NULL_VIOLATION ),
1602
1604
errmsg ("null value in column \"%s\" violates not-null constraint" ,
1603
- NameStr (rel -> rd_att -> attrs [attrChk - 1 ]-> attname )),
1605
+ NameStr (tupdesc -> attrs [attrChk - 1 ]-> attname )),
1604
1606
errdetail ("Failing row contains %s." ,
1605
- ExecBuildSlotValueDescription (slot , 64 )),
1607
+ ExecBuildSlotValueDescription (slot ,
1608
+ tupdesc ,
1609
+ 64 )),
1606
1610
errtablecol (rel , attrChk )));
1607
1611
}
1608
1612
}
@@ -1617,7 +1621,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
1617
1621
errmsg ("new row for relation \"%s\" violates check constraint \"%s\"" ,
1618
1622
RelationGetRelationName (rel ), failed ),
1619
1623
errdetail ("Failing row contains %s." ,
1620
- ExecBuildSlotValueDescription (slot , 64 )),
1624
+ ExecBuildSlotValueDescription (slot ,
1625
+ tupdesc ,
1626
+ 64 )),
1621
1627
errtableconstraint (rel , failed )));
1622
1628
}
1623
1629
}
@@ -1626,15 +1632,22 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
1626
1632
* ExecBuildSlotValueDescription -- construct a string representing a tuple
1627
1633
*
1628
1634
* This is intentionally very similar to BuildIndexValueDescription, but
1629
- * unlike that function, we truncate long field values. That seems necessary
1630
- * here since heap field values could be very long, whereas index entries
1631
- * typically aren't so wide.
1635
+ * unlike that function, we truncate long field values (to at most maxfieldlen
1636
+ * bytes). That seems necessary here since heap field values could be very
1637
+ * long, whereas index entries typically aren't so wide.
1638
+ *
1639
+ * Also, unlike the case with index entries, we need to be prepared to ignore
1640
+ * dropped columns. We used to use the slot's tuple descriptor to decode the
1641
+ * data, but the slot's descriptor doesn't identify dropped columns, so we
1642
+ * now need to be passed the relation's descriptor.
1632
1643
*/
1633
1644
static char *
1634
- ExecBuildSlotValueDescription (TupleTableSlot * slot , int maxfieldlen )
1645
+ ExecBuildSlotValueDescription (TupleTableSlot * slot ,
1646
+ TupleDesc tupdesc ,
1647
+ int maxfieldlen )
1635
1648
{
1636
1649
StringInfoData buf ;
1637
- TupleDesc tupdesc = slot -> tts_tupleDescriptor ;
1650
+ bool write_comma = false ;
1638
1651
int i ;
1639
1652
1640
1653
/* Make sure the tuple is fully deconstructed */
@@ -1649,6 +1662,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
1649
1662
char * val ;
1650
1663
int vallen ;
1651
1664
1665
+ /* ignore dropped columns */
1666
+ if (tupdesc -> attrs [i ]-> attisdropped )
1667
+ continue ;
1668
+
1652
1669
if (slot -> tts_isnull [i ])
1653
1670
val = "null" ;
1654
1671
else
@@ -1661,8 +1678,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
1661
1678
val = OidOutputFunctionCall (foutoid , slot -> tts_values [i ]);
1662
1679
}
1663
1680
1664
- if (i > 0 )
1681
+ if (write_comma )
1665
1682
appendStringInfoString (& buf , ", " );
1683
+ else
1684
+ write_comma = true;
1666
1685
1667
1686
/* truncate if needed */
1668
1687
vallen = strlen (val );
0 commit comments