/ Check-in [cfbeda1b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added the SQLITE_TESTCTRL_RESERVE option to sqlite3_test_control(). Simplifications to btree.c to facilitate structural coverage testing. (CVS 6894)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cfbeda1b3126503e9631471ce4713e25b007859f
User & Date: drh 2009-07-15 11:26:44
Context
2009-07-15
16:30
Remove an assert() from vdbeaux.c that might not be true if the database file is corrupt. (CVS 6895) check-in: a42dc51e user: drh tags: trunk
11:26
Added the SQLITE_TESTCTRL_RESERVE option to sqlite3_test_control(). Simplifications to btree.c to facilitate structural coverage testing. (CVS 6894) check-in: cfbeda1b user: drh tags: trunk
2009-07-14
18:35
Add comments and assert() statements to show that the return value from sqlite3BtreeKeySize() and sqlite3BtreeData() usually do not matter. Ticket #3968. Also remove a NEVER() macro that can sometimes be true - discovered while testing the previous change. (CVS 6893) check-in: 0c710c1b user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** $Id: btree.c,v 1.687 2009/07/14 17:48:06 drh Exp $
           12  +** $Id: btree.c,v 1.688 2009/07/15 11:26:44 drh Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** See the header comment on "btreeInt.h" for additional information.
    16     16   ** Including a description of file format and an overview of operation.
    17     17   */
    18     18   #include "btreeInt.h"
    19     19   
................................................................................
  1196   1196   static int freeSpace(MemPage *pPage, int start, int size){
  1197   1197     int addr, pbegin, hdr;
  1198   1198     int iLast;                        /* Largest possible freeblock offset */
  1199   1199     unsigned char *data = pPage->aData;
  1200   1200   
  1201   1201     assert( pPage->pBt!=0 );
  1202   1202     assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  1203         -  assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) );
         1203  +  assert( start>=pPage->hdrOffset+6+pPage->childPtrSize );
  1204   1204     assert( (start + size)<=pPage->pBt->usableSize );
  1205   1205     assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  1206   1206     assert( size>=0 );   /* Minimum cell size is 4 */
  1207   1207   
  1208   1208   #ifdef SQLITE_SECURE_DELETE
  1209   1209     /* Overwrite deleted information with zeros when the SECURE_DELETE 
  1210   1210     ** option is enabled at compile-time */
................................................................................
  4881   4881     ** possibilities. If the free-list is currently empty, or if the first
  4882   4882     ** trunk page in the free-list is full, then this page will become a
  4883   4883     ** new free-list trunk page. Otherwise, it will become a leaf of the
  4884   4884     ** first trunk page in the current free-list. This block tests if it
  4885   4885     ** is possible to add the page as a new free-list leaf.
  4886   4886     */
  4887   4887     if( nFree!=0 ){
  4888         -    int nLeaf;                /* Initial number of leaf cells on trunk page */
         4888  +    u32 nLeaf;                /* Initial number of leaf cells on trunk page */
  4889   4889   
  4890   4890       iTrunk = get4byte(&pPage1->aData[32]);
  4891   4891       rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
  4892   4892       if( rc!=SQLITE_OK ){
  4893   4893         goto freepage_out;
  4894   4894       }
  4895   4895   
  4896   4896       nLeaf = get4byte(&pTrunk->aData[4]);
  4897         -    if( nLeaf<0 ){
         4897  +    if( nLeaf > pBt->usableSize/4 - 2 ){
  4898   4898         rc = SQLITE_CORRUPT_BKPT;
  4899   4899         goto freepage_out;
  4900   4900       }
  4901   4901       if( nLeaf<pBt->usableSize/4 - 8 ){
  4902   4902         /* In this case there is room on the trunk page to insert the page
  4903   4903         ** being freed as a new leaf.
  4904   4904         **
  4905   4905         ** Note that the trunk page is not really full until it contains
  4906   4906         ** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have
  4907   4907         ** coded.  But due to a coding error in versions of SQLite prior to
  4908   4908         ** 3.6.0, databases with freelist trunk pages holding more than
  4909   4909         ** usableSize/4 - 8 entries will be reported as corrupt.  In order
  4910   4910         ** to maintain backwards compatibility with older versions of SQLite,
  4911         -      ** we will contain to restrict the number of entries to usableSize/4 - 8
         4911  +      ** we will continue to restrict the number of entries to usableSize/4 - 8
  4912   4912         ** for now.  At some point in the future (once everyone has upgraded
  4913   4913         ** to 3.6.0 or later) we should consider fixing the conditional above
  4914   4914         ** to read "usableSize/4-2" instead of "usableSize/4-8".
  4915   4915         */
  4916   4916         rc = sqlite3PagerWrite(pTrunk->pDbPage);
  4917   4917         if( rc==SQLITE_OK ){
  4918   4918           put4byte(&pTrunk->aData[4], nLeaf+1);
................................................................................
  4931   4931   
  4932   4932     /* If control flows to this point, then it was not possible to add the
  4933   4933     ** the page being freed as a leaf page of the first trunk in the free-list.
  4934   4934     ** Possibly because the free-list is empty, or possibly because the 
  4935   4935     ** first trunk in the free-list is full. Either way, the page being freed
  4936   4936     ** will become the new first trunk page in the free-list.
  4937   4937     */
  4938         -  if(   ((!pPage) && (0 != (rc = btreeGetPage(pBt, iPage, &pPage, 0))))
  4939         -     || (0 != (rc = sqlite3PagerWrite(pPage->pDbPage)))
  4940         -  ){
         4938  +  if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
         4939  +    goto freepage_out;
         4940  +  }
         4941  +  rc = sqlite3PagerWrite(pPage->pDbPage);
         4942  +  if( rc!=SQLITE_OK ){
  4941   4943       goto freepage_out;
  4942   4944     }
  4943   4945     put4byte(pPage->aData, iTrunk);
  4944   4946     put4byte(&pPage->aData[4], 0);
  4945   4947     put4byte(&pPage1->aData[32], iPage);
  4946   4948     TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk));
  4947   4949   
................................................................................
  5181   5183     assert( idx>=0 && idx<pPage->nCell );
  5182   5184     assert( sz==cellSize(pPage, idx) );
  5183   5185     assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  5184   5186     assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  5185   5187     data = pPage->aData;
  5186   5188     ptr = &data[pPage->cellOffset + 2*idx];
  5187   5189     pc = get2byte(ptr);
  5188         -  if( (pc<pPage->hdrOffset+6+(pPage->leaf?0:4))
         5190  +  if( NEVER(pc<pPage->hdrOffset+6+pPage->childPtrSize)
  5189   5191        || (pc+sz>pPage->pBt->usableSize) ){
  5190   5192       return SQLITE_CORRUPT_BKPT;
  5191   5193     }
  5192   5194     rc = freeSpace(pPage, pc, sz);
  5193   5195     if( rc!=SQLITE_OK ){
  5194   5196       return rc;
  5195   5197     }
................................................................................
  6862   6864     assert( p->inTrans==TRANS_WRITE );
  6863   6865   
  6864   6866     /* Invalidate all incrblob cursors open on table iTable (assuming iTable
  6865   6867     ** is the root of a table b-tree - if it is not, the following call is
  6866   6868     ** a no-op).  */
  6867   6869     invalidateIncrblobCursors(p, iTable, 0, 1);
  6868   6870   
  6869         -  if( SQLITE_OK==(rc = saveAllCursors(pBt, (Pgno)iTable, 0)) ){
         6871  +  rc = saveAllCursors(pBt, (Pgno)iTable, 0);
         6872  +  if( SQLITE_OK==rc ){
  6870   6873       rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
  6871   6874     }
  6872   6875     sqlite3BtreeLeave(p);
  6873   6876     return rc;
  6874   6877   }
  6875   6878   
  6876   6879   /*
................................................................................
  6902   6905     assert( p->inTrans==TRANS_WRITE );
  6903   6906   
  6904   6907     /* It is illegal to drop a table if any cursors are open on the
  6905   6908     ** database. This is because in auto-vacuum mode the backend may
  6906   6909     ** need to move another root-page to fill a gap left by the deleted
  6907   6910     ** root page. If an open cursor was using this page a problem would 
  6908   6911     ** occur.
         6912  +  **
         6913  +  ** This error is caught long before control reaches this point.
  6909   6914     */
  6910         -  if( pBt->pCursor ){
         6915  +  if( NEVER(pBt->pCursor) ){
  6911   6916       sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db);
  6912   6917       return SQLITE_LOCKED_SHAREDCACHE;
  6913   6918     }
  6914   6919   
  6915   6920     rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
  6916   6921     if( rc ) return rc;
  6917   6922     rc = sqlite3BtreeClearTable(p, iTable, 0);
................................................................................
  6985   6990         rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
  6986   6991       }else{
  6987   6992         rc = freePage(pPage);
  6988   6993         releasePage(pPage);
  6989   6994       }
  6990   6995   #endif
  6991   6996     }else{
  6992         -    /* If sqlite3BtreeDropTable was called on page 1. */
         6997  +    /* If sqlite3BtreeDropTable was called on page 1.
         6998  +    ** This really never should happen except in a corrupt
         6999  +    ** database. 
         7000  +    */
  6993   7001       zeroPage(pPage, PTF_INTKEY|PTF_LEAF );
  6994   7002       releasePage(pPage);
  6995   7003     }
  6996   7004     return rc;  
  6997   7005   }
  6998   7006   int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
  6999   7007     int rc;

Changes to src/main.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17         -** $Id: main.c,v 1.560 2009/06/26 15:14:55 drh Exp $
           17  +** $Id: main.c,v 1.561 2009/07/15 11:26:44 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   
    21     21   #ifdef SQLITE_ENABLE_FTS3
    22     22   # include "fts3.h"
    23     23   #endif
    24     24   #ifdef SQLITE_ENABLE_RTREE
................................................................................
  2241   2241       **    }
  2242   2242       */
  2243   2243       case SQLITE_TESTCTRL_ALWAYS: {
  2244   2244         int x = va_arg(ap,int);
  2245   2245         rc = ALWAYS(x);
  2246   2246         break;
  2247   2247       }
         2248  +
         2249  +    /*   sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
         2250  +    **
         2251  +    ** Set the nReserve size to N for the main database on the database
         2252  +    ** connection db.
         2253  +    */
         2254  +    case SQLITE_TESTCTRL_RESERVE: {
         2255  +      sqlite3 *db = va_arg(ap, sqlite3*);
         2256  +      int x = va_arg(ap,int);
         2257  +      sqlite3_mutex_enter(db->mutex);
         2258  +      sqlite3BtreeSetPageSize(db->aDb[0].pBt, 0, x, 0);
         2259  +      sqlite3_mutex_leave(db->mutex);
         2260  +      break;
         2261  +    }
         2262  +
  2248   2263     }
  2249   2264     va_end(ap);
  2250   2265   #endif /* SQLITE_OMIT_BUILTIN_TEST */
  2251   2266     return rc;
  2252   2267   }

Changes to src/sqlite.h.in.

    26     26   ** on how SQLite interfaces are suppose to operate.
    27     27   **
    28     28   ** The name of this file under configuration management is "sqlite.h.in".
    29     29   ** The makefile makes some minor changes to this file (such as inserting
    30     30   ** the version number) and changes its name to "sqlite3.h" as
    31     31   ** part of the build process.
    32     32   **
    33         -** @(#) $Id: sqlite.h.in,v 1.458 2009/06/19 22:50:31 drh Exp $
           33  +** @(#) $Id: sqlite.h.in,v 1.459 2009/07/15 11:26:44 drh Exp $
    34     34   */
    35     35   #ifndef _SQLITE3_H_
    36     36   #define _SQLITE3_H_
    37     37   #include <stdarg.h>     /* Needed for the definition of va_list */
    38     38   
    39     39   /*
    40     40   ** Make sure we can call this stuff from C++.
................................................................................
  4941   4941   #define SQLITE_TESTCTRL_PRNG_RESET               7
  4942   4942   #define SQLITE_TESTCTRL_BITVEC_TEST              8
  4943   4943   #define SQLITE_TESTCTRL_FAULT_INSTALL            9
  4944   4944   #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
  4945   4945   #define SQLITE_TESTCTRL_PENDING_BYTE            11
  4946   4946   #define SQLITE_TESTCTRL_ASSERT                  12
  4947   4947   #define SQLITE_TESTCTRL_ALWAYS                  13
         4948  +#define SQLITE_TESTCTRL_RESERVE                 14
  4948   4949   
  4949   4950   /*
  4950   4951   ** CAPI3REF: SQLite Runtime Status {H17200} <S60200>
  4951   4952   ** EXPERIMENTAL
  4952   4953   **
  4953   4954   ** This interface is used to retrieve runtime status information
  4954   4955   ** about the preformance of SQLite, and optionally to reset various