/ Check-in [9b230c43]
Login

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

Overview
Comment:Support compile-time option SQLITE_OMIT_WAL, for building without WAL support.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal
Files: files | file ages | folders
SHA1: 9b230c43dfa112e3e1589f9775926807bd36b36e
User & Date: dan 2010-05-01 16:40:20
Context
2010-05-01
17:50
Rework mutexes on the SHM implemention for os_unix to avoid a deadlock during WAL recovery. check-in: 1a0f69be user: drh tags: wal
16:40
Support compile-time option SQLITE_OMIT_WAL, for building without WAL support. check-in: 9b230c43 user: dan tags: wal
11:33
Fix a typo in the walmode.test test script introducted yesterday. check-in: dcabc90c user: drh tags: wal
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  2257   2257       int pageSize;
  2258   2258       int usableSize;
  2259   2259       u8 *page1 = pPage1->aData;
  2260   2260       rc = SQLITE_NOTADB;
  2261   2261       if( memcmp(page1, zMagicHeader, 16)!=0 ){
  2262   2262         goto page1_init_failed;
  2263   2263       }
         2264  +
         2265  +#ifdef SQLITE_OMIT_WAL
         2266  +    if( page1[18]>1 ){
         2267  +      pBt->readOnly = 1;
         2268  +    }
         2269  +    if( page1[19]>1 ){
         2270  +      goto page1_init_failed;
         2271  +    }
         2272  +#else
  2264   2273       if( page1[18]>2 ){
  2265   2274         pBt->readOnly = 1;
  2266   2275       }
  2267   2276       if( page1[19]>2 ){
  2268   2277         goto page1_init_failed;
  2269   2278       }
  2270   2279   
................................................................................
  2283   2292           goto page1_init_failed;
  2284   2293         }else if( isOpen==0 ){
  2285   2294           releasePage(pPage1);
  2286   2295           return SQLITE_OK;
  2287   2296         }
  2288   2297         rc = SQLITE_NOTADB;
  2289   2298       }
         2299  +#endif
  2290   2300   
  2291   2301       /* The maximum embedded fraction must be exactly 25%.  And the minimum
  2292   2302       ** embedded fraction must be 12.5% for both leaf-data and non-leaf-data.
  2293   2303       ** The original design allowed these amounts to vary, but as of
  2294   2304       ** version 3.6.0, we require them to be fixed.
  2295   2305       */
  2296   2306       if( memcmp(&page1[21], "\100\040\040",3)!=0 ){

Changes to src/main.c.

  1191   1191   ** into the write-ahead-log by this database connection.
  1192   1192   */
  1193   1193   void *sqlite3_wal_hook(
  1194   1194     sqlite3 *db,                    /* Attach the hook to this db handle */
  1195   1195     int(*xCallback)(void *, sqlite3*, const char*, int),
  1196   1196     void *pArg                      /* First argument passed to xCallback() */
  1197   1197   ){
         1198  +#ifndef SQLITE_OMIT_WAL
  1198   1199     void *pRet;
  1199   1200     sqlite3_mutex_enter(db->mutex);
  1200   1201     pRet = db->pWalArg;
  1201   1202     db->xWalCallback = xCallback;
  1202   1203     db->pWalArg = pArg;
  1203   1204     sqlite3_mutex_leave(db->mutex);
  1204   1205     return pRet;
         1206  +#else
         1207  +  return 0;
         1208  +#endif
  1205   1209   }
  1206   1210   
  1207   1211   /*
  1208   1212   ** This function returns true if main-memory should be used instead of
  1209   1213   ** a temporary file for transient pager files and statement journals.
  1210   1214   ** The value returned depends on the value of db->temp_store (runtime
  1211   1215   ** parameter) and the compile time value of SQLITE_TEMP_STORE. The

Changes to src/os_unix.c.

  4558   4558   static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
  4559   4559     UNUSED_PARAMETER(NotUsed);
  4560   4560     UNUSED_PARAMETER(NotUsed2);
  4561   4561     UNUSED_PARAMETER(NotUsed3);
  4562   4562     return 0;
  4563   4563   }
  4564   4564   
         4565  +#ifndef SQLITE_OMIT_WAL
         4566  +
  4565   4567   /* Forward reference */
  4566   4568   typedef struct unixShm unixShm;
  4567   4569   typedef struct unixShmFile unixShmFile;
  4568   4570   
  4569   4571   /*
  4570   4572   ** Object used to represent a single file opened and mmapped to provide
  4571   4573   ** shared memory.  When multiple threads all reference the same
................................................................................
  5330   5332   /*
  5331   5333   ** Delete a shared-memory segment from the system.
  5332   5334   */
  5333   5335   static int unixShmDelete(sqlite3_vfs *pVfs, const char *zName){
  5334   5336     return pVfs->xDelete(pVfs, zName, 0);
  5335   5337   }
  5336   5338   
         5339  +#else
         5340  +# define unixShmOpen    0
         5341  +# define unixShmSize    0
         5342  +# define unixShmGet     0
         5343  +# define unixShmRelease 0
         5344  +# define unixShmLock    0
         5345  +# define unixShmClose   0
         5346  +# define unixShmDelete  0
         5347  +#endif /* #ifndef SQLITE_OMIT_WAL */
  5337   5348   
  5338   5349   /*
  5339   5350   ************************ End of sqlite3_vfs methods ***************************
  5340   5351   ******************************************************************************/
  5341   5352   
  5342   5353   /******************************************************************************
  5343   5354   ************************** Begin Proxy Locking ********************************

Changes to src/pager.c.

   395    395     void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
   396    396     void (*xCodecFree)(void*);             /* Destructor for the codec */
   397    397     void *pCodec;               /* First argument to xCodec... methods */
   398    398   #endif
   399    399     char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
   400    400     PCache *pPCache;            /* Pointer to page cache object */
   401    401     sqlite3_backup *pBackup;    /* Pointer to list of ongoing backup processes */
          402  +#ifndef SQLITE_OMIT_WAL
   402    403     Wal *pWal;                  /* Write-ahead log used by "journal_mode=wal" */
          404  +#endif
   403    405   };
   404    406   
   405    407   /*
   406    408   ** The following global variables hold counters used for
   407    409   ** testing purposes only.  These variables do not exist in
   408    410   ** a non-testing build.  These variables are not thread-safe.
   409    411   */
................................................................................
  1188   1190     return rc;
  1189   1191   }
  1190   1192   
  1191   1193   /*
  1192   1194   ** Return true if this pager uses a write-ahead log instead of the usual
  1193   1195   ** rollback journal. Otherwise false.
  1194   1196   */
         1197  +#ifndef SQLITE_OMIT_WAL
  1195   1198   static int pagerUseWal(Pager *pPager){
  1196   1199     return (pPager->pWal!=0);
  1197   1200   }
         1201  +#else
         1202  +# define pagerUseWal(x) 0
         1203  +# define pagerRollbackWal(x) 0
         1204  +# define pagerWalFrames(v,w,x,y,z) 0
         1205  +# define pagerOpenWalIfPresent(z) SQLITE_OK
         1206  +#endif
  1198   1207   
  1199   1208   /*
  1200   1209   ** Unlock the database file. This function is a no-op if the pager
  1201   1210   ** is in exclusive mode.
  1202   1211   **
  1203   1212   ** If the pager is currently in error state, discard the contents of 
  1204   1213   ** the cache and reset the Pager structure internal state. If there is
................................................................................
  2238   2247     IOTRACE(("PGIN %p %d\n", pPager, pgno));
  2239   2248     PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
  2240   2249                  PAGERID(pPager), pgno, pager_pagehash(pPg)));
  2241   2250   
  2242   2251     return rc;
  2243   2252   }
  2244   2253   
         2254  +#ifndef SQLITE_OMIT_WAL
  2245   2255   /*
  2246   2256   ** This function is invoked once for each page that has already been 
  2247   2257   ** written into the log file when a WAL transaction is rolled back.
  2248   2258   ** Parameter iPg is the page number of said page. The pCtx argument 
  2249   2259   ** is actually a pointer to the Pager structure.
  2250   2260   **
  2251   2261   ** If page iPg is present in the cache, and has no outstanding references,
................................................................................
  2307   2317       rc = pagerUndoCallback((void *)pPager, pList->pgno);
  2308   2318       pList = pNext;
  2309   2319     }
  2310   2320   
  2311   2321     return rc;
  2312   2322   }
  2313   2323   
         2324  +/*
         2325  +** This function is a wrapper around sqlite3WalFrames(). As well as logging
         2326  +** the contents of the list of pages headed by pList (connected by pDirty),
         2327  +** this function notifies any active backup processes that the pages have
         2328  +** changed. 
         2329  +*/ 
         2330  +static int pagerWalFrames(
         2331  +  Pager *pPager,                  /* Pager object */
         2332  +  PgHdr *pList,                   /* List of frames to log */
         2333  +  Pgno nTruncate,                 /* Database size after this commit */
         2334  +  int isCommit,                   /* True if this is a commit */
         2335  +  int sync_flags                  /* Flags to pass to OsSync() (or 0) */
         2336  +){
         2337  +  int rc;                         /* Return code */
         2338  +
         2339  +  assert( pPager->pWal );
         2340  +  rc = sqlite3WalFrames(pPager->pWal, 
         2341  +      pPager->pageSize, pList, nTruncate, isCommit, sync_flags
         2342  +  );
         2343  +  if( rc==SQLITE_OK && pPager->pBackup ){
         2344  +    PgHdr *p;
         2345  +    for(p=pList; p; p=p->pDirty){
         2346  +      sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
         2347  +    }
         2348  +  }
         2349  +  return rc;
         2350  +}
         2351  +
         2352  +/*
         2353  +** Open a WAL snapshot on the log file this pager is connected to.
         2354  +*/
         2355  +static int pagerOpenSnapshot(Pager *pPager){
         2356  +  int rc;                         /* Return code */
         2357  +  int changed = 0;                /* True if cache must be reset */
         2358  +
         2359  +  assert( pagerUseWal(pPager) );
         2360  +
         2361  +  rc = sqlite3WalOpenSnapshot(pPager->pWal, &changed);
         2362  +  if( rc==SQLITE_OK ){
         2363  +    int dummy;
         2364  +    if( changed ){
         2365  +      pager_reset(pPager);
         2366  +      assert( pPager->errCode || pPager->dbSizeValid==0 );
         2367  +    }
         2368  +    rc = sqlite3PagerPagecount(pPager, &dummy);
         2369  +  }
         2370  +  pPager->state = PAGER_SHARED;
         2371  +
         2372  +  return rc;
         2373  +}
         2374  +
         2375  +/*
         2376  +** Check if the *-wal file that corresponds to the database opened by pPager
         2377  +** exists. Assuming no error occurs, set *pExists to 1 if the file exists,
         2378  +** or 0 otherwise and return SQLITE_OK. If an IO or OOM error occurs, return
         2379  +** an SQLite error code.
         2380  +*/
         2381  +static int pagerHasWAL(Pager *pPager, int *pExists){
         2382  +  int rc;                         /* Return code */
         2383  +
         2384  +  if( !pPager->tempFile ){
         2385  +    char *zWal = sqlite3_mprintf("%s-wal", pPager->zFilename);
         2386  +    if( !zWal ){
         2387  +      rc = SQLITE_NOMEM;
         2388  +    }else{
         2389  +      rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists);
         2390  +      sqlite3_free(zWal);
         2391  +    }
         2392  +  }else{
         2393  +    rc = SQLITE_OK;
         2394  +    *pExists = 0;
         2395  +  }
         2396  +  return rc;
         2397  +}
         2398  +
         2399  +/*
         2400  +** Check if the *-wal file that corresponds to the database opened by pPager
         2401  +** exists. If it does, open the pager in WAL mode. Otherwise, if no error
         2402  +** occurs, make sure Pager.journalMode is not set to PAGER_JOURNALMODE_WAL.
         2403  +** If an IO or OOM error occurs, return an SQLite error code.
         2404  +**
         2405  +** If the WAL file is opened, also open a snapshot (read transaction).
         2406  +**
         2407  +** The caller must hold a SHARED lock on the database file to call this
         2408  +** function. Because an EXCLUSIVE lock on the db file is required to delete 
         2409  +** a WAL, this ensures there is no race condition between the xAccess() 
         2410  +** below and an xDelete() being executed by some other connection.
         2411  +*/
         2412  +static int pagerOpenWalIfPresent(Pager *pPager){
         2413  +  int rc = SQLITE_OK;
         2414  +  if( !pPager->tempFile ){
         2415  +    int isWal;                    /* True if WAL file exists */
         2416  +    rc = pagerHasWAL(pPager, &isWal);
         2417  +    if( rc==SQLITE_OK ){
         2418  +      if( isWal ){
         2419  +        pager_reset(pPager);
         2420  +        rc = sqlite3PagerOpenWal(pPager, 0);
         2421  +        if( rc==SQLITE_OK ){
         2422  +          rc = pagerOpenSnapshot(pPager);
         2423  +        }
         2424  +      }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
         2425  +        pPager->journalMode = PAGER_JOURNALMODE_DELETE;
         2426  +      }
         2427  +    }
         2428  +  }
         2429  +  return rc;
         2430  +}
         2431  +#endif
         2432  +
  2314   2433   /*
  2315   2434   ** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
  2316   2435   ** the entire master journal file. The case pSavepoint==NULL occurs when 
  2317   2436   ** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction 
  2318   2437   ** savepoint.
  2319   2438   **
  2320   2439   ** When pSavepoint is not NULL (meaning a non-transaction savepoint is 
................................................................................
  2930   3049   int sqlite3PagerClose(Pager *pPager){
  2931   3050     u8 *pTmp = (u8 *)pPager->pTmpSpace;
  2932   3051   
  2933   3052     disable_simulated_io_errors();
  2934   3053     sqlite3BeginBenignMalloc();
  2935   3054     pPager->errCode = 0;
  2936   3055     pPager->exclusiveMode = 0;
         3056  +#ifndef SQLITE_OMIT_WAL
  2937   3057     sqlite3WalClose(pPager->pWal, pPager->fd, 
  2938   3058       (pPager->noSync ? 0 : pPager->sync_flags), pTmp
  2939   3059     );
  2940   3060     pPager->pWal = 0;
         3061  +#endif
  2941   3062     pager_reset(pPager);
  2942   3063     if( MEMDB ){
  2943   3064       pager_unlock(pPager);
  2944   3065     }else{
  2945   3066       /* Set Pager.journalHdr to -1 for the benefit of the pager_playback() 
  2946   3067       ** call which may be made from within pagerUnlockAndRollback(). If it
  2947   3068       ** is not -1, then the unsynced portion of an open journal file may
................................................................................
  3273   3394       }
  3274   3395     }
  3275   3396     if( rc==SQLITE_OK ){
  3276   3397       pPager->nSubRec++;
  3277   3398       assert( pPager->nSavepoint>0 );
  3278   3399       rc = addToSavepointBitvecs(pPager, pPg->pgno);
  3279   3400     }
  3280         -  return rc;
  3281         -}
  3282         -
  3283         -/*
  3284         -** This function is a wrapper around sqlite3WalFrames(). As well as logging
  3285         -** the contents of the list of pages headed by pList (connected by pDirty),
  3286         -** this function notifies any active backup processes that the pages have
  3287         -** changed. 
  3288         -*/ 
  3289         -static int pagerWalFrames(
  3290         -  Pager *pPager,                  /* Pager object */
  3291         -  PgHdr *pList,                   /* List of frames to log */
  3292         -  Pgno nTruncate,                 /* Database size after this commit */
  3293         -  int isCommit,                   /* True if this is a commit */
  3294         -  int sync_flags                  /* Flags to pass to OsSync() (or 0) */
  3295         -){
  3296         -  int rc;                         /* Return code */
  3297         -
  3298         -  assert( pPager->pWal );
  3299         -  rc = sqlite3WalFrames(pPager->pWal, 
  3300         -      pPager->pageSize, pList, nTruncate, isCommit, sync_flags
  3301         -  );
  3302         -  if( rc==SQLITE_OK && pPager->pBackup ){
  3303         -    PgHdr *p;
  3304         -    for(p=pList; p; p=p->pDirty){
  3305         -      sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
  3306         -    }
  3307         -  }
  3308   3401     return rc;
  3309   3402   }
  3310   3403   
  3311   3404   /*
  3312   3405   ** This function is called by the pcache layer when it has reached some
  3313   3406   ** soft memory limit. The first argument is a pointer to a Pager object
  3314   3407   ** (cast as a void*). The pager is always 'purgeable' (not an in-memory
................................................................................
  3815   3908         }
  3816   3909       }
  3817   3910     }
  3818   3911   
  3819   3912     return rc;
  3820   3913   }
  3821   3914   
  3822         -/*
  3823         -** Check if the *-wal file that corresponds to the database opened by pPager
  3824         -** exists. Assuming no error occurs, set *pExists to 1 if the file exists,
  3825         -** or 0 otherwise and return SQLITE_OK. If an IO or OOM error occurs, return
  3826         -** an SQLite error code.
  3827         -**
  3828         -** The caller must hold a SHARED lock on the database file to call this
  3829         -** function. Because an EXCLUSIVE lock on the db file is required to delete 
  3830         -** a WAL, this ensures there is no race condition between the xAccess() 
  3831         -** below and an xDelete() being executed by some other connection.
  3832         -*/
  3833         -static int pagerHasWAL(Pager *pPager, int *pExists){
  3834         -  int rc;                         /* Return code */
  3835         -
  3836         -  if( !pPager->tempFile ){
  3837         -    char *zWal = sqlite3_mprintf("%s-wal", pPager->zFilename);
  3838         -    if( !zWal ){
  3839         -      rc = SQLITE_NOMEM;
  3840         -    }else{
  3841         -      rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists);
  3842         -      sqlite3_free(zWal);
  3843         -    }
  3844         -  }else{
  3845         -    rc = SQLITE_OK;
  3846         -    *pExists = 0;
  3847         -  }
  3848         -  return rc;
  3849         -}
  3850         -
  3851         -static int pagerOpenSnapshot(Pager *pPager){
  3852         -  int rc;                         /* Return code */
  3853         -  int changed = 0;                /* True if cache must be reset */
  3854         -
  3855         -  assert( pagerUseWal(pPager) );
  3856         -
  3857         -  rc = sqlite3WalOpenSnapshot(pPager->pWal, &changed);
  3858         -  if( rc==SQLITE_OK ){
  3859         -    int dummy;
  3860         -    if( changed ){
  3861         -      pager_reset(pPager);
  3862         -      assert( pPager->errCode || pPager->dbSizeValid==0 );
  3863         -    }
  3864         -    rc = sqlite3PagerPagecount(pPager, &dummy);
  3865         -  }
  3866         -  pPager->state = PAGER_SHARED;
  3867         -
  3868         -  return rc;
  3869         -}
  3870         -
  3871   3915   /*
  3872   3916   ** This function is called to obtain a shared lock on the database file.
  3873   3917   ** It is illegal to call sqlite3PagerAcquire() until after this function
  3874   3918   ** has been successfully called. If a shared-lock is already held when
  3875   3919   ** this function is called, it is a no-op.
  3876   3920   **
  3877   3921   ** The following operations are also performed by this function.
................................................................................
  3922   3966     }
  3923   3967   
  3924   3968     if( pagerUseWal(pPager) ){
  3925   3969       rc = pagerOpenSnapshot(pPager);
  3926   3970     }else if( pPager->state==PAGER_UNLOCK || isErrorReset ){
  3927   3971       sqlite3_vfs * const pVfs = pPager->pVfs;
  3928   3972       int isHotJournal = 0;
  3929         -    int isWal = 0;
  3930   3973       assert( !MEMDB );
  3931   3974       assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
  3932   3975       if( pPager->noReadlock ){
  3933   3976         assert( pPager->readOnly );
  3934   3977         pPager->state = PAGER_SHARED;
  3935   3978       }else{
  3936   3979         rc = pager_wait_on_lock(pPager, SHARED_LOCK);
................................................................................
  4077   4120   
  4078   4121         if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
  4079   4122           pager_reset(pPager);
  4080   4123         }
  4081   4124       }
  4082   4125       assert( pPager->exclusiveMode || pPager->state==PAGER_SHARED );
  4083   4126   
  4084         -    rc = pagerHasWAL(pPager, &isWal);
  4085         -    if( rc!=SQLITE_OK ){
  4086         -      goto failed;
  4087         -    }
  4088         -    if( isWal ){
  4089         -      pager_reset(pPager);
  4090         -      rc = sqlite3PagerOpenWal(pPager, 0);
  4091         -      if( rc==SQLITE_OK ){
  4092         -        rc = pagerOpenSnapshot(pPager);
  4093         -      }
  4094         -    }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
  4095         -      pPager->journalMode = PAGER_JOURNALMODE_DELETE;
  4096         -    }
         4127  +    /* If there is a WAL file in the file-system, open this database in WAL
         4128  +    ** mode. Otherwise, the following function call is a no-op.
         4129  +    */
         4130  +    rc = pagerOpenWalIfPresent(pPager);
  4097   4131     }
  4098   4132   
  4099   4133    failed:
  4100   4134     if( rc!=SQLITE_OK ){
  4101   4135       /* pager_unlock() is a no-op for exclusive mode and in-memory databases. */
  4102   4136       pager_unlock(pPager);
  4103   4137     }
................................................................................
  5785   5819   ** uses it opaquely as an argument to sqlite3BackupRestart() and
  5786   5820   ** sqlite3BackupUpdate() only.
  5787   5821   */
  5788   5822   sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){
  5789   5823     return &pPager->pBackup;
  5790   5824   }
  5791   5825   
         5826  +#ifndef SQLITE_OMIT_WAL
  5792   5827   /*
  5793   5828   ** This function is called when the user invokes "PRAGMA checkpoint".
  5794   5829   */
  5795   5830   int sqlite3PagerCheckpoint(Pager *pPager){
  5796   5831     int rc = SQLITE_OK;
  5797   5832     if( pPager->pWal ){
  5798   5833       u8 *zBuf = (u8 *)pPager->pTmpSpace;
................................................................................
  5832   5867     }else{
  5833   5868       *pisOpen = 1;
  5834   5869     }
  5835   5870   
  5836   5871     return rc;
  5837   5872   }
  5838   5873   
  5839         -
  5840   5874   /*
  5841   5875   ** This function is called to close the connection to the log file prior
  5842   5876   ** to switching from WAL to rollback mode.
  5843   5877   **
  5844   5878   ** Before closing the log file, this function attempts to take an 
  5845   5879   ** EXCLUSIVE lock on the database file. If this cannot be obtained, an
  5846   5880   ** error (SQLITE_BUSY) is returned and the log connection is not closed.
................................................................................
  5877   5911           (u8*)pPager->pTmpSpace
  5878   5912         );
  5879   5913         pPager->pWal = 0;
  5880   5914       }
  5881   5915     }
  5882   5916     return rc;
  5883   5917   }
         5918  +#endif
  5884   5919   
  5885   5920   #endif /* SQLITE_OMIT_DISKIO */

Changes to src/pragma.c.

   261    261   /*
   262    262   ** Parameter eMode must be one of the PAGER_JOURNALMODE_XXX constants
   263    263   ** defined in pager.h. This function returns the associated lowercase
   264    264   ** journal-mode name.
   265    265   */
   266    266   const char *sqlite3JournalModename(int eMode){
   267    267     static char * const azModeName[] = {
   268         -    "delete", "persist", "off", "truncate", "memory", "wal"
          268  +    "delete", "persist", "off", "truncate", "memory"
          269  +#ifndef SQLITE_OMIT_WAL
          270  +     , "wal"
          271  +#endif
   269    272     };
   270    273     assert( PAGER_JOURNALMODE_DELETE==0 );
   271    274     assert( PAGER_JOURNALMODE_PERSIST==1 );
   272    275     assert( PAGER_JOURNALMODE_OFF==2 );
   273    276     assert( PAGER_JOURNALMODE_TRUNCATE==3 );
   274    277     assert( PAGER_JOURNALMODE_MEMORY==4 );
   275    278     assert( PAGER_JOURNALMODE_WAL==5 );
................................................................................
  1393   1396       while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){
  1394   1397         sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0);
  1395   1398         sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
  1396   1399       }
  1397   1400     }else
  1398   1401   #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
  1399   1402   
         1403  +#ifndef SQLITE_OMIT_WAL
         1404  +  /*
         1405  +  **   PRAGMA [database.]checkpoint
         1406  +  **
         1407  +  ** Checkpoint the database.
         1408  +  */
  1400   1409     if( sqlite3StrICmp(zLeft, "checkpoint")==0 ){
  1401   1410       sqlite3VdbeUsesBtree(v, iDb);
  1402   1411       sqlite3VdbeAddOp3(v, OP_Checkpoint, iDb, 0, 0);
  1403   1412     }else
         1413  +#endif
  1404   1414   
  1405   1415   #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  1406   1416     /*
  1407   1417     ** Report the current state of file logs for all databases
  1408   1418     */
  1409   1419     if( sqlite3StrICmp(zLeft, "lock_status")==0 ){
  1410   1420       static const char *const azLockName[] = {

Changes to src/sqliteInt.h.

   819    819     void *pProfileArg;                        /* Argument to profile function */
   820    820     void *pCommitArg;                 /* Argument to xCommitCallback() */   
   821    821     int (*xCommitCallback)(void*);    /* Invoked at every commit. */
   822    822     void *pRollbackArg;               /* Argument to xRollbackCallback() */   
   823    823     void (*xRollbackCallback)(void*); /* Invoked at every commit. */
   824    824     void *pUpdateArg;
   825    825     void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
          826  +#ifndef SQLITE_OMIT_WAL
   826    827     int (*xWalCallback)(void *, sqlite3 *, const char *, int);
   827    828     void *pWalArg;
          829  +#endif
   828    830     void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
   829    831     void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
   830    832     void *pCollNeededArg;
   831    833     sqlite3_value *pErr;          /* Most recent error message */
   832    834     char *zErrMsg;                /* Most recent error message (UTF-8 encoded) */
   833    835     char *zErrMsg16;              /* Most recent error message (UTF-16 encoded) */
   834    836     union {

Changes to src/test_config.c.

   494    494   #endif
   495    495   
   496    496   #ifdef SQLITE_OMIT_VIRTUALTABLE
   497    497     Tcl_SetVar2(interp, "sqlite_options", "vtab", "0", TCL_GLOBAL_ONLY);
   498    498   #else
   499    499     Tcl_SetVar2(interp, "sqlite_options", "vtab", "1", TCL_GLOBAL_ONLY);
   500    500   #endif
          501  +
          502  +#ifdef SQLITE_OMIT_WAL
          503  +  Tcl_SetVar2(interp, "sqlite_options", "wal", "0", TCL_GLOBAL_ONLY);
          504  +#else
          505  +  Tcl_SetVar2(interp, "sqlite_options", "wal", "1", TCL_GLOBAL_ONLY);
          506  +#endif
   501    507   
   502    508   #ifdef SQLITE_OMIT_WSD
   503    509     Tcl_SetVar2(interp, "sqlite_options", "wsd", "0", TCL_GLOBAL_ONLY);
   504    510   #else
   505    511     Tcl_SetVar2(interp, "sqlite_options", "wsd", "1", TCL_GLOBAL_ONLY);
   506    512   #endif
   507    513   

Changes to src/vdbe.c.

  5182   5182     UPDATE_MAX_BLOBSIZE(pMem);
  5183   5183     if( sqlite3VdbeMemTooBig(pMem) ){
  5184   5184       goto too_big;
  5185   5185     }
  5186   5186     break;
  5187   5187   }
  5188   5188   
         5189  +#ifndef SQLITE_OMIT_WAL
  5189   5190   /* Opcode: Checkpoint P1 * * * *
  5190   5191   **
  5191   5192   ** Checkpoint database P1. This is a no-op if P1 is not currently in
  5192   5193   ** WAL mode.
  5193   5194   */
  5194   5195   case OP_Checkpoint: {
  5195   5196     Btree *pBt;                     /* Btree to checkpoint */
................................................................................
  5196   5197   
  5197   5198     assert( pOp->p1>=0 && pOp->p1<db->nDb );
  5198   5199     assert( (p->btreeMask & (1<<pOp->p1))!=0 );
  5199   5200     pBt = db->aDb[pOp->p1].pBt;
  5200   5201     rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt));
  5201   5202     break;
  5202   5203   };  
         5204  +#endif
  5203   5205   
  5204   5206   /* Opcode: JournalMode P1 P2 P3 * *
  5205   5207   **
  5206   5208   ** Change the journal mode of database P1 to P3. P3 must be one of the
  5207   5209   ** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
  5208   5210   ** modes (delete, truncate, persist, off and memory), this is a simple
  5209   5211   ** operation. No IO is required.
................................................................................
  5230   5232          || eNew==PAGER_JOURNALMODE_QUERY
  5231   5233     );
  5232   5234     assert( pOp->p1>=0 && pOp->p1<db->nDb );
  5233   5235     assert( (p->btreeMask & (1<<pOp->p1))!=0 );
  5234   5236   
  5235   5237     pBt = db->aDb[pOp->p1].pBt;
  5236   5238     pPager = sqlite3BtreePager(pBt);
         5239  +
         5240  +#ifndef SQLITE_OMIT_WAL
  5237   5241     zFilename = sqlite3PagerFilename(pPager);
  5238   5242     pVfs = sqlite3PagerVfs(pPager);
  5239   5243   
  5240   5244     /* Do not allow a transition to journal_mode=WAL for a database
  5241   5245     ** in temporary storage or if the VFS does not support xShmOpen.
  5242   5246     */
  5243   5247     if( eNew==PAGER_JOURNALMODE_WAL
................................................................................
  5278   5282           */
  5279   5283           assert( sqlite3BtreeIsInTrans(pBt)==0 );
  5280   5284           rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
  5281   5285           if( rc!=SQLITE_OK ) goto abort_due_to_error;
  5282   5286         }
  5283   5287       }
  5284   5288     }
         5289  +#endif /* ifndef SQLITE_OMIT_WAL */
  5285   5290   
  5286   5291     eNew = sqlite3PagerJournalMode(pPager, eNew);
  5287   5292     pOut = &aMem[pOp->p2];
  5288   5293     pOut->flags = MEM_Str|MEM_Static|MEM_Term;
  5289   5294     pOut->z = (char *)sqlite3JournalModename(eNew);
  5290   5295     pOut->n = sqlite3Strlen30(pOut->z);
  5291   5296     pOut->enc = SQLITE_UTF8;

Changes to src/vdbeapi.c.

   302    302   void sqlite3_result_error_nomem(sqlite3_context *pCtx){
   303    303     assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   304    304     sqlite3VdbeMemSetNull(&pCtx->s);
   305    305     pCtx->isError = SQLITE_NOMEM;
   306    306     pCtx->s.db->mallocFailed = 1;
   307    307   }
   308    308   
          309  +/*
          310  +** This function is called after a transaction has been committed. It 
          311  +** invokes callbacks registered with sqlite3_wal_hook() as required.
          312  +*/
   309    313   static int doWalCallbacks(sqlite3 *db){
   310         -  int i;
   311    314     int rc = SQLITE_OK;
          315  +#ifndef SQLITE_OMIT_WAL
          316  +  int i;
   312    317     for(i=0; i<db->nDb; i++){
   313    318       Btree *pBt = db->aDb[i].pBt;
   314    319       if( pBt ){
   315    320         int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
   316    321         if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK
   317    322          && db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry)
   318    323         ){
   319    324           rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt));
   320    325         }
   321    326       }
   322    327     }
          328  +#endif
   323    329     return rc;
   324    330   }
   325    331   
   326    332   /*
   327    333   ** Execute the statement pStmt, either until a row of data is ready, the
   328    334   ** statement is completely executed or an error occurs.
   329    335   **

Changes to src/wal.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   **
    13     13   ** This file contains the implementation of a write-ahead log file used in 
    14     14   ** "journal_mode=wal" mode.
    15     15   */
           16  +#ifndef SQLITE_OMIT_WAL
           17  +
    16     18   #include "wal.h"
    17     19   
    18     20   
    19     21   /*
    20     22   ** WRITE-AHEAD LOG (WAL) FILE FORMAT
    21     23   **
    22     24   ** A wal file consists of a header followed by zero or more "frames".
................................................................................
  1267   1269     int (*xBusyHandler)(void *),    /* Pointer to busy-handler function */
  1268   1270     void *pBusyHandlerArg           /* Argument to pass to xBusyHandler */
  1269   1271   ){
  1270   1272     int rc;                         /* Return code */
  1271   1273     int isChanged = 0;              /* True if a new wal-index header is loaded */
  1272   1274   
  1273   1275     assert( pWal->lockState==SQLITE_SHM_UNLOCK );
         1276  +  assert( pWal->pWiData==0 );
  1274   1277   
  1275   1278     /* Get the CHECKPOINT lock */
  1276   1279     do {
  1277   1280       rc = walSetLock(pWal, SQLITE_SHM_CHECKPOINT);
  1278   1281     }while( rc==SQLITE_BUSY && xBusyHandler(pBusyHandlerArg) );
  1279   1282     if( rc!=SQLITE_OK ){
  1280   1283       walSetLock(pWal, SQLITE_SHM_UNLOCK);
................................................................................
  1311   1314     u32 ret = 0;
  1312   1315     if( pWal ){
  1313   1316       ret = pWal->iCallback;
  1314   1317       pWal->iCallback = 0;
  1315   1318     }
  1316   1319     return (int)ret;
  1317   1320   }
         1321  +#endif /* #ifndef SQLITE_OMIT_WAL */

Changes to src/wal.h.

    14     14   ** the implementation of each function in log.c for further details.
    15     15   */
    16     16   
    17     17   #ifndef _WAL_H_
    18     18   #define _WAL_H_
    19     19   
    20     20   #include "sqliteInt.h"
           21  +
           22  +#ifdef SQLITE_OMIT_WAL
           23  +# define sqlite3WalOpen(x,y,z)             0
           24  +# define sqlite3WalClose(w,x,y,z)          0
           25  +# define sqlite3WalOpenSnapshot(y,z)       0
           26  +# define sqlite3WalCloseSnapshot(z) 
           27  +# define sqlite3WalRead(w,x,y,z)           0
           28  +# define sqlite3WalDbsize(y,z)
           29  +# define sqlite3WalWriteLock(y,z)          0
           30  +# define sqlite3WalUndo(x,y,z)             0
           31  +# define sqlite3WalSavepoint(z)            0
           32  +# define sqlite3WalSavepointUndo(y,z)      0
           33  +# define sqlite3WalFrames(u,v,w,x,y,z)     0
           34  +# define sqlite3WalCheckpoint(u,v,w,x,y,z) 0
           35  +# define sqlite3WalCallback(z)             0
           36  +#else
    21     37   
    22     38   /* Connection to a write-ahead log (WAL) file. 
    23     39   ** There is one object of this type for each pager. 
    24     40   */
    25     41   typedef struct Wal Wal;
    26     42   
    27     43   /* Open and close a connection to a write-ahead log. */
................................................................................
    75     91   /* Return the value to pass to a sqlite3_wal_hook callback, the
    76     92   ** number of frames in the WAL at the point of the last commit since
    77     93   ** sqlite3WalCallback() was called.  If no commits have occurred since
    78     94   ** the last call, then return 0.
    79     95   */
    80     96   int sqlite3WalCallback(Wal *pWal);
    81     97   
           98  +#endif /* ifndef SQLITE_OMIT_WAL */
    82     99   #endif /* _WAL_H_ */

Changes to test/corruptA.test.

    33     33   
    34     34   # Corrupt the file header in various ways and make sure the corruption
    35     35   # is detected when opening the database file.
    36     36   #
    37     37   db close
    38     38   file copy -force test.db test.db-template
    39     39   
           40  +set unreadable_version 02
           41  +ifcapable wal { set unreadable_version 03 }
    40     42   do_test corruptA-2.1 {
    41     43     file copy -force test.db-template test.db
    42         -  hexio_write test.db 19 03   ;# the read format number
           44  +  hexio_write test.db 19 $unreadable_version   ;# the read format number
    43     45     sqlite3 db test.db
    44     46     catchsql {SELECT * FROM t1}  
    45     47   } {1 {file is encrypted or is not a database}}
    46     48    
    47     49   do_test corruptA-2.2 {
    48     50     db close
    49     51     file copy -force test.db-template test.db

Changes to test/rdonly.test.

    63     63   } {0 {1 2}}
    64     64   
    65     65   # Now, after connection [db] has loaded the database schema, modify the
    66     66   # write-version of the file (and the change-counter, so that the 
    67     67   # write-version is reloaded). This way, SQLite does not discover that
    68     68   # the database is read-only until after it is locked.
    69     69   #
           70  +set ro_version 02
           71  +ifcapable wal { set ro_version 03 }
    70     72   do_test rdonly-1.6 {
    71         -  hexio_write test.db 18 03              ; # write-version
           73  +  hexio_write test.db 18 $ro_version     ; # write-version
    72     74     hexio_write test.db 24 11223344        ; # change-counter
    73     75     catchsql {
    74     76       INSERT INTO t1 VALUES(2);
    75     77     }
    76     78   } {1 {attempt to write a readonly database}}
    77     79   
    78     80   finish_test

Changes to test/wal.test.

    12     12   # focus of this file is testing the operation of the library in
    13     13   # "PRAGMA journal_mode=WAL" mode.
    14     14   #
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   source $testdir/lock_common.tcl
           19  +
           20  +ifcapable !wal {finish_test ; return }
    19     21   
    20     22   proc reopen_db {} {
    21     23     catch { db close }
    22     24     file delete -force test.db test.db-wal test.db-wal-summary
    23     25     sqlite3_wal db test.db
    24     26   }
    25     27   

Changes to test/walbak.test.

    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the operation of the library in
    13     13   # "PRAGMA journal_mode=WAL" mode.
    14     14   #
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
           18  +
           19  +ifcapable !wal {finish_test ; return }
    18     20   
    19     21   proc log_file_size {nFrame pgsz} {
    20     22     expr {12 + ($pgsz+16)*$nFrame}
    21     23   }
    22     24   
    23     25   # Test organization:
    24     26   # 

Changes to test/walcrash.test.

    23     23   #               than one page.
    24     24   # walcrash-3.*: Recover multiple databases where the failed transaction 
    25     25   #               was a multi-file transaction.
    26     26   #
    27     27   
    28     28   set testdir [file dirname $argv0]
    29     29   source $testdir/tester.tcl
           30  +ifcapable !wal {finish_test ; return }
           31  +
    30     32   db close
    31     33   
    32     34   set seed 0
    33     35   set REPEATS 100
    34     36   
    35     37   # walcrash-1.*
    36     38   #

Changes to test/walhook.test.

    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the operation of the library in
    13     13   # "PRAGMA journal_mode=WAL" mode.
    14     14   #
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
           18  +
           19  +ifcapable !wal {finish_test ; return }
    18     20   
    19     21   proc sqlite3_wal {args} {
    20     22     eval sqlite3 $args
    21     23     [lindex $args 0] eval { 
    22     24       PRAGMA journal_mode = wal;
    23     25       PRAGMA synchronous = normal;
    24     26       PRAGMA page_size = 1024;

Changes to test/walmode.test.

    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the operation of the library in
    13     13   # "PRAGMA journal_mode=WAL" mode.
    14     14   #
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
           18  +
           19  +# If the library was compiled without WAL support, check that the 
           20  +# "PRAGMA journal_mode=WAL" treats "WAL" as an unrecognized mode.
           21  +#
           22  +ifcapable !wal {
           23  +
           24  +  do_test walmode-0.1 {
           25  +    execsql { PRAGMA journal_mode = wal }
           26  +  } {delete}
           27  +  do_test walmode-0.2 {
           28  +    execsql { PRAGMA main.journal_mode = wal }
           29  +  } {delete}
           30  +  do_test walmode-0.3 {
           31  +    execsql { PRAGMA main.journal_mode }
           32  +  } {delete}
           33  +
           34  +  finish_test
           35  +  return
           36  +}
    18     37   
    19     38   do_test walmode-1.1 {
    20     39     set sqlite_sync_count 0
    21     40     execsql { PRAGMA page_size = 1024 }
    22     41     execsql { PRAGMA journal_mode = wal }
    23     42   } {wal}
    24     43   do_test walmode-1.2 {

Changes to test/walslow.test.

    12     12   # focus of this file is testing the operation of the library in
    13     13   # "PRAGMA journal_mode=WAL" mode. The tests in this file use 
    14     14   # brute force methods, so may take a while to run.
    15     15   #
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
           19  +
           20  +ifcapable !wal {finish_test ; return }
    19     21   
    20     22   proc reopen_db {} {
    21     23     catch { db close }
    22     24     file delete -force test.db test.db-wal
    23     25     sqlite3 db test.db
    24     26     execsql { PRAGMA journal_mode = wal }
    25     27   }

Changes to test/walthread.test.

    14     14   #
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   
    18     18   source $testdir/tester.tcl
    19     19   source $testdir/lock_common.tcl
    20     20   if {[run_thread_tests]==0} { finish_test ; return }
           21  +ifcapable !wal             { finish_test ; return }
    21     22   
    22     23   set sqlite_walsummary_mmap_incr 64
    23     24   
    24     25   # How long, in seconds, to run each test for. If a test is set to run for
    25     26   # 0 seconds, it is omitted entirely.
    26     27   #
    27     28   set seconds(walthread-1) 20