Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 864f35b

Browse files
committed
Support VACCUM ONLY LOCAL and rewrite replicate of functions accessing temporary tables
1 parent b4a0f07 commit 864f35b

File tree

3 files changed

+107
-20
lines changed

3 files changed

+107
-20
lines changed

contrib/mmts/multimaster.c

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5139,12 +5139,60 @@ void MtmUpdateLockGraph(int nodeId, void const* messageBody, int messageSize)
51395139
MTM_LOG1("Update deadlock graph for node %d size %d", nodeId, messageSize);
51405140
}
51415141

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+
51425189
static void MtmProcessUtility(Node *parsetree, const char *queryString,
51435190
ProcessUtilityContext context, ParamListInfo params,
51445191
DestReceiver *dest, char *completionTag)
51455192
{
51465193
bool skipCommand = false;
51475194
bool executed = false;
5195+
bool prevMyXactAccessedTempRel;
51485196

51495197
MTM_LOG2("%d: Process utility statement tag=%d, context=%d, issubtrans=%d, creating_extension=%d, query=%s",
51505198
MyProcPid, nodeTag(parsetree), context, IsSubTransaction(), creating_extension, queryString);
@@ -5226,19 +5274,24 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
52265274
break;
52275275

52285276
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+
}
52425295
case T_CreateDomainStmt:
52435296
/* Detect temp tables access */
52445297
{
@@ -5403,6 +5456,14 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
54035456
}
54045457
}
54055458
}
5459+
case T_CreateFunctionStmt:
5460+
{
5461+
if (MtmTx.isReplicated)
5462+
{
5463+
// disable functiob body cehck at replica
5464+
check_function_bodies = false;
5465+
}
5466+
}
54065467
break;
54075468
}
54085469

@@ -5420,6 +5481,8 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
54205481
}
54215482
else MTM_LOG3("Skip utility statement '%s': skip=%d, insideDDL=%d", queryString, skipCommand, MtmDDLStatement != NULL);
54225483

5484+
prevMyXactAccessedTempRel = MyXactAccessedTempRel;
5485+
54235486
if (PreviousProcessUtilityHook != NULL)
54245487
{
54255488
PreviousProcessUtilityHook(parsetree, queryString, context,
@@ -5435,6 +5498,19 @@ static void MtmProcessUtility(Node *parsetree, const char *queryString,
54355498
MTM_ELOG(ERROR, "Isolation level %s is not supported by multimaster", isoLevelStr[XactIsoLevel]);
54365499
}
54375500
#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+
}
54385514
if (MyXactAccessedTempRel)
54395515
{
54405516
MTM_LOG1("Xact accessed temp table, stopping replication of statement '%s'", queryString);

src/backend/parser/gram.y

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
413413

414414
%type <boolean> opt_autonomous
415415
%type <boolean> opt_instead
416-
%type <boolean> opt_unique opt_concurrently opt_verbose opt_full
416+
%type <boolean> opt_unique opt_concurrently opt_verbose opt_full opt_local
417417
%type <boolean> opt_freeze opt_default opt_recheck
418418
%type <defelt> opt_binary opt_oids copy_delimiter
419419

@@ -9650,7 +9650,7 @@ cluster_index_specification:
96509650
*
96519651
*****************************************************************************/
96529652

9653-
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
9653+
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose opt_local
96549654
{
96559655
VacuumStmt *n = makeNode(VacuumStmt);
96569656
n->options = VACOPT_VACUUM;
@@ -9660,11 +9660,13 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
96609660
n->options |= VACOPT_FREEZE;
96619661
if ($4)
96629662
n->options |= VACOPT_VERBOSE;
9663+
if ($5)
9664+
n->options |= VACOPT_LOCAL;
96639665
n->relation = NULL;
96649666
n->va_cols = NIL;
96659667
$$ = (Node *)n;
96669668
}
9667-
| VACUUM opt_full opt_freeze opt_verbose qualified_name
9669+
| VACUUM opt_full opt_freeze opt_verbose opt_local qualified_name
96689670
{
96699671
VacuumStmt *n = makeNode(VacuumStmt);
96709672
n->options = VACOPT_VACUUM;
@@ -9674,20 +9676,24 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
96749676
n->options |= VACOPT_FREEZE;
96759677
if ($4)
96769678
n->options |= VACOPT_VERBOSE;
9677-
n->relation = $5;
9679+
if ($5)
9680+
n->options |= VACOPT_LOCAL;
9681+
n->relation = $6;
96789682
n->va_cols = NIL;
96799683
$$ = (Node *)n;
96809684
}
9681-
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
9685+
| VACUUM opt_full opt_freeze opt_verbose opt_local AnalyzeStmt
96829686
{
9683-
VacuumStmt *n = (VacuumStmt *) $5;
9687+
VacuumStmt *n = (VacuumStmt *) $6;
96849688
n->options |= VACOPT_VACUUM;
96859689
if ($2)
96869690
n->options |= VACOPT_FULL;
96879691
if ($3)
96889692
n->options |= VACOPT_FREEZE;
96899693
if ($4)
96909694
n->options |= VACOPT_VERBOSE;
9695+
if ($5)
9696+
n->options |= VACOPT_LOCAL;
96919697
$$ = (Node *)n;
96929698
}
96939699
| VACUUM '(' vacuum_option_list ')'
@@ -9773,6 +9779,10 @@ opt_freeze: FREEZE { $$ = TRUE; }
97739779
| /*EMPTY*/ { $$ = FALSE; }
97749780
;
97759781

9782+
opt_local: ONLY LOCAL { $$ = TRUE; }
9783+
| /*EMPTY*/ { $$ = FALSE; }
9784+
;
9785+
97769786
opt_name_list:
97779787
'(' name_list ')' { $$ = $2; }
97789788
| /*EMPTY*/ { $$ = NIL; }

src/include/nodes/parsenodes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2876,7 +2876,8 @@ typedef enum VacuumOption
28762876
VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */
28772877
VACOPT_NOWAIT = 1 << 5, /* don't wait to get lock (autovacuum only) */
28782878
VACOPT_SKIPTOAST = 1 << 6, /* don't process the TOAST table, if any */
2879-
VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7 /* don't skip any pages */
2879+
VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7, /* don't skip any pages */
2880+
VACOPT_LOCAL = 1 << 8 /* Multimaster: perform vacuum only on local node */
28802881
} VacuumOption;
28812882

28822883
typedef struct VacuumStmt

0 commit comments

Comments
 (0)