aboutsummaryrefslogtreecommitdiff
path: root/contrib/postgres_fdw/deparse.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2016-01-28 16:44:01 -0500
committerRobert Haas <rhaas@postgresql.org>2016-01-28 16:44:01 -0500
commitb88ef201d46e6519b5e0589358c952a4c0f5bf0f (patch)
tree4a686d632d3db12e47e9cffbf53b0f108ce697cf /contrib/postgres_fdw/deparse.c
parentfbe5a3fb73102c2cfec11aaaa4a67943f4474383 (diff)
downloadpostgresql-b88ef201d46e6519b5e0589358c952a4c0f5bf0f.tar.gz
postgresql-b88ef201d46e6519b5e0589358c952a4c0f5bf0f.zip
postgres_fdw: Refactor deparsing code for locking clauses.
The upcoming patch to allow join pushdown in postgres_fdw needs to use this code multiple times, which requires moving it to deparse.c. That seems like a good idea anyway, so do that now both on general principle and to simplify the future patch. Inspired by a patch by Shigeru Hanada and Ashutosh Bapat, but I did it a little differently than what that patch did.
Diffstat (limited to 'contrib/postgres_fdw/deparse.c')
-rw-r--r--contrib/postgres_fdw/deparse.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c
index e59af2c8e9b..e577a039566 100644
--- a/contrib/postgres_fdw/deparse.c
+++ b/contrib/postgres_fdw/deparse.c
@@ -45,7 +45,9 @@
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "nodes/nodeFuncs.h"
+#include "nodes/plannodes.h"
#include "optimizer/clauses.h"
+#include "optimizer/prep.h"
#include "optimizer/var.h"
#include "parser/parsetree.h"
#include "utils/builtins.h"
@@ -808,6 +810,64 @@ deparseTargetList(StringInfo buf,
}
/*
+ * Deparse the appropriate locking clause (FOR SELECT or FOR SHARE) for a
+ * given relation.
+ */
+void
+deparseLockingClause(StringInfo buf, PlannerInfo *root, RelOptInfo *rel)
+{
+ /*
+ * Add FOR UPDATE/SHARE if appropriate. We apply locking during the
+ * initial row fetch, rather than later on as is done for local tables.
+ * The extra roundtrips involved in trying to duplicate the local
+ * semantics exactly don't seem worthwhile (see also comments for
+ * RowMarkType).
+ *
+ * Note: because we actually run the query as a cursor, this assumes that
+ * DECLARE CURSOR ... FOR UPDATE is supported, which it isn't before 8.3.
+ */
+ if (rel->relid == root->parse->resultRelation &&
+ (root->parse->commandType == CMD_UPDATE ||
+ root->parse->commandType == CMD_DELETE))
+ {
+ /* Relation is UPDATE/DELETE target, so use FOR UPDATE */
+ appendStringInfoString(buf, " FOR UPDATE");
+ }
+ else
+ {
+ PlanRowMark *rc = get_plan_rowmark(root->rowMarks, rel->relid);
+
+ if (rc)
+ {
+ /*
+ * Relation is specified as a FOR UPDATE/SHARE target, so handle
+ * that. (But we could also see LCS_NONE, meaning this isn't a
+ * target relation after all.)
+ *
+ * For now, just ignore any [NO] KEY specification, since (a) it's
+ * not clear what that means for a remote table that we don't have
+ * complete information about, and (b) it wouldn't work anyway on
+ * older remote servers. Likewise, we don't worry about NOWAIT.
+ */
+ switch (rc->strength)
+ {
+ case LCS_NONE:
+ /* No locking needed */
+ break;
+ case LCS_FORKEYSHARE:
+ case LCS_FORSHARE:
+ appendStringInfoString(buf, " FOR SHARE");
+ break;
+ case LCS_FORNOKEYUPDATE:
+ case LCS_FORUPDATE:
+ appendStringInfoString(buf, " FOR UPDATE");
+ break;
+ }
+ }
+ }
+}
+
+/*
* Deparse WHERE clauses in given list of RestrictInfos and append them to buf.
*
* baserel is the foreign table we're planning for.