summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavan Deolasee2017-09-11 09:47:15 +0000
committerPavan Deolasee2017-09-11 10:30:15 +0000
commit2aea4fefba737f0fa70ab720e8ed17a2998ee6aa (patch)
tree261d26267aa380efe6e5ac2a7611557ab16b0c9e
parent9eedea1972422afc47d113b6e259477ea7f7ce8a (diff)
Further refactoring of utility.c code
Furthre more simplification and consolidation of the code.
-rw-r--r--src/backend/tcop/utility.c286
1 files changed, 151 insertions, 135 deletions
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 994c0e17f3..0749400ccf 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -90,8 +90,17 @@
#include "pgxc/pause.h"
#endif
-static void ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes, bool sentToRemote,
- bool force_autocommit, RemoteQueryExecType exec_type,
+static void ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes,
+ bool sentToRemote,
+ bool force_autocommit,
+ RemoteQueryExecType exec_type,
+ bool is_temp,
+ bool add_context);
+static void ExecUtilityStmtOnNodesInternal(const char *queryString,
+ ExecNodes *nodes,
+ bool sentToRemote,
+ bool force_autocommit,
+ RemoteQueryExecType exec_type,
bool is_temp);
static RemoteQueryExecType ExecUtilityFindNodes(ObjectType objectType,
Oid relid,
@@ -102,7 +111,6 @@ static RemoteQueryExecType GetNodesForRulesUtility(RangeVar *relation, bool *is_
static void DropStmtPreTreatment(DropStmt *stmt, const char *queryString, bool sentToRemote,
bool *is_temp, RemoteQueryExecType *exec_type);
static bool IsStmtAllowedInLockedMode(Node *parsetree, const char *queryString);
-static void ExecUtilityWithMessage(const char *queryString, bool sentToRemote, bool is_temp);
#endif
/* Hook for plugins to get control in ProcessUtility() */
@@ -411,6 +419,10 @@ ProcessUtility(PlannedStmt *pstmt,
completionTag);
}
+/*
+ * Do the necessary processing before executing the utility command locally on
+ * the coordinator.
+ */
static bool
ProcessUtilityPre(PlannedStmt *pstmt,
const char *queryString,
@@ -421,6 +433,18 @@ ProcessUtilityPre(PlannedStmt *pstmt,
{
Node *parsetree = pstmt->utilityStmt;
bool isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
+ bool all_done = false;
+ bool is_temp = false;
+ bool auto_commit = false;
+ bool add_context = false;
+ RemoteQueryExecType exec_type = EXEC_ON_NONE;
+
+ /*
+ * auto_commit and is_temp is initialised to false and changed if required.
+ *
+ * exec_type is initialised to EXEC_ON_NONE and updated iff the command
+ * needs remote execution during the preprocessing step.
+ */
switch (nodeTag(parsetree))
{
@@ -461,7 +485,7 @@ ProcessUtilityPre(PlannedStmt *pstmt,
if (IS_PGXC_LOCAL_COORDINATOR)
{
if (!FinishRemotePreparedTransaction(stmt->gid, true) && !xc_maintenance_mode)
- return false; /* No need to commit locally */
+ all_done = true; /* No need to commit locally */
}
break;
@@ -471,7 +495,7 @@ ProcessUtilityPre(PlannedStmt *pstmt,
if (IS_PGXC_LOCAL_COORDINATOR)
{
if (!FinishRemotePreparedTransaction(stmt->gid, false) && !xc_maintenance_mode)
- return false;
+ all_done = true;
}
break;
@@ -529,7 +553,8 @@ ProcessUtilityPre(PlannedStmt *pstmt,
/* Clean also remote Coordinators */
sprintf(query, "CLEAN CONNECTION TO ALL FOR DATABASE %s;",
quote_identifier(stmt->dbname));
- ExecUtilityStmtOnNodes(query, NULL, sentToRemote, true, EXEC_ON_ALL_NODES, false);
+ ExecUtilityStmtOnNodes(query, NULL, sentToRemote, true,
+ EXEC_ON_ALL_NODES, false, false);
}
break;
@@ -552,11 +577,9 @@ ProcessUtilityPre(PlannedStmt *pstmt,
* We have to run the command on nodes before Coordinator because
* vacuum() pops active snapshot and we can not send it to nodes
*/
- if (IS_PGXC_LOCAL_COORDINATOR &&
- !(stmt->options & VACOPT_COORDINATOR))
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote,
- true,
- EXEC_ON_DATANODES, false);
+ if (!(stmt->options & VACOPT_COORDINATOR))
+ exec_type = EXEC_ON_DATANODES;
+ auto_commit = true;
}
break;
@@ -605,23 +628,28 @@ ProcessUtilityPre(PlannedStmt *pstmt,
case T_AlterNodeStmt:
PgxcNodeAlter((AlterNodeStmt *) parsetree);
if (((AlterNodeStmt *) parsetree)->cluster)
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, false);
+ exec_type = EXEC_ON_ALL_NODES;
+ all_done = true;
break;
case T_CreateNodeStmt:
PgxcNodeCreate((CreateNodeStmt *) parsetree);
+ all_done = true;
break;
case T_DropNodeStmt:
PgxcNodeRemove((DropNodeStmt *) parsetree);
+ all_done = true;
break;
case T_CreateGroupStmt:
PgxcGroupCreate((CreateGroupStmt *) parsetree);
+ all_done = true;
break;
case T_DropGroupStmt:
PgxcGroupRemove((DropGroupStmt *) parsetree);
+ all_done = true;
break;
case T_ReindexStmt:
@@ -632,8 +660,6 @@ ProcessUtilityPre(PlannedStmt *pstmt,
case T_RenameStmt:
{
RenameStmt *stmt = (RenameStmt *) parsetree;
- RemoteQueryExecType exec_type;
- bool is_temp = false;
if (IS_PGXC_LOCAL_COORDINATOR)
{
@@ -663,12 +689,6 @@ ProcessUtilityPre(PlannedStmt *pstmt,
exec_type = ExecUtilityFindNodes(stmt->renameType,
InvalidOid,
&is_temp);
- ExecUtilityStmtOnNodes(queryString,
- NULL,
- sentToRemote,
- false,
- exec_type,
- is_temp);
}
}
break;
@@ -694,7 +714,8 @@ ProcessUtilityPre(PlannedStmt *pstmt,
* connections, then clean local pooler
*/
if (IS_PGXC_COORDINATOR)
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, true, EXEC_ON_ALL_NODES, false);
+ ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, true,
+ EXEC_ON_ALL_NODES, false, false);
CleanConnection((CleanConnStmt *) parsetree);
break;
@@ -771,12 +792,11 @@ ProcessUtilityPre(PlannedStmt *pstmt,
break;
case T_RefreshMatViewStmt:
- if ((IS_PGXC_COORDINATOR) && !IsConnFromCoord())
+ if (IS_PGXC_LOCAL_COORDINATOR)
{
RefreshMatViewStmt *stmt = (RefreshMatViewStmt *) parsetree;
if (stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
- ExecUtilityStmtOnNodes(queryString, NULL,
- sentToRemote, false, EXEC_ON_COORDS, false);
+ exec_type = EXEC_ON_COORDS;
}
break;
@@ -857,7 +877,15 @@ ProcessUtilityPre(PlannedStmt *pstmt,
break;
}
- return true;
+ /*
+ * Send queryString to remote nodes, if needed.
+ */
+ if (IS_PGXC_LOCAL_COORDINATOR)
+ ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, auto_commit,
+ exec_type, is_temp, add_context);
+
+
+ return all_done;
}
static void
@@ -868,6 +896,17 @@ ProcessUtilityPost(PlannedStmt *pstmt,
bool sentToRemote)
{
Node *parsetree = pstmt->utilityStmt;
+ bool is_temp = false;
+ bool auto_commit = false;
+ bool add_context = false;
+ RemoteQueryExecType exec_type = EXEC_ON_NONE;
+
+ /*
+ * auto_commit and is_temp is initialised to false and changed if required.
+ *
+ * exec_type is initialised to EXEC_ON_NONE and updated iff the command
+ * needs remote execution during the preprocessing step.
+ */
switch (nodeTag(parsetree))
{
@@ -931,8 +970,8 @@ ProcessUtilityPost(PlannedStmt *pstmt,
case T_CreateTableSpaceStmt:
case T_CreatedbStmt:
- if (IS_PGXC_LOCAL_COORDINATOR)
- ExecUtilityWithMessage(queryString, sentToRemote, false);
+ add_context = true;
+ exec_type = EXEC_ON_ALL_NODES;
break;
case T_DropTableSpaceStmt:
@@ -973,8 +1012,7 @@ ProcessUtilityPost(PlannedStmt *pstmt,
case T_CreatePolicyStmt: /* CREATE POLICY */
case T_AlterPolicyStmt: /* ALTER POLICY */
case T_CreateAmStmt:
- if (IS_PGXC_COORDINATOR)
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, false);
+ exec_type = EXEC_ON_ALL_NODES;
break;
case T_TruncateStmt:
@@ -985,7 +1023,6 @@ ProcessUtilityPost(PlannedStmt *pstmt,
*/
if (IS_PGXC_LOCAL_COORDINATOR)
{
- bool is_temp = false;
ListCell *cell;
TruncateStmt *stmt = (TruncateStmt *) parsetree;
@@ -1001,8 +1038,7 @@ ProcessUtilityPost(PlannedStmt *pstmt,
break;
}
}
-
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_DATANODES, is_temp);
+ exec_type = EXEC_ON_DATANODES;
}
break;
@@ -1013,23 +1049,21 @@ ProcessUtilityPost(PlannedStmt *pstmt,
* If this is not a SET TABLESPACE statement, just propogate the
* cmd as usual.
*/
- if (!IsSetTableSpace((AlterDatabaseStmt*) parsetree))
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, false);
- else
- ExecUtilityWithMessage(queryString, sentToRemote, false);
+ if (IsSetTableSpace((AlterDatabaseStmt*) parsetree))
+ add_context = true;
+ exec_type = EXEC_ON_ALL_NODES;
}
break;
case T_LoadStmt:
case T_ConstraintsSetStmt:
- if (IS_PGXC_LOCAL_COORDINATOR)
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_DATANODES, false);
+ exec_type = EXEC_ON_DATANODES;
break;
case T_ClusterStmt:
case T_CheckPointStmt:
- if (IS_PGXC_LOCAL_COORDINATOR)
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, true, EXEC_ON_DATANODES, false);
+ auto_commit = true;
+ exec_type = EXEC_ON_DATANODES;
break;
case T_DiscardStmt:
@@ -1038,16 +1072,14 @@ ProcessUtilityPost(PlannedStmt *pstmt,
* For example, temporary tables are created on all Datanodes
* and Coordinators.
*/
- if (IS_PGXC_COORDINATOR)
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, true, EXEC_ON_ALL_NODES, false);
+ auto_commit = true;
+ exec_type = EXEC_ON_ALL_NODES;
break;
case T_ReindexStmt:
{
ReindexStmt *stmt = (ReindexStmt *) parsetree;
Oid relid;
- RemoteQueryExecType exec_type;
- bool is_temp;
/* forbidden in parallel mode due to CommandIsReadOnly */
switch (stmt->kind)
@@ -1069,10 +1101,8 @@ ProcessUtilityPost(PlannedStmt *pstmt,
}
if (IS_PGXC_LOCAL_COORDINATOR)
{
- bool auto_commit = (stmt->kind == REINDEX_OBJECT_DATABASE ||
+ auto_commit = (stmt->kind == REINDEX_OBJECT_DATABASE ||
stmt->kind == REINDEX_OBJECT_SCHEMA);
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote,
- auto_commit, exec_type, false);
}
}
break;
@@ -1083,7 +1113,6 @@ ProcessUtilityPost(PlannedStmt *pstmt,
if (IS_PGXC_LOCAL_COORDINATOR)
{
RemoteQueryExecType remoteExecType = EXEC_ON_ALL_NODES;
- bool is_temp = false;
/* Launch GRANT on Coordinator if object is a sequence */
if ((stmt->objtype == ACL_OBJECT_RELATION &&
@@ -1125,7 +1154,7 @@ ProcessUtilityPost(PlannedStmt *pstmt,
}
}
}
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, remoteExecType, is_temp);
+ exec_type = remoteExecType;
}
}
break;
@@ -1134,8 +1163,6 @@ ProcessUtilityPost(PlannedStmt *pstmt,
if (IS_PGXC_LOCAL_COORDINATOR)
{
AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) parsetree;
- RemoteQueryExecType exec_type;
- bool is_temp = false;
/* Try to use the object relation if possible */
if (stmt->relation)
@@ -1161,13 +1188,6 @@ ProcessUtilityPost(PlannedStmt *pstmt,
InvalidOid,
&is_temp);
}
-
- ExecUtilityStmtOnNodes(queryString,
- NULL,
- sentToRemote,
- false,
- exec_type,
- is_temp);
}
break;
@@ -1175,10 +1195,8 @@ ProcessUtilityPost(PlannedStmt *pstmt,
/* Comment objects depending on their object and temporary types */
if (IS_PGXC_LOCAL_COORDINATOR)
{
- bool is_temp = false;
CommentStmt *stmt = (CommentStmt *) parsetree;
- RemoteQueryExecType exec_type = GetNodesForCommentUtility(stmt, &is_temp);
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, exec_type, is_temp);
+ exec_type = GetNodesForCommentUtility(stmt, &is_temp);
}
break;
@@ -1186,8 +1204,6 @@ ProcessUtilityPost(PlannedStmt *pstmt,
{
IndexStmt *stmt = (IndexStmt *) parsetree;
Oid relid;
- bool is_temp = false;
- RemoteQueryExecType exec_type = EXEC_ON_ALL_NODES;
/* INDEX on a temporary table cannot use 2PC at commit */
relid = RangeVarGetRelid(stmt->relation, NoLock, true);
@@ -1197,9 +1213,9 @@ ProcessUtilityPost(PlannedStmt *pstmt,
else
exec_type = EXEC_ON_NONE;
- if (IS_PGXC_COORDINATOR && !stmt->isconstraint && !IsConnFromCoord())
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote,
- stmt->concurrent, exec_type, is_temp);
+ auto_commit = stmt->concurrent;
+ if (stmt->isconstraint)
+ exec_type = EXEC_ON_NONE;
}
break;
@@ -1208,28 +1224,23 @@ ProcessUtilityPost(PlannedStmt *pstmt,
* In this case force autocommit, this transaction cannot be launched
* inside a transaction block.
*/
- if (IS_PGXC_LOCAL_COORDINATOR)
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false , EXEC_ON_ALL_NODES, false);
+ exec_type = EXEC_ON_ALL_NODES;
break;
case T_ViewStmt: /* CREATE VIEW */
if (IS_PGXC_LOCAL_COORDINATOR)
{
ViewStmt *stmt = (ViewStmt *) parsetree;
-
if (stmt->view->relpersistence != RELPERSISTENCE_TEMP)
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_COORDS, false);
+ exec_type = EXEC_ON_COORDS;
}
break;
case T_RuleStmt: /* CREATE RULE */
if (IS_PGXC_LOCAL_COORDINATOR)
{
- RemoteQueryExecType exec_type;
- bool is_temp;
exec_type = GetNodesForRulesUtility(((RuleStmt *) parsetree)->relation,
&is_temp);
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, exec_type, is_temp);
}
break;
@@ -1240,10 +1251,8 @@ ProcessUtilityPost(PlannedStmt *pstmt,
/* In case this query is related to a SERIAL execution, just bypass */
if (!stmt->is_serial)
- {
- bool is_temp = stmt->sequence->relpersistence == RELPERSISTENCE_TEMP;
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, is_temp);
- }
+ is_temp = stmt->sequence->relpersistence == RELPERSISTENCE_TEMP;
+ exec_type = EXEC_ON_ALL_NODES;
}
break;
@@ -1255,8 +1264,6 @@ ProcessUtilityPost(PlannedStmt *pstmt,
/* In case this query is related to a SERIAL execution, just bypass */
if (!stmt->is_serial)
{
- bool is_temp;
- RemoteQueryExecType exec_type;
Oid relid = RangeVarGetRelid(stmt->sequence, NoLock, true);
if (!OidIsValid(relid))
@@ -1266,13 +1273,12 @@ ProcessUtilityPost(PlannedStmt *pstmt,
relid,
&is_temp);
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, exec_type, is_temp);
}
}
break;
case T_CreateTableAsStmt:
- if ((IS_PGXC_COORDINATOR) && !IsConnFromCoord())
+ if (IS_PGXC_LOCAL_COORDINATOR)
{
CreateTableAsStmt *stmt = (CreateTableAsStmt *) parsetree;
@@ -1282,15 +1288,13 @@ ProcessUtilityPost(PlannedStmt *pstmt,
*/
Assert(stmt->relkind == OBJECT_MATVIEW);
if (stmt->into->rel->relpersistence != RELPERSISTENCE_TEMP)
- ExecUtilityStmtOnNodes(queryString, NULL,
- sentToRemote, false, EXEC_ON_COORDS, false);
+ exec_type = EXEC_ON_COORDS;
}
break;
case T_CreateStatsStmt:
if (IS_PGXC_LOCAL_COORDINATOR)
{
- bool is_temp;
CreateStatsStmt *stmt = (CreateStatsStmt *) parsetree;
RangeVar *rln = linitial(stmt->relations);
Relation rel = relation_openrv((RangeVar *) rln, ShareUpdateExclusiveLock);
@@ -1302,11 +1306,9 @@ ProcessUtilityPost(PlannedStmt *pstmt,
* fetch the nodes. This is ok because the command must
* only be even used on some kind of relation.
*/
- RemoteQueryExecType exec_type =
+ exec_type =
ExecUtilityFindNodesRelkind(RelationGetRelid(rel), &is_temp);
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote,
- false, exec_type, false);
relation_close(rel, NoLock);
}
break;
@@ -1316,6 +1318,10 @@ ProcessUtilityPost(PlannedStmt *pstmt,
(int) nodeTag(parsetree));
break;
}
+
+ if (IS_PGXC_LOCAL_COORDINATOR)
+ ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, auto_commit,
+ exec_type, is_temp, add_context);
}
/*
* standard_ProcessUtility itself deals only with utility commands for
@@ -1378,7 +1384,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (completionTag)
completionTag[0] = '\0';
- if (!ProcessUtilityPre(pstmt, queryString, context, queryEnv, sentToRemote,
+ if (ProcessUtilityPre(pstmt, queryString, context, queryEnv, sentToRemote,
completionTag))
return;
@@ -2840,7 +2846,7 @@ ExecDropStmt(DropStmt *stmt, bool isTopLevel)
/* DROP is done depending on the object type and its temporary type */
if (IS_PGXC_LOCAL_COORDINATOR)
ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false,
- exec_type, is_temp);
+ exec_type, is_temp, false);
}
#endif
break;
@@ -2858,7 +2864,7 @@ ExecDropStmt(DropStmt *stmt, bool isTopLevel)
#ifdef PGXC
if (IS_PGXC_LOCAL_COORDINATOR)
ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false,
- exec_type, is_temp);
+ exec_type, is_temp, false);
}
#endif
break;
@@ -4583,51 +4589,8 @@ GetCommandLogLevel(Node *parsetree)
}
#ifdef PGXC
-
-/*
- * ExecUtilityWithMessage:
- * Execute the query on remote nodes in a transaction block.
- * If this fails on one of the nodes :
- * Add a context message containing the failed node names.
- * Rethrow the error with the message about the failed nodes.
- * If all are successful, just return.
- */
- static void
-ExecUtilityWithMessage(const char *queryString, bool sentToRemote, bool is_temp)
-{
- PG_TRY();
- {
- ExecUtilityStmtOnNodes(queryString, NULL, sentToRemote, false, EXEC_ON_ALL_NODES, is_temp);
- }
- PG_CATCH();
- {
-
- /*
- * Some nodes failed. Add context about what all nodes the query
- * failed
- */
- ExecNodes *coord_success_nodes = NULL;
- ExecNodes *data_success_nodes = NULL;
- char *msg_failed_nodes;
-
- pgxc_all_success_nodes(&data_success_nodes, &coord_success_nodes, &msg_failed_nodes);
- if (msg_failed_nodes)
- errcontext("%s", msg_failed_nodes);
- PG_RE_THROW();
- }
- PG_END_TRY();
-
-
-}
-
-/*
- * Execute a Utility statement on nodes, including Coordinators
- * If the DDL is received from a remote Coordinator,
- * it is not possible to push down DDL to Datanodes
- * as it is taken in charge by the remote Coordinator.
- */
- static void
-ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes, bool sentToRemote,
+static void
+ExecUtilityStmtOnNodesInternal(const char *queryString, ExecNodes *nodes, bool sentToRemote,
bool force_autocommit, RemoteQueryExecType exec_type, bool is_temp)
{
/* Return if query is launched on no nodes */
@@ -4660,6 +4623,59 @@ ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes, bool sentToRem
}
}
+
+/*
+ * ExecUtilityStmtOnNodes
+ *
+ * Execute the query on remote nodes
+ *
+ * queryString is the raw query to be executed.
+ * If nodes is NULL then the list of nodes is computed from exec_type.
+ * If auto_commit is true, then the query is executed without a transaction
+ * block and auto-committed on the remote node.
+ * exec_type is used to compute the list of remote nodes on which the query is
+ * executed.
+ * is_temp is set to true if the query involves a temporary database object.
+ * If add_context is true and if this fails on one of the nodes then add a
+ * context message containing the failed node names.
+ */
+static void
+ExecUtilityStmtOnNodes(const char *queryString, ExecNodes *nodes,
+ bool sentToRemote, bool auto_commit, RemoteQueryExecType exec_type,
+ bool is_temp, bool add_context)
+{
+ PG_TRY();
+ {
+ ExecUtilityStmtOnNodesInternal(queryString, nodes, sentToRemote,
+ auto_commit, exec_type, is_temp);
+ }
+ PG_CATCH();
+ {
+ /*
+ * Some nodes failed. Add context about what all nodes the query
+ * failed
+ */
+ ExecNodes *coord_success_nodes = NULL;
+ ExecNodes *data_success_nodes = NULL;
+ char *msg_failed_nodes;
+
+ /*
+ * If the caller has asked for context information, add that and
+ * re-throw the error.
+ */
+ if (!add_context)
+ PG_RE_THROW();
+
+ pgxc_all_success_nodes(&data_success_nodes, &coord_success_nodes, &msg_failed_nodes);
+ if (msg_failed_nodes)
+ errcontext("%s", msg_failed_nodes);
+ PG_RE_THROW();
+ }
+ PG_END_TRY();
+
+
+}
+
/*
* ExecUtilityFindNodes
*