aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteHandler.c
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2014-03-23 02:16:34 -0400
committerNoah Misch <noah@leadboat.com>2014-03-23 02:16:34 -0400
commit7cbe57c34dec4860243e6d0f81738cfbb6e5d069 (patch)
tree1b2e725b85caef56f986db8ae7c43732819c1f5c /src/backend/rewrite/rewriteHandler.c
parent6115480c543c0141011a99db78987ad13540be59 (diff)
downloadpostgresql-7cbe57c34dec4860243e6d0f81738cfbb6e5d069.tar.gz
postgresql-7cbe57c34dec4860243e6d0f81738cfbb6e5d069.zip
Offer triggers on foreign tables.
This covers all the SQL-standard trigger types supported for regular tables; it does not cover constraint triggers. The approach for acquiring the old row mirrors that for view INSTEAD OF triggers. For AFTER ROW triggers, we spool the foreign tuples to a tuplestore. This changes the FDW API contract; when deciding which columns to populate in the slot returned from data modification callbacks, writable FDWs will need to check for AFTER ROW triggers in addition to checking for a RETURNING clause. In support of the feature addition, refactor the TriggerFlags bits and the assembly of old tuples in ModifyTable. Ronan Dunklau, reviewed by KaiGai Kohei; some additional hacking by me.
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r--src/backend/rewrite/rewriteHandler.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 3728d8c418c..5dbcce3e550 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -1199,7 +1199,7 @@ static void
rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte,
Relation target_relation)
{
- Var *var;
+ Var *var = NULL;
const char *attrname;
TargetEntry *tle;
@@ -1231,7 +1231,26 @@ rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte,
fdwroutine->AddForeignUpdateTargets(parsetree, target_rte,
target_relation);
- return;
+ /*
+ * If we have a row-level trigger corresponding to the operation, emit
+ * a whole-row Var so that executor will have the "old" row to pass to
+ * the trigger. Alas, this misses system columns.
+ */
+ if (target_relation->trigdesc &&
+ ((parsetree->commandType == CMD_UPDATE &&
+ (target_relation->trigdesc->trig_update_after_row ||
+ target_relation->trigdesc->trig_update_before_row)) ||
+ (parsetree->commandType == CMD_DELETE &&
+ (target_relation->trigdesc->trig_delete_after_row ||
+ target_relation->trigdesc->trig_delete_before_row))))
+ {
+ var = makeWholeRowVar(target_rte,
+ parsetree->resultRelation,
+ 0,
+ false);
+
+ attrname = "wholerow";
+ }
}
else
{
@@ -1247,12 +1266,15 @@ rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte,
attrname = "wholerow";
}
- tle = makeTargetEntry((Expr *) var,
- list_length(parsetree->targetList) + 1,
- pstrdup(attrname),
- true);
+ if (var != NULL)
+ {
+ tle = makeTargetEntry((Expr *) var,
+ list_length(parsetree->targetList) + 1,
+ pstrdup(attrname),
+ true);
- parsetree->targetList = lappend(parsetree->targetList, tle);
+ parsetree->targetList = lappend(parsetree->targetList, tle);
+ }
}