From 7cbe57c34dec4860243e6d0f81738cfbb6e5d069 Mon Sep 17 00:00:00 2001 From: Noah Misch Date: Sun, 23 Mar 2014 02:16:34 -0400 Subject: 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. --- contrib/postgres_fdw/deparse.c | 63 +++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 26 deletions(-) (limited to 'contrib/postgres_fdw/deparse.c') diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c index 2dfe80da0af..32c01350714 100644 --- a/contrib/postgres_fdw/deparse.c +++ b/contrib/postgres_fdw/deparse.c @@ -110,6 +110,7 @@ static void deparseTargetList(StringInfo buf, List **retrieved_attrs); static void deparseReturningList(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, + bool trig_after_row, List *returningList, List **retrieved_attrs); static void deparseColumnRef(StringInfo buf, int varno, int varattno, @@ -875,11 +876,9 @@ deparseInsertSql(StringInfo buf, PlannerInfo *root, else appendStringInfoString(buf, " DEFAULT VALUES"); - if (returningList) - deparseReturningList(buf, root, rtindex, rel, returningList, - retrieved_attrs); - else - *retrieved_attrs = NIL; + deparseReturningList(buf, root, rtindex, rel, + rel->trigdesc && rel->trigdesc->trig_insert_after_row, + returningList, retrieved_attrs); } /* @@ -919,11 +918,9 @@ deparseUpdateSql(StringInfo buf, PlannerInfo *root, } appendStringInfoString(buf, " WHERE ctid = $1"); - if (returningList) - deparseReturningList(buf, root, rtindex, rel, returningList, - retrieved_attrs); - else - *retrieved_attrs = NIL; + deparseReturningList(buf, root, rtindex, rel, + rel->trigdesc && rel->trigdesc->trig_update_after_row, + returningList, retrieved_attrs); } /* @@ -943,34 +940,48 @@ deparseDeleteSql(StringInfo buf, PlannerInfo *root, deparseRelation(buf, rel); appendStringInfoString(buf, " WHERE ctid = $1"); - if (returningList) - deparseReturningList(buf, root, rtindex, rel, returningList, - retrieved_attrs); - else - *retrieved_attrs = NIL; + deparseReturningList(buf, root, rtindex, rel, + rel->trigdesc && rel->trigdesc->trig_delete_after_row, + returningList, retrieved_attrs); } /* - * deparse RETURNING clause of INSERT/UPDATE/DELETE + * Add a RETURNING clause, if needed, to an INSERT/UPDATE/DELETE. */ static void deparseReturningList(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel, + bool trig_after_row, List *returningList, List **retrieved_attrs) { - Bitmapset *attrs_used; + Bitmapset *attrs_used = NULL; - /* - * We need the attrs mentioned in the query's RETURNING list. - */ - attrs_used = NULL; - pull_varattnos((Node *) returningList, rtindex, - &attrs_used); + if (trig_after_row) + { + /* whole-row reference acquires all non-system columns */ + attrs_used = + bms_make_singleton(0 - FirstLowInvalidHeapAttributeNumber); + } - appendStringInfoString(buf, " RETURNING "); - deparseTargetList(buf, root, rtindex, rel, attrs_used, - retrieved_attrs); + if (returningList != NIL) + { + /* + * We need the attrs, non-system and system, mentioned in the local + * query's RETURNING list. + */ + pull_varattnos((Node *) returningList, rtindex, + &attrs_used); + } + + if (attrs_used != NULL) + { + appendStringInfoString(buf, " RETURNING "); + deparseTargetList(buf, root, rtindex, rel, attrs_used, + retrieved_attrs); + } + else + *retrieved_attrs = NIL; } /* -- cgit v1.2.3