diff options
author | Noah Misch <noah@leadboat.com> | 2014-03-23 02:16:34 -0400 |
---|---|---|
committer | Noah Misch <noah@leadboat.com> | 2014-03-23 02:16:34 -0400 |
commit | 7cbe57c34dec4860243e6d0f81738cfbb6e5d069 (patch) | |
tree | 1b2e725b85caef56f986db8ae7c43732819c1f5c /src/backend/rewrite/rewriteHandler.c | |
parent | 6115480c543c0141011a99db78987ad13540be59 (diff) | |
download | postgresql-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.c | 36 |
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); + } } |