/ Check-in [f021559d]
Login

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

Overview
Comment:Merge updates from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | configReadOnly
Files: files | file ages | folders
SHA1:f021559d8a23934e3bdccad5b55fc7a91d185f53
User & Date: mistachkin 2012-10-16 23:08:28
Context
2012-12-08
06:46
Merge updates from trunk. check-in: e65db42c user: mistachkin tags: configReadOnly
2012-10-16
23:08
Merge updates from trunk. check-in: f021559d user: mistachkin tags: configReadOnly
2012-10-15
20:28
Correct comments and enhance readability of the mkvsix tool. check-in: 2c3af657 user: mistachkin tags: trunk
2012-10-07
14:14
Merge updates from trunk. check-in: bbb0d189 user: mistachkin tags: configReadOnly
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.msc.

     5      5   # The toplevel directory of the source tree.  This is the directory
     6      6   # that contains this "Makefile.msc".
     7      7   #
     8      8   TOP = .
     9      9   
    10     10   # Set this non-0 to create and use the SQLite amalgamation file.
    11     11   #
           12  +!IFNDEF USE_AMALGAMATION
    12     13   USE_AMALGAMATION = 1
           14  +!ENDIF
    13     15   
    14     16   # Set this non-0 to use the International Components for Unicode (ICU).
    15     17   #
           18  +!IFNDEF USE_ICU
    16     19   USE_ICU = 0
           20  +!ENDIF
    17     21   
    18     22   # Set this non-0 to dynamically link to the MSVC runtime library.
    19     23   #
           24  +!IFNDEF USE_CRT_DLL
    20     25   USE_CRT_DLL = 0
           26  +!ENDIF
    21     27   
    22     28   # Set this non-0 to attempt setting the native compiler automatically
    23     29   # for cross-compiling the command line tools needed during the compilation
    24     30   # process.
    25     31   #
           32  +!IFNDEF XCOMPILE
    26     33   XCOMPILE = 0
           34  +!ENDIF
    27     35   
    28     36   # Set this non-0 to use the native libraries paths for cross-compiling
    29     37   # the command line tools needed during the compilation process.
    30     38   #
           39  +!IFNDEF USE_NATIVE_LIBPATHS
    31     40   USE_NATIVE_LIBPATHS = 0
           41  +!ENDIF
    32     42   
    33     43   # Set this 0 to skip the compiling and embedding of version resources.
    34     44   #
           45  +!IFNDEF USE_RC
    35     46   USE_RC = 1
           47  +!ENDIF
    36     48   
    37     49   # Set this non-0 to compile binaries suitable for the WinRT environment.
    38     50   # This setting does not apply to any binaries that require Tcl to operate
    39     51   # properly (i.e. the text fixture, etc).
    40     52   #
           53  +!IFNDEF FOR_WINRT
    41     54   FOR_WINRT = 0
           55  +!ENDIF
    42     56   
    43     57   # Set this non-0 to skip attempting to look for and/or link with the Tcl
    44     58   # runtime library.
    45     59   #
           60  +!IFNDEF NO_TCL
    46     61   NO_TCL = 0
           62  +!ENDIF
    47     63   
    48     64   # Set this to non-0 to create and use PDBs.
    49     65   #
           66  +!IFNDEF SYMBOLS
    50     67   SYMBOLS = 1
           68  +!ENDIF
    51     69   
    52     70   # Set this to non-0 to use the SQLite debugging heap subsystem.
    53     71   #
           72  +!IFNDEF MEMDEBUG
    54     73   MEMDEBUG = 0
           74  +!ENDIF
    55     75   
    56     76   # Set this to non-0 to use the Win32 native heap subsystem.
    57     77   #
           78  +!IFNDEF WIN32HEAP
    58     79   WIN32HEAP = 0
           80  +!ENDIF
    59     81   
    60     82   # Set this to one of the following values to enable various debugging
    61     83   # features.  Each level includes the debugging options from the previous
    62     84   # levels.  Currently, the recognized values for DEBUG are:
    63     85   #
    64     86   # 0 == NDEBUG: Disables assert() and other runtime diagnostics.
    65     87   # 1 == Disables NDEBUG and all optimizations and then enables PDBs.
    66     88   # 2 == SQLITE_DEBUG: Enables various diagnostics messages and code.
    67     89   # 3 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
    68     90   # 4 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
    69     91   # 5 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
    70     92   #
           93  +!IFNDEF DEBUG
    71     94   DEBUG = 0
           95  +!ENDIF
    72     96   
    73     97   # Check for the predefined command macro CC.  This should point to the compiler
    74     98   # binary for the target platform.  If it is not defined, simply define it to
    75     99   # the legacy default value 'cl.exe'.
    76    100   #
    77    101   !IFNDEF CC
    78    102   CC = cl.exe

Changes to src/backup.c.

   409    409     
   410    410       /* Update the schema version field in the destination database. This
   411    411       ** is to make sure that the schema-version really does change in
   412    412       ** the case where the source and destination databases have the
   413    413       ** same schema version.
   414    414       */
   415    415       if( rc==SQLITE_DONE ){
   416         -      rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
          416  +      if( nSrcPage==0 ){
          417  +        rc = sqlite3BtreeNewDb(p->pDest);
          418  +        nSrcPage = 1;
          419  +      }
          420  +      if( rc==SQLITE_OK || rc==SQLITE_DONE ){
          421  +        rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
          422  +      }
   417    423         if( rc==SQLITE_OK ){
   418    424           if( p->pDestDb ){
   419    425             sqlite3ResetAllSchemasOfConnection(p->pDestDb);
   420    426           }
   421    427           if( destMode==PAGER_JOURNALMODE_WAL ){
   422    428             rc = sqlite3BtreeSetVersion(p->pDest, 2);
   423    429           }
................................................................................
   443    449             nDestTruncate = (nSrcPage+ratio-1)/ratio;
   444    450             if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
   445    451               nDestTruncate--;
   446    452             }
   447    453           }else{
   448    454             nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
   449    455           }
          456  +        assert( nDestTruncate>0 );
   450    457           sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
   451    458   
   452    459           if( pgszSrc<pgszDest ){
   453    460             /* If the source page-size is smaller than the destination page-size,
   454    461             ** two extra things may need to happen:
   455    462             **
   456    463             **   * The destination may need to be truncated, and
................................................................................
   461    468             */
   462    469             const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
   463    470             sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
   464    471             i64 iOff;
   465    472             i64 iEnd;
   466    473   
   467    474             assert( pFile );
   468         -          assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
          475  +          assert( nDestTruncate==0 
          476  +              || (i64)nDestTruncate*(i64)pgszDest >= iSize || (
   469    477                   nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
   470    478                && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
   471    479             ));
   472    480   
   473    481             /* This call ensures that all data required to recreate the original
   474    482             ** database has been stored in the journal for pDestPager and the
   475    483             ** journal synced to disk. So at this point we may safely modify

Changes to src/btree.c.

  2526   2526     put4byte(&data[36 + 4*4], pBt->autoVacuum);
  2527   2527     put4byte(&data[36 + 7*4], pBt->incrVacuum);
  2528   2528   #endif
  2529   2529     pBt->nPage = 1;
  2530   2530     data[31] = 1;
  2531   2531     return SQLITE_OK;
  2532   2532   }
         2533  +
         2534  +/*
         2535  +** Initialize the first page of the database file (creating a database
         2536  +** consisting of a single page and no schema objects). Return SQLITE_OK
         2537  +** if successful, or an SQLite error code otherwise.
         2538  +*/
         2539  +int sqlite3BtreeNewDb(Btree *p){
         2540  +  int rc;
         2541  +  sqlite3BtreeEnter(p);
         2542  +  p->pBt->nPage = 0;
         2543  +  rc = newDatabase(p->pBt);
         2544  +  sqlite3BtreeLeave(p);
         2545  +  return rc;
         2546  +}
  2533   2547   
  2534   2548   /*
  2535   2549   ** Attempt to start a new transaction. A write-transaction
  2536   2550   ** is started if the second argument is nonzero, otherwise a read-
  2537   2551   ** transaction.  If the second argument is 2 or more and exclusive
  2538   2552   ** transaction is started, meaning that no other process is allowed
  2539   2553   ** to access the database.  A preexisting transaction may not be

Changes to src/btree.h.

   112    112   
   113    113   int sqlite3BtreeDropTable(Btree*, int, int*);
   114    114   int sqlite3BtreeClearTable(Btree*, int, int*);
   115    115   void sqlite3BtreeTripAllCursors(Btree*, int);
   116    116   
   117    117   void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
   118    118   int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
          119  +
          120  +int sqlite3BtreeNewDb(Btree *p);
   119    121   
   120    122   /*
   121    123   ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
   122    124   ** should be one of the following values. The integer values are assigned 
   123    125   ** to constants so that the offset of the corresponding field in an
   124    126   ** SQLite database header may be found using the following formula:
   125    127   **

Changes to src/build.c.

  2015   2015           iLargest = iIdx;
  2016   2016         }
  2017   2017       }
  2018   2018       if( iLargest==0 ){
  2019   2019         return;
  2020   2020       }else{
  2021   2021         int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
         2022  +      assert( iDb>=0 && iDb<pParse->db->nDb );
  2022   2023         destroyRootPage(pParse, iLargest, iDb);
  2023   2024         iDestroyed = iLargest;
  2024   2025       }
  2025   2026     }
  2026   2027   #endif
  2027   2028   }
  2028   2029   
................................................................................
  2573   2574           sqlite3FixSrcList(&sFix, pTblName)
  2574   2575       ){
  2575   2576         /* Because the parser constructs pTblName from a single identifier,
  2576   2577         ** sqlite3FixSrcList can never fail. */
  2577   2578         assert(0);
  2578   2579       }
  2579   2580       pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
  2580         -    if( !pTab || db->mallocFailed ) goto exit_create_index;
         2581  +    assert( db->mallocFailed==0 || pTab==0 );
         2582  +    if( pTab==0 ) goto exit_create_index;
  2581   2583       assert( db->aDb[iDb].pSchema==pTab->pSchema );
  2582   2584     }else{
  2583   2585       assert( pName==0 );
  2584   2586       assert( pStart==0 );
  2585   2587       pTab = pParse->pNewTable;
  2586   2588       if( !pTab ) goto exit_create_index;
  2587   2589       iDb = sqlite3SchemaToIndex(db, pTab->pSchema);

Changes to src/insert.c.

  1271   1271     if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
  1272   1272       ExprList *pCheck = pTab->pCheck;
  1273   1273       pParse->ckBase = regData;
  1274   1274       onError = overrideError!=OE_Default ? overrideError : OE_Abort;
  1275   1275       for(i=0; i<pCheck->nExpr; i++){
  1276   1276         int allOk = sqlite3VdbeMakeLabel(v);
  1277   1277         Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0);
  1278         -      if( pDup==0 ) break;
  1279         -      sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL);
  1280         -      if( onError==OE_Ignore ){
  1281         -        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
  1282         -      }else{
  1283         -        char *zConsName = pCheck->a[i].zName;
  1284         -        if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
  1285         -        if( zConsName ){
  1286         -          zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
         1278  +      if( !db->mallocFailed ){
         1279  +        assert( pDup!=0 );
         1280  +        sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL);
         1281  +        if( onError==OE_Ignore ){
         1282  +          sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
  1287   1283           }else{
  1288         -          zConsName = 0;
         1284  +          char *zConsName = pCheck->a[i].zName;
         1285  +          if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
         1286  +          if( zConsName ){
         1287  +            zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
         1288  +          }else{
         1289  +            zConsName = 0;
         1290  +          }
         1291  +          sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
  1289   1292           }
  1290         -        sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
         1293  +        sqlite3VdbeResolveLabel(v, allOk);
  1291   1294         }
  1292         -      sqlite3VdbeResolveLabel(v, allOk);
  1293   1295         sqlite3ExprDelete(db, pDup);
  1294   1296       }
  1295   1297     }
  1296   1298   #endif /* !defined(SQLITE_OMIT_CHECK) */
  1297   1299   
  1298   1300     /* If we have an INTEGER PRIMARY KEY, make sure the primary key
  1299   1301     ** of the new record does not previously exist.  Except, if this

Changes to src/lempar.c.

   604    604     **  #line <lineno> <grammarfile>
   605    605     **     { ... }           // User supplied code
   606    606     **  #line <lineno> <thisfile>
   607    607     **     break;
   608    608     */
   609    609   %%
   610    610     };
          611  +  assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
   611    612     yygoto = yyRuleInfo[yyruleno].lhs;
   612    613     yysize = yyRuleInfo[yyruleno].nrhs;
   613    614     yypParser->yyidx -= yysize;
   614    615     yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
   615    616     if( yyact < YYNSTATE ){
   616    617   #ifdef NDEBUG
   617    618       /* If we are not debugging and the reduce action popped at least

Changes to src/os_unix.c.

  2082   2082     return SQLITE_OK;
  2083   2083   }
  2084   2084   
  2085   2085   /*
  2086   2086   ** Close a file.  Make sure the lock has been released before closing.
  2087   2087   */
  2088   2088   static int dotlockClose(sqlite3_file *id) {
  2089         -  int rc;
         2089  +  int rc = SQLITE_OK;
  2090   2090     if( id ){
  2091   2091       unixFile *pFile = (unixFile*)id;
  2092   2092       dotlockUnlock(id, NO_LOCK);
  2093   2093       sqlite3_free(pFile->lockingContext);
         2094  +    rc = closeUnixFile(id);
  2094   2095     }
  2095         -  rc = closeUnixFile(id);
  2096   2096     return rc;
  2097   2097   }
  2098   2098   /****************** End of the dot-file lock implementation *******************
  2099   2099   ******************************************************************************/
  2100   2100   
  2101   2101   /******************************************************************************
  2102   2102   ************************** Begin flock Locking ********************************
................................................................................
  2292   2292     }
  2293   2293   }
  2294   2294   
  2295   2295   /*
  2296   2296   ** Close a file.
  2297   2297   */
  2298   2298   static int flockClose(sqlite3_file *id) {
         2299  +  int rc = SQLITE_OK;
  2299   2300     if( id ){
  2300   2301       flockUnlock(id, NO_LOCK);
         2302  +    rc = closeUnixFile(id);
  2301   2303     }
  2302         -  return closeUnixFile(id);
         2304  +  return rc;
  2303   2305   }
  2304   2306   
  2305   2307   #endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
  2306   2308   
  2307   2309   /******************* End of the flock lock implementation *********************
  2308   2310   ******************************************************************************/
  2309   2311   
................................................................................
  4094   4096       }
  4095   4097       pShmNode->apRegion = apNew;
  4096   4098       while(pShmNode->nRegion<=iRegion){
  4097   4099         void *pMem;
  4098   4100         if( pShmNode->h>=0 ){
  4099   4101           pMem = mmap(0, szRegion,
  4100   4102               pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
  4101         -            MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
         4103  +            MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
  4102   4104           );
  4103   4105           if( pMem==MAP_FAILED ){
  4104   4106             rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
  4105   4107             goto shmpage_out;
  4106   4108           }
  4107   4109         }else{
  4108   4110           pMem = sqlite3_malloc(szRegion);

Changes to src/os_win.c.

    29     29   ** available in Windows platforms based on the NT kernel.
    30     30   */
    31     31   #if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
    32     32   # error "WAL mode requires support from the Windows NT kernel, compile\
    33     33    with SQLITE_OMIT_WAL."
    34     34   #endif
    35     35   
           36  +/*
           37  +** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
           38  +** based on the sub-platform)?
           39  +*/
           40  +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
           41  +#  define SQLITE_WIN32_HAS_ANSI
           42  +#endif
           43  +
           44  +/*
           45  +** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
           46  +** based on the sub-platform)?
           47  +*/
           48  +#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
           49  +#  define SQLITE_WIN32_HAS_WIDE
           50  +#endif
           51  +
           52  +/*
           53  +** Do we need to manually define the Win32 file mapping APIs for use with WAL
           54  +** mode (e.g. these APIs are available in the Windows CE SDK; however, they
           55  +** are not present in the header file)?
           56  +*/
           57  +#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
           58  +/*
           59  +** Two of the file mapping APIs are different under WinRT.  Figure out which
           60  +** set we need.
           61  +*/
           62  +#if SQLITE_OS_WINRT
           63  +WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
           64  +        LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
           65  +
           66  +WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
           67  +#else
           68  +#if defined(SQLITE_WIN32_HAS_ANSI)
           69  +WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
           70  +        DWORD, DWORD, DWORD, LPCSTR);
           71  +#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
           72  +
           73  +#if defined(SQLITE_WIN32_HAS_WIDE)
           74  +WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
           75  +        DWORD, DWORD, DWORD, LPCWSTR);
           76  +#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
           77  +
           78  +WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
           79  +#endif /* SQLITE_OS_WINRT */
           80  +
           81  +/*
           82  +** This file mapping API is common to both Win32 and WinRT.
           83  +*/
           84  +WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
           85  +#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
           86  +
    36     87   /*
    37     88   ** Macro to find the minimum of two numeric values.
    38     89   */
    39     90   #ifndef MIN
    40     91   # define MIN(x,y) ((x)<(y)?(x):(y))
    41     92   #endif
    42     93   
................................................................................
   234    285   */
   235    286   #ifdef SQLITE_TEST
   236    287   int sqlite3_os_type = 0;
   237    288   #else
   238    289   static int sqlite3_os_type = 0;
   239    290   #endif
   240    291   
   241         -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
   242         -#  define SQLITE_WIN32_HAS_ANSI
   243         -#endif
   244         -
   245         -#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
   246         -#  define SQLITE_WIN32_HAS_WIDE
   247         -#endif
   248         -
   249    292   #ifndef SYSCALL
   250    293   #  define SYSCALL sqlite3_syscall_ptr
   251    294   #endif
   252    295   
   253    296   /*
   254    297   ** This function is not available on Windows CE or WinRT.
   255    298    */

Changes to src/pager.c.

  5661   5661   # define DIRECT_MODE 0
  5662   5662     assert( isDirectMode==0 );
  5663   5663     UNUSED_PARAMETER(isDirectMode);
  5664   5664   #else
  5665   5665   # define DIRECT_MODE isDirectMode
  5666   5666   #endif
  5667   5667   
  5668         -  if( !pPager->changeCountDone && pPager->dbSize>0 ){
         5668  +  if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
  5669   5669       PgHdr *pPgHdr;                /* Reference to page 1 */
  5670   5670   
  5671   5671       assert( !pPager->tempFile && isOpen(pPager->fd) );
  5672   5672   
  5673   5673       /* Open page 1 of the file for writing. */
  5674   5674       rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
  5675   5675       assert( pPgHdr==0 || rc==SQLITE_OK );
................................................................................
  6912   6912                              pPager->pageSize, (u8*)pPager->pTmpSpace);
  6913   6913         pPager->pWal = 0;
  6914   6914       }
  6915   6915     }
  6916   6916     return rc;
  6917   6917   }
  6918   6918   
         6919  +#endif /* !SQLITE_OMIT_WAL */
         6920  +
  6919   6921   #ifdef SQLITE_ENABLE_ZIPVFS
  6920   6922   /*
  6921   6923   ** A read-lock must be held on the pager when this function is called. If
  6922   6924   ** the pager is in WAL mode and the WAL file currently contains one or more
  6923   6925   ** frames, return the size in bytes of the page images stored within the
  6924   6926   ** WAL frames. Otherwise, if this is not a WAL database or the WAL file
  6925   6927   ** is empty, return 0.
................................................................................
  6941   6943   void *sqlite3PagerCodec(PgHdr *pPg){
  6942   6944     void *aData = 0;
  6943   6945     CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
  6944   6946     return aData;
  6945   6947   }
  6946   6948   #endif /* SQLITE_HAS_CODEC */
  6947   6949   
  6948         -#endif /* !SQLITE_OMIT_WAL */
  6949         -
  6950   6950   #endif /* SQLITE_OMIT_DISKIO */

Changes to src/pager.h.

   134    134   int sqlite3PagerSync(Pager *pPager);
   135    135   int sqlite3PagerCommitPhaseTwo(Pager*);
   136    136   int sqlite3PagerRollback(Pager*);
   137    137   int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
   138    138   int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
   139    139   int sqlite3PagerSharedLock(Pager *pPager);
   140    140   
   141         -int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
   142         -int sqlite3PagerWalSupported(Pager *pPager);
   143         -int sqlite3PagerWalCallback(Pager *pPager);
   144         -int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
   145         -int sqlite3PagerCloseWal(Pager *pPager);
          141  +#ifndef SQLITE_OMIT_WAL
          142  +  int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
          143  +  int sqlite3PagerWalSupported(Pager *pPager);
          144  +  int sqlite3PagerWalCallback(Pager *pPager);
          145  +  int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
          146  +  int sqlite3PagerCloseWal(Pager *pPager);
          147  +#endif
          148  +
   146    149   #ifdef SQLITE_ENABLE_ZIPVFS
   147    150     int sqlite3PagerWalFramesize(Pager *pPager);
   148    151   #endif
   149    152   
   150    153   /* Functions used to query pager state and configuration. */
   151    154   u8 sqlite3PagerIsreadonly(Pager*);
   152    155   int sqlite3PagerRefcount(Pager*);

Changes to src/pragma.c.

  1565   1565       int i;
  1566   1566       sqlite3VdbeSetNumCols(v, 2);
  1567   1567       pParse->nMem = 2;
  1568   1568       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC);
  1569   1569       sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC);
  1570   1570       for(i=0; i<db->nDb; i++){
  1571   1571         Btree *pBt;
  1572         -      Pager *pPager;
  1573   1572         const char *zState = "unknown";
  1574   1573         int j;
  1575   1574         if( db->aDb[i].zName==0 ) continue;
  1576   1575         sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC);
  1577   1576         pBt = db->aDb[i].pBt;
  1578         -      if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
         1577  +      if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
  1579   1578           zState = "closed";
  1580   1579         }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, 
  1581   1580                                        SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
  1582   1581            zState = azLockName[j];
  1583   1582         }
  1584   1583         sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
  1585   1584         sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);

Changes to src/resolve.c.

   191    191     struct SrcList_item *pMatch = 0;  /* The matching pSrcList item */
   192    192     NameContext *pTopNC = pNC;        /* First namecontext in the list */
   193    193     Schema *pSchema = 0;              /* Schema of the expression */
   194    194     int isTrigger = 0;
   195    195   
   196    196     assert( pNC );     /* the name context cannot be NULL. */
   197    197     assert( zCol );    /* The Z in X.Y.Z cannot be NULL */
   198         -  assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
          198  +  assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
   199    199   
   200    200     /* Initialize the node to no-match */
   201    201     pExpr->iTable = -1;
   202    202     pExpr->pTab = 0;
   203    203     ExprSetIrreducible(pExpr);
   204    204   
   205    205     /* Start at the inner-most context and move outward until a match is found */

Changes to src/select.c.

  3094   3094       **
  3095   3095       ** We look at every expression in the outer query and every place we see
  3096   3096       ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
  3097   3097       */
  3098   3098       pList = pParent->pEList;
  3099   3099       for(i=0; i<pList->nExpr; i++){
  3100   3100         if( pList->a[i].zName==0 ){
  3101         -        const char *zSpan = pList->a[i].zSpan;
  3102         -        if( ALWAYS(zSpan) ){
  3103         -          pList->a[i].zName = sqlite3DbStrDup(db, zSpan);
  3104         -        }
         3101  +        char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan);
         3102  +        sqlite3Dequote(zName);
         3103  +        pList->a[i].zName = zName;
  3105   3104         }
  3106   3105       }
  3107   3106       substExprList(db, pParent->pEList, iParent, pSub->pEList);
  3108   3107       if( isAgg ){
  3109   3108         substExprList(db, pParent->pGroupBy, iParent, pSub->pEList);
  3110   3109         pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
  3111   3110       }

Changes to src/sqliteInt.h.

  3181   3181   int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
  3182   3182   int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
  3183   3183   int sqlite3Reprepare(Vdbe*);
  3184   3184   void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
  3185   3185   CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
  3186   3186   int sqlite3TempInMemory(const sqlite3*);
  3187   3187   const char *sqlite3JournalModename(int);
  3188         -int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
  3189         -int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
         3188  +#ifndef SQLITE_OMIT_WAL
         3189  +  int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
         3190  +  int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
         3191  +#endif
  3190   3192   
  3191   3193   /* Declarations for functions in fkey.c. All of these are replaced by
  3192   3194   ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
  3193   3195   ** key functionality is available. If OMIT_TRIGGER is defined but
  3194   3196   ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
  3195   3197   ** this case foreign keys are parsed, but no other functionality is 
  3196   3198   ** provided (enforcement of FK constraints requires the triggers sub-system).

Changes to src/vacuum.c.

    81     81   ** with 2.0.0, SQLite no longer uses GDBM so this command has
    82     82   ** become a no-op.
    83     83   */
    84     84   void sqlite3Vacuum(Parse *pParse){
    85     85     Vdbe *v = sqlite3GetVdbe(pParse);
    86     86     if( v ){
    87     87       sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
           88  +    sqlite3VdbeUsesBtree(v, 0);
    88     89     }
    89     90     return;
    90     91   }
    91     92   
    92     93   /*
    93     94   ** This routine implements the OP_Vacuum opcode of the VDBE.
    94     95   */

Changes to src/vtab.c.

   259    259   ** in the list are moved to the sqlite3.pDisconnect list of the associated 
   260    260   ** database connection.
   261    261   */
   262    262   void sqlite3VtabClear(sqlite3 *db, Table *p){
   263    263     if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
   264    264     if( p->azModuleArg ){
   265    265       int i;
   266         -    assert( p->nModuleArg<2 || p->azModuleArg[1]==0 );
   267    266       for(i=0; i<p->nModuleArg; i++){
   268         -      sqlite3DbFree(db, p->azModuleArg[i]);
          267  +      if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
   269    268       }
   270    269       sqlite3DbFree(db, p->azModuleArg);
   271    270     }
   272    271   }
   273    272   
   274    273   /*
   275    274   ** Add a new module argument to pTable->azModuleArg[].

Changes to src/wal.c.

  2514   2514         ** are no outstanding references to any page other than page 1. And
  2515   2515         ** page 1 is never written to the log until the transaction is
  2516   2516         ** committed. As a result, the call to xUndo may not fail.
  2517   2517         */
  2518   2518         assert( walFramePgno(pWal, iFrame)!=1 );
  2519   2519         rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
  2520   2520       }
  2521         -    walCleanupHash(pWal);
         2521  +    if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
  2522   2522     }
  2523   2523     assert( rc==SQLITE_OK );
  2524   2524     return rc;
  2525   2525   }
  2526   2526   
  2527   2527   /* 
  2528   2528   ** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 

Changes to src/where.c.

  1438   1438   
  1439   1439     /* Prevent ON clause terms of a LEFT JOIN from being used to drive
  1440   1440     ** an index for tables to the left of the join.
  1441   1441     */
  1442   1442     pTerm->prereqRight |= extraRight;
  1443   1443   }
  1444   1444   
  1445         -/*
  1446         -** Return TRUE if the given index is UNIQUE and all columns past the
  1447         -** first nSkip columns are NOT NULL.
  1448         -*/
  1449         -static int indexIsUniqueNotNull(Index *pIdx, int nSkip){
  1450         -  Table *pTab = pIdx->pTable;
  1451         -  int i;
  1452         -  if( pIdx->onError==OE_None ) return 0;
  1453         -  for(i=nSkip; i<pIdx->nColumn; i++){
  1454         -    int j = pIdx->aiColumn[i];
  1455         -    assert( j>=0 && j<pTab->nCol );
  1456         -    if( pTab->aCol[j].notNull==0 ) return 0;
  1457         -  }
  1458         -  return 1;
  1459         -}
  1460         -
  1461   1445   /*
  1462   1446   ** This function searches the expression list passed as the second argument
  1463   1447   ** for an expression of type TK_COLUMN that refers to the same column and
  1464   1448   ** uses the same collation sequence as the iCol'th column of index pIdx.
  1465   1449   ** Argument iBase is the cursor number used for the table that pIdx refers
  1466   1450   ** to.
  1467   1451   **
................................................................................
  2722   2706     }
  2723   2707     return rc;
  2724   2708   }
  2725   2709   #endif /* defined(SQLITE_ENABLE_STAT3) */
  2726   2710   
  2727   2711   /*
  2728   2712   ** Check to see if column iCol of the table with cursor iTab will appear
  2729         -** in sorted order according to the current query plan.  Return true if
  2730         -** it will and false if not.  
         2713  +** in sorted order according to the current query plan.
  2731   2714   **
  2732         -** If *pbRev is initially 2 (meaning "unknown") then set *pbRev to the
  2733         -** sort order of iTab.iCol.  If *pbRev is 0 or 1 but does not match
  2734         -** the sort order of iTab.iCol, then consider the column to be unordered.
         2715  +** Return values:
         2716  +**
         2717  +**    0   iCol is not ordered
         2718  +**    1   iCol has only a single value
         2719  +**    2   iCol is in ASC order
         2720  +**    3   iCol is in DESC order
  2735   2721   */
  2736         -static int isOrderedColumn(WhereBestIdx *p, int iTab, int iCol, int *pbRev){
         2722  +static int isOrderedColumn(
         2723  +  WhereBestIdx *p,
         2724  +  int iTab,
         2725  +  int iCol
         2726  +){
  2737   2727     int i, j;
  2738   2728     WhereLevel *pLevel = &p->aLevel[p->i-1];
  2739   2729     Index *pIdx;
  2740   2730     u8 sortOrder;
  2741   2731     for(i=p->i-1; i>=0; i--, pLevel--){
  2742   2732       if( pLevel->iTabCur!=iTab ) continue;
  2743   2733       if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
  2744   2734         return 1;
  2745   2735       }
  2746         -    if( (pLevel->plan.wsFlags & WHERE_ORDERED)==0 ){
  2747         -      return 0;
  2748         -    }
         2736  +    assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 );
  2749   2737       if( (pIdx = pLevel->plan.u.pIdx)!=0 ){
  2750   2738         if( iCol<0 ){
  2751   2739           sortOrder = 0;
  2752   2740           testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
  2753   2741         }else{
  2754   2742           int n = pIdx->nColumn;
  2755   2743           for(j=0; j<n; j++){
................................................................................
  2765   2753         testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
  2766   2754       }
  2767   2755       if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
  2768   2756         assert( sortOrder==0 || sortOrder==1 );
  2769   2757         testcase( sortOrder==1 );
  2770   2758         sortOrder = 1 - sortOrder;
  2771   2759       }
  2772         -    if( *pbRev==2 ){
  2773         -      *pbRev = sortOrder;
  2774         -      return 1;
  2775         -    }
  2776         -    return (*pbRev==sortOrder);
         2760  +    return sortOrder+2;
  2777   2761     }
  2778   2762     return 0;
  2779   2763   }
  2780   2764   
  2781         -/*
  2782         -** pTerm is an == constraint.  Check to see if the other side of
  2783         -** the == is a constant or a value that is guaranteed to be ordered
  2784         -** by outer loops.  Return 1 if pTerm is ordered, and 0 if not.
  2785         -*/
  2786         -static int isOrderedTerm(WhereBestIdx *p, WhereTerm *pTerm, int *pbRev){
  2787         -  Expr *pExpr = pTerm->pExpr;
  2788         -  assert( pExpr->op==TK_EQ );
  2789         -  assert( pExpr->pLeft!=0 && pExpr->pLeft->op==TK_COLUMN );
  2790         -  assert( pExpr->pRight!=0 );
  2791         -  if( pTerm->prereqRight==0 ){
  2792         -    return 1;  /* RHS of the == is a constant */
  2793         -  }
  2794         -  if( pExpr->pRight->op==TK_COLUMN 
  2795         -   && isOrderedColumn(p, pExpr->pRight->iTable, pExpr->pRight->iColumn, pbRev)
  2796         -  ){
  2797         -    return 1;
  2798         -  }
  2799         -
  2800         -  /* If we cannot prove that the constraint is ordered, assume it is not */
  2801         -  return 0;
  2802         -}
  2803         -
  2804   2765   /*
  2805   2766   ** This routine decides if pIdx can be used to satisfy the ORDER BY
  2806   2767   ** clause, either in whole or in part.  The return value is the 
  2807   2768   ** cumulative number of terms in the ORDER BY clause that are satisfied
  2808   2769   ** by the index pIdx and other indices in outer loops.
  2809   2770   **
  2810   2771   ** The table being queried has a cursor number of "base".  pIdx is the
  2811   2772   ** index that is postulated for use to access the table.
  2812   2773   **
  2813         -** nEqCol is the number of columns of pIdx that are used as equality
  2814         -** constraints and where the other side of the == is an ordered column
  2815         -** or constant.  An "order column" in the previous sentence means a column
  2816         -** in table from an outer loop whose values will always appear in the 
  2817         -** correct order due to othre index, or because the outer loop generates
  2818         -** a unique result.  Any of the first nEqCol columns of pIdx may be missing
  2819         -** from the ORDER BY clause and the match can still be a success.
  2820         -**
  2821   2774   ** The *pbRev value is set to 0 order 1 depending on whether or not
  2822   2775   ** pIdx should be run in the forward order or in reverse order.
  2823   2776   */
  2824   2777   static int isSortingIndex(
  2825   2778     WhereBestIdx *p,    /* Best index search context */
  2826   2779     Index *pIdx,        /* The index we are testing */
  2827   2780     int base,           /* Cursor number for the table to be sorted */
  2828         -  int nEqCol,         /* Number of index columns with ordered == constraints */
  2829         -  int wsFlags,        /* Index usages flags */
  2830         -  int bOuterRev,      /* True if outer loops scan in reverse order */
  2831   2781     int *pbRev          /* Set to 1 for reverse-order scan of pIdx */
  2832   2782   ){
  2833   2783     int i;                        /* Number of pIdx terms used */
  2834   2784     int j;                        /* Number of ORDER BY terms satisfied */
  2835         -  int sortOrder = 0;            /* XOR of index and ORDER BY sort direction */
         2785  +  int sortOrder = 2;            /* 0: forward.  1: backward.  2: unknown */
  2836   2786     int nTerm;                    /* Number of ORDER BY terms */
  2837         -  struct ExprList_item *pTerm;  /* A term of the ORDER BY clause */
         2787  +  struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
         2788  +  Table *pTab = pIdx->pTable;   /* Table that owns index pIdx */
  2838   2789     ExprList *pOrderBy;           /* The ORDER BY clause */
  2839   2790     Parse *pParse = p->pParse;    /* Parser context */
  2840   2791     sqlite3 *db = pParse->db;     /* Database connection */
  2841   2792     int nPriorSat;                /* ORDER BY terms satisfied by outer loops */
  2842   2793     int seenRowid = 0;            /* True if an ORDER BY rowid term is seen */
  2843         -  int nEqOneRow;                /* Idx columns that ref unique values */
         2794  +  int uniqueNotNull;            /* pIdx is UNIQUE with all terms are NOT NULL */
  2844   2795   
  2845   2796     if( p->i==0 ){
  2846   2797       nPriorSat = 0;
  2847   2798     }else{
  2848   2799       nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
  2849         -    if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return nPriorSat;
  2850         -  }
  2851         -  if( nEqCol==0 ){
  2852         -    if( p->i && (p->aLevel[p->i-1].plan.wsFlags & WHERE_ORDERED)==0 ){
         2800  +    if( (p->aLevel[p->i-1].plan.wsFlags & WHERE_ORDERED)==0 ){
         2801  +      /* This loop cannot be ordered unless the next outer loop is
         2802  +      ** also ordered */
         2803  +      return nPriorSat;
         2804  +    }
         2805  +    if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
         2806  +      /* Only look at the outer-most loop if the OrderByIdxJoin
         2807  +      ** optimization is disabled */
  2853   2808         return nPriorSat;
  2854   2809       }
  2855         -    nEqOneRow = 0;
  2856         -  }else if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
  2857         -    nEqOneRow = nEqCol;
  2858         -  }else{
  2859         -    sortOrder = bOuterRev;
  2860         -    nEqOneRow = -1;
  2861   2810     }
  2862   2811     pOrderBy = p->pOrderBy;
  2863   2812     assert( pOrderBy!=0 );
  2864         -  if( wsFlags & WHERE_COLUMN_IN ) return nPriorSat;
  2865         -  if( pIdx->bUnordered ) return nPriorSat;
         2813  +  if( pIdx->bUnordered ){
         2814  +    /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
         2815  +    ** be used for sorting */
         2816  +    return nPriorSat;
         2817  +  }
  2866   2818     nTerm = pOrderBy->nExpr;
         2819  +  uniqueNotNull = pIdx->onError!=OE_None;
  2867   2820     assert( nTerm>0 );
  2868   2821   
  2869   2822     /* Argument pIdx must either point to a 'real' named index structure, 
  2870   2823     ** or an index structure allocated on the stack by bestBtreeIndex() to
  2871   2824     ** represent the rowid index that is part of every table.  */
  2872   2825     assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
  2873   2826   
................................................................................
  2875   2828     ** the index.
  2876   2829     **
  2877   2830     ** Note that indices have pIdx->nColumn regular columns plus
  2878   2831     ** one additional column containing the rowid.  The rowid column
  2879   2832     ** of the index is also allowed to match against the ORDER BY
  2880   2833     ** clause.
  2881   2834     */
  2882         -  for(i=0,j=nPriorSat,pTerm=&pOrderBy->a[j]; j<nTerm; i++){
  2883         -    Expr *pExpr;       /* The expression of the ORDER BY pTerm */
  2884         -    CollSeq *pColl;    /* The collating sequence of pExpr */
  2885         -    int termSortOrder; /* Sort order for this term */
  2886         -    int iColumn;       /* The i-th column of the index.  -1 for rowid */
  2887         -    int iSortOrder;    /* 1 for DESC, 0 for ASC on the i-th index term */
  2888         -    const char *zColl; /* Name of the collating sequence for i-th index term */
         2835  +  j = nPriorSat;
         2836  +  for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){
         2837  +    Expr *pOBExpr;          /* The expression of the ORDER BY pOBItem */
         2838  +    CollSeq *pColl;         /* The collating sequence of pOBExpr */
         2839  +    int termSortOrder;      /* Sort order for this term */
         2840  +    int iColumn;            /* The i-th column of the index.  -1 for rowid */
         2841  +    int iSortOrder;         /* 1 for DESC, 0 for ASC on the i-th index term */
         2842  +    int isEq;               /* Subject to an == or IS NULL constraint */
         2843  +    int isMatch;            /* ORDER BY term matches the index term */
         2844  +    const char *zColl;      /* Name of collating sequence for i-th index term */
         2845  +    WhereTerm *pConstraint; /* A constraint in the WHERE clause */
  2889   2846   
  2890         -    assert( i<=pIdx->nColumn );
  2891         -    pExpr = pTerm->pExpr;
  2892         -    if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){
  2893         -      /* Can not use an index sort on anything that is not a column in the
  2894         -      ** left-most table of the FROM clause */
         2847  +    /* If the next term of the ORDER BY clause refers to anything other than
         2848  +    ** a column in the "base" table, then this index will not be of any
         2849  +    ** further use in handling the ORDER BY. */
         2850  +    pOBExpr = pOBItem->pExpr;
         2851  +    if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
  2895   2852         break;
  2896   2853       }
  2897         -    pColl = sqlite3ExprCollSeq(pParse, pExpr);
  2898         -    if( !pColl ){
  2899         -      pColl = db->pDfltColl;
  2900         -    }
         2854  +
         2855  +    /* Find column number and collating sequence for the next entry
         2856  +    ** in the index */
  2901   2857       if( pIdx->zName && i<pIdx->nColumn ){
  2902   2858         iColumn = pIdx->aiColumn[i];
  2903   2859         if( iColumn==pIdx->pTable->iPKey ){
  2904   2860           iColumn = -1;
  2905   2861         }
  2906   2862         iSortOrder = pIdx->aSortOrder[i];
  2907   2863         zColl = pIdx->azColl[i];
         2864  +      assert( zColl!=0 );
  2908   2865       }else{
  2909   2866         iColumn = -1;
  2910   2867         iSortOrder = 0;
  2911         -      zColl = pColl->zName;
  2912         -    }
  2913         -    if( pExpr->iColumn!=iColumn || sqlite3StrICmp(pColl->zName, zColl) ){
  2914         -      /* Term j of the ORDER BY clause does not match column i of the index */
  2915         -      if( i<nEqCol ){
  2916         -        /* If an index column that is constrained by == fails to match an
  2917         -        ** ORDER BY term, that is OK.  Just ignore that column of the index
  2918         -        */
  2919         -        continue;
  2920         -      }else if( i==pIdx->nColumn ){
  2921         -        /* Index column i is the rowid.  All other terms match. */
         2868  +      zColl = 0;
         2869  +    }
         2870  +
         2871  +    /* Check to see if the column number and collating sequence of the
         2872  +    ** index match the column number and collating sequence of the ORDER BY
         2873  +    ** clause entry.  Set isMatch to 1 if they both match. */
         2874  +    if( pOBExpr->iColumn==iColumn ){
         2875  +      if( zColl ){
         2876  +        pColl = sqlite3ExprCollSeq(pParse, pOBExpr);
         2877  +        if( !pColl ) pColl = db->pDfltColl;
         2878  +        isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
         2879  +      }else{
         2880  +        isMatch = 1;
         2881  +      }
         2882  +    }else{
         2883  +      isMatch = 0;
         2884  +    }
         2885  +
         2886  +    /* termSortOrder is 0 or 1 for whether or not the access loop should
         2887  +    ** run forward or backwards (respectively) in order to satisfy this 
         2888  +    ** term of the ORDER BY clause. */
         2889  +    assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
         2890  +    assert( iSortOrder==0 || iSortOrder==1 );
         2891  +    termSortOrder = iSortOrder ^ pOBItem->sortOrder;
         2892  +
         2893  +    /* If X is the column in the index and ORDER BY clause, check to see
         2894  +    ** if there are any X= or X IS NULL constraints in the WHERE clause. */
         2895  +    pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
         2896  +                           WO_EQ|WO_ISNULL|WO_IN, pIdx);
         2897  +    if( pConstraint==0 ){
         2898  +      isEq = 0;
         2899  +    }else if( pConstraint->eOperator==WO_IN ){
         2900  +      /* Constraints of the form: "X IN ..." cannot be used with an ORDER BY
         2901  +      ** because we do not know in what order the values on the RHS of the IN
         2902  +      ** operator will occur. */
         2903  +      break;
         2904  +    }else if( pConstraint->eOperator==WO_ISNULL ){
         2905  +      uniqueNotNull = 0;
         2906  +      isEq = 1;  /* "X IS NULL" means X has only a single value */
         2907  +    }else if( pConstraint->prereqRight==0 ){
         2908  +      isEq = 1;  /* Constraint "X=constant" means X has only a single value */
         2909  +    }else{
         2910  +      Expr *pRight = pConstraint->pExpr->pRight;
         2911  +      if( pRight->op==TK_COLUMN ){
         2912  +        WHERETRACE(("       .. isOrderedColumn(tab=%d,col=%d)",
         2913  +                    pRight->iTable, pRight->iColumn));
         2914  +        isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
         2915  +        WHERETRACE((" -> isEq=%d\n", isEq));
         2916  +
         2917  +        /* If the constraint is of the form X=Y where Y is an ordered value
         2918  +        ** in an outer loop, then make sure the sort order of Y matches the
         2919  +        ** sort order required for X. */
         2920  +        if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
         2921  +          testcase( isEq==2 );
         2922  +          testcase( isEq==3 );
         2923  +          break;
         2924  +        }
         2925  +      }else{
         2926  +        isEq = 0;  /* "X=expr" places no ordering constraints on X */
         2927  +      }
         2928  +    }
         2929  +    if( !isMatch ){
         2930  +      if( isEq==0 ){
  2922   2931           break;
  2923   2932         }else{
  2924         -        /* If an index column fails to match and is not constrained by ==
  2925         -        ** then the index cannot satisfy the ORDER BY constraint.
  2926         -        */
  2927         -        return nPriorSat;
         2933  +        continue;
  2928   2934         }
  2929         -    }
  2930         -    assert( pIdx->aSortOrder!=0 || iColumn==-1 );
  2931         -    assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 );
  2932         -    assert( iSortOrder==0 || iSortOrder==1 );
  2933         -    termSortOrder = iSortOrder ^ pTerm->sortOrder;
  2934         -    if( i>nEqOneRow ){
  2935         -      if( termSortOrder!=sortOrder ){
  2936         -        /* Indices can only be used if all ORDER BY terms past the
  2937         -        ** equality constraints have the correct DESC or ASC. */
         2935  +    }else if( isEq!=1 ){
         2936  +      if( sortOrder==2 ){
         2937  +        sortOrder = termSortOrder;
         2938  +      }else if( termSortOrder!=sortOrder ){
  2938   2939           break;
  2939   2940         }
  2940         -    }else{
  2941         -      sortOrder = termSortOrder;
  2942   2941       }
  2943   2942       j++;
  2944         -    pTerm++;
         2943  +    pOBItem++;
  2945   2944       if( iColumn<0 ){
  2946   2945         seenRowid = 1;
  2947   2946         break;
         2947  +    }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
         2948  +      testcase( isEq==0 );
         2949  +      testcase( isEq==2 );
         2950  +      testcase( isEq==3 );
         2951  +      uniqueNotNull = 0;
  2948   2952       }
  2949   2953     }
  2950         -  *pbRev = sortOrder;
         2954  +
         2955  +  /* If we have not found at least one ORDER BY term that matches the
         2956  +  ** index, then show no progress. */
         2957  +  if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
         2958  +
         2959  +  /* Return the necessary scan order back to the caller */
         2960  +  *pbRev = sortOrder & 1;
  2951   2961   
  2952   2962     /* If there was an "ORDER BY rowid" term that matched, or it is only
  2953   2963     ** possible for a single row from this table to match, then skip over
  2954   2964     ** any additional ORDER BY terms dealing with this table.
  2955   2965     */
  2956         -  if( seenRowid ||
  2957         -     (   (wsFlags & WHERE_COLUMN_NULL)==0
  2958         -      && i>=pIdx->nColumn
  2959         -      && indexIsUniqueNotNull(pIdx, nEqCol)
  2960         -     )
  2961         -  ){
         2966  +  if( seenRowid || (uniqueNotNull && i>=pIdx->nColumn) ){
  2962   2967       /* Advance j over additional ORDER BY terms associated with base */
  2963   2968       WhereMaskSet *pMS = p->pWC->pMaskSet;
  2964   2969       Bitmask m = ~getMask(pMS, base);
  2965   2970       while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){
  2966   2971         j++;
  2967   2972       }
  2968   2973     }
................................................................................
  3060   3065   
  3061   3066     /* Loop over all indices looking for the best one to use
  3062   3067     */
  3063   3068     for(; pProbe; pIdx=pProbe=pProbe->pNext){
  3064   3069       const tRowcnt * const aiRowEst = pProbe->aiRowEst;
  3065   3070       WhereCost pc;               /* Cost of using pProbe */
  3066   3071       double log10N = (double)1;  /* base-10 logarithm of nRow (inexact) */
  3067         -    int bRev = 2;               /* 0=forward scan.  1=reverse.  2=undecided */
  3068   3072   
  3069   3073       /* The following variables are populated based on the properties of
  3070   3074       ** index being evaluated. They are then used to determine the expected
  3071   3075       ** cost and number of rows returned.
  3072   3076       **
  3073   3077       **  pc.plan.nEq: 
  3074   3078       **    Number of equality terms that can be implemented using the index.
................................................................................
  3091   3095       **
  3092   3096       **    nInMul is set to 1.
  3093   3097       **
  3094   3098       **    If there exists a WHERE term of the form "x IN (SELECT ...)", then 
  3095   3099       **    the sub-select is assumed to return 25 rows for the purposes of 
  3096   3100       **    determining nInMul.
  3097   3101       **
  3098         -    **  nOrdered:
  3099         -    **    The number of equality terms that are constrainted by outer loop
  3100         -    **    variables that are well-ordered.
  3101         -    **
  3102   3102       **  bInEst:  
  3103   3103       **    Set to true if there was at least one "x IN (SELECT ...)" term used 
  3104   3104       **    in determining the value of nInMul.  Note that the RHS of the
  3105   3105       **    IN operator must be a SELECT, not a value list, for this variable
  3106   3106       **    to be true.
  3107   3107       **
  3108   3108       **  rangeDiv:
................................................................................
  3132   3132       **    two queries requires table b-tree lookups in order to find the value
  3133   3133       **    of column c, but the first does not because columns a and b are
  3134   3134       **    both available in the index.
  3135   3135       **
  3136   3136       **             SELECT a, b    FROM tbl WHERE a = 1;
  3137   3137       **             SELECT a, b, c FROM tbl WHERE a = 1;
  3138   3138       */
  3139         -    int nOrdered;                 /* Number of ordered terms matching index */
  3140   3139       int bInEst = 0;               /* True if "x IN (SELECT...)" seen */
  3141   3140       int nInMul = 1;               /* Number of distinct equalities to lookup */
  3142   3141       double rangeDiv = (double)1;  /* Estimated reduction in search space */
  3143   3142       int nBound = 0;               /* Number of range constraints seen */
  3144   3143       int bSort;                    /* True if external sort required */
  3145   3144       int bDist;                    /* True if index cannot help with DISTINCT */
  3146   3145       int bLookup = 0;              /* True if not a covering index */
................................................................................
  3147   3146       int nPriorSat;                /* ORDER BY terms satisfied by outer loops */
  3148   3147       int nOrderBy;                 /* Number of ORDER BY terms */
  3149   3148       WhereTerm *pTerm;             /* A single term of the WHERE clause */
  3150   3149   #ifdef SQLITE_ENABLE_STAT3
  3151   3150       WhereTerm *pFirstTerm = 0;    /* First term matching the index */
  3152   3151   #endif
  3153   3152   
         3153  +    WHERETRACE((
         3154  +      "   %s(%s):\n",
         3155  +      pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
         3156  +    ));
  3154   3157       memset(&pc, 0, sizeof(pc));
  3155   3158       nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
  3156   3159       if( p->i ){
  3157   3160         nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat;
  3158   3161         bSort = nPriorSat<nOrderBy;
  3159   3162         bDist = 0;
  3160   3163       }else{
  3161   3164         nPriorSat = pc.plan.nOBSat = 0;
  3162   3165         bSort = nOrderBy>0;
  3163   3166         bDist = p->pDistinct!=0;
  3164   3167       }
  3165   3168   
  3166   3169       /* Determine the values of pc.plan.nEq and nInMul */
  3167         -    for(pc.plan.nEq=nOrdered=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
         3170  +    for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
  3168   3171         int j = pProbe->aiColumn[pc.plan.nEq];
  3169   3172         pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
  3170   3173         if( pTerm==0 ) break;
  3171   3174         pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
  3172   3175         testcase( pTerm->pWC!=pWC );
  3173   3176         if( pTerm->eOperator & WO_IN ){
  3174   3177           Expr *pExpr = pTerm->pExpr;
................................................................................
  3179   3182             bInEst = 1;
  3180   3183           }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
  3181   3184             /* "x IN (value, value, ...)" */
  3182   3185             nInMul *= pExpr->x.pList->nExpr;
  3183   3186           }
  3184   3187         }else if( pTerm->eOperator & WO_ISNULL ){
  3185   3188           pc.plan.wsFlags |= WHERE_COLUMN_NULL;
  3186         -        if( pc.plan.nEq==nOrdered ) nOrdered++;
  3187         -      }else if( bSort && pc.plan.nEq==nOrdered
  3188         -             && isOrderedTerm(p,pTerm,&bRev) ){
  3189         -        nOrdered++;
  3190   3189         }
  3191   3190   #ifdef SQLITE_ENABLE_STAT3
  3192   3191         if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
  3193   3192   #endif
  3194   3193         pc.used |= pTerm->prereqRight;
  3195   3194       }
  3196   3195    
................................................................................
  3237   3236       }
  3238   3237   
  3239   3238       /* If there is an ORDER BY clause and the index being considered will
  3240   3239       ** naturally scan rows in the required order, set the appropriate flags
  3241   3240       ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
  3242   3241       ** the index will scan rows in a different order, set the bSort
  3243   3242       ** variable.  */
  3244         -    assert( bRev>=0 && bRev<=2 );
  3245         -    if( bSort ){
  3246         -      testcase( bRev==0 );
  3247         -      testcase( bRev==1 );
  3248         -      testcase( bRev==2 );
  3249         -      pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, nOrdered,
  3250         -                                 pc.plan.wsFlags, bRev&1, &bRev);
         3243  +    if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
         3244  +      int bRev = 2;
         3245  +      WHERETRACE(("      --> before isSortingIndex: nPriorSat=%d\n",nPriorSat));
         3246  +      pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
         3247  +      WHERETRACE(("      --> after  isSortingIndex: bRev=%d nOBSat=%d\n",
         3248  +                  bRev, pc.plan.nOBSat));
  3251   3249         if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_UNIQUE)!=0 ){
  3252   3250           pc.plan.wsFlags |= WHERE_ORDERED;
  3253   3251         }
  3254   3252         if( nOrderBy==pc.plan.nOBSat ){
  3255   3253           bSort = 0;
  3256   3254           pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
  3257   3255         }
................................................................................
  3361   3359         ** the cost function to err on the side of choosing an index over
  3362   3360         ** choosing a full scan.  This 4x full-scan penalty is an arguable
  3363   3361         ** decision and one which we expect to revisit in the future.  But
  3364   3362         ** it seems to be working well enough at the moment.
  3365   3363         */
  3366   3364         pc.rCost = aiRowEst[0]*4;
  3367   3365         pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
  3368         -      if( pIdx ) pc.plan.wsFlags &= ~WHERE_ORDERED;
         3366  +      if( pIdx ){
         3367  +        pc.plan.wsFlags &= ~WHERE_ORDERED;
         3368  +        pc.plan.nOBSat = nPriorSat;
         3369  +      }
  3369   3370       }else{
  3370   3371         log10N = estLog(aiRowEst[0]);
  3371   3372         pc.rCost = pc.plan.nRow;
  3372   3373         if( pIdx ){
  3373   3374           if( bLookup ){
  3374   3375             /* For an index lookup followed by a table lookup:
  3375   3376             **    nInMul index searches to find the start of each index range
................................................................................
  3466   3467           }
  3467   3468         }
  3468   3469         if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
  3469   3470       }
  3470   3471   
  3471   3472   
  3472   3473       WHERETRACE((
  3473         -      "%s(%s):\n"
  3474         -      "    nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
  3475         -      "    notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
  3476         -      "    used=0x%llx nOrdered=%d nOBSat=%d\n",
  3477         -      pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"), 
         3474  +      "      nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
         3475  +      "      notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
         3476  +      "      used=0x%llx nOBSat=%d\n",
  3478   3477         pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
  3479         -      p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used, nOrdered,
         3478  +      p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
  3480   3479         pc.plan.nOBSat
  3481   3480       ));
  3482   3481   
  3483   3482       /* If this index is the best we have seen so far, then record this
  3484   3483       ** index and its cost in the p->cost structure.
  3485   3484       */
  3486   3485       if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
................................................................................
  3510   3509     assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
  3511   3510     assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
  3512   3511     assert( pSrc->pIndex==0 
  3513   3512          || p->cost.plan.u.pIdx==0 
  3514   3513          || p->cost.plan.u.pIdx==pSrc->pIndex 
  3515   3514     );
  3516   3515   
  3517         -  WHERETRACE(("best index is: %s\n",
         3516  +  WHERETRACE(("   best index is: %s\n",
  3518   3517            p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk"));
  3519   3518     
  3520   3519     bestOrClauseIndex(p);
  3521   3520     bestAutomaticIndex(p);
  3522   3521     p->cost.plan.wsFlags |= eqTermMask;
  3523   3522   }
  3524   3523   
................................................................................
  4602   4601   
  4603   4602             /* Finish the loop through table entries that match term pOrTerm. */
  4604   4603             sqlite3WhereEnd(pSubWInfo);
  4605   4604           }
  4606   4605         }
  4607   4606       }
  4608   4607       pLevel->u.pCovidx = pCov;
  4609         -    pLevel->iIdxCur = iCovCur;
         4608  +    if( pCov ) pLevel->iIdxCur = iCovCur;
  4610   4609       if( pAndExpr ){
  4611   4610         pAndExpr->pLeft = 0;
  4612   4611         sqlite3ExprDelete(pParse->db, pAndExpr);
  4613   4612       }
  4614   4613       sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
  4615   4614       sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
  4616   4615       sqlite3VdbeResolveLabel(v, iLoopBody);
................................................................................
  5060   5059           if( (m & sWBI.notValid)==0 ){
  5061   5060             if( j==iFrom ) iFrom++;
  5062   5061             continue;
  5063   5062           }
  5064   5063           sWBI.notReady = (isOptimal ? m : sWBI.notValid);
  5065   5064           if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
  5066   5065     
  5067         -        WHERETRACE(("=== trying table %d (%s) with isOptimal=%d ===\n",
         5066  +        WHERETRACE(("   === trying table %d (%s) with isOptimal=%d ===\n",
  5068   5067                       j, sWBI.pSrc->pTab->zName, isOptimal));
  5069   5068           assert( sWBI.pSrc->pTab );
  5070   5069   #ifndef SQLITE_OMIT_VIRTUALTABLE
  5071   5070           if( IsVirtual(sWBI.pSrc->pTab) ){
  5072   5071             sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
  5073   5072             bestVirtualIndex(&sWBI);
  5074   5073           }else 
................................................................................
  5113   5112               && (bestJ<0 || (notIndexed&m)!=0                     /* (2) */
  5114   5113                   || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
  5115   5114                   || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
  5116   5115               && (nUnconstrained==0 || sWBI.pSrc->pIndex==0        /* (3) */
  5117   5116                   || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
  5118   5117               && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan))   /* (4) */
  5119   5118           ){
  5120         -          WHERETRACE(("=== table %d (%s) is best so far\n"
  5121         -                      "    cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
         5119  +          WHERETRACE(("   === table %d (%s) is best so far\n"
         5120  +                      "       cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
  5122   5121                         j, sWBI.pSrc->pTab->zName,
  5123   5122                         sWBI.cost.rCost, sWBI.cost.plan.nRow,
  5124   5123                         sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
  5125   5124             bestPlan = sWBI.cost;
  5126   5125             bestJ = j;
  5127   5126           }
  5128   5127           if( doNotReorder ) break;

Added test/backup4.test.

            1  +# 2012 October 13
            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  +# The tests in this file verify that if an empty database (zero bytes in 
           13  +# size) is used as the source of a backup operation, the final destination
           14  +# database is one page in size.
           15  +#
           16  +# The destination must consist of at least one page as truncating a 
           17  +# database file to zero bytes is equivalent to resetting the database
           18  +# schema cookie and change counter. Doing that could cause other clients
           19  +# to become confused and continue using out-of-date cache data.
           20  +#
           21  +
           22  +set testdir [file dirname $argv0]
           23  +source $testdir/tester.tcl
           24  +set testprefix backup4
           25  +
           26  +#-------------------------------------------------------------------------
           27  +# At one point this test was failing because [db] was using an out of
           28  +# date schema in test case 1.2.
           29  +#
           30  +do_execsql_test 1.0 {
           31  +  CREATE TABLE t1(x, y, UNIQUE(x, y));
           32  +  INSERT INTO t1 VALUES('one', 'two');
           33  +  SELECT * FROM t1 WHERE x='one';
           34  +  PRAGMA integrity_check;
           35  +} {one two ok}
           36  +
           37  +do_test 1.1 {
           38  +  sqlite3 db1 :memory:
           39  +  db1 backup test.db
           40  +  sqlite3 db1 test.db
           41  +  db1 eval {
           42  +    CREATE TABLE t1(x, y);
           43  +    INSERT INTO t1 VALUES('one', 'two');
           44  +  }
           45  +  db1 close
           46  +} {}
           47  +
           48  +do_execsql_test 1.2 {
           49  +  SELECT * FROM t1 WHERE x='one';
           50  +  PRAGMA integrity_check;
           51  +} {one two ok}
           52  +
           53  +db close
           54  +forcedelete test.db
           55  +forcedelete test.db2
           56  +sqlite3 db test.db
           57  +
           58  +#-------------------------------------------------------------------------
           59  +# Test that if the source is zero bytes, the destination database 
           60  +# consists of a single page only.
           61  +#
           62  +do_execsql_test 2.1 {
           63  +  CREATE TABLE t1(a, b);
           64  +  CREATE INDEX i1 ON t1(a, b);
           65  +}
           66  +
           67  +do_test 2.2 { file size test.db } 3072
           68  +
           69  +do_test 2.3 {
           70  +  sqlite3 db1 test.db2
           71  +  db1 backup test.db
           72  +  db1 close
           73  +  file size test.db
           74  +} {1024}
           75  +
           76  +do_test 2.4 { file size test.db2 } 0
           77  +
           78  +db close
           79  +forcedelete test.db
           80  +forcedelete test.db2
           81  +sqlite3 db test.db
           82  +
           83  +#-------------------------------------------------------------------------
           84  +# Test that if the destination has a page-size larger than the implicit
           85  +# page-size of the source, the final destination database still consists
           86  +# of a single page.
           87  +#
           88  +do_execsql_test 3.1 {
           89  +  PRAGMA page_size = 4096;
           90  +  CREATE TABLE t1(a, b);
           91  +  CREATE INDEX i1 ON t1(a, b);
           92  +}
           93  +
           94  +do_test 3.2 { file size test.db } 12288
           95  +
           96  +do_test 3.3 {
           97  +  sqlite3 db1 test.db2
           98  +  db1 backup test.db
           99  +  db1 close
          100  +  file size test.db
          101  +} {1024}
          102  +
          103  +do_test 3.4 { file size test.db2 } 0
          104  +
          105  +finish_test
          106  +

Changes to test/orderby1.test.

   110    110     }
   111    111   } {three-a three-c two-a two-b one-a one-c}  ;# verify same order after sorting
   112    112   do_test 1.4c {
   113    113     db eval {
   114    114       EXPLAIN QUERY PLAN
   115    115       SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
   116    116     }
   117         -} {/ORDER BY/}  ;# separate sorting pass due to mixed DESC/ASC
          117  +} {~/ORDER BY/}  ;# optimized out
   118    118   
   119    119   
   120    120   do_test 1.5a {
   121    121     db eval {
   122    122       SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
   123    123     }
   124    124   } {one-c one-a two-b two-a three-c three-a}
................................................................................
   128    128     }
   129    129   } {one-c one-a two-b two-a three-c three-a}  ;# verify same order after sorting
   130    130   do_test 1.5c {
   131    131     db eval {
   132    132       EXPLAIN QUERY PLAN
   133    133       SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
   134    134     }
   135         -} {/ORDER BY/}  ;# separate sorting pass due to mixed DESC/ASC
          135  +} {~/ORDER BY/}  ;# optimized out
   136    136   
   137    137   do_test 1.6a {
   138    138     db eval {
   139    139       SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
   140    140     }
   141    141   } {three-c three-a two-b two-a one-c one-a}
   142    142   do_test 1.6b {
................................................................................
   257    257     }
   258    258   } {three-a three-c two-a two-b one-a one-c}  ;# verify same order after sorting
   259    259   do_test 2.4c {
   260    260     db eval {
   261    261       EXPLAIN QUERY PLAN
   262    262       SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
   263    263     }
   264         -} {/ORDER BY/}  ;# separate sorting pass due to mixed DESC/ASC
          264  +} {~/ORDER BY/}  ;# optimized out
   265    265   
   266    266   
   267    267   do_test 2.5a {
   268    268     db eval {
   269    269       SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
   270    270     }
   271    271   } {one-c one-a two-b two-a three-c three-a}
................................................................................
   275    275     }
   276    276   } {one-c one-a two-b two-a three-c three-a}  ;# verify same order after sorting
   277    277   do_test 2.5c {
   278    278     db eval {
   279    279       EXPLAIN QUERY PLAN
   280    280       SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn DESC
   281    281     }
   282         -} {/ORDER BY/}  ;# separate sorting pass due to mixed ASC/DESC
          282  +} {~/ORDER BY/}  ;# optimized out
   283    283   
   284    284   do_test 2.6a {
   285    285     db eval {
   286    286       SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
   287    287     }
   288    288   } {three-c three-a two-b two-a one-c one-a}
   289    289   do_test 2.6b {
................................................................................
   392    392     }
   393    393   } {one-a one-c two-a two-b three-a three-c}  ;# verify same order after sorting
   394    394   do_test 3.4c {
   395    395     db eval {
   396    396       EXPLAIN QUERY PLAN
   397    397       SELECT name FROM album JOIN track USING (aid) ORDER BY title, tn
   398    398     }
   399         -} {/ORDER BY/}  ;# separate sorting pass due to mismatched DESC/ASC
          399  +} {~/ORDER BY/}  ;# optimized out
   400    400   
   401    401   
   402    402   do_test 3.5a {
   403    403     db eval {
   404    404       SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
   405    405     }
   406    406   } {three-c three-a two-b two-a one-c one-a}
................................................................................
   410    410     }
   411    411   } {three-c three-a two-b two-a one-c one-a}  ;# verify same order after sorting
   412    412   do_test 3.5c {
   413    413     db eval {
   414    414       EXPLAIN QUERY PLAN
   415    415       SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn DESC
   416    416     }
   417         -} {/ORDER BY/}  ;# separate sorting pass due to mismatched ASC/DESC
          417  +} {~/ORDER BY/}  ;# optimzed out
   418    418   
   419    419   
   420    420   do_test 3.6a {
   421    421     db eval {
   422    422       SELECT name FROM album JOIN track USING (aid) ORDER BY title DESC, tn
   423    423     }
   424    424   } {three-a three-c two-a two-b one-a one-c}

Changes to test/pager1.test.

  1361   1361       CREATE TABLE t2(a, b);
  1362   1362     } db2
  1363   1363     sqlite3_backup B db2 main db main
  1364   1364     list [B step 10000] [B finish]
  1365   1365   } {SQLITE_DONE SQLITE_OK}
  1366   1366   do_test pager1-9.4.2 {
  1367   1367     list [file size test.db2] [file size test.db]
  1368         -} {0 0}
         1368  +} {1024 0}
  1369   1369   db2 close
  1370   1370   
  1371   1371   #-------------------------------------------------------------------------
  1372   1372   # Test that regardless of the value returned by xSectorSize(), the
  1373   1373   # minimum effective sector-size is 512 and the maximum 65536 bytes.
  1374   1374   #
  1375   1375   testvfs tv -default 1

Added test/wal9.test.

            1  +# 2012 October 15
            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  +# This test case tests that a problem causing a failing assert() has
           13  +# been fixed. The problem occurred if a writer process with a subset
           14  +# of the *shm file mapped rolled back a transaction begun after the
           15  +# entire WAL file was checkpointed into the db file (i.e. a transaction
           16  +# that would have restarted the WAL file from the beginning).
           17  +#
           18  +
           19  +set testdir [file dirname $argv0]
           20  +source $testdir/tester.tcl
           21  +set testprefix wal9
           22  +
           23  +sqlite3 db2 test.db
           24  +
           25  +do_execsql_test 1.0 {
           26  +  PRAGMA page_size = 1024;
           27  +  PRAGMA journal_mode = WAL;
           28  +  PRAGMA wal_autocheckpoint = 0;
           29  +  CREATE TABLE t(x);
           30  +} {wal 0}
           31  +
           32  +do_test 1.1 { 
           33  +  execsql "SELECT * FROM t" db2
           34  +} {}
           35  +
           36  +do_execsql_test 1.2 {
           37  +  BEGIN;
           38  +    INSERT INTO t VALUES(randomblob(100));
           39  +    INSERT INTO t SELECT randomblob(100) FROM t;
           40  +    INSERT INTO t SELECT randomblob(100) FROM t;
           41  +    INSERT INTO t SELECT randomblob(100) FROM t;
           42  +    INSERT INTO t SELECT randomblob(100) FROM t;
           43  +    INSERT INTO t SELECT randomblob(100) FROM t;
           44  +    INSERT INTO t SELECT randomblob(100) FROM t;
           45  +    INSERT INTO t SELECT randomblob(100) FROM t;
           46  +
           47  +    INSERT INTO t SELECT randomblob(100) FROM t;
           48  +    INSERT INTO t SELECT randomblob(100) FROM t;
           49  +    INSERT INTO t SELECT randomblob(100) FROM t;
           50  +    INSERT INTO t SELECT randomblob(100) FROM t;
           51  +    INSERT INTO t SELECT randomblob(100) FROM t;
           52  +    INSERT INTO t SELECT randomblob(100) FROM t;
           53  +    INSERT INTO t SELECT randomblob(100) FROM t;
           54  +    INSERT INTO t SELECT randomblob(100) FROM t;
           55  +
           56  +    INSERT INTO t SELECT randomblob(100) FROM t;
           57  +    INSERT INTO t SELECT randomblob(100) FROM t;
           58  +  COMMIT;
           59  +} {}
           60  +
           61  +# Check file sizes are as expected. The real requirement here is that 
           62  +# the *shm file is now more than one chunk (>32KiB).
           63  +do_test 1.3 { file size test.db     } {1024}
           64  +do_test 1.4 { file size test.db-wal } {15421352}
           65  +do_test 1.5 { file size test.db-shm } {131072}
           66  +
           67  +do_execsql_test 1.6 { PRAGMA wal_checkpoint } {0 14715 14715}
           68  +
           69  +# At this point connection [db2] has mapped the first 32KB of the *shm file
           70  +# only. Because the entire WAL file has been checkpointed, it is not 
           71  +# necessary to map any more of the *-shm file to read or write the database
           72  +# (since all data will be read directly from the db file). 
           73  +#
           74  +# However, at one point if a transaction that had not yet written to the 
           75  +# WAL file was rolled back an assert() attempting to verify that the entire 
           76  +# *-shm file was mapped would fail. If NDEBUG was defined (and the assert() 
           77  +# disabled) this bug caused SQLite to ignore the return code of a mmap() 
           78  +# call.
           79  +#
           80  +do_test 1.7 {
           81  +  execsql { 
           82  +    BEGIN;
           83  +      INSERT INTO t VALUES('hello');
           84  +    ROLLBACK;
           85  +  } db2
           86  +} {}
           87  +db2 close
           88  +
           89  +finish_test
           90  +

Changes to test/whereD.test.

   156    156   
   157    157   do_searchcount_test 3.5.1 {
   158    158     SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR rowid=4
   159    159   } {1 one 2 two search 2}
   160    160   do_searchcount_test 3.5.2 {
   161    161     SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR rowid=4
   162    162   } {1 i 2 ii search 2}
          163  +
          164  +# Ticket [d02e1406a58ea02d] (2012-10-04)
          165  +# LEFT JOIN with an OR in the ON clause causes segfault 
          166  +#
          167  +do_test 4.1 {
          168  +  db eval {
          169  +    CREATE TABLE t41(a,b,c);
          170  +    INSERT INTO t41 VALUES(1,2,3), (4,5,6);
          171  +    CREATE TABLE t42(d,e,f);
          172  +    INSERT INTO t42 VALUES(3,6,9), (4,8,12);
          173  +    SELECT * FROM t41 AS x LEFT JOIN t42 AS y ON (y.d=x.c) OR (y.e=x.b);
          174  +  }
          175  +} {1 2 3 3 6 9 4 5 6 {} {} {}}
          176  +do_test 4.2 {
          177  +  db eval {
          178  +    CREATE INDEX t42d ON t42(d);
          179  +    CREATE INDEX t42e ON t42(e);
          180  +    SELECT * FROM t41 AS x LEFT JOIN t42 AS y ON (y.d=x.c) OR (y.e=x.b);
          181  +  }
          182  +} {1 2 3 3 6 9 4 5 6 {} {} {}}
          183  +do_test 4.3 {
          184  +  db eval {
          185  +    SELECT * FROM t41 AS x LEFT JOIN t42 AS y ON (y.d=x.c) OR (y.d=x.b);
          186  +  }
          187  +} {1 2 3 3 6 9 4 5 6 {} {} {}}
   163    188   
   164    189   finish_test

Changes to tool/build-all-msvc.bat.

     6      6   :: Multi-Platform Build Tool for MSVC
     7      7   ::
     8      8   
     9      9   SETLOCAL
    10     10   
    11     11   REM SET __ECHO=ECHO
    12     12   REM SET __ECHO2=ECHO
           13  +REM SET __ECHO3=ECHO
    13     14   IF NOT DEFINED _AECHO (SET _AECHO=REM)
    14     15   IF NOT DEFINED _CECHO (SET _CECHO=REM)
    15     16   IF NOT DEFINED _VECHO (SET _VECHO=REM)
    16     17   
    17     18   %_AECHO% Running %0 %*
    18     19   
    19     20   REM SET DFLAGS=/L
................................................................................
   177    178       CALL :fn_UnsetVariable WindowsSdkDir_old
   178    179   
   179    180       REM
   180    181       REM NOTE: Reset the PATH here to the absolute bare minimum required.
   181    182       REM
   182    183       SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot%
   183    184   
   184         -    REM
   185         -    REM NOTE: Launch a nested command shell to perform the following steps:
   186         -    REM
   187         -    REM       1. Setup the MSVC environment for this platform using the
   188         -    REM          official batch file.
   189         -    REM
   190         -    REM       2. Make sure that no stale build output files are present.
   191         -    REM
   192         -    REM       3. Build the "sqlite3.dll" and "sqlite3.lib" binaries for this
   193         -    REM          platform.
   194         -    REM
   195         -    REM       4. Copy the "sqlite3.dll" and "sqlite3.lib" binaries for this
   196         -    REM          platform to the platform-specific directory beneath the
   197         -    REM          binary directory.
   198         -    REM
   199         -    "%ComSpec%" /C (
          185  +    FOR %%B IN (Debug Retail) DO (
          186  +      REM
          187  +      REM NOTE: When preparing the debug build, set the DEBUG and MEMDEBUG
          188  +      REM       environment variables to be picked up by the MSVC makefile
          189  +      REM       itself.
   200    190         REM
   201         -      REM NOTE: Attempt to setup the MSVC environment for this platform.
   202         -      REM
   203         -      %__ECHO% CALL "%VCINSTALLDIR%\vcvarsall.bat" %%P
   204         -
   205         -      IF ERRORLEVEL 1 (
   206         -        ECHO Failed to call "%VCINSTALLDIR%\vcvarsall.bat" for platform %%P.
   207         -        GOTO errors
          191  +      IF /I "%%B" == "Debug" (
          192  +        SET DEBUG=2
          193  +        SET MEMDEBUG=1
          194  +      ) ELSE (
          195  +        CALL :fn_UnsetVariable DEBUG
          196  +        CALL :fn_UnsetVariable MEMDEBUG
   208    197         )
   209    198   
   210    199         REM
   211         -      REM NOTE: If this batch file is not running in "what-if" mode, check to
   212         -      REM       be sure we were actually able to setup the MSVC environment as
   213         -      REM       current versions of their official batch file do not set the
   214         -      REM       exit code upon failure.
          200  +      REM NOTE: Launch a nested command shell to perform the following steps:
          201  +      REM
          202  +      REM       1. Setup the MSVC environment for this platform using the
          203  +      REM          official batch file.
          204  +      REM
          205  +      REM       2. Make sure that no stale build output files are present.
          206  +      REM
          207  +      REM       3. Build the "sqlite3.dll" and "sqlite3.lib" binaries for this
          208  +      REM          platform.
          209  +      REM
          210  +      REM       4. Copy the "sqlite3.dll" and "sqlite3.lib" binaries for this
          211  +      REM          platform to the platform-specific directory beneath the
          212  +      REM          binary directory.
   215    213         REM
   216         -      IF NOT DEFINED __ECHO (
   217         -        IF NOT DEFINED WindowsSdkDir (
   218         -          ECHO Cannot build, Windows SDK not found for platform %%P.
          214  +      "%ComSpec%" /C (
          215  +        REM
          216  +        REM NOTE: Attempt to setup the MSVC environment for this platform.
          217  +        REM
          218  +        %__ECHO3% CALL "%VCINSTALLDIR%\vcvarsall.bat" %%P
          219  +
          220  +        IF ERRORLEVEL 1 (
          221  +          ECHO Failed to call "%VCINSTALLDIR%\vcvarsall.bat" for platform %%P.
          222  +          GOTO errors
          223  +        )
          224  +
          225  +        REM
          226  +        REM NOTE: If this batch file is not running in "what-if" mode, check to
          227  +        REM       be sure we were actually able to setup the MSVC environment
          228  +        REM       as current versions of their official batch file do not set
          229  +        REM       the exit code upon failure.
          230  +        REM
          231  +        IF NOT DEFINED __ECHO (
          232  +          IF NOT DEFINED WindowsSdkDir (
          233  +            ECHO Cannot build, Windows SDK not found for platform %%P.
          234  +            GOTO errors
          235  +          )
          236  +        )
          237  +
          238  +        REM
          239  +        REM NOTE: When using MSVC 2012, the native SDK path cannot simply use
          240  +        REM       the "lib" sub-directory beneath the location specified in the
          241  +        REM       WindowsSdkDir environment variable because that location does
          242  +        REM       not actually contain the necessary library files for x86.
          243  +        REM       This must be done for each iteration because it relies upon
          244  +        REM       the WindowsSdkDir environment variable being set by the batch
          245  +        REM       file used to setup the MSVC environment.
          246  +        REM
          247  +        IF DEFINED SET_NSDKLIBPATH (
          248  +          CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH
          249  +          CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
          250  +        )
          251  +
          252  +        REM
          253  +        REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC
          254  +        REM       makefile to clean any stale build output from previous
          255  +        REM       iterations of this loop and/or previous runs of this batch
          256  +        REM       file, etc.
          257  +        REM
          258  +        IF NOT DEFINED NOCLEAN (
          259  +          %__ECHO% nmake -f Makefile.msc clean
          260  +
          261  +          IF ERRORLEVEL 1 (
          262  +            ECHO Failed to clean for platform %%P.
          263  +            GOTO errors
          264  +          )
          265  +        ) ELSE (
          266  +          REM
          267  +          REM NOTE: Even when the cleaning step has been disabled, we still
          268  +          REM       need to remove the build output for the files we are
          269  +          REM       specifically wanting to build for each platform.
          270  +          REM
          271  +          %__ECHO% DEL /Q sqlite3.dll sqlite3.lib sqlite3.pdb
          272  +        )
          273  +
          274  +        REM
          275  +        REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.dll"
          276  +        REM       binary.  The x86 compiler will be used to compile the native
          277  +        REM       command line tools needed during the build process itself.
          278  +        REM       Also, disable looking for and/or linking to the native Tcl
          279  +        REM       runtime library.
          280  +        REM
          281  +        %__ECHO% nmake -f Makefile.msc sqlite3.dll XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
          282  +
          283  +        IF ERRORLEVEL 1 (
          284  +          ECHO Failed to build %%B "sqlite3.dll" for platform %%P.
   219    285             GOTO errors
   220    286           )
   221         -      )
   222    287   
   223         -      REM
   224         -      REM NOTE: When using MSVC 2012, the native SDK path cannot simply use
   225         -      REM       the "lib" sub-directory beneath the location specified in the
   226         -      REM       WindowsSdkDir environment variable because that location does
   227         -      REM       not actually contain the necessary library files for x86.
   228         -      REM       This must be done for each iteration because it relies upon
   229         -      REM       the WindowsSdkDir environment variable being set by the batch
   230         -      REM       file used to setup the MSVC environment.
   231         -      REM
   232         -      IF DEFINED SET_NSDKLIBPATH (
   233         -        CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH
   234         -        CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
   235         -      )
   236         -
   237         -      REM
   238         -      REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC
   239         -      REM       makefile to clean any stale build output from previous
   240         -      REM       iterations of this loop and/or previous runs of this batch
   241         -      REM       file, etc.
   242         -      REM
   243         -      IF NOT DEFINED NOCLEAN (
   244         -        %__ECHO% nmake -f Makefile.msc clean
          288  +        REM
          289  +        REM NOTE: Copy the "sqlite3.dll" file to the appropriate directory for
          290  +        REM       the build and platform beneath the binary directory.
          291  +        REM
          292  +        %__ECHO% XCOPY sqlite3.dll "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
   245    293   
   246    294           IF ERRORLEVEL 1 (
   247         -          ECHO Failed to clean for platform %%P.
          295  +          ECHO Failed to copy "sqlite3.dll" to "%BINARYDIRECTORY%\%%B\%%D\".
   248    296             GOTO errors
   249    297           )
   250         -      ) ELSE (
          298  +
   251    299           REM
   252         -        REM NOTE: Even when the cleaning step has been disabled, we still need
   253         -        REM       to remove the build output for the files we are specifically
   254         -        REM       wanting to build for each platform.
          300  +        REM NOTE: Copy the "sqlite3.lib" file to the appropriate directory for
          301  +        REM       the build and platform beneath the binary directory.
   255    302           REM
   256         -        %__ECHO% DEL /Q sqlite3.dll sqlite3.lib sqlite3.pdb
   257         -      )
   258         -
   259         -      REM
   260         -      REM NOTE: Invoke NMAKE with the MSVC makefile to build the "sqlite3.dll"
   261         -      REM       binary.  The x86 compiler will be used to compile the native
   262         -      REM       command line tools needed during the build process itself.
   263         -      REM       Also, disable looking for and/or linking to the native Tcl
   264         -      REM       runtime library.
   265         -      REM
   266         -      %__ECHO% nmake -f Makefile.msc sqlite3.dll "NCC=""%VCINSTALLDIR%\bin\cl.exe""" USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
   267         -
   268         -      IF ERRORLEVEL 1 (
   269         -        ECHO Failed to build "sqlite3.dll" for platform %%P.
   270         -        GOTO errors
   271         -      )
   272         -
   273         -      REM
   274         -      REM NOTE: Copy the "sqlite3.dll" file to the platform-specific directory
   275         -      REM       beneath the binary directory.
   276         -      REM
   277         -      %__ECHO% XCOPY sqlite3.dll "%BINARYDIRECTORY%\%%D\" %FFLAGS% %DFLAGS%
   278         -
   279         -      IF ERRORLEVEL 1 (
   280         -        ECHO Failed to copy "sqlite3.dll" to "%BINARYDIRECTORY%\%%D\".
   281         -        GOTO errors
   282         -      )
   283         -
   284         -      REM
   285         -      REM NOTE: Copy the "sqlite3.lib" file to the platform-specific directory
   286         -      REM       beneath the binary directory.
   287         -      REM
   288         -      %__ECHO% XCOPY sqlite3.lib "%BINARYDIRECTORY%\%%D\" %FFLAGS% %DFLAGS%
   289         -
   290         -      IF ERRORLEVEL 1 (
   291         -        ECHO Failed to copy "sqlite3.lib" to "%BINARYDIRECTORY%\%%D\".
   292         -        GOTO errors
   293         -      )
   294         -
   295         -      REM
   296         -      REM NOTE: Copy the "sqlite3.pdb" file to the platform-specific directory
   297         -      REM       beneath the binary directory unless we are prevented from doing
   298         -      REM       so.
   299         -      REM
   300         -      IF NOT DEFINED NOSYMBOLS (
   301         -        %__ECHO% XCOPY sqlite3.pdb "%BINARYDIRECTORY%\%%D\" %FFLAGS% %DFLAGS%
          303  +        %__ECHO% XCOPY sqlite3.lib "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
   302    304   
   303    305           IF ERRORLEVEL 1 (
   304         -          ECHO Failed to copy "sqlite3.pdb" to "%BINARYDIRECTORY%\%%D\".
          306  +          ECHO Failed to copy "sqlite3.lib" to "%BINARYDIRECTORY%\%%B\%%D\".
   305    307             GOTO errors
   306    308           )
          309  +
          310  +        REM
          311  +        REM NOTE: Copy the "sqlite3.pdb" file to the appropriate directory for
          312  +        REM       the build and platform beneath the binary directory unless we
          313  +        REM       are prevented from doing so.
          314  +        REM
          315  +        IF NOT DEFINED NOSYMBOLS (
          316  +          %__ECHO% XCOPY sqlite3.pdb "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
          317  +
          318  +          IF ERRORLEVEL 1 (
          319  +            ECHO Failed to copy "sqlite3.pdb" to "%BINARYDIRECTORY%\%%B\%%D\".
          320  +            GOTO errors
          321  +          )
          322  +        )
   307    323         )
   308    324       )
   309    325     )
   310    326   
   311    327     REM
   312    328     REM NOTE: Handle any errors generated during the nested command shell.
   313    329     REM

Changes to tool/mkvsix.tcl.

    86     86     # NOTE: Performs all Tcl command, variable, and backslash substitutions in
    87     87     #       the specified file and then re-writes the contents of that same file
    88     88     #       with the substituted data.
    89     89     #
    90     90     return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
    91     91   }
    92     92   
    93         -proc replacePlatform { fileName platformName } {
           93  +proc replaceBuildAndPlatform { fileName buildName platformName } {
    94     94     #
    95     95     # NOTE: Returns the specified file name containing the platform name instead
    96     96     #       of platform placeholder tokens.
    97     97     #
    98         -  return [string map [list <platform> $platformName] $fileName]
           98  +  return [string map [list <build> $buildName <platform> $platformName] \
           99  +      $fileName]
    99    100   }
   100    101   
   101    102   set script [file normalize [info script]]
   102    103   
   103    104   if {[string length $script] == 0} then {
   104    105     fail "script file currently being evaluated is unknown" true
   105    106   }
................................................................................
   245    246   
   246    247   #
   247    248   # NOTE: Setup the master file list data, including the necessary flags.
   248    249   #
   249    250   if {![info exists fileNames(source)]} then {
   250    251     set fileNames(source) [list "" "" "" \
   251    252         [file join $sourceDirectory sqlite3.h] \
   252         -      [file join $binaryDirectory <platform> sqlite3.lib] \
   253         -      [file join $binaryDirectory <platform> sqlite3.dll]]
          253  +      [file join $binaryDirectory <build> <platform> sqlite3.lib] \
          254  +      [file join $binaryDirectory <build> <platform> sqlite3.dll]]
   254    255   
   255    256     if {![info exists no(symbols)]} then {
   256    257       lappend fileNames(source) \
   257         -        [file join $binaryDirectory <platform> sqlite3.pdb]
          258  +        [file join $binaryDirectory <build> <platform> sqlite3.pdb]
   258    259     }
   259    260   }
   260    261   
   261    262   if {![info exists fileNames(destination)]} then {
   262    263     set fileNames(destination) [list \
   263    264         [file join $stagingDirectory extension.vsixmanifest] \
   264    265         [file join $stagingDirectory SDKManifest.xml] \
   265         -      [file join $stagingDirectory DesignTime CommonConfiguration \
   266         -          <platform> SQLite.WinRT.props] \
   267         -      [file join $stagingDirectory DesignTime CommonConfiguration \
   268         -          <platform> sqlite3.h] \
   269         -      [file join $stagingDirectory DesignTime CommonConfiguration \
   270         -          <platform> sqlite3.lib] \
   271         -      [file join $stagingDirectory Redist CommonConfiguration \
   272         -          <platform> sqlite3.dll]]
          266  +      [file join $stagingDirectory DesignTime <build> <platform> \
          267  +          SQLite.WinRT.props] \
          268  +      [file join $stagingDirectory DesignTime <build> <platform> sqlite3.h] \
          269  +      [file join $stagingDirectory DesignTime <build> <platform> sqlite3.lib] \
          270  +      [file join $stagingDirectory Redist <build> <platform> sqlite3.dll]]
   273    271   
   274    272     if {![info exists no(symbols)]} then {
   275    273       lappend fileNames(destination) \
   276         -        [file join $stagingDirectory Redist Debug \
   277         -            <platform> sqlite3.pdb]
          274  +        [file join $stagingDirectory Redist <build> <platform> sqlite3.pdb]
          275  +  }
          276  +}
          277  +
          278  +if {![info exists fileNames(buildNeutral)]} then {
          279  +  set fileNames(buildNeutral) [list 1 1 1 1 0 0]
          280  +
          281  +  if {![info exists no(symbols)]} then {
          282  +    lappend fileNames(buildNeutral) 0
   278    283     }
   279    284   }
   280    285   
   281         -if {![info exists fileNames(neutral)]} then {
   282         -  set fileNames(neutral) [list 1 1 1 1 0 0]
          286  +if {![info exists fileNames(platformNeutral)]} then {
          287  +  set fileNames(platformNeutral) [list 1 1 1 1 0 0]
   283    288   
   284    289     if {![info exists no(symbols)]} then {
   285         -    lappend fileNames(neutral) 0
          290  +    lappend fileNames(platformNeutral) 0
   286    291     }
   287    292   }
   288    293   
   289    294   if {![info exists fileNames(subst)]} then {
   290    295     set fileNames(subst) [list 1 1 1 0 0 0]
   291    296   
   292    297     if {![info exists no(symbols)]} then {
   293    298       lappend fileNames(subst) 0
   294    299     }
   295    300   }
          301  +
          302  +if {![info exists fileNames(noDebug)]} then {
          303  +  set fileNames(noDebug) [list 0 0 0 0 0 0]
          304  +
          305  +  if {![info exists no(symbols)]} then {
          306  +    lappend fileNames(noDebug) 0
          307  +  }
          308  +}
          309  +
          310  +if {![info exists fileNames(noRetail)]} then {
          311  +  set fileNames(noRetail) [list 0 0 0 0 0 0]
          312  +
          313  +  if {![info exists no(symbols)]} then {
          314  +    lappend fileNames(noRetail) 1
          315  +  }
          316  +}
          317  +
          318  +###############################################################################
          319  +
          320  +#
          321  +# NOTE: Setup the list of builds supported by this script.
          322  +#
          323  +if {![info exists buildNames]} then {
          324  +  set buildNames [list Debug Retail]
          325  +}
   296    326   
   297    327   ###############################################################################
   298    328   
   299    329   #
   300    330   # NOTE: Setup the list of platforms supported by this script.
   301    331   #
   302    332   if {![info exists platformNames]} then {
................................................................................
   320    350   # NOTE: Extract the template package to the staging directory.
   321    351   #
   322    352   eval $extractCommand
   323    353   
   324    354   ###############################################################################
   325    355   
   326    356   #
   327         -# NOTE: Process each file in the master file list.  There are actually four
   328         -#       parallel lists that contain the source file names, destination file
   329         -#       names, the platform-neutral flags, and the use-subst flags.  When the
          357  +# NOTE: Process each file in the master file list.  There are actually seven
          358  +#       parallel lists that contain the source file names, the destination file
          359  +#       names, the build-neutral flags, the platform-neutral flags, the
          360  +#       use-subst flags, the no-debug flags, and the no-retail flags.  If the
   330    361   #       platform-neutral flag is non-zero, the file is not platform-specific.
   331         -#       When the use-subst flag is non-zero, the file is considered to be a
   332         -#       text file that may contain Tcl variable and/or command replacements,
   333         -#       to be dynamically replaced during processing.  If the source file name
   334         -#       is an empty string, then the destination file name will be assumed to
   335         -#       already exist in the staging directory and will not be copied; however,
   336         -#       dynamic replacements may still be performed on the destination file
   337         -#       prior to the package being re-zipped.
          362  +#       If the build-neutral flag is non-zero, the file is not build-specific.
          363  +#       If the use-subst flag is non-zero, the file is considered to be a text
          364  +#       file that may contain Tcl variable and/or command replacements, to be
          365  +#       dynamically replaced during processing.  If the no-debug flag is
          366  +#       non-zero, the file will be skipped when processing for the debug build.
          367  +#       If the no-retail flag is non-zero, the file will be skipped when
          368  +#       processing for the retail build.  If the source file name is an empty
          369  +#       string, then the destination file name will be assumed to already exist
          370  +#       in the staging directory and will not be copied; however, dynamic
          371  +#       replacements may still be performed on the destination file prior to
          372  +#       the package being re-zipped.
   338    373   #
   339         -foreach sourceFileName $fileNames(source) \
   340         -    destinationFileName $fileNames(destination) \
   341         -    isNeutral $fileNames(neutral) useSubst $fileNames(subst) {
          374  +foreach sourceFileName      $fileNames(source) \
          375  +        destinationFileName $fileNames(destination) \
          376  +        buildNeutral        $fileNames(buildNeutral) \
          377  +        platformNeutral     $fileNames(platformNeutral) \
          378  +        useSubst            $fileNames(subst) \
          379  +        noDebug             $fileNames(noDebug) \
          380  +        noRetail            $fileNames(noRetail) {
   342    381     #
   343         -  # NOTE: If the current file is platform-neutral, then only one platform will
   344         -  #       be processed for it, namely "neutral"; otherwise, each supported
   345         -  #       platform will be processed for it individually.
          382  +  # NOTE: If the current file is build-neutral, then only one build will
          383  +  #       be processed for it, namely "CommonConfiguration"; otherwise, each
          384  +  #       supported build will be processed for it individually.
   346    385     #
   347         -  foreach platformName [expr {$isNeutral ? [list neutral] : $platformNames}] {
   348         -    #
   349         -    # NOTE: Use the actual platform name in the destination file name.
          386  +  foreach buildName \
          387  +      [expr {$buildNeutral ? [list CommonConfiguration] : $buildNames}] {
   350    388       #
   351         -    set newDestinationFileName [replacePlatform $destinationFileName \
   352         -        $platformName]
   353         -
          389  +    # NOTE: Should the current file be skipped for this build?
   354    390       #
   355         -    # NOTE: Does the source file need to be copied to the destination file?
   356         -    #
   357         -    if {[string length $sourceFileName] > 0} then {
   358         -      #
   359         -      # NOTE: First, make sure the destination directory exists.
   360         -      #
   361         -      file mkdir [file dirname $newDestinationFileName]
   362         -
   363         -      #
   364         -      # NOTE: Then, copy the source file to the destination file verbatim.
   365         -      #
   366         -      file copy [replacePlatform $sourceFileName $platformName] \
   367         -          $newDestinationFileName
          391  +    if {[info exists no${buildName}] && [set no${buildName}]} then {
          392  +      continue
   368    393       }
   369    394   
   370    395       #
   371         -    # NOTE: Does the destination file contain dynamic replacements that must
   372         -    #       be processed now?
          396  +    # NOTE: If the current file is platform-neutral, then only one platform
          397  +    #       will be processed for it, namely "neutral"; otherwise, each
          398  +    #       supported platform will be processed for it individually.
   373    399       #
   374         -    if {$useSubst} then {
          400  +    foreach platformName \
          401  +        [expr {$platformNeutral ? [list neutral] : $platformNames}] {
          402  +      #
          403  +      # NOTE: Use the actual platform name in the destination file name.
          404  +      #
          405  +      set newDestinationFileName [replaceBuildAndPlatform \
          406  +          $destinationFileName $buildName $platformName]
          407  +
          408  +      #
          409  +      # NOTE: Does the source file need to be copied to the destination file?
          410  +      #
          411  +      if {[string length $sourceFileName] > 0} then {
          412  +        #
          413  +        # NOTE: First, make sure the destination directory exists.
          414  +        #
          415  +        file mkdir [file dirname $newDestinationFileName]
          416  +
          417  +        #
          418  +        # NOTE: Then, copy the source file to the destination file verbatim.
          419  +        #
          420  +        file copy [replaceBuildAndPlatform $sourceFileName $buildName \
          421  +            $platformName] $newDestinationFileName
          422  +      }
          423  +
   375    424         #
   376         -      # NOTE: Perform any dynamic replacements contained in the destination
   377         -      #       file and then re-write it in-place.
          425  +      # NOTE: Does the destination file contain dynamic replacements that must
          426  +      #       be processed now?
   378    427         #
   379         -      substFile $newDestinationFileName
          428  +      if {$useSubst} then {
          429  +        #
          430  +        # NOTE: Perform any dynamic replacements contained in the destination
          431  +        #       file and then re-write it in-place.
          432  +        #
          433  +        substFile $newDestinationFileName
          434  +      }
   380    435       }
   381    436     }
   382    437   }
   383    438   
   384    439   ###############################################################################
   385    440   
   386    441   #

Changes to tool/showdb.c.

     2      2   ** A utility for printing all or part of an SQLite database file.
     3      3   */
     4      4   #include <stdio.h>
     5      5   #include <ctype.h>
     6      6   #include <sys/types.h>
     7      7   #include <sys/stat.h>
     8      8   #include <fcntl.h>
            9  +
           10  +#if !defined(_MSC_VER)
     9     11   #include <unistd.h>
           12  +#endif
           13  +
    10     14   #include <stdlib.h>
    11     15   #include <string.h>
    12     16   #include "sqlite3.h"
    13     17   
    14     18   
    15     19   static int pagesize = 1024;     /* Size of a database page */
    16     20   static int db = -1;             /* File descriptor for reading the DB */

Changes to tool/spaceanal.tcl.

    26     26     } elseif {$file_to_analyze!=""} {
    27     27       usage
    28     28     } else {
    29     29       set file_to_analyze $arg
    30     30     }
    31     31   }
    32     32   if {$file_to_analyze==""} usage
    33         -if {![file exists $file_to_analyze]} {
    34         -  puts stderr "No such file: $file_to_analyze"
           33  +set root_filename $file_to_analyze
           34  +regexp {^file:(//)?([^?]*)} $file_to_analyze all x1 root_filename
           35  +if {![file exists $root_filename]} {
           36  +  puts stderr "No such file: $root_filename"
    35     37     exit 1
    36     38   }
    37         -if {![file readable $file_to_analyze]} {
    38         -  puts stderr "File is not readable: $file_to_analyze"
           39  +if {![file readable $root_filename]} {
           40  +  puts stderr "File is not readable: $root_filename"
    39     41     exit 1
    40     42   }
    41         -set true_file_size [file size $file_to_analyze]
           43  +set true_file_size [file size $root_filename]
    42     44   if {$true_file_size<512} {
    43         -  puts stderr "Empty or malformed database: $file_to_analyze"
           45  +  puts stderr "Empty or malformed database: $root_filename"
    44     46     exit 1
    45     47   }
    46     48   
    47     49   # Compute the total file size assuming test_multiplexor is being used.
    48     50   # Assume that SQLITE_ENABLE_8_3_NAMES might be enabled
    49     51   #
    50         -set extension [file extension $file_to_analyze]
    51         -set pattern $file_to_analyze
           52  +set extension [file extension $root_filename]
           53  +set pattern $root_filename
    52     54   append pattern {[0-3][0-9][0-9]}
    53     55   foreach f [glob -nocomplain $pattern] {
    54     56     incr true_file_size [file size $f]
    55     57     set extension {}
    56     58   }
    57     59   if {[string length $extension]>=2 && [string length $extension]<=4} {
    58         -  set pattern [file rootname $file_to_analyze]
           60  +  set pattern [file rootname $root_filename]
    59     61     append pattern {.[0-3][0-9][0-9]}
    60     62     foreach f [glob -nocomplain $pattern] {
    61     63       incr true_file_size [file size $f]
    62     64     }
    63     65   }
    64     66   
    65     67   # Open the database
    66     68   #
    67         -sqlite3 db $file_to_analyze
           69  +if {[catch {sqlite3 db $file_to_analyze -uri 1} msg]} {
           70  +  puts stderr "error trying to open $file_to_analyze: $msg"
           71  +  exit 1
           72  +}
    68     73   register_dbstat_vtab db
    69     74   
    70     75   db eval {SELECT count(*) FROM sqlite_master}
    71     76   set pageSize [expr {wide([db one {PRAGMA page_size}])}]
    72     77   
    73     78   if {$flags(-pageinfo)} {
    74     79     db eval {CREATE VIRTUAL TABLE temp.stat USING dbstat}
................................................................................
   480    485   # set total_payload [mem eval "SELECT sum(payload) FROM space_used"]
   481    486   set user_payload [mem one {SELECT int(sum(payload)) FROM space_used
   482    487        WHERE NOT is_index AND name NOT LIKE 'sqlite_master'}]
   483    488   set user_percent [percent $user_payload $file_bytes]
   484    489   
   485    490   # Output the summary statistics calculated above.
   486    491   #
   487         -puts "/** Disk-Space Utilization Report For $file_to_analyze"
          492  +puts "/** Disk-Space Utilization Report For $root_filename"
   488    493   catch {
   489    494     puts "*** As of [clock format [clock seconds] -format {%Y-%b-%d %H:%M:%S}]"
   490    495   }
   491    496   puts ""
   492    497   statline {Page size in bytes} $pageSize
   493    498   statline {Pages in the whole file (measured)} $file_pgcnt
   494    499   statline {Pages in the whole file (calculated)} $file_pgcnt2