@@ -5139,12 +5139,60 @@ void MtmUpdateLockGraph(int nodeId, void const* messageBody, int messageSize)
5139
5139
MTM_LOG1 ("Update deadlock graph for node %d size %d" , nodeId , messageSize );
5140
5140
}
5141
5141
5142
+ static bool MtmIsTempType (TypeName * typeName )
5143
+ {
5144
+ bool isTemp = false;
5145
+
5146
+ if (typeName != NULL )
5147
+ {
5148
+ Type typeTuple = LookupTypeName (NULL , typeName , NULL , false);
5149
+ if (typeTuple != NULL )
5150
+ {
5151
+ Form_pg_type typeStruct = (Form_pg_type ) GETSTRUCT (typeTuple );
5152
+ Oid relid = typeStruct -> typrelid ;
5153
+ ReleaseSysCache (typeTuple );
5154
+
5155
+ if (relid != InvalidOid )
5156
+ {
5157
+ HeapTuple classTuple = SearchSysCache1 (RELOID , relid );
5158
+ Form_pg_class classStruct = (Form_pg_class ) GETSTRUCT (classTuple );
5159
+ if (classStruct -> relpersistence == 't' )
5160
+ isTemp = true;
5161
+ ReleaseSysCache (classTuple );
5162
+ }
5163
+ }
5164
+ }
5165
+ return isTemp ;
5166
+ }
5167
+
5168
+ static bool MtmFunctionProfileDependsOnTempTable (CreateFunctionStmt * func )
5169
+ {
5170
+ ListCell * elem ;
5171
+
5172
+ if (MtmIsTempType (func -> returnType ))
5173
+ {
5174
+ return true;
5175
+ }
5176
+ foreach (elem , func -> parameters )
5177
+ {
5178
+ FunctionParameter * param = (FunctionParameter * ) lfirst (elem );
5179
+ if (MtmIsTempType (param -> argType ))
5180
+ {
5181
+ return true;
5182
+ }
5183
+ }
5184
+ return false;
5185
+ }
5186
+
5187
+
5188
+
5142
5189
static void MtmProcessUtility (Node * parsetree , const char * queryString ,
5143
5190
ProcessUtilityContext context , ParamListInfo params ,
5144
5191
DestReceiver * dest , char * completionTag )
5145
5192
{
5146
5193
bool skipCommand = false;
5147
5194
bool executed = false;
5195
+ bool prevMyXactAccessedTempRel ;
5148
5196
5149
5197
MTM_LOG2 ("%d: Process utility statement tag=%d, context=%d, issubtrans=%d, creating_extension=%d, query=%s" ,
5150
5198
MyProcPid , nodeTag (parsetree ), context , IsSubTransaction (), creating_extension , queryString );
@@ -5226,19 +5274,24 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
5226
5274
break ;
5227
5275
5228
5276
case T_VacuumStmt :
5229
- skipCommand = true;
5230
- if (context == PROCESS_UTILITY_TOPLEVEL ) {
5231
- MtmProcessDDLCommand (queryString , false);
5232
- MtmTx .isDistributed = false;
5233
- } else if (MtmApplyContext != NULL ) {
5234
- MemoryContext oldContext = MemoryContextSwitchTo (MtmApplyContext );
5235
- Assert (oldContext != MtmApplyContext );
5236
- MtmVacuumStmt = (VacuumStmt * )copyObject (parsetree );
5237
- MemoryContextSwitchTo (oldContext );
5238
- return ;
5239
- }
5240
- break ;
5241
-
5277
+ {
5278
+ VacuumStmt * vacuum = (VacuumStmt * )parsetree ;
5279
+ skipCommand = true;
5280
+ if ((vacuum -> options & VACOPT_LOCAL ) == 0 && !MtmVolksWagenMode )
5281
+ {
5282
+ if (context == PROCESS_UTILITY_TOPLEVEL ) {
5283
+ MtmProcessDDLCommand (queryString , false);
5284
+ MtmTx .isDistributed = false;
5285
+ } else if (MtmApplyContext != NULL ) {
5286
+ MemoryContext oldContext = MemoryContextSwitchTo (MtmApplyContext );
5287
+ Assert (oldContext != MtmApplyContext );
5288
+ MtmVacuumStmt = (VacuumStmt * )copyObject (parsetree );
5289
+ MemoryContextSwitchTo (oldContext );
5290
+ return ;
5291
+ }
5292
+ }
5293
+ break ;
5294
+ }
5242
5295
case T_CreateDomainStmt :
5243
5296
/* Detect temp tables access */
5244
5297
{
@@ -5403,6 +5456,14 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
5403
5456
}
5404
5457
}
5405
5458
}
5459
+ case T_CreateFunctionStmt :
5460
+ {
5461
+ if (MtmTx .isReplicated )
5462
+ {
5463
+ // disable functiob body cehck at replica
5464
+ check_function_bodies = false;
5465
+ }
5466
+ }
5406
5467
break ;
5407
5468
}
5408
5469
@@ -5420,6 +5481,8 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
5420
5481
}
5421
5482
else MTM_LOG3 ("Skip utility statement '%s': skip=%d, insideDDL=%d" , queryString , skipCommand , MtmDDLStatement != NULL );
5422
5483
5484
+ prevMyXactAccessedTempRel = MyXactAccessedTempRel ;
5485
+
5423
5486
if (PreviousProcessUtilityHook != NULL )
5424
5487
{
5425
5488
PreviousProcessUtilityHook (parsetree , queryString , context ,
@@ -5435,6 +5498,19 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
5435
5498
MTM_ELOG (ERROR , "Isolation level %s is not supported by multimaster" , isoLevelStr [XactIsoLevel ]);
5436
5499
}
5437
5500
#endif
5501
+ /* Allow replication of functions operating on temporary tables.
5502
+ * Even through temporary table doesn't exist at replica, diasabling functoin body check makes it possible to create such function at replica.
5503
+ * And it can be accessed later at replica if correspondent temporary table will be created.
5504
+ * But disable replication of functions returning temporary tables: such functions can not be created at replica in any case.
5505
+ */
5506
+ if (IsA (parsetree , CreateFunctionStmt ))
5507
+ {
5508
+ if (MtmFunctionProfileDependsOnTempTable ((CreateFunctionStmt * )parsetree ))
5509
+ {
5510
+ prevMyXactAccessedTempRel = true;
5511
+ }
5512
+ MyXactAccessedTempRel = prevMyXactAccessedTempRel ;
5513
+ }
5438
5514
if (MyXactAccessedTempRel )
5439
5515
{
5440
5516
MTM_LOG1 ("Xact accessed temp table, stopping replication of statement '%s'" , queryString );
0 commit comments