]> granicus.if.org Git - postgresql/blobdiff - src/backend/access/gin/ginscan.c
Use a separate memory context for GIN scan keys.
[postgresql] / src / backend / access / gin / ginscan.c
index b3a2de1edd4d37d72f6b665c8c1d7cd552dbb4f0..ac3a92b1981a372a04dc1799b9c96689554ba543 100644 (file)
@@ -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);