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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy