@@ -4808,12 +4808,60 @@ void MtmUpdateLockGraph(int nodeId, void const* messageBody, int messageSize)
48084808 MTM_LOG1 ("Update deadlock graph for node %d size %d" , nodeId , messageSize );
48094809}
48104810
4811+ static bool MtmIsTempType (TypeName * typeName )
4812+ {
4813+ bool isTemp = false;
4814+
4815+ if (typeName != NULL )
4816+ {
4817+ Type typeTuple = LookupTypeName (NULL , typeName , NULL , false);
4818+ if (typeTuple != NULL )
4819+ {
4820+ Form_pg_type typeStruct = (Form_pg_type ) GETSTRUCT (typeTuple );
4821+ Oid relid = typeStruct -> typrelid ;
4822+ ReleaseSysCache (typeTuple );
4823+
4824+ if (relid != InvalidOid )
4825+ {
4826+ HeapTuple classTuple = SearchSysCache1 (RELOID , relid );
4827+ Form_pg_class classStruct = (Form_pg_class ) GETSTRUCT (classTuple );
4828+ if (classStruct -> relpersistence == 't' )
4829+ isTemp = true;
4830+ ReleaseSysCache (classTuple );
4831+ }
4832+ }
4833+ }
4834+ return isTemp ;
4835+ }
4836+
4837+ static bool MtmFunctionProfileDependsOnTempTable (CreateFunctionStmt * func )
4838+ {
4839+ ListCell * elem ;
4840+
4841+ if (MtmIsTempType (func -> returnType ))
4842+ {
4843+ return true;
4844+ }
4845+ foreach (elem , func -> parameters )
4846+ {
4847+ FunctionParameter * param = (FunctionParameter * ) lfirst (elem );
4848+ if (MtmIsTempType (param -> argType ))
4849+ {
4850+ return true;
4851+ }
4852+ }
4853+ return false;
4854+ }
4855+
4856+
4857+
48114858static void MtmProcessUtility (Node * parsetree , const char * queryString ,
48124859 ProcessUtilityContext context , ParamListInfo params ,
48134860 DestReceiver * dest , char * completionTag )
48144861{
48154862 bool skipCommand = false;
48164863 bool executed = false;
4864+ bool prevMyXactAccessedTempRel ;
48174865
48184866 MTM_LOG2 ("%d: Process utility statement tag=%d, context=%d, issubtrans=%d, creating_extension=%d, query=%s" ,
48194867 MyProcPid , nodeTag (parsetree ), context , IsSubTransaction (), creating_extension , queryString );
@@ -4895,19 +4943,24 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
48954943 break ;
48964944
48974945 case T_VacuumStmt :
4898- skipCommand = true;
4899- if (context == PROCESS_UTILITY_TOPLEVEL ) {
4900- MtmProcessDDLCommand (queryString , false);
4901- MtmTx .isDistributed = false;
4902- } else if (MtmApplyContext != NULL ) {
4903- MemoryContext oldContext = MemoryContextSwitchTo (MtmApplyContext );
4904- Assert (oldContext != MtmApplyContext );
4905- MtmVacuumStmt = (VacuumStmt * )copyObject (parsetree );
4906- MemoryContextSwitchTo (oldContext );
4907- return ;
4908- }
4909- break ;
4910-
4946+ {
4947+ VacuumStmt * vacuum = (VacuumStmt * )parsetree ;
4948+ skipCommand = true;
4949+ if ((vacuum -> options & VACOPT_LOCAL ) == 0 && !MtmVolksWagenMode )
4950+ {
4951+ if (context == PROCESS_UTILITY_TOPLEVEL ) {
4952+ MtmProcessDDLCommand (queryString , false);
4953+ MtmTx .isDistributed = false;
4954+ } else if (MtmApplyContext != NULL ) {
4955+ MemoryContext oldContext = MemoryContextSwitchTo (MtmApplyContext );
4956+ Assert (oldContext != MtmApplyContext );
4957+ MtmVacuumStmt = (VacuumStmt * )copyObject (parsetree );
4958+ MemoryContextSwitchTo (oldContext );
4959+ return ;
4960+ }
4961+ }
4962+ break ;
4963+ }
49114964 case T_CreateDomainStmt :
49124965 /* Detect temp tables access */
49134966 {
@@ -5072,6 +5125,14 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
50725125 }
50735126 }
50745127 }
5128+ case T_CreateFunctionStmt :
5129+ {
5130+ if (MtmTx .isReplicated )
5131+ {
5132+ // disable functiob body cehck at replica
5133+ check_function_bodies = false;
5134+ }
5135+ }
50755136 break ;
50765137 }
50775138
@@ -5089,6 +5150,8 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
50895150 }
50905151 else MTM_LOG3 ("Skip utility statement '%s': skip=%d, insideDDL=%d" , queryString , skipCommand , MtmDDLStatement != NULL );
50915152
5153+ prevMyXactAccessedTempRel = MyXactAccessedTempRel ;
5154+
50925155 if (PreviousProcessUtilityHook != NULL )
50935156 {
50945157 PreviousProcessUtilityHook (parsetree , queryString , context ,
@@ -5104,6 +5167,19 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
51045167 MTM_ELOG (ERROR , "Isolation level %s is not supported by multimaster" , isoLevelStr [XactIsoLevel ]);
51055168 }
51065169#endif
5170+ /* Allow replication of functions operating on temporary tables.
5171+ * Even through temporary table doesn't exist at replica, diasabling functoin body check makes it possible to create such function at replica.
5172+ * And it can be accessed later at replica if correspondent temporary table will be created.
5173+ * But disable replication of functions returning temporary tables: such functions can not be created at replica in any case.
5174+ */
5175+ if (IsA (parsetree , CreateFunctionStmt ))
5176+ {
5177+ if (MtmFunctionProfileDependsOnTempTable ((CreateFunctionStmt * )parsetree ))
5178+ {
5179+ prevMyXactAccessedTempRel = true;
5180+ }
5181+ MyXactAccessedTempRel = prevMyXactAccessedTempRel ;
5182+ }
51075183 if (MyXactAccessedTempRel )
51085184 {
51095185 MTM_LOG1 ("Xact accessed temp table, stopping replication of statement '%s'" , queryString );
0 commit comments