/ Check-in [df94e61f]
Login

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

Overview
Comment:Merge all recent trunk enhancements and fixes into the sessions branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: df94e61f93da390cb75c48975c50e9d62096ea0b
User & Date: drh 2015-03-31 00:10:21
Context
2015-04-01
16:39
Merge recent enhancements from trunk. check-in: aea439bd user: drh tags: sessions
2015-03-31
00:10
Merge all recent trunk enhancements and fixes into the sessions branch. check-in: df94e61f user: drh tags: sessions
2015-03-30
23:43
Prevent a possible infinite loop when trying to DROP a table from a corrupt database. check-in: 395bb3e6 user: drh tags: trunk
2015-03-24
19:02
Merge all recent trunk enhancements into the sessions branch. check-in: 54aaa6f2 user: drh tags: sessions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.msc.

   308    308   # also be noted here that building any target with these "stdcall" options
   309    309   # will most likely fail if the Tcl library is also required.  This is due
   310    310   # to how the Tcl library functions are declared and exported (i.e. without
   311    311   # an explicit calling convention, which results in "cdecl").
   312    312   #
   313    313   !IF $(USE_STDCALL)!=0
   314    314   !IF "$(PLATFORM)"=="x86"
   315         -CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
   316         -SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
          315  +CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
          316  +SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
   317    317   !ELSE
   318    318   !IFNDEF PLATFORM
   319         -CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
   320         -SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl
          319  +CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
          320  +SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
   321    321   !ELSE
   322    322   CORE_CCONV_OPTS =
   323    323   SHELL_CCONV_OPTS =
   324    324   !ENDIF
   325    325   !ENDIF
   326    326   !ELSE
   327    327   CORE_CCONV_OPTS =
   328    328   SHELL_CCONV_OPTS =
   329    329   !ENDIF
   330    330   
   331    331   # These are additional compiler options used for the core library.
   332    332   #
   333    333   !IFNDEF CORE_COMPILE_OPTS
   334         -!IF $(USE_STDCALL)!=0
          334  +!IF $(DYNAMIC_SHELL)!=0
   335    335   CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport)
   336    336   !ELSE
   337    337   CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS)
   338    338   !ENDIF
   339    339   !ENDIF
   340    340   
   341    341   # These are the additional targets that the core library should depend on
   342    342   # when linking.
   343    343   #
   344    344   !IFNDEF CORE_LINK_DEP
   345         -!IF $(USE_STDCALL)!=0
          345  +!IF $(DYNAMIC_SHELL)!=0
   346    346   CORE_LINK_DEP =
   347    347   !ELSE
   348    348   CORE_LINK_DEP = sqlite3.def
   349    349   !ENDIF
   350    350   !ENDIF
   351    351   
   352    352   # These are additional linker options used for the core library.
   353    353   #
   354    354   !IFNDEF CORE_LINK_OPTS
   355         -!IF $(USE_STDCALL)!=0
          355  +!IF $(DYNAMIC_SHELL)!=0
   356    356   CORE_LINK_OPTS =
   357    357   !ELSE
   358    358   CORE_LINK_OPTS = /DEF:sqlite3.def
   359    359   !ENDIF
   360    360   !ENDIF
   361    361   
   362    362   # These are additional compiler options used for the shell executable.

Changes to ext/fts3/fts3.c.

  1104   1104     char *zCsr;                     /* Space for holding column names */
  1105   1105     int nDb;                        /* Bytes required to hold database name */
  1106   1106     int nName;                      /* Bytes required to hold table name */
  1107   1107     int isFts4 = (argv[0][3]=='4'); /* True for FTS4, false for FTS3 */
  1108   1108     const char **aCol;              /* Array of column names */
  1109   1109     sqlite3_tokenizer *pTokenizer = 0;        /* Tokenizer for this table */
  1110   1110   
  1111         -  int nIndex;                     /* Size of aIndex[] array */
         1111  +  int nIndex = 0;                 /* Size of aIndex[] array */
  1112   1112     struct Fts3Index *aIndex = 0;   /* Array of indexes for this table */
  1113   1113   
  1114   1114     /* The results of parsing supported FTS4 key=value options: */
  1115   1115     int bNoDocsize = 0;             /* True to omit %_docsize table */
  1116   1116     int bDescIdx = 0;               /* True to store descending indexes */
  1117   1117     char *zPrefix = 0;              /* Prefix parameter value (or NULL) */
  1118   1118     char *zCompress = 0;            /* compress=? parameter (or NULL) */

Changes to src/btree.c.

   596    596   **
   597    597   ** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID)
   598    598   ** prior to calling this routine.  
   599    599   */
   600    600   static int saveCursorPosition(BtCursor *pCur){
   601    601     int rc;
   602    602   
   603         -  assert( CURSOR_VALID==pCur->eState );
          603  +  assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState );
   604    604     assert( 0==pCur->pKey );
   605    605     assert( cursorHoldsMutex(pCur) );
   606    606   
          607  +  if( pCur->eState==CURSOR_SKIPNEXT ){
          608  +    pCur->eState = CURSOR_VALID;
          609  +  }else{
          610  +    pCur->skipNext = 0;
          611  +  }
   607    612     rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
   608    613     assert( rc==SQLITE_OK );  /* KeySize() cannot fail */
   609    614   
   610    615     /* If this is an intKey table, then the above call to BtreeKeySize()
   611    616     ** stores the integer key in pCur->nKey. In this case this value is
   612    617     ** all that is required. Otherwise, if pCur is not open on an intKey
   613    618     ** table, then malloc space for and store the pCur->nKey bytes of key 
................................................................................
   670    675   static int SQLITE_NOINLINE saveCursorsOnList(
   671    676     BtCursor *p,         /* The first cursor that needs saving */
   672    677     Pgno iRoot,          /* Only save cursor with this iRoot. Save all if zero */
   673    678     BtCursor *pExcept    /* Do not save this cursor */
   674    679   ){
   675    680     do{
   676    681       if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
   677         -      if( p->eState==CURSOR_VALID ){
          682  +      if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
   678    683           int rc = saveCursorPosition(p);
   679    684           if( SQLITE_OK!=rc ){
   680    685             return rc;
   681    686           }
   682    687         }else{
   683    688           testcase( p->iPage>0 );
   684    689           btreeReleaseAllCursorPages(p);
................................................................................
   742    747   ** when saveCursorPosition() was called. Note that this call deletes the 
   743    748   ** saved position info stored by saveCursorPosition(), so there can be
   744    749   ** at most one effective restoreCursorPosition() call after each 
   745    750   ** saveCursorPosition().
   746    751   */
   747    752   static int btreeRestoreCursorPosition(BtCursor *pCur){
   748    753     int rc;
          754  +  int skipNext;
   749    755     assert( cursorHoldsMutex(pCur) );
   750    756     assert( pCur->eState>=CURSOR_REQUIRESEEK );
   751    757     if( pCur->eState==CURSOR_FAULT ){
   752    758       return pCur->skipNext;
   753    759     }
   754    760     pCur->eState = CURSOR_INVALID;
   755         -  rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext);
          761  +  rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
   756    762     if( rc==SQLITE_OK ){
   757    763       sqlite3_free(pCur->pKey);
   758    764       pCur->pKey = 0;
   759    765       assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
          766  +    pCur->skipNext |= skipNext;
   760    767       if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
   761    768         pCur->eState = CURSOR_SKIPNEXT;
   762    769       }
   763    770     }
   764    771     return rc;
   765    772   }
   766    773   
................................................................................
   804    811     assert( pCur!=0 );
   805    812     assert( pCur->eState!=CURSOR_VALID );
   806    813     rc = restoreCursorPosition(pCur);
   807    814     if( rc ){
   808    815       *pDifferentRow = 1;
   809    816       return rc;
   810    817     }
   811         -  if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
          818  +  if( pCur->eState!=CURSOR_VALID ){
   812    819       *pDifferentRow = 1;
   813    820     }else{
          821  +    assert( pCur->skipNext==0 );
   814    822       *pDifferentRow = 0;
   815    823     }
   816    824     return SQLITE_OK;
   817    825   }
   818    826   
   819    827   #ifndef SQLITE_OMIT_AUTOVACUUM
   820    828   /*
................................................................................
  3621   3629   
  3622   3630     assert( (writeOnly==0 || writeOnly==1) && BTCF_WriteFlag==1 );
  3623   3631     if( pBtree ){
  3624   3632       sqlite3BtreeEnter(pBtree);
  3625   3633       for(p=pBtree->pBt->pCursor; p; p=p->pNext){
  3626   3634         int i;
  3627   3635         if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){
  3628         -        if( p->eState==CURSOR_VALID ){
         3636  +        if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
  3629   3637             rc = saveCursorPosition(p);
  3630   3638             if( rc!=SQLITE_OK ){
  3631   3639               (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0);
  3632   3640               break;
  3633   3641             }
  3634   3642           }
  3635   3643         }else{
................................................................................
  4027   4035   ** Failure is not possible.  This function always returns SQLITE_OK.
  4028   4036   ** It might just as well be a procedure (returning void) but we continue
  4029   4037   ** to return an integer result code for historical reasons.
  4030   4038   */
  4031   4039   int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
  4032   4040     assert( cursorHoldsMutex(pCur) );
  4033   4041     assert( pCur->eState==CURSOR_VALID );
         4042  +  assert( pCur->iPage>=0 );
         4043  +  assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
  4034   4044     assert( pCur->apPage[pCur->iPage]->intKeyLeaf==1 );
  4035   4045     getCellInfo(pCur);
  4036   4046     *pSize = pCur->info.nPayload;
  4037   4047     return SQLITE_OK;
  4038   4048   }
  4039   4049   
  4040   4050   /*
................................................................................
  4505   4515     pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
  4506   4516     if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
  4507   4517       return SQLITE_CORRUPT_BKPT;
  4508   4518     }
  4509   4519     return SQLITE_OK;
  4510   4520   }
  4511   4521   
  4512         -#if 0
         4522  +#if SQLITE_DEBUG
  4513   4523   /*
  4514   4524   ** Page pParent is an internal (non-leaf) tree page. This function 
  4515   4525   ** asserts that page number iChild is the left-child if the iIdx'th
  4516   4526   ** cell in page pParent. Or, if iIdx is equal to the total number of
  4517   4527   ** cells in pParent, that page number iChild is the right-child of
  4518   4528   ** the page.
  4519   4529   */
  4520   4530   static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
         4531  +  if( CORRUPT_DB ) return;  /* The conditions tested below might not be true
         4532  +                            ** in a corrupt database */
  4521   4533     assert( iIdx<=pParent->nCell );
  4522   4534     if( iIdx==pParent->nCell ){
  4523   4535       assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild );
  4524   4536     }else{
  4525   4537       assert( get4byte(findCell(pParent, iIdx))==iChild );
  4526   4538     }
  4527   4539   }
................................................................................
  4538   4550   ** the largest cell index.
  4539   4551   */
  4540   4552   static void moveToParent(BtCursor *pCur){
  4541   4553     assert( cursorHoldsMutex(pCur) );
  4542   4554     assert( pCur->eState==CURSOR_VALID );
  4543   4555     assert( pCur->iPage>0 );
  4544   4556     assert( pCur->apPage[pCur->iPage] );
  4545         -
  4546         -  /* UPDATE: It is actually possible for the condition tested by the assert
  4547         -  ** below to be untrue if the database file is corrupt. This can occur if
  4548         -  ** one cursor has modified page pParent while a reference to it is held 
  4549         -  ** by a second cursor. Which can only happen if a single page is linked
  4550         -  ** into more than one b-tree structure in a corrupt database.  */
  4551         -#if 0
  4552   4557     assertParentIndex(
  4553   4558       pCur->apPage[pCur->iPage-1], 
  4554   4559       pCur->aiIdx[pCur->iPage-1], 
  4555   4560       pCur->apPage[pCur->iPage]->pgno
  4556   4561     );
  4557         -#endif
  4558   4562     testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
  4559   4563   
  4560   4564     releasePage(pCur->apPage[pCur->iPage]);
  4561   4565     pCur->iPage--;
  4562   4566     pCur->info.nSize = 0;
  4563   4567     pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
  4564   4568   }
................................................................................
  7498   7502         }
  7499   7503   
  7500   7504         pPage->nOverflow = 0;
  7501   7505   
  7502   7506         /* The next iteration of the do-loop balances the parent page. */
  7503   7507         releasePage(pPage);
  7504   7508         pCur->iPage--;
         7509  +      assert( pCur->iPage>=0 );
  7505   7510       }
  7506   7511     }while( rc==SQLITE_OK );
  7507   7512   
  7508   7513     if( pFree ){
  7509   7514       sqlite3PageFree(pFree);
  7510   7515     }
  7511   7516     return rc;
................................................................................
  7969   7974   ){
  7970   7975     MemPage *pPage;
  7971   7976     int rc;
  7972   7977     unsigned char *pCell;
  7973   7978     int i;
  7974   7979     int hdr;
  7975   7980     u16 szCell;
         7981  +  u8 hasChildren;
  7976   7982   
  7977   7983     assert( sqlite3_mutex_held(pBt->mutex) );
  7978   7984     if( pgno>btreePagecount(pBt) ){
  7979   7985       return SQLITE_CORRUPT_BKPT;
  7980   7986     }
  7981   7987   
  7982   7988     rc = getAndInitPage(pBt, pgno, &pPage, 0);
  7983   7989     if( rc ) return rc;
         7990  +  hasChildren = !pPage->leaf;
         7991  +  pPage->leaf = 1;  /* Block looping if the database is corrupt */
  7984   7992     hdr = pPage->hdrOffset;
  7985   7993     for(i=0; i<pPage->nCell; i++){
  7986   7994       pCell = findCell(pPage, i);
  7987         -    if( !pPage->leaf ){
         7995  +    if( hasChildren ){
  7988   7996         rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
  7989   7997         if( rc ) goto cleardatabasepage_out;
  7990   7998       }
  7991   7999       rc = clearCell(pPage, pCell, &szCell);
  7992   8000       if( rc ) goto cleardatabasepage_out;
  7993   8001     }
  7994         -  if( !pPage->leaf ){
         8002  +  if( hasChildren ){
  7995   8003       rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
  7996   8004       if( rc ) goto cleardatabasepage_out;
  7997   8005     }else if( pnChange ){
  7998   8006       assert( pPage->intKey );
  7999   8007       *pnChange += pPage->nCell;
  8000   8008     }
  8001   8009     if( freePageFlag ){

Changes to src/main.c.

    58     58   #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
    59     59   /*
    60     60   ** If the following function pointer is not NULL and if
    61     61   ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
    62     62   ** I/O active are written using this function.  These messages
    63     63   ** are intended for debugging activity only.
    64     64   */
    65         -/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0;
           65  +SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0;
    66     66   #endif
    67     67   
    68     68   /*
    69     69   ** If the following global variable points to a string which is the
    70     70   ** name of a directory, then that directory will be used to store
    71     71   ** temporary files.
    72     72   **

Changes to src/malloc.c.

   158    158     sqlite3_soft_heap_limit64(n);
   159    159   }
   160    160   
   161    161   /*
   162    162   ** Initialize the memory allocation subsystem.
   163    163   */
   164    164   int sqlite3MallocInit(void){
          165  +  int rc;
   165    166     if( sqlite3GlobalConfig.m.xMalloc==0 ){
   166    167       sqlite3MemSetDefault();
   167    168     }
   168    169     memset(&mem0, 0, sizeof(mem0));
   169    170     if( sqlite3GlobalConfig.bCoreMutex ){
   170    171       mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
   171    172     }
................................................................................
   193    194     }
   194    195     if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
   195    196         || sqlite3GlobalConfig.nPage<1 ){
   196    197       sqlite3GlobalConfig.pPage = 0;
   197    198       sqlite3GlobalConfig.szPage = 0;
   198    199       sqlite3GlobalConfig.nPage = 0;
   199    200     }
   200         -  return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
          201  +  rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
          202  +  if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));
          203  +  return rc;
   201    204   }
   202    205   
   203    206   /*
   204    207   ** Return true if the heap is currently under memory pressure - in other
   205    208   ** words if the amount of heap used is close to the limit set by
   206    209   ** sqlite3_soft_heap_limit().
   207    210   */

Changes to src/os_win.c.

  1962   1962     }
  1963   1963     return 0;
  1964   1964   }
  1965   1965   
  1966   1966   /*
  1967   1967   ** Log a I/O error retry episode.
  1968   1968   */
  1969         -static void winLogIoerr(int nRetry){
         1969  +static void winLogIoerr(int nRetry, int lineno){
  1970   1970     if( nRetry ){
  1971   1971       sqlite3_log(SQLITE_IOERR,
  1972         -      "delayed %dms for lock/sharing conflict",
  1973         -      winIoerrRetryDelay*nRetry*(nRetry+1)/2
         1972  +      "delayed %dms for lock/sharing conflict at line %d",
         1973  +      winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno
  1974   1974       );
  1975   1975     }
  1976   1976   }
  1977   1977   
  1978   1978   #if SQLITE_OS_WINCE
  1979   1979   /*************************************************************************
  1980   1980   ** This section contains code for WinCE only.
................................................................................
  2446   2446     winFile *pFile = (winFile*)id;
  2447   2447   
  2448   2448     assert( id!=0 );
  2449   2449   #ifndef SQLITE_OMIT_WAL
  2450   2450     assert( pFile->pShm==0 );
  2451   2451   #endif
  2452   2452     assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
  2453         -  OSTRACE(("CLOSE file=%p\n", pFile->h));
         2453  +  OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n",
         2454  +           osGetCurrentProcessId(), pFile, pFile->h));
  2454   2455   
  2455   2456   #if SQLITE_MAX_MMAP_SIZE>0
  2456   2457     winUnmapfile(pFile);
  2457   2458   #endif
  2458   2459   
  2459   2460     do{
  2460   2461       rc = osCloseHandle(pFile->h);
................................................................................
  2475   2476       sqlite3_free(pFile->zDeleteOnClose);
  2476   2477     }
  2477   2478   #endif
  2478   2479     if( rc ){
  2479   2480       pFile->h = NULL;
  2480   2481     }
  2481   2482     OpenCounter(-1);
  2482         -  OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
         2483  +  OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n",
         2484  +           osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed"));
  2483   2485     return rc ? SQLITE_OK
  2484   2486               : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
  2485   2487                             "winClose", pFile->zPath);
  2486   2488   }
  2487   2489   
  2488   2490   /*
  2489   2491   ** Read data from a file into a buffer.  Return SQLITE_OK if all
................................................................................
  2503   2505     DWORD nRead;                    /* Number of bytes actually read from file */
  2504   2506     int nRetry = 0;                 /* Number of retrys */
  2505   2507   
  2506   2508     assert( id!=0 );
  2507   2509     assert( amt>0 );
  2508   2510     assert( offset>=0 );
  2509   2511     SimulateIOError(return SQLITE_IOERR_READ);
  2510         -  OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
         2512  +  OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
         2513  +           "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
  2511   2514              pFile->h, pBuf, amt, offset, pFile->locktype));
  2512   2515   
  2513   2516   #if SQLITE_MAX_MMAP_SIZE>0
  2514   2517     /* Deal with as much of this read request as possible by transfering
  2515   2518     ** data from the memory mapping using memcpy().  */
  2516   2519     if( offset<pFile->mmapSize ){
  2517   2520       if( offset+amt <= pFile->mmapSize ){
  2518   2521         memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
  2519         -      OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
         2522  +      OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
         2523  +               osGetCurrentProcessId(), pFile, pFile->h));
  2520   2524         return SQLITE_OK;
  2521   2525       }else{
  2522   2526         int nCopy = (int)(pFile->mmapSize - offset);
  2523   2527         memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
  2524   2528         pBuf = &((u8 *)pBuf)[nCopy];
  2525   2529         amt -= nCopy;
  2526   2530         offset += nCopy;
  2527   2531       }
  2528   2532     }
  2529   2533   #endif
  2530   2534   
  2531   2535   #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
  2532   2536     if( winSeekFile(pFile, offset) ){
  2533         -    OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
         2537  +    OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
         2538  +             osGetCurrentProcessId(), pFile, pFile->h));
  2534   2539       return SQLITE_FULL;
  2535   2540     }
  2536   2541     while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
  2537   2542   #else
  2538   2543     memset(&overlapped, 0, sizeof(OVERLAPPED));
  2539   2544     overlapped.Offset = (LONG)(offset & 0xffffffff);
  2540   2545     overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
  2541   2546     while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
  2542   2547            osGetLastError()!=ERROR_HANDLE_EOF ){
  2543   2548   #endif
  2544   2549       DWORD lastErrno;
  2545   2550       if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
  2546   2551       pFile->lastErrno = lastErrno;
  2547         -    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
         2552  +    OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n",
         2553  +             osGetCurrentProcessId(), pFile, pFile->h));
  2548   2554       return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
  2549   2555                          "winRead", pFile->zPath);
  2550   2556     }
  2551         -  winLogIoerr(nRetry);
         2557  +  winLogIoerr(nRetry, __LINE__);
  2552   2558     if( nRead<(DWORD)amt ){
  2553   2559       /* Unread parts of the buffer must be zero-filled */
  2554   2560       memset(&((char*)pBuf)[nRead], 0, amt-nRead);
  2555         -    OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
         2561  +    OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n",
         2562  +             osGetCurrentProcessId(), pFile, pFile->h));
  2556   2563       return SQLITE_IOERR_SHORT_READ;
  2557   2564     }
  2558   2565   
  2559         -  OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
         2566  +  OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
         2567  +           osGetCurrentProcessId(), pFile, pFile->h));
  2560   2568     return SQLITE_OK;
  2561   2569   }
  2562   2570   
  2563   2571   /*
  2564   2572   ** Write data from a buffer into a file.  Return SQLITE_OK on success
  2565   2573   ** or some other error code on failure.
  2566   2574   */
................................................................................
  2575   2583     int nRetry = 0;                 /* Number of retries */
  2576   2584   
  2577   2585     assert( amt>0 );
  2578   2586     assert( pFile );
  2579   2587     SimulateIOError(return SQLITE_IOERR_WRITE);
  2580   2588     SimulateDiskfullError(return SQLITE_FULL);
  2581   2589   
  2582         -  OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
         2590  +  OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
         2591  +           "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
  2583   2592              pFile->h, pBuf, amt, offset, pFile->locktype));
  2584   2593   
  2585   2594   #if SQLITE_MAX_MMAP_SIZE>0
  2586   2595     /* Deal with as much of this write request as possible by transfering
  2587   2596     ** data from the memory mapping using memcpy().  */
  2588   2597     if( offset<pFile->mmapSize ){
  2589   2598       if( offset+amt <= pFile->mmapSize ){
  2590   2599         memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
  2591         -      OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
         2600  +      OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
         2601  +               osGetCurrentProcessId(), pFile, pFile->h));
  2592   2602         return SQLITE_OK;
  2593   2603       }else{
  2594   2604         int nCopy = (int)(pFile->mmapSize - offset);
  2595   2605         memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
  2596   2606         pBuf = &((u8 *)pBuf)[nCopy];
  2597   2607         amt -= nCopy;
  2598   2608         offset += nCopy;
................................................................................
  2647   2657         rc = 1;
  2648   2658       }
  2649   2659     }
  2650   2660   
  2651   2661     if( rc ){
  2652   2662       if(   ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
  2653   2663          || ( pFile->lastErrno==ERROR_DISK_FULL )){
  2654         -      OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
         2664  +      OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
         2665  +               osGetCurrentProcessId(), pFile, pFile->h));
  2655   2666         return winLogError(SQLITE_FULL, pFile->lastErrno,
  2656   2667                            "winWrite1", pFile->zPath);
  2657   2668       }
  2658         -    OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
         2669  +    OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n",
         2670  +             osGetCurrentProcessId(), pFile, pFile->h));
  2659   2671       return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
  2660   2672                          "winWrite2", pFile->zPath);
  2661   2673     }else{
  2662         -    winLogIoerr(nRetry);
         2674  +    winLogIoerr(nRetry, __LINE__);
  2663   2675     }
  2664         -  OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
         2676  +  OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
         2677  +           osGetCurrentProcessId(), pFile, pFile->h));
  2665   2678     return SQLITE_OK;
  2666   2679   }
  2667   2680   
  2668   2681   /*
  2669   2682   ** Truncate an open file to a specified size
  2670   2683   */
  2671   2684   static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
  2672   2685     winFile *pFile = (winFile*)id;  /* File handle object */
  2673   2686     int rc = SQLITE_OK;             /* Return code for this function */
  2674   2687     DWORD lastErrno;
  2675   2688   
  2676   2689     assert( pFile );
  2677   2690     SimulateIOError(return SQLITE_IOERR_TRUNCATE);
  2678         -  OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n",
  2679         -           pFile->h, nByte, pFile->locktype));
         2691  +  OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",
         2692  +           osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));
  2680   2693   
  2681   2694     /* If the user has configured a chunk-size for this file, truncate the
  2682   2695     ** file so that it consists of an integer number of chunks (i.e. the
  2683   2696     ** actual file size after the operation may be larger than the requested
  2684   2697     ** size).
  2685   2698     */
  2686   2699     if( pFile->szChunk>0 ){
................................................................................
  2704   2717     ** use read() and write() to access data beyond this point from now on.
  2705   2718     */
  2706   2719     if( pFile->pMapRegion && nByte<pFile->mmapSize ){
  2707   2720       pFile->mmapSize = nByte;
  2708   2721     }
  2709   2722   #endif
  2710   2723   
  2711         -  OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
         2724  +  OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n",
         2725  +           osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc)));
  2712   2726     return rc;
  2713   2727   }
  2714   2728   
  2715   2729   #ifdef SQLITE_TEST
  2716   2730   /*
  2717   2731   ** Count the number of fullsyncs and normal syncs.  This is used to test
  2718   2732   ** that syncs and fullsyncs are occuring at the right times.
................................................................................
  2749   2763     );
  2750   2764   
  2751   2765     /* Unix cannot, but some systems may return SQLITE_FULL from here. This
  2752   2766     ** line is to test that doing so does not cause any problems.
  2753   2767     */
  2754   2768     SimulateDiskfullError( return SQLITE_FULL );
  2755   2769   
  2756         -  OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n",
  2757         -           pFile->h, flags, pFile->locktype));
         2770  +  OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n",
         2771  +           osGetCurrentProcessId(), pFile, pFile->h, flags,
         2772  +           pFile->locktype));
  2758   2773   
  2759   2774   #ifndef SQLITE_TEST
  2760   2775     UNUSED_PARAMETER(flags);
  2761   2776   #else
  2762   2777     if( (flags&0x0F)==SQLITE_SYNC_FULL ){
  2763   2778       sqlite3_fullsync_count++;
  2764   2779     }
................................................................................
  2765   2780     sqlite3_sync_count++;
  2766   2781   #endif
  2767   2782   
  2768   2783     /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
  2769   2784     ** no-op
  2770   2785     */
  2771   2786   #ifdef SQLITE_NO_SYNC
  2772         -  OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h));
         2787  +  OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
         2788  +           osGetCurrentProcessId(), pFile, pFile->h));
  2773   2789     return SQLITE_OK;
  2774   2790   #else
  2775   2791     rc = osFlushFileBuffers(pFile->h);
  2776   2792     SimulateIOError( rc=FALSE );
  2777   2793     if( rc ){
  2778         -    OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
         2794  +    OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
         2795  +             osGetCurrentProcessId(), pFile, pFile->h));
  2779   2796       return SQLITE_OK;
  2780   2797     }else{
  2781   2798       pFile->lastErrno = osGetLastError();
  2782         -    OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
         2799  +    OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n",
         2800  +             osGetCurrentProcessId(), pFile, pFile->h));
  2783   2801       return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
  2784   2802                          "winSync", pFile->zPath);
  2785   2803     }
  2786   2804   #endif
  2787   2805   }
  2788   2806   
  2789   2807   /*
................................................................................
  4748   4766                                 dwFlagsAndAttributes,
  4749   4767                                 NULL))==INVALID_HANDLE_VALUE &&
  4750   4768                                 winRetryIoerr(&cnt, &lastErrno) ){
  4751   4769                  /* Noop */
  4752   4770       }
  4753   4771     }
  4754   4772   #endif
  4755         -  winLogIoerr(cnt);
         4773  +  winLogIoerr(cnt, __LINE__);
  4756   4774   
  4757   4775     OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
  4758   4776              dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
  4759   4777   
  4760   4778     if( h==INVALID_HANDLE_VALUE ){
  4761   4779       pFile->lastErrno = lastErrno;
  4762   4780       winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
................................................................................
  4932   4950         }
  4933   4951       } while(1);
  4934   4952     }
  4935   4953   #endif
  4936   4954     if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
  4937   4955       rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename);
  4938   4956     }else{
  4939         -    winLogIoerr(cnt);
         4957  +    winLogIoerr(cnt, __LINE__);
  4940   4958     }
  4941   4959     sqlite3_free(zConverted);
  4942   4960     OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
  4943   4961     return rc;
  4944   4962   }
  4945   4963   
  4946   4964   /*
................................................................................
  4982   5000             && sAttrData.nFileSizeHigh==0
  4983   5001             && sAttrData.nFileSizeLow==0 ){
  4984   5002           attr = INVALID_FILE_ATTRIBUTES;
  4985   5003         }else{
  4986   5004           attr = sAttrData.dwFileAttributes;
  4987   5005         }
  4988   5006       }else{
  4989         -      winLogIoerr(cnt);
         5007  +      winLogIoerr(cnt, __LINE__);
  4990   5008         if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
  4991   5009           sqlite3_free(zConverted);
  4992   5010           return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
  4993   5011                              zFilename);
  4994   5012         }else{
  4995   5013           attr = INVALID_FILE_ATTRIBUTES;
  4996   5014         }

Changes to src/shell.c.

   366    366   /*
   367    367   ** This routine works like printf in that its first argument is a
   368    368   ** format string and subsequent arguments are values to be substituted
   369    369   ** in place of % fields.  The result of formatting this string
   370    370   ** is written to iotrace.
   371    371   */
   372    372   #ifdef SQLITE_ENABLE_IOTRACE
   373         -static void iotracePrintf(const char *zFormat, ...){
          373  +static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
   374    374     va_list ap;
   375    375     char *z;
   376    376     if( iotrace==0 ) return;
   377    377     va_start(ap, zFormat);
   378    378     z = sqlite3_vmprintf(zFormat, ap);
   379    379     va_end(ap);
   380    380     fprintf(iotrace, "%s", z);
................................................................................
  3229   3229         fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n");
  3230   3230         rc = 1;
  3231   3231       }
  3232   3232     }else
  3233   3233   
  3234   3234   #ifdef SQLITE_ENABLE_IOTRACE
  3235   3235     if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
  3236         -    extern void (*sqlite3IoTrace)(const char*, ...);
         3236  +    SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
  3237   3237       if( iotrace && iotrace!=stdout ) fclose(iotrace);
  3238   3238       iotrace = 0;
  3239   3239       if( nArg<2 ){
  3240   3240         sqlite3IoTrace = 0;
  3241   3241       }else if( strcmp(azArg[1], "-")==0 ){
  3242   3242         sqlite3IoTrace = iotracePrintf;
  3243   3243         iotrace = stdout;
................................................................................
  4080   4080   
  4081   4081           case SQLITE_TESTCTRL_IMPOSTER:
  4082   4082             if( nArg==5 ){
  4083   4083               rc = sqlite3_test_control(testctrl, p->db, 
  4084   4084                             azArg[2],
  4085   4085                             integerValue(azArg[3]),
  4086   4086                             integerValue(azArg[4]));
         4087  +            fprintf(p->out, "%d (0x%08x)\n", rc, rc);
  4087   4088             }else{
  4088         -            fprintf(stderr,"Usage: .testctrl initmode dbName onoff tnum\n");
  4089         -            rc = 1;
         4089  +            fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
  4090   4090             }
  4091   4091             break;
  4092   4092   
  4093   4093           case SQLITE_TESTCTRL_BITVEC_TEST:         
  4094   4094           case SQLITE_TESTCTRL_FAULT_INSTALL:       
  4095   4095           case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: 
  4096   4096           case SQLITE_TESTCTRL_SCRATCHMALLOC:       

Changes to src/sqlite.h.in.

    39     39   */
    40     40   #ifdef __cplusplus
    41     41   extern "C" {
    42     42   #endif
    43     43   
    44     44   
    45     45   /*
    46         -** Add the ability to override 'extern'
           46  +** Provide the ability to override linkage features of the interface.
    47     47   */
    48     48   #ifndef SQLITE_EXTERN
    49     49   # define SQLITE_EXTERN extern
    50     50   #endif
    51         -
    52         -/*
    53         -** Add the ability to override 'cdecl'
    54         -*/
           51  +#ifndef SQLITE_API
           52  +# define SQLITE_API
           53  +#endif
    55     54   #ifndef SQLITE_CDECL
    56     55   # define SQLITE_CDECL
    57     56   #endif
           57  +#ifndef SQLITE_STDCALL
           58  +# define SQLITE_STDCALL
           59  +#endif
    58     60   
    59     61   /*
    60     62   ** These no-op macros are used in front of interfaces to mark those
    61     63   ** interfaces as either deprecated or experimental.  New applications
    62     64   ** should not use deprecated interfaces - they are supported for backwards
    63     65   ** compatibility only.  Application writers should be aware that
    64     66   ** experimental interfaces are subject to change in point releases.

Changes to src/sqliteInt.h.

  3811   3811   ** If the SQLITE_ENABLE IOTRACE exists then the global variable
  3812   3812   ** sqlite3IoTrace is a pointer to a printf-like routine used to
  3813   3813   ** print I/O tracing messages. 
  3814   3814   */
  3815   3815   #ifdef SQLITE_ENABLE_IOTRACE
  3816   3816   # define IOTRACE(A)  if( sqlite3IoTrace ){ sqlite3IoTrace A; }
  3817   3817     void sqlite3VdbeIOTraceSql(Vdbe*);
  3818         -SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
         3818  +SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...);
  3819   3819   #else
  3820   3820   # define IOTRACE(A)
  3821   3821   # define sqlite3VdbeIOTraceSql(X)
  3822   3822   #endif
  3823   3823   
  3824   3824   /*
  3825   3825   ** These routines are available for the mem2.c debugging memory allocator

Added test/btree02.test.

            1  +# 2015-03-25
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.
           12  +#
           13  +# The focus of this script is making multiple calls to saveCursorPosition()
           14  +# and restoreCursorPosition() when cursors have eState==CURSOR_SKIPNEXT
           15  +# 
           16  +
           17  +set testdir [file dirname $argv0]
           18  +source $testdir/tester.tcl
           19  +
           20  +load_static_extension db eval
           21  +do_execsql_test btree02-100 {
           22  +  CREATE TABLE t1(a TEXT, ax INTEGER, b INT, PRIMARY KEY(a,ax)) WITHOUT ROWID;
           23  +  WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
           24  +    INSERT INTO t1(a,ax,b) SELECT printf('%02x',i), random(), i FROM c;
           25  +  CREATE INDEX t1a ON t1(a);
           26  +  CREATE TABLE t2(x,y);
           27  +  CREATE TABLE t3(cnt);
           28  +  WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<4)
           29  +    INSERT INTO t3(cnt) SELECT i FROM c;
           30  +  SELECT count(*) FROM t1;
           31  +} {10}
           32  +do_test btree02-110 {
           33  +  db eval BEGIN
           34  +  set i 0
           35  +  db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} {
           36  +    db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)}
           37  +    # puts "a,b,cnt = ($a,$b,$cnt)"
           38  +    incr i
           39  +    if {$i%2==1} {
           40  +      set bx [expr {$b+1000}]
           41  +      # puts "INSERT ($a),$bx"
           42  +      db eval {INSERT INTO t1(a,ax,b) VALUES(printf('(%s)',$a),random(),$bx)}
           43  +    } else {
           44  +      # puts "DELETE a=$a"
           45  +      db eval {DELETE FROM t1 WHERE a=$a}
           46  +    }
           47  +    db eval {COMMIT; BEGIN}
           48  +  }  
           49  +  db one {COMMIT; SELECT count(*) FROM t1;}
           50  +} {20}
           51  +
           52  +finish_test

Added test/corruptJ.test.

            1  +# 2015-03-30
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# Corruption consisting of a database page that thinks it is a child
           13  +# of itself.
           14  +#
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +set testprefix corruptJ
           19  +
           20  +if {[permutation]=="mmap"} {
           21  +  finish_test
           22  +  return
           23  +}
           24  +
           25  +# Do not use a codec for tests in this file, as the database file is
           26  +# manipulated directly using tcl scripts (using the [hexio_write] command).
           27  +#
           28  +do_not_use_codec
           29  +database_may_be_corrupt
           30  +
           31  +# Initialize the database.
           32  +#
           33  +do_execsql_test 1.1 {
           34  +  PRAGMA page_size=1024;
           35  +  PRAGMA auto_vacuum=0;
           36  +  CREATE TABLE t1(a,b);
           37  +  WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
           38  +    INSERT INTO t1(a,b) SELECT i, zeroblob(700) FROM c;
           39  +} {}
           40  +db close
           41  +
           42  +# Corrupt the root page of the t1 table such that the left-child pointer
           43  +# for the very first cell points back to the root.  Then try to DROP the
           44  +# table.  The clearDatabasePage() routine should not loop.
           45  +#
           46  +do_test 1.2 {
           47  +  hexio_write test.db [expr {2*1024-2}] 02
           48  +  sqlite3 db test.db
           49  +  catchsql { DROP TABLE t1 }
           50  +} {1 {database disk image is malformed}}
           51  +
           52  +# Similar test using a WITHOUT ROWID table
           53  +#
           54  +do_test 2.1 {
           55  +  db close
           56  +  forcedelete test.db
           57  +  sqlite3 db test.db
           58  +  db eval {
           59  +    PRAGMA page_size=1024;
           60  +    PRAGMA auto_vacuum=0;
           61  +    CREATE TABLE t1(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID;
           62  +    WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<100)
           63  +      INSERT INTO t1(a,b) SELECT i, zeroblob(200) FROM c;
           64  +  }
           65  +} {}
           66  +
           67  +# The table is three levels deep.  Corrupt the left child of an intermediate
           68  +# page so that it points back to the root page.
           69  +#
           70  +do_test 2.2 {
           71  +  db close
           72  +  hexio_read test.db [expr {9*1024+391}] 8
           73  +} {00000008814D0401}
           74  +do_test 2.2b {
           75  +  hexio_write test.db [expr {9*1024+391}] 00000002
           76  +  sqlite3 db test.db
           77  +  catchsql { DROP TABLE t1 }
           78  +} {0 {}}
           79  +
           80  +finish_test

Changes to test/win32lock.test.

    60     60       lappend win32_lock_ok $::delay1
    61     61       do_test win32lock-1.2-$delay1-ok {
    62     62          set ::msg
    63     63       } {1 100000 2 50000 3 25000 4 12500}
    64     64       if {[info exists ::log] && $::log!=""} {
    65     65         do_test win32lock-1.2-$delay1-log1 {
    66     66           regsub {\d+} $::log # x
           67  +        regsub { at line \d+} $x "" x
    67     68           set x
    68     69         } {{delayed #ms for lock/sharing conflict}}
    69     70       }
    70     71     }
    71     72     if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
    72     73     incr delay1 25
    73     74     if {$delay1 > 12500} {
................................................................................
   108    109       lappend win32_lock_ok $::delay1
   109    110       do_test win32lock-2.2-$delay1-ok {
   110    111          set ::msg
   111    112       } {1 100000 2 50000 3 25000 4 12500}
   112    113       if {[info exists ::log] && $::log!=""} {
   113    114         do_test win32lock-2.2-$delay1-log1 {
   114    115           regsub {\d+} $::log # x
          116  +        regsub { at line \d+} $x "" x
   115    117           set x
   116    118         } {{delayed #ms for lock/sharing conflict}}
   117    119       }
   118    120     }
   119    121     if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
   120    122     incr delay1 1
   121    123     if {$delay1 > 500} {

Changes to tool/mksqlite3c-noext.tcl.

    13     13   # For example, the "parse.c" and "parse.h" files to implement the
    14     14   # the parser are derived from "parse.y" using lemon.  And the 
    15     15   # "keywordhash.h" files is generated by a program named "mkkeywordhash".
    16     16   #
    17     17   # After the "tsrc" directory has been created and populated, run
    18     18   # this script:
    19     19   #
    20         -#      tclsh mksqlite3c.tcl
           20  +#      tclsh mksqlite3c-noext.tcl
    21     21   #
    22     22   # The amalgamated SQLite code will be written into sqlite3.c
    23     23   #
    24     24   
    25     25   # Begin by reading the "sqlite3.h" header file.  Extract the version number
    26         -# from in this file.  The versioon number is needed to generate the header
           26  +# from in this file.  The version number is needed to generate the header
    27     27   # comment of the amalgamation.
    28     28   #
    29     29   if {[lsearch $argv --nostatic]>=0} {
    30     30     set addstatic 0
    31     31   } else {
    32     32     set addstatic 1
    33     33   }
................................................................................
    76     76   */
    77     77   #define SQLITE_CORE 1
    78     78   #define SQLITE_AMALGAMATION 1}]
    79     79   if {$addstatic} {
    80     80     puts $out \
    81     81   {#ifndef SQLITE_PRIVATE
    82     82   # define SQLITE_PRIVATE static
    83         -#endif
    84         -#ifndef SQLITE_API
    85         -# define SQLITE_API
    86     83   #endif}
    87     84   }
    88     85   
    89     86   # These are the header files used by SQLite.  The first time any of these 
    90     87   # files are seen in a #include statement in the C code, include the complete
    91     88   # text of the file in-line.  The file only needs to be included once.
    92     89   #
................................................................................
   102     99      os_common.h
   103    100      os_setup.h
   104    101      os_win.h
   105    102      os.h
   106    103      pager.h
   107    104      parse.h
   108    105      pcache.h
          106  +   pragma.h
   109    107      sqlite3ext.h
   110    108      sqlite3.h
   111    109      sqliteicu.h
   112    110      sqliteInt.h
   113    111      sqliteLimit.h
   114    112      vdbe.h
   115    113      vdbeInt.h
          114  +   vxworks.h
   116    115      wal.h
          116  +   whereInt.h
   117    117   } {
   118    118     set available_hdr($hdr) 1
   119    119   }
   120    120   set available_hdr(sqliteInt.h) 0
          121  +
          122  +# These headers should be copied into the amalgamation without modifying any
          123  +# of their function declarations or definitions.
          124  +set varonly_hdr(sqlite3.h) 1
          125  +
          126  +# These are the functions that accept a variable number of arguments.  They
          127  +# always need to use the "cdecl" calling convention even when another calling
          128  +# convention (e.g. "stcall") is being used for the rest of the library.
          129  +set cdecllist {
          130  +  sqlite3_config
          131  +  sqlite3_db_config
          132  +  sqlite3_log
          133  +  sqlite3_mprintf
          134  +  sqlite3_snprintf
          135  +  sqlite3_test_control
          136  +  sqlite3_vtab_config
          137  +}
   121    138   
   122    139   # 78 stars used for comment formatting.
   123    140   set s78 \
   124    141   {*****************************************************************************}
   125    142   
   126    143   # Insert a comment into the code
   127    144   #
................................................................................
   131    148     set nstar [expr {60 - $n}]
   132    149     set stars [string range $s78 0 $nstar]
   133    150     puts $out "/************** $text $stars/"
   134    151   }
   135    152   
   136    153   # Read the source file named $filename and write it into the
   137    154   # sqlite3.c output file.  If any #include statements are seen,
   138         -# process them approprately.
          155  +# process them appropriately.
   139    156   #
   140    157   proc copy_file {filename} {
   141         -  global seen_hdr available_hdr out addstatic linemacros
          158  +  global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
   142    159     set ln 0
   143    160     set tail [file tail $filename]
   144    161     section_comment "Begin file $tail"
   145    162     if {$linemacros} {puts $out "#line 1 \"$filename\""}
   146    163     set in [open $filename r]
   147    164     set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
   148         -  set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(}
          165  +  set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
   149    166     if {[file extension $filename]==".h"} {
   150    167       set declpattern " *$declpattern"
   151    168     }
   152         -  set declpattern ^$declpattern
          169  +  set declpattern ^$declpattern\$
   153    170     while {![eof $in]} {
   154    171       set line [gets $in]
   155    172       incr ln
   156    173       if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
   157    174         if {[info exists available_hdr($hdr)]} {
   158    175           if {$available_hdr($hdr)} {
   159    176             if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
................................................................................
   161    178             }
   162    179             section_comment "Include $hdr in the middle of $tail"
   163    180             copy_file tsrc/$hdr
   164    181             section_comment "Continuing where we left off in $tail"
   165    182             if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
   166    183           }
   167    184         } elseif {![info exists seen_hdr($hdr)]} {
   168         -        set seen_hdr($hdr) 1
          185  +        if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
          186  +          set seen_hdr($hdr) 1
          187  +        }
          188  +        puts $out $line
          189  +      } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
          190  +        # This include file must be kept because there was a "keep"
          191  +        # directive inside of a line comment.
   169    192           puts $out $line
   170    193         } else {
   171         -        puts $out "/* $line */"
          194  +        # Comment out the entire line, replacing any nested comment
          195  +        # begin/end markers with the harmless substring "**".
          196  +        puts $out "/* [string map [list /* ** */ **] $line] */"
   172    197         }
   173    198       } elseif {[regexp {^#ifdef __cplusplus} $line]} {
   174    199         puts $out "#if 0"
   175    200       } elseif {!$linemacros && [regexp {^#line} $line]} {
   176    201         # Skip #line directives.
   177    202       } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
   178         -      regsub {^SQLITE_API } $line {} line
   179         -      if {[regexp $declpattern $line all funcname]} {
          203  +      # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
          204  +      # functions if this header file does not need it.
          205  +      if {![info exists varonly_hdr($tail)]
          206  +       && [regexp $declpattern $line all rettype funcname rest]} {
          207  +        regsub {^SQLITE_API } $line {} line
   180    208           # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
   181    209           # so that linkage can be modified at compile-time.
   182    210           if {[regexp {^sqlite3_} $funcname]} {
   183         -          puts $out "SQLITE_API $line"
          211  +          set line SQLITE_API
          212  +          append line " " [string trim $rettype]
          213  +          if {[string index $rettype end] ne "*"} {
          214  +            append line " "
          215  +          }
          216  +          if {[lsearch -exact $cdecllist $funcname] >= 0} {
          217  +            append line SQLITE_CDECL
          218  +          } else {
          219  +            append line SQLITE_STDCALL
          220  +          }
          221  +          append line " " $funcname $rest
          222  +          puts $out $line
   184    223           } else {
   185    224             puts $out "SQLITE_PRIVATE $line"
   186    225           }
   187    226         } elseif {[regexp $varpattern $line all varname]} {
   188         -        # Add the SQLITE_PRIVATE before variable declarations or
   189         -        # definitions for internal use
   190         -        if {![regexp {^sqlite3_} $varname]} {
   191         -          regsub {^extern } $line {} line
   192         -          puts $out "SQLITE_PRIVATE $line"
   193         -        } else {
   194         -          if {[regexp {const char sqlite3_version\[\];} $line]} {
   195         -            set line {const char sqlite3_version[] = SQLITE_VERSION;}
          227  +          # Add the SQLITE_PRIVATE before variable declarations or
          228  +          # definitions for internal use
          229  +          regsub {^SQLITE_API } $line {} line
          230  +          if {![regexp {^sqlite3_} $varname]} {
          231  +            regsub {^extern } $line {} line
          232  +            puts $out "SQLITE_PRIVATE $line"
          233  +          } else {
          234  +            if {[regexp {const char sqlite3_version\[\];} $line]} {
          235  +              set line {const char sqlite3_version[] = SQLITE_VERSION;}
          236  +            }
          237  +            regsub {^SQLITE_EXTERN } $line {} line
          238  +            puts $out "SQLITE_API $line"
   196    239             }
   197         -          regsub {^SQLITE_EXTERN } $line {} line
   198         -          puts $out "SQLITE_API $line"
   199         -        }
   200    240         } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
          241  +        regsub {^SQLITE_API } $line {} line
   201    242           regsub {^SQLITE_EXTERN } $line {} line
   202         -        puts $out "SQLITE_PRIVATE $line"
          243  +        puts $out $line
   203    244         } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
          245  +        regsub {^SQLITE_API } $line {} line
   204    246           puts $out "SQLITE_PRIVATE $line"
   205    247         } else {
   206    248           puts $out $line
   207    249         }
   208    250       } else {
   209    251         puts $out $line
   210    252       }

Changes to tool/mksqlite3c.tcl.

    76     76   */
    77     77   #define SQLITE_CORE 1
    78     78   #define SQLITE_AMALGAMATION 1}]
    79     79   if {$addstatic} {
    80     80     puts $out \
    81     81   {#ifndef SQLITE_PRIVATE
    82     82   # define SQLITE_PRIVATE static
    83         -#endif
    84         -#ifndef SQLITE_API
    85         -# define SQLITE_API
    86     83   #endif}
    87     84   }
    88     85   
    89     86   # These are the header files used by SQLite.  The first time any of these 
    90     87   # files are seen in a #include statement in the C code, include the complete
    91     88   # text of the file in-line.  The file only needs to be included once.
    92     89   #
................................................................................
   124    121      wal.h
   125    122      whereInt.h
   126    123   } {
   127    124     set available_hdr($hdr) 1
   128    125   }
   129    126   set available_hdr(sqliteInt.h) 0
   130    127   set available_hdr(sqlite3session.h) 0
          128  +
          129  +# These headers should be copied into the amalgamation without modifying any
          130  +# of their function declarations or definitions.
          131  +set varonly_hdr(sqlite3.h) 1
          132  +
          133  +# These are the functions that accept a variable number of arguments.  They
          134  +# always need to use the "cdecl" calling convention even when another calling
          135  +# convention (e.g. "stcall") is being used for the rest of the library.
          136  +set cdecllist {
          137  +  sqlite3_config
          138  +  sqlite3_db_config
          139  +  sqlite3_log
          140  +  sqlite3_mprintf
          141  +  sqlite3_snprintf
          142  +  sqlite3_test_control
          143  +  sqlite3_vtab_config
          144  +}
   131    145   
   132    146   # 78 stars used for comment formatting.
   133    147   set s78 \
   134    148   {*****************************************************************************}
   135    149   
   136    150   # Insert a comment into the code
   137    151   #
................................................................................
   144    158   }
   145    159   
   146    160   # Read the source file named $filename and write it into the
   147    161   # sqlite3.c output file.  If any #include statements are seen,
   148    162   # process them appropriately.
   149    163   #
   150    164   proc copy_file {filename} {
   151         -  global seen_hdr available_hdr out addstatic linemacros
          165  +  global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
   152    166     set ln 0
   153    167     set tail [file tail $filename]
   154    168     section_comment "Begin file $tail"
   155    169     if {$linemacros} {puts $out "#line 1 \"$filename\""}
   156    170     set in [open $filename r]
   157    171     set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
   158         -  set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(}
          172  +  set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
   159    173     if {[file extension $filename]==".h"} {
   160    174       set declpattern " *$declpattern"
   161    175     }
   162         -  set declpattern ^$declpattern
          176  +  set declpattern ^$declpattern\$
   163    177     while {![eof $in]} {
   164    178       set line [gets $in]
   165    179       incr ln
   166    180       if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
   167    181         if {[info exists available_hdr($hdr)]} {
   168    182           if {$available_hdr($hdr)} {
   169    183             if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
................................................................................
   189    203           puts $out "/* [string map [list /* ** */ **] $line] */"
   190    204         }
   191    205       } elseif {[regexp {^#ifdef __cplusplus} $line]} {
   192    206         puts $out "#if 0"
   193    207       } elseif {!$linemacros && [regexp {^#line} $line]} {
   194    208         # Skip #line directives.
   195    209       } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
   196         -      regsub {^SQLITE_API } $line {} line
   197         -      if {[regexp $declpattern $line all funcname]} {
          210  +      # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
          211  +      # functions if this header file does not need it.
          212  +      if {![info exists varonly_hdr($tail)]
          213  +       && [regexp $declpattern $line all rettype funcname rest]} {
          214  +        regsub {^SQLITE_API } $line {} line
   198    215           # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
   199    216           # so that linkage can be modified at compile-time.
   200    217           if {[regexp {^sqlite3[a-z]*_} $funcname]} {
   201         -          puts $out "SQLITE_API $line"
          218  +          set line SQLITE_API
          219  +          append line " " [string trim $rettype]
          220  +          if {[string index $rettype end] ne "*"} {
          221  +            append line " "
          222  +          }
          223  +          if {[lsearch -exact $cdecllist $funcname] >= 0} {
          224  +            append line SQLITE_CDECL
          225  +          } else {
          226  +            append line SQLITE_STDCALL
          227  +          }
          228  +          append line " " $funcname $rest
          229  +          puts $out $line
   202    230           } else {
   203    231             puts $out "SQLITE_PRIVATE $line"
   204    232           }
   205    233         } elseif {[regexp $varpattern $line all varname]} {
   206         -        # Add the SQLITE_PRIVATE before variable declarations or
   207         -        # definitions for internal use
   208         -        if {![regexp {^sqlite3_} $varname]} {
   209         -          regsub {^extern } $line {} line
   210         -          puts $out "SQLITE_PRIVATE $line"
   211         -        } else {
   212         -          if {[regexp {const char sqlite3_version\[\];} $line]} {
   213         -            set line {const char sqlite3_version[] = SQLITE_VERSION;}
          234  +          # Add the SQLITE_PRIVATE before variable declarations or
          235  +          # definitions for internal use
          236  +          regsub {^SQLITE_API } $line {} line
          237  +          if {![regexp {^sqlite3_} $varname]} {
          238  +            regsub {^extern } $line {} line
          239  +            puts $out "SQLITE_PRIVATE $line"
          240  +          } else {
          241  +            if {[regexp {const char sqlite3_version\[\];} $line]} {
          242  +              set line {const char sqlite3_version[] = SQLITE_VERSION;}
          243  +            }
          244  +            regsub {^SQLITE_EXTERN } $line {} line
          245  +            puts $out "SQLITE_API $line"
   214    246             }
   215         -          regsub {^SQLITE_EXTERN } $line {} line
   216         -          puts $out "SQLITE_API $line"
   217         -        }
   218    247         } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
          248  +        regsub {^SQLITE_API } $line {} line
   219    249           regsub {^SQLITE_EXTERN } $line {} line
   220    250           puts $out $line
   221    251         } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
          252  +        regsub {^SQLITE_API } $line {} line
   222    253           puts $out "SQLITE_PRIVATE $line"
   223    254         } else {
   224    255           puts $out $line
   225    256         }
   226    257       } else {
   227    258         puts $out $line
   228    259       }

Changes to tool/mksqlite3h.tcl.

    59     59     }
    60     60   }
    61     61   close $in
    62     62   
    63     63   # Set up patterns for recognizing API declarations.
    64     64   #
    65     65   set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+sqlite3_[_a-zA-Z0-9]+(\[|;| =)}
    66         -set declpattern {^ *[a-zA-Z][a-zA-Z_0-9 ]+ \**sqlite3_[_a-zA-Z0-9]+\(}
           66  +set declpattern {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3_[_a-zA-Z0-9]+)(\(.*)$}
    67     67   
    68     68   # Force the output to use unix line endings, even on Windows.
    69     69   fconfigure stdout -translation lf
    70     70   
    71     71   set filelist [subst {
    72     72     $TOP/src/sqlite.h.in
    73     73     $TOP/ext/rtree/sqlite3rtree.h
    74     74     $TOP/ext/session/sqlite3session.h
    75     75   }]
           76  +
           77  +# These are the functions that accept a variable number of arguments.  They
           78  +# always need to use the "cdecl" calling convention even when another calling
           79  +# convention (e.g. "stcall") is being used for the rest of the library.
           80  +set cdecllist {
           81  +  sqlite3_config
           82  +  sqlite3_db_config
           83  +  sqlite3_log
           84  +  sqlite3_mprintf
           85  +  sqlite3_snprintf
           86  +  sqlite3_test_control
           87  +  sqlite3_vtab_config
           88  +}
    76     89   
    77     90   # Process the source files.
    78     91   #
    79     92   foreach file $filelist {
    80     93     set in [open $file]
    81     94     if {![regexp {sqlite\.h\.in} $file]} {
    82     95       puts "/******** Begin file [file tail $file] *********/"
................................................................................
    89    102       # line when copying sqlite3rtree.h into sqlite3.h.
    90    103       #
    91    104       if {[string match {*#include*<sqlite3.h>*} $line]} continue
    92    105     
    93    106       regsub -- --VERS--           $line $zVersion line
    94    107       regsub -- --VERSION-NUMBER-- $line $nVersion line
    95    108       regsub -- --SOURCE-ID--      $line "$zDate $zUuid" line
    96         -  
    97         -    if {[regexp {define SQLITE_EXTERN extern} $line]} {
    98         -      puts $line
    99         -      puts [gets $in]
   100         -      puts ""
   101         -      puts "#ifndef SQLITE_API"
   102         -      puts "# define SQLITE_API"
   103         -      puts "#endif"
   104         -      set line ""
   105         -    }
   106         -  
   107         -    if {([regexp $varpattern $line] && ![regexp {^ *typedef} $line])
   108         -     || ([regexp $declpattern $line])
   109         -    } {
          109  +
          110  +    if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} {
   110    111         set line "SQLITE_API $line"
          112  +    } else {
          113  +      if {[regexp $declpattern $line all rettype funcname rest]} {
          114  +        set line SQLITE_API
          115  +        append line " " [string trim $rettype]
          116  +        if {[string index $rettype end] ne "*"} {
          117  +          append line " "
          118  +        }
          119  +        if {[lsearch -exact $cdecllist $funcname] >= 0} {
          120  +          append line SQLITE_CDECL
          121  +        } else {
          122  +          append line SQLITE_STDCALL
          123  +        }
          124  +        append line " " $funcname $rest
          125  +      }
   111    126       }
   112    127       puts $line
   113    128     }
   114    129     close $in
   115    130     if {![regexp {sqlite\.h\.in} $file]} {
   116    131       puts "/******** End of [file tail $file] *********/"
   117    132     }
   118    133   }