| Index: third_party/sqlite/src/src/btree.c
 | 
| diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
 | 
| index f5feff8a4c597c8b490c9e154dfa5b056e9b93a1..de553423b8847ff23b58c2ce3ec8218314c7a2e8 100644
 | 
| --- a/third_party/sqlite/src/src/btree.c
 | 
| +++ b/third_party/sqlite/src/src/btree.c
 | 
| @@ -350,7 +350,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
 | 
|    if( !pLock ){
 | 
|      pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock));
 | 
|      if( !pLock ){
 | 
| -      return SQLITE_NOMEM;
 | 
| +      return SQLITE_NOMEM_BKPT;
 | 
|      }
 | 
|      pLock->iTable = iTable;
 | 
|      pLock->pBtree = p;
 | 
| @@ -450,6 +450,19 @@ static void releasePage(MemPage *pPage);  /* Forward reference */
 | 
|  static int cursorHoldsMutex(BtCursor *p){
 | 
|    return sqlite3_mutex_held(p->pBt->mutex);
 | 
|  }
 | 
| +
 | 
| +/* Verify that the cursor and the BtShared agree about what is the current
 | 
| +** database connetion. This is important in shared-cache mode. If the database 
 | 
| +** connection pointers get out-of-sync, it is possible for routines like
 | 
| +** btreeInitPage() to reference an stale connection pointer that references a
 | 
| +** a connection that has already closed.  This routine is used inside assert()
 | 
| +** statements only and for the purpose of double-checking that the btree code
 | 
| +** does keep the database connection pointers up-to-date.
 | 
| +*/
 | 
| +static int cursorOwnsBtShared(BtCursor *p){
 | 
| +  assert( cursorHoldsMutex(p) );
 | 
| +  return (p->pBtree->db==p->pBt->db);
 | 
| +}
 | 
|  #endif
 | 
|  
 | 
|  /*
 | 
| @@ -549,7 +562,7 @@ static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
 | 
|      assert( pgno<=pBt->nPage );
 | 
|      pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
 | 
|      if( !pBt->pHasContent ){
 | 
| -      rc = SQLITE_NOMEM;
 | 
| +      rc = SQLITE_NOMEM_BKPT;
 | 
|      }
 | 
|    }
 | 
|    if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
 | 
| @@ -605,30 +618,28 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){
 | 
|  ** the key.
 | 
|  */
 | 
|  static int saveCursorKey(BtCursor *pCur){
 | 
| -  int rc;
 | 
| +  int rc = SQLITE_OK;
 | 
|    assert( CURSOR_VALID==pCur->eState );
 | 
|    assert( 0==pCur->pKey );
 | 
|    assert( cursorHoldsMutex(pCur) );
 | 
|  
 | 
| -  rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
 | 
| -  assert( rc==SQLITE_OK );  /* KeySize() cannot fail */
 | 
| -
 | 
| -  /* If this is an intKey table, then the above call to BtreeKeySize()
 | 
| -  ** stores the integer key in pCur->nKey. In this case this value is
 | 
| -  ** all that is required. Otherwise, if pCur is not open on an intKey
 | 
| -  ** table, then malloc space for and store the pCur->nKey bytes of key 
 | 
| -  ** data.  */
 | 
| -  if( 0==pCur->curIntKey ){
 | 
| -    void *pKey = sqlite3Malloc( pCur->nKey );
 | 
| +  if( pCur->curIntKey ){
 | 
| +    /* Only the rowid is required for a table btree */
 | 
| +    pCur->nKey = sqlite3BtreeIntegerKey(pCur);
 | 
| +  }else{
 | 
| +    /* For an index btree, save the complete key content */
 | 
| +    void *pKey;
 | 
| +    pCur->nKey = sqlite3BtreePayloadSize(pCur);
 | 
| +    pKey = sqlite3Malloc( pCur->nKey );
 | 
|      if( pKey ){
 | 
| -      rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey);
 | 
| +      rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
 | 
|        if( rc==SQLITE_OK ){
 | 
|          pCur->pKey = pKey;
 | 
|        }else{
 | 
|          sqlite3_free(pKey);
 | 
|        }
 | 
|      }else{
 | 
| -      rc = SQLITE_NOMEM;
 | 
| +      rc = SQLITE_NOMEM_BKPT;
 | 
|      }
 | 
|    }
 | 
|    assert( !pCur->curIntKey || !pCur->pKey );
 | 
| @@ -752,26 +763,23 @@ static int btreeMoveto(
 | 
|  ){
 | 
|    int rc;                    /* Status code */
 | 
|    UnpackedRecord *pIdxKey;   /* Unpacked index key */
 | 
| -  char aSpace[200];          /* Temp space for pIdxKey - to avoid a malloc */
 | 
| -  char *pFree = 0;
 | 
|  
 | 
|    if( pKey ){
 | 
|      assert( nKey==(i64)(int)nKey );
 | 
| -    pIdxKey = sqlite3VdbeAllocUnpackedRecord(
 | 
| -        pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
 | 
| -    );
 | 
| -    if( pIdxKey==0 ) return SQLITE_NOMEM;
 | 
| +    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
 | 
| +    if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
 | 
|      sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
 | 
|      if( pIdxKey->nField==0 ){
 | 
| -      sqlite3DbFree(pCur->pKeyInfo->db, pFree);
 | 
| -      return SQLITE_CORRUPT_BKPT;
 | 
| +      rc = SQLITE_CORRUPT_BKPT;
 | 
| +      goto moveto_done;
 | 
|      }
 | 
|    }else{
 | 
|      pIdxKey = 0;
 | 
|    }
 | 
|    rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
 | 
| -  if( pFree ){
 | 
| -    sqlite3DbFree(pCur->pKeyInfo->db, pFree);
 | 
| +moveto_done:
 | 
| +  if( pIdxKey ){
 | 
| +    sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
 | 
|    }
 | 
|    return rc;
 | 
|  }
 | 
| @@ -786,7 +794,7 @@ static int btreeMoveto(
 | 
|  static int btreeRestoreCursorPosition(BtCursor *pCur){
 | 
|    int rc;
 | 
|    int skipNext;
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pCur->eState>=CURSOR_REQUIRESEEK );
 | 
|    if( pCur->eState==CURSOR_FAULT ){
 | 
|      return pCur->skipNext;
 | 
| @@ -1075,7 +1083,6 @@ static void btreeParseCellPtrNoPayload(
 | 
|  ){
 | 
|    assert( sqlite3_mutex_held(pPage->pBt->mutex) );
 | 
|    assert( pPage->leaf==0 );
 | 
| -  assert( pPage->noPayload );
 | 
|    assert( pPage->childPtrSize==4 );
 | 
|  #ifndef SQLITE_DEBUG
 | 
|    UNUSED_PARAMETER(pPage);
 | 
| @@ -1097,8 +1104,6 @@ static void btreeParseCellPtr(
 | 
|  
 | 
|    assert( sqlite3_mutex_held(pPage->pBt->mutex) );
 | 
|    assert( pPage->leaf==0 || pPage->leaf==1 );
 | 
| -  assert( pPage->intKeyLeaf || pPage->noPayload );
 | 
| -  assert( pPage->noPayload==0 );
 | 
|    assert( pPage->intKeyLeaf );
 | 
|    assert( pPage->childPtrSize==0 );
 | 
|    pIter = pCell;
 | 
| @@ -1167,7 +1172,6 @@ static void btreeParseCellPtrIndex(
 | 
|    assert( sqlite3_mutex_held(pPage->pBt->mutex) );
 | 
|    assert( pPage->leaf==0 || pPage->leaf==1 );
 | 
|    assert( pPage->intKeyLeaf==0 );
 | 
| -  assert( pPage->noPayload==0 );
 | 
|    pIter = pCell + pPage->childPtrSize;
 | 
|    nPayload = *pIter;
 | 
|    if( nPayload>=0x80 ){
 | 
| @@ -1228,7 +1232,6 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
 | 
|    pPage->xParseCell(pPage, pCell, &debuginfo);
 | 
|  #endif
 | 
|  
 | 
| -  assert( pPage->noPayload==0 );
 | 
|    nSize = *pIter;
 | 
|    if( nSize>=0x80 ){
 | 
|      pEnd = &pIter[8];
 | 
| @@ -1599,8 +1602,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
 | 
|    if( data[iPtr+1]==0 && data[iPtr]==0 ){
 | 
|      iFreeBlk = 0;  /* Shortcut for the case when the freelist is empty */
 | 
|    }else{
 | 
| -    while( (iFreeBlk = get2byte(&data[iPtr]))>0 && iFreeBlk<iStart ){
 | 
| -      if( iFreeBlk<iPtr+4 ) return SQLITE_CORRUPT_BKPT;
 | 
| +    while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
 | 
| +      if( iFreeBlk<iPtr+4 ){
 | 
| +        if( iFreeBlk==0 ) break;
 | 
| +        return SQLITE_CORRUPT_BKPT;
 | 
| +      }
 | 
|        iPtr = iFreeBlk;
 | 
|      }
 | 
|      if( iFreeBlk>iLast ) return SQLITE_CORRUPT_BKPT;
 | 
| @@ -1677,35 +1683,32 @@ static int decodeFlags(MemPage *pPage, int flagByte){
 | 
|    pPage->xCellSize = cellSizePtr;
 | 
|    pBt = pPage->pBt;
 | 
|    if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
 | 
| -    /* EVIDENCE-OF: R-03640-13415 A value of 5 means the page is an interior
 | 
| -    ** table b-tree page. */
 | 
| +    /* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an
 | 
| +    ** interior table b-tree page. */
 | 
|      assert( (PTF_LEAFDATA|PTF_INTKEY)==5 );
 | 
| -    /* EVIDENCE-OF: R-20501-61796 A value of 13 means the page is a leaf
 | 
| -    ** table b-tree page. */
 | 
| +    /* EVIDENCE-OF: R-26900-09176 A value of 13 (0x0d) means the page is a
 | 
| +    ** leaf table b-tree page. */
 | 
|      assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
 | 
|      pPage->intKey = 1;
 | 
|      if( pPage->leaf ){
 | 
|        pPage->intKeyLeaf = 1;
 | 
| -      pPage->noPayload = 0;
 | 
|        pPage->xParseCell = btreeParseCellPtr;
 | 
|      }else{
 | 
|        pPage->intKeyLeaf = 0;
 | 
| -      pPage->noPayload = 1;
 | 
|        pPage->xCellSize = cellSizePtrNoPayload;
 | 
|        pPage->xParseCell = btreeParseCellPtrNoPayload;
 | 
|      }
 | 
|      pPage->maxLocal = pBt->maxLeaf;
 | 
|      pPage->minLocal = pBt->minLeaf;
 | 
|    }else if( flagByte==PTF_ZERODATA ){
 | 
| -    /* EVIDENCE-OF: R-27225-53936 A value of 2 means the page is an interior
 | 
| -    ** index b-tree page. */
 | 
| +    /* EVIDENCE-OF: R-43316-37308 A value of 2 (0x02) means the page is an
 | 
| +    ** interior index b-tree page. */
 | 
|      assert( (PTF_ZERODATA)==2 );
 | 
| -    /* EVIDENCE-OF: R-16571-11615 A value of 10 means the page is a leaf
 | 
| -    ** index b-tree page. */
 | 
| +    /* EVIDENCE-OF: R-59615-42828 A value of 10 (0x0a) means the page is a
 | 
| +    ** leaf index b-tree page. */
 | 
|      assert( (PTF_ZERODATA|PTF_LEAF)==10 );
 | 
|      pPage->intKey = 0;
 | 
|      pPage->intKeyLeaf = 0;
 | 
| -    pPage->noPayload = 0;
 | 
|      pPage->xParseCell = btreeParseCellPtrIndex;
 | 
|      pPage->maxLocal = pBt->maxLocal;
 | 
|      pPage->minLocal = pBt->minLocal;
 | 
| @@ -1737,7 +1740,7 @@ static int btreeInitPage(MemPage *pPage){
 | 
|    assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
 | 
|  
 | 
|    if( !pPage->isInit ){
 | 
| -    u16 pc;            /* Address of a freeblock within pPage->aData[] */
 | 
| +    int pc;            /* Address of a freeblock within pPage->aData[] */
 | 
|      u8 hdr;            /* Offset to beginning of page header */
 | 
|      u8 *data;          /* Equal to pPage->aData */
 | 
|      BtShared *pBt;        /* The main btree structure */
 | 
| @@ -1817,25 +1820,30 @@ static int btreeInitPage(MemPage *pPage){
 | 
|      ** freeblocks. */
 | 
|      pc = get2byte(&data[hdr+1]);
 | 
|      nFree = data[hdr+7] + top;  /* Init nFree to non-freeblock free space */
 | 
| -    while( pc>0 ){
 | 
| -      u16 next, size;
 | 
| -      if( pc<iCellFirst || pc>iCellLast ){
 | 
| +    if( pc>0 ){
 | 
| +      u32 next, size;
 | 
| +      if( pc<iCellFirst ){
 | 
|          /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
 | 
|          ** always be at least one cell before the first freeblock.
 | 
| -        **
 | 
| -        ** Or, the freeblock is off the end of the page
 | 
|          */
 | 
|          return SQLITE_CORRUPT_BKPT; 
 | 
|        }
 | 
| -      next = get2byte(&data[pc]);
 | 
| -      size = get2byte(&data[pc+2]);
 | 
| -      if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
 | 
| -        /* Free blocks must be in ascending order. And the last byte of
 | 
| -        ** the free-block must lie on the database page.  */
 | 
| -        return SQLITE_CORRUPT_BKPT; 
 | 
| +      while( 1 ){
 | 
| +        if( pc>iCellLast ){
 | 
| +          return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */
 | 
| +        }
 | 
| +        next = get2byte(&data[pc]);
 | 
| +        size = get2byte(&data[pc+2]);
 | 
| +        nFree = nFree + size;
 | 
| +        if( next<=pc+size+3 ) break;
 | 
| +        pc = next;
 | 
| +      }
 | 
| +      if( next>0 ){
 | 
| +        return SQLITE_CORRUPT_BKPT;  /* Freeblock not in ascending order */
 | 
| +      }
 | 
| +      if( pc+size>(unsigned int)usableSize ){
 | 
| +        return SQLITE_CORRUPT_BKPT;  /* Last freeblock extends past page end */
 | 
|        }
 | 
| -      nFree = nFree + size;
 | 
| -      pc = next;
 | 
|      }
 | 
|  
 | 
|      /* At this point, nFree contains the sum of the offset to the start
 | 
| @@ -2180,7 +2188,7 @@ int sqlite3BtreeOpen(
 | 
|    }
 | 
|    p = sqlite3MallocZero(sizeof(Btree));
 | 
|    if( !p ){
 | 
| -    return SQLITE_NOMEM;
 | 
| +    return SQLITE_NOMEM_BKPT;
 | 
|    }
 | 
|    p->inTrans = TRANS_NONE;
 | 
|    p->db = db;
 | 
| @@ -2204,7 +2212,7 @@ int sqlite3BtreeOpen(
 | 
|        p->sharable = 1;
 | 
|        if( !zFullPathname ){
 | 
|          sqlite3_free(p);
 | 
| -        return SQLITE_NOMEM;
 | 
| +        return SQLITE_NOMEM_BKPT;
 | 
|        }
 | 
|        if( isMemdb ){
 | 
|          memcpy(zFullPathname, zFilename, nFilename);
 | 
| @@ -2272,11 +2280,11 @@ int sqlite3BtreeOpen(
 | 
|    
 | 
|      pBt = sqlite3MallocZero( sizeof(*pBt) );
 | 
|      if( pBt==0 ){
 | 
| -      rc = SQLITE_NOMEM;
 | 
| +      rc = SQLITE_NOMEM_BKPT;
 | 
|        goto btree_open_out;
 | 
|      }
 | 
|      rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
 | 
| -                          EXTRA_SIZE, flags, vfsFlags, pageReinit);
 | 
| +                          sizeof(MemPage), flags, vfsFlags, pageReinit);
 | 
|      if( rc==SQLITE_OK ){
 | 
|        sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
 | 
|        rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
 | 
| @@ -2334,15 +2342,14 @@ int sqlite3BtreeOpen(
 | 
|  #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
 | 
|      /* Add the new BtShared object to the linked list sharable BtShareds.
 | 
|      */
 | 
| +    pBt->nRef = 1;
 | 
|      if( p->sharable ){
 | 
|        MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
 | 
| -      pBt->nRef = 1;
 | 
|        MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);)
 | 
|        if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
 | 
|          pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
 | 
|          if( pBt->mutex==0 ){
 | 
| -          rc = SQLITE_NOMEM;
 | 
| -          db->mallocFailed = 0;
 | 
| +          rc = SQLITE_NOMEM_BKPT;
 | 
|            goto btree_open_out;
 | 
|          }
 | 
|        }
 | 
| @@ -2365,12 +2372,12 @@ int sqlite3BtreeOpen(
 | 
|      for(i=0; i<db->nDb; i++){
 | 
|        if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){
 | 
|          while( pSib->pPrev ){ pSib = pSib->pPrev; }
 | 
| -        if( p->pBt<pSib->pBt ){
 | 
| +        if( (uptr)p->pBt<(uptr)pSib->pBt ){
 | 
|            p->pNext = pSib;
 | 
|            p->pPrev = 0;
 | 
|            pSib->pPrev = p;
 | 
|          }else{
 | 
| -          while( pSib->pNext && pSib->pNext->pBt<p->pBt ){
 | 
| +          while( pSib->pNext && (uptr)pSib->pNext->pBt<(uptr)p->pBt ){
 | 
|              pSib = pSib->pNext;
 | 
|            }
 | 
|            p->pNext = pSib->pNext;
 | 
| @@ -2390,12 +2397,14 @@ int sqlite3BtreeOpen(
 | 
|  btree_open_out:
 | 
|    if( rc!=SQLITE_OK ){
 | 
|      if( pBt && pBt->pPager ){
 | 
| -      sqlite3PagerClose(pBt->pPager);
 | 
| +      sqlite3PagerClose(pBt->pPager, 0);
 | 
|      }
 | 
|      sqlite3_free(pBt);
 | 
|      sqlite3_free(p);
 | 
|      *ppBtree = 0;
 | 
|    }else{
 | 
| +    sqlite3_file *pFile;
 | 
| +
 | 
|      /* If the B-Tree was successfully opened, set the pager-cache size to the
 | 
|      ** default value. Except, when opening on an existing shared pager-cache,
 | 
|      ** do not change the pager-cache size.
 | 
| @@ -2403,11 +2412,17 @@ btree_open_out:
 | 
|      if( sqlite3BtreeSchema(p, 0, 0)==0 ){
 | 
|        sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
 | 
|      }
 | 
| +
 | 
| +    pFile = sqlite3PagerFile(pBt->pPager);
 | 
| +    if( pFile->pMethods ){
 | 
| +      sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db);
 | 
| +    }
 | 
|    }
 | 
|    if( mutexOpen ){
 | 
|      assert( sqlite3_mutex_held(mutexOpen) );
 | 
|      sqlite3_mutex_leave(mutexOpen);
 | 
|    }
 | 
| +  assert( rc!=SQLITE_OK || sqlite3BtreeConnectionCount(*ppBtree)>0 );
 | 
|    return rc;
 | 
|  }
 | 
|  
 | 
| @@ -2531,7 +2546,7 @@ int sqlite3BtreeClose(Btree *p){
 | 
|      ** Clean out and delete the BtShared object.
 | 
|      */
 | 
|      assert( !pBt->pCursor );
 | 
| -    sqlite3PagerClose(pBt->pPager);
 | 
| +    sqlite3PagerClose(pBt->pPager, p->db);
 | 
|      if( pBt->xFreeSchema && pBt->pSchema ){
 | 
|        pBt->xFreeSchema(pBt->pSchema);
 | 
|      }
 | 
| @@ -2625,21 +2640,6 @@ int sqlite3BtreeSetPagerFlags(
 | 
|  #endif
 | 
|  
 | 
|  /*
 | 
| -** Return TRUE if the given btree is set to safety level 1.  In other
 | 
| -** words, return TRUE if no sync() occurs on the disk files.
 | 
| -*/
 | 
| -int sqlite3BtreeSyncDisabled(Btree *p){
 | 
| -  BtShared *pBt = p->pBt;
 | 
| -  int rc;
 | 
| -  assert( sqlite3_mutex_held(p->db->mutex) );  
 | 
| -  sqlite3BtreeEnter(p);
 | 
| -  assert( pBt && pBt->pPager );
 | 
| -  rc = sqlite3PagerNosync(pBt->pPager);
 | 
| -  sqlite3BtreeLeave(p);
 | 
| -  return rc;
 | 
| -}
 | 
| -
 | 
| -/*
 | 
|  ** Change the default pages size and the number of reserved bytes per page.
 | 
|  ** Or, if the page size has already been fixed, return SQLITE_READONLY 
 | 
|  ** without changing anything.
 | 
| @@ -2884,9 +2884,25 @@ static int lockBtree(BtShared *pBt){
 | 
|        rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
 | 
|        if( rc!=SQLITE_OK ){
 | 
|          goto page1_init_failed;
 | 
| -      }else if( isOpen==0 ){
 | 
| -        releasePage(pPage1);
 | 
| -        return SQLITE_OK;
 | 
| +      }else{
 | 
| +#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
 | 
| +        sqlite3 *db;
 | 
| +        Db *pDb;
 | 
| +        if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
 | 
| +          while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
 | 
| +          if( pDb->bSyncSet==0
 | 
| +           && pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS+1
 | 
| +          ){
 | 
| +            pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS+1;
 | 
| +            sqlite3PagerSetFlags(pBt->pPager,
 | 
| +               pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
 | 
| +          }
 | 
| +        }
 | 
| +#endif
 | 
| +        if( isOpen==0 ){
 | 
| +          releasePage(pPage1);
 | 
| +          return SQLITE_OK;
 | 
| +        }
 | 
|        }
 | 
|        rc = SQLITE_NOTADB;
 | 
|      }
 | 
| @@ -3126,7 +3142,6 @@ int sqlite3BtreeNewDb(Btree *p){
 | 
|  ** proceed.
 | 
|  */
 | 
|  int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
 | 
| -  sqlite3 *pBlock = 0;
 | 
|    BtShared *pBt = p->pBt;
 | 
|    int rc = SQLITE_OK;
 | 
|  
 | 
| @@ -3149,27 +3164,30 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
 | 
|    }
 | 
|  
 | 
|  #ifndef SQLITE_OMIT_SHARED_CACHE
 | 
| -  /* If another database handle has already opened a write transaction 
 | 
| -  ** on this shared-btree structure and a second write transaction is
 | 
| -  ** requested, return SQLITE_LOCKED.
 | 
| -  */
 | 
| -  if( (wrflag && pBt->inTransaction==TRANS_WRITE)
 | 
| -   || (pBt->btsFlags & BTS_PENDING)!=0
 | 
| -  ){
 | 
| -    pBlock = pBt->pWriter->db;
 | 
| -  }else if( wrflag>1 ){
 | 
| -    BtLock *pIter;
 | 
| -    for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
 | 
| -      if( pIter->pBtree!=p ){
 | 
| -        pBlock = pIter->pBtree->db;
 | 
| -        break;
 | 
| +  {
 | 
| +    sqlite3 *pBlock = 0;
 | 
| +    /* If another database handle has already opened a write transaction 
 | 
| +    ** on this shared-btree structure and a second write transaction is
 | 
| +    ** requested, return SQLITE_LOCKED.
 | 
| +    */
 | 
| +    if( (wrflag && pBt->inTransaction==TRANS_WRITE)
 | 
| +     || (pBt->btsFlags & BTS_PENDING)!=0
 | 
| +    ){
 | 
| +      pBlock = pBt->pWriter->db;
 | 
| +    }else if( wrflag>1 ){
 | 
| +      BtLock *pIter;
 | 
| +      for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
 | 
| +        if( pIter->pBtree!=p ){
 | 
| +          pBlock = pIter->pBtree->db;
 | 
| +          break;
 | 
| +        }
 | 
|        }
 | 
|      }
 | 
| -  }
 | 
| -  if( pBlock ){
 | 
| -    sqlite3ConnectionBlocked(p->db, pBlock);
 | 
| -    rc = SQLITE_LOCKED_SHAREDCACHE;
 | 
| -    goto trans_begun;
 | 
| +    if( pBlock ){
 | 
| +      sqlite3ConnectionBlocked(p->db, pBlock);
 | 
| +      rc = SQLITE_LOCKED_SHAREDCACHE;
 | 
| +      goto trans_begun;
 | 
| +    }
 | 
|    }
 | 
|  #endif
 | 
|  
 | 
| @@ -3275,14 +3293,11 @@ static int setChildPtrmaps(MemPage *pPage){
 | 
|    int nCell;                         /* Number of cells in page pPage */
 | 
|    int rc;                            /* Return code */
 | 
|    BtShared *pBt = pPage->pBt;
 | 
| -  u8 isInitOrig = pPage->isInit;
 | 
|    Pgno pgno = pPage->pgno;
 | 
|  
 | 
|    assert( sqlite3_mutex_held(pPage->pBt->mutex) );
 | 
|    rc = btreeInitPage(pPage);
 | 
| -  if( rc!=SQLITE_OK ){
 | 
| -    goto set_child_ptrmaps_out;
 | 
| -  }
 | 
| +  if( rc!=SQLITE_OK ) return rc;
 | 
|    nCell = pPage->nCell;
 | 
|  
 | 
|    for(i=0; i<nCell; i++){
 | 
| @@ -3301,8 +3316,6 @@ static int setChildPtrmaps(MemPage *pPage){
 | 
|      ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc);
 | 
|    }
 | 
|  
 | 
| -set_child_ptrmaps_out:
 | 
| -  pPage->isInit = isInitOrig;
 | 
|    return rc;
 | 
|  }
 | 
|  
 | 
| @@ -3330,7 +3343,6 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
 | 
|      }
 | 
|      put4byte(pPage->aData, iTo);
 | 
|    }else{
 | 
| -    u8 isInitOrig = pPage->isInit;
 | 
|      int i;
 | 
|      int nCell;
 | 
|      int rc;
 | 
| @@ -3344,12 +3356,14 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
 | 
|        if( eType==PTRMAP_OVERFLOW1 ){
 | 
|          CellInfo info;
 | 
|          pPage->xParseCell(pPage, pCell, &info);
 | 
| -        if( info.nLocal<info.nPayload
 | 
| -         && pCell+info.nSize-1<=pPage->aData+pPage->maskPage
 | 
| -         && iFrom==get4byte(pCell+info.nSize-4)
 | 
| -        ){
 | 
| -          put4byte(pCell+info.nSize-4, iTo);
 | 
| -          break;
 | 
| +        if( info.nLocal<info.nPayload ){
 | 
| +          if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){
 | 
| +            return SQLITE_CORRUPT_BKPT;
 | 
| +          }
 | 
| +          if( iFrom==get4byte(pCell+info.nSize-4) ){
 | 
| +            put4byte(pCell+info.nSize-4, iTo);
 | 
| +            break;
 | 
| +          }
 | 
|          }
 | 
|        }else{
 | 
|          if( get4byte(pCell)==iFrom ){
 | 
| @@ -3366,8 +3380,6 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
 | 
|        }
 | 
|        put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
 | 
|      }
 | 
| -
 | 
| -    pPage->isInit = isInitOrig;
 | 
|    }
 | 
|    return SQLITE_OK;
 | 
|  }
 | 
| @@ -4026,7 +4038,12 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
 | 
|      assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
 | 
|      assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
 | 
|      sqlite3BtreeEnter(p);
 | 
| -    rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
 | 
| +    if( op==SAVEPOINT_ROLLBACK ){
 | 
| +      rc = saveAllCursors(pBt, 0, 0);
 | 
| +    }
 | 
| +    if( rc==SQLITE_OK ){
 | 
| +      rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
 | 
| +    }
 | 
|      if( rc==SQLITE_OK ){
 | 
|        if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
 | 
|          pBt->nPage = 0;
 | 
| @@ -4051,13 +4068,13 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
 | 
|  ** on the database already. If a write-cursor is requested, then
 | 
|  ** the caller is assumed to have an open write transaction.
 | 
|  **
 | 
| -** If wrFlag==0, then the cursor can only be used for reading.
 | 
| -** If wrFlag==1, then the cursor can be used for reading or for
 | 
| -** writing if other conditions for writing are also met.  These
 | 
| -** are the conditions that must be met in order for writing to
 | 
| -** be allowed:
 | 
| +** If the BTREE_WRCSR bit of wrFlag is clear, then the cursor can only
 | 
| +** be used for reading.  If the BTREE_WRCSR bit is set, then the cursor
 | 
| +** can be used for reading or for writing if other conditions for writing
 | 
| +** are also met.  These are the conditions that must be met in order
 | 
| +** for writing to be allowed:
 | 
|  **
 | 
| -** 1:  The cursor must have been opened with wrFlag==1
 | 
| +** 1:  The cursor must have been opened with wrFlag containing BTREE_WRCSR
 | 
|  **
 | 
|  ** 2:  Other database connections that share the same pager cache
 | 
|  **     but which are not in the READ_UNCOMMITTED state may not have
 | 
| @@ -4069,6 +4086,16 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
 | 
|  **
 | 
|  ** 4:  There must be an active transaction.
 | 
|  **
 | 
| +** The BTREE_FORDELETE bit of wrFlag may optionally be set if BTREE_WRCSR
 | 
| +** is set.  If FORDELETE is set, that is a hint to the implementation that
 | 
| +** this cursor will only be used to seek to and delete entries of an index
 | 
| +** as part of a larger DELETE statement.  The FORDELETE hint is not used by
 | 
| +** this implementation.  But in a hypothetical alternative storage engine 
 | 
| +** in which index entries are automatically deleted when corresponding table
 | 
| +** rows are deleted, the FORDELETE flag is a hint that all SEEK and DELETE
 | 
| +** operations on this cursor can be no-ops and all READ operations can 
 | 
| +** return a null row (2-bytes: 0x01 0x00).
 | 
| +**
 | 
|  ** No checking is done to make sure that page iTable really is the
 | 
|  ** root page of a b-tree.  If it is not, then the cursor acquired
 | 
|  ** will not work correctly.
 | 
| @@ -4107,7 +4134,7 @@ static int btreeCursor(
 | 
|  
 | 
|    if( wrFlag ){
 | 
|      allocateTempSpace(pBt);
 | 
| -    if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM;
 | 
| +    if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
 | 
|    }
 | 
|    if( iTable==1 && btreePagecount(pBt)==0 ){
 | 
|      assert( wrFlag==0 );
 | 
| @@ -4252,48 +4279,39 @@ int sqlite3BtreeCursorIsValid(BtCursor *pCur){
 | 
|    return pCur && pCur->eState==CURSOR_VALID;
 | 
|  }
 | 
|  #endif /* NDEBUG */
 | 
| +int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){
 | 
| +  assert( pCur!=0 );
 | 
| +  return pCur->eState==CURSOR_VALID;
 | 
| +}
 | 
|  
 | 
|  /*
 | 
| -** Set *pSize to the size of the buffer needed to hold the value of
 | 
| -** the key for the current entry.  If the cursor is not pointing
 | 
| -** to a valid entry, *pSize is set to 0. 
 | 
| -**
 | 
| -** For a table with the INTKEY flag set, this routine returns the key
 | 
| -** itself, not the number of bytes in the key.
 | 
| -**
 | 
| -** The caller must position the cursor prior to invoking this routine.
 | 
| -** 
 | 
| -** This routine cannot fail.  It always returns SQLITE_OK.  
 | 
| +** Return the value of the integer key or "rowid" for a table btree.
 | 
| +** This routine is only valid for a cursor that is pointing into a
 | 
| +** ordinary table btree.  If the cursor points to an index btree or
 | 
| +** is invalid, the result of this routine is undefined.
 | 
|  */
 | 
| -int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
 | 
| +i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
 | 
|    assert( cursorHoldsMutex(pCur) );
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
| +  assert( pCur->curIntKey );
 | 
|    getCellInfo(pCur);
 | 
| -  *pSize = pCur->info.nKey;
 | 
| -  return SQLITE_OK;
 | 
| +  return pCur->info.nKey;
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| -** Set *pSize to the number of bytes of data in the entry the
 | 
| -** cursor currently points to.
 | 
| +** Return the number of bytes of payload for the entry that pCur is
 | 
| +** currently pointing to.  For table btrees, this will be the amount
 | 
| +** of data.  For index btrees, this will be the size of the key.
 | 
|  **
 | 
|  ** The caller must guarantee that the cursor is pointing to a non-NULL
 | 
|  ** valid entry.  In other words, the calling procedure must guarantee
 | 
|  ** that the cursor has Cursor.eState==CURSOR_VALID.
 | 
| -**
 | 
| -** Failure is not possible.  This function always returns SQLITE_OK.
 | 
| -** It might just as well be a procedure (returning void) but we continue
 | 
| -** to return an integer result code for historical reasons.
 | 
|  */
 | 
| -int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
 | 
| +u32 sqlite3BtreePayloadSize(BtCursor *pCur){
 | 
|    assert( cursorHoldsMutex(pCur) );
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
| -  assert( pCur->iPage>=0 );
 | 
| -  assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
 | 
| -  assert( pCur->apPage[pCur->iPage]->intKeyLeaf==1 );
 | 
|    getCellInfo(pCur);
 | 
| -  *pSize = pCur->info.nPayload;
 | 
| -  return SQLITE_OK;
 | 
| +  return pCur->info.nPayload;
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| @@ -4411,7 +4429,6 @@ static int copyPayload(
 | 
|  **
 | 
|  **   0: The operation is a read. Populate the overflow cache.
 | 
|  **   1: The operation is a write. Populate the overflow cache.
 | 
| -**   2: The operation is a read. Do not populate the overflow cache.
 | 
|  **
 | 
|  ** A total of "amt" bytes are read or written beginning at "offset".
 | 
|  ** Data is read to or from the buffer pBuf.
 | 
| @@ -4419,13 +4436,13 @@ static int copyPayload(
 | 
|  ** The content being read or written might appear on the main page
 | 
|  ** or be scattered out on multiple overflow pages.
 | 
|  **
 | 
| -** If the current cursor entry uses one or more overflow pages and the
 | 
| -** eOp argument is not 2, this function may allocate space for and lazily 
 | 
| -** populates the overflow page-list cache array (BtCursor.aOverflow). 
 | 
| +** If the current cursor entry uses one or more overflow pages
 | 
| +** this function may allocate space for and lazily populate
 | 
| +** the overflow page-list cache array (BtCursor.aOverflow). 
 | 
|  ** Subsequent calls use this cache to make seeking to the supplied offset 
 | 
|  ** more efficient.
 | 
|  **
 | 
| -** Once an overflow page-list cache has been allocated, it may be
 | 
| +** Once an overflow page-list cache has been allocated, it must be
 | 
|  ** invalidated if some other cursor writes to the same table, or if
 | 
|  ** the cursor is moved to a different row. Additionally, in auto-vacuum
 | 
|  ** mode, the following events may invalidate an overflow page-list cache.
 | 
| @@ -4447,25 +4464,26 @@ static int accessPayload(
 | 
|    MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
 | 
|    BtShared *pBt = pCur->pBt;                  /* Btree this cursor belongs to */
 | 
|  #ifdef SQLITE_DIRECT_OVERFLOW_READ
 | 
| -  unsigned char * const pBufStart = pBuf;
 | 
| -  int bEnd;                                 /* True if reading to end of data */
 | 
| +  unsigned char * const pBufStart = pBuf;     /* Start of original out buffer */
 | 
|  #endif
 | 
|  
 | 
|    assert( pPage );
 | 
| +  assert( eOp==0 || eOp==1 );
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
|    assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
 | 
|    assert( cursorHoldsMutex(pCur) );
 | 
| -  assert( eOp!=2 || offset==0 );    /* Always start from beginning for eOp==2 */
 | 
|  
 | 
|    getCellInfo(pCur);
 | 
|    aPayload = pCur->info.pPayload;
 | 
| -#ifdef SQLITE_DIRECT_OVERFLOW_READ
 | 
| -  bEnd = offset+amt==pCur->info.nPayload;
 | 
| -#endif
 | 
|    assert( offset+amt <= pCur->info.nPayload );
 | 
|  
 | 
| -  if( &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ){
 | 
| -    /* Trying to read or write past the end of the data is an error */
 | 
| +  assert( aPayload > pPage->aData );
 | 
| +  if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){
 | 
| +    /* Trying to read or write past the end of the data is an error.  The
 | 
| +    ** conditional above is really:
 | 
| +    **    &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
 | 
| +    ** but is recast into its current form to avoid integer overflow problems
 | 
| +    */
 | 
|      return SQLITE_CORRUPT_BKPT;
 | 
|    }
 | 
|  
 | 
| @@ -4475,7 +4493,7 @@ static int accessPayload(
 | 
|      if( a+offset>pCur->info.nLocal ){
 | 
|        a = pCur->info.nLocal - offset;
 | 
|      }
 | 
| -    rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage);
 | 
| +    rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
 | 
|      offset = 0;
 | 
|      pBuf += a;
 | 
|      amt -= a;
 | 
| @@ -4491,53 +4509,46 @@ static int accessPayload(
 | 
|      nextPage = get4byte(&aPayload[pCur->info.nLocal]);
 | 
|  
 | 
|      /* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
 | 
| -    ** Except, do not allocate aOverflow[] for eOp==2.
 | 
|      **
 | 
|      ** The aOverflow[] array is sized at one entry for each overflow page
 | 
|      ** in the overflow chain. The page number of the first overflow page is
 | 
|      ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
 | 
|      ** means "not yet known" (the cache is lazily populated).
 | 
|      */
 | 
| -    if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
 | 
| +    if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
 | 
|        int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
 | 
|        if( nOvfl>pCur->nOvflAlloc ){
 | 
|          Pgno *aNew = (Pgno*)sqlite3Realloc(
 | 
|              pCur->aOverflow, nOvfl*2*sizeof(Pgno)
 | 
|          );
 | 
|          if( aNew==0 ){
 | 
| -          rc = SQLITE_NOMEM;
 | 
| +          return SQLITE_NOMEM_BKPT;
 | 
|          }else{
 | 
|            pCur->nOvflAlloc = nOvfl*2;
 | 
|            pCur->aOverflow = aNew;
 | 
|          }
 | 
|        }
 | 
| -      if( rc==SQLITE_OK ){
 | 
| -        memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
 | 
| -        pCur->curFlags |= BTCF_ValidOvfl;
 | 
| +      memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
 | 
| +      pCur->curFlags |= BTCF_ValidOvfl;
 | 
| +    }else{
 | 
| +      /* If the overflow page-list cache has been allocated and the
 | 
| +      ** entry for the first required overflow page is valid, skip
 | 
| +      ** directly to it.
 | 
| +      */
 | 
| +      if( pCur->aOverflow[offset/ovflSize] ){
 | 
| +        iIdx = (offset/ovflSize);
 | 
| +        nextPage = pCur->aOverflow[iIdx];
 | 
| +        offset = (offset%ovflSize);
 | 
|        }
 | 
|      }
 | 
|  
 | 
| -    /* If the overflow page-list cache has been allocated and the
 | 
| -    ** entry for the first required overflow page is valid, skip
 | 
| -    ** directly to it.
 | 
| -    */
 | 
| -    if( (pCur->curFlags & BTCF_ValidOvfl)!=0
 | 
| -     && pCur->aOverflow[offset/ovflSize]
 | 
| -    ){
 | 
| -      iIdx = (offset/ovflSize);
 | 
| -      nextPage = pCur->aOverflow[iIdx];
 | 
| -      offset = (offset%ovflSize);
 | 
| -    }
 | 
| -
 | 
| -    for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
 | 
| -
 | 
| +    assert( rc==SQLITE_OK && amt>0 );
 | 
| +    while( nextPage ){
 | 
|        /* If required, populate the overflow page-list cache. */
 | 
| -      if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
 | 
| -        assert( pCur->aOverflow[iIdx]==0
 | 
| -                || pCur->aOverflow[iIdx]==nextPage
 | 
| -                || CORRUPT_DB );
 | 
| -        pCur->aOverflow[iIdx] = nextPage;
 | 
| -      }
 | 
| +      assert( pCur->aOverflow[iIdx]==0
 | 
| +              || pCur->aOverflow[iIdx]==nextPage
 | 
| +              || CORRUPT_DB );
 | 
| +      pCur->aOverflow[iIdx] = nextPage;
 | 
|  
 | 
|        if( offset>=ovflSize ){
 | 
|          /* The only reason to read this page is to obtain the page
 | 
| @@ -4545,11 +4556,7 @@ static int accessPayload(
 | 
|          ** data is not required. So first try to lookup the overflow
 | 
|          ** page-list cache, if any, then fall back to the getOverflowPage()
 | 
|          ** function.
 | 
| -        **
 | 
| -        ** Note that the aOverflow[] array must be allocated because eOp!=2
 | 
| -        ** here.  If eOp==2, then offset==0 and this branch is never taken.
 | 
|          */
 | 
| -        assert( eOp!=2 );
 | 
|          assert( pCur->curFlags & BTCF_ValidOvfl );
 | 
|          assert( pCur->pBtree->db==pBt->db );
 | 
|          if( pCur->aOverflow[iIdx+1] ){
 | 
| @@ -4563,7 +4570,7 @@ static int accessPayload(
 | 
|          ** range of data that is being read (eOp==0) or written (eOp!=0).
 | 
|          */
 | 
|  #ifdef SQLITE_DIRECT_OVERFLOW_READ
 | 
| -        sqlite3_file *fd;
 | 
| +        sqlite3_file *fd;      /* File from which to do direct overflow read */
 | 
|  #endif
 | 
|          int a = amt;
 | 
|          if( a + offset > ovflSize ){
 | 
| @@ -4575,27 +4582,25 @@ static int accessPayload(
 | 
|          **
 | 
|          **   1) this is a read operation, and 
 | 
|          **   2) data is required from the start of this overflow page, and
 | 
| -        **   3) the database is file-backed, and
 | 
| -        **   4) there is no open write-transaction, and
 | 
| -        **   5) the database is not a WAL database,
 | 
| -        **   6) all data from the page is being read.
 | 
| -        **   7) at least 4 bytes have already been read into the output buffer 
 | 
| +        **   3) there is no open write-transaction, and
 | 
| +        **   4) the database is file-backed, and
 | 
| +        **   5) the page is not in the WAL file
 | 
| +        **   6) at least 4 bytes have already been read into the output buffer 
 | 
|          **
 | 
|          ** then data can be read directly from the database file into the
 | 
|          ** output buffer, bypassing the page-cache altogether. This speeds
 | 
|          ** up loading large records that span many overflow pages.
 | 
|          */
 | 
| -        if( (eOp&0x01)==0                                      /* (1) */
 | 
| +        if( eOp==0                                             /* (1) */
 | 
|           && offset==0                                          /* (2) */
 | 
| -         && (bEnd || a==ovflSize)                              /* (6) */
 | 
| -         && pBt->inTransaction==TRANS_READ                     /* (4) */
 | 
| -         && (fd = sqlite3PagerFile(pBt->pPager))->pMethods     /* (3) */
 | 
| -         && pBt->pPage1->aData[19]==0x01                       /* (5) */
 | 
| -         && &pBuf[-4]>=pBufStart                               /* (7) */
 | 
| +         && pBt->inTransaction==TRANS_READ                     /* (3) */
 | 
| +         && (fd = sqlite3PagerFile(pBt->pPager))->pMethods     /* (4) */
 | 
| +         && 0==sqlite3PagerUseWal(pBt->pPager, nextPage)       /* (5) */
 | 
| +         && &pBuf[-4]>=pBufStart                               /* (6) */
 | 
|          ){
 | 
|            u8 aSave[4];
 | 
|            u8 *aWrite = &pBuf[-4];
 | 
| -          assert( aWrite>=pBufStart );                         /* hence (7) */
 | 
| +          assert( aWrite>=pBufStart );                         /* due to (6) */
 | 
|            memcpy(aSave, aWrite, 4);
 | 
|            rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
 | 
|            nextPage = get4byte(aWrite);
 | 
| @@ -4606,41 +4611,49 @@ static int accessPayload(
 | 
|          {
 | 
|            DbPage *pDbPage;
 | 
|            rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
 | 
| -              ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
 | 
| +              (eOp==0 ? PAGER_GET_READONLY : 0)
 | 
|            );
 | 
|            if( rc==SQLITE_OK ){
 | 
|              aPayload = sqlite3PagerGetData(pDbPage);
 | 
|              nextPage = get4byte(aPayload);
 | 
| -            rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
 | 
| +            rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
 | 
|              sqlite3PagerUnref(pDbPage);
 | 
|              offset = 0;
 | 
|            }
 | 
|          }
 | 
|          amt -= a;
 | 
| +        if( amt==0 ) return rc;
 | 
|          pBuf += a;
 | 
|        }
 | 
| +      if( rc ) break;
 | 
| +      iIdx++;
 | 
|      }
 | 
|    }
 | 
|  
 | 
|    if( rc==SQLITE_OK && amt>0 ){
 | 
| -    return SQLITE_CORRUPT_BKPT;
 | 
| +    return SQLITE_CORRUPT_BKPT; /* Overflow chain ends prematurely */
 | 
|    }
 | 
|    return rc;
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| -** Read part of the key associated with cursor pCur.  Exactly
 | 
| -** "amt" bytes will be transferred into pBuf[].  The transfer
 | 
| +** Read part of the payload for the row at which that cursor pCur is currently
 | 
| +** pointing.  "amt" bytes will be transferred into pBuf[].  The transfer
 | 
|  ** begins at "offset".
 | 
|  **
 | 
| -** The caller must ensure that pCur is pointing to a valid row
 | 
| -** in the table.
 | 
| +** pCur can be pointing to either a table or an index b-tree.
 | 
| +** If pointing to a table btree, then the content section is read.  If
 | 
| +** pCur is pointing to an index b-tree then the key section is read.
 | 
| +**
 | 
| +** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing
 | 
| +** to a valid row in the table.  For sqlite3BtreePayloadChecked(), the
 | 
| +** cursor might be invalid or might need to be restored before being read.
 | 
|  **
 | 
|  ** Return SQLITE_OK on success or an error code if anything goes
 | 
|  ** wrong.  An error is returned if "offset+amt" is larger than
 | 
|  ** the available payload.
 | 
|  */
 | 
| -int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
 | 
| +int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
 | 
|    assert( cursorHoldsMutex(pCur) );
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
|    assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
 | 
| @@ -4649,33 +4662,34 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| -** Read part of the data associated with cursor pCur.  Exactly
 | 
| -** "amt" bytes will be transfered into pBuf[].  The transfer
 | 
| -** begins at "offset".
 | 
| -**
 | 
| -** Return SQLITE_OK on success or an error code if anything goes
 | 
| -** wrong.  An error is returned if "offset+amt" is larger than
 | 
| -** the available payload.
 | 
| +** This variant of sqlite3BtreePayload() works even if the cursor has not
 | 
| +** in the CURSOR_VALID state.  It is only used by the sqlite3_blob_read()
 | 
| +** interface.
 | 
|  */
 | 
| -int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
 | 
| -  int rc;
 | 
| -
 | 
|  #ifndef SQLITE_OMIT_INCRBLOB
 | 
| +static SQLITE_NOINLINE int accessPayloadChecked(
 | 
| +  BtCursor *pCur,
 | 
| +  u32 offset,
 | 
| +  u32 amt,
 | 
| +  void *pBuf
 | 
| +){
 | 
| +  int rc;
 | 
|    if ( pCur->eState==CURSOR_INVALID ){
 | 
|      return SQLITE_ABORT;
 | 
|    }
 | 
| -#endif
 | 
| -
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| -  rc = restoreCursorPosition(pCur);
 | 
| -  if( rc==SQLITE_OK ){
 | 
| -    assert( pCur->eState==CURSOR_VALID );
 | 
| -    assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
 | 
| -    assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
 | 
| -    rc = accessPayload(pCur, offset, amt, pBuf, 0);
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
| +  rc = btreeRestoreCursorPosition(pCur);
 | 
| +  return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0);
 | 
| +}
 | 
| +int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
 | 
| +  if( pCur->eState==CURSOR_VALID ){
 | 
| +    assert( cursorOwnsBtShared(pCur) );
 | 
| +    return accessPayload(pCur, offset, amt, pBuf, 0);
 | 
| +  }else{
 | 
| +    return accessPayloadChecked(pCur, offset, amt, pBuf);
 | 
|    }
 | 
| -  return rc;
 | 
|  }
 | 
| +#endif /* SQLITE_OMIT_INCRBLOB */
 | 
|  
 | 
|  /*
 | 
|  ** Return a pointer to payload information from the entry that the 
 | 
| @@ -4704,7 +4718,7 @@ static const void *fetchPayload(
 | 
|    assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
|    assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
 | 
|    assert( pCur->info.nSize>0 );
 | 
|    assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
 | 
| @@ -4730,10 +4744,7 @@ static const void *fetchPayload(
 | 
|  ** These routines is used to get quick access to key and data
 | 
|  ** in the common case where no overflow pages are used.
 | 
|  */
 | 
| -const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){
 | 
| -  return fetchPayload(pCur, pAmt);
 | 
| -}
 | 
| -const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){
 | 
| +const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){
 | 
|    return fetchPayload(pCur, pAmt);
 | 
|  }
 | 
|  
 | 
| @@ -4750,7 +4761,7 @@ const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){
 | 
|  static int moveToChild(BtCursor *pCur, u32 newPgno){
 | 
|    BtShared *pBt = pCur->pBt;
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
|    assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
 | 
|    assert( pCur->iPage>=0 );
 | 
| @@ -4796,7 +4807,7 @@ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
 | 
|  ** the largest cell index.
 | 
|  */
 | 
|  static void moveToParent(BtCursor *pCur){
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
|    assert( pCur->iPage>0 );
 | 
|    assert( pCur->apPage[pCur->iPage] );
 | 
| @@ -4836,7 +4847,7 @@ static int moveToRoot(BtCursor *pCur){
 | 
|    MemPage *pRoot;
 | 
|    int rc = SQLITE_OK;
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
 | 
|    assert( CURSOR_VALID   < CURSOR_REQUIRESEEK );
 | 
|    assert( CURSOR_FAULT   > CURSOR_REQUIRESEEK );
 | 
| @@ -4849,9 +4860,12 @@ static int moveToRoot(BtCursor *pCur){
 | 
|    }
 | 
|  
 | 
|    if( pCur->iPage>=0 ){
 | 
| -    while( pCur->iPage ){
 | 
| -      assert( pCur->apPage[pCur->iPage]!=0 );
 | 
| -      releasePageNotNull(pCur->apPage[pCur->iPage--]);
 | 
| +    if( pCur->iPage ){
 | 
| +      do{
 | 
| +        assert( pCur->apPage[pCur->iPage]!=0 );
 | 
| +        releasePageNotNull(pCur->apPage[pCur->iPage--]);
 | 
| +      }while( pCur->iPage);
 | 
| +      goto skip_init;
 | 
|      }
 | 
|    }else if( pCur->pgnoRoot==0 ){
 | 
|      pCur->eState = CURSOR_INVALID;
 | 
| @@ -4862,7 +4876,7 @@ static int moveToRoot(BtCursor *pCur){
 | 
|                          0, pCur->curPagerFlags);
 | 
|      if( rc!=SQLITE_OK ){
 | 
|        pCur->eState = CURSOR_INVALID;
 | 
| -      return rc;
 | 
| +       return rc;
 | 
|      }
 | 
|      pCur->iPage = 0;
 | 
|      pCur->curIntKey = pCur->apPage[0]->intKey;
 | 
| @@ -4885,10 +4899,12 @@ static int moveToRoot(BtCursor *pCur){
 | 
|      return SQLITE_CORRUPT_BKPT;
 | 
|    }
 | 
|  
 | 
| +skip_init:  
 | 
|    pCur->aiIdx[0] = 0;
 | 
|    pCur->info.nSize = 0;
 | 
|    pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
 | 
|  
 | 
| +  pRoot = pCur->apPage[0];
 | 
|    if( pRoot->nCell>0 ){
 | 
|      pCur->eState = CURSOR_VALID;
 | 
|    }else if( !pRoot->leaf ){
 | 
| @@ -4915,7 +4931,7 @@ static int moveToLeftmost(BtCursor *pCur){
 | 
|    int rc = SQLITE_OK;
 | 
|    MemPage *pPage;
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
|    while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
 | 
|      assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
 | 
| @@ -4940,7 +4956,7 @@ static int moveToRightmost(BtCursor *pCur){
 | 
|    int rc = SQLITE_OK;
 | 
|    MemPage *pPage = 0;
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
|    while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
 | 
|      pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
 | 
| @@ -4961,7 +4977,7 @@ static int moveToRightmost(BtCursor *pCur){
 | 
|  int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
 | 
|    int rc;
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
 | 
|    rc = moveToRoot(pCur);
 | 
|    if( rc==SQLITE_OK ){
 | 
| @@ -4984,7 +5000,7 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
 | 
|  int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
 | 
|    int rc;
 | 
|   
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
 | 
|  
 | 
|    /* If the cursor already points to the last entry, this is a no-op. */
 | 
| @@ -5062,23 +5078,41 @@ int sqlite3BtreeMovetoUnpacked(
 | 
|    int rc;
 | 
|    RecordCompare xRecordCompare;
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
 | 
|    assert( pRes );
 | 
|    assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
 | 
| +  assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) );
 | 
|  
 | 
|    /* If the cursor is already positioned at the point we are trying
 | 
|    ** to move to, then just return without doing any work */
 | 
| -  if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
 | 
| -   && pCur->curIntKey 
 | 
| +  if( pIdxKey==0
 | 
| +   && pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
 | 
|    ){
 | 
|      if( pCur->info.nKey==intKey ){
 | 
|        *pRes = 0;
 | 
|        return SQLITE_OK;
 | 
|      }
 | 
| -    if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
 | 
| -      *pRes = -1;
 | 
| -      return SQLITE_OK;
 | 
| +    if( pCur->info.nKey<intKey ){
 | 
| +      if( (pCur->curFlags & BTCF_AtLast)!=0 ){
 | 
| +        *pRes = -1;
 | 
| +        return SQLITE_OK;
 | 
| +      }
 | 
| +      /* If the requested key is one more than the previous key, then
 | 
| +      ** try to get there using sqlite3BtreeNext() rather than a full
 | 
| +      ** binary search.  This is an optimization only.  The correct answer
 | 
| +      ** is still obtained without this ase, only a little more slowely */
 | 
| +      if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
 | 
| +        *pRes = 0;
 | 
| +        rc = sqlite3BtreeNext(pCur, pRes);
 | 
| +        if( rc ) return rc;
 | 
| +        if( *pRes==0 ){
 | 
| +          getCellInfo(pCur);
 | 
| +          if( pCur->info.nKey==intKey ){
 | 
| +            return SQLITE_OK;
 | 
| +          }
 | 
| +        }
 | 
| +      }
 | 
|      }
 | 
|    }
 | 
|  
 | 
| @@ -5144,16 +5178,16 @@ int sqlite3BtreeMovetoUnpacked(
 | 
|            if( lwr>upr ){ c = +1; break; }
 | 
|          }else{
 | 
|            assert( nCellKey==intKey );
 | 
| -          pCur->curFlags |= BTCF_ValidNKey;
 | 
| -          pCur->info.nKey = nCellKey;
 | 
|            pCur->aiIdx[pCur->iPage] = (u16)idx;
 | 
|            if( !pPage->leaf ){
 | 
|              lwr = idx;
 | 
|              goto moveto_next_layer;
 | 
|            }else{
 | 
| +            pCur->curFlags |= BTCF_ValidNKey;
 | 
| +            pCur->info.nKey = nCellKey;
 | 
| +            pCur->info.nSize = 0;
 | 
|              *pRes = 0;
 | 
| -            rc = SQLITE_OK;
 | 
| -            goto moveto_finish;
 | 
| +            return SQLITE_OK;
 | 
|            }
 | 
|          }
 | 
|          assert( lwr+upr>=0 );
 | 
| @@ -5210,11 +5244,12 @@ int sqlite3BtreeMovetoUnpacked(
 | 
|            }
 | 
|            pCellKey = sqlite3Malloc( nCell+18 );
 | 
|            if( pCellKey==0 ){
 | 
| -            rc = SQLITE_NOMEM;
 | 
| +            rc = SQLITE_NOMEM_BKPT;
 | 
|              goto moveto_finish;
 | 
|            }
 | 
|            pCur->aiIdx[pCur->iPage] = (u16)idx;
 | 
| -          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
 | 
| +          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
 | 
| +          pCur->curFlags &= ~BTCF_ValidOvfl;
 | 
|            if( rc ){
 | 
|              sqlite3_free(pCellKey);
 | 
|              goto moveto_finish;
 | 
| @@ -5264,7 +5299,7 @@ moveto_next_layer:
 | 
|    }
 | 
|  moveto_finish:
 | 
|    pCur->info.nSize = 0;
 | 
| -  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
 | 
| +  assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
 | 
|    return rc;
 | 
|  }
 | 
|  
 | 
| @@ -5310,7 +5345,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
 | 
|    int idx;
 | 
|    MemPage *pPage;
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
 | 
|    assert( *pRes==0 );
 | 
|    if( pCur->eState!=CURSOR_VALID ){
 | 
| @@ -5374,7 +5409,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
 | 
|  }
 | 
|  int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
 | 
|    MemPage *pPage;
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pRes!=0 );
 | 
|    assert( *pRes==0 || *pRes==1 );
 | 
|    assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
 | 
| @@ -5419,7 +5454,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
 | 
|    int rc;
 | 
|    MemPage *pPage;
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pRes!=0 );
 | 
|    assert( *pRes==0 );
 | 
|    assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
 | 
| @@ -5462,7 +5497,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
 | 
|        moveToParent(pCur);
 | 
|      }
 | 
|      assert( pCur->info.nSize==0 );
 | 
| -    assert( (pCur->curFlags & (BTCF_ValidNKey|BTCF_ValidOvfl))==0 );
 | 
| +    assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 );
 | 
|  
 | 
|      pCur->aiIdx[pCur->iPage]--;
 | 
|      pPage = pCur->apPage[pCur->iPage];
 | 
| @@ -5475,7 +5510,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
 | 
|    return rc;
 | 
|  }
 | 
|  int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pRes!=0 );
 | 
|    assert( *pRes==0 || *pRes==1 );
 | 
|    assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
 | 
| @@ -5978,30 +6013,28 @@ static void freePage(MemPage *pPage, int *pRC){
 | 
|  static int clearCell(
 | 
|    MemPage *pPage,          /* The page that contains the Cell */
 | 
|    unsigned char *pCell,    /* First byte of the Cell */
 | 
| -  u16 *pnSize              /* Write the size of the Cell here */
 | 
| +  CellInfo *pInfo          /* Size information about the cell */
 | 
|  ){
 | 
|    BtShared *pBt = pPage->pBt;
 | 
| -  CellInfo info;
 | 
|    Pgno ovflPgno;
 | 
|    int rc;
 | 
|    int nOvfl;
 | 
|    u32 ovflPageSize;
 | 
|  
 | 
|    assert( sqlite3_mutex_held(pPage->pBt->mutex) );
 | 
| -  pPage->xParseCell(pPage, pCell, &info);
 | 
| -  *pnSize = info.nSize;
 | 
| -  if( info.nLocal==info.nPayload ){
 | 
| +  pPage->xParseCell(pPage, pCell, pInfo);
 | 
| +  if( pInfo->nLocal==pInfo->nPayload ){
 | 
|      return SQLITE_OK;  /* No overflow pages. Return without doing anything */
 | 
|    }
 | 
| -  if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){
 | 
| +  if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){
 | 
|      return SQLITE_CORRUPT_BKPT;  /* Cell extends past end of page */
 | 
|    }
 | 
| -  ovflPgno = get4byte(pCell + info.nSize - 4);
 | 
| +  ovflPgno = get4byte(pCell + pInfo->nSize - 4);
 | 
|    assert( pBt->usableSize > 4 );
 | 
|    ovflPageSize = pBt->usableSize - 4;
 | 
| -  nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
 | 
| +  nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
 | 
|    assert( nOvfl>0 || 
 | 
| -    (CORRUPT_DB && (info.nPayload + ovflPageSize)<ovflPageSize)
 | 
| +    (CORRUPT_DB && (pInfo->nPayload + ovflPageSize)<ovflPageSize)
 | 
|    );
 | 
|    while( nOvfl-- ){
 | 
|      Pgno iNext = 0;
 | 
| @@ -6059,9 +6092,7 @@ static int clearCell(
 | 
|  static int fillInCell(
 | 
|    MemPage *pPage,                /* The page that contains the cell */
 | 
|    unsigned char *pCell,          /* Complete text of the cell */
 | 
| -  const void *pKey, i64 nKey,    /* The key */
 | 
| -  const void *pData,int nData,   /* The data */
 | 
| -  int nZero,                     /* Extra zero bytes to append to pData */
 | 
| +  const BtreePayload *pX,        /* Payload with which to construct the cell */
 | 
|    int *pnSize                    /* Write cell size here */
 | 
|  ){
 | 
|    int nPayload;
 | 
| @@ -6085,26 +6116,21 @@ static int fillInCell(
 | 
|  
 | 
|    /* Fill in the header. */
 | 
|    nHeader = pPage->childPtrSize;
 | 
| -  nPayload = nData + nZero;
 | 
| -  if( pPage->intKeyLeaf ){
 | 
| +  if( pPage->intKey ){
 | 
| +    nPayload = pX->nData + pX->nZero;
 | 
| +    pSrc = pX->pData;
 | 
| +    nSrc = pX->nData;
 | 
| +    assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */
 | 
|      nHeader += putVarint32(&pCell[nHeader], nPayload);
 | 
| +    nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey);
 | 
|    }else{
 | 
| -    assert( nData==0 );
 | 
| -    assert( nZero==0 );
 | 
| +    assert( pX->nKey<=0x7fffffff && pX->pKey!=0 );
 | 
| +    nSrc = nPayload = (int)pX->nKey;
 | 
| +    pSrc = pX->pKey;
 | 
| +    nHeader += putVarint32(&pCell[nHeader], nPayload);
 | 
|    }
 | 
| -  nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey);
 | 
|    
 | 
| -  /* Fill in the payload size */
 | 
| -  if( pPage->intKey ){
 | 
| -    pSrc = pData;
 | 
| -    nSrc = nData;
 | 
| -    nData = 0;
 | 
| -  }else{ 
 | 
| -    assert( nKey<=0x7fffffff && pKey!=0 );
 | 
| -    nPayload = (int)nKey;
 | 
| -    pSrc = pKey;
 | 
| -    nSrc = (int)nKey;
 | 
| -  }
 | 
| +  /* Fill in the payload */
 | 
|    if( nPayload<=pPage->maxLocal ){
 | 
|      n = nHeader + nPayload;
 | 
|      testcase( n==3 );
 | 
| @@ -6141,8 +6167,8 @@ static int fillInCell(
 | 
|    {
 | 
|      CellInfo info;
 | 
|      pPage->xParseCell(pPage, pCell, &info);
 | 
| -    assert( nHeader=(int)(info.pPayload - pCell) );
 | 
| -    assert( info.nKey==nKey );
 | 
| +    assert( nHeader==(int)(info.pPayload - pCell) );
 | 
| +    assert( info.nKey==pX->nKey );
 | 
|      assert( *pnSize == info.nSize );
 | 
|      assert( spaceLeft == info.nLocal );
 | 
|    }
 | 
| @@ -6227,10 +6253,6 @@ static int fillInCell(
 | 
|      pSrc += n;
 | 
|      nSrc -= n;
 | 
|      spaceLeft -= n;
 | 
| -    if( nSrc==0 ){
 | 
| -      nSrc = nData;
 | 
| -      pSrc = pData;
 | 
| -    }
 | 
|    }
 | 
|    releasePage(pToRelease);
 | 
|    return SQLITE_OK;
 | 
| @@ -6252,7 +6274,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
 | 
|    int hdr;        /* Beginning of the header.  0 most pages.  100 page 1 */
 | 
|  
 | 
|    if( *pRC ) return;
 | 
| -
 | 
|    assert( idx>=0 && idx<pPage->nCell );
 | 
|    assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
 | 
|    assert( sqlite3PagerIswriteable(pPage->pDbPage) );
 | 
| @@ -6297,6 +6318,8 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
 | 
|  ** in pTemp or the original pCell) and also record its index. 
 | 
|  ** Allocating a new entry in pPage->aCell[] implies that 
 | 
|  ** pPage->nOverflow is incremented.
 | 
| +**
 | 
| +** *pRC must be SQLITE_OK when this routine is called.
 | 
|  */
 | 
|  static void insertCell(
 | 
|    MemPage *pPage,   /* Page into which we are copying */
 | 
| @@ -6312,8 +6335,7 @@ static void insertCell(
 | 
|    u8 *data;         /* The content of the whole page */
 | 
|    u8 *pIns;         /* The point in pPage->aCellIdx[] where no cell inserted */
 | 
|  
 | 
| -  if( *pRC ) return;
 | 
| -
 | 
| +  assert( *pRC==SQLITE_OK );
 | 
|    assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
 | 
|    assert( MX_CELL(pPage->pBt)<=10921 );
 | 
|    assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB );
 | 
| @@ -6335,7 +6357,10 @@ static void insertCell(
 | 
|        put4byte(pCell, iChild);
 | 
|      }
 | 
|      j = pPage->nOverflow++;
 | 
| -    assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) );
 | 
| +    /* Comparison against ArraySize-1 since we hold back one extra slot
 | 
| +    ** as a contingency.  In other words, never need more than 3 overflow
 | 
| +    ** slots but 4 are allocated, just to be safe. */
 | 
| +    assert( j < ArraySize(pPage->apOvfl)-1 );
 | 
|      pPage->apOvfl[j] = pCell;
 | 
|      pPage->aiOvfl[j] = (u16)i;
 | 
|  
 | 
| @@ -6387,7 +6412,7 @@ static void insertCell(
 | 
|  
 | 
|  /*
 | 
|  ** A CellArray object contains a cache of pointers and sizes for a
 | 
| -** consecutive sequence of cells that might be held multiple pages.
 | 
| +** consecutive sequence of cells that might be held on multiple pages.
 | 
|  */
 | 
|  typedef struct CellArray CellArray;
 | 
|  struct CellArray {
 | 
| @@ -6532,8 +6557,8 @@ static int pageInsertArray(
 | 
|      u8 *pSlot;
 | 
|      sz = cachedCellSize(pCArray, i);
 | 
|      if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
 | 
| +      if( (pData - pBegin)<sz ) return 1;
 | 
|        pData -= sz;
 | 
| -      if( pData<pBegin ) return 1;
 | 
|        pSlot = pData;
 | 
|      }
 | 
|      /* pSlot and pCArray->apCell[i] will never overlap on a well-formed
 | 
| @@ -6695,7 +6720,7 @@ static int editPage(
 | 
|    for(i=0; i<nNew && !CORRUPT_DB; i++){
 | 
|      u8 *pCell = pCArray->apCell[i+iNew];
 | 
|      int iOff = get2byteAligned(&pPg->aCellIdx[i*2]);
 | 
| -    if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){
 | 
| +    if( SQLITE_WITHIN(pCell, aData, &aData[pPg->pBt->usableSize]) ){
 | 
|        pCell = &pTmp[pCell - aData];
 | 
|      }
 | 
|      assert( 0==memcmp(pCell, &aData[iOff],
 | 
| @@ -6819,8 +6844,10 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
 | 
|      while( ((*(pOut++) = *(pCell++))&0x80) && pCell<pStop );
 | 
|  
 | 
|      /* Insert the new divider cell into pParent. */
 | 
| -    insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace),
 | 
| -               0, pPage->pgno, &rc);
 | 
| +    if( rc==SQLITE_OK ){
 | 
| +      insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace),
 | 
| +                   0, pPage->pgno, &rc);
 | 
| +    }
 | 
|  
 | 
|      /* Set the right-child pointer of pParent to point to the new page. */
 | 
|      put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
 | 
| @@ -7029,7 +7056,7 @@ static int balance_nonroot(
 | 
|    assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );
 | 
|  
 | 
|    if( !aOvflSpace ){
 | 
| -    return SQLITE_NOMEM;
 | 
| +    return SQLITE_NOMEM_BKPT;
 | 
|    }
 | 
|  
 | 
|    /* Find the sibling pages to balance. Also locate the cells in pParent 
 | 
| @@ -7073,7 +7100,7 @@ static int balance_nonroot(
 | 
|      nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
 | 
|      if( (i--)==0 ) break;
 | 
|  
 | 
| -    if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){
 | 
| +    if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
 | 
|        apDiv[i] = pParent->apOvfl[0];
 | 
|        pgno = get4byte(apDiv[i]);
 | 
|        szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
 | 
| @@ -7129,7 +7156,7 @@ static int balance_nonroot(
 | 
|    assert( szScratch<=6*(int)pBt->pageSize );
 | 
|    b.apCell = sqlite3ScratchMalloc( szScratch ); 
 | 
|    if( b.apCell==0 ){
 | 
| -    rc = SQLITE_NOMEM;
 | 
| +    rc = SQLITE_NOMEM_BKPT;
 | 
|      goto balance_cleanup;
 | 
|    }
 | 
|    b.szCell = (u16*)&b.apCell[nMaxCells];
 | 
| @@ -7188,9 +7215,8 @@ static int balance_nonroot(
 | 
|      ** long be able to find the cells if a pointer to each cell is not saved
 | 
|      ** first.
 | 
|      */
 | 
| -    memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*limit);
 | 
| +    memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
 | 
|      if( pOld->nOverflow>0 ){
 | 
| -      memset(&b.szCell[b.nCell+limit], 0, sizeof(b.szCell[0])*pOld->nOverflow);
 | 
|        limit = pOld->aiOvfl[0];
 | 
|        for(j=0; j<limit; j++){
 | 
|          b.apCell[b.nCell] = aData + (maskPage & get2byteAligned(piCell));
 | 
| @@ -7266,7 +7292,6 @@ static int balance_nonroot(
 | 
|    for(i=0; i<nOld; i++){
 | 
|      MemPage *p = apOld[i];
 | 
|      szNew[i] = usableSpace - p->nFree;
 | 
| -    if( szNew[i]<0 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
 | 
|      for(j=0; j<p->nOverflow; j++){
 | 
|        szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
 | 
|      }
 | 
| @@ -7341,7 +7366,7 @@ static int balance_nonroot(
 | 
|        assert( r<nMaxCells );
 | 
|        (void)cachedCellSize(&b, r);
 | 
|        if( szRight!=0
 | 
| -       && (bBulk || szRight+b.szCell[d]+2 > szLeft-(b.szCell[r]+2)) ){
 | 
| +       && (bBulk || szRight+b.szCell[d]+2 > szLeft-(b.szCell[r]+(i==k-1?0:2)))){
 | 
|          break;
 | 
|        }
 | 
|        szRight += b.szCell[d] + 2;
 | 
| @@ -7565,9 +7590,9 @@ static int balance_nonroot(
 | 
|        ** any cell). But it is important to pass the correct size to 
 | 
|        ** insertCell(), so reparse the cell now.
 | 
|        **
 | 
| -      ** Note that this can never happen in an SQLite data file, as all
 | 
| -      ** cells are at least 4 bytes. It only happens in b-trees used
 | 
| -      ** to evaluate "IN (SELECT ...)" and similar clauses.
 | 
| +      ** This can only happen for b-trees used to evaluate "IN (SELECT ...)"
 | 
| +      ** and WITHOUT ROWID tables with exactly one column which is the
 | 
| +      ** primary key.
 | 
|        */
 | 
|        if( b.szCell[j]==4 ){
 | 
|          assert(leafCorrection==4);
 | 
| @@ -7801,8 +7826,8 @@ static int balance(BtCursor *pCur){
 | 
|    u8 aBalanceQuickSpace[13];
 | 
|    u8 *pFree = 0;
 | 
|  
 | 
| -  TESTONLY( int balance_quick_called = 0 );
 | 
| -  TESTONLY( int balance_deeper_called = 0 );
 | 
| +  VVA_ONLY( int balance_quick_called = 0 );
 | 
| +  VVA_ONLY( int balance_deeper_called = 0 );
 | 
|  
 | 
|    do {
 | 
|      int iPage = pCur->iPage;
 | 
| @@ -7815,7 +7840,8 @@ static int balance(BtCursor *pCur){
 | 
|          ** and copy the current contents of the root-page to it. The
 | 
|          ** next iteration of the do-loop will balance the child page.
 | 
|          */ 
 | 
| -        assert( (balance_deeper_called++)==0 );
 | 
| +        assert( balance_deeper_called==0 );
 | 
| +        VVA_ONLY( balance_deeper_called++ );
 | 
|          rc = balance_deeper(pPage, &pCur->apPage[1]);
 | 
|          if( rc==SQLITE_OK ){
 | 
|            pCur->iPage = 1;
 | 
| @@ -7854,7 +7880,8 @@ static int balance(BtCursor *pCur){
 | 
|            ** function. If this were not verified, a subtle bug involving reuse
 | 
|            ** of the aBalanceQuickSpace[] might sneak in.
 | 
|            */
 | 
| -          assert( (balance_quick_called++)==0 );
 | 
| +          assert( balance_quick_called==0 ); 
 | 
| +          VVA_ONLY( balance_quick_called++ );
 | 
|            rc = balance_quick(pParent, pPage, aBalanceQuickSpace);
 | 
|          }else
 | 
|  #endif
 | 
| @@ -7911,33 +7938,39 @@ static int balance(BtCursor *pCur){
 | 
|  
 | 
|  
 | 
|  /*
 | 
| -** Insert a new record into the BTree.  The key is given by (pKey,nKey)
 | 
| -** and the data is given by (pData,nData).  The cursor is used only to
 | 
| -** define what table the record should be inserted into.  The cursor
 | 
| -** is left pointing at a random location.
 | 
| +** Insert a new record into the BTree.  The content of the new record
 | 
| +** is described by the pX object.  The pCur cursor is used only to
 | 
| +** define what table the record should be inserted into, and is left
 | 
| +** pointing at a random location.
 | 
| +**
 | 
| +** For a table btree (used for rowid tables), only the pX.nKey value of
 | 
| +** the key is used. The pX.pKey value must be NULL.  The pX.nKey is the
 | 
| +** rowid or INTEGER PRIMARY KEY of the row.  The pX.nData,pData,nZero fields
 | 
| +** hold the content of the row.
 | 
|  **
 | 
| -** For an INTKEY table, only the nKey value of the key is used.  pKey is
 | 
| -** ignored.  For a ZERODATA table, the pData and nData are both ignored.
 | 
| +** For an index btree (used for indexes and WITHOUT ROWID tables), the
 | 
| +** key is an arbitrary byte sequence stored in pX.pKey,nKey.  The 
 | 
| +** pX.pData,nData,nZero fields must be zero.
 | 
|  **
 | 
|  ** If the seekResult parameter is non-zero, then a successful call to
 | 
| -** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already
 | 
| -** been performed. seekResult is the search result returned (a negative
 | 
| -** number if pCur points at an entry that is smaller than (pKey, nKey), or
 | 
| -** a positive value if pCur points at an entry that is larger than 
 | 
| -** (pKey, nKey)). 
 | 
| -**
 | 
| -** If the seekResult parameter is non-zero, then the caller guarantees that
 | 
| -** cursor pCur is pointing at the existing copy of a row that is to be
 | 
| -** overwritten.  If the seekResult parameter is 0, then cursor pCur may
 | 
| -** point to any entry or to no entry at all and so this function has to seek
 | 
| -** the cursor before the new key can be inserted.
 | 
| +** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already
 | 
| +** been performed.  In other words, if seekResult!=0 then the cursor
 | 
| +** is currently pointing to a cell that will be adjacent to the cell
 | 
| +** to be inserted.  If seekResult<0 then pCur points to a cell that is
 | 
| +** smaller then (pKey,nKey).  If seekResult>0 then pCur points to a cell
 | 
| +** that is larger than (pKey,nKey).
 | 
| +**
 | 
| +** If seekResult==0, that means pCur is pointing at some unknown location.
 | 
| +** In that case, this routine must seek the cursor to the correct insertion
 | 
| +** point for (pKey,nKey) before doing the insertion.  For index btrees,
 | 
| +** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked
 | 
| +** key values and pX->aMem can be used instead of pX->pKey to avoid having
 | 
| +** to decode the key.
 | 
|  */
 | 
|  int sqlite3BtreeInsert(
 | 
|    BtCursor *pCur,                /* Insert data into the table of this cursor */
 | 
| -  const void *pKey, i64 nKey,    /* The key of the new record */
 | 
| -  const void *pData, int nData,  /* The data of the new record */
 | 
| -  int nZero,                     /* Number of extra 0 bytes to append to data */
 | 
| -  int appendBias,                /* True if this is likely an append */
 | 
| +  const BtreePayload *pX,        /* Content of the row to be inserted */
 | 
| +  int flags,                     /* True if this is likely an append */
 | 
|    int seekResult                 /* Result of prior MovetoUnpacked() call */
 | 
|  ){
 | 
|    int rc;
 | 
| @@ -7950,12 +7983,14 @@ int sqlite3BtreeInsert(
 | 
|    unsigned char *oldCell;
 | 
|    unsigned char *newCell = 0;
 | 
|  
 | 
| +  assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
 | 
| +
 | 
|    if( pCur->eState==CURSOR_FAULT ){
 | 
|      assert( pCur->skipNext!=SQLITE_OK );
 | 
|      return pCur->skipNext;
 | 
|    }
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( (pCur->curFlags & BTCF_WriteFlag)!=0
 | 
|                && pBt->inTransaction==TRANS_WRITE
 | 
|                && (pBt->btsFlags & BTS_READ_ONLY)==0 );
 | 
| @@ -7966,7 +8001,7 @@ int sqlite3BtreeInsert(
 | 
|    ** keys with no associated data. If the cursor was opened expecting an
 | 
|    ** intkey table, the caller should be inserting integer keys with a
 | 
|    ** blob of associated data.  */
 | 
| -  assert( (pKey==0)==(pCur->pKeyInfo==0) );
 | 
| +  assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
 | 
|  
 | 
|    /* Save the positions of any other cursors open on this table.
 | 
|    **
 | 
| @@ -7985,44 +8020,64 @@ int sqlite3BtreeInsert(
 | 
|    }
 | 
|  
 | 
|    if( pCur->pKeyInfo==0 ){
 | 
| -    assert( pKey==0 );
 | 
| +    assert( pX->pKey==0 );
 | 
|      /* If this is an insert into a table b-tree, invalidate any incrblob 
 | 
|      ** cursors open on the row being replaced */
 | 
| -    invalidateIncrblobCursors(p, nKey, 0);
 | 
| +    invalidateIncrblobCursors(p, pX->nKey, 0);
 | 
| +
 | 
| +    /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing 
 | 
| +    ** to a row with the same key as the new entry being inserted.  */
 | 
| +    assert( (flags & BTREE_SAVEPOSITION)==0 || 
 | 
| +            ((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) );
 | 
|  
 | 
|      /* If the cursor is currently on the last row and we are appending a
 | 
|      ** new row onto the end, set the "loc" to avoid an unnecessary
 | 
|      ** btreeMoveto() call */
 | 
| -    if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0
 | 
| -      && pCur->info.nKey==nKey-1 ){
 | 
| -       loc = -1;
 | 
| +    if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){
 | 
| +      loc = 0;
 | 
| +    }else if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0
 | 
| +               && pCur->info.nKey==pX->nKey-1 ){
 | 
| +      loc = -1;
 | 
|      }else if( loc==0 ){
 | 
| -      rc = sqlite3BtreeMovetoUnpacked(pCur, 0, nKey, appendBias, &loc);
 | 
| +      rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
 | 
|        if( rc ) return rc;
 | 
|      }
 | 
| -  }else if( loc==0 ){
 | 
| -    rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc);
 | 
| +  }else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){
 | 
| +    if( pX->nMem ){
 | 
| +      UnpackedRecord r;
 | 
| +      r.pKeyInfo = pCur->pKeyInfo;
 | 
| +      r.aMem = pX->aMem;
 | 
| +      r.nField = pX->nMem;
 | 
| +      r.default_rc = 0;
 | 
| +      r.errCode = 0;
 | 
| +      r.r1 = 0;
 | 
| +      r.r2 = 0;
 | 
| +      r.eqSeen = 0;
 | 
| +      rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
 | 
| +    }else{
 | 
| +      rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
 | 
| +    }
 | 
|      if( rc ) return rc;
 | 
|    }
 | 
|    assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
 | 
|  
 | 
|    pPage = pCur->apPage[pCur->iPage];
 | 
| -  assert( pPage->intKey || nKey>=0 );
 | 
| +  assert( pPage->intKey || pX->nKey>=0 );
 | 
|    assert( pPage->leaf || !pPage->intKey );
 | 
|  
 | 
|    TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
 | 
| -          pCur->pgnoRoot, nKey, nData, pPage->pgno,
 | 
| +          pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
 | 
|            loc==0 ? "overwrite" : "new entry"));
 | 
|    assert( pPage->isInit );
 | 
|    newCell = pBt->pTmpSpace;
 | 
|    assert( newCell!=0 );
 | 
| -  rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew);
 | 
| +  rc = fillInCell(pPage, newCell, pX, &szNew);
 | 
|    if( rc ) goto end_insert;
 | 
|    assert( szNew==pPage->xCellSize(pPage, newCell) );
 | 
|    assert( szNew <= MX_CELL_SIZE(pBt) );
 | 
|    idx = pCur->aiIdx[pCur->iPage];
 | 
|    if( loc==0 ){
 | 
| -    u16 szOld;
 | 
| +    CellInfo info;
 | 
|      assert( idx<pPage->nCell );
 | 
|      rc = sqlite3PagerWrite(pPage->pDbPage);
 | 
|      if( rc ){
 | 
| @@ -8032,8 +8087,19 @@ int sqlite3BtreeInsert(
 | 
|      if( !pPage->leaf ){
 | 
|        memcpy(newCell, oldCell, 4);
 | 
|      }
 | 
| -    rc = clearCell(pPage, oldCell, &szOld);
 | 
| -    dropCell(pPage, idx, szOld, &rc);
 | 
| +    rc = clearCell(pPage, oldCell, &info);
 | 
| +    if( info.nSize==szNew && info.nLocal==info.nPayload ){
 | 
| +      /* Overwrite the old cell with the new if they are the same size.
 | 
| +      ** We could also try to do this if the old cell is smaller, then add
 | 
| +      ** the leftover space to the free list.  But experiments show that
 | 
| +      ** doing that is no faster then skipping this optimization and just
 | 
| +      ** calling dropCell() and insertCell(). */
 | 
| +      assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
 | 
| +      if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
 | 
| +      memcpy(oldCell, newCell, szNew);
 | 
| +      return SQLITE_OK;
 | 
| +    }
 | 
| +    dropCell(pPage, idx, info.nSize, &rc);
 | 
|      if( rc ) goto end_insert;
 | 
|    }else if( loc<0 && pPage->nCell>0 ){
 | 
|      assert( pPage->leaf );
 | 
| @@ -8042,6 +8108,7 @@ int sqlite3BtreeInsert(
 | 
|      assert( pPage->leaf );
 | 
|    }
 | 
|    insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
 | 
| +  assert( pPage->nOverflow==0 || rc==SQLITE_OK );
 | 
|    assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
 | 
|  
 | 
|    /* If no error has occurred and pPage has an overflow cell, call balance() 
 | 
| @@ -8065,7 +8132,8 @@ int sqlite3BtreeInsert(
 | 
|    ** row without seeking the cursor. This can be a big performance boost.
 | 
|    */
 | 
|    pCur->info.nSize = 0;
 | 
| -  if( rc==SQLITE_OK && pPage->nOverflow ){
 | 
| +  if( pPage->nOverflow ){
 | 
| +    assert( rc==SQLITE_OK );
 | 
|      pCur->curFlags &= ~(BTCF_ValidNKey);
 | 
|      rc = balance(pCur);
 | 
|  
 | 
| @@ -8075,6 +8143,20 @@ int sqlite3BtreeInsert(
 | 
|      ** from trying to save the current position of the cursor.  */
 | 
|      pCur->apPage[pCur->iPage]->nOverflow = 0;
 | 
|      pCur->eState = CURSOR_INVALID;
 | 
| +    if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){
 | 
| +      rc = moveToRoot(pCur);
 | 
| +      if( pCur->pKeyInfo ){
 | 
| +        assert( pCur->pKey==0 );
 | 
| +        pCur->pKey = sqlite3Malloc( pX->nKey );
 | 
| +        if( pCur->pKey==0 ){
 | 
| +          rc = SQLITE_NOMEM;
 | 
| +        }else{
 | 
| +          memcpy(pCur->pKey, pX->pKey, pX->nKey);
 | 
| +        }
 | 
| +      }
 | 
| +      pCur->eState = CURSOR_REQUIRESEEK;
 | 
| +      pCur->nKey = pX->nKey;
 | 
| +    }
 | 
|    }
 | 
|    assert( pCur->apPage[pCur->iPage]->nOverflow==0 );
 | 
|  
 | 
| @@ -8085,13 +8167,21 @@ end_insert:
 | 
|  /*
 | 
|  ** Delete the entry that the cursor is pointing to. 
 | 
|  **
 | 
| -** If the second parameter is zero, then the cursor is left pointing at an
 | 
| -** arbitrary location after the delete. If it is non-zero, then the cursor 
 | 
| -** is left in a state such that the next call to BtreeNext() or BtreePrev()
 | 
| -** moves it to the same row as it would if the call to BtreeDelete() had
 | 
| -** been omitted.
 | 
| -*/
 | 
| -int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
 | 
| +** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
 | 
| +** the cursor is left pointing at an arbitrary location after the delete.
 | 
| +** But if that bit is set, then the cursor is left in a state such that
 | 
| +** the next call to BtreeNext() or BtreePrev() moves it to the same row
 | 
| +** as it would have been on if the call to BtreeDelete() had been omitted.
 | 
| +**
 | 
| +** The BTREE_AUXDELETE bit of flags indicates that is one of several deletes
 | 
| +** associated with a single table entry and its indexes.  Only one of those
 | 
| +** deletes is considered the "primary" delete.  The primary delete occurs
 | 
| +** on a cursor that is not a BTREE_FORDELETE cursor.  All but one delete
 | 
| +** operation on non-FORDELETE cursors is tagged with the AUXDELETE flag.
 | 
| +** The BTREE_AUXDELETE bit is a hint that is not used by this implementation,
 | 
| +** but which might be used by alternative storage engines.
 | 
| +*/
 | 
| +int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
 | 
|    Btree *p = pCur->pBtree;
 | 
|    BtShared *pBt = p->pBt;              
 | 
|    int rc;                              /* Return code */
 | 
| @@ -8099,10 +8189,11 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
 | 
|    unsigned char *pCell;                /* Pointer to cell to delete */
 | 
|    int iCellIdx;                        /* Index of cell to delete */
 | 
|    int iCellDepth;                      /* Depth of node containing pCell */ 
 | 
| -  u16 szCell;                          /* Size of the cell being deleted */
 | 
| +  CellInfo info;                       /* Size of the cell being deleted */
 | 
|    int bSkipnext = 0;                   /* Leaf cursor in SKIPNEXT state */
 | 
| +  u8 bPreserve = flags & BTREE_SAVEPOSITION;  /* Keep cursor valid */
 | 
|  
 | 
| -  assert( cursorHoldsMutex(pCur) );
 | 
| +  assert( cursorOwnsBtShared(pCur) );
 | 
|    assert( pBt->inTransaction==TRANS_WRITE );
 | 
|    assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
 | 
|    assert( pCur->curFlags & BTCF_WriteFlag );
 | 
| @@ -8110,12 +8201,35 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
 | 
|    assert( !hasReadConflicts(p, pCur->pgnoRoot) );
 | 
|    assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
 | 
|    assert( pCur->eState==CURSOR_VALID );
 | 
| +  assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
 | 
|  
 | 
|    iCellDepth = pCur->iPage;
 | 
|    iCellIdx = pCur->aiIdx[iCellDepth];
 | 
|    pPage = pCur->apPage[iCellDepth];
 | 
|    pCell = findCell(pPage, iCellIdx);
 | 
|  
 | 
| +  /* If the bPreserve flag is set to true, then the cursor position must
 | 
| +  ** be preserved following this delete operation. If the current delete
 | 
| +  ** will cause a b-tree rebalance, then this is done by saving the cursor
 | 
| +  ** key and leaving the cursor in CURSOR_REQUIRESEEK state before 
 | 
| +  ** returning. 
 | 
| +  **
 | 
| +  ** Or, if the current delete will not cause a rebalance, then the cursor
 | 
| +  ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
 | 
| +  ** before or after the deleted entry. In this case set bSkipnext to true.  */
 | 
| +  if( bPreserve ){
 | 
| +    if( !pPage->leaf 
 | 
| +     || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
 | 
| +    ){
 | 
| +      /* A b-tree rebalance will be required after deleting this entry.
 | 
| +      ** Save the cursor key.  */
 | 
| +      rc = saveCursorKey(pCur);
 | 
| +      if( rc ) return rc;
 | 
| +    }else{
 | 
| +      bSkipnext = 1;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    /* If the page containing the entry to delete is not a leaf page, move
 | 
|    ** the cursor to the largest entry in the tree that is smaller than
 | 
|    ** the entry being deleted. This cell will replace the cell being deleted
 | 
| @@ -8142,35 +8256,13 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
 | 
|      invalidateIncrblobCursors(p, pCur->info.nKey, 0);
 | 
|    }
 | 
|  
 | 
| -  /* If the bPreserve flag is set to true, then the cursor position must
 | 
| -  ** be preserved following this delete operation. If the current delete
 | 
| -  ** will cause a b-tree rebalance, then this is done by saving the cursor
 | 
| -  ** key and leaving the cursor in CURSOR_REQUIRESEEK state before 
 | 
| -  ** returning. 
 | 
| -  **
 | 
| -  ** Or, if the current delete will not cause a rebalance, then the cursor
 | 
| -  ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
 | 
| -  ** before or after the deleted entry. In this case set bSkipnext to true.  */
 | 
| -  if( bPreserve ){
 | 
| -    if( !pPage->leaf 
 | 
| -     || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
 | 
| -    ){
 | 
| -      /* A b-tree rebalance will be required after deleting this entry.
 | 
| -      ** Save the cursor key.  */
 | 
| -      rc = saveCursorKey(pCur);
 | 
| -      if( rc ) return rc;
 | 
| -    }else{
 | 
| -      bSkipnext = 1;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
|    /* Make the page containing the entry to be deleted writable. Then free any
 | 
|    ** overflow pages associated with the entry and finally remove the cell
 | 
|    ** itself from within the page.  */
 | 
|    rc = sqlite3PagerWrite(pPage->pDbPage);
 | 
|    if( rc ) return rc;
 | 
| -  rc = clearCell(pPage, pCell, &szCell);
 | 
| -  dropCell(pPage, iCellIdx, szCell, &rc);
 | 
| +  rc = clearCell(pPage, pCell, &info);
 | 
| +  dropCell(pPage, iCellIdx, info.nSize, &rc);
 | 
|    if( rc ) return rc;
 | 
|  
 | 
|    /* If the cell deleted was not located on a leaf page, then the cursor
 | 
| @@ -8191,7 +8283,9 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
 | 
|      pTmp = pBt->pTmpSpace;
 | 
|      assert( pTmp!=0 );
 | 
|      rc = sqlite3PagerWrite(pLeaf->pDbPage);
 | 
| -    insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
 | 
| +    if( rc==SQLITE_OK ){
 | 
| +      insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
 | 
| +    }
 | 
|      dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
 | 
|      if( rc ) return rc;
 | 
|    }
 | 
| @@ -8222,7 +8316,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, int bPreserve){
 | 
|    if( rc==SQLITE_OK ){
 | 
|      if( bSkipnext ){
 | 
|        assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
 | 
| -      assert( pPage==pCur->apPage[pCur->iPage] );
 | 
| +      assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB );
 | 
|        assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
 | 
|        pCur->eState = CURSOR_SKIPNEXT;
 | 
|        if( iCellIdx>=pPage->nCell ){
 | 
| @@ -8418,7 +8512,7 @@ static int clearDatabasePage(
 | 
|    unsigned char *pCell;
 | 
|    int i;
 | 
|    int hdr;
 | 
| -  u16 szCell;
 | 
| +  CellInfo info;
 | 
|  
 | 
|    assert( sqlite3_mutex_held(pBt->mutex) );
 | 
|    if( pgno>btreePagecount(pBt) ){
 | 
| @@ -8438,7 +8532,7 @@ static int clearDatabasePage(
 | 
|        rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
 | 
|        if( rc ) goto cleardatabasepage_out;
 | 
|      }
 | 
| -    rc = clearCell(pPage, pCell, &szCell);
 | 
| +    rc = clearCell(pPage, pCell, &info);
 | 
|      if( rc ) goto cleardatabasepage_out;
 | 
|    }
 | 
|    if( !pPage->leaf ){
 | 
| @@ -8529,19 +8623,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
 | 
|  
 | 
|    assert( sqlite3BtreeHoldsMutex(p) );
 | 
|    assert( p->inTrans==TRANS_WRITE );
 | 
| -
 | 
| -  /* It is illegal to drop a table if any cursors are open on the
 | 
| -  ** database. This is because in auto-vacuum mode the backend may
 | 
| -  ** need to move another root-page to fill a gap left by the deleted
 | 
| -  ** root page. If an open cursor was using this page a problem would 
 | 
| -  ** occur.
 | 
| -  **
 | 
| -  ** This error is caught long before control reaches this point.
 | 
| -  */
 | 
| -  if( NEVER(pBt->pCursor) ){
 | 
| -    sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db);
 | 
| -    return SQLITE_LOCKED_SHAREDCACHE;
 | 
| -  }
 | 
| +  assert( iTable>=2 );
 | 
|  
 | 
|    rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
 | 
|    if( rc ) return rc;
 | 
| @@ -8553,76 +8635,67 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
 | 
|  
 | 
|    *piMoved = 0;
 | 
|  
 | 
| -  if( iTable>1 ){
 | 
|  #ifdef SQLITE_OMIT_AUTOVACUUM
 | 
| -    freePage(pPage, &rc);
 | 
| -    releasePage(pPage);
 | 
| +  freePage(pPage, &rc);
 | 
| +  releasePage(pPage);
 | 
|  #else
 | 
| -    if( pBt->autoVacuum ){
 | 
| -      Pgno maxRootPgno;
 | 
| -      sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno);
 | 
| -
 | 
| -      if( iTable==maxRootPgno ){
 | 
| -        /* If the table being dropped is the table with the largest root-page
 | 
| -        ** number in the database, put the root page on the free list. 
 | 
| -        */
 | 
| -        freePage(pPage, &rc);
 | 
| -        releasePage(pPage);
 | 
| -        if( rc!=SQLITE_OK ){
 | 
| -          return rc;
 | 
| -        }
 | 
| -      }else{
 | 
| -        /* The table being dropped does not have the largest root-page
 | 
| -        ** number in the database. So move the page that does into the 
 | 
| -        ** gap left by the deleted root-page.
 | 
| -        */
 | 
| -        MemPage *pMove;
 | 
| -        releasePage(pPage);
 | 
| -        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
 | 
| -        if( rc!=SQLITE_OK ){
 | 
| -          return rc;
 | 
| -        }
 | 
| -        rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
 | 
| -        releasePage(pMove);
 | 
| -        if( rc!=SQLITE_OK ){
 | 
| -          return rc;
 | 
| -        }
 | 
| -        pMove = 0;
 | 
| -        rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
 | 
| -        freePage(pMove, &rc);
 | 
| -        releasePage(pMove);
 | 
| -        if( rc!=SQLITE_OK ){
 | 
| -          return rc;
 | 
| -        }
 | 
| -        *piMoved = maxRootPgno;
 | 
| -      }
 | 
| +  if( pBt->autoVacuum ){
 | 
| +    Pgno maxRootPgno;
 | 
| +    sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &maxRootPgno);
 | 
|  
 | 
| -      /* Set the new 'max-root-page' value in the database header. This
 | 
| -      ** is the old value less one, less one more if that happens to
 | 
| -      ** be a root-page number, less one again if that is the
 | 
| -      ** PENDING_BYTE_PAGE.
 | 
| +    if( iTable==maxRootPgno ){
 | 
| +      /* If the table being dropped is the table with the largest root-page
 | 
| +      ** number in the database, put the root page on the free list. 
 | 
|        */
 | 
| -      maxRootPgno--;
 | 
| -      while( maxRootPgno==PENDING_BYTE_PAGE(pBt)
 | 
| -             || PTRMAP_ISPAGE(pBt, maxRootPgno) ){
 | 
| -        maxRootPgno--;
 | 
| +      freePage(pPage, &rc);
 | 
| +      releasePage(pPage);
 | 
| +      if( rc!=SQLITE_OK ){
 | 
| +        return rc;
 | 
|        }
 | 
| -      assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) );
 | 
| -
 | 
| -      rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
 | 
|      }else{
 | 
| -      freePage(pPage, &rc);
 | 
| +      /* The table being dropped does not have the largest root-page
 | 
| +      ** number in the database. So move the page that does into the 
 | 
| +      ** gap left by the deleted root-page.
 | 
| +      */
 | 
| +      MemPage *pMove;
 | 
|        releasePage(pPage);
 | 
| +      rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
 | 
| +      if( rc!=SQLITE_OK ){
 | 
| +        return rc;
 | 
| +      }
 | 
| +      rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
 | 
| +      releasePage(pMove);
 | 
| +      if( rc!=SQLITE_OK ){
 | 
| +        return rc;
 | 
| +      }
 | 
| +      pMove = 0;
 | 
| +      rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
 | 
| +      freePage(pMove, &rc);
 | 
| +      releasePage(pMove);
 | 
| +      if( rc!=SQLITE_OK ){
 | 
| +        return rc;
 | 
| +      }
 | 
| +      *piMoved = maxRootPgno;
 | 
|      }
 | 
| -#endif
 | 
| -  }else{
 | 
| -    /* If sqlite3BtreeDropTable was called on page 1.
 | 
| -    ** This really never should happen except in a corrupt
 | 
| -    ** database. 
 | 
| +
 | 
| +    /* Set the new 'max-root-page' value in the database header. This
 | 
| +    ** is the old value less one, less one more if that happens to
 | 
| +    ** be a root-page number, less one again if that is the
 | 
| +    ** PENDING_BYTE_PAGE.
 | 
|      */
 | 
| -    zeroPage(pPage, PTF_INTKEY|PTF_LEAF );
 | 
| +    maxRootPgno--;
 | 
| +    while( maxRootPgno==PENDING_BYTE_PAGE(pBt)
 | 
| +           || PTRMAP_ISPAGE(pBt, maxRootPgno) ){
 | 
| +      maxRootPgno--;
 | 
| +    }
 | 
| +    assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) );
 | 
| +
 | 
| +    rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
 | 
| +  }else{
 | 
| +    freePage(pPage, &rc);
 | 
|      releasePage(pPage);
 | 
|    }
 | 
| +#endif
 | 
|    return rc;  
 | 
|  }
 | 
|  int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
 | 
| @@ -8809,9 +8882,9 @@ static void checkAppendMsg(
 | 
|      sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
 | 
|    }
 | 
|    if( pCheck->zPfx ){
 | 
| -    sqlite3XPrintf(&pCheck->errMsg, 0, pCheck->zPfx, pCheck->v1, pCheck->v2);
 | 
| +    sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2);
 | 
|    }
 | 
| -  sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
 | 
| +  sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap);
 | 
|    va_end(ap);
 | 
|    if( pCheck->errMsg.accError==STRACCUM_NOMEM ){
 | 
|      pCheck->mallocFailed = 1;
 | 
| @@ -9312,7 +9385,8 @@ char *sqlite3BtreeIntegrityCheck(
 | 
|  
 | 
|    sqlite3BtreeEnter(p);
 | 
|    assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
 | 
| -  assert( (nRef = sqlite3PagerRefcount(pBt->pPager))>=0 );
 | 
| +  VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
 | 
| +  assert( nRef>=0 );
 | 
|    sCheck.pBt = pBt;
 | 
|    sCheck.pPager = pBt->pPager;
 | 
|    sCheck.nPage = btreePagecount(sCheck.pBt);
 | 
| @@ -9325,6 +9399,7 @@ char *sqlite3BtreeIntegrityCheck(
 | 
|    sCheck.aPgRef = 0;
 | 
|    sCheck.heap = 0;
 | 
|    sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
 | 
| +  sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL;
 | 
|    if( sCheck.nPage==0 ){
 | 
|      goto integrity_ck_cleanup;
 | 
|    }
 | 
| @@ -9456,7 +9531,7 @@ int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){
 | 
|      if( pBt->inTransaction!=TRANS_NONE ){
 | 
|        rc = SQLITE_LOCKED;
 | 
|      }else{
 | 
| -      rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt);
 | 
| +      rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt);
 | 
|      }
 | 
|      sqlite3BtreeLeave(p);
 | 
|    }
 | 
| @@ -9564,7 +9639,7 @@ int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
 | 
|  */
 | 
|  int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
 | 
|    int rc;
 | 
| -  assert( cursorHoldsMutex(pCsr) );
 | 
| +  assert( cursorOwnsBtShared(pCsr) );
 | 
|    assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
 | 
|    assert( pCsr->curFlags & BTCF_Incrblob );
 | 
|  
 | 
| @@ -9671,3 +9746,22 @@ int sqlite3BtreeIsReadonly(Btree *p){
 | 
|  ** Return the size of the header added to each page by this module.
 | 
|  */
 | 
|  int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
 | 
| +
 | 
| +#if !defined(SQLITE_OMIT_SHARED_CACHE)
 | 
| +/*
 | 
| +** Return true if the Btree passed as the only argument is sharable.
 | 
| +*/
 | 
| +int sqlite3BtreeSharable(Btree *p){
 | 
| +  return p->sharable;
 | 
| +}
 | 
| +
 | 
| +/*
 | 
| +** Return the number of connections to the BtShared object accessed by
 | 
| +** the Btree handle passed as the only argument. For private caches 
 | 
| +** this is always 1. For shared caches it may be 1 or greater.
 | 
| +*/
 | 
| +int sqlite3BtreeConnectionCount(Btree *p){
 | 
| +  testcase( p->sharable );
 | 
| +  return p->pBt->nRef;
 | 
| +}
 | 
| +#endif
 | 
| 
 |