]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix bug where GIN scan keys were not initialized with gin_fuzzy_search_limit.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 29 Jan 2015 17:35:55 +0000 (19:35 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Thu, 29 Jan 2015 17:37:25 +0000 (19:37 +0200)
When gin_fuzzy_search_limit was used, we could jump out of startScan()
without calling startScanKey(). That was harmless in 9.3 and below, because
startScanKey()() didn't do anything interesting, but in 9.4 it initializes
information needed for skipping entries (aka GIN fast scans), and you
readily get a segfault if it's not done. Nevertheless, it was clearly wrong
all along, so backpatch all the way to 9.1 where the early return was
introduced.

(AFAICS startScanKey() did nothing useful in 9.3 and below, because the
fields it initialized were already initialized in ginFillScanKey(), but I
don't dare to change that in a minor release. ginFillScanKey() is always
called in gingetbitmap() even though there's a check there to see if the
scan keys have already been initialized, because they never are; ginrescan()
free's them.)

In the passing, remove unnecessary if-check from the second inner loop in
startScan(). We already check in the first loop that the condition is true
for all entries.

Reported by Olaf Gawenda, bug #12694, Backpatch to 9.1 and above, although
AFAICS it causes a live bug only in 9.4.

src/backend/access/gin/ginget.c

index 8a7adaf034a117b8893f63b771566e0bb78e960c..28c3486589c8596ee66a65ef14c9a0c302f29121 100644 (file)
@@ -509,17 +509,24 @@ startScan(IndexScanDesc scan)
                 * supposition isn't true), that total result will not more than
                 * minimal predictNumberResult.
                 */
+               bool            reduce = true;
 
                for (i = 0; i < so->totalentries; i++)
+               {
                        if (so->entries[i]->predictNumberResult <= so->totalentries * GinFuzzySearchLimit)
-                               return;
-
-               for (i = 0; i < so->totalentries; i++)
-                       if (so->entries[i]->predictNumberResult > so->totalentries * GinFuzzySearchLimit)
+                       {
+                               reduce = false;
+                               break;
+                       }
+               }
+               if (reduce)
+               {
+                       for (i = 0; i < so->totalentries; i++)
                        {
                                so->entries[i]->predictNumberResult /= so->totalentries;
                                so->entries[i]->reduceResult = TRUE;
                        }
+               }
        }
 
        for (i = 0; i < so->nkeys; i++)