diff options
author | Robert Haas <rhaas@postgresql.org> | 2017-04-10 12:20:08 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2017-04-10 12:20:08 -0400 |
commit | c0a8ae7be392aa09dd7e148ff662013e8e148893 (patch) | |
tree | c2c280cf4d22b8f4a056247fbce70db8d14f224b /src/backend/executor/execMain.c | |
parent | 244f1c89070c1a661623bf1eaddf1307f8f598a3 (diff) | |
download | postgresql-c0a8ae7be392aa09dd7e148ff662013e8e148893.tar.gz postgresql-c0a8ae7be392aa09dd7e148ff662013e8e148893.zip |
Fix reporting of violations in ExecConstraints, again.
We decided in f1b4c771ea74f42447dccaed42ffcdcccf3aa694 to pass the
original slot to ExecConstraints(), but that breaks when there are
BEFORE ROW triggers involved. So we need to do reverse-map the tuples
back to the original descriptor instead, as Amit originally proposed.
Amit Langote, reviewed by Ashutosh Bapat. One overlooked comment
fixed by me.
Discussion: http://postgr.es/m/b3a17254-6849-e542-2353-bde4e880b6a4@lab.ntt.co.jp
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r-- | src/backend/executor/execMain.c | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 920b12072fb..5c12fb457d5 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -1824,14 +1824,12 @@ ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, * the partition constraint, if any. * * Note: 'slot' contains the tuple to check the constraints of, which may - * have been converted from the original input tuple after tuple routing, - * while 'orig_slot' contains the original tuple to be shown in the message, - * if an error occurs. + * have been converted from the original input tuple after tuple routing. + * 'resultRelInfo' is the original result relation, before tuple routing. */ void ExecConstraints(ResultRelInfo *resultRelInfo, - TupleTableSlot *slot, TupleTableSlot *orig_slot, - EState *estate) + TupleTableSlot *slot, EState *estate) { Relation rel = resultRelInfo->ri_RelationDesc; TupleDesc tupdesc = RelationGetDescr(rel); @@ -1854,23 +1852,37 @@ ExecConstraints(ResultRelInfo *resultRelInfo, { char *val_desc; Relation orig_rel = rel; - TupleDesc orig_tupdesc = tupdesc; + TupleDesc orig_tupdesc = RelationGetDescr(rel); /* - * choose the correct relation to build val_desc from the - * tuple contained in orig_slot + * 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 shown error message matches the + * input tuple. */ if (resultRelInfo->ri_PartitionRoot) { + HeapTuple tuple = ExecFetchSlotTuple(slot); + TupleConversionMap *map; + rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); + /* a reverse map */ + map = convert_tuples_by_name(orig_tupdesc, tupdesc, + gettext_noop("could not convert row type")); + if (map != NULL) + { + tuple = do_convert_tuple(tuple, map); + ExecStoreTuple(tuple, slot, InvalidBuffer, false); + } } insertedCols = GetInsertedColumns(resultRelInfo, estate); updatedCols = GetUpdatedColumns(resultRelInfo, estate); modifiedCols = bms_union(insertedCols, updatedCols); val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), - orig_slot, + slot, tupdesc, modifiedCols, 64); @@ -1897,15 +1909,27 @@ ExecConstraints(ResultRelInfo *resultRelInfo, /* See the comment above. */ if (resultRelInfo->ri_PartitionRoot) { + HeapTuple tuple = ExecFetchSlotTuple(slot); + TupleDesc old_tupdesc = RelationGetDescr(rel); + TupleConversionMap *map; + rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); + /* a reverse map */ + map = convert_tuples_by_name(old_tupdesc, tupdesc, + gettext_noop("could not convert row type")); + if (map != NULL) + { + tuple = do_convert_tuple(tuple, map); + ExecStoreTuple(tuple, slot, InvalidBuffer, false); + } } insertedCols = GetInsertedColumns(resultRelInfo, estate); updatedCols = GetUpdatedColumns(resultRelInfo, estate); modifiedCols = bms_union(insertedCols, updatedCols); val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), - orig_slot, + slot, tupdesc, modifiedCols, 64); @@ -1927,15 +1951,27 @@ ExecConstraints(ResultRelInfo *resultRelInfo, /* See the comment above. */ if (resultRelInfo->ri_PartitionRoot) { + HeapTuple tuple = ExecFetchSlotTuple(slot); + TupleDesc old_tupdesc = RelationGetDescr(rel); + TupleConversionMap *map; + rel = resultRelInfo->ri_PartitionRoot; tupdesc = RelationGetDescr(rel); + /* a reverse map */ + map = convert_tuples_by_name(old_tupdesc, tupdesc, + gettext_noop("could not convert row type")); + if (map != NULL) + { + tuple = do_convert_tuple(tuple, map); + ExecStoreTuple(tuple, slot, InvalidBuffer, false); + } } insertedCols = GetInsertedColumns(resultRelInfo, estate); updatedCols = GetUpdatedColumns(resultRelInfo, estate); modifiedCols = bms_union(insertedCols, updatedCols); val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), - orig_slot, + slot, tupdesc, modifiedCols, 64); |