2424#include "tcop/pquery.h"
2525#include "utils/snapmgr.h"
2626#include "nodes/makefuncs.h"
27+ #include "nodes/nodeFuncs.h"
2728#include "catalog/pg_constraint.h"
2829#include "catalog/pg_namespace.h"
2930#include "executor/spi.h"
@@ -848,16 +849,14 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString,
848849
849850 case T_CreateTableSpaceStmt :
850851 case T_DropTableSpaceStmt :
851- {
852852 skipCommand = true;
853853 MtmProcessDDLCommand (stmt_string , false);
854854 break ;
855- }
856855
857856 /*
858857 * Explain will not call ProcessUtility for passed CreateTableAsStmt,
859- * but will run it manually, so we will not catch it in a standart way.
860- * So catch it in a non-standart way.
858+ * but will run it manually, so we will not catch it in a standard way.
859+ * So catch it in a non-standard way.
861860 */
862861 case T_ExplainStmt :
863862 {
@@ -948,7 +947,8 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString,
948947 DropStmt * stmt = (DropStmt * ) parsetree ;
949948 if (stmt -> removeType == OBJECT_INDEX && stmt -> concurrent )
950949 {
951- if (context == PROCESS_UTILITY_TOPLEVEL ) {
950+ if (context == PROCESS_UTILITY_TOPLEVEL )
951+ {
952952 MtmProcessDDLCommand (stmt_string , false);
953953 skipCommand = true;
954954 }
@@ -971,9 +971,9 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString,
971971 if (OidIsValid (relid ))
972972 {
973973 Relation rel = heap_open (relid , ShareLock );
974- if (RelationNeedsWAL (rel )) {
974+ if (RelationNeedsWAL (rel ))
975975 MtmTx .contains_dml = true;
976- }
976+
977977 heap_close (rel , ShareLock );
978978 }
979979 }
@@ -1032,37 +1032,70 @@ MtmProcessUtilitySender(PlannedStmt *pstmt, const char *queryString,
10321032 }
10331033}
10341034
1035+ static bool
1036+ targetList_walker (Node * node , void * context )
1037+ {
1038+ if (node == NULL )
1039+ return false;
1040+
1041+ if (IsA (node , FuncExpr ))
1042+ {
1043+ Oid func_oid = ((FuncExpr * ) node )-> funcid ;
1044+
1045+ if (hash_search (MtmRemoteFunctions , & func_oid , HASH_FIND , NULL ))
1046+ return true;
1047+ }
1048+
1049+ return expression_tree_walker (node , targetList_walker , context );
1050+ }
1051+
1052+ static bool
1053+ search_for_remote_functions (PlanState * node , void * context )
1054+ {
1055+ if (node == NULL )
1056+ return false;
1057+
1058+ if (targetList_walker ((Node * ) node -> plan -> targetlist , NULL ))
1059+ return true;
1060+
1061+ return planstate_tree_walker (node , search_for_remote_functions , NULL );
1062+ }
1063+
10351064static void
10361065MtmExecutorStart (QueryDesc * queryDesc , int eflags )
10371066{
1067+ if (PreviousExecutorStartHook != NULL )
1068+ PreviousExecutorStartHook (queryDesc , eflags );
1069+ else
1070+ standard_ExecutorStart (queryDesc , eflags );
1071+
1072+ /*
1073+ * Explain can contain remote functions. But we don't need to send it to
1074+ * another nodes of multimaster.
1075+ */
1076+ if (eflags & EXEC_FLAG_EXPLAIN_ONLY )
1077+ return ;
1078+
10381079 if (!MtmIsLogicalReceiver && !MtmDDLStatement && MtmIsEnabled ())
10391080 {
1040- ListCell * tlist ;
1041-
10421081 if (!MtmRemoteFunctionsValid )
10431082 MtmInitializeRemoteFunctionsMap ();
10441083
1045- foreach (tlist , queryDesc -> plannedstmt -> planTree -> targetlist )
1046- {
1047- TargetEntry * tle = (TargetEntry * ) lfirst (tlist );
1048- if (tle -> expr && IsA (tle -> expr , FuncExpr ))
1049- {
1050- Oid func_oid = ((FuncExpr * ) tle -> expr )-> funcid ;
1084+ Assert (queryDesc -> planstate );
10511085
1052- if (hash_search (MtmRemoteFunctions , & func_oid , HASH_FIND , NULL ))
1053- {
1054- MtmProcessDDLCommand (queryDesc -> sourceText , true);
1055- MtmDDLStatement = queryDesc ;
1056- MtmTx .contains_ddl = true;
1057- break ;
1058- }
1059- }
1086+ /*
1087+ * If any node contains function from the remote functions list in its
1088+ * target list than we will send all query as a DDL command.
1089+ */
1090+ if (search_for_remote_functions (queryDesc -> planstate , NULL ))
1091+ {
1092+ MtmProcessDDLCommand (queryDesc -> sourceText , true);
1093+ MtmDDLStatement = queryDesc ;
1094+ MtmTx .contains_ddl = true;
10601095 }
1096+ else
1097+ mtm_log (DDLProcessingTrace , "The query plan don't contain any remote functions" );
10611098 }
1062- if (PreviousExecutorStartHook != NULL )
1063- PreviousExecutorStartHook (queryDesc , eflags );
1064- else
1065- standard_ExecutorStart (queryDesc , eflags );
10661099}
10671100
10681101static void
@@ -1082,14 +1115,19 @@ MtmExecutorFinish(QueryDesc *queryDesc)
10821115 operation == CMD_DELETE || pstmt -> hasModifyingCTE )
10831116 {
10841117 int i ;
1085- for (i = 0 ; i < estate -> es_num_result_relations ; i ++ ) {
1118+
1119+ for (i = 0 ; i < estate -> es_num_result_relations ; i ++ )
1120+ {
10861121 Relation rel = estate -> es_result_relations [i ].ri_RelationDesc ;
1087- if (RelationNeedsWAL (rel )) {
1088- if (MtmIgnoreTablesWithoutPk ) {
1089- if (!rel -> rd_indexvalid ) {
1122+ if (RelationNeedsWAL (rel ))
1123+ {
1124+ if (MtmIgnoreTablesWithoutPk )
1125+ {
1126+ if (!rel -> rd_indexvalid )
10901127 RelationGetIndexList (rel );
1091- }
1092- if (rel -> rd_replidindex == InvalidOid ) {
1128+
1129+ if (rel -> rd_replidindex == InvalidOid )
1130+ {
10931131 // XXX
10941132 MtmMakeRelationLocal (RelationGetRelid (rel ), false);
10951133 continue ;
@@ -1417,14 +1455,12 @@ MtmInitializeRemoteFunctionsMap()
14171455 p = pstrdup (MtmRemoteFunctionsList );
14181456 do {
14191457 q = strchr (p , ',' );
1420- if (q != NULL ) {
1458+ if (q != NULL )
14211459 * q ++ = '\0' ;
1422- }
1460+
14231461 clist = FuncnameGetCandidates (stringToQualifiedNameList (p ), -1 , NIL , false, false, true);
14241462 if (clist == NULL )
1425- {
14261463 mtm_log (DEBUG1 , "Can't resolve function '%s', postponing that" , p );
1427- }
14281464 else
14291465 {
14301466 while (clist != NULL )
@@ -1438,9 +1474,8 @@ MtmInitializeRemoteFunctionsMap()
14381474 } while (p != NULL );
14391475
14401476 clist = FuncnameGetCandidates (stringToQualifiedNameList ("mtm.alter_sequences" ), -1 , NIL , false, false, true);
1441- if (clist != NULL ) {
1477+ if (clist != NULL )
14421478 hash_search (MtmRemoteFunctions , & clist -> oid , HASH_ENTER , NULL );
1443- }
14441479
14451480 /* restore back current user context */
14461481 SetUserIdAndSecContext (save_userid , save_sec_context );
0 commit comments