diff options
author | Robert Haas <rhaas@postgresql.org> | 2016-01-28 16:44:01 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2016-01-28 16:44:01 -0500 |
commit | b88ef201d46e6519b5e0589358c952a4c0f5bf0f (patch) | |
tree | 4a686d632d3db12e47e9cffbf53b0f108ce697cf /contrib/postgres_fdw/deparse.c | |
parent | fbe5a3fb73102c2cfec11aaaa4a67943f4474383 (diff) | |
download | postgresql-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.c | 60 |
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. |