]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
fix a memory leak in btree_rb.c. (CVS 918)
authordrh <drh@noemail.net>
Fri, 18 Apr 2003 22:52:38 +0000 (22:52 +0000)
committerdrh <drh@noemail.net>
Fri, 18 Apr 2003 22:52:38 +0000 (22:52 +0000)
FossilOrigin-Name: 1e3d0d094776c2a429fa2a3eebc036a0b6374862

manifest
manifest.uuid
src/btree_rb.c

index fbe09502d8cf44a9e720f0956cf63ff31105e0ac..de4d25111cb698c7835f61085be66ae60636b2c3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sfor\sticket\s#297\s-\sbug\sin\ssqliteSortCompare().\s(CVS\s917)
-D 2003-04-18T17:45:14
+C fix\sa\smemory\sleak\sin\sbtree_rb.c.\s(CVS\s918)
+D 2003-04-18T22:52:39
 F Makefile.in df3a4db41a7450468b5fe934d9dd8f723b631249
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -23,7 +23,7 @@ F src/attach.c 7ebc7487de43e357a64226f8abef81f2669f2183
 F src/auth.c 2dd558dba4d8ffbed25fe1644e9af242f389f3e9
 F src/btree.c b9487cceb9ea78af9cbae9def34114902f511736
 F src/btree.h 529c98cb0715c62214544fbbe50b946f99a85540
-F src/btree_rb.c 7fa4901a65de66522ce31985833f20b98f7baad4
+F src/btree_rb.c b14803c84dc1c8fb51f5db1542237b7b7d411957
 F src/build.c 6694013c86c4c480754f515ddab561302c6e732a
 F src/copy.c 8699e571994934c78f70761a1458d7b9e9e75073
 F src/delete.c af65b26d9d13abbf63fdc4e97b88d26c700b04bb
@@ -162,7 +162,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be
 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 6e948d9aaea109c683ac4fcc4714e335b545d22b
-R d350172ce34cbf799885ede2eb5043c7
+P 4ded1965eb83dee0f28c27ba935d615c77331571
+R 2320d7d2beaa3603b04f97d8f781e745
 U drh
-Z a203462f3c9a0a6b91b58e9eba1fc107
+Z b76abd0e65d7599880199d2a9894cd84
index 73d465c469bdcc6e6c573d54777a0394b343fd71..19a9f9b981df335bda224216ceb55263aa65b5ac 100644 (file)
@@ -1 +1 @@
-4ded1965eb83dee0f28c27ba935d615c77331571
\ No newline at end of file
+1e3d0d094776c2a429fa2a3eebc036a0b6374862
\ No newline at end of file
index de11f9bbfa53f865f3ac5ce7c5a2ee17742afe1b..5804288dee9bd2b6f5014bd941d7e072da8ad4d3 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree_rb.c,v 1.3 2003/04/16 01:28:16 drh Exp $
+** $Id: btree_rb.c,v 1.4 2003/04/18 22:52:39 drh Exp $
 **
 ** This file implements an in-core database using Red-Black balanced
 ** binary trees.
@@ -69,7 +69,7 @@ struct BtRollbackOp {
 #define ROLLBACK_DROP   4 /* Drop a table */
 
 struct Btree {
-  BtOps *pOps;   /* Function table */
+  BtOps *pOps;    /* Function table */
   int aMetaData[SQLITE_N_BTREE_META];
 
   int next_idx;   /* next available table index */
@@ -89,10 +89,10 @@ struct Btree {
 #define TRANS_INTRANSACTION  1  /* A transaction is in progress */
 #define TRANS_INCHECKPOINT   2  /* A checkpoint is in progress  */
 #define TRANS_ROLLBACK       3  /* We are currently rolling back a checkpoint or
-                                * transaction. */
+                                 * transaction. */
 
 struct BtCursor {
-  BtCursorOps *pOps;       /* Function table */
+  BtCursorOps *pOps;        /* Function table */
   Btree    *pBtree;
   BtRbTree *pTree;
   int       iTree;          /* Index of pTree in pBtree */
@@ -298,61 +298,61 @@ static void check_redblack_tree(BtRbTree * tree, char ** msg)
   while( pNode ){
     switch( prev_step ){
       case 0:
-       if( pNode->pLeft ){
-         pNode = pNode->pLeft;
-       }else{ 
-         prev_step = 1;
-       }
-       break;
+        if( pNode->pLeft ){
+          pNode = pNode->pLeft;
+        }else{ 
+          prev_step = 1;
+        }
+        break;
       case 1:
-       if( pNode->pRight ){
-         pNode = pNode->pRight;
-         prev_step = 0;
-       }else{
-         prev_step = 2;
-       }
-       break;
+        if( pNode->pRight ){
+          pNode = pNode->pRight;
+          prev_step = 0;
+        }else{
+          prev_step = 2;
+        }
+        break;
       case 2:
-       /* Check red-black property (1) */
-       if( !pNode->isBlack &&
-           ( (pNode->pLeft && !pNode->pLeft->isBlack) ||
-             (pNode->pRight && !pNode->pRight->isBlack) )
-         ){
-         char buf[128];
-         sprintf(buf, "Red node with red child at %p\n", pNode);
-         *msg = append_val(*msg, buf);
-         *msg = append_node(*msg, tree->pHead, 0);
-         *msg = append_val(*msg, "\n");
-       }
-
-       /* Check red-black property (2) */
-       { 
-         int leftHeight = 0;
-         int rightHeight = 0;
-         if( pNode->pLeft ){
-           leftHeight += pNode->pLeft->nBlackHeight;
-           leftHeight += (pNode->pLeft->isBlack?1:0);
-         }
-         if( pNode->pRight ){
-           rightHeight += pNode->pRight->nBlackHeight;
-           rightHeight += (pNode->pRight->isBlack?1:0);
-         }
-         if( leftHeight != rightHeight ){
-           char buf[128];
-           sprintf(buf, "Different black-heights at %p\n", pNode);
-           *msg = append_val(*msg, buf);
-           *msg = append_node(*msg, tree->pHead, 0);
-         *msg = append_val(*msg, "\n");
-         }
-         pNode->nBlackHeight = leftHeight;
-       }
-
-       if( pNode->pParent ){
-         if( pNode == pNode->pParent->pLeft ) prev_step = 1;
-         else prev_step = 2;
-       }
-       pNode = pNode->pParent;
-       break;
+        /* Check red-black property (1) */
+        if( !pNode->isBlack &&
+            ( (pNode->pLeft && !pNode->pLeft->isBlack) ||
+              (pNode->pRight && !pNode->pRight->isBlack) )
+          ){
+          char buf[128];
+          sprintf(buf, "Red node with red child at %p\n", pNode);
+          *msg = append_val(*msg, buf);
+          *msg = append_node(*msg, tree->pHead, 0);
+          *msg = append_val(*msg, "\n");
+        }
+
+        /* Check red-black property (2) */
+        
+          int leftHeight = 0;
+          int rightHeight = 0;
+          if( pNode->pLeft ){
+            leftHeight += pNode->pLeft->nBlackHeight;
+            leftHeight += (pNode->pLeft->isBlack?1:0);
+          }
+          if( pNode->pRight ){
+            rightHeight += pNode->pRight->nBlackHeight;
+            rightHeight += (pNode->pRight->isBlack?1:0);
+          }
+          if( leftHeight != rightHeight ){
+            char buf[128];
+            sprintf(buf, "Different black-heights at %p\n", pNode);
+            *msg = append_val(*msg, buf);
+            *msg = append_node(*msg, tree->pHead, 0);
+            *msg = append_val(*msg, "\n");
+          }
+          pNode->nBlackHeight = leftHeight;
+        }
+
+        if( pNode->pParent ){
+          if( pNode == pNode->pParent->pLeft ) prev_step = 1;
+          else prev_step = 2;
+        }
+        pNode = pNode->pParent;
+        break;
       default: assert(0);
     }
   }
@@ -408,47 +408,47 @@ static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX)
     }else{
 
       if( pX->pParent == pGrandparent->pLeft ){
-       if( pX == pX->pParent->pRight ){
-         /* If pX is a right-child, do the following transform, essentially
-          * to change pX into a left-child: 
-          *       |                  | 
-          *      G(b)               G(b)
-          *      /  \               /  \        
-          *   P(r)   U(b)        X(r)  U(b)
-          *      \                /
-          *     X(r)            P(r) <-- new X
-          *
-          *     BEFORE             AFTER
-          */
-         pX = pX->pParent;
-         leftRotate(pTree, pX);
-       }
-
-       /* Do the following transform, which balances the tree :) 
-        *       |                  | 
-        *      G(b)               P(b)
-        *      /  \               /  \        
-        *   P(r)   U(b)        X(r)  G(r)
-        *    /                         \
-        *  X(r)                        U(b)
-        *
-        *     BEFORE             AFTER
-        */
-       assert( pGrandparent == pX->pParent->pParent );
-       pGrandparent->isBlack = 0;
-       pX->pParent->isBlack = 1;
-       rightRotate( pTree, pGrandparent );
+        if( pX == pX->pParent->pRight ){
+          /* If pX is a right-child, do the following transform, essentially
+           * to change pX into a left-child: 
+           *       |                  | 
+           *      G(b)               G(b)
+           *      /  \               /  \        
+           *   P(r)   U(b)        X(r)  U(b)
+           *      \                /
+           *     X(r)            P(r) <-- new X
+           *
+           *     BEFORE             AFTER
+           */
+          pX = pX->pParent;
+          leftRotate(pTree, pX);
+        }
+
+        /* Do the following transform, which balances the tree :) 
+         *       |                  | 
+         *      G(b)               P(b)
+         *      /  \               /  \        
+         *   P(r)   U(b)        X(r)  G(r)
+         *    /                         \
+         *  X(r)                        U(b)
+         *
+         *     BEFORE             AFTER
+         */
+        assert( pGrandparent == pX->pParent->pParent );
+        pGrandparent->isBlack = 0;
+        pX->pParent->isBlack = 1;
+        rightRotate( pTree, pGrandparent );
 
       }else{
-       /* This code is symetric to the illustrated case above. */
-       if( pX == pX->pParent->pLeft ){
-         pX = pX->pParent;
-         rightRotate(pTree, pX);
-       }
-       assert( pGrandparent == pX->pParent->pParent );
-       pGrandparent->isBlack = 0;
-       pX->pParent->isBlack = 1;
-       leftRotate( pTree, pGrandparent );
+        /* This code is symetric to the illustrated case above. */
+        if( pX == pX->pParent->pLeft ){
+          pX = pX->pParent;
+          rightRotate(pTree, pX);
+        }
+        assert( pGrandparent == pX->pParent->pParent );
+        pGrandparent->isBlack = 0;
+        pX->pParent->isBlack = 1;
+        leftRotate( pTree, pGrandparent );
       }
     }
   }
@@ -470,7 +470,8 @@ static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX)
  * properties have been violated, and pX has an "extra black". This function 
  * performs rotations and color-changes to re-balance the tree.
  */
-static void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent)
+static 
+void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent)
 {
   BtRbNode *pSib; 
 
@@ -479,58 +480,58 @@ static void do_delete_balancing(BtRbTree *pTree, BtRbNode *pX, BtRbNode *pParent
     if( pX == pParent->pLeft ){
       pSib = pParent->pRight;
       if( pSib && !(pSib->isBlack) ){
-       pSib->isBlack = 1;
-       pParent->isBlack = 0;
-       leftRotate(pTree, pParent);
-       pSib = pParent->pRight;
+        pSib->isBlack = 1;
+        pParent->isBlack = 0;
+        leftRotate(pTree, pParent);
+        pSib = pParent->pRight;
       }
       if( !pSib ){
-       pX = pParent;
+        pX = pParent;
       }else if( 
-         (!pSib->pLeft  || pSib->pLeft->isBlack) &&
-         (!pSib->pRight || pSib->pRight->isBlack) ) {
-       pSib->isBlack = 0;
-       pX = pParent;
+          (!pSib->pLeft  || pSib->pLeft->isBlack) &&
+          (!pSib->pRight || pSib->pRight->isBlack) ) {
+        pSib->isBlack = 0;
+        pX = pParent;
       }else{
-       if( (!pSib->pRight || pSib->pRight->isBlack) ){
-         if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
-         pSib->isBlack = 0;
-         rightRotate( pTree, pSib );
-         pSib = pParent->pRight;
-       }
-       pSib->isBlack = pParent->isBlack;
-       pParent->isBlack = 1;
-       if( pSib->pRight ) pSib->pRight->isBlack = 1;
-       leftRotate(pTree, pParent);
-       pX = pTree->pHead;
+        if( (!pSib->pRight || pSib->pRight->isBlack) ){
+          if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
+          pSib->isBlack = 0;
+          rightRotate( pTree, pSib );
+          pSib = pParent->pRight;
+        }
+        pSib->isBlack = pParent->isBlack;
+        pParent->isBlack = 1;
+        if( pSib->pRight ) pSib->pRight->isBlack = 1;
+        leftRotate(pTree, pParent);
+        pX = pTree->pHead;
       }
     }else{
       pSib = pParent->pLeft;
       if( pSib && !(pSib->isBlack) ){
-       pSib->isBlack = 1;
-       pParent->isBlack = 0;
-       rightRotate(pTree, pParent);
-       pSib = pParent->pLeft;
+        pSib->isBlack = 1;
+        pParent->isBlack = 0;
+        rightRotate(pTree, pParent);
+        pSib = pParent->pLeft;
       }
       if( !pSib ){
-       pX = pParent;
+        pX = pParent;
       }else if( 
           (!pSib->pLeft  || pSib->pLeft->isBlack) &&
-         (!pSib->pRight || pSib->pRight->isBlack) ){
-       pSib->isBlack = 0;
-       pX = pParent;
+          (!pSib->pRight || pSib->pRight->isBlack) ){
+        pSib->isBlack = 0;
+        pX = pParent;
       }else{
-       if( (!pSib->pLeft || pSib->pLeft->isBlack) ){
-         if( pSib->pRight ) pSib->pRight->isBlack = 1;
-         pSib->isBlack = 0;
-         leftRotate( pTree, pSib );
-         pSib = pParent->pLeft;
-       }
-       pSib->isBlack = pParent->isBlack;
-       pParent->isBlack = 1;
-       if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
-       rightRotate(pTree, pParent);
-       pX = pTree->pHead;
+        if( (!pSib->pLeft || pSib->pLeft->isBlack) ){
+          if( pSib->pRight ) pSib->pRight->isBlack = 1;
+          pSib->isBlack = 0;
+          leftRotate( pTree, pSib );
+          pSib = pParent->pLeft;
+        }
+        pSib->isBlack = pParent->isBlack;
+        pParent->isBlack = 1;
+        if( pSib->pLeft ) pSib->pLeft->isBlack = 1;
+        rightRotate(pTree, pParent);
+        pX = pTree->pHead;
       }
     }
     pParent = pX->pParent;
@@ -573,10 +574,7 @@ int sqliteRBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree)
   *ppBtree = (Btree *)sqliteMalloc(sizeof(Btree));
   sqliteHashInit(&(*ppBtree)->tblHash, SQLITE_HASH_INT, 0);
 
-  /* Create binary trees for tables 0, 1 and 2. SQLite assumes these
-   * tables always exist. At least I think so? */
-  btreeCreateTable(*ppBtree, 0);
-  btreeCreateTable(*ppBtree, 1);
+  /* Create a binary tree for the SQLITE_MASTER table at location 2 */
   btreeCreateTable(*ppBtree, 2);
   (*ppBtree)->next_idx = 3;
   (*ppBtree)->pOps = &sqliteBtreeOps;
@@ -620,10 +618,9 @@ static int memBtreeDropTable(Btree* tree, int n)
   assert( tree->eTransState != TRANS_NONE );
 
   memBtreeClearTable(tree, n);
-  pTree = sqliteHashFind(&tree->tblHash, 0, n);
+  pTree = sqliteHashInsert(&tree->tblHash, 0, n, 0);
   assert(pTree);
   sqliteFree(pTree);
-  sqliteHashInsert(&tree->tblHash, 0, n, 0);
 
   if( tree->eTransState != TRANS_ROLLBACK ){
     BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
@@ -636,7 +633,7 @@ static int memBtreeDropTable(Btree* tree, int n)
 }
 
 static int memBtreeKeyCompare(BtCursor* pCur, const void *pKey, int nKey,
-                                int nIgnore, int *pRes)
+                                 int nIgnore, int *pRes)
 {
   assert(pCur);
 
@@ -647,7 +644,7 @@ static int memBtreeKeyCompare(BtCursor* pCur, const void *pKey, int nKey,
       *pRes = -1;
     }else{
       *pRes = key_compare(pCur->pNode->pKey, pCur->pNode->nKey-nIgnore, 
-         pKey, nKey);
+          pKey, nKey);
     }
   }
   return SQLITE_OK;
@@ -681,7 +678,7 @@ static int memBtreeCursor(Btree* tree, int iTable, int wrFlag, BtCursor **ppCur)
  * If the key exists already in the tree, just replace the data. 
  */
 static int memBtreeInsert(BtCursor* pCur, const void *pKey, int nKey,
-                            const void *pDataInput, int nData)
+                             const void *pDataInput, int nData)
 {
   void * pData;
   int match;
@@ -715,18 +712,18 @@ static int memBtreeInsert(BtCursor* pCur, const void *pKey, int nKey,
     pNode->pData = pData; 
     if( pCur->pNode ){
       switch( match ){
-       case -1:
-         assert( !pCur->pNode->pRight );
-         pNode->pParent = pCur->pNode;
-         pCur->pNode->pRight = pNode;
-         break;
-       case 1:
-         assert( !pCur->pNode->pLeft );
-         pNode->pParent = pCur->pNode;
-         pCur->pNode->pLeft = pNode;
-         break;
-       default:
-         assert(0);
+        case -1:
+          assert( !pCur->pNode->pRight );
+          pNode->pParent = pCur->pNode;
+          pCur->pNode->pRight = pNode;
+          break;
+        case 1:
+          assert( !pCur->pNode->pLeft );
+          pNode->pParent = pCur->pNode;
+          pCur->pNode->pLeft = pNode;
+          break;
+        default:
+          assert(0);
       }
     }else{
       pCur->pTree->pHead = pNode;
@@ -800,11 +797,11 @@ static int memBtreeMoveto(BtCursor* pCur, const void *pKey, int nKey, int *pRes)
     pTmp = pCur->pNode;
     switch( *pRes ){
       case 1:    /* cursor > key */
-       pCur->pNode = pCur->pNode->pLeft;
-       break;
+        pCur->pNode = pCur->pNode->pLeft;
+        break;
       case -1:   /* cursor < key */
-       pCur->pNode = pCur->pNode->pRight;
-       break;
+        pCur->pNode = pCur->pNode->pRight;
+        break;
     }
   } 
 
@@ -894,8 +891,8 @@ static int memBtreeDelete(BtCursor* pCur)
       pCur->eSkip = SKIP_PREV;
     }
     if( pCur->pBtree->eTransState == TRANS_ROLLBACK ){
-       sqliteFree(pZ->pKey);
-       sqliteFree(pZ->pData);
+        sqliteFree(pZ->pKey);
+        sqliteFree(pZ->pData);
     }
   }
 
@@ -908,7 +905,7 @@ static int memBtreeDelete(BtCursor* pCur)
     if( pZ->pParent ){
       assert( pZ == pZ->pParent->pLeft || pZ == pZ->pParent->pRight );
       ppParentSlot = ((pZ == pZ->pParent->pLeft)
-         ?&pZ->pParent->pLeft:&pZ->pParent->pRight);
+          ?&pZ->pParent->pLeft:&pZ->pParent->pRight);
       *ppParentSlot = pChild;
     }else{
       pCur->pTree->pHead = pChild;
@@ -951,22 +948,22 @@ static int memBtreeClearTable(Btree* tree, int n)
     else {
       BtRbNode *pTmp = pNode->pParent;
       if( tree->eTransState == TRANS_ROLLBACK ){
-       sqliteFree( pNode->pKey );
-       sqliteFree( pNode->pData );
+        sqliteFree( pNode->pKey );
+        sqliteFree( pNode->pData );
       }else{
-       BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
-       pRollbackOp->eOp = ROLLBACK_INSERT;
-       pRollbackOp->iTab = n;
-       pRollbackOp->nKey = pNode->nKey;
-       pRollbackOp->pKey = pNode->pKey;
-       pRollbackOp->nData = pNode->nData;
-       pRollbackOp->pData = pNode->pData;
-       btreeLogRollbackOp(tree, pRollbackOp);
+        BtRollbackOp *pRollbackOp = sqliteMalloc(sizeof(BtRollbackOp));
+        pRollbackOp->eOp = ROLLBACK_INSERT;
+        pRollbackOp->iTab = n;
+        pRollbackOp->nKey = pNode->nKey;
+        pRollbackOp->pKey = pNode->pKey;
+        pRollbackOp->nData = pNode->nData;
+        pRollbackOp->pData = pNode->pData;
+        btreeLogRollbackOp(tree, pRollbackOp);
       }
       sqliteFree( pNode );
       if( pTmp ){
-       if( pTmp->pLeft == pNode ) pTmp->pLeft = 0;
-       else if( pTmp->pRight == pNode ) pTmp->pRight = 0;
+        if( pTmp->pLeft == pNode ) pTmp->pLeft = 0;
+        else if( pTmp->pRight == pNode ) pTmp->pRight = 0;
       }
       pNode = pTmp;
     }
@@ -1016,13 +1013,13 @@ static int memBtreeNext(BtCursor* pCur, int *pRes)
     if( pCur->pNode->pRight ){
       pCur->pNode = pCur->pNode->pRight;
       while( pCur->pNode->pLeft )
-       pCur->pNode = pCur->pNode->pLeft;
+        pCur->pNode = pCur->pNode->pLeft;
     }else{
       BtRbNode * pX = pCur->pNode;
       pCur->pNode = pX->pParent;
       while( pCur->pNode && (pCur->pNode->pRight == pX) ){
-       pX = pCur->pNode;
-       pCur->pNode = pX->pParent;
+        pX = pCur->pNode;
+        pCur->pNode = pX->pParent;
       }
     }
   }
@@ -1043,13 +1040,13 @@ static int memBtreePrevious(BtCursor* pCur, int *pRes)
     if( pCur->pNode->pLeft ){
       pCur->pNode = pCur->pNode->pLeft;
       while( pCur->pNode->pRight )
-       pCur->pNode = pCur->pNode->pRight;
+        pCur->pNode = pCur->pNode->pRight;
     }else{
       BtRbNode * pX = pCur->pNode;
       pCur->pNode = pX->pParent;
       while( pCur->pNode && (pCur->pNode->pLeft == pX) ){
-       pX = pCur->pNode;
-       pCur->pNode = pX->pParent;
+        pX = pCur->pNode;
+        pCur->pNode = pX->pParent;
       }
     }
   }
@@ -1152,11 +1149,11 @@ static char *memBtreeIntegrityCheck(Btree* tree, int* aRoot, int nRoot)
 static int memBtreeClose(Btree* tree)
 {
   HashElem *p;
-  for(p=sqliteHashFirst(&tree->tblHash); p; p=sqliteHashNext(p)){
+  while( (p=sqliteHashFirst(&tree->tblHash))!=0 ){
     tree->eTransState = TRANS_ROLLBACK;
-    memBtreeClearTable(tree, sqliteHashKeysize(p));
-    sqliteFree(sqliteHashData(p));
+    memBtreeDropTable(tree, sqliteHashKeysize(p));
   }
+  sqliteHashClear(&tree->tblHash);
   sqliteFree(tree);
   return SQLITE_OK;
 }
@@ -1220,30 +1217,30 @@ static void execute_rollback_list(Btree *pBtree, BtRollbackOp *pList)
   while( pList ){
     switch( pList->eOp ){
       case ROLLBACK_INSERT:
-       cur.pTree  = sqliteHashFind( &pBtree->tblHash, 0, pList->iTab );
-       assert(cur.pTree);
-       cur.iTree  = pList->iTab;
-       cur.eSkip  = SKIP_NONE;
-       memBtreeInsert( &cur, pList->pKey,
-           pList->nKey, pList->pData, pList->nData );
-       break;
+        cur.pTree  = sqliteHashFind( &pBtree->tblHash, 0, pList->iTab );
+        assert(cur.pTree);
+        cur.iTree  = pList->iTab;
+        cur.eSkip  = SKIP_NONE;
+        memBtreeInsert( &cur, pList->pKey,
+            pList->nKey, pList->pData, pList->nData );
+        break;
       case ROLLBACK_DELETE:
-       cur.pTree  = sqliteHashFind( &pBtree->tblHash, 0, pList->iTab );
-       assert(cur.pTree);
-       cur.iTree  = pList->iTab;
-       cur.eSkip  = SKIP_NONE;
-       memBtreeMoveto(&cur, pList->pKey, pList->nKey, &res);
-       assert(res == 0);
-       memBtreeDelete( &cur );
-       break;
+        cur.pTree  = sqliteHashFind( &pBtree->tblHash, 0, pList->iTab );
+        assert(cur.pTree);
+        cur.iTree  = pList->iTab;
+        cur.eSkip  = SKIP_NONE;
+        memBtreeMoveto(&cur, pList->pKey, pList->nKey, &res);
+        assert(res == 0);
+        memBtreeDelete( &cur );
+        break;
       case ROLLBACK_CREATE:
-       btreeCreateTable(pBtree, pList->iTab);
-       break;
+        btreeCreateTable(pBtree, pList->iTab);
+        break;
       case ROLLBACK_DROP:
-       memBtreeDropTable(pBtree, pList->iTab);
-       break;
+        memBtreeDropTable(pBtree, pList->iTab);
+        break;
       default:
-       assert(0);
+        assert(0);
     }
     sqliteFree(pList->pKey);
     sqliteFree(pList->pData);