mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Fix multicolumn GIN's wrong results with fastupdate enabled.
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>
This commit is contained in:
		@@ -8,7 +8,7 @@
 | 
				
			|||||||
 * Portions Copyright (c) 1994, Regents of the University of California
 | 
					 * Portions Copyright (c) 1994, Regents of the University of California
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * 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 $
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,6 +29,7 @@ typedef struct pendingPosition
 | 
				
			|||||||
	OffsetNumber 		firstOffset;
 | 
						OffsetNumber 		firstOffset;
 | 
				
			||||||
	OffsetNumber 		lastOffset;
 | 
						OffsetNumber 		lastOffset;
 | 
				
			||||||
	ItemPointerData 	item;
 | 
						ItemPointerData 	item;
 | 
				
			||||||
 | 
						bool			   *hasMatchKey;
 | 
				
			||||||
} pendingPosition;
 | 
					} pendingPosition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -873,6 +874,18 @@ matchPartialInPendingList(GinState *ginstate, Page page,
 | 
				
			|||||||
	return false;
 | 
						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
 | 
					 * Sets entryRes array for each key by looking at
 | 
				
			||||||
 * every entry per indexed value (heap's row) in pending list.
 | 
					 * every entry per indexed value (heap's row) in pending list.
 | 
				
			||||||
@@ -889,7 +902,6 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
 | 
				
			|||||||
	IndexTuple	itup;
 | 
						IndexTuple	itup;
 | 
				
			||||||
	int			i,
 | 
						int			i,
 | 
				
			||||||
				j;
 | 
									j;
 | 
				
			||||||
	bool		hasMatch = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Resets entryRes
 | 
						 * Resets entryRes
 | 
				
			||||||
@@ -900,6 +912,7 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		memset(key->entryRes, FALSE, key->nentries);
 | 
							memset(key->entryRes, FALSE, key->nentries);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						memset(pos->hasMatchKey, FALSE, so->nkeys); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (;;)
 | 
						for (;;)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -1005,7 +1018,7 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
 | 
				
			|||||||
												  entry->extra_data);
 | 
																	  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
 | 
								 * We scan all values from one tuple, go to next one
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return hasMatch;
 | 
								return hasAllMatchingKeys(so, pos);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							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);
 | 
						LockBuffer(pos.pendingBuffer, GIN_SHARE);
 | 
				
			||||||
	pos.firstOffset = FirstOffsetNumber;
 | 
						pos.firstOffset = FirstOffsetNumber;
 | 
				
			||||||
	UnlockReleaseBuffer(metabuffer);
 | 
						UnlockReleaseBuffer(metabuffer);
 | 
				
			||||||
 | 
						pos.hasMatchKey = palloc(sizeof(bool) * so->nkeys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * loop for each heap row. scanGetCandidate returns full row or row's
 | 
						 * loop for each heap row. scanGetCandidate returns full row or row's
 | 
				
			||||||
@@ -1126,6 +1140,8 @@ scanPendingInsert(IndexScanDesc scan, TIDBitmap *tbm, int64 *ntids)
 | 
				
			|||||||
			(*ntids)++;
 | 
								(*ntids)++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pfree(pos.hasMatchKey);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user