aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/copy.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2017-06-07 12:45:32 -0400
committerRobert Haas <rhaas@postgresql.org>2017-06-07 12:50:45 -0400
commit15ce775faa428dc91027e4e2d6b7a167a27118b5 (patch)
tree4c5607db44f239459c851c4b58eed69fac6fca7b /src/backend/commands/copy.c
parente6c33d594a004a2c831cdff1a16276347d30f703 (diff)
downloadpostgresql-15ce775faa428dc91027e4e2d6b7a167a27118b5.tar.gz
postgresql-15ce775faa428dc91027e4e2d6b7a167a27118b5.zip
Prevent BEFORE triggers from violating partitioning constraints.
Since tuple-routing implicitly checks the partitioning constraints at least for the levels of the partitioning hierarchy it traverses, there's normally no need to revalidate the partitioning constraint after performing tuple routing. However, if there's a BEFORE trigger on the target partition, it could modify the tuple, causing the partitioning constraint to be violated. Catch that case. Also, instead of checking the root table's partition constraint after tuple-routing, check it beforehand. Otherwise, the rules for when the partitioning constraint gets checked get too complicated, because you sometimes have to check part of the constraint but not all of it. This effectively reverts commit 39162b2030fb0a35a6bb28dc636b5a71b8df8d1c in favor of a different approach altogether. Report by me. Initial debugging by Jeevan Ladhe. Patch by Amit Langote, reviewed by me. Discussion: http://postgr.es/m/CA+Tgmoa9DTgeVOqopieV8d1QRpddmP65aCdxyjdYDoEO5pS5KA@mail.gmail.com
Diffstat (limited to 'src/backend/commands/copy.c')
-rw-r--r--src/backend/commands/copy.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 810bae5dadc..0a33c40c17f 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2640,9 +2640,24 @@ CopyFrom(CopyState cstate)
}
else
{
+ /*
+ * We always check the partition constraint, including when
+ * the tuple got here via tuple-routing. However we don't
+ * need to in the latter case if no BR trigger is defined on
+ * the partition. Note that a BR trigger might modify the
+ * tuple such that the partition constraint is no longer
+ * satisfied, so we need to check in that case.
+ */
+ bool check_partition_constr =
+ (resultRelInfo->ri_PartitionCheck != NIL);
+
+ if (saved_resultRelInfo != NULL &&
+ !(resultRelInfo->ri_TrigDesc &&
+ resultRelInfo->ri_TrigDesc->trig_insert_before_row))
+ check_partition_constr = false;
+
/* Check the constraints of the tuple */
- if (cstate->rel->rd_att->constr ||
- resultRelInfo->ri_PartitionCheck)
+ if (cstate->rel->rd_att->constr || check_partition_constr)
ExecConstraints(resultRelInfo, slot, estate);
if (useHeapMultiInsert)