allow-query-cancel-in-spgdoinsert-WIP.patch
text/x-diff
Filename: allow-query-cancel-in-spgdoinsert-WIP.patch
Type: text/x-diff
Part: 0
Message:
Re: OOM in spgist insert
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/spgist/spgdoinsert.c | 26 | 5 |
diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c
index 4d380c99f0..82e68c4ab7 100644
--- a/src/backend/access/spgist/spgdoinsert.c
+++ b/src/backend/access/spgist/spgdoinsert.c
@@ -1905,13 +1905,14 @@ spgSplitNodeAction(Relation index, SpGistState *state,
* Insert one item into the index.
*
* Returns true on success, false if we failed to complete the insertion
- * because of conflict with a concurrent insert. In the latter case,
- * caller should re-call spgdoinsert() with the same args.
+ * (typically because of conflict with a concurrent insert). In the latter
+ * case, caller should re-call spgdoinsert() with the same args.
*/
bool
spgdoinsert(Relation index, SpGistState *state,
ItemPointer heapPtr, Datum *datums, bool *isnulls)
{
+ bool result = true;
TupleDesc leafDescriptor = state->leafTupDesc;
bool isnull = isnulls[spgKeyColumn];
int level = 0;
@@ -2019,9 +2020,17 @@ spgdoinsert(Relation index, SpGistState *state,
/*
* Bail out if query cancel is pending. We must have this somewhere
* in the loop since a broken opclass could produce an infinite
- * picksplit loop.
+ * picksplit loop. Moreover, because it's typically the case that
+ * we're holding buffer lock(s), ProcessInterrupts() won't be able to
+ * throw an error now. Hence, if we see that InterruptPending remains
+ * true, break out of the loop and deal with the problem below.
*/
CHECK_FOR_INTERRUPTS();
+ if (unlikely(InterruptPending))
+ {
+ result = false;
+ break;
+ }
if (current.blkno == InvalidBlockNumber)
{
@@ -2140,10 +2149,15 @@ spgdoinsert(Relation index, SpGistState *state,
* spgAddNode and spgSplitTuple cases will loop back to here to
* complete the insertion operation. Just in case the choose
* function is broken and produces add or split requests
- * repeatedly, check for query cancel.
+ * repeatedly, check for query cancel (see comments above).
*/
process_inner_tuple:
CHECK_FOR_INTERRUPTS();
+ if (unlikely(InterruptPending))
+ {
+ result = false;
+ break;
+ }
innerTuple = (SpGistInnerTuple) PageGetItem(current.page,
PageGetItemId(current.page, current.offnum));
@@ -2267,5 +2281,12 @@ spgdoinsert(Relation index, SpGistState *state,
UnlockReleaseBuffer(parent.buffer);
}
- return true;
+ /*
+ * Finally, check for interrupts again. If there was one,
+ * ProcessInterrupts() will be able to throw the error now. But should it
+ * not do so for some reason, return false to cause a retry.
+ */
+ CHECK_FOR_INTERRUPTS();
+
+ return result;
}