|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.78 2001/01/29 07:28:16 vadim Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.79 2001/01/31 01:08:36 vadim Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -37,7 +37,9 @@ typedef struct
|
37 | 37 | externboolFixBTree;
|
38 | 38 |
|
39 | 39 | Buffer_bt_fixroot(Relationrel,Bufferoldrootbuf,boolrelease);
|
40 |
| -staticvoid_bt_fixtree(Relationrel,BlockNumberblkno,BTStackstack); |
| 40 | +staticvoid_bt_fixtree(Relationrel,BlockNumberblkno); |
| 41 | +staticBlockNumber_bt_fixlevel(Relationrel,Bufferbuf,BlockNumberlimit); |
| 42 | +staticOffsetNumber_bt_getoff(Pagepage,BlockNumberblkno); |
41 | 43 |
|
42 | 44 | staticBuffer_bt_newroot(Relationrel,Bufferlbuf,Bufferrbuf);
|
43 | 45 |
|
@@ -512,7 +514,7 @@ _bt_insertonpg(Relation rel,
|
512 | 514 | {
|
513 | 515 | blkno=lpageop->btpo_parent;
|
514 | 516 | _bt_relbuf(rel,buf,BT_WRITE);
|
515 |
| -_bt_fixtree(rel,blkno,NULL); |
| 517 | +_bt_fixtree(rel,blkno); |
516 | 518 | gotoformres;
|
517 | 519 | }
|
518 | 520 | }
|
@@ -561,6 +563,10 @@ _bt_insertonpg(Relation rel,
|
561 | 563 |
|
562 | 564 | pbuf=_bt_getstackbuf(rel,stack);
|
563 | 565 |
|
| 566 | +if (pbuf==InvalidBuffer) |
| 567 | +elog(ERROR,"_bt_getstackbuf: my bits moved right off the end of the world!" |
| 568 | +"\n\tRecreate index %s.",RelationGetRelationName(rel)); |
| 569 | + |
564 | 570 | /* Now we can write and unlock the children */
|
565 | 571 | _bt_wrtbuf(rel,rbuf);
|
566 | 572 | _bt_wrtbuf(rel,buf);
|
@@ -1172,8 +1178,10 @@ _bt_getstackbuf(Relation rel, BTStack stack)
|
1172 | 1178 | }
|
1173 | 1179 | /* by here, the item we're looking for moved right at least one page */
|
1174 | 1180 | if (P_RIGHTMOST(opaque))
|
1175 |
| -elog(FATAL,"_bt_getstackbuf: my bits moved right off the end of the world!" |
1176 |
| -"\n\tRecreate index %s.",RelationGetRelationName(rel)); |
| 1181 | +{ |
| 1182 | +_bt_relbuf(rel,buf,BT_WRITE); |
| 1183 | +return(InvalidBuffer); |
| 1184 | +} |
1177 | 1185 |
|
1178 | 1186 | blkno=opaque->btpo_next;
|
1179 | 1187 | _bt_relbuf(rel,buf,BT_WRITE);
|
@@ -1450,6 +1458,7 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
|
1450 | 1458 |
|
1451 | 1459 | /* give up left buffer */
|
1452 | 1460 | _bt_relbuf(rel,leftbuf,BT_WRITE);
|
| 1461 | +pfree(btitem); |
1453 | 1462 | leftbuf=rightbuf;
|
1454 | 1463 | leftpage=rightpage;
|
1455 | 1464 | leftopaque=rightopaque;
|
@@ -1477,10 +1486,318 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
|
1477 | 1486 | return(rootbuf);
|
1478 | 1487 | }
|
1479 | 1488 |
|
| 1489 | +/* |
| 1490 | + * Using blkno of leftmost page on a level inside tree this func |
| 1491 | + * checks/fixes tree from this level up to the root page. |
| 1492 | + */ |
1480 | 1493 | staticvoid
|
1481 |
| -_bt_fixtree(Relationrel,BlockNumberblkno,BTStackstack) |
| 1494 | +_bt_fixtree(Relationrel,BlockNumberblkno) |
| 1495 | +{ |
| 1496 | +Bufferbuf; |
| 1497 | +Pagepage; |
| 1498 | +BTPageOpaqueopaque; |
| 1499 | +BlockNumberpblkno; |
| 1500 | + |
| 1501 | +elog(ERROR,"bt_fixtree: unimplemented , yet (need to recreate index)"); |
| 1502 | + |
| 1503 | +for ( ; ; ) |
| 1504 | +{ |
| 1505 | +buf=_bt_getbuf(rel,blkno,BT_READ); |
| 1506 | +page=BufferGetPage(buf); |
| 1507 | +opaque= (BTPageOpaque)PageGetSpecialPointer(page); |
| 1508 | +if (!P_LEFTMOST(opaque)||P_ISLEAF(opaque)) |
| 1509 | +elog(ERROR,"bt_fixtree: invalid start page (need to recreate index)"); |
| 1510 | +pblkno=opaque->btpo_parent; |
| 1511 | + |
| 1512 | +/* check/fix entire level */ |
| 1513 | +_bt_fixlevel(rel,buf,InvalidBlockNumber); |
| 1514 | + |
| 1515 | +/* |
| 1516 | + * No pins/locks are held here. Re-read start page if its |
| 1517 | + * btpo_parent pointed to meta page else go up one level. |
| 1518 | + */ |
| 1519 | +if (pblkno==BTREE_METAPAGE) |
| 1520 | +{ |
| 1521 | +buf=_bt_getbuf(rel,blkno,BT_WRITE); |
| 1522 | +page=BufferGetPage(buf); |
| 1523 | +opaque= (BTPageOpaque)PageGetSpecialPointer(page); |
| 1524 | +if (P_ISROOT(opaque)) |
| 1525 | +{ |
| 1526 | +/* Tree is Ok now */ |
| 1527 | +_bt_relbuf(rel,buf,BT_WRITE); |
| 1528 | +return; |
| 1529 | +} |
| 1530 | +pblkno=opaque->btpo_parent; |
| 1531 | +/* Call _bt_fixroot() if there is no upper level */ |
| 1532 | +if (pblkno==BTREE_METAPAGE) |
| 1533 | +{ |
| 1534 | +buf=_bt_fixroot(rel,buf, true); |
| 1535 | +_bt_relbuf(rel,buf,BT_WRITE); |
| 1536 | +return; |
| 1537 | +} |
| 1538 | +/* Have to go up one level */ |
| 1539 | +_bt_relbuf(rel,buf,BT_WRITE); |
| 1540 | +blkno=pblkno; |
| 1541 | +} |
| 1542 | +} |
| 1543 | + |
| 1544 | +} |
| 1545 | + |
| 1546 | +/* |
| 1547 | + * Check/fix level starting from page in buffer buf up to block |
| 1548 | + * limit on *child* level (or till rightmost child page if limit |
| 1549 | + * is InvalidBlockNumber). Start buffer must be read locked. |
| 1550 | + * No pins/locks are held on exit. Returns block number of last |
| 1551 | + * visited/pointing-to-limit page on *check/fix* level. |
| 1552 | + */ |
| 1553 | +staticBlockNumber |
| 1554 | +_bt_fixlevel(Relationrel,Bufferbuf,BlockNumberlimit) |
| 1555 | +{ |
| 1556 | +BlockNumberblkno=BufferGetBlockNumber(buf); |
| 1557 | +BlockNumberpblkno=blkno; |
| 1558 | +Pagepage; |
| 1559 | +BTPageOpaqueopaque; |
| 1560 | +BlockNumbercblkno[3]; |
| 1561 | +OffsetNumbercoff[3]; |
| 1562 | +Buffercbuf[3]; |
| 1563 | +Pagecpage[3]; |
| 1564 | +BTPageOpaquecopaque[3]; |
| 1565 | +BTItembtitem; |
| 1566 | +intcidx,i; |
| 1567 | +boolgoodbye= false; |
| 1568 | +chartbuf[BLCKSZ]; |
| 1569 | + |
| 1570 | +page=BufferGetPage(buf); |
| 1571 | +/* copy page to temp storage */ |
| 1572 | +memmove(tbuf,page,PageGetPageSize(page)); |
| 1573 | +_bt_relbuf(rel,buf,BT_READ); |
| 1574 | + |
| 1575 | +page= (Page)tbuf; |
| 1576 | +opaque= (BTPageOpaque)PageGetSpecialPointer(page); |
| 1577 | + |
| 1578 | +/* Initialize first child data */ |
| 1579 | +coff[0]=P_FIRSTDATAKEY(opaque); |
| 1580 | +if (coff[0]>PageGetMaxOffsetNumber(page)) |
| 1581 | +elog(ERROR,"bt_fixlevel: invalid maxoff on start page (need to recreate index)"); |
| 1582 | +btitem= (BTItem)PageGetItem(page,PageGetItemId(page,coff[0])); |
| 1583 | +cblkno[0]=ItemPointerGetBlockNumber(&(btitem->bti_itup.t_tid)); |
| 1584 | +cbuf[0]=_bt_getbuf(rel,cblkno[0],BT_READ); |
| 1585 | +cpage[0]=BufferGetPage(cbuf[0]); |
| 1586 | +copaque[0]= (BTPageOpaque)PageGetSpecialPointer(cpage[0]); |
| 1587 | +if (P_LEFTMOST(opaque)&& !P_LEFTMOST(copaque[0])) |
| 1588 | +elog(ERROR,"bt_fixtlevel: non-leftmost child page of leftmost parent (need to recreate index)"); |
| 1589 | +/* caller should take care and avoid this */ |
| 1590 | +if (P_RIGHTMOST(copaque[0])) |
| 1591 | +elog(ERROR,"bt_fixtlevel: invalid start child (need to recreate index)"); |
| 1592 | + |
| 1593 | +for ( ; ; ) |
| 1594 | +{ |
| 1595 | +/* |
| 1596 | + * Read up to 2 more child pages and look for pointers |
| 1597 | + * to them in *saved* parent page |
| 1598 | + */ |
| 1599 | +coff[1]=coff[2]=InvalidOffsetNumber; |
| 1600 | +for (cidx=0;cidx<2; ) |
| 1601 | +{ |
| 1602 | +cidx++; |
| 1603 | +cblkno[cidx]= (copaque[cidx-1])->btpo_next; |
| 1604 | +cbuf[cidx]=_bt_getbuf(rel,cblkno[cidx],BT_READ); |
| 1605 | +cpage[cidx]=BufferGetPage(cbuf[cidx]); |
| 1606 | +copaque[cidx]= (BTPageOpaque)PageGetSpecialPointer(cpage[cidx]); |
| 1607 | +coff[cidx]=_bt_getoff(page,cblkno[cidx]); |
| 1608 | + |
| 1609 | +/* sanity check */ |
| 1610 | +if (coff[cidx]!=InvalidOffsetNumber) |
| 1611 | +{ |
| 1612 | +for (i=cidx-1;i >=0;i--) |
| 1613 | +{ |
| 1614 | +if (coff[i]==InvalidOffsetNumber) |
| 1615 | +continue; |
| 1616 | +if (coff[cidx]!=coff[i]+1) |
| 1617 | +elog(ERROR,"bt_fixlevel: invalid item order(1) (need to recreate index)"); |
| 1618 | +break; |
| 1619 | +} |
| 1620 | +} |
| 1621 | + |
| 1622 | +if (P_RIGHTMOST(copaque[cidx])) |
| 1623 | +break; |
| 1624 | +} |
| 1625 | + |
| 1626 | +/* |
| 1627 | + * Read parent page and insert missed pointers. |
| 1628 | + */ |
| 1629 | +if (coff[1]==InvalidOffsetNumber|| |
| 1630 | +(cidx==2&&coff[2]==InvalidOffsetNumber)) |
| 1631 | +{ |
| 1632 | +Buffernewbuf; |
| 1633 | +Pagenewpage; |
| 1634 | +BTPageOpaquenewopaque; |
| 1635 | +BTItemritem; |
| 1636 | +Sizeitemsz; |
| 1637 | +OffsetNumbernewitemoff; |
| 1638 | +BlockNumberparblk[3]; |
| 1639 | +BTStackDatastack; |
| 1640 | + |
| 1641 | +stack.bts_parent=NULL; |
| 1642 | +stack.bts_blkno=pblkno; |
| 1643 | +stack.bts_offset=InvalidOffsetNumber; |
| 1644 | +ItemPointerSet(&(stack.bts_btitem.bti_itup.t_tid), |
| 1645 | +cblkno[0],P_HIKEY); |
| 1646 | + |
| 1647 | +buf=_bt_getstackbuf(rel,&stack); |
| 1648 | +if (buf==InvalidBuffer) |
| 1649 | +elog(ERROR,"bt_fixlevel: pointer disappeared (need to recreate index)"); |
| 1650 | + |
| 1651 | +page=BufferGetPage(buf); |
| 1652 | +opaque= (BTPageOpaque)PageGetSpecialPointer(page); |
| 1653 | +coff[0]=stack.bts_offset; |
| 1654 | +pblkno=BufferGetBlockNumber(buf); |
| 1655 | +parblk[0]=pblkno; |
| 1656 | +if (cblkno[0]==limit) |
| 1657 | +blkno=pblkno;/* where we have seen pointer to limit */ |
| 1658 | + |
| 1659 | +/* Check/insert missed pointers */ |
| 1660 | +for (i=1;i <=cidx;i++) |
| 1661 | +{ |
| 1662 | +coff[i]=_bt_getoff(page,cblkno[i]); |
| 1663 | + |
| 1664 | +/* sanity check */ |
| 1665 | +parblk[i]=BufferGetBlockNumber(buf); |
| 1666 | +if (coff[i]!=InvalidOffsetNumber) |
| 1667 | +{ |
| 1668 | +if (parblk[i]==parblk[i-1]&& |
| 1669 | +coff[i]!=coff[i-1]+1) |
| 1670 | +elog(ERROR,"bt_fixlevel: invalid item order(2) (need to recreate index)"); |
| 1671 | +if (cblkno[i]==limit) |
| 1672 | +blkno=parblk[i]; |
| 1673 | +continue; |
| 1674 | +} |
| 1675 | +/* Have to check next page ? */ |
| 1676 | +if ((!P_RIGHTMOST(opaque))&& |
| 1677 | +coff[i-1]==PageGetMaxOffsetNumber(page))/* yes */ |
| 1678 | +{ |
| 1679 | +newbuf=_bt_getbuf(rel,opaque->btpo_next,BT_WRITE); |
| 1680 | +newpage=BufferGetPage(newbuf); |
| 1681 | +newopaque= (BTPageOpaque)PageGetSpecialPointer(newpage); |
| 1682 | +coff[i]=_bt_getoff(newpage,cblkno[i]); |
| 1683 | +if (coff[i]!=InvalidOffsetNumber)/* found ! */ |
| 1684 | +{ |
| 1685 | +if (coff[i]!=P_FIRSTDATAKEY(newopaque)) |
| 1686 | +elog(ERROR,"bt_fixlevel: invalid item order(3) (need to recreate index)"); |
| 1687 | +_bt_relbuf(rel,buf,BT_WRITE); |
| 1688 | +buf=newbuf; |
| 1689 | +page=newpage; |
| 1690 | +opaque=newopaque; |
| 1691 | +pblkno=BufferGetBlockNumber(buf); |
| 1692 | +parblk[i]=pblkno; |
| 1693 | +if (cblkno[i]==limit) |
| 1694 | +blkno=pblkno; |
| 1695 | +continue; |
| 1696 | +} |
| 1697 | +/* unfound - need to insert on current page */ |
| 1698 | +_bt_relbuf(rel,newbuf,BT_WRITE); |
| 1699 | +} |
| 1700 | +/* insert pointer */ |
| 1701 | +ritem= (BTItem)PageGetItem(cpage[i-1], |
| 1702 | +PageGetItemId(cpage[i-1],P_HIKEY)); |
| 1703 | +btitem=_bt_formitem(&(ritem->bti_itup)); |
| 1704 | +ItemPointerSet(&(btitem->bti_itup.t_tid),cblkno[i],P_HIKEY); |
| 1705 | +itemsz=IndexTupleDSize(btitem->bti_itup) |
| 1706 | ++ (sizeof(BTItemData)-sizeof(IndexTupleData)); |
| 1707 | +itemsz=MAXALIGN(itemsz); |
| 1708 | + |
| 1709 | +newitemoff=coff[i-1]+1; |
| 1710 | + |
| 1711 | +if (PageGetFreeSpace(page)<itemsz) |
| 1712 | +{ |
| 1713 | +OffsetNumberfirstright; |
| 1714 | +OffsetNumberitup_off; |
| 1715 | +BlockNumberitup_blkno; |
| 1716 | +boolnewitemonleft; |
| 1717 | + |
| 1718 | +firstright=_bt_findsplitloc(rel,page, |
| 1719 | +newitemoff,itemsz,&newitemonleft); |
| 1720 | +newbuf=_bt_split(rel,buf,firstright, |
| 1721 | +newitemoff,itemsz,btitem,newitemonleft, |
| 1722 | +&itup_off,&itup_blkno); |
| 1723 | +/* what buffer we need in ? */ |
| 1724 | +if (newitemonleft) |
| 1725 | +_bt_relbuf(rel,newbuf,BT_WRITE); |
| 1726 | +else |
| 1727 | +{ |
| 1728 | +_bt_relbuf(rel,buf,BT_WRITE); |
| 1729 | +buf=newbuf; |
| 1730 | +page=BufferGetPage(buf); |
| 1731 | +opaque= (BTPageOpaque)PageGetSpecialPointer(page); |
| 1732 | +} |
| 1733 | +pblkno=BufferGetBlockNumber(buf); |
| 1734 | +coff[i]=itup_off; |
| 1735 | +} |
| 1736 | +else |
| 1737 | +{ |
| 1738 | +_bt_insertuple(rel,buf,itemsz,btitem,newitemoff); |
| 1739 | +coff[i]=newitemoff; |
| 1740 | +} |
| 1741 | + |
| 1742 | +pfree(btitem); |
| 1743 | +parblk[i]=pblkno; |
| 1744 | +if (cblkno[i]==limit) |
| 1745 | +blkno=pblkno; |
| 1746 | +} |
| 1747 | + |
| 1748 | +/* copy page with pointer to cblkno[cidx] to temp storage */ |
| 1749 | +memmove(tbuf,page,PageGetPageSize(page)); |
| 1750 | +_bt_relbuf(rel,buf,BT_WRITE); |
| 1751 | +page= (Page)tbuf; |
| 1752 | +opaque= (BTPageOpaque)PageGetSpecialPointer(page); |
| 1753 | +if (limit==InvalidBlockNumber) |
| 1754 | +blkno=pblkno;/* last visited page */ |
| 1755 | +} |
| 1756 | + |
| 1757 | +/* Continue if current check/fix level page is rightmost */ |
| 1758 | +if (P_RIGHTMOST(opaque)) |
| 1759 | +goodbye= false; |
| 1760 | + |
| 1761 | +/* Pointers to child pages are Ok - right end of child level ? */ |
| 1762 | +_bt_relbuf(rel,cbuf[0],BT_READ); |
| 1763 | +_bt_relbuf(rel,cbuf[1],BT_READ); |
| 1764 | +if (cidx==1|| |
| 1765 | +(cidx==2&& (P_RIGHTMOST(copaque[2])||goodbye))) |
| 1766 | +{ |
| 1767 | +if (cidx==2) |
| 1768 | +_bt_relbuf(rel,cbuf[2],BT_READ); |
| 1769 | +return(blkno); |
| 1770 | +} |
| 1771 | +if (cblkno[0]==limit||cblkno[1]==limit) |
| 1772 | +goodbye= true; |
| 1773 | +cblkno[0]=cblkno[2]; |
| 1774 | +cbuf[0]=cbuf[2]; |
| 1775 | +cpage[0]=cpage[2]; |
| 1776 | +copaque[0]=copaque[2]; |
| 1777 | +coff[0]=coff[2]; |
| 1778 | +} |
| 1779 | +} |
| 1780 | + |
| 1781 | +staticOffsetNumber |
| 1782 | +_bt_getoff(Pagepage,BlockNumberblkno) |
1482 | 1783 | {
|
1483 |
| -elog(ERROR,"bt_fixtree: unimplemented , yet"); |
| 1784 | +BTPageOpaqueopaque= (BTPageOpaque)PageGetSpecialPointer(page); |
| 1785 | +OffsetNumbermaxoff=PageGetMaxOffsetNumber(page); |
| 1786 | +OffsetNumberoffnum=P_FIRSTDATAKEY(opaque); |
| 1787 | +BlockNumbercurblkno; |
| 1788 | +ItemIditemid; |
| 1789 | +BTItemitem; |
| 1790 | + |
| 1791 | +for ( ;offnum <=maxoff;offnum++) |
| 1792 | +{ |
| 1793 | +itemid=PageGetItemId(page,offnum); |
| 1794 | +item= (BTItem)PageGetItem(page,itemid); |
| 1795 | +curblkno=ItemPointerGetBlockNumber(&(item->bti_itup.t_tid)); |
| 1796 | +if (curblkno==blkno) |
| 1797 | +return(offnum); |
| 1798 | +} |
| 1799 | + |
| 1800 | +return(InvalidOffsetNumber); |
1484 | 1801 | }
|
1485 | 1802 |
|
1486 | 1803 | /*
|
|