@@ -80,6 +80,7 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
80
80
static bool ExecCheckRTEPerms (RangeTblEntry * rte );
81
81
static void ExecCheckXactReadOnly (PlannedStmt * plannedstmt );
82
82
static char * ExecBuildSlotValueDescription (TupleTableSlot * slot ,
83
+ TupleDesc tupdesc ,
83
84
int maxfieldlen );
84
85
static void EvalPlanQualStart (EPQState * epqstate , EState * parentestate ,
85
86
Plan * planTree );
@@ -1506,25 +1507,28 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
1506
1507
TupleTableSlot * slot , EState * estate )
1507
1508
{
1508
1509
Relation rel = resultRelInfo -> ri_RelationDesc ;
1509
- TupleConstr * constr = rel -> rd_att -> constr ;
1510
+ TupleDesc tupdesc = RelationGetDescr (rel );
1511
+ TupleConstr * constr = tupdesc -> constr ;
1510
1512
1511
1513
Assert (constr );
1512
1514
1513
1515
if (constr -> has_not_null )
1514
1516
{
1515
- int natts = rel -> rd_att -> natts ;
1517
+ int natts = tupdesc -> natts ;
1516
1518
int attrChk ;
1517
1519
1518
1520
for (attrChk = 1 ; attrChk <= natts ; attrChk ++ )
1519
1521
{
1520
- if (rel -> rd_att -> attrs [attrChk - 1 ]-> attnotnull &&
1522
+ if (tupdesc -> attrs [attrChk - 1 ]-> attnotnull &&
1521
1523
slot_attisnull (slot , attrChk ))
1522
1524
ereport (ERROR ,
1523
1525
(errcode (ERRCODE_NOT_NULL_VIOLATION ),
1524
1526
errmsg ("null value in column \"%s\" violates not-null constraint" ,
1525
- NameStr (rel -> rd_att -> attrs [attrChk - 1 ]-> attname )),
1527
+ NameStr (tupdesc -> attrs [attrChk - 1 ]-> attname )),
1526
1528
errdetail ("Failing row contains %s." ,
1527
- ExecBuildSlotValueDescription (slot , 64 ))));
1529
+ ExecBuildSlotValueDescription (slot ,
1530
+ tupdesc ,
1531
+ 64 ))));
1528
1532
}
1529
1533
}
1530
1534
@@ -1538,23 +1542,32 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
1538
1542
errmsg ("new row for relation \"%s\" violates check constraint \"%s\"" ,
1539
1543
RelationGetRelationName (rel ), failed ),
1540
1544
errdetail ("Failing row contains %s." ,
1541
- ExecBuildSlotValueDescription (slot , 64 ))));
1545
+ ExecBuildSlotValueDescription (slot ,
1546
+ tupdesc ,
1547
+ 64 ))));
1542
1548
}
1543
1549
}
1544
1550
1545
1551
/*
1546
1552
* ExecBuildSlotValueDescription -- construct a string representing a tuple
1547
1553
*
1548
1554
* This is intentionally very similar to BuildIndexValueDescription, but
1549
- * unlike that function, we truncate long field values. That seems necessary
1550
- * here since heap field values could be very long, whereas index entries
1551
- * typically aren't so wide.
1555
+ * unlike that function, we truncate long field values (to at most maxfieldlen
1556
+ * bytes). That seems necessary here since heap field values could be very
1557
+ * long, whereas index entries typically aren't so wide.
1558
+ *
1559
+ * Also, unlike the case with index entries, we need to be prepared to ignore
1560
+ * dropped columns. We used to use the slot's tuple descriptor to decode the
1561
+ * data, but the slot's descriptor doesn't identify dropped columns, so we
1562
+ * now need to be passed the relation's descriptor.
1552
1563
*/
1553
1564
static char *
1554
- ExecBuildSlotValueDescription (TupleTableSlot * slot , int maxfieldlen )
1565
+ ExecBuildSlotValueDescription (TupleTableSlot * slot ,
1566
+ TupleDesc tupdesc ,
1567
+ int maxfieldlen )
1555
1568
{
1556
1569
StringInfoData buf ;
1557
- TupleDesc tupdesc = slot -> tts_tupleDescriptor ;
1570
+ bool write_comma = false ;
1558
1571
int i ;
1559
1572
1560
1573
/* Make sure the tuple is fully deconstructed */
@@ -1569,6 +1582,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
1569
1582
char * val ;
1570
1583
int vallen ;
1571
1584
1585
+ /* ignore dropped columns */
1586
+ if (tupdesc -> attrs [i ]-> attisdropped )
1587
+ continue ;
1588
+
1572
1589
if (slot -> tts_isnull [i ])
1573
1590
val = "null" ;
1574
1591
else
@@ -1581,8 +1598,10 @@ ExecBuildSlotValueDescription(TupleTableSlot *slot, int maxfieldlen)
1581
1598
val = OidOutputFunctionCall (foutoid , slot -> tts_values [i ]);
1582
1599
}
1583
1600
1584
- if (i > 0 )
1601
+ if (write_comma )
1585
1602
appendStringInfoString (& buf , ", " );
1603
+ else
1604
+ write_comma = true;
1586
1605
1587
1606
/* truncate if needed */
1588
1607
vallen = strlen (val );
0 commit comments