]> granicus.if.org Git - postgresql/commitdiff
postgres_fdw: Refactor deparsing code for locking clauses.
authorRobert Haas <rhaas@postgresql.org>
Thu, 28 Jan 2016 21:44:01 +0000 (16:44 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 28 Jan 2016 21:44:01 +0000 (16:44 -0500)
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.

contrib/postgres_fdw/deparse.c
contrib/postgres_fdw/postgres_fdw.c
contrib/postgres_fdw/postgres_fdw.h

index e59af2c8e9b0ae35cc7d74a906553a96c5bdb20b..e577a039566b4b3775828938276ccf1730258d4c 100644 (file)
@@ -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"
@@ -807,6 +809,64 @@ deparseTargetList(StringInfo buf,
                appendStringInfoString(buf, "NULL");
 }
 
+/*
+ * 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.
  *
index a237e152c02f0fa60c9f3796ccc121ecc0ea83ff..0aa7fbeac04b326faa3844c8cf73388bd52011db 100644 (file)
@@ -1013,55 +1013,8 @@ postgresGetForeignPlan(PlannerInfo *root,
        if (best_path->path.pathkeys)
                appendOrderByClause(&sql, root, baserel, best_path->path.pathkeys);
 
-       /*
-        * 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 (baserel->relid == root->parse->resultRelation &&
-               (root->parse->commandType == CMD_UPDATE ||
-                root->parse->commandType == CMD_DELETE))
-       {
-               /* Relation is UPDATE/DELETE target, so use FOR UPDATE */
-               appendStringInfoString(&sql, " FOR UPDATE");
-       }
-       else
-       {
-               PlanRowMark *rc = get_plan_rowmark(root->rowMarks, baserel->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(&sql, " FOR SHARE");
-                                       break;
-                               case LCS_FORNOKEYUPDATE:
-                               case LCS_FORUPDATE:
-                                       appendStringInfoString(&sql, " FOR UPDATE");
-                                       break;
-                       }
-               }
-       }
+       /* Add any necessary FOR UPDATE/SHARE. */
+       deparseLockingClause(&sql, root, baserel);
 
        /*
         * Build the fdw_private list that will be available to the executor.
index 59e9f60c04bbe065f1d207360b77f5a8d7df0159..0d8c271505c1038eb63773dd36e0bc0ccadafc2b 100644 (file)
@@ -88,6 +88,8 @@ extern void deparseSelectSql(StringInfo buf,
                                 RelOptInfo *baserel,
                                 Bitmapset *attrs_used,
                                 List **retrieved_attrs);
+extern void deparseLockingClause(StringInfo buf,
+                                        PlannerInfo *root, RelOptInfo *rel);
 extern void appendWhereClause(StringInfo buf,
                                  PlannerInfo *root,
                                  RelOptInfo *baserel,