aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeModifyTable.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2017-05-01 08:23:01 -0400
committerRobert Haas <rhaas@postgresql.org>2017-05-01 08:23:01 -0400
commite180c8aa8caf5c55a273d4a8e6092e77ff3cff10 (patch)
treedb85b867105969b352fdd95ac83d506fae3f8e04 /src/backend/executor/nodeModifyTable.c
parente18b2c480da478f62781e06488cda56fe1b4e919 (diff)
downloadpostgresql-e180c8aa8caf5c55a273d4a8e6092e77ff3cff10.tar.gz
postgresql-e180c8aa8caf5c55a273d4a8e6092e77ff3cff10.zip
Fire per-statement triggers on partitioned tables.
Even though no actual tuples are ever inserted into a partitioned table (the actual tuples are in the partitions, not the partitioned table itself), we still need to have a ResultRelInfo for the partitioned table, or per-statement triggers won't get fired. Amit Langote, per a report from Rajkumar Raghuwanshi. Reviewed by me. Discussion: http://postgr.es/m/CAKcux6%3DwYospCRY2J4XEFuVy0L41S%3Dfic7rmkbsU-GXhhSbmBg%40mail.gmail.com
Diffstat (limited to 'src/backend/executor/nodeModifyTable.c')
-rw-r--r--src/backend/executor/nodeModifyTable.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 71e3b8ec2d6..652cd975996 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1328,19 +1328,29 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
static void
fireBSTriggers(ModifyTableState *node)
{
+ ResultRelInfo *resultRelInfo = node->resultRelInfo;
+
+ /*
+ * If the node modifies a partitioned table, we must fire its triggers.
+ * Note that in that case, node->resultRelInfo points to the first leaf
+ * partition, not the root table.
+ */
+ if (node->rootResultRelInfo != NULL)
+ resultRelInfo = node->rootResultRelInfo;
+
switch (node->operation)
{
case CMD_INSERT:
- ExecBSInsertTriggers(node->ps.state, node->resultRelInfo);
+ ExecBSInsertTriggers(node->ps.state, resultRelInfo);
if (node->mt_onconflict == ONCONFLICT_UPDATE)
ExecBSUpdateTriggers(node->ps.state,
- node->resultRelInfo);
+ resultRelInfo);
break;
case CMD_UPDATE:
- ExecBSUpdateTriggers(node->ps.state, node->resultRelInfo);
+ ExecBSUpdateTriggers(node->ps.state, resultRelInfo);
break;
case CMD_DELETE:
- ExecBSDeleteTriggers(node->ps.state, node->resultRelInfo);
+ ExecBSDeleteTriggers(node->ps.state, resultRelInfo);
break;
default:
elog(ERROR, "unknown operation");
@@ -1354,19 +1364,29 @@ fireBSTriggers(ModifyTableState *node)
static void
fireASTriggers(ModifyTableState *node)
{
+ ResultRelInfo *resultRelInfo = node->resultRelInfo;
+
+ /*
+ * If the node modifies a partitioned table, we must fire its triggers.
+ * Note that in that case, node->resultRelInfo points to the first leaf
+ * partition, not the root table.
+ */
+ if (node->rootResultRelInfo != NULL)
+ resultRelInfo = node->rootResultRelInfo;
+
switch (node->operation)
{
case CMD_INSERT:
if (node->mt_onconflict == ONCONFLICT_UPDATE)
ExecASUpdateTriggers(node->ps.state,
- node->resultRelInfo);
- ExecASInsertTriggers(node->ps.state, node->resultRelInfo);
+ resultRelInfo);
+ ExecASInsertTriggers(node->ps.state, resultRelInfo);
break;
case CMD_UPDATE:
- ExecASUpdateTriggers(node->ps.state, node->resultRelInfo);
+ ExecASUpdateTriggers(node->ps.state, resultRelInfo);
break;
case CMD_DELETE:
- ExecASDeleteTriggers(node->ps.state, node->resultRelInfo);
+ ExecASDeleteTriggers(node->ps.state, resultRelInfo);
break;
default:
elog(ERROR, "unknown operation");
@@ -1652,6 +1672,12 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);
mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;
+
+ /* If modifying a partitioned table, initialize the root table info */
+ if (node->rootResultRelIndex >= 0)
+ mtstate->rootResultRelInfo = estate->es_root_result_relations +
+ node->rootResultRelIndex;
+
mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans);
mtstate->mt_nplans = nplans;
mtstate->mt_onconflict = node->onConflictAction;