Annotation of embedaddon/php/ext/sqlite/libsqlite/src/btree_rb.c, revision 1.1.1.1

1.1       misho       1: /*
                      2: ** 2003 Feb 4
                      3: **
                      4: ** The author disclaims copyright to this source code.  In place of
                      5: ** a legal notice, here is a blessing:
                      6: **
                      7: **    May you do good and not evil.
                      8: **    May you find forgiveness for yourself and forgive others.
                      9: **    May you share freely, never taking more than you give.
                     10: **
                     11: *************************************************************************
                     12: ** $Id: btree_rb.c 195361 2005-09-07 15:11:33Z iliaa $
                     13: **
                     14: ** This file implements an in-core database using Red-Black balanced
                     15: ** binary trees.
                     16: ** 
                     17: ** It was contributed to SQLite by anonymous on 2003-Feb-04 23:24:49 UTC.
                     18: */
                     19: #include "btree.h"
                     20: #include "sqliteInt.h"
                     21: #include <assert.h>
                     22: 
                     23: /*
                     24: ** Omit this whole file if the SQLITE_OMIT_INMEMORYDB macro is
                     25: ** defined.  This allows a lot of code to be omitted for installations
                     26: ** that do not need it.
                     27: */
                     28: #ifndef SQLITE_OMIT_INMEMORYDB
                     29: 
                     30: 
                     31: typedef struct BtRbTree BtRbTree;
                     32: typedef struct BtRbNode BtRbNode;
                     33: typedef struct BtRollbackOp BtRollbackOp;
                     34: typedef struct Rbtree Rbtree;
                     35: typedef struct RbtCursor RbtCursor;
                     36: 
                     37: /* Forward declarations */
                     38: static BtOps sqliteRbtreeOps;
                     39: static BtCursorOps sqliteRbtreeCursorOps;
                     40: 
                     41: /*
                     42:  * During each transaction (or checkpoint), a linked-list of
                     43:  * "rollback-operations" is accumulated. If the transaction is rolled back,
                     44:  * then the list of operations must be executed (to restore the database to
                     45:  * it's state before the transaction started). If the transaction is to be
                     46:  * committed, just delete the list.
                     47:  *
                     48:  * Each operation is represented as follows, depending on the value of eOp:
                     49:  *
                     50:  * ROLLBACK_INSERT  ->  Need to insert (pKey, pData) into table iTab.
                     51:  * ROLLBACK_DELETE  ->  Need to delete the record (pKey) into table iTab.
                     52:  * ROLLBACK_CREATE  ->  Need to create table iTab.
                     53:  * ROLLBACK_DROP    ->  Need to drop table iTab.
                     54:  */
                     55: struct BtRollbackOp {
                     56:   u8 eOp;
                     57:   int iTab;
                     58:   int nKey; 
                     59:   void *pKey;
                     60:   int nData;
                     61:   void *pData;
                     62:   BtRollbackOp *pNext;
                     63: };
                     64: 
                     65: /*
                     66: ** Legal values for BtRollbackOp.eOp:
                     67: */
                     68: #define ROLLBACK_INSERT 1 /* Insert a record */
                     69: #define ROLLBACK_DELETE 2 /* Delete a record */
                     70: #define ROLLBACK_CREATE 3 /* Create a table */
                     71: #define ROLLBACK_DROP   4 /* Drop a table */
                     72: 
                     73: struct Rbtree {
                     74:   BtOps *pOps;    /* Function table */
                     75:   int aMetaData[SQLITE_N_BTREE_META];
                     76: 
                     77:   int next_idx;   /* next available table index */
                     78:   Hash tblHash;   /* All created tables, by index */
                     79:   u8 isAnonymous; /* True if this Rbtree is to be deleted when closed */
                     80:   u8 eTransState; /* State of this Rbtree wrt transactions */
                     81: 
                     82:   BtRollbackOp *pTransRollback; 
                     83:   BtRollbackOp *pCheckRollback;
                     84:   BtRollbackOp *pCheckRollbackTail;
                     85: };
                     86: 
                     87: /*
                     88: ** Legal values for Rbtree.eTransState.
                     89: */
                     90: #define TRANS_NONE           0  /* No transaction is in progress */
                     91: #define TRANS_INTRANSACTION  1  /* A transaction is in progress */
                     92: #define TRANS_INCHECKPOINT   2  /* A checkpoint is in progress  */
                     93: #define TRANS_ROLLBACK       3  /* We are currently rolling back a checkpoint or
                     94:                                  * transaction. */
                     95: 
                     96: struct RbtCursor {
                     97:   BtCursorOps *pOps;        /* Function table */
                     98:   Rbtree    *pRbtree;
                     99:   BtRbTree *pTree;
                    100:   int       iTree;          /* Index of pTree in pRbtree */
                    101:   BtRbNode *pNode;
                    102:   RbtCursor *pShared;       /* List of all cursors on the same Rbtree */
                    103:   u8 eSkip;                 /* Determines if next step operation is a no-op */
                    104:   u8 wrFlag;                /* True if this cursor is open for writing */
                    105: };
                    106: 
                    107: /*
                    108: ** Legal values for RbtCursor.eSkip.
                    109: */
                    110: #define SKIP_NONE     0   /* Always step the cursor */
                    111: #define SKIP_NEXT     1   /* The next sqliteRbtreeNext() is a no-op */
                    112: #define SKIP_PREV     2   /* The next sqliteRbtreePrevious() is a no-op */
                    113: #define SKIP_INVALID  3   /* Calls to Next() and Previous() are invalid */
                    114: 
                    115: struct BtRbTree {
                    116:   RbtCursor *pCursors;     /* All cursors pointing to this tree */
                    117:   BtRbNode *pHead;         /* Head of the tree, or NULL */
                    118: };
                    119: 
                    120: struct BtRbNode {
                    121:   int nKey;
                    122:   void *pKey;
                    123:   int nData;
                    124:   void *pData;
                    125:   u8 isBlack;        /* true for a black node, 0 for a red node */
                    126:   BtRbNode *pParent; /* Nodes parent node, NULL for the tree head */
                    127:   BtRbNode *pLeft;   /* Nodes left child, or NULL */
                    128:   BtRbNode *pRight;  /* Nodes right child, or NULL */
                    129: 
                    130:   int nBlackHeight;  /* Only used during the red-black integrity check */
                    131: };
                    132: 
                    133: /* Forward declarations */
                    134: static int memRbtreeMoveto(
                    135:   RbtCursor* pCur,
                    136:   const void *pKey,
                    137:   int nKey,
                    138:   int *pRes
                    139: );
                    140: static int memRbtreeClearTable(Rbtree* tree, int n);
                    141: static int memRbtreeNext(RbtCursor* pCur, int *pRes);
                    142: static int memRbtreeLast(RbtCursor* pCur, int *pRes);
                    143: static int memRbtreePrevious(RbtCursor* pCur, int *pRes);
                    144: 
                    145: 
                    146: /*
                    147: ** This routine checks all cursors that point to the same table
                    148: ** as pCur points to.  If any of those cursors were opened with
                    149: ** wrFlag==0 then this routine returns SQLITE_LOCKED.  If all
                    150: ** cursors point to the same table were opened with wrFlag==1
                    151: ** then this routine returns SQLITE_OK.
                    152: **
                    153: ** In addition to checking for read-locks (where a read-lock 
                    154: ** means a cursor opened with wrFlag==0) this routine also NULLs
                    155: ** out the pNode field of all other cursors.
                    156: ** This is necessary because an insert 
                    157: ** or delete might change erase the node out from under
                    158: ** another cursor.
                    159: */
                    160: static int checkReadLocks(RbtCursor *pCur){
                    161:   RbtCursor *p;
                    162:   assert( pCur->wrFlag );
                    163:   for(p=pCur->pTree->pCursors; p; p=p->pShared){
                    164:     if( p!=pCur ){
                    165:       if( p->wrFlag==0 ) return SQLITE_LOCKED;
                    166:       p->pNode = 0;
                    167:     }
                    168:   }
                    169:   return SQLITE_OK;
                    170: }
                    171: 
                    172: /*
                    173:  * The key-compare function for the red-black trees. Returns as follows:
                    174:  *
                    175:  * (key1 < key2)             -1
                    176:  * (key1 == key2)             0 
                    177:  * (key1 > key2)              1
                    178:  *
                    179:  * Keys are compared using memcmp(). If one key is an exact prefix of the
                    180:  * other, then the shorter key is less than the longer key.
                    181:  */
                    182: static int key_compare(void const*pKey1, int nKey1, void const*pKey2, int nKey2)
                    183: {
                    184:   int mcmp = memcmp(pKey1, pKey2, (nKey1 <= nKey2)?nKey1:nKey2);
                    185:   if( mcmp == 0){
                    186:     if( nKey1 == nKey2 ) return 0;
                    187:     return ((nKey1 < nKey2)?-1:1);
                    188:   }
                    189:   return ((mcmp>0)?1:-1);
                    190: }
                    191: 
                    192: /*
                    193:  * Perform the LEFT-rotate transformation on node X of tree pTree. This
                    194:  * transform is part of the red-black balancing code.
                    195:  *
                    196:  *        |                   |
                    197:  *        X                   Y
                    198:  *       / \                 / \
                    199:  *      a   Y               X   c
                    200:  *         / \             / \
                    201:  *        b   c           a   b
                    202:  *
                    203:  *      BEFORE              AFTER
                    204:  */
                    205: static void leftRotate(BtRbTree *pTree, BtRbNode *pX)
                    206: {
                    207:   BtRbNode *pY;
                    208:   BtRbNode *pb;
                    209:   pY = pX->pRight;
                    210:   pb = pY->pLeft;
                    211: 
                    212:   pY->pParent = pX->pParent;
                    213:   if( pX->pParent ){
                    214:     if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
                    215:     else pX->pParent->pRight = pY;
                    216:   }
                    217:   pY->pLeft = pX;
                    218:   pX->pParent = pY;
                    219:   pX->pRight = pb;
                    220:   if( pb ) pb->pParent = pX;
                    221:   if( pTree->pHead == pX ) pTree->pHead = pY;
                    222: }
                    223: 
                    224: /*
                    225:  * Perform the RIGHT-rotate transformation on node X of tree pTree. This
                    226:  * transform is part of the red-black balancing code.
                    227:  *
                    228:  *        |                   |
                    229:  *        X                   Y
                    230:  *       / \                 / \
                    231:  *      Y   c               a   X
                    232:  *     / \                     / \
                    233:  *    a   b                   b   c
                    234:  *
                    235:  *      BEFORE              AFTER
                    236:  */
                    237: static void rightRotate(BtRbTree *pTree, BtRbNode *pX)
                    238: {
                    239:   BtRbNode *pY;
                    240:   BtRbNode *pb;
                    241:   pY = pX->pLeft;
                    242:   pb = pY->pRight;
                    243: 
                    244:   pY->pParent = pX->pParent;
                    245:   if( pX->pParent ){
                    246:     if( pX->pParent->pLeft == pX ) pX->pParent->pLeft = pY;
                    247:     else pX->pParent->pRight = pY;
                    248:   }
                    249:   pY->pRight = pX;
                    250:   pX->pParent = pY;
                    251:   pX->pLeft = pb;
                    252:   if( pb ) pb->pParent = pX;
                    253:   if( pTree->pHead == pX ) pTree->pHead = pY;
                    254: }
                    255: 
                    256: /*
                    257:  * A string-manipulation helper function for check_redblack_tree(). If (orig ==
                    258:  * NULL) a copy of val is returned. If (orig != NULL) then a copy of the *
                    259:  * concatenation of orig and val is returned. The original orig is deleted
                    260:  * (using sqliteFree()).
                    261:  */
                    262: static char *append_val(char * orig, char const * val){
                    263:   char *z;
                    264:   if( !orig ){
                    265:     z = sqliteStrDup( val );
                    266:   } else{
                    267:     z = 0;
                    268:     sqliteSetString(&z, orig, val, (char*)0);
                    269:     sqliteFree( orig );
                    270:   }
                    271:   return z;
                    272: }
                    273: 
                    274: /*
                    275:  * Append a string representation of the entire node to orig and return it.
                    276:  * This is used to produce debugging information if check_redblack_tree() finds
                    277:  * a problem with a red-black binary tree.
                    278:  */
                    279: static char *append_node(char * orig, BtRbNode *pNode, int indent)
                    280: {
                    281:   char buf[128];
                    282:   int i;
                    283: 
                    284:   for( i=0; i<indent; i++ ){
                    285:       orig = append_val(orig, " ");
                    286:   }
                    287: 
                    288:   sprintf(buf, "%p", pNode);
                    289:   orig = append_val(orig, buf);
                    290: 
                    291:   if( pNode ){
                    292:     indent += 3;
                    293:     if( pNode->isBlack ){
                    294:       orig = append_val(orig, " B \n");
                    295:     }else{
                    296:       orig = append_val(orig, " R \n");
                    297:     }
                    298:     orig = append_node( orig, pNode->pLeft, indent );
                    299:     orig = append_node( orig, pNode->pRight, indent );
                    300:   }else{
                    301:     orig = append_val(orig, "\n");
                    302:   }
                    303:   return orig;
                    304: }
                    305: 
                    306: /*
                    307:  * Print a representation of a node to stdout. This function is only included
                    308:  * so you can call it from within a debugger if things get really bad.  It
                    309:  * is not called from anyplace in the code.
                    310:  */
                    311: static void print_node(BtRbNode *pNode)
                    312: {
                    313:     char * str = append_node(0, pNode, 0);
                    314:     printf("%s", str);
                    315: 
                    316:     /* Suppress a warning message about print_node() being unused */
                    317:     (void)print_node;
                    318: }
                    319: 
                    320: /* 
                    321:  * Check the following properties of the red-black tree:
                    322:  * (1) - If a node is red, both of it's children are black
                    323:  * (2) - Each path from a given node to a leaf (NULL) node passes thru the
                    324:  *       same number of black nodes 
                    325:  *
                    326:  * If there is a problem, append a description (using append_val() ) to *msg.
                    327:  */
                    328: static void check_redblack_tree(BtRbTree * tree, char ** msg)
                    329: {
                    330:   BtRbNode *pNode;
                    331: 
                    332:   /* 0 -> came from parent 
                    333:    * 1 -> came from left
                    334:    * 2 -> came from right */
                    335:   int prev_step = 0;
                    336: 
                    337:   pNode = tree->pHead;
                    338:   while( pNode ){
                    339:     switch( prev_step ){
                    340:       case 0:
                    341:         if( pNode->pLeft ){
                    342:           pNode = pNode->pLeft;
                    343:         }else{ 
                    344:           prev_step = 1;
                    345:         }
                    346:         break;
                    347:       case 1:
                    348:         if( pNode->pRight ){
                    349:           pNode = pNode->pRight;
                    350:           prev_step = 0;
                    351:         }else{
                    352:           prev_step = 2;
                    353:         }
                    354:         break;
                    355:       case 2:
                    356:         /* Check red-black property (1) */
                    357:         if( !pNode->isBlack &&
                    358:             ( (pNode->pLeft && !pNode->pLeft->isBlack) ||
                    359:               (pNode->pRight && !pNode->pRight->isBlack) )
                    360:           ){
                    361:           char buf[128];
                    362:           sprintf(buf, "Red node with red child at %p\n", pNode);
                    363:           *msg = append_val(*msg, buf);
                    364:           *msg = append_node(*msg, tree->pHead, 0);
                    365:           *msg = append_val(*msg, "\n");
                    366:         }
                    367: 
                    368:         /* Check red-black property (2) */
                    369:         { 
                    370:           int leftHeight = 0;
                    371:           int rightHeight = 0;
                    372:           if( pNode->pLeft ){
                    373:             leftHeight += pNode->pLeft->nBlackHeight;
                    374:             leftHeight += (pNode->pLeft->isBlack?1:0);
                    375:           }
                    376:           if( pNode->pRight ){
                    377:             rightHeight += pNode->pRight->nBlackHeight;
                    378:             rightHeight += (pNode->pRight->isBlack?1:0);
                    379:           }
                    380:           if( leftHeight != rightHeight ){
                    381:             char buf[128];
                    382:             sprintf(buf, "Different black-heights at %p\n", pNode);
                    383:             *msg = append_val(*msg, buf);
                    384:             *msg = append_node(*msg, tree->pHead, 0);
                    385:             *msg = append_val(*msg, "\n");
                    386:           }
                    387:           pNode->nBlackHeight = leftHeight;
                    388:         }
                    389: 
                    390:         if( pNode->pParent ){
                    391:           if( pNode == pNode->pParent->pLeft ) prev_step = 1;
                    392:           else prev_step = 2;
                    393:         }
                    394:         pNode = pNode->pParent;
                    395:         break;
                    396:       default: assert(0);
                    397:     }
                    398:   }
                    399: } 
                    400: 
                    401: /*
                    402:  * Node pX has just been inserted into pTree (by code in sqliteRbtreeInsert()).
                    403:  * It is possible that pX is a red node with a red parent, which is a violation
                    404:  * of the red-black tree properties. This function performs rotations and 
                    405:  * color changes to rebalance the tree
                    406:  */
                    407: static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX)
                    408: {
                    409:   /* In the first iteration of this loop, pX points to the red node just
                    410:    * inserted in the tree. If the parent of pX exists (pX is not the root
                    411:    * node) and is red, then the properties of the red-black tree are
                    412:    * violated.
                    413:    *
                    414:    * At the start of any subsequent iterations, pX points to a red node
                    415:    * with a red parent. In all other respects the tree is a legal red-black
                    416:    * binary tree. */
                    417:   while( pX != pTree->pHead && !pX->pParent->isBlack ){
                    418:     BtRbNode *pUncle;
                    419:     BtRbNode *pGrandparent;
                    420: 
                    421:     /* Grandparent of pX must exist and must be black. */
                    422:     pGrandparent = pX->pParent->pParent;
                    423:     assert( pGrandparent );
                    424:     assert( pGrandparent->isBlack );
                    425: 
                    426:     /* Uncle of pX may or may not exist. */
                    427:     if( pX->pParent == pGrandparent->pLeft ) 
                    428:       pUncle = pGrandparent->pRight;
                    429:     else 
                    430:       pUncle = pGrandparent->pLeft;
                    431: 
                    432:     /* If the uncle of pX exists and is red, we do the following:
                    433:      *       |                 |
                    434:      *      G(b)              G(r)
                    435:      *      /  \              /  \        
                    436:      *   U(r)   P(r)       U(b)  P(b)
                    437:      *            \                \
                    438:      *           X(r)              X(r)
                    439:      *
                    440:      *     BEFORE             AFTER
                    441:      * pX is then set to G. If the parent of G is red, then the while loop
                    442:      * will run again.  */
                    443:     if( pUncle && !pUncle->isBlack ){
                    444:       pGrandparent->isBlack = 0;
                    445:       pUncle->isBlack = 1;
                    446:       pX->pParent->isBlack = 1;
                    447:       pX = pGrandparent;
                    448:     }else{
                    449: 
                    450:       if( pX->pParent == pGrandparent->pLeft ){
                    451:         if( pX == pX->pParent->pRight ){
                    452:           /* If pX is a right-child, do the following transform, essentially
                    453:            * to change pX into a left-child: 
                    454:            *       |                  | 
                    455:            *      G(b)               G(b)
                    456:            *      /  \               /  \        
                    457:            *   P(r)   U(b)        X(r)  U(b)
                    458:            *      \                /
                    459:            *     X(r)            P(r) <-- new X
                    460:            *
                    461:            *     BEFORE             AFTER
                    462:            */
                    463:           pX = pX->pParent;
                    464:           leftRotate(pTree, pX);
                    465:         }
                    466: 
                    467:         /* Do the following transform, which balances the tree :) 
                    468:          *       |                  | 
                    469:          *      G(b)               P(b)
                    470:          *      /  \               /  \        
                    471:          *   P(r)   U(b)        X(r)  G(r)
                    472:          *    /                         \
                    473:          *  X(r)                        U(b)
                    474:          *
                    475:          *     BEFORE             AFTER
                    476:          */
                    477:         assert( pGrandparent == pX->pParent->pParent );
                    478:         pGrandparent->isBlack = 0;
                    479:         pX->pParent->isBlack = 1;
                    480:         rightRotate( pTree, pGrandparent );
                    481: 
                    482:       }else{
                    483:         /* This code is symetric to the illustrated case above. */
                    484:         if( pX == pX->pParent->pLeft ){
                    485:           pX = pX->pParent;
                    486:           rightRotate(pTree, pX);
                    487:         }
                    488:         assert( pGrandparent == pX->pParent->pParent );
                    489:         pGrandparent->isBlack = 0;
                    490:         pX->pParent->isBlack = 1;
                    491:         leftRotate( pTree, pGrandparent );
                    492:       }
                    493:     }
                    494:   }
                    495:   pTree->pHead->isBlack = 1;
                    496: }
                    497: 
                    498: /*
                    499:  * A child of pParent, which in turn had child pX, has just been removed from 
                    500:  * pTree (the figure below depicts the operation, Z is being removed). pParent
                    501:  * or pX, or both may be NULL.  
                    502:  *                |           |
                    503:  *                P           P
                    504:  *               / \         / \
                    505:  *              Z           X
                    506:  *             / \
                    507:  *            X  nil
                    508:  *
                    509:  * This function is only called if Z was black. In this case the red-black tree
                    510:  * properties have been violated, and pX has an "extra black". This function 
                    511:  * performs rotations and color-changes to re-balance the tree.
                    512:  */
                    513: static 
                    514: void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent)
                    515: {
                    516:   BtRbNode *pSib; 
                    517: 
                    518:   /* TODO: Comment this code! */
                    519:   while( pX != pTree->pHead && (!pX || pX->isBlack) ){
                    520:     if( pX == pParent->pLeft ){
                    521:       pSib = pParent->pRight;
                    522:       if( pSib && !(pSib->isBlack) ){
                    523:         pSib->isBlack = 1;
                    524:         pParent->isBlack = 0;
                    525:         leftRotate(pTree, pParent);
                    526:         pSib = pParent->pRight;
                    527:       }
                    528:       if( !pSib ){
                    529:         pX = pParent;
                    530:       }else if( 
                    531:           (!pSib->pLeft  || pSib->pLeft->isBlack) &&
                    532:           (!pSib->pRight || pSib->pRight->isBlack) ) {
                    533:         pSib->isBlack = 0;
                    534:         pX = pParent;
                    535:       }else{
                    536:         if( (!pSib->pRight || pSib->pRight->isBlack) ){
                    537:           if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
                    538:           pSib->isBlack = 0;
                    539:           rightRotate( pTree, pSib );
                    540:           pSib = pParent->pRight;
                    541:         }
                    542:         pSib->isBlack = pParent->isBlack;
                    543:         pParent->isBlack = 1;
                    544:         if( pSib->pRight ) pSib->pRight->isBlack = 1;
                    545:         leftRotate(pTree, pParent);
                    546:         pX = pTree->pHead;
                    547:       }
                    548:     }else{
                    549:       pSib = pParent->pLeft;
                    550:       if( pSib && !(pSib->isBlack) ){
                    551:         pSib->isBlack = 1;
                    552:         pParent->isBlack = 0;
                    553:         rightRotate(pTree, pParent);
                    554:         pSib = pParent->pLeft;
                    555:       }
                    556:       if( !pSib ){
                    557:         pX = pParent;
                    558:       }else if( 
                    559:           (!pSib->pLeft  || pSib->pLeft->isBlack) &&
                    560:           (!pSib->pRight || pSib->pRight->isBlack) ){
                    561:         pSib->isBlack = 0;
                    562:         pX = pParent;
                    563:       }else{
                    564:         if( (!pSib->pLeft || pSib->pLeft->isBlack) ){
                    565:           if( pSib->pRight ) pSib->pRight->isBlack = 1;
                    566:           pSib->isBlack = 0;
                    567:           leftRotate( pTree, pSib );
                    568:           pSib = pParent->pLeft;
                    569:         }
                    570:         pSib->isBlack = pParent->isBlack;
                    571:         pParent->isBlack = 1;
                    572:         if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
                    573:         rightRotate(pTree, pParent);
                    574:         pX = pTree->pHead;
                    575:       }
                    576:     }
                    577:     pParent = pX->pParent;
                    578:   }
                    579:   if( pX ) pX->isBlack = 1;
                    580: }
                    581: 
                    582: /*
                    583:  * Create table n in tree pRbtree. Table n must not exist.
                    584:  */
                    585: static void btreeCreateTable(Rbtree* pRbtree, int n)
                    586: {
                    587:   BtRbTree *pNewTbl = sqliteMalloc(sizeof(BtRbTree));
                    588:   sqliteHashInsert(&pRbtree->tblHash, 0, n, pNewTbl);
                    589: }
                    590: 
                    591: /*
                    592:  * Log a single "rollback-op" for the given Rbtree. See comments for struct
                    593:  * BtRollbackOp.
                    594:  */
                    595: static void btreeLogRollbackOp(Rbtree* pRbtree, BtRollbackOp *pRollbackOp)
                    596: {
                    597:   assert( pRbtree->eTransState == TRANS_INCHECKPOINT ||
                    598:       pRbtree->eTransState == TRANS_INTRANSACTION );
                    599:   if( pRbtree->eTransState == TRANS_INTRANSACTION ){
                    600:     pRollbackOp->pNext = pRbtree->pTransRollback;
                    601:     pRbtree->pTransRollback = pRollbackOp;
                    602:   }
                    603:   if( pRbtree->eTransState == TRANS_INCHECKPOINT ){
                    604:     if( !pRbtree->pCheckRollback ){
                    605:       pRbtree->pCheckRollbackTail = pRollbackOp;
                    606:     }
                    607:     pRollbackOp->pNext = pRbtree->pCheckRollback;
                    608:     pRbtree->pCheckRollback = pRollbackOp;
                    609:   }
                    610: }
                    611: 
                    612: int sqliteRbtreeOpen(
                    613:   const char *zFilename,
                    614:   int mode,
                    615:   int nPg,
                    616:   Btree **ppBtree
                    617: ){
                    618:   Rbtree **ppRbtree = (Rbtree**)ppBtree;
                    619:   *ppRbtree = (Rbtree *)sqliteMalloc(sizeof(Rbtree));
                    620:   if( sqlite_malloc_failed ) goto open_no_mem;
                    621:   sqliteHashInit(&(*ppRbtree)->tblHash, SQLITE_HASH_INT, 0);
                    622: 
                    623:   /* Create a binary tree for the SQLITE_MASTER table at location 2 */
                    624:   btreeCreateTable(*ppRbtree, 2);
                    625:   if( sqlite_malloc_failed ) goto open_no_mem;
                    626:   (*ppRbtree)->next_idx = 3;
                    627:   (*ppRbtree)->pOps = &sqliteRbtreeOps;
                    628:   /* Set file type to 4; this is so that "attach ':memory:' as ...."  does not
                    629:   ** think that the database in uninitialised and refuse to attach
                    630:   */
                    631:   (*ppRbtree)->aMetaData[2] = 4;
                    632:   
                    633:   return SQLITE_OK;
                    634: 
                    635: open_no_mem:
                    636:   *ppBtree = 0;
                    637:   return SQLITE_NOMEM;
                    638: }
                    639: 
                    640: /*
                    641:  * Create a new table in the supplied Rbtree. Set *n to the new table number.
                    642:  * Return SQLITE_OK if the operation is a success.
                    643:  */
                    644: static int memRbtreeCreateTable(Rbtree* tree, int* n)
                    645: {
                    646:   assert( tree->eTransState != TRANS_NONE );
                    647: 
                    648:   *n = tree->next_idx++;
                    649:   btreeCreateTable(tree, *n);
                    650:   if( sqlite_malloc_failed ) return SQLITE_NOMEM;
                    651: 
                    652:   /* Set up the rollback structure (if we are not doing this as part of a
                    653:    * rollback) */
                    654:   if( tree->eTransState != TRANS_ROLLBACK ){
                    655:     BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
                    656:     if( pRollbackOp==0 ) return SQLITE_NOMEM;
                    657:     pRollbackOp->eOp = ROLLBACK_DROP;
                    658:     pRollbackOp->iTab = *n;
                    659:     btreeLogRollbackOp(tree, pRollbackOp);
                    660:   }
                    661: 
                    662:   return SQLITE_OK;
                    663: }
                    664: 
                    665: /*
                    666:  * Delete table n from the supplied Rbtree. 
                    667:  */
                    668: static int memRbtreeDropTable(Rbtree* tree, int n)
                    669: {
                    670:   BtRbTree *pTree;
                    671:   assert( tree->eTransState != TRANS_NONE );
                    672: 
                    673:   memRbtreeClearTable(tree, n);
                    674:   pTree = sqliteHashInsert(&tree->tblHash, 0, n, 0);
                    675:   assert(pTree);
                    676:   assert( pTree->pCursors==0 );
                    677:   sqliteFree(pTree);
                    678: 
                    679:   if( tree->eTransState != TRANS_ROLLBACK ){
                    680:     BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
                    681:     if( pRollbackOp==0 ) return SQLITE_NOMEM;
                    682:     pRollbackOp->eOp = ROLLBACK_CREATE;
                    683:     pRollbackOp->iTab = n;
                    684:     btreeLogRollbackOp(tree, pRollbackOp);
                    685:   }
                    686: 
                    687:   return SQLITE_OK;
                    688: }
                    689: 
                    690: static int memRbtreeKeyCompare(RbtCursor* pCur, const void *pKey, int nKey,
                    691:                                  int nIgnore, int *pRes)
                    692: {
                    693:   assert(pCur);
                    694: 
                    695:   if( !pCur->pNode ) {
                    696:     *pRes = -1;
                    697:   } else {
                    698:     if( (pCur->pNode->nKey - nIgnore) < 0 ){
                    699:       *pRes = -1;
                    700:     }else{
                    701:       *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey-nIgnore, 
                    702:           pKey, nKey);
                    703:     }
                    704:   }
                    705:   return SQLITE_OK;
                    706: }
                    707: 
                    708: /*
                    709:  * Get a new cursor for table iTable of the supplied Rbtree. The wrFlag
                    710:  * parameter indicates that the cursor is open for writing.
                    711:  *
                    712:  * Note that RbtCursor.eSkip and RbtCursor.pNode both initialize to 0.
                    713:  */
                    714: static int memRbtreeCursor(
                    715:   Rbtree* tree,
                    716:   int iTable,
                    717:   int wrFlag,
                    718:   RbtCursor **ppCur
                    719: ){
                    720:   RbtCursor *pCur;
                    721:   assert(tree);
                    722:   pCur = *ppCur = sqliteMalloc(sizeof(RbtCursor));
                    723:   if( sqlite_malloc_failed ) return SQLITE_NOMEM;
                    724:   pCur->pTree  = sqliteHashFind(&tree->tblHash, 0, iTable);
                    725:   assert( pCur->pTree );
                    726:   pCur->pRbtree = tree;
                    727:   pCur->iTree  = iTable;
                    728:   pCur->pOps = &sqliteRbtreeCursorOps;
                    729:   pCur->wrFlag = wrFlag;
                    730:   pCur->pShared = pCur->pTree->pCursors;
                    731:   pCur->pTree->pCursors = pCur;
                    732: 
                    733:   assert( (*ppCur)->pTree );
                    734:   return SQLITE_OK;
                    735: }
                    736: 
                    737: /*
                    738:  * Insert a new record into the Rbtree.  The key is given by (pKey,nKey)
                    739:  * and the data is given by (pData,nData).  The cursor is used only to
                    740:  * define what database the record should be inserted into.  The cursor
                    741:  * is left pointing at the new record.
                    742:  *
                    743:  * If the key exists already in the tree, just replace the data. 
                    744:  */
                    745: static int memRbtreeInsert(
                    746:   RbtCursor* pCur,
                    747:   const void *pKey,
                    748:   int nKey,
                    749:   const void *pDataInput,
                    750:   int nData
                    751: ){
                    752:   void * pData;
                    753:   int match;
                    754: 
                    755:   /* It is illegal to call sqliteRbtreeInsert() if we are
                    756:   ** not in a transaction */
                    757:   assert( pCur->pRbtree->eTransState != TRANS_NONE );
                    758: 
                    759:   /* Make sure some other cursor isn't trying to read this same table */
                    760:   if( checkReadLocks(pCur) ){
                    761:     return SQLITE_LOCKED; /* The table pCur points to has a read lock */
                    762:   }
                    763: 
                    764:   /* Take a copy of the input data now, in case we need it for the 
                    765:    * replace case */
                    766:   pData = sqliteMallocRaw(nData);
                    767:   if( sqlite_malloc_failed ) return SQLITE_NOMEM;
                    768:   memcpy(pData, pDataInput, nData);
                    769: 
                    770:   /* Move the cursor to a node near the key to be inserted. If the key already
                    771:    * exists in the table, then (match == 0). In this case we can just replace
                    772:    * the data associated with the entry, we don't need to manipulate the tree.
                    773:    * 
                    774:    * If there is no exact match, then the cursor points at what would be either
                    775:    * the predecessor (match == -1) or successor (match == 1) of the
                    776:    * searched-for key, were it to be inserted. The new node becomes a child of
                    777:    * this node.
                    778:    * 
                    779:    * The new node is initially red.
                    780:    */
                    781:   memRbtreeMoveto( pCur, pKey, nKey, &match);
                    782:   if( match ){
                    783:     BtRbNode *pNode = sqliteMalloc(sizeof(BtRbNode));
                    784:     if( pNode==0 ) return SQLITE_NOMEM;
                    785:     pNode->nKey = nKey;
                    786:     pNode->pKey = sqliteMallocRaw(nKey);
                    787:     if( sqlite_malloc_failed ) return SQLITE_NOMEM;
                    788:     memcpy(pNode->pKey, pKey, nKey);
                    789:     pNode->nData = nData;
                    790:     pNode->pData = pData; 
                    791:     if( pCur->pNode ){
                    792:       switch( match ){
                    793:         case -1:
                    794:           assert( !pCur->pNode->pRight );
                    795:           pNode->pParent = pCur->pNode;
                    796:           pCur->pNode->pRight = pNode;
                    797:           break;
                    798:         case 1:
                    799:           assert( !pCur->pNode->pLeft );
                    800:           pNode->pParent = pCur->pNode;
                    801:           pCur->pNode->pLeft = pNode;
                    802:           break;
                    803:         default:
                    804:           assert(0);
                    805:       }
                    806:     }else{
                    807:       pCur->pTree->pHead = pNode;
                    808:     }
                    809: 
                    810:     /* Point the cursor at the node just inserted, as per SQLite requirements */
                    811:     pCur->pNode = pNode;
                    812: 
                    813:     /* A new node has just been inserted, so run the balancing code */
                    814:     do_insert_balancing(pCur->pTree, pNode);
                    815: 
                    816:     /* Set up a rollback-op in case we have to roll this operation back */
                    817:     if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
                    818:       BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
                    819:       if( pOp==0 ) return SQLITE_NOMEM;
                    820:       pOp->eOp = ROLLBACK_DELETE;
                    821:       pOp->iTab = pCur->iTree;
                    822:       pOp->nKey = pNode->nKey;
                    823:       pOp->pKey = sqliteMallocRaw( pOp->nKey );
                    824:       if( sqlite_malloc_failed ) return SQLITE_NOMEM;
                    825:       memcpy( pOp->pKey, pNode->pKey, pOp->nKey );
                    826:       btreeLogRollbackOp(pCur->pRbtree, pOp);
                    827:     }
                    828: 
                    829:   }else{ 
                    830:     /* No need to insert a new node in the tree, as the key already exists.
                    831:      * Just clobber the current nodes data. */
                    832: 
                    833:     /* Set up a rollback-op in case we have to roll this operation back */
                    834:     if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
                    835:       BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
                    836:       if( pOp==0 ) return SQLITE_NOMEM;
                    837:       pOp->iTab = pCur->iTree;
                    838:       pOp->nKey = pCur->pNode->nKey;
                    839:       pOp->pKey = sqliteMallocRaw( pOp->nKey );
                    840:       if( sqlite_malloc_failed ) return SQLITE_NOMEM;
                    841:       memcpy( pOp->pKey, pCur->pNode->pKey, pOp->nKey );
                    842:       pOp->nData = pCur->pNode->nData;
                    843:       pOp->pData = pCur->pNode->pData;
                    844:       pOp->eOp = ROLLBACK_INSERT;
                    845:       btreeLogRollbackOp(pCur->pRbtree, pOp);
                    846:     }else{
                    847:       sqliteFree( pCur->pNode->pData );
                    848:     }
                    849: 
                    850:     /* Actually clobber the nodes data */
                    851:     pCur->pNode->pData = pData;
                    852:     pCur->pNode->nData = nData;
                    853:   }
                    854: 
                    855:   return SQLITE_OK;
                    856: }
                    857: 
                    858: /* Move the cursor so that it points to an entry near pKey.
                    859: ** Return a success code.
                    860: **
                    861: **     *pRes<0      The cursor is left pointing at an entry that
                    862: **                  is smaller than pKey or if the table is empty
                    863: **                  and the cursor is therefore left point to nothing.
                    864: **
                    865: **     *pRes==0     The cursor is left pointing at an entry that
                    866: **                  exactly matches pKey.
                    867: **
                    868: **     *pRes>0      The cursor is left pointing at an entry that
                    869: **                  is larger than pKey.
                    870: */
                    871: static int memRbtreeMoveto(
                    872:   RbtCursor* pCur,
                    873:   const void *pKey,
                    874:   int nKey,
                    875:   int *pRes
                    876: ){
                    877:   BtRbNode *pTmp = 0;
                    878: 
                    879:   pCur->pNode = pCur->pTree->pHead;
                    880:   *pRes = -1;
                    881:   while( pCur->pNode && *pRes ) {
                    882:     *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey, pKey, nKey);
                    883:     pTmp = pCur->pNode;
                    884:     switch( *pRes ){
                    885:       case 1:    /* cursor > key */
                    886:         pCur->pNode = pCur->pNode->pLeft;
                    887:         break;
                    888:       case -1:   /* cursor < key */
                    889:         pCur->pNode = pCur->pNode->pRight;
                    890:         break;
                    891:     }
                    892:   } 
                    893: 
                    894:   /* If (pCur->pNode == NULL), then we have failed to find a match. Set
                    895:    * pCur->pNode to pTmp, which is either NULL (if the tree is empty) or the
                    896:    * last node traversed in the search. In either case the relation ship
                    897:    * between pTmp and the searched for key is already stored in *pRes. pTmp is
                    898:    * either the successor or predecessor of the key we tried to move to. */
                    899:   if( !pCur->pNode ) pCur->pNode = pTmp;
                    900:   pCur->eSkip = SKIP_NONE;
                    901: 
                    902:   return SQLITE_OK;
                    903: }
                    904: 
                    905: 
                    906: /*
                    907: ** Delete the entry that the cursor is pointing to.
                    908: **
                    909: ** The cursor is left pointing at either the next or the previous
                    910: ** entry.  If the cursor is left pointing to the next entry, then 
                    911: ** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to 
                    912: ** sqliteRbtreeNext() to be a no-op.  That way, you can always call
                    913: ** sqliteRbtreeNext() after a delete and the cursor will be left
                    914: ** pointing to the first entry after the deleted entry.  Similarly,
                    915: ** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to
                    916: ** the entry prior to the deleted entry so that a subsequent call to
                    917: ** sqliteRbtreePrevious() will always leave the cursor pointing at the
                    918: ** entry immediately before the one that was deleted.
                    919: */
                    920: static int memRbtreeDelete(RbtCursor* pCur)
                    921: {
                    922:   BtRbNode *pZ;      /* The one being deleted */
                    923:   BtRbNode *pChild;  /* The child of the spliced out node */
                    924: 
                    925:   /* It is illegal to call sqliteRbtreeDelete() if we are
                    926:   ** not in a transaction */
                    927:   assert( pCur->pRbtree->eTransState != TRANS_NONE );
                    928: 
                    929:   /* Make sure some other cursor isn't trying to read this same table */
                    930:   if( checkReadLocks(pCur) ){
                    931:     return SQLITE_LOCKED; /* The table pCur points to has a read lock */
                    932:   }
                    933: 
                    934:   pZ = pCur->pNode;
                    935:   if( !pZ ){
                    936:     return SQLITE_OK;
                    937:   }
                    938: 
                    939:   /* If we are not currently doing a rollback, set up a rollback op for this 
                    940:    * deletion */
                    941:   if( pCur->pRbtree->eTransState != TRANS_ROLLBACK ){
                    942:     BtRollbackOp *pOp = sqliteMalloc( sizeof(BtRollbackOp) );
                    943:     if( pOp==0 ) return SQLITE_NOMEM;
                    944:     pOp->iTab = pCur->iTree;
                    945:     pOp->nKey = pZ->nKey;
                    946:     pOp->pKey = pZ->pKey;
                    947:     pOp->nData = pZ->nData;
                    948:     pOp->pData = pZ->pData;
                    949:     pOp->eOp = ROLLBACK_INSERT;
                    950:     btreeLogRollbackOp(pCur->pRbtree, pOp);
                    951:   }
                    952: 
                    953:   /* First do a standard binary-tree delete (node pZ is to be deleted). How
                    954:    * to do this depends on how many children pZ has:
                    955:    *
                    956:    * If pZ has no children or one child, then splice out pZ.  If pZ has two
                    957:    * children, splice out the successor of pZ and replace the key and data of
                    958:    * pZ with the key and data of the spliced out successor.  */
                    959:   if( pZ->pLeft && pZ->pRight ){
                    960:     BtRbNode *pTmp;
                    961:     int dummy;
                    962:     pCur->eSkip = SKIP_NONE;
                    963:     memRbtreeNext(pCur, &dummy);
                    964:     assert( dummy == 0 );
                    965:     if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
                    966:       sqliteFree(pZ->pKey);
                    967:       sqliteFree(pZ->pData);
                    968:     }
                    969:     pZ->pData = pCur->pNode->pData;
                    970:     pZ->nData = pCur->pNode->nData;
                    971:     pZ->pKey = pCur->pNode->pKey;
                    972:     pZ->nKey = pCur->pNode->nKey;
                    973:     pTmp = pZ;
                    974:     pZ = pCur->pNode;
                    975:     pCur->pNode = pTmp;
                    976:     pCur->eSkip = SKIP_NEXT;
                    977:   }else{
                    978:     int res;
                    979:     pCur->eSkip = SKIP_NONE;
                    980:     memRbtreeNext(pCur, &res);
                    981:     pCur->eSkip = SKIP_NEXT;
                    982:     if( res ){
                    983:       memRbtreeLast(pCur, &res);
                    984:       memRbtreePrevious(pCur, &res);
                    985:       pCur->eSkip = SKIP_PREV;
                    986:     }
                    987:     if( pCur->pRbtree->eTransState == TRANS_ROLLBACK ){
                    988:         sqliteFree(pZ->pKey);
                    989:         sqliteFree(pZ->pData);
                    990:     }
                    991:   }
                    992: 
                    993:   /* pZ now points at the node to be spliced out. This block does the 
                    994:    * splicing. */
                    995:   {
                    996:     BtRbNode **ppParentSlot = 0;
                    997:     assert( !pZ->pLeft || !pZ->pRight ); /* pZ has at most one child */
                    998:     pChild = ((pZ->pLeft)?pZ->pLeft:pZ->pRight);
                    999:     if( pZ->pParent ){
                   1000:       assert( pZ == pZ->pParent->pLeft || pZ == pZ->pParent->pRight );
                   1001:       ppParentSlot = ((pZ == pZ->pParent->pLeft)
                   1002:           ?&pZ->pParent->pLeft:&pZ->pParent->pRight);
                   1003:       *ppParentSlot = pChild;
                   1004:     }else{
                   1005:       pCur->pTree->pHead = pChild;
                   1006:     }
                   1007:     if( pChild ) pChild->pParent = pZ->pParent;
                   1008:   }
                   1009: 
                   1010:   /* pZ now points at the spliced out node. pChild is the only child of pZ, or
                   1011:    * NULL if pZ has no children. If pZ is black, and not the tree root, then we
                   1012:    * will have violated the "same number of black nodes in every path to a
                   1013:    * leaf" property of the red-black tree. The code in do_delete_balancing()
                   1014:    * repairs this. */
                   1015:   if( pZ->isBlack ){ 
                   1016:     do_delete_balancing(pCur->pTree, pChild, pZ->pParent);
                   1017:   }
                   1018: 
                   1019:   sqliteFree(pZ);
                   1020:   return SQLITE_OK;
                   1021: }
                   1022: 
                   1023: /*
                   1024:  * Empty table n of the Rbtree.
                   1025:  */
                   1026: static int memRbtreeClearTable(Rbtree* tree, int n)
                   1027: {
                   1028:   BtRbTree *pTree;
                   1029:   BtRbNode *pNode;
                   1030: 
                   1031:   pTree = sqliteHashFind(&tree->tblHash, 0, n);
                   1032:   assert(pTree);
                   1033: 
                   1034:   pNode = pTree->pHead;
                   1035:   while( pNode ){
                   1036:     if( pNode->pLeft ){
                   1037:       pNode = pNode->pLeft;
                   1038:     }
                   1039:     else if( pNode->pRight ){
                   1040:       pNode = pNode->pRight;
                   1041:     }
                   1042:     else {
                   1043:       BtRbNode *pTmp = pNode->pParent;
                   1044:       if( tree->eTransState == TRANS_ROLLBACK ){
                   1045:         sqliteFree( pNode->pKey );
                   1046:         sqliteFree( pNode->pData );
                   1047:       }else{
                   1048:         BtRollbackOp *pRollbackOp = sqliteMallocRaw(sizeof(BtRollbackOp));
                   1049:         if( pRollbackOp==0 ) return SQLITE_NOMEM;
                   1050:         pRollbackOp->eOp = ROLLBACK_INSERT;
                   1051:         pRollbackOp->iTab = n;
                   1052:         pRollbackOp->nKey = pNode->nKey;
                   1053:         pRollbackOp->pKey = pNode->pKey;
                   1054:         pRollbackOp->nData = pNode->nData;
                   1055:         pRollbackOp->pData = pNode->pData;
                   1056:         btreeLogRollbackOp(tree, pRollbackOp);
                   1057:       }
                   1058:       sqliteFree( pNode );
                   1059:       if( pTmp ){
                   1060:         if( pTmp->pLeft == pNode ) pTmp->pLeft = 0;
                   1061:         else if( pTmp->pRight == pNode ) pTmp->pRight = 0;
                   1062:       }
                   1063:       pNode = pTmp;
                   1064:     }
                   1065:   }
                   1066: 
                   1067:   pTree->pHead = 0;
                   1068:   return SQLITE_OK;
                   1069: }
                   1070: 
                   1071: static int memRbtreeFirst(RbtCursor* pCur, int *pRes)
                   1072: {
                   1073:   if( pCur->pTree->pHead ){
                   1074:     pCur->pNode = pCur->pTree->pHead;
                   1075:     while( pCur->pNode->pLeft ){
                   1076:       pCur->pNode = pCur->pNode->pLeft;
                   1077:     }
                   1078:   }
                   1079:   if( pCur->pNode ){
                   1080:     *pRes = 0;
                   1081:   }else{
                   1082:     *pRes = 1;
                   1083:   }
                   1084:   pCur->eSkip = SKIP_NONE;
                   1085:   return SQLITE_OK;
                   1086: }
                   1087: 
                   1088: static int memRbtreeLast(RbtCursor* pCur, int *pRes)
                   1089: {
                   1090:   if( pCur->pTree->pHead ){
                   1091:     pCur->pNode = pCur->pTree->pHead;
                   1092:     while( pCur->pNode->pRight ){
                   1093:       pCur->pNode = pCur->pNode->pRight;
                   1094:     }
                   1095:   }
                   1096:   if( pCur->pNode ){
                   1097:     *pRes = 0;
                   1098:   }else{
                   1099:     *pRes = 1;
                   1100:   }
                   1101:   pCur->eSkip = SKIP_NONE;
                   1102:   return SQLITE_OK;
                   1103: }
                   1104: 
                   1105: /*
                   1106: ** Advance the cursor to the next entry in the database.  If
                   1107: ** successful then set *pRes=0.  If the cursor
                   1108: ** was already pointing to the last entry in the database before
                   1109: ** this routine was called, then set *pRes=1.
                   1110: */
                   1111: static int memRbtreeNext(RbtCursor* pCur, int *pRes)
                   1112: {
                   1113:   if( pCur->pNode && pCur->eSkip != SKIP_NEXT ){
                   1114:     if( pCur->pNode->pRight ){
                   1115:       pCur->pNode = pCur->pNode->pRight;
                   1116:       while( pCur->pNode->pLeft )
                   1117:         pCur->pNode = pCur->pNode->pLeft;
                   1118:     }else{
                   1119:       BtRbNode * pX = pCur->pNode;
                   1120:       pCur->pNode = pX->pParent;
                   1121:       while( pCur->pNode && (pCur->pNode->pRight == pX) ){
                   1122:         pX = pCur->pNode;
                   1123:         pCur->pNode = pX->pParent;
                   1124:       }
                   1125:     }
                   1126:   }
                   1127:   pCur->eSkip = SKIP_NONE;
                   1128: 
                   1129:   if( !pCur->pNode ){
                   1130:     *pRes = 1;
                   1131:   }else{
                   1132:     *pRes = 0;
                   1133:   }
                   1134: 
                   1135:   return SQLITE_OK;
                   1136: }
                   1137: 
                   1138: static int memRbtreePrevious(RbtCursor* pCur, int *pRes)
                   1139: {
                   1140:   if( pCur->pNode && pCur->eSkip != SKIP_PREV ){
                   1141:     if( pCur->pNode->pLeft ){
                   1142:       pCur->pNode = pCur->pNode->pLeft;
                   1143:       while( pCur->pNode->pRight )
                   1144:         pCur->pNode = pCur->pNode->pRight;
                   1145:     }else{
                   1146:       BtRbNode * pX = pCur->pNode;
                   1147:       pCur->pNode = pX->pParent;
                   1148:       while( pCur->pNode && (pCur->pNode->pLeft == pX) ){
                   1149:         pX = pCur->pNode;
                   1150:         pCur->pNode = pX->pParent;
                   1151:       }
                   1152:     }
                   1153:   }
                   1154:   pCur->eSkip = SKIP_NONE;
                   1155: 
                   1156:   if( !pCur->pNode ){
                   1157:     *pRes = 1;
                   1158:   }else{
                   1159:     *pRes = 0;
                   1160:   }
                   1161: 
                   1162:   return SQLITE_OK;
                   1163: }
                   1164: 
                   1165: static int memRbtreeKeySize(RbtCursor* pCur, int *pSize)
                   1166: {
                   1167:   if( pCur->pNode ){
                   1168:     *pSize = pCur->pNode->nKey;
                   1169:   }else{
                   1170:     *pSize = 0;
                   1171:   }
                   1172:   return SQLITE_OK;
                   1173: }
                   1174: 
                   1175: static int memRbtreeKey(RbtCursor* pCur, int offset, int amt, char *zBuf)
                   1176: {
                   1177:   if( !pCur->pNode ) return 0;
                   1178:   if( !pCur->pNode->pKey || ((amt + offset) <= pCur->pNode->nKey) ){
                   1179:     memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, amt);
                   1180:   }else{
                   1181:     memcpy(zBuf, ((char*)pCur->pNode->pKey)+offset, pCur->pNode->nKey-offset);
                   1182:     amt = pCur->pNode->nKey-offset;
                   1183:   }
                   1184:   return amt;
                   1185: }
                   1186: 
                   1187: static int memRbtreeDataSize(RbtCursor* pCur, int *pSize)
                   1188: {
                   1189:   if( pCur->pNode ){
                   1190:     *pSize = pCur->pNode->nData;
                   1191:   }else{
                   1192:     *pSize = 0;
                   1193:   }
                   1194:   return SQLITE_OK;
                   1195: }
                   1196: 
                   1197: static int memRbtreeData(RbtCursor *pCur, int offset, int amt, char *zBuf)
                   1198: {
                   1199:   if( !pCur->pNode ) return 0;
                   1200:   if( (amt + offset) <= pCur->pNode->nData ){
                   1201:     memcpy(zBuf, ((char*)pCur->pNode->pData)+offset, amt);
                   1202:   }else{
                   1203:     memcpy(zBuf, ((char*)pCur->pNode->pData)+offset ,pCur->pNode->nData-offset);
                   1204:     amt = pCur->pNode->nData-offset;
                   1205:   }
                   1206:   return amt;
                   1207: }
                   1208: 
                   1209: static int memRbtreeCloseCursor(RbtCursor* pCur)
                   1210: {
                   1211:   if( pCur->pTree->pCursors==pCur ){
                   1212:     pCur->pTree->pCursors = pCur->pShared;
                   1213:   }else{
                   1214:     RbtCursor *p = pCur->pTree->pCursors;
                   1215:     while( p && p->pShared!=pCur ){ p = p->pShared; }
                   1216:     assert( p!=0 );
                   1217:     if( p ){
                   1218:       p->pShared = pCur->pShared;
                   1219:     }
                   1220:   }
                   1221:   sqliteFree(pCur);
                   1222:   return SQLITE_OK;
                   1223: }
                   1224: 
                   1225: static int memRbtreeGetMeta(Rbtree* tree, int* aMeta)
                   1226: {
                   1227:   memcpy( aMeta, tree->aMetaData, sizeof(int) * SQLITE_N_BTREE_META );
                   1228:   return SQLITE_OK;
                   1229: }
                   1230: 
                   1231: static int memRbtreeUpdateMeta(Rbtree* tree, int* aMeta)
                   1232: {
                   1233:   memcpy( tree->aMetaData, aMeta, sizeof(int) * SQLITE_N_BTREE_META );
                   1234:   return SQLITE_OK;
                   1235: }
                   1236: 
                   1237: /*
                   1238:  * Check that each table in the Rbtree meets the requirements for a red-black
                   1239:  * binary tree. If an error is found, return an explanation of the problem in 
                   1240:  * memory obtained from sqliteMalloc(). Parameters aRoot and nRoot are ignored. 
                   1241:  */
                   1242: static char *memRbtreeIntegrityCheck(Rbtree* tree, int* aRoot, int nRoot)
                   1243: {
                   1244:   char * msg = 0;
                   1245:   HashElem *p;
                   1246: 
                   1247:   for(p=sqliteHashFirst(&tree->tblHash); p; p=sqliteHashNext(p)){
                   1248:     BtRbTree *pTree = sqliteHashData(p);
                   1249:     check_redblack_tree(pTree, &msg);
                   1250:   }
                   1251: 
                   1252:   return msg;
                   1253: }
                   1254: 
                   1255: static int memRbtreeSetCacheSize(Rbtree* tree, int sz)
                   1256: {
                   1257:   return SQLITE_OK;
                   1258: }
                   1259: 
                   1260: static int memRbtreeSetSafetyLevel(Rbtree *pBt, int level){
                   1261:   return SQLITE_OK;
                   1262: }
                   1263: 
                   1264: static int memRbtreeBeginTrans(Rbtree* tree)
                   1265: {
                   1266:   if( tree->eTransState != TRANS_NONE ) 
                   1267:     return SQLITE_ERROR;
                   1268: 
                   1269:   assert( tree->pTransRollback == 0 );
                   1270:   tree->eTransState = TRANS_INTRANSACTION;
                   1271:   return SQLITE_OK;
                   1272: }
                   1273: 
                   1274: /*
                   1275: ** Delete a linked list of BtRollbackOp structures.
                   1276: */
                   1277: static void deleteRollbackList(BtRollbackOp *pOp){
                   1278:   while( pOp ){
                   1279:     BtRollbackOp *pTmp = pOp->pNext;
                   1280:     sqliteFree(pOp->pData);
                   1281:     sqliteFree(pOp->pKey);
                   1282:     sqliteFree(pOp);
                   1283:     pOp = pTmp;
                   1284:   }
                   1285: }
                   1286: 
                   1287: static int memRbtreeCommit(Rbtree* tree){
                   1288:   /* Just delete pTransRollback and pCheckRollback */
                   1289:   deleteRollbackList(tree->pCheckRollback);
                   1290:   deleteRollbackList(tree->pTransRollback);
                   1291:   tree->pTransRollback = 0;
                   1292:   tree->pCheckRollback = 0;
                   1293:   tree->pCheckRollbackTail = 0;
                   1294:   tree->eTransState = TRANS_NONE;
                   1295:   return SQLITE_OK;
                   1296: }
                   1297: 
                   1298: /*
                   1299:  * Close the supplied Rbtree. Delete everything associated with it.
                   1300:  */
                   1301: static int memRbtreeClose(Rbtree* tree)
                   1302: {
                   1303:   HashElem *p;
                   1304:   memRbtreeCommit(tree);
                   1305:   while( (p=sqliteHashFirst(&tree->tblHash))!=0 ){
                   1306:     tree->eTransState = TRANS_ROLLBACK;
                   1307:     memRbtreeDropTable(tree, sqliteHashKeysize(p));
                   1308:   }
                   1309:   sqliteHashClear(&tree->tblHash);
                   1310:   sqliteFree(tree);
                   1311:   return SQLITE_OK;
                   1312: }
                   1313: 
                   1314: /*
                   1315:  * Execute and delete the supplied rollback-list on pRbtree.
                   1316:  */
                   1317: static void execute_rollback_list(Rbtree *pRbtree, BtRollbackOp *pList)
                   1318: {
                   1319:   BtRollbackOp *pTmp;
                   1320:   RbtCursor cur;
                   1321:   int res;
                   1322: 
                   1323:   cur.pRbtree = pRbtree;
                   1324:   cur.wrFlag = 1;
                   1325:   while( pList ){
                   1326:     switch( pList->eOp ){
                   1327:       case ROLLBACK_INSERT:
                   1328:         cur.pTree  = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
                   1329:         assert(cur.pTree);
                   1330:         cur.iTree  = pList->iTab;
                   1331:         cur.eSkip  = SKIP_NONE;
                   1332:         memRbtreeInsert( &cur, pList->pKey,
                   1333:             pList->nKey, pList->pData, pList->nData );
                   1334:         break;
                   1335:       case ROLLBACK_DELETE:
                   1336:         cur.pTree  = sqliteHashFind( &pRbtree->tblHash, 0, pList->iTab );
                   1337:         assert(cur.pTree);
                   1338:         cur.iTree  = pList->iTab;
                   1339:         cur.eSkip  = SKIP_NONE;
                   1340:         memRbtreeMoveto(&cur, pList->pKey, pList->nKey, &res);
                   1341:         assert(res == 0);
                   1342:         memRbtreeDelete( &cur );
                   1343:         break;
                   1344:       case ROLLBACK_CREATE:
                   1345:         btreeCreateTable(pRbtree, pList->iTab);
                   1346:         break;
                   1347:       case ROLLBACK_DROP:
                   1348:         memRbtreeDropTable(pRbtree, pList->iTab);
                   1349:         break;
                   1350:       default:
                   1351:         assert(0);
                   1352:     }
                   1353:     sqliteFree(pList->pKey);
                   1354:     sqliteFree(pList->pData);
                   1355:     pTmp = pList->pNext;
                   1356:     sqliteFree(pList);
                   1357:     pList = pTmp;
                   1358:   }
                   1359: }
                   1360: 
                   1361: static int memRbtreeRollback(Rbtree* tree)
                   1362: {
                   1363:   tree->eTransState = TRANS_ROLLBACK;
                   1364:   execute_rollback_list(tree, tree->pCheckRollback);
                   1365:   execute_rollback_list(tree, tree->pTransRollback);
                   1366:   tree->pTransRollback = 0;
                   1367:   tree->pCheckRollback = 0;
                   1368:   tree->pCheckRollbackTail = 0;
                   1369:   tree->eTransState = TRANS_NONE;
                   1370:   return SQLITE_OK;
                   1371: }
                   1372: 
                   1373: static int memRbtreeBeginCkpt(Rbtree* tree)
                   1374: {
                   1375:   if( tree->eTransState != TRANS_INTRANSACTION ) 
                   1376:     return SQLITE_ERROR;
                   1377: 
                   1378:   assert( tree->pCheckRollback == 0 );
                   1379:   assert( tree->pCheckRollbackTail == 0 );
                   1380:   tree->eTransState = TRANS_INCHECKPOINT;
                   1381:   return SQLITE_OK;
                   1382: }
                   1383: 
                   1384: static int memRbtreeCommitCkpt(Rbtree* tree)
                   1385: {
                   1386:   if( tree->eTransState == TRANS_INCHECKPOINT ){ 
                   1387:     if( tree->pCheckRollback ){
                   1388:       tree->pCheckRollbackTail->pNext = tree->pTransRollback;
                   1389:       tree->pTransRollback = tree->pCheckRollback;
                   1390:       tree->pCheckRollback = 0;
                   1391:       tree->pCheckRollbackTail = 0;
                   1392:     }
                   1393:     tree->eTransState = TRANS_INTRANSACTION;
                   1394:   }
                   1395:   return SQLITE_OK;
                   1396: }
                   1397: 
                   1398: static int memRbtreeRollbackCkpt(Rbtree* tree)
                   1399: {
                   1400:   if( tree->eTransState != TRANS_INCHECKPOINT ) return SQLITE_OK;
                   1401:   tree->eTransState = TRANS_ROLLBACK;
                   1402:   execute_rollback_list(tree, tree->pCheckRollback);
                   1403:   tree->pCheckRollback = 0;
                   1404:   tree->pCheckRollbackTail = 0;
                   1405:   tree->eTransState = TRANS_INTRANSACTION;
                   1406:   return SQLITE_OK;
                   1407: }
                   1408: 
                   1409: #ifdef SQLITE_TEST
                   1410: static int memRbtreePageDump(Rbtree* tree, int pgno, int rec)
                   1411: {
                   1412:   assert(!"Cannot call sqliteRbtreePageDump");
                   1413:   return SQLITE_OK;
                   1414: }
                   1415: 
                   1416: static int memRbtreeCursorDump(RbtCursor* pCur, int* aRes)
                   1417: {
                   1418:   assert(!"Cannot call sqliteRbtreeCursorDump");
                   1419:   return SQLITE_OK;
                   1420: }
                   1421: #endif
                   1422: 
                   1423: static struct Pager *memRbtreePager(Rbtree* tree)
                   1424: {
                   1425:   return 0;
                   1426: }
                   1427: 
                   1428: /*
                   1429: ** Return the full pathname of the underlying database file.
                   1430: */
                   1431: static const char *memRbtreeGetFilename(Rbtree *pBt){
                   1432:   return 0;  /* A NULL return indicates there is no underlying file */
                   1433: }
                   1434: 
                   1435: /*
                   1436: ** The copy file function is not implemented for the in-memory database
                   1437: */
                   1438: static int memRbtreeCopyFile(Rbtree *pBt, Rbtree *pBt2){
                   1439:   return SQLITE_INTERNAL;  /* Not implemented */
                   1440: }
                   1441: 
                   1442: static BtOps sqliteRbtreeOps = {
                   1443:     (int(*)(Btree*)) memRbtreeClose,
                   1444:     (int(*)(Btree*,int)) memRbtreeSetCacheSize,
                   1445:     (int(*)(Btree*,int)) memRbtreeSetSafetyLevel,
                   1446:     (int(*)(Btree*)) memRbtreeBeginTrans,
                   1447:     (int(*)(Btree*)) memRbtreeCommit,
                   1448:     (int(*)(Btree*)) memRbtreeRollback,
                   1449:     (int(*)(Btree*)) memRbtreeBeginCkpt,
                   1450:     (int(*)(Btree*)) memRbtreeCommitCkpt,
                   1451:     (int(*)(Btree*)) memRbtreeRollbackCkpt,
                   1452:     (int(*)(Btree*,int*)) memRbtreeCreateTable,
                   1453:     (int(*)(Btree*,int*)) memRbtreeCreateTable,
                   1454:     (int(*)(Btree*,int)) memRbtreeDropTable,
                   1455:     (int(*)(Btree*,int)) memRbtreeClearTable,
                   1456:     (int(*)(Btree*,int,int,BtCursor**)) memRbtreeCursor,
                   1457:     (int(*)(Btree*,int*)) memRbtreeGetMeta,
                   1458:     (int(*)(Btree*,int*)) memRbtreeUpdateMeta,
                   1459:     (char*(*)(Btree*,int*,int)) memRbtreeIntegrityCheck,
                   1460:     (const char*(*)(Btree*)) memRbtreeGetFilename,
                   1461:     (int(*)(Btree*,Btree*)) memRbtreeCopyFile,
                   1462:     (struct Pager*(*)(Btree*)) memRbtreePager,
                   1463: #ifdef SQLITE_TEST
                   1464:     (int(*)(Btree*,int,int)) memRbtreePageDump,
                   1465: #endif
                   1466: };
                   1467: 
                   1468: static BtCursorOps sqliteRbtreeCursorOps = {
                   1469:     (int(*)(BtCursor*,const void*,int,int*)) memRbtreeMoveto,
                   1470:     (int(*)(BtCursor*)) memRbtreeDelete,
                   1471:     (int(*)(BtCursor*,const void*,int,const void*,int)) memRbtreeInsert,
                   1472:     (int(*)(BtCursor*,int*)) memRbtreeFirst,
                   1473:     (int(*)(BtCursor*,int*)) memRbtreeLast,
                   1474:     (int(*)(BtCursor*,int*)) memRbtreeNext,
                   1475:     (int(*)(BtCursor*,int*)) memRbtreePrevious,
                   1476:     (int(*)(BtCursor*,int*)) memRbtreeKeySize,
                   1477:     (int(*)(BtCursor*,int,int,char*)) memRbtreeKey,
                   1478:     (int(*)(BtCursor*,const void*,int,int,int*)) memRbtreeKeyCompare,
                   1479:     (int(*)(BtCursor*,int*)) memRbtreeDataSize,
                   1480:     (int(*)(BtCursor*,int,int,char*)) memRbtreeData,
                   1481:     (int(*)(BtCursor*)) memRbtreeCloseCursor,
                   1482: #ifdef SQLITE_TEST
                   1483:     (int(*)(BtCursor*,int*)) memRbtreeCursorDump,
                   1484: #endif
                   1485: 
                   1486: };
                   1487: 
                   1488: #endif /* SQLITE_OMIT_INMEMORYDB */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>