/ Changes On Branch nx-devkit
Login

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

Changes In Branch nx-devkit Excluding Merge-Ins

This is equivalent to a diff from 1c45b2a0 to 627eff32

2012-04-04
13:51
Fix the multiplexor logging so that it works with SQLITE_ENABLE_8_3_NAMES. (Leaf check-in: 627eff32 user: drh tags: nx-devkit)
13:47
In the multiplexor extension, improve the error logging when a chunk fails to open. (check-in: e6806f0d user: drh tags: nx-devkit)
2011-12-12
20:01
Backport a minimal set of changes needed to get 8+3 filenames and the multiplexor shim playing well together. (check-in: c4e2ce48 user: drh tags: nx-devkit)
2011-11-18
13:10
Change the multiplexor to use a 3-digit suffix. (check-in: 0b7edc44 user: drh tags: trunk)
2011-11-17
11:49
Improvements to the documentation of the sqlite3_db_filename() interface. (check-in: 1c45b2a0 user: drh tags: trunk)
11:43
Restore the test for sqlite3OsFullPathname() failure that was mistakenly removed when [ceee03c79a] was backed out by [69ec53fc1c]. (check-in: 4d3cf9e1 user: drh tags: trunk)

Changes to ext/fts3/fts3.c.

  2596   2596           sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
  2597   2597           rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
  2598   2598           if( rc!=SQLITE_OK ) goto finished;
  2599   2599           if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
  2600   2600         }
  2601   2601    
  2602   2602         rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, 
  2603         -          iStartBlock, iLeavesEndBlock, iEndBlock, zRoot, nRoot, &pSeg
         2603  +          (isPrefix==0 && isScan==0),
         2604  +          iStartBlock, iLeavesEndBlock, 
         2605  +          iEndBlock, zRoot, nRoot, &pSeg
  2604   2606         );
  2605   2607         if( rc!=SQLITE_OK ) goto finished;
  2606   2608         rc = fts3SegReaderCursorAppend(pCsr, pSeg);
  2607   2609       }
  2608   2610     }
  2609   2611   
  2610   2612    finished:

Changes to ext/fts3/fts3Int.h.

   397    397   
   398    398   
   399    399   /* fts3_write.c */
   400    400   int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
   401    401   int sqlite3Fts3PendingTermsFlush(Fts3Table *);
   402    402   void sqlite3Fts3PendingTermsClear(Fts3Table *);
   403    403   int sqlite3Fts3Optimize(Fts3Table *);
   404         -int sqlite3Fts3SegReaderNew(int, sqlite3_int64,
          404  +int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64,
   405    405     sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
   406    406   int sqlite3Fts3SegReaderPending(
   407    407     Fts3Table*,int,const char*,int,int,Fts3SegReader**);
   408    408   void sqlite3Fts3SegReaderFree(Fts3SegReader *);
   409    409   int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **);
   410    410   int sqlite3Fts3ReadLock(Fts3Table *);
   411    411   int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);

Changes to ext/fts3/fts3_write.c.

   106    106   **
   107    107   **   fts3SegReaderNext()
   108    108   **   fts3SegReaderFirstDocid()
   109    109   **   fts3SegReaderNextDocid()
   110    110   */
   111    111   struct Fts3SegReader {
   112    112     int iIdx;                       /* Index within level, or 0x7FFFFFFF for PT */
          113  +  int bLookup;                    /* True for a lookup only */
   113    114   
   114    115     sqlite3_int64 iStartBlock;      /* Rowid of first leaf block to traverse */
   115    116     sqlite3_int64 iLeafEndBlock;    /* Rowid of final leaf block to traverse */
   116    117     sqlite3_int64 iEndBlock;        /* Rowid of final block in segment (or 0) */
   117    118     sqlite3_int64 iCurrentBlock;    /* Current leaf block (or 0) */
   118    119   
   119    120     char *aNode;                    /* Pointer to node data (or NULL) */
................................................................................
  1083   1084     while( pReader->pBlob && rc==SQLITE_OK 
  1084   1085        &&  (pFrom - pReader->aNode + nByte)>pReader->nPopulate
  1085   1086     ){
  1086   1087       rc = fts3SegReaderIncrRead(pReader);
  1087   1088     }
  1088   1089     return rc;
  1089   1090   }
         1091  +
         1092  +/*
         1093  +** Set an Fts3SegReader cursor to point at EOF.
         1094  +*/
         1095  +static void fts3SegReaderSetEof(Fts3SegReader *pSeg){
         1096  +  if( !fts3SegReaderIsRootOnly(pSeg) ){
         1097  +    sqlite3_free(pSeg->aNode);
         1098  +    sqlite3_blob_close(pSeg->pBlob);
         1099  +    pSeg->pBlob = 0;
         1100  +  }
         1101  +  pSeg->aNode = 0;
         1102  +}
  1090   1103   
  1091   1104   /*
  1092   1105   ** Move the iterator passed as the first argument to the next term in the
  1093   1106   ** segment. If successful, SQLITE_OK is returned. If there is no next term,
  1094   1107   ** SQLITE_DONE. Otherwise, an SQLite error code.
  1095   1108   */
  1096   1109   static int fts3SegReaderNext(
................................................................................
  1123   1136           pReader->aNode = pReader->aDoclist = pList->aData;
  1124   1137           pReader->ppNextElem++;
  1125   1138           assert( pReader->aNode );
  1126   1139         }
  1127   1140         return SQLITE_OK;
  1128   1141       }
  1129   1142   
  1130         -    if( !fts3SegReaderIsRootOnly(pReader) ){
  1131         -      sqlite3_free(pReader->aNode);
  1132         -      sqlite3_blob_close(pReader->pBlob);
  1133         -      pReader->pBlob = 0;
  1134         -    }
  1135         -    pReader->aNode = 0;
         1143  +    fts3SegReaderSetEof(pReader);
  1136   1144   
  1137   1145       /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf 
  1138   1146       ** blocks have already been traversed.  */
  1139   1147       assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
  1140   1148       if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
  1141   1149         return SQLITE_OK;
  1142   1150       }
................................................................................
  1375   1383   }
  1376   1384   
  1377   1385   /*
  1378   1386   ** Allocate a new SegReader object.
  1379   1387   */
  1380   1388   int sqlite3Fts3SegReaderNew(
  1381   1389     int iAge,                       /* Segment "age". */
         1390  +  int bLookup,                    /* True for a lookup only */
  1382   1391     sqlite3_int64 iStartLeaf,       /* First leaf to traverse */
  1383   1392     sqlite3_int64 iEndLeaf,         /* Final leaf to traverse */
  1384   1393     sqlite3_int64 iEndBlock,        /* Final block of segment */
  1385   1394     const char *zRoot,              /* Buffer containing root node */
  1386   1395     int nRoot,                      /* Size of buffer containing root node */
  1387   1396     Fts3SegReader **ppReader        /* OUT: Allocated Fts3SegReader */
  1388   1397   ){
................................................................................
  1397   1406   
  1398   1407     pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
  1399   1408     if( !pReader ){
  1400   1409       return SQLITE_NOMEM;
  1401   1410     }
  1402   1411     memset(pReader, 0, sizeof(Fts3SegReader));
  1403   1412     pReader->iIdx = iAge;
         1413  +  pReader->bLookup = bLookup;
  1404   1414     pReader->iStartBlock = iStartLeaf;
  1405   1415     pReader->iLeafEndBlock = iEndLeaf;
  1406   1416     pReader->iEndBlock = iEndBlock;
  1407   1417   
  1408   1418     if( nExtra ){
  1409   1419       /* The entire segment is stored in the root node. */
  1410   1420       pReader->aNode = (char *)&pReader[1];
................................................................................
  2399   2409     /* If the Fts3SegFilter defines a specific term (or term prefix) to search 
  2400   2410     ** for, then advance each segment iterator until it points to a term of
  2401   2411     ** equal or greater value than the specified term. This prevents many
  2402   2412     ** unnecessary merge/sort operations for the case where single segment
  2403   2413     ** b-tree leaf nodes contain more than one term.
  2404   2414     */
  2405   2415     for(i=0; pCsr->bRestart==0 && i<pCsr->nSegment; i++){
         2416  +    int res;
  2406   2417       Fts3SegReader *pSeg = pCsr->apSegment[i];
  2407   2418       do {
  2408   2419         int rc = fts3SegReaderNext(p, pSeg, 0);
  2409   2420         if( rc!=SQLITE_OK ) return rc;
  2410         -    }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 );
         2421  +    }while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 );
         2422  +
         2423  +    if( pSeg->bLookup && res!=0 ){
         2424  +      fts3SegReaderSetEof(pSeg);
         2425  +    }
  2411   2426     }
  2412   2427     fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp);
  2413   2428   
  2414   2429     return SQLITE_OK;
  2415   2430   }
  2416   2431   
  2417   2432   int sqlite3Fts3SegReaderStart(
................................................................................
  2524   2539       int nMerge;
  2525   2540       int i;
  2526   2541     
  2527   2542       /* Advance the first pCsr->nAdvance entries in the apSegment[] array
  2528   2543       ** forward. Then sort the list in order of current term again.  
  2529   2544       */
  2530   2545       for(i=0; i<pCsr->nAdvance; i++){
  2531         -      rc = fts3SegReaderNext(p, apSegment[i], 0);
         2546  +      Fts3SegReader *pSeg = apSegment[i];
         2547  +      if( pSeg->bLookup ){
         2548  +        fts3SegReaderSetEof(pSeg);
         2549  +      }else{
         2550  +        rc = fts3SegReaderNext(p, pSeg, 0);
         2551  +      }
  2532   2552         if( rc!=SQLITE_OK ) return rc;
  2533   2553       }
  2534   2554       fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp);
  2535   2555       pCsr->nAdvance = 0;
  2536   2556   
  2537   2557       /* If all the seg-readers are at EOF, we're finished. return SQLITE_OK. */
  2538   2558       assert( rc==SQLITE_OK );

Changes to src/btree.c.

  3975   3975            && pBt->inTransaction==TRANS_READ                     /* (4) */
  3976   3976            && (fd = sqlite3PagerFile(pBt->pPager))->pMethods     /* (3) */
  3977   3977            && pBt->pPage1->aData[19]==0x01                       /* (5) */
  3978   3978           ){
  3979   3979             u8 aSave[4];
  3980   3980             u8 *aWrite = &pBuf[-4];
  3981   3981             memcpy(aSave, aWrite, 4);
  3982         -          rc = sqlite3OsRead(fd, aWrite, a+4, pBt->pageSize * (nextPage-1));
         3982  +          rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
  3983   3983             nextPage = get4byte(aWrite);
  3984   3984             memcpy(aWrite, aSave, 4);
  3985   3985           }else
  3986   3986   #endif
  3987   3987   
  3988   3988           {
  3989   3989             DbPage *pDbPage;

Changes to src/loadext.c.

   621    621   ** Load all automatic extensions.
   622    622   **
   623    623   ** If anything goes wrong, set an error in the database connection.
   624    624   */
   625    625   void sqlite3AutoLoadExtensions(sqlite3 *db){
   626    626     int i;
   627    627     int go = 1;
          628  +  int rc;
   628    629     int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
   629    630   
   630    631     wsdAutoextInit;
   631    632     if( wsdAutoext.nExt==0 ){
   632    633       /* Common case: early out without every having to acquire a mutex */
   633    634       return;
   634    635     }
................................................................................
   643    644         go = 0;
   644    645       }else{
   645    646         xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
   646    647                 wsdAutoext.aExt[i];
   647    648       }
   648    649       sqlite3_mutex_leave(mutex);
   649    650       zErrmsg = 0;
   650         -    if( xInit && xInit(db, &zErrmsg, &sqlite3Apis) ){
   651         -      sqlite3Error(db, SQLITE_ERROR,
          651  +    if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){
          652  +      sqlite3Error(db, rc,
   652    653               "automatic extension loading failed: %s", zErrmsg);
   653    654         go = 0;
   654    655       }
   655    656       sqlite3_free(zErrmsg);
   656    657     }
   657    658   }

Changes to src/main.c.

   235    235   #endif
   236    236   
   237    237     /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
   238    238     ** compile-time option.
   239    239     */
   240    240   #ifdef SQLITE_EXTRA_INIT
   241    241     if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
   242         -    int SQLITE_EXTRA_INIT(void);
   243         -    rc = SQLITE_EXTRA_INIT();
          242  +    int SQLITE_EXTRA_INIT(const char*);
          243  +    rc = SQLITE_EXTRA_INIT(0);
   244    244     }
   245    245   #endif
   246    246   
   247    247     return rc;
   248    248   }
   249    249   
   250    250   /*
................................................................................
   253    253   ** while any part of SQLite is otherwise in use in any thread.  This
   254    254   ** routine is not threadsafe.  But it is safe to invoke this routine
   255    255   ** on when SQLite is already shut down.  If SQLite is already shut down
   256    256   ** when this routine is invoked, then this routine is a harmless no-op.
   257    257   */
   258    258   int sqlite3_shutdown(void){
   259    259     if( sqlite3GlobalConfig.isInit ){
          260  +#ifdef SQLITE_EXTRA_SHUTDOWN
          261  +    void SQLITE_EXTRA_SHUTDOWN(void);
          262  +    SQLITE_EXTRA_SHUTDOWN();
          263  +#endif
   260    264       sqlite3_os_end();
   261    265       sqlite3_reset_auto_extension();
   262    266       sqlite3GlobalConfig.isInit = 0;
   263    267     }
   264    268     if( sqlite3GlobalConfig.isPCacheInit ){
   265    269       sqlite3PcacheShutdown();
   266    270       sqlite3GlobalConfig.isPCacheInit = 0;
................................................................................
  2242   2246     */
  2243   2247     sqlite3Error(db, SQLITE_OK, 0);
  2244   2248     sqlite3RegisterBuiltinFunctions(db);
  2245   2249   
  2246   2250     /* Load automatic extensions - extensions that have been registered
  2247   2251     ** using the sqlite3_automatic_extension() API.
  2248   2252     */
  2249         -  sqlite3AutoLoadExtensions(db);
  2250   2253     rc = sqlite3_errcode(db);
  2251         -  if( rc!=SQLITE_OK ){
  2252         -    goto opendb_out;
         2254  +  if( rc==SQLITE_OK ){
         2255  +    sqlite3AutoLoadExtensions(db);
         2256  +    rc = sqlite3_errcode(db);
         2257  +    if( rc!=SQLITE_OK ){
         2258  +      goto opendb_out;
         2259  +    }
  2253   2260     }
  2254   2261   
  2255   2262   #ifdef SQLITE_ENABLE_FTS1
  2256   2263     if( !db->mallocFailed ){
  2257   2264       extern int sqlite3Fts1Init(sqlite3*);
  2258   2265       rc = sqlite3Fts1Init(db);
  2259   2266     }

Changes to src/os.h.

    96     96   # include <os2.h>
    97     97   # include <uconv.h>
    98     98   # define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
    99     99   #else
   100    100   # define SQLITE_TEMPNAME_SIZE 200
   101    101   #endif
   102    102   
          103  +/*
          104  +** Determine if we are dealing with Windows NT.
          105  +**
          106  +** We ought to be able to determine if we are compiling for win98 or winNT
          107  +** using the _WIN32_WINNT macro as follows:
          108  +**
          109  +** #if defined(_WIN32_WINNT)
          110  +** # define SQLITE_OS_WINNT 1
          111  +** #else
          112  +** # define SQLITE_OS_WINNT 0
          113  +** #endif
          114  +**
          115  +** However, vs2005 does not set _WIN32_WINNT by default, as it ought to,
          116  +** so the above test does not work.  We'll just assume that everything is
          117  +** winNT unless the programmer explicitly says otherwise by setting
          118  +** SQLITE_OS_WINNT to 0.
          119  +*/
          120  +#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
          121  +# define SQLITE_OS_WINNT 1
          122  +#endif
          123  +
          124  +/*
          125  +** Determine if we are dealing with WindowsCE - which has a much
          126  +** reduced API.
          127  +*/
          128  +#if defined(_WIN32_WCE)
          129  +# define SQLITE_OS_WINCE 1
          130  +#else
          131  +# define SQLITE_OS_WINCE 0
          132  +#endif
          133  +
   103    134   /* If the SET_FULLSYNC macro is not defined above, then make it
   104    135   ** a no-op
   105    136   */
   106    137   #ifndef SET_FULLSYNC
   107    138   # define SET_FULLSYNC(x,y)
   108    139   #endif
   109    140   

Changes to src/os_unix.c.

   202    202   /*
   203    203   ** The unixFile structure is subclass of sqlite3_file specific to the unix
   204    204   ** VFS implementations.
   205    205   */
   206    206   typedef struct unixFile unixFile;
   207    207   struct unixFile {
   208    208     sqlite3_io_methods const *pMethod;  /* Always the first entry */
          209  +  sqlite3_vfs *pVfs;                  /* The VFS that created this unixFile */
   209    210     unixInodeInfo *pInode;              /* Info about locks on this inode */
   210    211     int h;                              /* The file descriptor */
   211    212     unsigned char eFileLock;            /* The type of lock held on this fd */
   212    213     unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
   213    214     int lastErrno;                      /* The unix errno from last I/O error */
   214    215     void *lockingContext;               /* Locking style specific state */
   215    216     UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
................................................................................
  3529   3530         }else if( bPersist==0 ){
  3530   3531           pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
  3531   3532         }else{
  3532   3533           pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
  3533   3534         }
  3534   3535         return SQLITE_OK;
  3535   3536       }
         3537  +    case SQLITE_FCNTL_VFSNAME: {
         3538  +      *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
         3539  +      return SQLITE_OK;
         3540  +    }
  3536   3541   #ifndef NDEBUG
  3537   3542       /* The pager calls this method to signal that it has done
  3538   3543       ** a rollback and that the database is therefore unchanged and
  3539   3544       ** it hence it is OK for the transaction change counter to be
  3540   3545       ** unchanged.
  3541   3546       */
  3542   3547       case SQLITE_FCNTL_DB_UNCHANGED: {
................................................................................
  4556   4561   #endif
  4557   4562   
  4558   4563     /* No locking occurs in temporary files */
  4559   4564     assert( zFilename!=0 || noLock );
  4560   4565   
  4561   4566     OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  4562   4567     pNew->h = h;
         4568  +  pNew->pVfs = pVfs;
  4563   4569     pNew->zPath = zFilename;
  4564   4570     if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
  4565   4571       pNew->ctrlFlags = UNIXFILE_EXCL;
  4566   4572     }else{
  4567   4573       pNew->ctrlFlags = 0;
  4568   4574     }
  4569   4575     if( isReadOnly ){
................................................................................
  4895   4901       **   "<path to db>-walNN"
  4896   4902       **
  4897   4903       ** where NN is a decimal number. The NN naming schemes are 
  4898   4904       ** used by the test_multiplex.c module.
  4899   4905       */
  4900   4906       nDb = sqlite3Strlen30(zPath) - 1; 
  4901   4907   #ifdef SQLITE_ENABLE_8_3_NAMES
  4902         -    while( nDb>0 && !sqlite3Isalnum(zPath[nDb]) ) nDb--;
         4908  +    while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
  4903   4909       if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
  4904   4910   #else
  4905   4911       while( zPath[nDb]!='-' ){
  4906   4912         assert( nDb>0 );
  4907   4913         assert( zPath[nDb]!='\n' );
  4908   4914         nDb--;
  4909   4915       }

Changes to src/os_win.c.

   177    177   ** testing and sandboxing.  The following array holds the names and pointers
   178    178   ** to all overrideable system calls.
   179    179   */
   180    180   #if !SQLITE_OS_WINCE
   181    181   #  define SQLITE_WIN32_HAS_ANSI
   182    182   #endif
   183    183   
   184         -#if SQLITE_OS_WINCE || defined(_WIN32_WINNT)
          184  +#if SQLITE_OS_WINCE || SQLITE_OS_WINNT
   185    185   #  define SQLITE_WIN32_HAS_WIDE
   186    186   #endif
   187    187   
   188    188   #ifndef SYSCALL
   189    189   #  define SYSCALL sqlite3_syscall_ptr
   190    190   #endif
   191    191   
................................................................................
  2140   2140         int bPersist = *(int*)pArg;
  2141   2141         if( bPersist<0 ){
  2142   2142           *(int*)pArg = pFile->bPersistWal;
  2143   2143         }else{
  2144   2144           pFile->bPersistWal = bPersist!=0;
  2145   2145         }
  2146   2146         return SQLITE_OK;
         2147  +    }
         2148  +    case SQLITE_FCNTL_VFSNAME: {
         2149  +      *(char**)pArg = sqlite3_mprintf("win32");
         2150  +      return SQLITE_OK;
  2147   2151       }
  2148   2152       case SQLITE_FCNTL_SYNC_OMITTED: {
  2149   2153         return SQLITE_OK;
  2150   2154       }
  2151   2155       case SQLITE_FCNTL_WIN32_AV_RETRY: {
  2152   2156         int *a = (int*)pArg;
  2153   2157         if( a[0]>0 ){

Changes to src/pager.c.

  2481   2481       assert( pPager->eLock==EXCLUSIVE_LOCK );
  2482   2482       /* TODO: Is it safe to use Pager.dbFileSize here? */
  2483   2483       rc = sqlite3OsFileSize(pPager->fd, &currentSize);
  2484   2484       newSize = szPage*(i64)nPage;
  2485   2485       if( rc==SQLITE_OK && currentSize!=newSize ){
  2486   2486         if( currentSize>newSize ){
  2487   2487           rc = sqlite3OsTruncate(pPager->fd, newSize);
  2488         -      }else{
         2488  +      }else if( (currentSize+szPage)<=newSize ){
  2489   2489           char *pTmp = pPager->pTmpSpace;
  2490   2490           memset(pTmp, 0, szPage);
  2491   2491           testcase( (newSize-szPage) <  currentSize );
  2492   2492           testcase( (newSize-szPage) == currentSize );
  2493   2493           testcase( (newSize-szPage) >  currentSize );
  2494   2494           rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
  2495   2495         }
................................................................................
  3070   3070       assert( isOpen(pPager->fd) || pPager->tempFile );
  3071   3071       if( isOpen(pPager->fd) ){
  3072   3072         int rc = sqlite3OsFileSize(pPager->fd, &n);
  3073   3073         if( rc!=SQLITE_OK ){
  3074   3074           return rc;
  3075   3075         }
  3076   3076       }
  3077         -    nPage = (Pgno)(n / pPager->pageSize);
         3077  +    nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
  3078   3078       if( nPage==0 && n>0 ){
  3079   3079         nPage = 1;
  3080   3080       }
  3081   3081     }
  3082   3082   
  3083   3083     /* If the current number of pages in the file is greater than the
  3084   3084     ** configured maximum pager number, increase the allowed limit so
................................................................................
  3263   3263   
  3264   3264     /* Finally,  rollback pages from the sub-journal.  Page that were
  3265   3265     ** previously rolled back out of the main journal (and are hence in pDone)
  3266   3266     ** will be skipped.  Out-of-range pages are also skipped.
  3267   3267     */
  3268   3268     if( pSavepoint ){
  3269   3269       u32 ii;            /* Loop counter */
  3270         -    i64 offset = pSavepoint->iSubRec*(4+pPager->pageSize);
         3270  +    i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);
  3271   3271   
  3272   3272       if( pagerUseWal(pPager) ){
  3273   3273         rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
  3274   3274       }
  3275   3275       for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
  3276         -      assert( offset==ii*(4+pPager->pageSize) );
         3276  +      assert( offset==(i64)ii*(4+pPager->pageSize) );
  3277   3277         rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
  3278   3278       }
  3279   3279       assert( rc!=SQLITE_DONE );
  3280   3280     }
  3281   3281   
  3282   3282     sqlite3BitvecDestroy(pDone);
  3283   3283     if( rc==SQLITE_OK ){
................................................................................
  3500   3500       if( rc==SQLITE_OK ){
  3501   3501         pNew = (char *)sqlite3PageMalloc(pageSize);
  3502   3502         if( !pNew ) rc = SQLITE_NOMEM;
  3503   3503       }
  3504   3504   
  3505   3505       if( rc==SQLITE_OK ){
  3506   3506         pager_reset(pPager);
  3507         -      pPager->dbSize = (Pgno)(nByte/pageSize);
         3507  +      pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
  3508   3508         pPager->pageSize = pageSize;
  3509   3509         sqlite3PageFree(pPager->pTmpSpace);
  3510   3510         pPager->pTmpSpace = pNew;
  3511   3511         sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
  3512   3512       }
  3513   3513     }
  3514   3514   
................................................................................
  4117   4117       );
  4118   4118       rc = openSubJournal(pPager);
  4119   4119   
  4120   4120       /* If the sub-journal was opened successfully (or was already open),
  4121   4121       ** write the journal record into the file.  */
  4122   4122       if( rc==SQLITE_OK ){
  4123   4123         void *pData = pPg->pData;
  4124         -      i64 offset = pPager->nSubRec*(4+pPager->pageSize);
         4124  +      i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
  4125   4125         char *pData2;
  4126   4126     
  4127   4127         CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
  4128   4128         PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
  4129   4129         rc = write32bits(pPager->sjfd, offset, pPg->pgno);
  4130   4130         if( rc==SQLITE_OK ){
  4131   4131           rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);

Changes to src/shell.c.

  1392   1392     ".separator STRING      Change separator used by output mode and .import\n"
  1393   1393     ".show                  Show the current values for various settings\n"
  1394   1394     ".stats ON|OFF          Turn stats on or off\n"
  1395   1395     ".tables ?TABLE?        List names of tables\n"
  1396   1396     "                         If TABLE specified, only list tables matching\n"
  1397   1397     "                         LIKE pattern TABLE.\n"
  1398   1398     ".timeout MS            Try opening locked tables for MS milliseconds\n"
         1399  +  ".vfsname ?AUX?         Print the name of the VFS stack\n"
  1399   1400     ".width NUM1 NUM2 ...   Set column widths for \"column\" mode\n"
  1400   1401   ;
  1401   1402   
  1402   1403   static char zTimerHelp[] =
  1403   1404     ".timer ON|OFF          Turn the CPU timer measurement on or off\n"
  1404   1405   ;
  1405   1406   
................................................................................
  2331   2332     if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
  2332   2333      && nArg==2
  2333   2334     ){
  2334   2335       enableTimer = booleanValue(azArg[1]);
  2335   2336     }else
  2336   2337     
  2337   2338     if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
  2338         -    printf("SQLite %s %s\n",
         2339  +    printf("SQLite %s %s\n" /*extra-version-info*/,
  2339   2340           sqlite3_libversion(), sqlite3_sourceid());
  2340   2341     }else
         2342  +
         2343  +  if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
         2344  +    const char *zDbName = nArg==2 ? azArg[1] : "main";
         2345  +    char *zVfsName = 0;
         2346  +    if( p->db ){
         2347  +      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
         2348  +      if( zVfsName ){
         2349  +        printf("%s\n", zVfsName);
         2350  +        sqlite3_free(zVfsName);
         2351  +      }
         2352  +    }
         2353  +  }else
  2341   2354   
  2342   2355     if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
  2343   2356       int j;
  2344   2357       assert( nArg<=ArraySize(azArg) );
  2345   2358       for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
  2346   2359         p->colWidth[j-1] = atoi(azArg[j]);
  2347   2360       }
................................................................................
  2640   2653     return rc;
  2641   2654   }
  2642   2655   
  2643   2656   /*
  2644   2657   ** Show available command line options
  2645   2658   */
  2646   2659   static const char zOptions[] = 
  2647         -  "   -help                show this message\n"
  2648         -  "   -init filename       read/process named file\n"
  2649         -  "   -echo                print commands before execution\n"
  2650         -  "   -[no]header          turn headers on or off\n"
  2651   2660     "   -bail                stop after hitting an error\n"
  2652         -  "   -interactive         force interactive I/O\n"
  2653   2661     "   -batch               force batch I/O\n"
  2654   2662     "   -column              set output mode to 'column'\n"
         2663  +  "   -cmd command         run \"command\" before reading stdin\n"
  2655   2664     "   -csv                 set output mode to 'csv'\n"
         2665  +  "   -echo                print commands before execution\n"
         2666  +  "   -init filename       read/process named file\n"
         2667  +  "   -[no]header          turn headers on or off\n"
         2668  +  "   -help                show this message\n"
  2656   2669     "   -html                set output mode to HTML\n"
         2670  +  "   -interactive         force interactive I/O\n"
  2657   2671     "   -line                set output mode to 'line'\n"
  2658   2672     "   -list                set output mode to 'list'\n"
         2673  +#ifdef SQLITE_ENABLE_MULTIPLEX
         2674  +  "   -multiplex           enable the multiplexor VFS\n"
         2675  +#endif
         2676  +  "   -nullvalue 'text'    set text string for NULL values\n"
  2659   2677     "   -separator 'x'       set output field separator (|)\n"
  2660   2678     "   -stats               print memory stats before each finalize\n"
  2661         -  "   -nullvalue 'text'    set text string for NULL values\n"
  2662   2679     "   -version             show SQLite version\n"
  2663   2680     "   -vfs NAME            use NAME as the default VFS\n"
  2664   2681   #ifdef SQLITE_ENABLE_VFSTRACE
  2665   2682     "   -vfstrace            enable tracing of all VFS calls\n"
  2666   2683   #endif
  2667         -#ifdef SQLITE_ENABLE_MULTIPLEX
  2668         -  "   -multiplex           enable the multiplexor VFS\n"
  2669         -#endif
  2670   2684   ;
  2671   2685   static void usage(int showDetail){
  2672   2686     fprintf(stderr,
  2673   2687         "Usage: %s [OPTIONS] FILENAME [SQL]\n"  
  2674   2688         "FILENAME is the name of an SQLite database. A new database is created\n"
  2675   2689         "if the file does not previously exist.\n", Argv0);
  2676   2690     if( showDetail ){
................................................................................
  2725   2739     ** the size of the alternative malloc heap,
  2726   2740     ** and the first command to execute.
  2727   2741     */
  2728   2742     for(i=1; i<argc-1; i++){
  2729   2743       char *z;
  2730   2744       if( argv[i][0]!='-' ) break;
  2731   2745       z = argv[i];
  2732         -    if( z[0]=='-' && z[1]=='-' ) z++;
  2733         -    if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){
         2746  +    if( z[1]=='-' ) z++;
         2747  +    if( strcmp(z,"-separator")==0
         2748  +     || strcmp(z,"-nullvalue")==0
         2749  +     || strcmp(z,"-cmd")==0
         2750  +    ){
  2734   2751         i++;
  2735         -    }else if( strcmp(argv[i],"-init")==0 ){
         2752  +    }else if( strcmp(z,"-init")==0 ){
  2736   2753         i++;
  2737   2754         zInitFile = argv[i];
  2738   2755       /* Need to check for batch mode here to so we can avoid printing
  2739   2756       ** informational messages (like from process_sqliterc) before 
  2740   2757       ** we do the actual processing of arguments later in a second pass.
  2741   2758       */
  2742         -    }else if( strcmp(argv[i],"-batch")==0 ){
         2759  +    }else if( strcmp(z,"-batch")==0 ){
  2743   2760         stdin_is_interactive = 0;
  2744         -    }else if( strcmp(argv[i],"-heap")==0 ){
         2761  +    }else if( strcmp(z,"-heap")==0 ){
  2745   2762   #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
  2746   2763         int j, c;
  2747   2764         const char *zSize;
  2748   2765         sqlite3_int64 szHeap;
  2749   2766   
  2750   2767         zSize = argv[++i];
  2751   2768         szHeap = atoi(zSize);
................................................................................
  2754   2771           if( c=='K' ){ szHeap *= 1000; break; }
  2755   2772           if( c=='G' ){ szHeap *= 1000000000; break; }
  2756   2773         }
  2757   2774         if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
  2758   2775         sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
  2759   2776   #endif
  2760   2777   #ifdef SQLITE_ENABLE_VFSTRACE
  2761         -    }else if( strcmp(argv[i],"-vfstrace")==0 ){
         2778  +    }else if( strcmp(z,"-vfstrace")==0 ){
  2762   2779         extern int vfstrace_register(
  2763   2780            const char *zTraceName,
  2764   2781            const char *zOldVfsName,
  2765   2782            int (*xOut)(const char*,void*),
  2766   2783            void *pOutArg,
  2767   2784            int makeDefault
  2768   2785         );
  2769   2786         vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
  2770   2787   #endif
  2771   2788   #ifdef SQLITE_ENABLE_MULTIPLEX
  2772         -    }else if( strcmp(argv[i],"-multiplex")==0 ){
         2789  +    }else if( strcmp(z,"-multiplex")==0 ){
  2773   2790         extern int sqlite3_multiple_initialize(const char*,int);
  2774   2791         sqlite3_multiplex_initialize(0, 1);
  2775   2792   #endif
  2776         -    }else if( strcmp(argv[i],"-vfs")==0 ){
         2793  +    }else if( strcmp(z,"-vfs")==0 ){
  2777   2794         sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[++i]);
  2778   2795         if( pVfs ){
  2779   2796           sqlite3_vfs_register(pVfs, 1);
  2780   2797         }else{
  2781   2798           fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
  2782   2799           exit(1);
  2783   2800         }
................................................................................
  2851   2868         data.mode = MODE_Column;
  2852   2869       }else if( strcmp(z,"-csv")==0 ){
  2853   2870         data.mode = MODE_Csv;
  2854   2871         memcpy(data.separator,",",2);
  2855   2872       }else if( strcmp(z,"-separator")==0 ){
  2856   2873         i++;
  2857   2874         if(i>=argc){
  2858         -        fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z);
         2875  +        fprintf(stderr,"%s: Error: missing argument for option: %s\n",
         2876  +                        Argv0, z);
  2859   2877           fprintf(stderr,"Use -help for a list of options.\n");
  2860   2878           return 1;
  2861   2879         }
  2862   2880         sqlite3_snprintf(sizeof(data.separator), data.separator,
  2863   2881                          "%.*s",(int)sizeof(data.separator)-1,argv[i]);
  2864   2882       }else if( strcmp(z,"-nullvalue")==0 ){
  2865   2883         i++;
  2866   2884         if(i>=argc){
  2867         -        fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z);
         2885  +        fprintf(stderr,"%s: Error: missing argument for option: %s\n",
         2886  +                        Argv0, z);
  2868   2887           fprintf(stderr,"Use -help for a list of options.\n");
  2869   2888           return 1;
  2870   2889         }
  2871   2890         sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
  2872   2891                          "%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
  2873   2892       }else if( strcmp(z,"-header")==0 ){
  2874   2893         data.showHeader = 1;
................................................................................
  2895   2914       }else if( strcmp(z,"-vfstrace")==0 ){
  2896   2915         i++;
  2897   2916   #endif
  2898   2917   #ifdef SQLITE_ENABLE_MULTIPLEX
  2899   2918       }else if( strcmp(z,"-multiplex")==0 ){
  2900   2919         i++;
  2901   2920   #endif
  2902         -    }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){
         2921  +    }else if( strcmp(z,"-help")==0 ){
  2903   2922         usage(1);
         2923  +    }else if( strcmp(z,"-cmd")==0 ){
         2924  +      if( i==argc-1 ) break;
         2925  +      i++;
         2926  +      z = argv[i];
         2927  +      if( z[0]=='.' ){
         2928  +        rc = do_meta_command(z, &data);
         2929  +        if( rc && bail_on_error ) return rc;
         2930  +      }else{
         2931  +        open_db(&data);
         2932  +        rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
         2933  +        if( zErrMsg!=0 ){
         2934  +          fprintf(stderr,"Error: %s\n", zErrMsg);
         2935  +          if( bail_on_error ) return rc!=0 ? rc : 1;
         2936  +        }else if( rc!=0 ){
         2937  +          fprintf(stderr,"Error: unable to process SQL \"%s\"\n", z);
         2938  +          if( bail_on_error ) return rc;
         2939  +        }
         2940  +      }
  2904   2941       }else{
  2905   2942         fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
  2906   2943         fprintf(stderr,"Use -help for a list of options.\n");
  2907   2944         return 1;
  2908   2945       }
  2909   2946     }
  2910   2947   
................................................................................
  2928   2965       /* Run commands received from standard input
  2929   2966       */
  2930   2967       if( stdin_is_interactive ){
  2931   2968         char *zHome;
  2932   2969         char *zHistory = 0;
  2933   2970         int nHistory;
  2934   2971         printf(
  2935         -        "SQLite version %s %.19s\n"
         2972  +        "SQLite version %s %.19s\n" /*extra-version-info*/
  2936   2973           "Enter \".help\" for instructions\n"
  2937   2974           "Enter SQL statements terminated with a \";\"\n",
  2938   2975           sqlite3_libversion(), sqlite3_sourceid()
  2939   2976         );
  2940   2977         zHome = find_home_dir();
  2941   2978         if( zHome ){
  2942   2979           nHistory = strlen30(zHome) + 20;

Changes to src/sqlite.h.in.

   767    767   ** WAL mode.  If the integer is -1, then it is overwritten with the current
   768    768   ** WAL persistence setting.
   769    769   **
   770    770   ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
   771    771   ** a write transaction to indicate that, unless it is rolled back for some
   772    772   ** reason, the entire database file will be overwritten by the current 
   773    773   ** transaction. This is used by VACUUM operations.
          774  +**
          775  +** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
          776  +** all [VFSes] in the VFS stack.  The names are of all VFS shims and the
          777  +** final bottom-level VFS are written into memory obtained from 
          778  +** [sqlite3_malloc()] and the result is stored in the char* variable
          779  +** that the fourth parameter of [sqlite3_file_control()] points to.
          780  +** The caller is responsible for freeing the memory when done.  As with
          781  +** all file-control actions, there is no guarantee that this will actually
          782  +** do anything.  Callers should initialize the char* variable to a NULL
          783  +** pointer in case this file-control is not implemented.  This file-control
          784  +** is intended for diagnostic use only.
   774    785   */
   775    786   #define SQLITE_FCNTL_LOCKSTATE        1
   776    787   #define SQLITE_GET_LOCKPROXYFILE      2
   777    788   #define SQLITE_SET_LOCKPROXYFILE      3
   778    789   #define SQLITE_LAST_ERRNO             4
   779    790   #define SQLITE_FCNTL_SIZE_HINT        5
   780    791   #define SQLITE_FCNTL_CHUNK_SIZE       6
   781    792   #define SQLITE_FCNTL_FILE_POINTER     7
   782    793   #define SQLITE_FCNTL_SYNC_OMITTED     8
   783    794   #define SQLITE_FCNTL_WIN32_AV_RETRY   9
   784    795   #define SQLITE_FCNTL_PERSIST_WAL     10
   785    796   #define SQLITE_FCNTL_OVERWRITE       11
          797  +#define SQLITE_FCNTL_VFSNAME         12
   786    798   
   787    799   /*
   788    800   ** CAPI3REF: Mutex Handle
   789    801   **
   790    802   ** The mutex module within SQLite defines [sqlite3_mutex] to be an
   791    803   ** abstract type for a mutex object.  The SQLite core never looks
   792    804   ** at the internal representation of an [sqlite3_mutex].  It only

Changes to src/test1.c.

  5204   5204     if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
  5205   5205     rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
  5206   5206     sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
  5207   5207     Tcl_AppendResult(interp, z, (char*)0);
  5208   5208     return TCL_OK;  
  5209   5209   }
  5210   5210   
         5211  +
         5212  +/*
         5213  +** tclcmd:   file_control_vfsname DB ?AUXDB?
         5214  +**
         5215  +** Return a string that describes the stack of VFSes.
         5216  +*/
         5217  +static int file_control_vfsname(
         5218  +  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
         5219  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
         5220  +  int objc,              /* Number of arguments */
         5221  +  Tcl_Obj *CONST objv[]  /* Command arguments */
         5222  +){
         5223  +  sqlite3 *db;
         5224  +  const char *zDbName = "main";
         5225  +  char *zVfsName = 0;
         5226  +
         5227  +  if( objc!=2 && objc!=3 ){
         5228  +    Tcl_AppendResult(interp, "wrong # args: should be \"",
         5229  +        Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
         5230  +    return TCL_ERROR;
         5231  +  }
         5232  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
         5233  +    return TCL_ERROR;
         5234  +  }
         5235  +  if( objc==3 ){
         5236  +    zDbName = Tcl_GetString(objv[2]);
         5237  +  }
         5238  +  sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
         5239  +  Tcl_AppendResult(interp, zVfsName, (char*)0);
         5240  +  sqlite3_free(zVfsName);
         5241  +  return TCL_OK;  
         5242  +}
         5243  +
  5211   5244   
  5212   5245   /*
  5213   5246   ** tclcmd:   sqlite3_vfs_list
  5214   5247   **
  5215   5248   **   Return a tcl list containing the names of all registered vfs's.
  5216   5249   */
  5217   5250   static int vfs_list(
................................................................................
  6028   6061        { "file_control_test",          file_control_test,   0   },
  6029   6062        { "file_control_lasterrno_test", file_control_lasterrno_test,  0   },
  6030   6063        { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
  6031   6064        { "file_control_chunksize_test", file_control_chunksize_test,  0   },
  6032   6065        { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
  6033   6066        { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
  6034   6067        { "file_control_persist_wal",    file_control_persist_wal,     0   },
         6068  +     { "file_control_vfsname",        file_control_vfsname,         0   },
  6035   6069        { "sqlite3_vfs_list",           vfs_list,     0   },
  6036   6070        { "sqlite3_create_function_v2", test_create_function_v2, 0 },
  6037   6071   
  6038   6072        /* Functions from os.h */
  6039   6073   #ifndef SQLITE_OMIT_UTF16
  6040   6074        { "add_test_collate",        test_collate, 0            },
  6041   6075        { "add_test_collate_needed", test_collate_needed, 0     },

Changes to src/test_journal.c.

   387    387           }
   388    388         }
   389    389       }
   390    390       iTrunk = decodeUint32(&aData[32]);
   391    391       while( rc==SQLITE_OK && iTrunk>0 ){
   392    392         u32 nLeaf;
   393    393         u32 iLeaf;
   394         -      sqlite3_int64 iOff = (iTrunk-1)*pMain->nPagesize;
          394  +      sqlite3_int64 iOff = (i64)(iTrunk-1)*pMain->nPagesize;
   395    395         rc = sqlite3OsRead(p, aData, pMain->nPagesize, iOff);
   396    396         nLeaf = decodeUint32(&aData[4]);
   397    397         for(iLeaf=0; rc==SQLITE_OK && iLeaf<nLeaf; iLeaf++){
   398    398           u32 pgno = decodeUint32(&aData[8+4*iLeaf]);
   399    399           sqlite3BitvecSet(pMain->pWritable, pgno);
   400    400         }
   401    401         iTrunk = decodeUint32(aData);

Changes to src/test_multiplex.c.

    77     77   #define sqlite3_mutex_enter(X)
    78     78   #define sqlite3_mutex_try(X)      SQLITE_OK
    79     79   #define sqlite3_mutex_leave(X)
    80     80   #define sqlite3_mutex_held(X)     ((void)(X),1)
    81     81   #define sqlite3_mutex_notheld(X)  ((void)(X),1)
    82     82   #endif /* SQLITE_THREADSAFE==0 */
    83     83   
           84  +/* First chunk for rollback journal files */
           85  +#define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
           86  +
    84     87   
    85     88   /************************ Shim Definitions ******************************/
    86     89   
    87     90   #ifndef SQLITE_MULTIPLEX_VFS_NAME
    88     91   # define SQLITE_MULTIPLEX_VFS_NAME "multiplex"
    89     92   #endif
    90     93   
................................................................................
    92     95   ** the xFileControl() interface.  It will be rounded up to a 
    93     96   ** multiple of MAX_PAGE_SIZE.  We default it here to 2GiB less 64KiB.
    94     97   */
    95     98   #ifndef SQLITE_MULTIPLEX_CHUNK_SIZE
    96     99   # define SQLITE_MULTIPLEX_CHUNK_SIZE 2147418112
    97    100   #endif
    98    101   
    99         -/* Default limit on number of chunks.  Care should be taken
   100         -** so that values for chunks numbers fit in the SQLITE_MULTIPLEX_EXT_FMT
   101         -** format specifier. It may be changed by calling
   102         -** the xFileControl() interface.
          102  +/* This used to be the default limit on number of chunks, but
          103  +** it is no longer enforced. There is currently no limit to the
          104  +** number of chunks.
          105  +**
          106  +** May be changed by calling the xFileControl() interface.
   103    107   */
   104    108   #ifndef SQLITE_MULTIPLEX_MAX_CHUNKS
   105         -# define SQLITE_MULTIPLEX_MAX_CHUNKS 32
          109  +# define SQLITE_MULTIPLEX_MAX_CHUNKS 12
   106    110   #endif
   107    111   
   108         -/* If SQLITE_MULTIPLEX_EXT_OVWR is defined, the 
   109         -** last SQLITE_MULTIPLEX_EXT_SZ characters of the 
   110         -** filename will be overwritten, otherwise, the 
   111         -** multiplex extension is simply appended to the filename.
   112         -** Ex.  (undefined) test.db -> test.db01
   113         -**      (defined)   test.db -> test.01
   114         -** Chunk 0 does not have a modified extension.
   115         -*/
   116         -#define SQLITE_MULTIPLEX_EXT_FMT    "%02d"
   117         -#define SQLITE_MULTIPLEX_EXT_SZ     2
   118         -
   119    112   /************************ Object Definitions ******************************/
   120    113   
   121    114   /* Forward declaration of all object types */
   122    115   typedef struct multiplexGroup multiplexGroup;
   123    116   typedef struct multiplexConn multiplexConn;
   124    117   
   125    118   /*
................................................................................
   136    129       char *z;                          /* Name of this chunk */
   137    130     } *aReal;                        /* list of all chunks */
   138    131     int nReal;                       /* Number of chunks */
   139    132     char *zName;                     /* Base filename of this group */
   140    133     int nName;                       /* Length of base filename */
   141    134     int flags;                       /* Flags used for original opening */
   142    135     unsigned int szChunk;            /* Chunk size used for this group */
   143         -  int bEnabled;                    /* TRUE to use Multiplex VFS for this file */
          136  +  unsigned char bEnabled;          /* TRUE to use Multiplex VFS for this file */
          137  +  unsigned char bTruncate;         /* TRUE to enable truncation of databases */
   144    138     multiplexGroup *pNext, *pPrev;   /* Doubly linked list of all group objects */
   145    139   };
   146    140   
   147    141   /*
   148    142   ** An instance of the following object represents each open connection
   149    143   ** to a file that is multiplex'ed.  This object is a 
   150    144   ** subclass of sqlite3_file.  The sqlite3_file object for the underlying
................................................................................
   220    214     const char *z2 = z;
   221    215     if( z==0 ) return 0;
   222    216     while( *z2 ){ z2++; }
   223    217     return 0x3fffffff & (int)(z2 - z);
   224    218   }
   225    219   
   226    220   /*
   227         -** Create a temporary file name in zBuf.  zBuf must be big enough to
   228         -** hold at pOrigVfs->mxPathname characters.  This function departs
   229         -** from the traditional temporary name generation in the os_win
   230         -** and os_unix VFS in several ways, but is necessary so that 
   231         -** the file name is known for temporary files (like those used 
   232         -** during vacuum.)
   233         -**
   234         -** N.B. This routine assumes your underlying VFS is ok with using
   235         -** "/" as a directory seperator.  This is the default for UNIXs
   236         -** and is allowed (even mixed) for most versions of Windows.
   237         -*/
   238         -static int multiplexGetTempname(sqlite3_vfs *pOrigVfs, int nBuf, char *zBuf){
   239         -  static char zChars[] =
   240         -    "abcdefghijklmnopqrstuvwxyz"
   241         -    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   242         -    "0123456789";
   243         -  int i,j;
   244         -  int attempts = 0;
   245         -  int exists = 0;
   246         -  int rc = SQLITE_ERROR;
   247         -
   248         -  /* Check that the output buffer is large enough for 
   249         -  ** pVfs->mxPathname characters.
   250         -  */
   251         -  if( pOrigVfs->mxPathname <= nBuf ){
   252         -    char *zTmp = sqlite3_malloc(pOrigVfs->mxPathname);
   253         -    if( zTmp==0 ) return SQLITE_NOMEM;
   254         -
   255         -    /* sqlite3_temp_directory should always be less than
   256         -    ** pVfs->mxPathname characters.
   257         -    */
   258         -    sqlite3_snprintf(pOrigVfs->mxPathname,
   259         -                     zTmp,
   260         -                     "%s/",
   261         -                     sqlite3_temp_directory ? sqlite3_temp_directory : ".");
   262         -    rc = pOrigVfs->xFullPathname(pOrigVfs, zTmp, nBuf, zBuf);
   263         -    sqlite3_free(zTmp);
   264         -    if( rc ) return rc;
   265         -
   266         -    /* Check that the output buffer is large enough for the temporary file 
   267         -    ** name.
   268         -    */
   269         -    j = multiplexStrlen30(zBuf);
   270         -    if( (j + 8 + 1 + 3 + 1) <= nBuf ){
   271         -      /* Make 3 attempts to generate a unique name. */
   272         -      do {
   273         -        attempts++;
   274         -        sqlite3_randomness(8, &zBuf[j]);
   275         -        for(i=0; i<8; i++){
   276         -          unsigned char uc = (unsigned char)zBuf[j+i];
   277         -          zBuf[j+i] = (char)zChars[uc%(sizeof(zChars)-1)];
   278         -        }
   279         -        memcpy(&zBuf[j+i], ".tmp", 5);
   280         -        rc = pOrigVfs->xAccess(pOrigVfs, zBuf, SQLITE_ACCESS_EXISTS, &exists);
   281         -      } while ( (rc==SQLITE_OK) && exists && (attempts<3) );
   282         -      if( rc==SQLITE_OK && exists ){
   283         -        rc = SQLITE_ERROR;
   284         -      }
   285         -    }
   286         -  }
   287         -
   288         -  return rc;
          221  +** Generate the file-name for chunk iChunk of the group with base name
          222  +** zBase. The file-name is written to buffer zOut before returning. Buffer
          223  +** zOut must be allocated by the caller so that it is at least (nBase+4)
          224  +** bytes in size, where nBase is the length of zBase, not including the
          225  +** nul-terminator.
          226  +*/
          227  +static void multiplexFilename(
          228  +  const char *zBase,              /* Filename for chunk 0 */
          229  +  int nBase,                      /* Size of zBase in bytes (without \0) */
          230  +  int flags,                      /* Flags used to open file */
          231  +  int iChunk,                     /* Chunk to generate filename for */
          232  +  char *zOut                      /* Buffer to write generated name to */
          233  +){
          234  +  memcpy(zOut, zBase, nBase+1);
          235  +  if( iChunk!=0 && iChunk!=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
          236  +    int n = nBase;
          237  +#ifdef SQLITE_ENABLE_8_3_NAMES
          238  +    int i;
          239  +    for(i=n-1; i>0 && i>=n-4 && zOut[i]!='.'; i--){}
          240  +    if( i>=n-4 ) n = i+1;
          241  +    if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
          242  +      /* The extensions on overflow files for main databases are 001, 002,
          243  +       ** 003 and so forth.  To avoid name collisions, add 400 to the 
          244  +       ** extensions of journal files so that they are 401, 402, 403, ....
          245  +       */
          246  +      iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
          247  +    }
          248  +#endif
          249  +    sqlite3_snprintf(4,&zOut[n],"%03d",iChunk);
          250  +  }
   289    251   }
   290    252   
   291    253   /* Compute the filename for the iChunk-th chunk
   292    254   */
   293    255   static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
   294    256     if( iChunk>=pGroup->nReal ){
   295    257       struct multiplexReal *p;
................................................................................
   297    259       if( p==0 ){
   298    260         return SQLITE_NOMEM;
   299    261       }
   300    262       memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal));
   301    263       pGroup->aReal = p;
   302    264       pGroup->nReal = iChunk+1;
   303    265     }
   304         -  if( pGroup->aReal[iChunk].z==0 ){
          266  +  if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
   305    267       char *z;
   306    268       int n = pGroup->nName;
   307         -    pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+3 );
          269  +    pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+4 );
   308    270       if( z==0 ){
   309    271         return SQLITE_NOMEM;
   310    272       }
   311         -    memcpy(z, pGroup->zName, n+1);
   312         -    if( iChunk>0 ){
   313         -#ifdef SQLITE_ENABLE_8_3_NAMES
   314         -      if( n>3 && z[n-3]=='.' ){
   315         -        n--;
   316         -      }else if( n>4 && z[n-4]=='.' ){
   317         -        n -= 2;
   318         -      }
   319         -#endif
   320         -      sqlite3_snprintf(3,&z[n],"%02d",iChunk);
   321         -    }
          273  +    multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z);
   322    274     }
   323    275     return SQLITE_OK;
   324    276   }
   325    277   
   326    278   /* Translate an sqlite3_file* that is really a multiplexGroup* into
   327    279   ** the sqlite3_file* for the underlying original VFS.
          280  +**
          281  +** For chunk 0, the pGroup->flags determines whether or not a new file
          282  +** is created if it does not already exist.  For chunks 1 and higher, the
          283  +** file is created only if createFlag is 1.
   328    284   */
   329    285   static sqlite3_file *multiplexSubOpen(
   330         -  multiplexGroup *pGroup,
   331         -  int iChunk,
   332         -  int *rc,
   333         -  int *pOutFlags
          286  +  multiplexGroup *pGroup,    /* The multiplexor group */
          287  +  int iChunk,                /* Which chunk to open.  0==original file */
          288  +  int *rc,                   /* Result code in and out */
          289  +  int *pOutFlags,            /* Output flags */
          290  +  int createFlag             /* True to create if iChunk>0 */
   334    291   ){
   335    292     sqlite3_file *pSubOpen = 0;
   336    293     sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;        /* Real VFS */
          294  +
          295  +#ifdef SQLITE_ENABLE_8_3_NAMES
          296  +  /* If JOURNAL_8_3_OFFSET is set to (say) 400, then any overflow files are 
          297  +  ** part of a database journal are named db.401, db.402, and so on. A 
          298  +  ** database may therefore not grow to larger than 400 chunks. Attempting
          299  +  ** to open chunk 401 indicates the database is full. */
          300  +  if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
          301  +    sqlite3_log(SQLITE_FULL, "multiplexed chunk overflow: %s", pGroup->zName);
          302  +    *rc = SQLITE_FULL;
          303  +    return 0;
          304  +  }
          305  +#endif
          306  +
   337    307     *rc = multiplexSubFilename(pGroup, iChunk);
   338    308     if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
          309  +    int flags, bExists;
          310  +    flags = pGroup->flags;
          311  +    if( createFlag ){
          312  +      flags |= SQLITE_OPEN_CREATE;
          313  +    }else if( iChunk==0 ){
          314  +      /* Fall through */
          315  +    }else if( pGroup->aReal[iChunk].z==0 ){
          316  +      return 0;
          317  +    }else{
          318  +      *rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[iChunk].z,
          319  +                              SQLITE_ACCESS_EXISTS, &bExists);
          320  +     if( *rc || !bExists ){
          321  +        if( *rc ){
          322  +          sqlite3_log(*rc, "multiplexor.xAccess failure on %s",
          323  +                      pGroup->aReal[iChunk].z);
          324  +        }
          325  +        return 0;
          326  +      }
          327  +      flags &= ~SQLITE_OPEN_CREATE;
          328  +    }
   339    329       pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile );
   340    330       if( pSubOpen==0 ){
   341         -      *rc = SQLITE_NOMEM;
          331  +      *rc = SQLITE_IOERR_NOMEM;
   342    332         return 0;
   343    333       }
   344    334       pGroup->aReal[iChunk].p = pSubOpen;
   345    335       *rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen,
   346         -                          pGroup->flags, pOutFlags);
   347         -    if( *rc!=SQLITE_OK ){
          336  +                          flags, pOutFlags);
          337  +    if( (*rc)!=SQLITE_OK ){
          338  +      sqlite3_log(*rc, "multiplexor.xOpen failure on %s",
          339  +                  pGroup->aReal[iChunk].z);
   348    340         sqlite3_free(pSubOpen);
   349    341         pGroup->aReal[iChunk].p = 0;
   350    342         return 0;
   351    343       }
   352    344     }
   353    345     return pSubOpen;
   354    346   }
   355    347   
          348  +/*
          349  +** Return the size, in bytes, of chunk number iChunk.  If that chunk
          350  +** does not exist, then return 0.  This function does not distingish between
          351  +** non-existant files and zero-length files.
          352  +*/
          353  +static sqlite3_int64 multiplexSubSize(
          354  +  multiplexGroup *pGroup,    /* The multiplexor group */
          355  +  int iChunk,                /* Which chunk to open.  0==original file */
          356  +  int *rc                    /* Result code in and out */
          357  +){
          358  +  sqlite3_file *pSub;
          359  +  sqlite3_int64 sz = 0;
          360  +
          361  +  pSub = multiplexSubOpen(pGroup, iChunk, rc, NULL, 0);
          362  +  if( pSub==0 ) return 0;
          363  +  *rc = pSub->pMethods->xFileSize(pSub, &sz);
          364  +  return sz;
          365  +}    
          366  +
   356    367   /*
   357    368   ** This is the implementation of the multiplex_control() SQL function.
   358    369   */
   359    370   static void multiplexControlFunc(
   360    371     sqlite3_context *context,
   361    372     int argc,
   362    373     sqlite3_value **argv
................................................................................
   416    427     multiplexGroup *pGroup,
   417    428     int iChunk,
   418    429     sqlite3_vfs *pOrigVfs
   419    430   ){
   420    431     sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p;
   421    432     if( pSubOpen ){
   422    433       pSubOpen->pMethods->xClose(pSubOpen);
   423         -    if( pOrigVfs ) pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
          434  +    if( pOrigVfs && pGroup->aReal[iChunk].z ){
          435  +      pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
          436  +    }
   424    437       sqlite3_free(pGroup->aReal[iChunk].p);
   425    438     }
   426    439     sqlite3_free(pGroup->aReal[iChunk].z);
   427    440     memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk]));
   428    441   }
   429    442   
   430    443   /*
................................................................................
   462    475     sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
   463    476     int nName;
   464    477     int sz;
   465    478     char *zToFree = 0;
   466    479   
   467    480     UNUSED_PARAMETER(pVfs);
   468    481     memset(pConn, 0, pVfs->szOsFile);
          482  +  assert( zName || (flags & SQLITE_OPEN_DELETEONCLOSE) );
   469    483   
   470    484     /* We need to create a group structure and manage
   471    485     ** access to this group of files.
   472    486     */
   473    487     multiplexEnter();
   474    488     pMultiplexOpen = (multiplexConn*)pConn;
   475    489   
   476         -  /* If the second argument to this function is NULL, generate a 
   477         -  ** temporary file name to use.  This will be handled by the
   478         -  ** original xOpen method.  We just need to allocate space for
   479         -  ** it.
   480         -  */
   481         -  if( !zName ){
   482         -    zName = zToFree = sqlite3_malloc( pOrigVfs->mxPathname + 10 );
   483         -    if( zName==0 ){
   484         -      rc = SQLITE_NOMEM;
   485         -    }else{
   486         -      rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, zToFree);
   487         -    }
   488         -  }
   489         -
   490    490     if( rc==SQLITE_OK ){
   491    491       /* allocate space for group */
   492         -    nName = multiplexStrlen30(zName);
          492  +    nName = zName ? multiplexStrlen30(zName) : 0;
   493    493       sz = sizeof(multiplexGroup)                             /* multiplexGroup */
   494    494          + nName + 1;                                         /* zName */
   495    495       pGroup = sqlite3_malloc( sz );
   496    496       if( pGroup==0 ){
   497    497         rc = SQLITE_NOMEM;
   498    498       }
   499    499     }
   500    500   
   501    501     if( rc==SQLITE_OK ){
   502    502       /* assign pointers to extra space allocated */
   503         -    char *p = (char *)&pGroup[1];
          503  +    memset(pGroup, 0, sz);
   504    504       pMultiplexOpen->pGroup = pGroup;
   505         -    memset(pGroup, 0, sz);
   506    505       pGroup->bEnabled = -1;
          506  +    pGroup->bTruncate = (flags & SQLITE_OPEN_MAIN_DB)==0;
   507    507       pGroup->szChunk = SQLITE_MULTIPLEX_CHUNK_SIZE;
   508         -    if( flags & SQLITE_OPEN_URI ){
   509         -      const char *zChunkSize;
   510         -      zChunkSize = sqlite3_uri_parameter(zName, "chunksize");
   511         -      if( zChunkSize ){
   512         -        unsigned int n = 0;
   513         -        int i;
   514         -        for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){
   515         -          n = n*10 + zChunkSize[i] - '0';
          508  +
          509  +    if( zName ){
          510  +      char *p = (char *)&pGroup[1];
          511  +      if( flags & SQLITE_OPEN_URI ){
          512  +        const char *zChunkSize;
          513  +        zChunkSize = sqlite3_uri_parameter(zName, "chunksize");
          514  +        if( zChunkSize ){
          515  +          unsigned int n = 0;
          516  +          int i;
          517  +          for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){
          518  +            n = n*10 + zChunkSize[i] - '0';
          519  +          }
          520  +          if( n>0 ){
          521  +            pGroup->szChunk = (n+0xffff)&~0xffff;
          522  +          }else{
          523  +            /* A zero or negative chunksize disabled the multiplexor */
          524  +            pGroup->bEnabled = 0;
          525  +          }
   516    526           }
   517         -        if( n>0 ){
   518         -          pGroup->szChunk = (n+0xffff)&~0xffff;
   519         -        }else{
   520         -          /* A zero or negative chunksize disabled the multiplexor */
   521         -          pGroup->bEnabled = 0;
   522         -        }
          527  +        if( sqlite3_uri_parameter(zName, "truncate") ) pGroup->bTruncate = 1;
          528  +      }
          529  +      pGroup->zName = p;
          530  +      memcpy(pGroup->zName, zName, nName+1);
          531  +      pGroup->nName = nName;
          532  +    }
          533  +    if( pGroup->bEnabled ){
          534  +      /* Make sure that the chunksize is not such that the pending byte
          535  +      ** falls at the end of a chunk.  A region of up to 64K following
          536  +      ** the pending byte is never written, so if the pending byte occurs
          537  +      ** near the end of a chunk, that chunk will be too small. */
          538  +      extern int sqlite3PendingByte;
          539  +      while( (sqlite3PendingByte % pGroup->szChunk)>=(pGroup->szChunk-65536) ){
          540  +        pGroup->szChunk += 65536;
   523    541         }
   524    542       }
   525         -    pGroup->zName = p;
   526         -    /* save off base filename, name length, and original open flags  */
   527         -    memcpy(pGroup->zName, zName, nName+1);
   528         -    pGroup->nName = nName;
   529    543       pGroup->flags = flags;
   530    544       rc = multiplexSubFilename(pGroup, 1);
   531    545       if( rc==SQLITE_OK ){
   532         -      pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags);
          546  +      pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags, 0);
          547  +      if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN;
   533    548       }
   534         -    if( pSubOpen ){
   535         -      int exists, rc2, rc3;
          549  +    if( rc==SQLITE_OK ){
   536    550         sqlite3_int64 sz;
   537    551   
   538         -      rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
   539         -      if( rc2==SQLITE_OK ){
   540         -        /* If the first overflow file exists and if the size of the main file
   541         -        ** is different from the chunk size, that means the chunk size is set
   542         -        ** set incorrectly.  So fix it.
   543         -        **
   544         -        ** Or, if the first overflow file does not exist and the main file is
   545         -        ** larger than the chunk size, that means the chunk size is too small.
   546         -        ** But we have no way of determining the intended chunk size, so 
   547         -        ** just disable the multiplexor all togethre.
   548         -        */
   549         -        rc3 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
   550         -            SQLITE_ACCESS_EXISTS, &exists);
   551         -        if( rc3==SQLITE_OK && exists && sz==(sz&0xffff0000) && sz>0
   552         -            && sz!=pGroup->szChunk ){
   553         -          pGroup->szChunk = sz;
   554         -        }else if( rc3==SQLITE_OK && !exists && sz>pGroup->szChunk ){
   555         -          pGroup->bEnabled = 0;
          552  +      rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
          553  +      if( rc==SQLITE_OK && zName ){
          554  +        int bExists;
          555  +        if( sz==0 ){
          556  +          if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
          557  +            /* If opening a main journal file and the first chunk is zero
          558  +            ** bytes in size, delete any subsequent chunks from the 
          559  +            ** file-system. */
          560  +            int iChunk = 1;
          561  +            do {
          562  +              rc = pOrigVfs->xAccess(pOrigVfs, 
          563  +                  pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists
          564  +              );
          565  +              if( rc==SQLITE_OK && bExists ){
          566  +                rc = pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
          567  +                if( rc==SQLITE_OK ){
          568  +                  rc = multiplexSubFilename(pGroup, ++iChunk);
          569  +                }
          570  +              }
          571  +            }while( rc==SQLITE_OK && bExists );
          572  +          }
          573  +        }else{
          574  +          /* If the first overflow file exists and if the size of the main file
          575  +          ** is different from the chunk size, that means the chunk size is set
          576  +          ** set incorrectly.  So fix it.
          577  +          **
          578  +          ** Or, if the first overflow file does not exist and the main file is
          579  +          ** larger than the chunk size, that means the chunk size is too small.
          580  +          ** But we have no way of determining the intended chunk size, so 
          581  +          ** just disable the multiplexor all togethre.
          582  +          */
          583  +          rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
          584  +              SQLITE_ACCESS_EXISTS, &bExists);
          585  +          bExists = multiplexSubSize(pGroup, 1, &rc)>0;
          586  +          if( rc==SQLITE_OK && bExists  && sz==(sz&0xffff0000) && sz>0
          587  +              && sz!=pGroup->szChunk ){
          588  +            pGroup->szChunk = sz;
          589  +          }else if( rc==SQLITE_OK && !bExists && sz>pGroup->szChunk ){
          590  +            pGroup->bEnabled = 0;
          591  +          }
   556    592           }
   557    593         }
          594  +    }
   558    595   
          596  +    if( rc==SQLITE_OK ){
   559    597         if( pSubOpen->pMethods->iVersion==1 ){
   560    598           pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
   561    599         }else{
   562    600           pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2;
   563    601         }
   564    602         /* place this group at the head of our list */
   565    603         pGroup->pNext = gMultiplex.pGroups;
................................................................................
   580    618   ** It attempts to delete the filename specified.
   581    619   */
   582    620   static int multiplexDelete(
   583    621     sqlite3_vfs *pVfs,         /* The multiplex VFS */
   584    622     const char *zName,         /* Name of file to delete */
   585    623     int syncDir
   586    624   ){
          625  +  int rc;
   587    626     sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
   588         -  return pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
          627  +  rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
          628  +  if( rc==SQLITE_OK ){
          629  +    /* If the main chunk was deleted successfully, also delete any subsequent
          630  +    ** chunks - starting with the last (highest numbered). 
          631  +    */
          632  +    int nName = strlen(zName);
          633  +    char *z;
          634  +    z = sqlite3_malloc(nName + 4);
          635  +    if( z==0 ){
          636  +      rc = SQLITE_IOERR_NOMEM;
          637  +    }else{
          638  +      int iChunk = 0;
          639  +      int bExists;
          640  +      do{
          641  +        multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, ++iChunk, z);
          642  +        rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists);
          643  +      }while( rc==SQLITE_OK && bExists );
          644  +      while( rc==SQLITE_OK && iChunk>1 ){
          645  +        multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, --iChunk, z);
          646  +        rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir);
          647  +      }
          648  +    }
          649  +    sqlite3_free(z);
          650  +  }
          651  +  return rc;
   589    652   }
   590    653   
   591    654   static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){
   592    655     return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, b, c, d);
   593    656   }
   594    657   static int multiplexFullPathname(sqlite3_vfs *a, const char *b, int c, char *d){
   595    658     return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, b, c, d);
................................................................................
   658    721     sqlite3_int64 iOfst
   659    722   ){
   660    723     multiplexConn *p = (multiplexConn*)pConn;
   661    724     multiplexGroup *pGroup = p->pGroup;
   662    725     int rc = SQLITE_OK;
   663    726     multiplexEnter();
   664    727     if( !pGroup->bEnabled ){
   665         -    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
          728  +    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
   666    729       if( pSubOpen==0 ){
   667    730         rc = SQLITE_IOERR_READ;
   668    731       }else{
   669    732         rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst);
   670    733       }
   671    734     }else{
   672    735       while( iAmt > 0 ){
   673    736         int i = (int)(iOfst / pGroup->szChunk);
   674         -      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
          737  +      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
   675    738         if( pSubOpen ){
   676    739           int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk;
   677    740           if( extra<0 ) extra = 0;
   678    741           iAmt -= extra;
   679    742           rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt,
   680    743                                          iOfst % pGroup->szChunk);
   681    744           if( rc!=SQLITE_OK ) break;
................................................................................
   703    766     sqlite3_int64 iOfst
   704    767   ){
   705    768     multiplexConn *p = (multiplexConn*)pConn;
   706    769     multiplexGroup *pGroup = p->pGroup;
   707    770     int rc = SQLITE_OK;
   708    771     multiplexEnter();
   709    772     if( !pGroup->bEnabled ){
   710         -    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
          773  +    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
   711    774       if( pSubOpen==0 ){
   712    775         rc = SQLITE_IOERR_WRITE;
   713    776       }else{
   714    777         rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst);
   715    778       }
   716    779     }else{
   717         -    while( iAmt > 0 ){
          780  +    while( rc==SQLITE_OK && iAmt>0 ){
   718    781         int i = (int)(iOfst / pGroup->szChunk);
   719         -      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
          782  +      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
   720    783         if( pSubOpen ){
   721    784           int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) -
   722    785                       pGroup->szChunk;
   723    786           if( extra<0 ) extra = 0;
   724    787           iAmt -= extra;
   725    788           rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt,
   726    789                                           iOfst % pGroup->szChunk);
   727         -        if( rc!=SQLITE_OK ) break;
   728    790           pBuf = (char *)pBuf + iAmt;
   729    791           iOfst += iAmt;
   730    792           iAmt = extra;
   731         -      }else{
   732         -        rc = SQLITE_IOERR_WRITE;
   733         -        break;
   734    793         }
   735    794       }
   736    795     }
   737    796     multiplexLeave();
   738    797     return rc;
   739    798   }
   740    799   
................................................................................
   744    803   */
   745    804   static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
   746    805     multiplexConn *p = (multiplexConn*)pConn;
   747    806     multiplexGroup *pGroup = p->pGroup;
   748    807     int rc = SQLITE_OK;
   749    808     multiplexEnter();
   750    809     if( !pGroup->bEnabled ){
   751         -    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
          810  +    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
   752    811       if( pSubOpen==0 ){
   753    812         rc = SQLITE_IOERR_TRUNCATE;
   754    813       }else{
   755    814         rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
   756    815       }
   757    816     }else{
   758         -    int rc2;
   759    817       int i;
          818  +    int iBaseGroup = (int)(size / pGroup->szChunk);
   760    819       sqlite3_file *pSubOpen;
   761    820       sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
   762    821       /* delete the chunks above the truncate limit */
   763         -    for(i=(int)(size / pGroup->szChunk)+1; i<pGroup->nReal; i++){
   764         -      multiplexSubClose(pGroup, i, pOrigVfs);
          822  +    for(i = pGroup->nReal-1; i>iBaseGroup && rc==SQLITE_OK; i--){
          823  +      if( pGroup->bTruncate ){
          824  +        multiplexSubClose(pGroup, i, pOrigVfs);
          825  +      }else{
          826  +        pSubOpen = multiplexSubOpen(pGroup, i, &rc, 0, 0);
          827  +        if( pSubOpen ){
          828  +          rc = pSubOpen->pMethods->xTruncate(pSubOpen, 0);
          829  +        }
          830  +      }
   765    831       }
   766         -    pSubOpen = multiplexSubOpen(pGroup, (int)(size/pGroup->szChunk), &rc2,0);
   767         -    if( pSubOpen ){
   768         -      rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk);
   769         -      if( rc2!=SQLITE_OK ) rc = rc2;
   770         -    }else{
   771         -      rc = SQLITE_IOERR_TRUNCATE;
          832  +    if( rc==SQLITE_OK ){
          833  +      pSubOpen = multiplexSubOpen(pGroup, iBaseGroup, &rc, 0, 0);
          834  +      if( pSubOpen ){
          835  +        rc = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk);
          836  +      }
   772    837       }
          838  +    if( rc ) rc = SQLITE_IOERR_TRUNCATE;
   773    839     }
   774    840     multiplexLeave();
   775    841     return rc;
   776    842   }
   777    843   
   778    844   /* Pass xSync requests through to the original VFS without change
   779    845   */
................................................................................
   797    863   /* Pass xFileSize requests through to the original VFS.
   798    864   ** Aggregate the size of all the chunks before returning.
   799    865   */
   800    866   static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
   801    867     multiplexConn *p = (multiplexConn*)pConn;
   802    868     multiplexGroup *pGroup = p->pGroup;
   803    869     int rc = SQLITE_OK;
   804         -  int rc2;
   805    870     int i;
   806    871     multiplexEnter();
   807    872     if( !pGroup->bEnabled ){
   808         -    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
          873  +    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
   809    874       if( pSubOpen==0 ){
   810    875         rc = SQLITE_IOERR_FSTAT;
   811    876       }else{
   812    877         rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize);
   813    878       }
   814    879     }else{
   815         -    sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;
   816    880       *pSize = 0;
   817         -    for(i=0; 1; i++){
   818         -      sqlite3_file *pSubOpen = 0;
   819         -      int exists = 0;
   820         -      rc = multiplexSubFilename(pGroup, i);
   821         -      if( rc ) break;
   822         -      rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[i].z,
   823         -          SQLITE_ACCESS_EXISTS, &exists);
   824         -      if( rc2==SQLITE_OK && exists){
   825         -        /* if it exists, open it */
   826         -        pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
   827         -      }else{
   828         -        /* stop at first "gap" */
   829         -        break;
   830         -      }
   831         -      if( pSubOpen ){
   832         -        sqlite3_int64 sz;
   833         -        rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
   834         -        if( rc2!=SQLITE_OK ){
   835         -          rc = rc2;
   836         -        }else{
   837         -          if( sz>pGroup->szChunk ){
   838         -            rc = SQLITE_IOERR_FSTAT;
   839         -          }
   840         -          *pSize += sz;
   841         -        }
   842         -      }else{
   843         -        break;
   844         -      }
          881  +    for(i=0; rc==SQLITE_OK; i++){
          882  +      sqlite3_int64 sz = multiplexSubSize(pGroup, i, &rc);
          883  +      if( sz==0 ) break;
          884  +      *pSize = i*(sqlite3_int64)pGroup->szChunk + sz;
   845    885       }
   846    886     }
   847    887     multiplexLeave();
   848    888     return rc;
   849    889   }
   850    890   
   851    891   /* Pass xLock requests through to the original VFS unchanged.
   852    892   */
   853    893   static int multiplexLock(sqlite3_file *pConn, int lock){
   854    894     multiplexConn *p = (multiplexConn*)pConn;
   855    895     int rc;
   856         -  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
          896  +  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
   857    897     if( pSubOpen ){
   858    898       return pSubOpen->pMethods->xLock(pSubOpen, lock);
   859    899     }
   860    900     return SQLITE_BUSY;
   861    901   }
   862    902   
   863    903   /* Pass xUnlock requests through to the original VFS unchanged.
   864    904   */
   865    905   static int multiplexUnlock(sqlite3_file *pConn, int lock){
   866    906     multiplexConn *p = (multiplexConn*)pConn;
   867    907     int rc;
   868         -  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
          908  +  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
   869    909     if( pSubOpen ){
   870    910       return pSubOpen->pMethods->xUnlock(pSubOpen, lock);
   871    911     }
   872    912     return SQLITE_IOERR_UNLOCK;
   873    913   }
   874    914   
   875    915   /* Pass xCheckReservedLock requests through to the original VFS unchanged.
   876    916   */
   877    917   static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){
   878    918     multiplexConn *p = (multiplexConn*)pConn;
   879    919     int rc;
   880         -  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
          920  +  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
   881    921     if( pSubOpen ){
   882    922       return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
   883    923     }
   884    924     return SQLITE_IOERR_CHECKRESERVEDLOCK;
   885    925   }
   886    926   
   887    927   /* Pass xFileControl requests through to the original VFS unchanged,
................................................................................
   921    961         break;
   922    962       case SQLITE_FCNTL_SIZE_HINT:
   923    963       case SQLITE_FCNTL_CHUNK_SIZE:
   924    964         /* no-op these */
   925    965         rc = SQLITE_OK;
   926    966         break;
   927    967       default:
   928         -      pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
          968  +      pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
   929    969         if( pSubOpen ){
   930    970           rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
          971  +        if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
          972  +         *(char**)pArg = sqlite3_mprintf("multiplex/%z", *(char**)pArg);
          973  +        }
   931    974         }
   932    975         break;
   933    976     }
   934    977     return rc;
   935    978   }
   936    979   
   937    980   /* Pass xSectorSize requests through to the original VFS unchanged.
   938    981   */
   939    982   static int multiplexSectorSize(sqlite3_file *pConn){
   940    983     multiplexConn *p = (multiplexConn*)pConn;
   941    984     int rc;
   942         -  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   943         -  if( pSubOpen ){
          985  +  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
          986  +  if( pSubOpen && pSubOpen->pMethods->xSectorSize ){
   944    987       return pSubOpen->pMethods->xSectorSize(pSubOpen);
   945    988     }
   946    989     return DEFAULT_SECTOR_SIZE;
   947    990   }
   948    991   
   949    992   /* Pass xDeviceCharacteristics requests through to the original VFS unchanged.
   950    993   */
   951    994   static int multiplexDeviceCharacteristics(sqlite3_file *pConn){
   952    995     multiplexConn *p = (multiplexConn*)pConn;
   953    996     int rc;
   954         -  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
          997  +  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
   955    998     if( pSubOpen ){
   956    999       return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen);
   957   1000     }
   958   1001     return 0;
   959   1002   }
   960   1003   
   961   1004   /* Pass xShmMap requests through to the original VFS unchanged.
................................................................................
   965   1008     int iRegion,                    /* Region to retrieve */
   966   1009     int szRegion,                   /* Size of regions */
   967   1010     int bExtend,                    /* True to extend file if necessary */
   968   1011     void volatile **pp              /* OUT: Mapped memory */
   969   1012   ){
   970   1013     multiplexConn *p = (multiplexConn*)pConn;
   971   1014     int rc;
   972         -  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
         1015  +  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
   973   1016     if( pSubOpen ){
   974   1017       return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp);
   975   1018     }
   976   1019     return SQLITE_IOERR;
   977   1020   }
   978   1021   
   979   1022   /* Pass xShmLock requests through to the original VFS unchanged.
................................................................................
   982   1025     sqlite3_file *pConn,       /* Database file holding the shared memory */
   983   1026     int ofst,                  /* First lock to acquire or release */
   984   1027     int n,                     /* Number of locks to acquire or release */
   985   1028     int flags                  /* What to do with the lock */
   986   1029   ){
   987   1030     multiplexConn *p = (multiplexConn*)pConn;
   988   1031     int rc;
   989         -  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
         1032  +  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
   990   1033     if( pSubOpen ){
   991   1034       return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags);
   992   1035     }
   993   1036     return SQLITE_BUSY;
   994   1037   }
   995   1038   
   996   1039   /* Pass xShmBarrier requests through to the original VFS unchanged.
   997   1040   */
   998   1041   static void multiplexShmBarrier(sqlite3_file *pConn){
   999   1042     multiplexConn *p = (multiplexConn*)pConn;
  1000   1043     int rc;
  1001         -  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
         1044  +  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
  1002   1045     if( pSubOpen ){
  1003   1046       pSubOpen->pMethods->xShmBarrier(pSubOpen);
  1004   1047     }
  1005   1048   }
  1006   1049   
  1007   1050   /* Pass xShmUnmap requests through to the original VFS unchanged.
  1008   1051   */
  1009   1052   static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){
  1010   1053     multiplexConn *p = (multiplexConn*)pConn;
  1011   1054     int rc;
  1012         -  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
         1055  +  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
  1013   1056     if( pSubOpen ){
  1014   1057       return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
  1015   1058     }
  1016   1059     return SQLITE_OK;
  1017   1060   }
  1018   1061   
  1019   1062   /************************** Public Interfaces *****************************/
................................................................................
  1187   1230     UNUSED_PARAMETER(objv);
  1188   1231   
  1189   1232     pResult = Tcl_NewObj();
  1190   1233     multiplexEnter();
  1191   1234     for(pGroup=gMultiplex.pGroups; pGroup; pGroup=pGroup->pNext){
  1192   1235       pGroupTerm = Tcl_NewObj();
  1193   1236   
  1194         -    pGroup->zName[pGroup->nName] = '\0';
  1195         -    Tcl_ListObjAppendElement(interp, pGroupTerm,
         1237  +    if( pGroup->zName ){
         1238  +      pGroup->zName[pGroup->nName] = '\0';
         1239  +      Tcl_ListObjAppendElement(interp, pGroupTerm,
  1196   1240             Tcl_NewStringObj(pGroup->zName, -1));
         1241  +    }else{
         1242  +      Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewObj());
         1243  +    }
  1197   1244       Tcl_ListObjAppendElement(interp, pGroupTerm,
  1198   1245             Tcl_NewIntObj(pGroup->nName));
  1199   1246       Tcl_ListObjAppendElement(interp, pGroupTerm,
  1200   1247             Tcl_NewIntObj(pGroup->flags));
  1201   1248   
  1202   1249       /* count number of chunks with open handles */
  1203   1250       for(i=0; i<pGroup->nReal; i++){

Changes to src/test_osinst.c.

   385    385   }
   386    386   
   387    387   /*
   388    388   ** File control method. For custom operations on an vfslog-file.
   389    389   */
   390    390   static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){
   391    391     VfslogFile *p = (VfslogFile *)pFile;
   392         -  return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
          392  +  int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
          393  +  if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
          394  +    *(char**)pArg = sqlite3_mprintf("vfslog/%z", *(char**)pArg);
          395  +  }
          396  +  return rc;
   393    397   }
   394    398   
   395    399   /*
   396    400   ** Return the sector-size in bytes for an vfslog-file.
   397    401   */
   398    402   static int vfslogSectorSize(sqlite3_file *pFile){
   399    403     int rc;

Changes to src/test_quota.c.

   585    585     return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
   586    586   }
   587    587   
   588    588   /* Pass xFileControl requests through to the original VFS unchanged.
   589    589   */
   590    590   static int quotaFileControl(sqlite3_file *pConn, int op, void *pArg){
   591    591     sqlite3_file *pSubOpen = quotaSubOpen(pConn);
   592         -  return pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
          592  +  int rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
          593  +  if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
          594  +    *(char**)pArg = sqlite3_mprintf("quota/%z", *(char**)pArg);
          595  +  }
          596  +  return rc;
   593    597   }
   594    598   
   595    599   /* Pass xSectorSize requests through to the original VFS unchanged.
   596    600   */
   597    601   static int quotaSectorSize(sqlite3_file *pConn){
   598    602     sqlite3_file *pSubOpen = quotaSubOpen(pConn);
   599    603     return pSubOpen->pMethods->xSectorSize(pSubOpen);

Changes to src/test_stat.c.

   365    365     Btree *pBt = pTab->db->aDb[0].pBt;
   366    366     Pager *pPager = sqlite3BtreePager(pBt);
   367    367     sqlite3_file *fd;
   368    368     sqlite3_int64 x[2];
   369    369   
   370    370     /* The default page size and offset */
   371    371     pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
   372         -  pCsr->iOffset = pCsr->szPage * (pCsr->iPageno - 1);
          372  +  pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
   373    373   
   374    374     /* If connected to a ZIPVFS backend, override the page size and
   375    375     ** offset with actual values obtained from ZIPVFS.
   376    376     */
   377    377     fd = sqlite3PagerFile(pPager);
   378    378     x[0] = pCsr->iPageno;
   379    379     if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){

Changes to src/test_vfstrace.c.

   467    467       case SQLITE_FCNTL_CHUNK_SIZE: {
   468    468         sqlite3_snprintf(sizeof(zBuf), zBuf, "CHUNK_SIZE,%d", *(int*)pArg);
   469    469         zOp = zBuf;
   470    470         break;
   471    471       }
   472    472       case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER";       break;
   473    473       case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED";       break;
          474  +    case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY";   break;
          475  +    case SQLITE_FCNTL_PERSIST_WAL:  zOp = "PERSIST_WAL";        break;
          476  +    case SQLITE_FCNTL_OVERWRITE:    zOp = "OVERWRITE";          break;
          477  +    case SQLITE_FCNTL_VFSNAME:      zOp = "VFSNAME";            break;
   474    478       case 0xca093fa0:                zOp = "DB_UNCHANGED";       break;
   475    479       default: {
   476    480         sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op);
   477    481         zOp = zBuf;
   478    482         break;
   479    483       }
   480    484     }
   481    485     vfstrace_printf(pInfo, "%s.xFileControl(%s,%s)",
   482    486                     pInfo->zVfsName, p->zFName, zOp);
   483    487     rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
   484    488     vfstrace_print_errcode(pInfo, " -> %s\n", rc);
          489  +  if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
          490  +    *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z",
          491  +                                    pInfo->zVfsName, *(char**)pArg);
          492  +  }
   485    493     return rc;
   486    494   }
   487    495   
   488    496   /*
   489    497   ** Return the sector-size in bytes for an vfstrace-file.
   490    498   */
   491    499   static int vfstraceSectorSize(sqlite3_file *pFile){

Changes to src/util.c.

  1165   1165   ** do the suffix shortening regardless of URI parameter.
  1166   1166   **
  1167   1167   ** Examples:
  1168   1168   **
  1169   1169   **     test.db-journal    =>   test.nal
  1170   1170   **     test.db-wal        =>   test.wal
  1171   1171   **     test.db-shm        =>   test.shm
         1172  +**     test.db-mj7f3319fa =>   test.9fa
  1172   1173   */
  1173   1174   void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
  1174   1175   #if SQLITE_ENABLE_8_3_NAMES<2
  1175   1176     const char *zOk;
  1176   1177     zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
  1177   1178     if( zOk && sqlite3GetBoolean(zOk) )
  1178   1179   #endif

Changes to src/vdbeaux.c.

  1820   1820       sqlite3_vfs *pVfs = db->pVfs;
  1821   1821       int needSync = 0;
  1822   1822       char *zMaster = 0;   /* File-name for the master journal */
  1823   1823       char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
  1824   1824       sqlite3_file *pMaster = 0;
  1825   1825       i64 offset = 0;
  1826   1826       int res;
         1827  +    int retryCount = 0;
         1828  +    int nMainFile;
  1827   1829   
  1828   1830       /* Select a master journal file name */
         1831  +    nMainFile = sqlite3Strlen30(zMainFile);
         1832  +    zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XX", zMainFile);
         1833  +    if( zMaster==0 ) return SQLITE_NOMEM;
  1829   1834       do {
  1830   1835         u32 iRandom;
  1831         -      sqlite3DbFree(db, zMaster);
         1836  +      if( retryCount++>100 ){
         1837  +        sqlite3_log(SQLITE_FULL, "cannot find unique master-journal");
         1838  +        sqlite3OsDelete(pVfs, zMaster, 0);
         1839  +        break;
         1840  +      }
  1832   1841         sqlite3_randomness(sizeof(iRandom), &iRandom);
  1833         -      zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, iRandom&0x7fffffff);
  1834         -      if( !zMaster ){
  1835         -        return SQLITE_NOMEM;
  1836         -      }
         1842  +      sqlite3_snprintf(13, &zMaster[nMainFile], "-mj%06X9%02X",
         1843  +                               (iRandom>>8)&0xffffff, iRandom&0xff);
         1844  +      /* The antipenultimate character of the master journal name must
         1845  +      ** be "9" to avoid name collisions when using 8+3 filenames. */
         1846  +      assert( zMaster[sqlite3Strlen30(zMaster)-3]=='9' );
  1837   1847         sqlite3FileSuffix3(zMainFile, zMaster);
  1838   1848         rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
  1839   1849       }while( rc==SQLITE_OK && res );
  1840   1850       if( rc==SQLITE_OK ){
  1841   1851         /* Open the master journal. */
  1842   1852         rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster, 
  1843   1853             SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|

Added test/bigfile2.test.

            1  +# 2011 December 20
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this script testing the ability of SQLite to handle database
           13  +# files larger than 4GB.
           14  +#
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +set testprefix bigfile2
           19  +
           20  +# Create a small database.
           21  +#
           22  +do_execsql_test 1.1 {
           23  +  CREATE TABLE t1(a, b);
           24  +  INSERT INTO t1 VALUES(1, 2);
           25  +}
           26  +
           27  +# Pad the file out to 4GB in size. Then clear the file-size field in the
           28  +# db header. This will cause SQLite to assume that the first 4GB of pages
           29  +# are actually in use and new pages will be appended to the file.
           30  +#
           31  +db close
           32  +if {[catch {fake_big_file 4096 [pwd]/test.db} msg]} {
           33  +  puts "**** Unable to create a file larger than 4096 MB. *****"
           34  +  finish_test
           35  +  return
           36  +}
           37  +hexio_write test.db 28 00000000
           38  +
           39  +do_test 1.2 {
           40  +  file size test.db
           41  +} [expr 14 + 4096 * (1<<20)]
           42  +
           43  +# Now insert a large row. The overflow pages will be located past the 4GB
           44  +# boundary. Then, after opening and closing the database, test that the row
           45  +# can be read back in. 
           46  +# 
           47  +set str [string repeat k 30000]
           48  +do_test 1.3 {
           49  +  sqlite3 db test.db
           50  +  execsql { INSERT INTO t1 VALUES(3, $str) }
           51  +  db close
           52  +  sqlite3 db test.db
           53  +  db one { SELECT b FROM t1 WHERE a = 3 }
           54  +} $str
           55  +
           56  +db close
           57  +file delete test.db
           58  +
           59  +finish_test

Changes to test/fts3auto.test.

   569    569   #--------------------------------------------------------------------------
   570    570   # The following test cases - fts3auto-5.* - focus on using prefix indexes.
   571    571   #
   572    572   set chunkconfig [fts3_configure_incr_load 1 1]
   573    573   foreach {tn create pending} {
   574    574     1    "fts4(a, b)"                                  1
   575    575     2    "fts4(a, b, order=ASC, prefix=1)"             1
   576         -  3    "fts4(a, b, order=ASC,  prefix=1,3)"          0
   577         -  4    "fts4(a, b, order=DESC, prefix=2,4)"          0
   578         -  5    "fts4(a, b, order=DESC, prefix=1)"            0
   579         -  6    "fts4(a, b, order=ASC,  prefix=1,3)"          0
          576  +  3    "fts4(a, b, order=ASC,  prefix=\"1,3\")"      0
          577  +  4    "fts4(a, b, order=DESC, prefix=\"2,4\")"      0
          578  +  5    "fts4(a, b, order=DESC, prefix=\"1\")"        0
          579  +  6    "fts4(a, b, order=ASC,  prefix=\"1,3\")"      0
   580    580   } {
   581    581   
   582    582     execsql [subst {
   583    583       DROP TABLE IF EXISTS t1;
   584    584       CREATE VIRTUAL TABLE t1 USING $create;
   585    585     }]
   586    586   

Added test/fts3prefix2.test.

            1  +# 2012 January 25
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#*************************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this script is testing the FTS3 module.
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +set testprefix fts3prefix2
           18  +
           19  +ifcapable !fts3 {
           20  +  finish_test
           21  +  return
           22  +}
           23  +
           24  +do_execsql_test 1.0 { PRAGMA page_size = 512 }
           25  +do_execsql_test 1.1 { 
           26  +  CREATE VIRTUAL TABLE t1 USING fts4(x, prefix="2,3");
           27  +
           28  +  BEGIN;
           29  +    INSERT INTO t1 VALUES('T TX T TX T TX T TX T TX');
           30  +    INSERT INTO t1 SELECT * FROM t1;                       -- 2
           31  +    INSERT INTO t1 SELECT * FROM t1;                       -- 4
           32  +    INSERT INTO t1 SELECT * FROM t1;                       -- 8
           33  +    INSERT INTO t1 SELECT * FROM t1;                       -- 16
           34  +    INSERT INTO t1 SELECT * FROM t1;                       -- 32
           35  +    INSERT INTO t1 SELECT * FROM t1;                       -- 64
           36  +    INSERT INTO t1 SELECT * FROM t1;                       -- 128
           37  +    INSERT INTO t1 SELECT * FROM t1;                       -- 256
           38  +    INSERT INTO t1 SELECT * FROM t1;                       -- 512
           39  +    INSERT INTO t1 SELECT * FROM t1;                       -- 1024
           40  +    INSERT INTO t1 SELECT * FROM t1;                       -- 2048
           41  +  COMMIT;
           42  +}
           43  +
           44  +do_execsql_test 1.2 {
           45  +  INSERT INTO t1 SELECT * FROM t1 LIMIT 10;
           46  +  INSERT INTO t1 SELECT * FROM t1 LIMIT 10;
           47  +  INSERT INTO t1 SELECT * FROM t1 LIMIT 10;
           48  +  DELETE FROM t1 WHERE docid > 5;
           49  +}
           50  +
           51  +do_execsql_test 1.3 {
           52  +  SELECT * FROM t1 WHERE t1 MATCH 'T*';
           53  +} {
           54  +  {T TX T TX T TX T TX T TX}
           55  +  {T TX T TX T TX T TX T TX}
           56  +  {T TX T TX T TX T TX T TX}
           57  +  {T TX T TX T TX T TX T TX}
           58  +  {T TX T TX T TX T TX T TX}
           59  +}
           60  +
           61  +finish_test
           62  +

Changes to test/multiplex.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
    15     15   source $testdir/malloc_common.tcl
           16  +
           17  +# The tests in this file assume that SQLite is compiled without
           18  +# ENABLE_8_3_NAMES.
           19  +#
           20  +ifcapable 8_3_names {
           21  +  puts -nonewline "SQLite compiled with SQLITE_ENABLE_8_3_NAMES. "
           22  +  puts            "Skipping tests multiplex-*."
           23  +  finish_test
           24  +  return
           25  +}
    16     26   
    17     27   set g_chunk_size [ expr ($::SQLITE_MAX_PAGE_SIZE*16384) ]
    18     28   set g_max_chunks 32
    19     29   
    20     30   # This handles appending the chunk number
    21     31   # to the end of the filename.  if 
    22     32   # SQLITE_MULTIPLEX_EXT_OVWR is defined, then
    23     33   # it overwrites the last 2 bytes of the 
    24     34   # file name with the chunk number.
    25     35   proc multiplex_name {name chunk} {
    26     36     if {$chunk==0} { return $name }
    27         -  set num [format "%02d" $chunk]
           37  +  set num [format "%03d" $chunk]
    28     38     ifcapable {multiplex_ext_overwrite} {
    29     39       set name [string range $name 0 [expr [string length $name]-2-1]]
    30     40     }
    31     41     return $name$num
    32     42   }
    33     43   
    34     44   # This saves off the parameters and calls the 
................................................................................
   142    152   #   multiplex-2.7.*: Disable/enable tests.
   143    153   #
   144    154   
   145    155   sqlite3_multiplex_initialize "" 1
   146    156   multiplex_set db main 32768 16
   147    157   
   148    158   forcedelete test.x
          159  +foreach f [glob -nocomplain {test.x*[0-9][0-9][0-9]}] {
          160  +  forcedelete $f
          161  +}
   149    162   do_test multiplex-2.1.2 {
   150    163     sqlite3 db test.x
   151    164     execsql {
   152    165       PRAGMA page_size=1024;
   153    166       PRAGMA auto_vacuum=OFF;
   154    167       PRAGMA journal_mode=DELETE;
   155    168     }
................................................................................
   178    191   do_test multiplex-2.4.1 {
   179    192     sqlite3_multiplex_shutdown
   180    193   } {SQLITE_MISUSE}
   181    194   do_test multiplex-2.4.2 {
   182    195     execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
   183    196   } {}
   184    197   do_test multiplex-2.4.4 { file size [multiplex_name test.x 0] } {7168}
   185         -do_test multiplex-2.4.99 {
          198  +do_test multiplex-2.4.5 {
          199  +  db close
          200  +  sqlite3 db test.x
          201  +  db eval vacuum
   186    202     db close
          203  +  glob test.x*
          204  +} {test.x}
          205  +do_test multiplex-2.4.99 {
   187    206     sqlite3_multiplex_shutdown
   188    207   } {SQLITE_OK}
   189         -
   190    208   
   191    209   do_test multiplex-2.5.1 {
   192    210     multiplex_delete test.x
   193    211     sqlite3_multiplex_initialize "" 1
   194    212     sqlite3 db test.x
   195    213     multiplex_set db main 4096 16
   196    214   } {SQLITE_OK}

Added test/multiplex2.test.

            1  +# 2010 October 29
            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  +
           13  +set testdir [file dirname $argv0]
           14  +source $testdir/tester.tcl
           15  +source $testdir/malloc_common.tcl
           16  +source $testdir/lock_common.tcl
           17  +set testprefix multiplex2
           18  +db close
           19  +
           20  +do_multiclient_test tn {
           21  +  foreach f [glob -nocomplain test.*] { forcedelete $f }
           22  +
           23  +  code1 { catch { sqlite3_multiplex_initialize "" 0 } }
           24  +  code2 { catch { sqlite3_multiplex_initialize "" 0 } }
           25  +
           26  +  code1 { db close }
           27  +  code2 { db2 close }
           28  +
           29  +  code1 { sqlite3 db test.db -vfs multiplex }
           30  +  code2 { sqlite3 db2 test.db -vfs multiplex }
           31  +
           32  +  code1 { sqlite3_multiplex_control db main chunk_size [expr 1024*1024] }
           33  +  code2 { sqlite3_multiplex_control db2 main chunk_size [expr 1024*1024] }
           34  +
           35  +  sql1 {
           36  +    CREATE TABLE t1(a, b);
           37  +    INSERT INTO t1 VALUES(randomblob(10), randomblob(4000));          --    1
           38  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --    2
           39  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --    4
           40  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --    8
           41  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   16
           42  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   32
           43  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   64
           44  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  128
           45  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  256
           46  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  512
           47  +    SELECT count(*) FROM t1;
           48  +  } 
           49  +
           50  +  do_test 1.$tn.1 { sql1 { SELECT count(*) FROM t1 } } 512
           51  +  do_test 1.$tn.2 { sql2 { SELECT count(*) FROM t1 } } 512
           52  +  sql2 { DELETE FROM t1 ; VACUUM }
           53  +  do_test 1.$tn.3 { sql1 { SELECT count(*) FROM t1 } } 0
           54  +
           55  +  sql1 {
           56  +    INSERT INTO t1 VALUES(randomblob(10), randomblob(4000));          --    1
           57  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --    2
           58  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --    4
           59  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --    8
           60  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   16
           61  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   32
           62  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   64
           63  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  128
           64  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  256
           65  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  512
           66  +    SELECT count(*) FROM t1;
           67  +  }
           68  +
           69  +  do_test 1.$tn.4 { sql2 { SELECT count(*) FROM t1 } } 512
           70  +}
           71  +
           72  +catch {db close}
           73  +foreach f [glob -nocomplain test.*] { forcedelete $f }
           74  +
           75  +ifcapable 8_3_names {
           76  +  sqlite3 db test.db -vfs multiplex
           77  +  sqlite3_multiplex_control db main chunk_size [expr 256*1024]
           78  +
           79  +  # Insert 512 * 256K (128MB) of data. If each row is around 4K, this means
           80  +  # we need 32768 rows.
           81  +  do_catchsql_test 2.1 {
           82  +    CREATE TABLE t1(a, b);
           83  +    INSERT INTO t1 VALUES(randomblob(10), randomblob(4000));          --    1
           84  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --    2
           85  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --    4
           86  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --    8
           87  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   16
           88  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   32
           89  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   64
           90  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  128
           91  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  256
           92  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  512
           93  +
           94  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   1K
           95  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   2K
           96  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   4K
           97  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --   8K
           98  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  16K
           99  +    INSERT INTO t1 SELECT randomblob(10), randomblob(4000) FROM t1;   --  32K
          100  +  
          101  +  } {1 {database or disk is full}}
          102  +
          103  +  do_execsql_test 2.2 {
          104  +    UPDATE t1 SET a=randomblob(9), b=randomblob(3900);
          105  +    PRAGMA integrity_check;
          106  +  } ok
          107  +
          108  +  db close
          109  +  sqlite3 db test.db -vfs multiplex
          110  +  sqlite3_multiplex_control db main chunk_size [expr 256*1024]
          111  +
          112  +  do_execsql_test 2.3 {
          113  +    PRAGMA integrity_check;
          114  +  } ok
          115  +}
          116  +
          117  +catch { db close }
          118  +catch { sqlite3_multiplex_shutdown }
          119  +finish_test

Added test/multiplex3.test.

            1  +
            2  +# 2011 December 13
            3  +#
            4  +# The author disclaims copyright to this source code.  In place of
            5  +# a legal notice, here is a blessing:
            6  +#
            7  +#    May you do good and not evil.
            8  +#    May you find forgiveness for yourself and forgive others.
            9  +#    May you share freely, never taking more than you give.
           10  +#
           11  +#***********************************************************************
           12  +#
           13  +# This file contains tests for error (IO, OOM etc.) handling when using
           14  +# the multiplexor extension with 8.3 filenames.
           15  +#
           16  +
           17  +set testdir [file dirname $argv0]
           18  +source $testdir/tester.tcl
           19  +source $testdir/malloc_common.tcl
           20  +set ::testprefix multiplex3
           21  +
           22  +ifcapable !8_3_names {
           23  +  puts -nonewline "SQLite compiled without SQLITE_ENABLE_8_3_NAMES. "
           24  +  puts            "Skipping tests zipvfsD-*."
           25  +  finish_test
           26  +  return
           27  +}
           28  +
           29  +db close
           30  +sqlite3_shutdown
           31  +sqlite3_config_uri 1
           32  +autoinstall_test_functions
           33  +
           34  +sqlite3_multiplex_initialize "" 1
           35  +
           36  +proc destroy_vfs_stack {} {
           37  +  generic_unregister stack
           38  +  sqlite3_multiplex_shutdown
           39  +}
           40  +
           41  +proc multiplex_delete_db {} {
           42  +  forcedelete test.db
           43  +  for {set i 1} {$i <= 1000} {incr i} {
           44  +    forcedelete test.[format %03d $i]
           45  +  }
           46  +}
           47  +
           48  +# Procs to save and restore the current muliplexed database.
           49  +#
           50  +proc multiplex_save_db {} {
           51  +  foreach f [glob -nocomplain sv_test.*] { forcedelete $f }
           52  +  foreach f [glob -nocomplain test.*]    { forcecopy $f "sv_$f" }
           53  +}
           54  +proc multiplex_restore_db {} {
           55  +  foreach f [glob -nocomplain test.*]    {forcedelete $f}
           56  +  foreach f [glob -nocomplain sv_test.*] {forcecopy $f [string range $f 3 end]} }
           57  +
           58  +proc setup_and_save_db {} {
           59  +  multiplex_delete_db
           60  +  sqlite3 db file:test.db?8_3_names=1
           61  +  sqlite3_multiplex_control db main chunk_size [expr 256*1024]
           62  +  execsql {
           63  +    CREATE TABLE t1(a PRIMARY KEY, b);
           64  +    INSERT INTO t1 VALUES(randomblob(15), randomblob(2000));
           65  +    INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    --   2
           66  +    INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    --   4
           67  +    INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    --   8
           68  +    INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    --  16
           69  +    INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    --  32
           70  +    INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    --  64
           71  +    INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    -- 128
           72  +    INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    -- 256
           73  +    INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    -- 512
           74  +  }
           75  +  set ::cksum1 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}]
           76  +  db close
           77  +  multiplex_save_db
           78  +}
           79  +
           80  +do_test 1.0 { setup_and_save_db } {}
           81  +do_faultsim_test 1 -prep {
           82  +  multiplex_restore_db
           83  +  sqlite3 db file:test.db?8_3_names=1
           84  +  sqlite3_multiplex_control db main chunk_size [expr 256*1024]
           85  +} -body {
           86  +  execsql {
           87  +    UPDATE t1 SET a=randomblob(12), b=randomblob(1500) WHERE (rowid%32)=0
           88  +  }
           89  +} -test {
           90  +  faultsim_test_result {0 {}}
           91  +  if {$testrc!=0} {
           92  +    set cksum2 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}]
           93  +    if {$cksum2 != $::cksum1} { error "data mismatch" }
           94  +  }
           95  +}
           96  +
           97  +#-------------------------------------------------------------------------
           98  +# The following tests verify that hot-journal rollback works. As follows:
           99  +#
          100  +#   1. Create a large database.
          101  +#   2. Set the pager cache to be very small.
          102  +#   3. Open a transaction. 
          103  +#   4. Run the following 100 times:
          104  +#      a. Update a row.
          105  +#      b. Copy all files on disk to a new db location, including the journal.
          106  +#      c. Verify that the new db can be opened and that the content matches
          107  +#         the database created in step 1 (proving the journal was rolled
          108  +#         back).
          109  +
          110  +do_test 2.0 { 
          111  +  setup_and_save_db
          112  +  multiplex_restore_db
          113  +  sqlite3 db file:test.db?8_3_names=1
          114  +  execsql { PRAGMA cache_size = 10 }
          115  +  execsql { BEGIN }
          116  +} {}
          117  +
          118  +for {set iTest 1} {$iTest<=100} {incr iTest} {
          119  +  do_test 2.$iTest {
          120  +    execsql { 
          121  +      UPDATE t1 SET a=randomblob(12), b=randomblob(1400) WHERE rowid=5*$iTest
          122  +    }
          123  +    foreach f [glob -nocomplain test.*] {forcecopy $f "xx_$f"}
          124  +    sqlite3 db2 file:xx_test.db?8_3_names=1
          125  +    execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a} db2
          126  +  } $::cksum1
          127  +
          128  +  db2 close
          129  +}
          130  +
          131  +catch { db close }
          132  +sqlite3_multiplex_shutdown
          133  +finish_test

Changes to test/quota.test.

    10     10   #***********************************************************************
    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
    15     15   source $testdir/malloc_common.tcl
    16     16   
           17  +unset -nocomplain defaultVfs
           18  +set defaultVfs [file_control_vfsname db]
    17     19   db close
    18     20   
    19     21   do_test quota-1.1 { sqlite3_quota_initialize nosuchvfs 1 } {SQLITE_ERROR}
    20     22   do_test quota-1.2 { sqlite3_quota_initialize "" 1 }        {SQLITE_OK}
    21     23   do_test quota-1.3 { sqlite3_quota_initialize "" 1 }        {SQLITE_MISUSE}
    22     24   do_test quota-1.4 { sqlite3_quota_shutdown }               {SQLITE_OK}
    23     25   
................................................................................
    69     71     execsql {
    70     72       CREATE TABLE t1(a, b);
    71     73       INSERT INTO t1 VALUES(1, randomblob(1100));
    72     74       INSERT INTO t1 VALUES(2, randomblob(1100));
    73     75     }
    74     76     set ::quota
    75     77   } {}
           78  +do_test quota-2.1.2.1 {
           79  +  file_control_vfsname db
           80  +} quota/$defaultVfs
    76     81   do_test quota-2.1.3 { file size test.db } {4096}
    77     82   do_test quota-2.1.4 {
    78     83     catchsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
    79     84   } {1 {database or disk is full}}
    80     85   do_test quota-2.1.5 { set ::quota } {4096 5120}
    81     86   
    82     87   set ::quota_request_ok 1