summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/nodes/readfuncs.c4
-rw-r--r--src/backend/pgxc/pool/execRemote.c22
-rw-r--r--src/backend/utils/cache/plancache.c21
-rw-r--r--src/backend/utils/cache/relcache.c18
-rw-r--r--src/include/nodes/nodes.h2
5 files changed, 61 insertions, 6 deletions
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 99dfce1cb9..dd47b2698c 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -59,10 +59,12 @@
* Later we may want to add extra parameter in stringToNode() function
*/
static bool portable_input = false;
-void
+bool
set_portable_input(bool value)
{
+ bool old_portable_input = portable_input;
portable_input = value;
+ return old_portable_input;
}
#endif /* XCP */
diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c
index 0286337639..2fd23687fc 100644
--- a/src/backend/pgxc/pool/execRemote.c
+++ b/src/backend/pgxc/pool/execRemote.c
@@ -5600,8 +5600,26 @@ ExecInitRemoteSubplan(RemoteSubplan *node, EState *estate, int eflags)
rstmt.distributionNodes = node->distributionNodes;
rstmt.distributionRestrict = node->distributionRestrict;
- set_portable_output(true);
- remotestate->subplanstr = nodeToString(&rstmt);
+ /*
+ * A try-catch block to ensure that we don't leave behind a stale state
+ * if nodeToString fails for whatever reason.
+ *
+ * XXX We should probably rewrite it someday by either passing a
+ * context to nodeToString() or remembering this information somewhere
+ * else which gets reset in case of errors. But for now, this seems
+ * enough.
+ */
+ PG_TRY();
+ {
+ set_portable_output(true);
+ remotestate->subplanstr = nodeToString(&rstmt);
+ }
+ PG_CATCH();
+ {
+ set_portable_output(false);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
set_portable_output(false);
/*
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 524c62d7a0..501cd54b9b 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -2017,9 +2017,26 @@ SetRemoteSubplan(CachedPlanSource *plansource, const char *plan_string)
/*
* Restore query plan.
+ *
+ * A try-catch block to ensure that we don't leave behind a stale state
+ * if nodeToString fails for whatever reason.
+ *
+ * XXX We should probably rewrite it someday by either passing a
+ * context to nodeToString() or remembering this information somewhere
+ * else which gets reset in case of errors. But for now, this seems
+ * enough.
*/
- set_portable_input(true);
- rstmt = (RemoteStmt *) stringToNode((char *) plan_string);
+ PG_TRY();
+ {
+ set_portable_input(true);
+ rstmt = (RemoteStmt *) stringToNode((char *) plan_string);
+ }
+ PG_CATCH();
+ {
+ set_portable_input(false);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
set_portable_input(false);
stmt = makeNode(PlannedStmt);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index c654213445..7a586f95cf 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1340,7 +1340,20 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
* Fetch rules and triggers that affect this relation
*/
if (relation->rd_rel->relhasrules)
+ {
+ /*
+ * We could be in the middle of reading a portable input string and get
+ * called to build the relation descriptor. This might require
+ * recursive calls to stringToNode (e.g. while reading rules) and those
+ * must not be done with portable input turned on (because the
+ * stringified versions are not created with portable output turned
+ * on). So temporarily reset portable input to false and restore once
+ * we are done with reading rules.
+ */
+ bool saved_portable_input = set_portable_input(false);
RelationBuildRuleLock(relation);
+ set_portable_input(saved_portable_input);
+ }
else
{
relation->rd_rules = NULL;
@@ -1358,7 +1371,12 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
RelationBuildLocator(relation);
#endif
if (relation->rd_rel->relrowsecurity)
+ {
+ /* See comments near RelationBuildRuleLocok for details */
+ bool saved_portable_input = set_portable_input(false);
RelationBuildRowSecurity(relation);
+ set_portable_input(saved_portable_input);
+ }
else
relation->rd_rsdesc = NULL;
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 47e55dbb5f..a620f29d0c 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -651,7 +651,7 @@ extern char *bmsToString(const struct Bitmapset *bms);
* nodes/{readfuncs.c,read.c}
*/
#ifdef XCP
-extern void set_portable_input(bool value);
+extern bool set_portable_input(bool value);
#endif
extern void *stringToNode(char *str);
extern struct Bitmapset *readBitmapset(void);