|
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;
|
|