@@ -4808,12 +4808,60 @@ void MtmUpdateLockGraph(int nodeId, void const* messageBody, int messageSize)
4808
4808
MTM_LOG1 ("Update deadlock graph for node %d size %d" , nodeId , messageSize );
4809
4809
}
4810
4810
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
+
4811
4858
static void MtmProcessUtility (Node * parsetree , const char * queryString ,
4812
4859
ProcessUtilityContext context , ParamListInfo params ,
4813
4860
DestReceiver * dest , char * completionTag )
4814
4861
{
4815
4862
bool skipCommand = false;
4816
4863
bool executed = false;
4864
+ bool prevMyXactAccessedTempRel ;
4817
4865
4818
4866
MTM_LOG2 ("%d: Process utility statement tag=%d, context=%d, issubtrans=%d, creating_extension=%d, query=%s" ,
4819
4867
MyProcPid , nodeTag (parsetree ), context , IsSubTransaction (), creating_extension , queryString );
@@ -4895,19 +4943,24 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
4895
4943
break ;
4896
4944
4897
4945
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
+ }
4911
4964
case T_CreateDomainStmt :
4912
4965
/* Detect temp tables access */
4913
4966
{
@@ -5072,6 +5125,14 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
5072
5125
}
5073
5126
}
5074
5127
}
5128
+ case T_CreateFunctionStmt :
5129
+ {
5130
+ if (MtmTx .isReplicated )
5131
+ {
5132
+ // disable functiob body cehck at replica
5133
+ check_function_bodies = false;
5134
+ }
5135
+ }
5075
5136
break ;
5076
5137
}
5077
5138
@@ -5089,6 +5150,8 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
5089
5150
}
5090
5151
else MTM_LOG3 ("Skip utility statement '%s': skip=%d, insideDDL=%d" , queryString , skipCommand , MtmDDLStatement != NULL );
5091
5152
5153
+ prevMyXactAccessedTempRel = MyXactAccessedTempRel ;
5154
+
5092
5155
if (PreviousProcessUtilityHook != NULL )
5093
5156
{
5094
5157
PreviousProcessUtilityHook (parsetree , queryString , context ,
@@ -5104,6 +5167,19 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
5104
5167
MTM_ELOG (ERROR , "Isolation level %s is not supported by multimaster" , isoLevelStr [XactIsoLevel ]);
5105
5168
}
5106
5169
#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
+ }
5107
5183
if (MyXactAccessedTempRel )
5108
5184
{
5109
5185
MTM_LOG1 ("Xact accessed temp table, stopping replication of statement '%s'" , queryString );
0 commit comments