aboutsummaryrefslogtreecommitdiff
path: root/contrib/postgres_fdw/deparse.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 /contrib/postgres_fdw/deparse.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 'contrib/postgres_fdw/deparse.c')
-rw-r--r--contrib/postgres_fdw/deparse.c63
1 files changed, 37 insertions, 26 deletions
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;
}
/*