|
27 | 27 | * had been its upper part (pd_upper to pd_special). We assume that the |
28 | 28 | * tuples had been added to the page in item-number order, and therefore |
29 | 29 | * the one with highest item number appears first (lowest on the page). |
30 | | - * |
31 | | - * NOTE: the way this routine is coded, the rebuilt page will have the items |
32 | | - * in correct itemno sequence, but physically the opposite order from the |
33 | | - * original, because we insert them in the opposite of itemno order. This |
34 | | - * does not matter in any current btree code, but it's something to keep an |
35 | | - * eye on.Is it worth changing just on general principles? See also the |
36 | | - * notes in btree_xlog_split(). |
37 | 30 | */ |
38 | 31 | staticvoid |
39 | 32 | _bt_restore_page(Pagepage,char*from,intlen) |
40 | 33 | { |
41 | 34 | IndexTupleDataitupdata; |
42 | 35 | Sizeitemsz; |
43 | 36 | char*end=from+len; |
| 37 | +Itemitems[MaxIndexTuplesPerPage]; |
| 38 | +uint16itemsizes[MaxIndexTuplesPerPage]; |
| 39 | +inti; |
| 40 | +intnitems; |
44 | 41 |
|
45 | | -for (;from<end;) |
| 42 | +/* |
| 43 | + * To get the items back in the original order, we add them to the page |
| 44 | + * in reverse. To figure out where one tuple ends and another begins, |
| 45 | + * we have to scan them in forward order first. |
| 46 | + */ |
| 47 | +i=0; |
| 48 | +while (from<end) |
46 | 49 | { |
47 | 50 | /* Need to copy tuple header due to alignment considerations */ |
48 | 51 | memcpy(&itupdata,from,sizeof(IndexTupleData)); |
49 | 52 | itemsz=IndexTupleDSize(itupdata); |
50 | 53 | itemsz=MAXALIGN(itemsz); |
51 | | -if (PageAddItem(page, (Item)from,itemsz,FirstOffsetNumber, |
| 54 | + |
| 55 | +items[i]= (Item)from; |
| 56 | +itemsizes[i]=itemsz; |
| 57 | +i++; |
| 58 | + |
| 59 | +from+=itemsz; |
| 60 | +} |
| 61 | +nitems=i; |
| 62 | + |
| 63 | +for (i=nitems-1;i >=0;i--) |
| 64 | +{ |
| 65 | +if (PageAddItem(page,items[i],itemsizes[i],nitems-i, |
52 | 66 | false, false)==InvalidOffsetNumber) |
53 | 67 | elog(PANIC,"_bt_restore_page: cannot add item to page"); |
54 | 68 | from+=itemsz; |
@@ -332,56 +346,66 @@ btree_xlog_split(bool onleft, bool isroot, |
332 | 346 | if (BufferIsValid(lbuf)) |
333 | 347 | { |
334 | 348 | /* |
335 | | - * Note that this code ensures that the items remaining on the |
336 | | - * left page are in the correct item number order, but it does not |
337 | | - * reproduce the physical order they would have had. Is this |
338 | | - * worth changing?See also _bt_restore_page(). |
| 349 | + * To retain the same physical order of the tuples that they had, |
| 350 | + * we initialize a temporary empty page for the left page and add |
| 351 | + * all the items to that in item number order. This mirrors how |
| 352 | + * _bt_split() works. It's not strictly required to retain the |
| 353 | + * same physical order, as long as the items are in the correct |
| 354 | + * item number order, but it helps debugging. See also |
| 355 | + * _bt_restore_page(), which does the same for the right page. |
339 | 356 | */ |
340 | 357 | Pagelpage= (Page)BufferGetPage(lbuf); |
341 | 358 | BTPageOpaquelopaque= (BTPageOpaque)PageGetSpecialPointer(lpage); |
342 | 359 |
|
343 | 360 | if (lsn>PageGetLSN(lpage)) |
344 | 361 | { |
345 | 362 | OffsetNumberoff; |
346 | | -OffsetNumbermaxoff=PageGetMaxOffsetNumber(lpage); |
347 | | -OffsetNumberdeletable[MaxOffsetNumber]; |
348 | | -intndeletable=0; |
349 | | - |
350 | | -/* |
351 | | - * Remove the items from the left page that were copied to the |
352 | | - * right page.Also remove the old high key, if any. (We must |
353 | | - * remove everything before trying to insert any items, else |
354 | | - * we risk not having enough space.) |
355 | | - */ |
356 | | -if (!P_RIGHTMOST(lopaque)) |
357 | | -{ |
358 | | -deletable[ndeletable++]=P_HIKEY; |
| 363 | +Pagenewlpage; |
| 364 | +OffsetNumberleftoff; |
359 | 365 |
|
360 | | -/* |
361 | | - * newitemoff is given to us relative to the original |
362 | | - * page's item numbering, so adjust it for this deletion. |
363 | | - */ |
364 | | -newitemoff--; |
| 366 | +newlpage=PageGetTempPageCopySpecial(lpage); |
| 367 | + |
| 368 | +/* Set high key */ |
| 369 | +leftoff=P_HIKEY; |
| 370 | +if (PageAddItem(newlpage,left_hikey,left_hikeysz, |
| 371 | +P_HIKEY, false, false)==InvalidOffsetNumber) |
| 372 | +elog(PANIC,"failed to add high key to left page after split"); |
| 373 | +leftoff=OffsetNumberNext(leftoff); |
| 374 | + |
| 375 | +for (off=P_FIRSTDATAKEY(lopaque);off<xlrec->firstright;off++) |
| 376 | +{ |
| 377 | +ItemIditemid; |
| 378 | +Sizeitemsz; |
| 379 | +Itemitem; |
| 380 | + |
| 381 | +/* add the new item if it was inserted on left page */ |
| 382 | +if (onleft&&off==newitemoff) |
| 383 | +{ |
| 384 | +if (PageAddItem(newlpage,newitem,newitemsz,leftoff, |
| 385 | +false, false)==InvalidOffsetNumber) |
| 386 | +elog(ERROR,"failed to add new item to left page after split"); |
| 387 | +leftoff=OffsetNumberNext(leftoff); |
| 388 | +} |
| 389 | + |
| 390 | +itemid=PageGetItemId(lpage,off); |
| 391 | +itemsz=ItemIdGetLength(itemid); |
| 392 | +item=PageGetItem(lpage,itemid); |
| 393 | +if (PageAddItem(newlpage,item,itemsz,leftoff, |
| 394 | +false, false)==InvalidOffsetNumber) |
| 395 | +elog(ERROR,"failed to add old item to left page after split"); |
| 396 | +leftoff=OffsetNumberNext(leftoff); |
365 | 397 | } |
366 | | -for (off=xlrec->firstright;off <=maxoff;off++) |
367 | | -deletable[ndeletable++]=off; |
368 | | -if (ndeletable>0) |
369 | | -PageIndexMultiDelete(lpage,deletable,ndeletable); |
370 | | - |
371 | | -/* |
372 | | - * Add the new item if it was inserted on left page. |
373 | | - */ |
374 | | -if (onleft) |
| 398 | + |
| 399 | +/* cope with possibility that newitem goes at the end */ |
| 400 | +if (onleft&&off==newitemoff) |
375 | 401 | { |
376 | | -if (PageAddItem(lpage,newitem,newitemsz,newitemoff, |
| 402 | +if (PageAddItem(newlpage,newitem,newitemsz,leftoff, |
377 | 403 | false, false)==InvalidOffsetNumber) |
378 | | -elog(PANIC,"failed to add new item to left page after split"); |
| 404 | +elog(ERROR,"failed to add new item to left page after split"); |
| 405 | +leftoff=OffsetNumberNext(leftoff); |
379 | 406 | } |
380 | 407 |
|
381 | | -/* Set high key */ |
382 | | -if (PageAddItem(lpage,left_hikey,left_hikeysz, |
383 | | -P_HIKEY, false, false)==InvalidOffsetNumber) |
384 | | -elog(PANIC,"failed to add high key to left page after split"); |
| 408 | +PageRestoreTempPage(newlpage,lpage); |
385 | 409 |
|
386 | 410 | /* Fix opaque fields */ |
387 | 411 | lopaque->btpo_flags=BTP_INCOMPLETE_SPLIT; |
|