aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/gin/ginget.c5
-rw-r--r--src/backend/access/gin/ginscan.c43
-rw-r--r--src/include/access/gin_private.h2
3 files changed, 29 insertions, 21 deletions
diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 9d73142ee93..3e2b8b5fedf 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -497,7 +497,7 @@ startScanKey(GinState *ginstate, GinScanOpaque so, GinScanKey key)
}
/* i is now the last required entry. */
- MemoryContextSwitchTo(oldCtx);
+ MemoryContextSwitchTo(so->keyCtx);
key->nrequired = i + 1;
key->nadditional = key->nentries - key->nrequired;
@@ -515,11 +515,14 @@ startScanKey(GinState *ginstate, GinScanOpaque so, GinScanKey key)
}
else
{
+ MemoryContextSwitchTo(so->keyCtx);
+
key->nrequired = 1;
key->nadditional = 0;
key->requiredEntries = palloc(1 * sizeof(GinScanEntry));
key->requiredEntries[0] = key->scanEntry[0];
}
+ MemoryContextSwitchTo(oldCtx);
}
static void
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index b3a2de1edd4..ac3a92b1981 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -44,6 +44,11 @@ ginbeginscan(PG_FUNCTION_ARGS)
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
+ so->keyCtx = AllocSetContextCreate(CurrentMemoryContext,
+ "Gin scan key context",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
initGinState(&so->ginstate, scan->indexRelation);
scan->opaque = so;
@@ -227,6 +232,9 @@ ginFillScanKey(GinScanOpaque so, OffsetNumber attnum,
}
}
+/*
+ * Release current scan keys, if any.
+ */
void
ginFreeScanKeys(GinScanOpaque so)
{
@@ -235,38 +243,22 @@ ginFreeScanKeys(GinScanOpaque so)
if (so->keys == NULL)
return;
- for (i = 0; i < so->nkeys; i++)
- {
- GinScanKey key = so->keys + i;
-
- pfree(key->scanEntry);
- pfree(key->entryRes);
- if (key->requiredEntries)
- pfree(key->requiredEntries);
- if (key->additionalEntries)
- pfree(key->additionalEntries);
- }
-
- pfree(so->keys);
- so->keys = NULL;
- so->nkeys = 0;
-
for (i = 0; i < so->totalentries; i++)
{
GinScanEntry entry = so->entries[i];
if (entry->buffer != InvalidBuffer)
ReleaseBuffer(entry->buffer);
- if (entry->list)
- pfree(entry->list);
if (entry->matchIterator)
tbm_end_iterate(entry->matchIterator);
if (entry->matchBitmap)
tbm_free(entry->matchBitmap);
- pfree(entry);
}
- pfree(so->entries);
+ MemoryContextResetAndDeleteChildren(so->keyCtx);
+
+ so->keys = NULL;
+ so->nkeys = 0;
so->entries = NULL;
so->totalentries = 0;
}
@@ -278,6 +270,14 @@ ginNewScanKey(IndexScanDesc scan)
GinScanOpaque so = (GinScanOpaque) scan->opaque;
int i;
bool hasNullQuery = false;
+ MemoryContext oldCtx;
+
+ /*
+ * Allocate all the scan key information in the key context. (If
+ * extractQuery leaks anything there, it won't be reset until the end of
+ * scan or rescan, but that's OK.)
+ */
+ oldCtx = MemoryContextSwitchTo(so->keyCtx);
/* if no scan keys provided, allocate extra EVERYTHING GinScanKey */
so->keys = (GinScanKey)
@@ -412,6 +412,8 @@ ginNewScanKey(IndexScanDesc scan)
RelationGetRelationName(scan->indexRelation))));
}
+ MemoryContextSwitchTo(oldCtx);
+
pgstat_count_index_scan(scan->indexRelation);
}
@@ -445,6 +447,7 @@ ginendscan(PG_FUNCTION_ARGS)
ginFreeScanKeys(so);
MemoryContextDelete(so->tempCtx);
+ MemoryContextDelete(so->keyCtx);
pfree(so);
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index c949c97edec..bda7c284b13 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -888,6 +888,8 @@ typedef struct GinScanOpaqueData
uint32 totalentries;
uint32 allocentries; /* allocated length of entries[] */
+ MemoryContext keyCtx; /* used to hold key and entry data */
+
bool isVoidRes; /* true if query is unsatisfiable */
} GinScanOpaqueData;