aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/spgist/spginsert.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/spgist/spginsert.c')
-rw-r--r--src/backend/access/spgist/spginsert.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c
index 94384acc485..f4d0fe5a0c2 100644
--- a/src/backend/access/spgist/spginsert.c
+++ b/src/backend/access/spgist/spginsert.c
@@ -45,7 +45,10 @@ spgistBuildCallback(Relation index, HeapTuple htup, Datum *values,
/* Work in temp context, and reset it after each tuple */
oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx);
- spgdoinsert(index, &buildstate->spgstate, &htup->t_self, *values, *isnull);
+ /* No concurrent insertions can be happening, so failure is unexpected */
+ if (!spgdoinsert(index, &buildstate->spgstate, &htup->t_self,
+ *values, *isnull))
+ elog(ERROR, "unexpected spgdoinsert() failure");
MemoryContextSwitchTo(oldCtx);
MemoryContextReset(buildstate->tmpCtx);
@@ -219,7 +222,17 @@ spginsert(PG_FUNCTION_ARGS)
initSpGistState(&spgstate, index);
- spgdoinsert(index, &spgstate, ht_ctid, *values, *isnull);
+ /*
+ * We might have to repeat spgdoinsert() multiple times, if conflicts
+ * occur with concurrent insertions. If so, reset the insertCtx each time
+ * to avoid cumulative memory consumption. That means we also have to
+ * redo initSpGistState(), but it's cheap enough not to matter.
+ */
+ while (!spgdoinsert(index, &spgstate, ht_ctid, *values, *isnull))
+ {
+ MemoryContextReset(insertCtx);
+ initSpGistState(&spgstate, index);
+ }
SpGistUpdateMetaPage(index);