Fix multicolumn GIN's wrong results with fastupdate enabled.
authorTeodor Sigaev <teodor@sigaev.ru>
Fri, 13 Nov 2009 11:17:04 +0000 (11:17 +0000)
committerTeodor Sigaev <teodor@sigaev.ru>
Fri, 13 Nov 2009 11:17:04 +0000 (11:17 +0000)
User-defined consistent functions believes the check array
contains at least one true element which was not a true for
scanning pending list.

Per report from Yury Don <yura@vpcit.ru>

src/backend/access/gin/ginget.c

index f5e0f788d1c6dd94a18f36119da578770df356e5..db8fcc5633fae22b5eea05a1dad551202a39b53f 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *                     $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.27 2009/06/11 14:48:53 momjian Exp $
+ *                     $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.28 2009/11/13 11:17:04 teodor Exp $
  *-------------------------------------------------------------------------
  */
 
 
 typedef struct pendingPosition
 {
-       Buffer          pendingBuffer;
-       OffsetNumber firstOffset;
-       OffsetNumber lastOffset;
-       ItemPointerData item;
+       Buffer                          pendingBuffer;
+       OffsetNumber            firstOffset;
+       OffsetNumber            lastOffset;
+       ItemPointerData         item;
+       bool                       *hasMatchKey;
 } pendingPosition;
 
 
@@ -873,6 +874,18 @@ matchPartialInPendingList(GinState *ginstate, Page page,
        return false;
 }
 
+static bool
+hasAllMatchingKeys(GinScanOpaque so, pendingPosition *pos)
+{
+       int             i;
+
+       for (i = 0; i < so->nkeys; i++)
+               if (pos->hasMatchKey[i] == false)
+                       return false;
+
+       return true;
+}
+
 /*
  * Sets entryRes array for each key by looking at
  * every entry per indexed value (heap's row) in pending list.
@@ -889,7 +902,6 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
        IndexTuple      itup;
        int                     i,
                                j;
-       bool            hasMatch = false;
 
        /*
         * Resets entryRes
@@ -900,6 +912,7 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
 
                memset(key->entryRes, FALSE, key->nentries);
        }
+       memset(pos->hasMatchKey, FALSE, so->nkeys); 
 
        for (;;)
        {
@@ -1005,7 +1018,7 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
                                                                                                  entry->extra_data);
                                }
 
-                               hasMatch |= key->entryRes[j];
+                               pos->hasMatchKey[i] |= key->entryRes[j];
                        }
                }
 
@@ -1017,7 +1030,7 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
                         * We scan all values from one tuple, go to next one
                         */
 
-                       return hasMatch;
+                       return hasAllMatchingKeys(so, pos);
                }
                else
                {
@@ -1034,7 +1047,7 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
                }
        }
 
-       return hasMatch;
+       return hasAllMatchingKeys(so, pos);
 }
 
 /*
@@ -1073,6 +1086,7 @@ scanPendingInsert(IndexScanDesc scan, TIDBitmap *tbm, int64 *ntids)
        LockBuffer(pos.pendingBuffer, GIN_SHARE);
        pos.firstOffset = FirstOffsetNumber;
        UnlockReleaseBuffer(metabuffer);
+       pos.hasMatchKey = palloc(sizeof(bool) * so->nkeys);
 
        /*
         * loop for each heap row. scanGetCandidate returns full row or row's
@@ -1126,6 +1140,8 @@ scanPendingInsert(IndexScanDesc scan, TIDBitmap *tbm, int64 *ntids)
                        (*ntids)++;
                }
        }
+
+       pfree(pos.hasMatchKey);
 }
 
 /*