Rewrite ExecPartitionCheckEmitError for clarity
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 28 Dec 2018 17:47:05 +0000 (14:47 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 28 Dec 2018 17:47:05 +0000 (14:47 -0300)
The original was hard to follow and failed to comply with DRY principle.

Discussion: https://postgr.es/m/20181206222221.g5witbsklvqthjll@alvherre.pgsql

src/backend/executor/execMain.c

index d83d296d82c283a1c3a92dbb76afb864ea607b01..5974e8f57778d3ea8303de46bbb586a6237d9ff4 100644 (file)
@@ -1837,25 +1837,26 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
                            TupleTableSlot *slot,
                            EState *estate)
 {
-   Relation    rel = resultRelInfo->ri_RelationDesc;
-   Relation    orig_rel = rel;
-   TupleDesc   tupdesc = RelationGetDescr(rel);
+   Oid         root_relid;
+   TupleDesc   tupdesc;
    char       *val_desc;
    Bitmapset  *modifiedCols;
-   Bitmapset  *insertedCols;
-   Bitmapset  *updatedCols;
 
    /*
-    * Need to first convert the tuple to the root partitioned table's row
-    * type. For details, check similar comments in ExecConstraints().
+    * If the tuple has been routed, it's been converted to the partition's
+    * rowtype, which might differ from the root table's.  We must convert it
+    * back to the root table's rowtype so that val_desc in the error message
+    * matches the input tuple.
     */
    if (resultRelInfo->ri_PartitionRoot)
    {
-       TupleDesc   old_tupdesc = RelationGetDescr(rel);
+       TupleDesc   old_tupdesc;
        AttrNumber *map;
 
-       rel = resultRelInfo->ri_PartitionRoot;
-       tupdesc = RelationGetDescr(rel);
+       root_relid = RelationGetRelid(resultRelInfo->ri_PartitionRoot);
+       tupdesc = RelationGetDescr(resultRelInfo->ri_PartitionRoot);
+
+       old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
        /* a reverse map */
        map = convert_tuples_by_name_map_if_req(old_tupdesc, tupdesc,
                                                gettext_noop("could not convert row type"));
@@ -1868,11 +1869,16 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
            slot = execute_attr_map_slot(map, slot,
                                         MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
    }
+   else
+   {
+       root_relid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
+       tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
+   }
+
+   modifiedCols = bms_add_members(GetInsertedColumns(resultRelInfo, estate),
+                                  GetUpdatedColumns(resultRelInfo, estate));
 
-   insertedCols = GetInsertedColumns(resultRelInfo, estate);
-   updatedCols = GetUpdatedColumns(resultRelInfo, estate);
-   modifiedCols = bms_union(insertedCols, updatedCols);
-   val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
+   val_desc = ExecBuildSlotValueDescription(root_relid,
                                             slot,
                                             tupdesc,
                                             modifiedCols,
@@ -1880,7 +1886,7 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
    ereport(ERROR,
            (errcode(ERRCODE_CHECK_VIOLATION),
             errmsg("new row for relation \"%s\" violates partition constraint",
-                   RelationGetRelationName(orig_rel)),
+                   RelationGetRelationName(resultRelInfo->ri_RelationDesc)),
             val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
 }