0014-optimize-sqljson-subtransactions-v15.patch
text/x-patch
Filename: 0014-optimize-sqljson-subtransactions-v15.patch
Type: text/x-patch
Part: 4
Message:
Re: SQL/JSON: functions
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v15-0014
| File | + | − |
|---|---|---|
| src/backend/access/transam/xact.c | 128 | 9 |
| src/backend/executor/execExprInterp.c | 1 | 1 |
| src/include/access/xact.h | 1 | 0 |
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 8e6aef3..eb51783 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -188,6 +188,8 @@ typedef struct TransactionStateData
bool startedInRecovery; /* did we start in recovery? */
bool didLogXid; /* has xid been included in WAL record? */
int parallelModeLevel; /* Enter/ExitParallelMode counter */
+ bool isCachedSubXact;
+ struct TransactionStateData *cachedSubXact;
struct TransactionStateData *parent; /* back link to parent */
} TransactionStateData;
@@ -320,7 +322,7 @@ static void CommitSubTransaction(void);
static void AbortSubTransaction(void);
static void CleanupSubTransaction(void);
static void PushTransaction(void);
-static void PopTransaction(void);
+static void PopTransaction(bool free);
static void AtSubAbort_Memory(void);
static void AtSubCleanup_Memory(void);
@@ -334,6 +336,8 @@ static void ShowTransactionStateRec(const char *str, TransactionState state);
static const char *BlockStateAsString(TBlockState blockState);
static const char *TransStateAsString(TransState state);
+static void ReleaseCurrentCachedSubTransaction(void);
+static void RollbackAndReleaseCurrentCachedSubTransaction(void);
/* ----------------------------------------------------------------
* transaction state accessors
@@ -2745,6 +2749,8 @@ CommitTransactionCommand(void)
{
TransactionState s = CurrentTransactionState;
+ ReleaseCurrentCachedSubTransaction();
+
switch (s->blockState)
{
/*
@@ -2985,6 +2991,8 @@ AbortCurrentTransaction(void)
{
TransactionState s = CurrentTransactionState;
+ RollbackAndReleaseCurrentCachedSubTransaction();
+
switch (s->blockState)
{
case TBLOCK_DEFAULT:
@@ -4132,6 +4140,47 @@ RollbackToSavepoint(const char *name)
BlockStateAsString(xact->blockState));
}
+static void
+RestoreSubTransactionState(TransactionState subxact)
+{
+ CurrentTransactionState = subxact;
+
+ CurTransactionContext = subxact->curTransactionContext;
+ MemoryContextSwitchTo(CurTransactionContext);
+ CurTransactionResourceOwner = subxact->curTransactionOwner;
+ CurrentResourceOwner = subxact->curTransactionOwner;
+}
+
+static void
+ReleaseCurrentCachedSubTransaction(void)
+{
+ TransactionState s = CurrentTransactionState;
+
+ if (s->cachedSubXact)
+ {
+ RestoreSubTransactionState(s->cachedSubXact);
+ ReleaseCurrentCachedSubTransaction();
+ MemoryContextSwitchTo(CurTransactionContext);
+ CommitSubTransaction();
+ Assert(s == CurrentTransactionState);
+ s->cachedSubXact = NULL;
+ }
+}
+
+static void
+RollbackAndReleaseCurrentCachedSubTransaction(void)
+{
+ TransactionState s = CurrentTransactionState;
+
+ if (s->cachedSubXact)
+ {
+ RestoreSubTransactionState(s->cachedSubXact);
+ RollbackAndReleaseCurrentSubTransaction();
+ Assert(s == CurrentTransactionState);
+ s->cachedSubXact = NULL;
+ }
+}
+
/*
* BeginInternalSubTransaction
* This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
@@ -4142,8 +4191,8 @@ RollbackToSavepoint(const char *name)
* CommitTransactionCommand/StartTransactionCommand instead of expecting
* the caller to do it.
*/
-void
-BeginInternalSubTransaction(const char *name)
+static void
+BeginInternalSubTransactionInternal(const char *name, bool cached)
{
TransactionState s = CurrentTransactionState;
@@ -4170,10 +4219,31 @@ BeginInternalSubTransaction(const char *name)
case TBLOCK_END:
case TBLOCK_PREPARE:
case TBLOCK_SUBINPROGRESS:
+ if (s->cachedSubXact)
+ {
+ TransactionState subxact = s->cachedSubXact;
+
+ s->cachedSubXact = NULL;
+
+ Assert(subxact->subTransactionId == currentSubTransactionId);
+ if (subxact->subTransactionId == currentSubTransactionId)
+ {
+ /* reuse cached subtransaction */
+ RestoreSubTransactionState(subxact);
+ return;
+ }
+ else
+ {
+ ReleaseCurrentCachedSubTransaction();
+ }
+ }
+
/* Normal subtransaction start */
PushTransaction();
s = CurrentTransactionState; /* changed by push */
+ s->isCachedSubXact = cached;
+
/*
* Savepoint names, like the TransactionState block itself, live
* in TopTransactionContext.
@@ -4206,6 +4276,18 @@ BeginInternalSubTransaction(const char *name)
StartTransactionCommand();
}
+void
+BeginInternalSubTransaction(const char *name)
+{
+ BeginInternalSubTransactionInternal(name, false);
+}
+
+void
+BeginInternalCachedSubTransaction(const char *name)
+{
+ BeginInternalSubTransactionInternal(name, true);
+}
+
/*
* ReleaseCurrentSubTransaction
*
@@ -4234,8 +4316,40 @@ ReleaseCurrentSubTransaction(void)
elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
BlockStateAsString(s->blockState));
Assert(s->state == TRANS_INPROGRESS);
- MemoryContextSwitchTo(CurTransactionContext);
- CommitSubTransaction();
+
+ ReleaseCurrentCachedSubTransaction();
+
+ if (s->isCachedSubXact &&
+ !TransactionIdIsValid(s->transactionId) &&
+ !s->cachedSubXact /*&
+ (!s->curTransactionOwner ||
+ (!s->curTransactionOwner->firstchild &&
+ s->curTransactionOwner->nlocks <= 0))*/)
+ {
+ if (s->curTransactionOwner)
+ {
+ ResourceOwnerRelease(s->curTransactionOwner,
+ RESOURCE_RELEASE_BEFORE_LOCKS,
+ true, false);
+ ResourceOwnerRelease(s->curTransactionOwner,
+ RESOURCE_RELEASE_LOCKS,
+ true, false);
+ ResourceOwnerRelease(s->curTransactionOwner,
+ RESOURCE_RELEASE_AFTER_LOCKS,
+ true, false);
+ }
+
+ Assert(!s->parent->cachedSubXact);
+ s->parent->cachedSubXact = s;
+
+ PopTransaction(false);
+ }
+ else
+ {
+ MemoryContextSwitchTo(CurTransactionContext);
+ CommitSubTransaction();
+ }
+
s = CurrentTransactionState; /* changed by pop */
Assert(s->state == TRANS_INPROGRESS);
}
@@ -4291,6 +4405,8 @@ RollbackAndReleaseCurrentSubTransaction(void)
break;
}
+ RollbackAndReleaseCurrentCachedSubTransaction();
+
/*
* Abort the current subtransaction, if needed.
*/
@@ -4654,7 +4770,7 @@ CommitSubTransaction(void)
s->state = TRANS_DEFAULT;
- PopTransaction();
+ PopTransaction(true);
}
/*
@@ -4831,7 +4947,7 @@ CleanupSubTransaction(void)
s->state = TRANS_DEFAULT;
- PopTransaction();
+ PopTransaction(true);
}
/*
@@ -4901,11 +5017,11 @@ PushTransaction(void)
* if it has a local pointer to it after calling this function.
*/
static void
-PopTransaction(void)
+PopTransaction(bool free)
{
TransactionState s = CurrentTransactionState;
- if (s->state != TRANS_DEFAULT)
+ if (free && s->state != TRANS_DEFAULT)
elog(WARNING, "PopTransaction while in %s state",
TransStateAsString(s->state));
@@ -4922,6 +5038,9 @@ PopTransaction(void)
CurTransactionResourceOwner = s->parent->curTransactionOwner;
CurrentResourceOwner = s->parent->curTransactionOwner;
+ if (!free)
+ return;
+
/* Free the old child structure */
if (s->name)
pfree(s->name);
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 1ca6d7b..c13143e 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -4531,7 +4531,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
MemoryContext oldcontext = CurrentMemoryContext;
ResourceOwner oldowner = CurrentResourceOwner;
- BeginInternalSubTransaction(NULL);
+ BeginInternalCachedSubTransaction(NULL);
/* Want to execute expressions inside function's memory context */
MemoryContextSwitchTo(oldcontext);
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 083e879..8f7be9a 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -380,6 +380,7 @@ extern void ReleaseSavepoint(const char *name);
extern void DefineSavepoint(const char *name);
extern void RollbackToSavepoint(const char *name);
extern void BeginInternalSubTransaction(const char *name);
+extern void BeginInternalCachedSubTransaction(const char *name);
extern void ReleaseCurrentSubTransaction(void);
extern void RollbackAndReleaseCurrentSubTransaction(void);
extern bool IsSubTransaction(void);