mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Back-patch defense against oversize index tuples and fix for trying to
split a page that only has one entry.
This commit is contained in:
		@@ -7,7 +7,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.42.2.2 1999/09/01 17:54:00 scrappy Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.42.2.3 1999/12/26 20:44:15 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -267,6 +267,18 @@ _bt_insertonpg(Relation rel,
 | 
				
			|||||||
										 * this but we need to be
 | 
															 * this but we need to be
 | 
				
			||||||
										 * consistent */
 | 
															 * consistent */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Check whether the item can fit on a btree page at all.
 | 
				
			||||||
 | 
						 * (Eventually, we ought to try to apply TOAST methods if not.)
 | 
				
			||||||
 | 
						 * We actually need to be able to fit three items on every page,
 | 
				
			||||||
 | 
						 * so restrict any one item to 1/3 the per-page available space.
 | 
				
			||||||
 | 
						 * Note that at this point, itemsz doesn't include the ItemId.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (itemsz > (PageGetPageSize(page)-sizeof(PageHeaderData)-MAXALIGN(sizeof(BTPageOpaqueData)))/3 - sizeof(ItemIdData))
 | 
				
			||||||
 | 
							elog(ERROR, "btree: index item size %d exceeds maximum %d",
 | 
				
			||||||
 | 
								 itemsz,
 | 
				
			||||||
 | 
								 (PageGetPageSize(page)-sizeof(PageHeaderData)-MAXALIGN(sizeof(BTPageOpaqueData)))/3 - sizeof(ItemIdData));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If we have to insert item on the leftmost page which is the first
 | 
						 * If we have to insert item on the leftmost page which is the first
 | 
				
			||||||
	 * page in the chain of duplicates then: 1. if scankey == hikey (i.e.
 | 
						 * page in the chain of duplicates then: 1. if scankey == hikey (i.e.
 | 
				
			||||||
@@ -342,12 +354,16 @@ _bt_insertonpg(Relation rel,
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		OffsetNumber offnum = (P_RIGHTMOST(lpageop)) ? P_HIKEY : P_FIRSTKEY;
 | 
							OffsetNumber offnum = (P_RIGHTMOST(lpageop)) ? P_HIKEY : P_FIRSTKEY;
 | 
				
			||||||
		OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
 | 
							OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (offnum < maxoff)	/* can't split unless at least 2 items... */
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
			ItemId		itid;
 | 
								ItemId		itid;
 | 
				
			||||||
			BTItem		previtem,
 | 
								BTItem		previtem,
 | 
				
			||||||
						chkitem;
 | 
											chkitem;
 | 
				
			||||||
			Size		maxsize;
 | 
								Size		maxsize;
 | 
				
			||||||
			Size		currsize;
 | 
								Size		currsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* find largest group of identically-keyed items on page */
 | 
				
			||||||
			itid = PageGetItemId(page, offnum);
 | 
								itid = PageGetItemId(page, offnum);
 | 
				
			||||||
			previtem = (BTItem) PageGetItem(page, itid);
 | 
								previtem = (BTItem) PageGetItem(page, itid);
 | 
				
			||||||
			maxsize = currsize = (ItemIdGetLength(itid) + sizeof(ItemIdData));
 | 
								maxsize = currsize = (ItemIdGetLength(itid) + sizeof(ItemIdData));
 | 
				
			||||||
@@ -368,11 +384,13 @@ _bt_insertonpg(Relation rel,
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			if (currsize > maxsize)
 | 
								if (currsize > maxsize)
 | 
				
			||||||
				maxsize = currsize;
 | 
									maxsize = currsize;
 | 
				
			||||||
 | 
								/* Decide to split if largest group is > 1/2 page size */
 | 
				
			||||||
			maxsize += sizeof(PageHeaderData) +
 | 
								maxsize += sizeof(PageHeaderData) +
 | 
				
			||||||
				MAXALIGN(sizeof(BTPageOpaqueData));
 | 
									MAXALIGN(sizeof(BTPageOpaqueData));
 | 
				
			||||||
			if (maxsize >= PageGetPageSize(page) / 2)
 | 
								if (maxsize >= PageGetPageSize(page) / 2)
 | 
				
			||||||
				do_split = true;
 | 
									do_split = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (do_split)
 | 
						if (do_split)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user