/ Check-in [5e2ee7db]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Updating apple-osx with minor source fixes, database truncate and replace private calls and a bunch of conditionalization for tests running in different environments
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA1: 5e2ee7db0f7a2a042b182336438107e2248d7b88
User & Date: adam 2010-08-18 00:09:48
Context
2010-08-18
00:24
Merge the 3.7.1 pre-release snapshot changes as of 2010-08-18 into the apple-osx branch. check-in: 866e9286 user: drh tags: apple-osx
00:09
Updating apple-osx with minor source fixes, database truncate and replace private calls and a bunch of conditionalization for tests running in different environments check-in: 5e2ee7db user: adam tags: apple-osx
2010-08-07
11:46
Merge in all changes up to the 3.7.0.1 release. check-in: f88c6367 user: drh tags: apple-osx
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

3029
3030
3031
3032
3033
3034
3035





3036
3037
3038
3039
3040
3041
3042
....
3068
3069
3070
3071
3072
3073
3074





















































































































































































































3075
3076
3077
3078
3079
3080
3081
....
4571
4572
4573
4574
4575
4576
4577



4578
4579
4580
4581
4582
4583
4584
....
4608
4609
4610
4611
4612
4613
4614


4615
4616
4617
4618
4619
4620



4621

4622
4623
4624
4625
4626
4627
4628
....
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
....
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
....
5893
5894
5895
5896
5897
5898
5899



5900
5901
5902
5903
5904
5905
5906
/*
** Handler for proxy-locking file-control verbs.  Defined below in the
** proxying locking division.
*/
static int proxyFileControl(sqlite3_file*,int,void*);
#endif







/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
................................................................................
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
    case SQLITE_SET_LOCKPROXYFILE:
    case SQLITE_GET_LOCKPROXYFILE: {
      return proxyFileControl(id,op,pArg);
    }
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */





















































































































































































































  }
  return SQLITE_ERROR;
}

/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
................................................................................
    if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */
    close(fd); /* silently leak if fail, in error */
    return SQLITE_IOERR_ACCESS;
  }
  if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
  }



#endif
  
#if SQLITE_ENABLE_LOCKING_STYLE
#if SQLITE_PREFER_PROXY_LOCKING
  isAutoProxy = 1;
#endif
  if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
................................................................................
        goto open_finished;
      }
      useProxy = !(fsInfo.f_flags&MNT_LOCAL);
    }
    if( useProxy ){
      rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
      if( rc==SQLITE_OK ){


        rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
        if( rc!=SQLITE_OK ){
          /* Use unixClose to clean up the resources added in fillInUnixFile 
          ** and clear all the structure's references.  Specifically, 
          ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op 
          */



          unixClose(pFile);

          return rc;
        }
      }
      goto open_finished;
    }
  }
#endif
................................................................................
/*
** pFile is a file that has been opened by a prior xOpen call.  dbPath
** is a string buffer at least MAXPATHLEN+1 characters in size.
**
** This routine find the filename associated with pFile and writes it
** int dbPath.
*/
static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
#if defined(__APPLE__)
  if( pFile->pMethod == &afpIoMethods ){
    /* afp style keeps a reference to the db path in the filePath field 
    ** of the struct */
    assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
    strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
  } else
................................................................................
  char dbPath[MAXPATHLEN+1];       /* Name of the database file */
  char *lockPath=NULL;
  int rc = SQLITE_OK;
  
  if( pFile->eFileLock!=NO_LOCK ){
    return SQLITE_BUSY;
  }
  proxyGetDbPathForUnixFile(pFile, dbPath);
  if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
    lockPath=NULL;
  }else{
    lockPath=(char *)path;
  }
  
  OSTRACE(("TRANSPROXY  %d for %s pid=%d\n", pFile->h,
................................................................................
        pCtx->conchHeld = -1; /* read only FS/ lockless */
        rc = SQLITE_OK;
      }
    }
  }  
  if( rc==SQLITE_OK && lockPath ){
    pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);



  }

  if( rc==SQLITE_OK ){
    pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
    if( pCtx->dbPath==NULL ){
      rc = SQLITE_NOMEM;
    }







>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







 







>
>






>
>
>
|
>







 







|







 







|







 







>
>
>







3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
....
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
....
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
....
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
....
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
....
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
....
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
/*
** Handler for proxy-locking file-control verbs.  Defined below in the
** proxying locking division.
*/
static int proxyFileControl(sqlite3_file*,int,void*);
#endif

#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
#include "sqlite3_private.h"
#include <copyfile.h>
static int getDbPathForUnixFile(unixFile *pFile, char *dbPath);
#endif

/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
................................................................................
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
    case SQLITE_SET_LOCKPROXYFILE:
    case SQLITE_GET_LOCKPROXYFILE: {
      return proxyFileControl(id,op,pArg);
    }
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
#if (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__)
    case SQLITE_TRUNCATE_DATABASE: {
      unixFile *pFile = (unixFile*)id;
      int trc = SQLITE_OK;
      int eFileLock = pFile->eFileLock;
      int rc = SQLITE_OK;
      char jPath[MAXPATHLEN+9];
      size_t jLen;
      
      if( eFileLock<SQLITE_LOCK_SHARED ){
        rc = pFile->pMethod->xLock(id, SQLITE_LOCK_SHARED);
      }
      if( !rc && eFileLock<SQLITE_LOCK_EXCLUSIVE ){
        rc = pFile->pMethod->xLock(id, SQLITE_LOCK_EXCLUSIVE);
      }
      if( rc ){
        if( pFile->eFileLock > eFileLock ){
          pFile->pMethod->xUnlock(id, eFileLock);
        }
        return rc;
      }
      rc = pFile->pMethod->xTruncate(id, ((pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) ? 1L : 0L);
      if( !rc && (SQLITE_OK==getDbPathForUnixFile(pFile, jPath)) ){
        jLen = strlcat(jPath, "-journal", MAXPATHLEN+9);
        if( jLen < MAXPATHLEN+9 ){
          int jfd = open(jPath, O_TRUNC);
          if( (jfd == -1) ){
            if ( errno!=ENOENT ){
              perror(jPath);
            }
          } else {
            fsync(jfd);
            close(jfd);
          }
        }
      }else{
        trc=rc;
      }
      if( !trc ){
        trc = pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
      }
      if( pFile->eFileLock > eFileLock ){
        int unlockRC = pFile->pMethod->xUnlock(id, SQLITE_LOCK_SHARED);
        if (!rc) rc = unlockRC;
      }
      if( pFile->eFileLock > eFileLock ){
        int unlockRC = pFile->pMethod->xUnlock(id, SQLITE_LOCK_NONE);
        if (!rc) rc = unlockRC;
      }
      if( trc ){
        return trc;
      }
      return rc;
    }
      
    case SQLITE_REPLACE_DATABASE: {
      unixFile *pFile = (unixFile*)id;
      int trc = SQLITE_OK;
      int eFileLock = pFile->eFileLock;
      int rc = SQLITE_OK;
      char jPath[MAXPATHLEN+9];
      size_t jLen;
      sqlite3 *srcdb = (sqlite3 *)pArg;
      Btree *pSrcBtree = NULL;
      int eSrcFileLock = SQLITE_LOCK_NONE;
      int srcLockRC = -1;
      sqlite3_file *src_file = NULL;
      unixFile *pSrcFile = NULL;
      
      if( !sqlite3SafetyCheckOk(srcdb) ){
        return SQLITE_MISUSE;
      }
      if( eFileLock<SQLITE_LOCK_SHARED ){
        rc = pFile->pMethod->xLock(id, SQLITE_LOCK_SHARED);
      }
      if( !rc && eFileLock<SQLITE_LOCK_EXCLUSIVE ){
        rc = pFile->pMethod->xLock(id, SQLITE_LOCK_EXCLUSIVE);
      }
      if( !rc ){
        /* get the src file descriptor adhering to the db struct access rules 
         ** this code is modeled after sqlite3_file_control() in main.c
         */ 
        sqlite3_mutex_enter(srcdb->mutex);
        if( srcdb->nDb>0 ){
          pSrcBtree = srcdb->aDb[0].pBt;
        }
        if( pSrcBtree ){
          Pager *pSrcPager;
          sqlite3BtreeEnter(pSrcBtree);
          pSrcPager = sqlite3BtreePager(pSrcBtree);
          assert( pSrcPager!=0 );
          src_file = sqlite3PagerFile(pSrcPager);
          assert( src_file!=0 );
          if( src_file->pMethods ){
            pSrcFile = (unixFile *)src_file;
            eSrcFileLock = pSrcFile->eFileLock;
            if( eSrcFileLock<SQLITE_LOCK_SHARED ){
              rc = pSrcFile->pMethod->xLock(src_file, SQLITE_LOCK_SHARED);
              srcLockRC = rc; /* SQLITE_OK means we need to unlock later */
            } else if( eSrcFileLock==SQLITE_LOCK_EXCLUSIVE ){
              /* if the src database has an exclusive lock, verify that the
               ** it doesn't have a journal file with open transactions 
               */
              if( getDbPathForUnixFile(pSrcFile, jPath) ){
                rc = SQLITE_INTERNAL;
              }else{
                jLen = strlcat(jPath, "-journal", MAXPATHLEN+9);
                if( jLen < MAXPATHLEN+9 ){
                  int jfd = open(jPath, O_RDONLY);
                  if( jfd==-1 ){
                    if( errno!=ENOENT ){
                      pFile->lastErrno = errno;
                      rc = SQLITE_IOERR;
                    }
                  }else{
                    /* if the journal exists ensure there's no pending 
                     ** transaction by checking the journal header */
                    char magic[8];
                    ssize_t rlen = pread(jfd, magic, 8, 0);
                    if( rlen<0 ){
                      pFile->lastErrno = errno;
                      rc = SQLITE_IOERR;
                    }else if( rlen==8 ){
                      char test[8] = {'\0','\0','\0','\0','\0','\0','\0','\0'};
                      if( memcmp(magic,test,8) ){
                        rc = SQLITE_LOCKED;
                      }
                    }else if( rlen!=0 ){
                      rc = SQLITE_INTERNAL;
                    }
                    close(jfd);
                  }
                }
              }
            }
          }else{
            rc = SQLITE_MISUSE;
          }
          if( rc ){
            if( srcLockRC==SQLITE_OK ){
              pSrcFile->pMethod->xUnlock(src_file, eSrcFileLock);
            }
            sqlite3BtreeLeave(pSrcBtree);
          }
        }
        if( pSrcFile==NULL || (pSrcFile->h<0) ){
          rc = SQLITE_INTERNAL;
          sqlite3_mutex_leave(srcdb->mutex);
        }
      }
      if( rc ){
        /* unroll state changes and return error code */
        if( pFile->eFileLock > eFileLock ){
          pFile->pMethod->xUnlock(id, eFileLock);
        }
        return rc;
      }else{
        /* both databases are locked appropriately, copy file data
         ** and then unroll the locks we added. 
         */
        copyfile_state_t s;
        
        s = copyfile_state_alloc();
        if( fcopyfile(pSrcFile->h, pFile->h, s, COPYFILE_ALL) ){
          switch(errno) {
            case ENOMEM:
              rc = SQLITE_NOMEM;
              break;
            default:
              rc = SQLITE_INTERNAL;
          }
        }
        copyfile_state_free(s);
        if( srcLockRC==SQLITE_OK ){
          pSrcFile->pMethod->xUnlock(src_file, eSrcFileLock);
        }
        sqlite3BtreeLeave(pSrcBtree);
        sqlite3_mutex_leave(srcdb->mutex);
      }
      
      if( !rc && (SQLITE_OK==getDbPathForUnixFile(pFile, jPath)) ){
        jLen = strlcat(jPath, "-journal", MAXPATHLEN+9);
        if( jLen < MAXPATHLEN+9 ){
          int jfd = open(jPath, O_TRUNC);
          if( (jfd == -1) ){
            if ( errno!=ENOENT ){
              perror(jPath);
            }
          } else {
            fsync(jfd);
            close(jfd);
          }
        }
      }else{
        trc=rc;
      }
      if( !trc ){
        trc = pFile->pMethod->xSync(id, SQLITE_SYNC_FULL);
      }
      if( pFile->eFileLock > eFileLock ){
        int unlockRC = pFile->pMethod->xUnlock(id, SQLITE_LOCK_SHARED);
        if (!rc) rc = unlockRC;
      }
      if( pFile->eFileLock > eFileLock ){
        int unlockRC = pFile->pMethod->xUnlock(id, SQLITE_LOCK_NONE);
        if (!rc) rc = unlockRC;
      }
      if( trc ){
        return trc;
      }
      return rc;
    }
#endif /* (SQLITE_ENABLE_APPLE_SPI>0) && defined(__APPLE__) */
  }
  return SQLITE_ERROR;
}

/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
................................................................................
    if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */
    close(fd); /* silently leak if fail, in error */
    return SQLITE_IOERR_ACCESS;
  }
  if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
  }
  if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) {
    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
  }
#endif
  
#if SQLITE_ENABLE_LOCKING_STYLE
#if SQLITE_PREFER_PROXY_LOCKING
  isAutoProxy = 1;
#endif
  if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
................................................................................
        goto open_finished;
      }
      useProxy = !(fsInfo.f_flags&MNT_LOCAL);
    }
    if( useProxy ){
      rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
      if( rc==SQLITE_OK ){
        /* cache the pMethod in case the transform fails */
        const struct sqlite3_io_methods *pMethod = pFile->pMethods;
        rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
        if( rc!=SQLITE_OK ){
          /* Use unixClose to clean up the resources added in fillInUnixFile 
          ** and clear all the structure's references.  Specifically, 
          ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op 
          */
          if( pMethod!=NULL ){
            pMethod->xClose(pFile);
          }else{
            unixClose(pFile);
          }
          return rc;
        }
      }
      goto open_finished;
    }
  }
#endif
................................................................................
/*
** pFile is a file that has been opened by a prior xOpen call.  dbPath
** is a string buffer at least MAXPATHLEN+1 characters in size.
**
** This routine find the filename associated with pFile and writes it
** int dbPath.
*/
static int getDbPathForUnixFile(unixFile *pFile, char *dbPath){
#if defined(__APPLE__)
  if( pFile->pMethod == &afpIoMethods ){
    /* afp style keeps a reference to the db path in the filePath field 
    ** of the struct */
    assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
    strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
  } else
................................................................................
  char dbPath[MAXPATHLEN+1];       /* Name of the database file */
  char *lockPath=NULL;
  int rc = SQLITE_OK;
  
  if( pFile->eFileLock!=NO_LOCK ){
    return SQLITE_BUSY;
  }
  getDbPathForUnixFile(pFile, dbPath);
  if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
    lockPath=NULL;
  }else{
    lockPath=(char *)path;
  }
  
  OSTRACE(("TRANSPROXY  %d for %s pid=%d\n", pFile->h,
................................................................................
        pCtx->conchHeld = -1; /* read only FS/ lockless */
        rc = SQLITE_OK;
      }
    }
  }  
  if( rc==SQLITE_OK && lockPath ){
    pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
    if( pCtx->lockProxyPath==NULL ){
      rc = SQLITE_NOMEM;
    }
  }

  if( rc==SQLITE_OK ){
    pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
    if( pCtx->dbPath==NULL ){
      rc = SQLITE_NOMEM;
    }

Changes to src/os_win.c.

1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
      *(int*)pArg = ((winFile*)id)->locktype;
      return SQLITE_OK;
    }
    case SQLITE_LAST_ERRNO: {
      *(int*)pArg = (int)((winFile*)id)->lastErrno;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
      sqlite3_int64 sz = *(sqlite3_int64*)pArg;
      winTruncate(id, sz);
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
      sqlite3_int64 sz = *(sqlite3_int64*)pArg;
      SimulateIOErrorBenign(1);
      winTruncate(id, sz);
      SimulateIOErrorBenign(0);
      return SQLITE_OK;
    }







<
<
<
<
<







1142
1143
1144
1145
1146
1147
1148





1149
1150
1151
1152
1153
1154
1155
      *(int*)pArg = ((winFile*)id)->locktype;
      return SQLITE_OK;
    }
    case SQLITE_LAST_ERRNO: {
      *(int*)pArg = (int)((winFile*)id)->lastErrno;
      return SQLITE_OK;
    }





    case SQLITE_FCNTL_SIZE_HINT: {
      sqlite3_int64 sz = *(sqlite3_int64*)pArg;
      SimulateIOErrorBenign(1);
      winTruncate(id, sz);
      SimulateIOErrorBenign(0);
      return SQLITE_OK;
    }

Changes to src/pragma.c.

1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
  **   PRAGMA wal_autocheckpoint = N
  **
  ** Configure a database connection to automatically checkpoint a database
  ** after accumulating N frames in the log. Or query for the current value
  ** of N.
  */
  if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
    sqlite3_int64 ret;
    if( zRight ){
      int nAuto = atoi(zRight);
      sqlite3_wal_autocheckpoint(db, nAuto);
    }
    if( db->xWalCallback==sqlite3WalDefaultHook ){
      ret = SQLITE_PTR_TO_INT(db->pWalArg);
    }else{
      ret = 0;
    }
    returnSingleInt(pParse, "wal_autocheckpoint", &ret);
  }else
#endif

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  /*
  ** Report the current state of file logs for all databases
  */







|





|
<
<

|







1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424


1425
1426
1427
1428
1429
1430
1431
1432
1433
  **   PRAGMA wal_autocheckpoint = N
  **
  ** Configure a database connection to automatically checkpoint a database
  ** after accumulating N frames in the log. Or query for the current value
  ** of N.
  */
  if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
    i64 walArg = 0;
    if( zRight ){
      int nAuto = atoi(zRight);
      sqlite3_wal_autocheckpoint(db, nAuto);
    }
    if( db->xWalCallback==sqlite3WalDefaultHook ){
      walArg = SQLITE_PTR_TO_INT(db->pWalArg);


    }
    returnSingleInt(pParse, "wal_autocheckpoint", &walArg);
  }else
#endif

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  /*
  ** Report the current state of file logs for all databases
  */

Added src/sqlite3_private.h.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 *  sqlite3_private.h
 */

#ifndef _SQLITE3_PRIVATE_H
#define _SQLITE3_PRIVATE_H

/*
** Pass the SQLITE_TRUNCATE_DATABASE operation code to sqlite3_file_control() 
** to truncate a database and its associated journal file to zero length.
*/
#define SQLITE_TRUNCATE_DATABASE      101

/*
** Pass the SQLITE_REPLACE_DATABASE operation code to sqlite3_file_control() 
** and a sqlite3 pointer to another open database file to safely copy the 
** contents of that database file into the receiving database.
*/
#define SQLITE_REPLACE_DATABASE       102

#endif

Changes to src/test1.c.

3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140


















3141
3142
3143
3144
3145
3146
3147
....
4680
4681
4682
4683
4684
4685
4686



























































































4687
4688
4689
4690
4691
4692
4693
....
5019
5020
5021
5022
5023
5024
5025

5026
5027
5028
5029
5030
5031
5032
....
5103
5104
5105
5106
5107
5108
5109


5110
5111
5112
5113
5114
5115
5116
  sqlite3_stmt *pStmt;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT");
    return TCL_ERROR;
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  sqlite3_clear_bindings(0); /* test for handling NULL <rdar://problem/6646331> */
  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
  return TCL_OK;
}



















/*
** Usage:   sqlite3_sleep MILLISECONDS
*/
static int test_sleep(
  void * clientData,
  Tcl_Interp *interp,
................................................................................
      return TCL_ERROR;
    }
  }
#endif
  return TCL_OK;  
}





























































































/*
** tclcmd:   sqlite3_vfs_list
**
**   Return a tcl list containing the names of all registered vfs's.
*/
static int vfs_list(
................................................................................
     { "sqlite3_bind_text",             test_bind_text     ,0 },
     { "sqlite3_bind_text16",           test_bind_text16   ,0 },
     { "sqlite3_bind_blob",             test_bind_blob     ,0 },
     { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},
     { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0},
     { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0},
     { "sqlite3_clear_bindings",        test_clear_bindings, 0},

     { "sqlite3_sleep",                 test_sleep,          0},
     { "sqlite3_errcode",               test_errcode       ,0 },
     { "sqlite3_extended_errcode",      test_ex_errcode    ,0 },
     { "sqlite3_errmsg",                test_errmsg        ,0 },
     { "sqlite3_errmsg16",              test_errmsg16      ,0 },
     { "sqlite3_open",                  test_open          ,0 },
     { "sqlite3_open16",                test_open16        ,0 },
................................................................................
     { "vfs_unlink_test",            vfs_unlink_test,     0   },
     { "vfs_initfail_test",          vfs_initfail_test,   0   },
     { "vfs_unregister_all",         vfs_unregister_all,  0   },
     { "vfs_reregister_all",         vfs_reregister_all,  0   },
     { "file_control_test",          file_control_test,   0   },
     { "file_control_lasterrno_test", file_control_lasterrno_test,  0   },
     { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },


     { "sqlite3_vfs_list",           vfs_list,     0   },

     /* Functions from os.h */
#ifndef SQLITE_OMIT_UTF16
     { "add_test_collate",        test_collate, 0            },
     { "add_test_collate_needed", test_collate_needed, 0     },
     { "add_test_function",       test_function, 0           },







<



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







>
>







3130
3131
3132
3133
3134
3135
3136

3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
....
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
....
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
....
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
  sqlite3_stmt *pStmt;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT");
    return TCL_ERROR;
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;

  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
  return TCL_OK;
}

/*
 ** Usage:   sqlite3_clear_bindings STMT
 **
 */
static int test_clear_bindings_null(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){  
  if( objc!=1 ){
    return TCL_ERROR;
  }
  /* test for handling NULL <rdar://problem/6646331> */
  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(0)));
  return TCL_OK;
}

/*
** Usage:   sqlite3_sleep MILLISECONDS
*/
static int test_sleep(
  void * clientData,
  Tcl_Interp *interp,
................................................................................
      return TCL_ERROR;
    }
  }
#endif
  return TCL_OK;  
}

#ifdef __APPLE__
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/errno.h>
#endif

/*
 ** tclcmd:   path_is_local PWD
 */
static int path_is_local(
  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  sqlite3 *db;
  const char *zPath;
  int nPath;
  
  if( objc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
                     Tcl_GetStringFromObj(objv[0], 0), " PATH", 0);
    return TCL_ERROR;
  }
  zPath = Tcl_GetStringFromObj(objv[1], &nPath);
  
#ifdef __APPLE__
  {
    struct statfs fsInfo;
    if( statfs(zPath, &fsInfo) == -1 ){
      int err = errno;
      Tcl_AppendResult(interp, "Error calling statfs on path",
                       Tcl_NewIntObj(err), 0);
      return TCL_ERROR;
    }
    if( fsInfo.f_flags&MNT_LOCAL ){
      Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); 
    } else {
      Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); 
    }
  }
#else
  Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); 
#endif
  
  return TCL_OK;  
}

/*
 ** tclcmd:   path_is_dos PWD
 */
static int path_is_dos(
  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  sqlite3 *db;
  const char *zPath;
  int nPath;
  
  if( objc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
                     Tcl_GetStringFromObj(objv[0], 0), " PATH", 0);
    return TCL_ERROR;
  }
  zPath = Tcl_GetStringFromObj(objv[1], &nPath);
  
#ifdef __APPLE__
  {
    struct statfs fsInfo;
    if( statfs(zPath, &fsInfo) == -1 ){
      int err = errno;
      Tcl_AppendResult(interp, "Error calling statfs on path",
                       Tcl_NewIntObj(err), 0);
      return TCL_ERROR;
    }
    if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
      Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); 
    } else if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) {
      Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); 
    } else {
      Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); 
    }
  }
#else
  Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); 
#endif
  
  return TCL_OK;  
}

/*
** tclcmd:   sqlite3_vfs_list
**
**   Return a tcl list containing the names of all registered vfs's.
*/
static int vfs_list(
................................................................................
     { "sqlite3_bind_text",             test_bind_text     ,0 },
     { "sqlite3_bind_text16",           test_bind_text16   ,0 },
     { "sqlite3_bind_blob",             test_bind_blob     ,0 },
     { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},
     { "sqlite3_bind_parameter_name",   test_bind_parameter_name,  0},
     { "sqlite3_bind_parameter_index",  test_bind_parameter_index, 0},
     { "sqlite3_clear_bindings",        test_clear_bindings, 0},
     { "sqlite3_clear_bindings_null",   test_clear_bindings_null, 0},
     { "sqlite3_sleep",                 test_sleep,          0},
     { "sqlite3_errcode",               test_errcode       ,0 },
     { "sqlite3_extended_errcode",      test_ex_errcode    ,0 },
     { "sqlite3_errmsg",                test_errmsg        ,0 },
     { "sqlite3_errmsg16",              test_errmsg16      ,0 },
     { "sqlite3_open",                  test_open          ,0 },
     { "sqlite3_open16",                test_open16        ,0 },
................................................................................
     { "vfs_unlink_test",            vfs_unlink_test,     0   },
     { "vfs_initfail_test",          vfs_initfail_test,   0   },
     { "vfs_unregister_all",         vfs_unregister_all,  0   },
     { "vfs_reregister_all",         vfs_reregister_all,  0   },
     { "file_control_test",          file_control_test,   0   },
     { "file_control_lasterrno_test", file_control_lasterrno_test,  0   },
     { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
     { "path_is_local",              path_is_local,  0   },
     { "path_is_dos",                path_is_dos,  0   },
     { "sqlite3_vfs_list",           vfs_list,     0   },

     /* Functions from os.h */
#ifndef SQLITE_OMIT_UTF16
     { "add_test_collate",        test_collate, 0            },
     { "add_test_collate_needed", test_collate_needed, 0     },
     { "add_test_function",       test_function, 0           },

Changes to src/test_config.c.

524
525
526
527
528
529
530
531
















532
533
534
535
536
537
538
#endif

#ifdef YYTRACKMAXSTACKDEPTH
  Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "0", TCL_GLOBAL_ONLY);
#endif

















#define LINKVAR(x) { \
    static const int cv_ ## x = SQLITE_ ## x; \
    Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
                TCL_LINK_INT | TCL_LINK_READ_ONLY); }

  LINKVAR( MAX_LENGTH );
  LINKVAR( MAX_COLUMN );







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
#endif

#ifdef YYTRACKMAXSTACKDEPTH
  Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "yytrackmaxstackdepth", "0", TCL_GLOBAL_ONLY);
#endif
  
#ifdef __APPLE__
# if  defined(__ppc__)
  Tcl_SetVar2(interp, "os_options", "arch", "ppc", TCL_GLOBAL_ONLY);
# elif defined(__i386__)
  Tcl_SetVar2(interp, "os_options", "arch", "i386", TCL_GLOBAL_ONLY);
# elif defined(__x86_64__)
  Tcl_SetVar2(interp, "os_options", "arch", "x86_64", TCL_GLOBAL_ONLY);
# elif defined(__arm__)
  Tcl_SetVar2(interp, "os_options", "arch", "arm", TCL_GLOBAL_ONLY);
# else
#  error Unrecognized architecture for exec_options
# endif
#else
  Tcl_SetVar2(interp, "os_options", "arch", "unknown", TCL_GLOBAL_ONLY);
#endif
  
#define LINKVAR(x) { \
    static const int cv_ ## x = SQLITE_ ## x; \
    Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
                TCL_LINK_INT | TCL_LINK_READ_ONLY); }

  LINKVAR( MAX_LENGTH );
  LINKVAR( MAX_COLUMN );

Changes to src/vdbe.c.

562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeMutexArrayEnter(p);
  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
    ** sqlite3_column_text16() failed.  */
    goto no_mem;
  }
  assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
  p->rc = SQLITE_OK;
  assert( p->explain==0 );
  p->pResultSet = 0;
  db->busyHandler.nBusy = 0;
  CHECK_FOR_INTERRUPT;
  sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK







|







562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeMutexArrayEnter(p);
  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
    ** sqlite3_column_text16() failed.  */
    goto no_mem;
  }
  assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || ((p->rc&0xFF) == SQLITE_LOCKED));
  p->rc = SQLITE_OK;
  assert( p->explain==0 );
  p->pResultSet = 0;
  db->busyHandler.nBusy = 0;
  CHECK_FOR_INTERRUPT;
  sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK

Changes to src/vdbeapi.c.

36
37
38
39
40
41
42
43

44
45
46
47
48
49
50

/*
** Check on a Vdbe to make sure it has not been finalized.  Log
** an error and return true if it has been finalized (or is otherwise
** invalid).  Return false if it is ok.
*/
static int vdbeSafety(Vdbe *p){
  if( p->db==0 ){

    sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
    return 1;
  }else{
    return 0;
  }
}
static int vdbeSafetyNotNull(Vdbe *p){







|
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

/*
** Check on a Vdbe to make sure it has not been finalized.  Log
** an error and return true if it has been finalized (or is otherwise
** invalid).  Return false if it is ok.
*/
static int vdbeSafety(Vdbe *p){
  sqlite3* db = p->db;
  if((db==0) || (db->magic != SQLITE_MAGIC_OPEN) || ((p->magic != VDBE_MAGIC_RUN) && (p->magic != VDBE_MAGIC_HALT))){
    sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
    return 1;
  }else{
    return 0;
  }
}
static int vdbeSafetyNotNull(Vdbe *p){

Changes to test/bind.test.

652
653
654
655
656
657
658



659
660
661
662
663
664
665
  sqlite3_reset $VM
  sqlite3_clear_bindings $VM
  sqlite3_step $VM
  list [sqlite3_column_type $VM 0] [sqlite3_column_type $VM 1] \
               [sqlite3_column_type $VM 2]
} {NULL NULL NULL}
sqlite3_finalize $VM




#--------------------------------------------------------------------
# These tests attempt to reproduce bug #3463.
#
proc param_names {db zSql} {
  set ret [list]
  set VM [sqlite3_prepare db $zSql -1 TAIL]







>
>
>







652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
  sqlite3_reset $VM
  sqlite3_clear_bindings $VM
  sqlite3_step $VM
  list [sqlite3_column_type $VM 0] [sqlite3_column_type $VM 1] \
               [sqlite3_column_type $VM 2]
} {NULL NULL NULL}
sqlite3_finalize $VM
do_test bind-13.5 {
  sqlite3_clear_bindings_null
} {0}

#--------------------------------------------------------------------
# These tests attempt to reproduce bug #3463.
#
proc param_names {db zSql} {
  set ret [list]
  set VM [sqlite3_prepare db $zSql -1 TAIL]

Changes to test/exclusive.test.

391
392
393
394
395
396
397
398
399
400
401
402
403

404
405
406
407
408
409
410
#
db close
sqlite db test.db

# if we're using proxy locks, we use 3 filedescriptors for a db
# that is open but NOT writing changes, normally
# sqlite uses 1 (proxy locking adds the conch and the local lock)
set using_proxy 0
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
  set using_proxy $value
}
set extrafds 0
if {$using_proxy!=0} {

  set extrafds 2
} 

do_test exclusive-5.0 {
  execsql {
    CREATE TABLE abc(a UNIQUE, b UNIQUE, c UNIQUE);
    BEGIN;







<
<
<
<

<
>







391
392
393
394
395
396
397




398

399
400
401
402
403
404
405
406
#
db close
sqlite db test.db

# if we're using proxy locks, we use 3 filedescriptors for a db
# that is open but NOT writing changes, normally
# sqlite uses 1 (proxy locking adds the conch and the local lock)




set extrafds 0

if {[forced_proxy_locking]} {
  set extrafds 2
} 

do_test exclusive-5.0 {
  execsql {
    CREATE TABLE abc(a UNIQUE, b UNIQUE, c UNIQUE);
    BEGIN;

Changes to test/journal3.test.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl

#-------------------------------------------------------------------------
# If a connection is required to create a journal file, it creates it with 
# the same file-system permissions as the database file itself. Test this.
#
if {$::tcl_platform(platform) == "unix"} {

  set umask [exec /bin/sh -c umask]
  faultsim_delete_and_reopen
  do_test journal3-1.1 { execsql { CREATE TABLE tx(y, z) } } {}

  foreach {tn permissions} {
   1 00644







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl

#-------------------------------------------------------------------------
# If a connection is required to create a journal file, it creates it with 
# the same file-system permissions as the database file itself. Test this.
#
if {$::tcl_platform(platform) == "unix" && ![path_is_dos "."]} {

  set umask [exec /bin/sh -c umask]
  faultsim_delete_and_reopen
  do_test journal3-1.1 { execsql { CREATE TABLE tx(y, z) } } {}

  foreach {tn permissions} {
   1 00644

Changes to test/lock5.test.

102
103
104
105
106
107
108



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191
192
193
194
195

file delete -force test.db
if {[catch {sqlite3 db test.db -vfs unix-flock} msg]} {
  finish_test
  return
}




do_test lock5-flock.1 {
  sqlite3 db test.db -vfs unix-flock
  execsql {
    CREATE TABLE t1(a, b);
    BEGIN;
    INSERT INTO t1 VALUES(1, 2);
  }
} {}

# Make sure we are not accidentally using the dotfile locking scheme.
do_test lock5-flock.2 {
  file exists test.db.lock
} {0}

do_test lock5-flock.3 {
  catch { sqlite3 db2 test.db -vfs unix-flock }
  catchsql { SELECT * FROM t1 } db2
} {1 {database is locked}}

do_test lock5-flock.4 {
  execsql COMMIT
  catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}

do_test lock5-flock.5 {
  execsql BEGIN
  catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}

do_test lock5-flock.6 {
  execsql {SELECT * FROM t1}
  catchsql { SELECT * FROM t1 } db2
} {1 {database is locked}}

do_test lock5-flock.7 {
  db close
  catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}

do_test lock5-flock.8 {
  db2 close
} {}

#####################################################################

do_test lock5-none.1 {
  sqlite3 db test.db -vfs unix-none
  sqlite3 db2 test.db -vfs unix-none
  execsql {
    BEGIN;
    INSERT INTO t1 VALUES(3, 4);
  }
} {}
do_test lock5-none.2 {
  execsql { SELECT * FROM t1 }
} {1 2 3 4}
do_test lock5-flock.3 {
  execsql { SELECT * FROM t1 } db2
} {1 2}
do_test lock5-none.4 {
  execsql { 
    BEGIN;
    SELECT * FROM t1;
  } db2
} {1 2}
do_test lock5-none.5 {
  execsql COMMIT
  execsql {SELECT * FROM t1} db2
} {1 2}

ifcapable memorymanage {
  do_test lock5-none.6 {
    sqlite3_release_memory 1000000
    execsql {SELECT * FROM t1} db2
  } {1 2 3 4}
}

do_test lock5-flock.X {
  db close
  db2 close
} {}


ifcapable lock_proxy_pragmas {
  set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy
}

finish_test







>
>
>
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|

|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
>






102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

file delete -force test.db
if {[catch {sqlite3 db test.db -vfs unix-flock} msg]} {
  finish_test
  return
}

# Only run the flock tests on a local file system
if { [path_is_local "."] } {

  do_test lock5-flock.1 {
    sqlite3 db test.db -vfs unix-flock
    execsql {
      CREATE TABLE t1(a, b);
      BEGIN;
      INSERT INTO t1 VALUES(1, 2);
    }
  } {}

  # Make sure we are not accidentally using the dotfile locking scheme.
  do_test lock5-flock.2 {
    file exists test.db.lock
  } {0}

  do_test lock5-flock.3 {
    catch { sqlite3 db2 test.db -vfs unix-flock }
    catchsql { SELECT * FROM t1 } db2
  } {1 {database is locked}}

  do_test lock5-flock.4 {
    execsql COMMIT
    catchsql { SELECT * FROM t1 } db2
  } {0 {1 2}}

  do_test lock5-flock.5 {
    execsql BEGIN
    catchsql { SELECT * FROM t1 } db2
  } {0 {1 2}}

  do_test lock5-flock.6 {
    execsql {SELECT * FROM t1}
    catchsql { SELECT * FROM t1 } db2
  } {1 {database is locked}}

  do_test lock5-flock.7 {
    db close
    catchsql { SELECT * FROM t1 } db2
  } {0 {1 2}}

  do_test lock5-flock.8 {
    db2 close
  } {}

  #####################################################################

  do_test lock5-none.1 {
    sqlite3 db test.db -vfs unix-none
    sqlite3 db2 test.db -vfs unix-none
    execsql {
      BEGIN;
      INSERT INTO t1 VALUES(3, 4);
    }
  } {}
  do_test lock5-none.2 {
    execsql { SELECT * FROM t1 }
  } {1 2 3 4}
  do_test lock5-flock.3 {
    execsql { SELECT * FROM t1 } db2
  } {1 2}
  do_test lock5-none.4 {
    execsql { 
      BEGIN;
      SELECT * FROM t1;
    } db2
  } {1 2}
  do_test lock5-none.5 {
    execsql COMMIT
    execsql {SELECT * FROM t1} db2
  } {1 2}

  ifcapable memorymanage {
    do_test lock5-none.6 {
      sqlite3_release_memory 1000000
      execsql {SELECT * FROM t1} db2
    } {1 2 3 4}
  }

  do_test lock5-flock.X {
    db close
    db2 close
  } {}
}

ifcapable lock_proxy_pragmas {
  set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy
}

finish_test

Changes to test/lock_proxy.test.

22
23
24
25
26
27
28

29
30
31
32
33

34
35
36

37
38
39











40

41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57


58
59
60
61
62
63

64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80



81
82
83
84
85
86
87
88


89
90
91
92
93
94
95
96


97
98
99
100
101
102
103
if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
  finish_test
  return
}
db close
file delete -force test.db.lock


ifcapable lock_proxy_pragmas {
  set ::using_proxy 0
  foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
    set ::using_proxy $value
  }

  # Disable the proxy locking for these tests
  set env(SQLITE_FORCE_PROXY_LOCKING) "0"
}



#####################################################################













# test proxy locking readonly file system handling
#
ifcapable lock_proxy_pragmas {

  if {[file exists /usr/bin/hdiutil]} {

    puts "Creating readonly file system for proxy locking tests..."
    if {[file exists /Volumes/readonly]} {
      exec hdiutil detach /Volumes/readonly
    }
    if {[file exists readonly.dmg]} {
      file delete readonly.dmg
    }
    exec hdiutil create -megabytes 1 -fs HFS+ readonly.dmg -volname readonly
    exec hdiutil attach readonly.dmg
    set sqlite_hostid_num 4
    set env(SQLITE_FORCE_PROXY_LOCKING) "1"



    sqlite3 db2 /Volumes/readonly/test1.db 
    execsql {
      create table x(y);
    } db2
    db2 close


    set sqlite_hostid_num 5
    sqlite3 db2 /Volumes/readonly/test2.db 
    execsql {
      create table x(y);
    } db2
    db2 close


    set env(SQLITE_FORCE_PROXY_LOCKING) "0"
    sqlite3 db2 /Volumes/readonly/test3.db 
    execsql {
      create table x(y);
    } db2
    db2 close
    set env(SQLITE_FORCE_PROXY_LOCKING) "1"
    exec hdiutil detach /Volumes/readonly
    exec hdiutil attach -readonly readonly.dmg




    do_test lock_proxy2.0 {
      sqlite3 db2 /Volumes/readonly/test1.db
      catchsql {
        select * from sqlite_master;
      } db2
    } {1 {database is locked}}
    catch { db2 close }
    


    do_test lock_proxy2.1 {
      sqlite3 db2 /Volumes/readonly/test2.db
      catchsql {
        select * from sqlite_master;
      } db2
    } {0 {table x x 2 {CREATE TABLE x(y)}}}
    catch { db2 close }



    do_test lock_proxy2.2 {
      sqlite3 db2 /Volumes/readonly/test3.db
      catchsql {
        select * from sqlite_master;
      } db2
    } {0 {table x x 2 {CREATE TABLE x(y)}}}
    catch { db2 close }







>





>
|
|
|
>
|

<
>
>
>
>
>
>
>
>
>
>
>

>
|
|
<
>











<
<

>
>






>







>






<



>
>
>








>
>








>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67
68


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
  finish_test
  return
}
db close
file delete -force test.db.lock

#####################################################################
ifcapable lock_proxy_pragmas {
  set ::using_proxy 0
  foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
    set ::using_proxy $value
  }

  # enable the proxy locking for these tests
  set env(SQLITE_FORCE_PROXY_LOCKING) "1"

  # test conch file creation
  #


  catch { file delete lock_proxy_test.db }
  catch { file delete .lock_proxy_test.db-conch }
  # test that proxy locking mode creates conch files
  do_test lock_proxy1.0 {
    sqlite3 db2 lock_proxy_test.db
    catchsql {
      create table x(y);
    } db2
    file exists .lock_proxy_test.db-conch
  } {1}
  catch { db2 close }


  # test proxy locking readonly file system handling
  #


  if {[file exists /usr/bin/hdiutil]} {

    puts "Creating readonly file system for proxy locking tests..."
    if {[file exists /Volumes/readonly]} {
      exec hdiutil detach /Volumes/readonly
    }
    if {[file exists readonly.dmg]} {
      file delete readonly.dmg
    }
    exec hdiutil create -megabytes 1 -fs HFS+ readonly.dmg -volname readonly
    exec hdiutil attach readonly.dmg



    # create test1.db and a .test1.db-conch for host4
    set sqlite_hostid_num 4
    sqlite3 db2 /Volumes/readonly/test1.db 
    execsql {
      create table x(y);
    } db2
    db2 close

    # create test2.db and a .test2.db-conch for host5
    set sqlite_hostid_num 5
    sqlite3 db2 /Volumes/readonly/test2.db 
    execsql {
      create table x(y);
    } db2
    db2 close

    # create test3.db without a conch file
    set env(SQLITE_FORCE_PROXY_LOCKING) "0"
    sqlite3 db2 /Volumes/readonly/test3.db 
    execsql {
      create table x(y);
    } db2
    db2 close

    exec hdiutil detach /Volumes/readonly
    exec hdiutil attach -readonly readonly.dmg

    # test that an unwritable, host-mismatched conch file prevents 
    # read only proxy-locking mode database access
    set env(SQLITE_FORCE_PROXY_LOCKING) "1"
    do_test lock_proxy2.0 {
      sqlite3 db2 /Volumes/readonly/test1.db
      catchsql {
        select * from sqlite_master;
      } db2
    } {1 {database is locked}}
    catch { db2 close }
    
    # test that an unwritable, host-matching conch file allows
    # read only proxy-locking mode database access
    do_test lock_proxy2.1 {
      sqlite3 db2 /Volumes/readonly/test2.db
      catchsql {
        select * from sqlite_master;
      } db2
    } {0 {table x x 2 {CREATE TABLE x(y)}}}
    catch { db2 close }

    # test that an unwritable, nonexistant conch file allows
    # read only proxy-locking mode database access
    do_test lock_proxy2.2 {
      sqlite3 db2 /Volumes/readonly/test3.db
      catchsql {
        select * from sqlite_master;
      } db2
    } {0 {table x x 2 {CREATE TABLE x(y)}}}
    catch { db2 close }

Changes to test/manydb.test.

18
19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
set testdir [file dirname $argv0]
source $testdir/tester.tcl

set N 300
# if we're using proxy locks, we use 5 filedescriptors for a db
# that is open and in the middle of writing changes, normally
# sqlite uses 3 (proxy locking adds the conch and the local lock)
set using_proxy 0
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
  set using_proxy value
}
set num_fd_per_openwrite_db 3
if {$using_proxy>0} {

  set num_fd_per_openwrite_db 5
} 

# First test how many file descriptors are available for use. To open a
# database for writing SQLite requires 3 file descriptors (the database, the
# journal and the directory).
set filehandles {}







<
<
<
<

<
>







18
19
20
21
22
23
24




25

26
27
28
29
30
31
32
33
set testdir [file dirname $argv0]
source $testdir/tester.tcl

set N 300
# if we're using proxy locks, we use 5 filedescriptors for a db
# that is open and in the middle of writing changes, normally
# sqlite uses 3 (proxy locking adds the conch and the local lock)




set num_fd_per_openwrite_db 3

if {[forced_proxy_locking]} {
  set num_fd_per_openwrite_db 5
} 

# First test how many file descriptors are available for use. To open a
# database for writing SQLite requires 3 file descriptors (the database, the
# journal and the directory).
set filehandles {}

Changes to test/pager1.test.

536
537
538
539
540
541
542




543
544
545
546
547
548
549
550
...
557
558
559
560
561
562
563

564
565
566
567
568
569
570
....
1073
1074
1075
1076
1077
1078
1079


1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120





1121
1122
1123
1124
1125
1126
1127
....
1286
1287
1288
1289
1290
1291
1292





1293
1294
1295

1296
1297
1298
1299
1300
1301
1302
....
1911
1912
1913
1914
1915
1916
1917

1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944

1945
1946
1947
1948
1949
1950

1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972

1973
1974
1975
1976
1977
1978
1979
  2 { 
    # This test depends on the underlying VFS being able to open paths
    # 512 bytes in length. The idea is to create a hot-journal file that
    # contains a master-journal pointer so large that it could contain
    # a valid page record (if the file page-size is 512 bytes). So as to
    # make sure SQLite doesn't get confused by this.
    #




    set nPadding [expr 511 - $::mj_filename_length]
    if {$tcl_platform(platform)=="windows"} {
      # TBD need to figure out how to do this correctly for Windows!!!
      set nPadding [expr 255 - $::mj_filename_length]
    }

    # We cannot just create a really long database file name to open, as
    # Linux limits a single component of a path to 255 bytes by default
................................................................................
      set p [string repeat $dirname $nDir]
      file mkdir $p
      cd $p
    }

    set padding [string repeat x [expr $nPadding %32]]
    set prefix "test.db${padding}"

  }
} {
  eval $tcl
  foreach {tn2 sql} {
    o { 
      PRAGMA main.synchronous=OFF;
      PRAGMA aux.synchronous=OFF;
................................................................................
#   $sql: SQL to execute.
#   $res: Expected result of executing $sql.
#   $js:  The expected size of the journal file, in bytes, after executing
#         the SQL script. Or -1 if the journal is not expected to exist.
#   $ws:  The expected size of the WAL file, in bytes, after executing
#         the SQL script. Or -1 if the WAL is not expected to exist.
#


ifcapable wal {
  faultsim_delete_and_reopen
  foreach {tn sql res js ws} [subst {
  
    1  {
      CREATE TABLE t1(a, b);
      PRAGMA auto_vacuum=OFF;
      PRAGMA synchronous=NORMAL;
      PRAGMA page_size=1024;
      PRAGMA locking_mode=EXCLUSIVE;
      PRAGMA journal_mode=TRUNCATE;
      INSERT INTO t1 VALUES(1, 2);
    } {exclusive truncate} 0 -1
  
    2  {
      BEGIN IMMEDIATE;
        SELECT * FROM t1;
      COMMIT;
    } {1 2} 0 -1
  
    3  {
      BEGIN;
        SELECT * FROM t1;
      COMMIT;
    } {1 2} 0 -1
  
    4  { PRAGMA journal_mode = WAL }    wal    -1 -1
    5  { INSERT INTO t1 VALUES(3, 4) }  {}     -1 [wal_file_size 1 1024]
    6  { PRAGMA locking_mode = NORMAL } normal -1 [wal_file_size 1 1024]
    7  { INSERT INTO t1 VALUES(5, 6); } {}     -1 [wal_file_size 2 1024]
  
    8  { PRAGMA journal_mode = TRUNCATE } truncate          0 -1
    9  { INSERT INTO t1 VALUES(7, 8) }    {}                0 -1
    10 { SELECT * FROM t1 }               {1 2 3 4 5 6 7 8} 0 -1
  
  }] {
    do_execsql_test pager1-7.1.$tn.1 $sql $res
    catch { set J -1 ; set J [file size test.db-journal] }
    catch { set W -1 ; set W [file size test.db-wal] }
    do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws]
  }





}

do_test pager1-7.2.1 {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA locking_mode = EXCLUSIVE;
    CREATE TABLE t1(a, b);
................................................................................
    PRAGMA page_size = 4096;
    CREATE TABLE t1(a, b);
    CREATE TABLE t2(a, b);
  } db2
  sqlite3_backup B db2 main db main
  list [B step 10000] [B finish]
} {SQLITE_DONE SQLITE_OK}





do_test pager1-9.4.2 {
  list [file size test.db2] [file size test.db]
} {0 0}

db2 close

#-------------------------------------------------------------------------
# Test that regardless of the value returned by xSectorSize(), the
# minimum effective sector-size is 512 and the maximum 65536 bytes.
#
testvfs tv -default 1
................................................................................
do_test pager1-20.2.2 {
  execsql {
    BEGIN EXCLUSIVE;
    COMMIT;
  }
} {}


do_test pager1-20.3.1 {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql {
    PRAGMA cache_size = 10;
    PRAGMA journal_mode = wal;
    BEGIN;
      CREATE TABLE t1(x);
      CREATE TABLE t2(y);
      INSERT INTO t1 VALUES(a_string(800));
      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*   2 */
      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*   4 */
      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*   8 */
      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*  16 */
      INSERT INTO t1 SELECT a_string(800) FROM t1;         /*  32 */
    COMMIT;
  }
} {wal}
do_test pager1-20.3.2 {
  execsql {
    BEGIN;
    INSERT INTO t2 VALUES('xxxx');
  }
  recursive_select 32 t1
  execsql COMMIT
} {}


#-------------------------------------------------------------------------
# Test that a WAL database may not be opened if:
#
#   pager1-21.1.*: The VFS has an iVersion less than 2, or
#   pager1-21.2.*: The VFS does not provide xShmXXX() methods.
#

do_test pager1-21.0 {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def');
    INSERT INTO ko DEFAULT VALUES;
  }
} {wal}
do_test pager1-21.1 {
  testvfs tv -noshm 1
  sqlite3 db2 test.db -vfs tv
  catchsql { SELECT * FROM ko } db2
} {1 {unable to open database file}}
db2 close
tv delete
do_test pager1-21.2 {
  testvfs tv -iversion 1
  sqlite3 db2 test.db -vfs tv
  catchsql { SELECT * FROM ko } db2
} {1 {unable to open database file}}
db2 close
tv delete


#-------------------------------------------------------------------------
# Test that a "PRAGMA wal_checkpoint":
#
#   pager1-22.1.*: is a no-op on a non-WAL db, and
#   pager1-22.2.*: does not cause xSync calls with a synchronous=off db.
#







>
>
>
>
|







 







>







 







>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>







 







>
>
>
>
>
|
|
|
>







 







>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>






>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
...
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
....
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
....
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
....
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
  2 { 
    # This test depends on the underlying VFS being able to open paths
    # 512 bytes in length. The idea is to create a hot-journal file that
    # contains a master-journal pointer so large that it could contain
    # a valid page record (if the file page-size is 512 bytes). So as to
    # make sure SQLite doesn't get confused by this.
    #
    set target_length 511
    if { [forced_proxy_locking] } {
      set target_length 255
    }
    set nPadding [expr $target_length - $::mj_filename_length]
    if {$tcl_platform(platform)=="windows"} {
      # TBD need to figure out how to do this correctly for Windows!!!
      set nPadding [expr 255 - $::mj_filename_length]
    }

    # We cannot just create a really long database file name to open, as
    # Linux limits a single component of a path to 255 bytes by default
................................................................................
      set p [string repeat $dirname $nDir]
      file mkdir $p
      cd $p
    }

    set padding [string repeat x [expr $nPadding %32]]
    set prefix "test.db${padding}"
    set prefix
  }
} {
  eval $tcl
  foreach {tn2 sql} {
    o { 
      PRAGMA main.synchronous=OFF;
      PRAGMA aux.synchronous=OFF;
................................................................................
#   $sql: SQL to execute.
#   $res: Expected result of executing $sql.
#   $js:  The expected size of the journal file, in bytes, after executing
#         the SQL script. Or -1 if the journal is not expected to exist.
#   $ws:  The expected size of the WAL file, in bytes, after executing
#         the SQL script. Or -1 if the WAL is not expected to exist.
#
set do_wal_tests [wal_is_ok]
if { $do_wal_tests } {
  ifcapable wal {
    faultsim_delete_and_reopen
    foreach {tn sql res js ws} [subst {
    
      1  {
        CREATE TABLE t1(a, b);
        PRAGMA auto_vacuum=OFF;
        PRAGMA synchronous=NORMAL;
        PRAGMA page_size=1024;
        PRAGMA locking_mode=EXCLUSIVE;
        PRAGMA journal_mode=TRUNCATE;
        INSERT INTO t1 VALUES(1, 2);
      } {exclusive truncate} 0 -1
    
      2  {
        BEGIN IMMEDIATE;
          SELECT * FROM t1;
        COMMIT;
      } {1 2} 0 -1
    
      3  {
        BEGIN;
          SELECT * FROM t1;
        COMMIT;
      } {1 2} 0 -1
    
      4  { PRAGMA journal_mode = WAL }    wal    -1 -1
      5  { INSERT INTO t1 VALUES(3, 4) }  {}     -1 [wal_file_size 1 1024]
      6  { PRAGMA locking_mode = NORMAL } normal -1 [wal_file_size 1 1024]
      7  { INSERT INTO t1 VALUES(5, 6); } {}     -1 [wal_file_size 2 1024]
    
      8  { PRAGMA journal_mode = TRUNCATE } truncate          0 -1
      9  { INSERT INTO t1 VALUES(7, 8) }    {}                0 -1
      10 { SELECT * FROM t1 }               {1 2 3 4 5 6 7 8} 0 -1
    
    }] {
      do_execsql_test pager1-7.1.$tn.1 $sql $res
      catch { set J -1 ; set J [file size test.db-journal] }
      catch { set W -1 ; set W [file size test.db-wal] }
      do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws]
    }
  }
} else {
  do_test pager1-7.1.wal_is_not_ok {
    execsql { PRAGMA journal_mode = WAL }
  } {delete}
}

do_test pager1-7.2.1 {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA locking_mode = EXCLUSIVE;
    CREATE TABLE t1(a, b);
................................................................................
    PRAGMA page_size = 4096;
    CREATE TABLE t1(a, b);
    CREATE TABLE t2(a, b);
  } db2
  sqlite3_backup B db2 main db main
  list [B step 10000] [B finish]
} {SQLITE_DONE SQLITE_OK}
if { [path_is_dos "."] } {
  do_test pager1-9.4.2_dos {
    list [file size test.db2] [file size test.db]
  } {0 1}
} else {
  do_test pager1-9.4.2 {
    list [file size test.db2] [file size test.db]
  } {0 0}
}
db2 close

#-------------------------------------------------------------------------
# Test that regardless of the value returned by xSectorSize(), the
# minimum effective sector-size is 512 and the maximum 65536 bytes.
#
testvfs tv -default 1
................................................................................
do_test pager1-20.2.2 {
  execsql {
    BEGIN EXCLUSIVE;
    COMMIT;
  }
} {}

if { $do_wal_tests } {
  do_test pager1-20.3.1 {
    faultsim_delete_and_reopen
    db func a_string a_string
    execsql {
      PRAGMA cache_size = 10;
      PRAGMA journal_mode = wal;
      BEGIN;
        CREATE TABLE t1(x);
        CREATE TABLE t2(y);
        INSERT INTO t1 VALUES(a_string(800));
        INSERT INTO t1 SELECT a_string(800) FROM t1;         /*   2 */
        INSERT INTO t1 SELECT a_string(800) FROM t1;         /*   4 */
        INSERT INTO t1 SELECT a_string(800) FROM t1;         /*   8 */
        INSERT INTO t1 SELECT a_string(800) FROM t1;         /*  16 */
        INSERT INTO t1 SELECT a_string(800) FROM t1;         /*  32 */
      COMMIT;
    }
  } {wal}
  do_test pager1-20.3.2 {
    execsql {
      BEGIN;
      INSERT INTO t2 VALUES('xxxx');
    }
    recursive_select 32 t1
    execsql COMMIT
  } {}
}

#-------------------------------------------------------------------------
# Test that a WAL database may not be opened if:
#
#   pager1-21.1.*: The VFS has an iVersion less than 2, or
#   pager1-21.2.*: The VFS does not provide xShmXXX() methods.
#
if { $do_wal_tests } {
  do_test pager1-21.0 {
    faultsim_delete_and_reopen
    execsql {
      PRAGMA journal_mode = WAL;
      CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def');
      INSERT INTO ko DEFAULT VALUES;
    }
  } {wal}
  do_test pager1-21.1 {
    testvfs tv -noshm 1
    sqlite3 db2 test.db -vfs tv
    catchsql { SELECT * FROM ko } db2
  } {1 {unable to open database file}}
  db2 close
  tv delete
  do_test pager1-21.2 {
    testvfs tv -iversion 1
    sqlite3 db2 test.db -vfs tv
    catchsql { SELECT * FROM ko } db2
  } {1 {unable to open database file}}
  db2 close
  tv delete
}

#-------------------------------------------------------------------------
# Test that a "PRAGMA wal_checkpoint":
#
#   pager1-22.1.*: is a no-op on a non-WAL db, and
#   pager1-22.2.*: does not cause xSync calls with a synchronous=off db.
#

Changes to test/shared.test.

41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
    break
  }
}

# if we're using proxy locks, we use 2 filedescriptors for a db
# that is open but NOT yet locked, after a lock is taken we'll have 3, 
# normally sqlite uses 1 (proxy locking adds the conch and the local lock)
set using_proxy 0
foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
  set using_proxy $value
}
set extrafds_prelock 0
set extrafds_postlock 0
if {$using_proxy>0} {

  set extrafds_prelock 1
  set extrafds_postlock 2
} 

# $av is currently 0 if this loop iteration is to test with auto-vacuum turned
# off, and 1 if it is turned on. Increment it so that (1 -> no auto-vacuum) 
# and (2 -> auto-vacuum). The sole reason for this is so that it looks nicer







<
<
<
<


<
>







41
42
43
44
45
46
47




48
49

50
51
52
53
54
55
56
57
    break
  }
}

# if we're using proxy locks, we use 2 filedescriptors for a db
# that is open but NOT yet locked, after a lock is taken we'll have 3, 
# normally sqlite uses 1 (proxy locking adds the conch and the local lock)




set extrafds_prelock 0
set extrafds_postlock 0

if {[forced_proxy_locking]} {
  set extrafds_prelock 1
  set extrafds_postlock 2
} 

# $av is currently 0 if this loop iteration is to test with auto-vacuum turned
# off, and 1 if it is turned on. Increment it so that (1 -> no auto-vacuum) 
# and (2 -> auto-vacuum). The sole reason for this is so that it looks nicer

Changes to test/stat.test.

26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
db func a_string a_string

register_dbstat_vtab db
do_execsql_test stat-0.0 {
  CREATE VIRTUAL TABLE temp.stat USING dbstat;
  SELECT * FROM stat;
} {}

do_execsql_test stat-0.1 {
  PRAGMA journal_mode = WAL;
  PRAGMA journal_mode = delete;
  SELECT * FROM stat;
} {wal delete sqlite_master / 1 leaf 0 0 916 0}

do_test stat-1.0 {
  execsql {
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(b);
    INSERT INTO t1(rowid, a, b) VALUES(2, 2, 3);
    INSERT INTO t1(rowid, a, b) VALUES(3, 4, 5);
  }







>
|
|
|
|
|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
db func a_string a_string

register_dbstat_vtab db
do_execsql_test stat-0.0 {
  CREATE VIRTUAL TABLE temp.stat USING dbstat;
  SELECT * FROM stat;
} {}
if {[wal_is_ok]} {
  do_execsql_test stat-0.1 {
    PRAGMA journal_mode = WAL;
    PRAGMA journal_mode = delete;
    SELECT * FROM stat;
  } {wal delete sqlite_master / 1 leaf 0 0 916 0}
}
do_test stat-1.0 {
  execsql {
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(b);
    INSERT INTO t1(rowid, a, b) VALUES(2, 2, 3);
    INSERT INTO t1(rowid, a, b) VALUES(3, 4, 5);
  }

Changes to test/stmt.test.

26
27
28
29
30
31
32










33
34

35
36
37
38
39
40
41

42
43
44
45
46
47

48
49
50
51

52
53
54
55
56
57
58

59
60
61
62

63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#
# This only work if SQLITE_TEMP_STORE!=3
#
if {$::TEMP_STORE==3} {
  finish_test
  return
}










do_test stmt-1.2 {
  set sqlite_open_file_count

} {1}
do_test stmt-1.3 {
  execsql {
    BEGIN;
      INSERT INTO t1 VALUES(1, 1);
  }
  set sqlite_open_file_count

} {2}
do_test stmt-1.4 {
  execsql {
    INSERT INTO t1 SELECT a+1, b+1 FROM t1;
  }
  set sqlite_open_file_count

} {3}
do_test stmt-1.5 {
  execsql COMMIT
  set sqlite_open_file_count

} {1}
do_test stmt-1.6.1 {
  execsql {
    BEGIN;
      INSERT INTO t1 SELECT a+2, b+2 FROM t1;
  }
  set sqlite_open_file_count

} {2}
do_test stmt-1.6.2 {
  execsql { INSERT INTO t1 SELECT a+4, b+4 FROM t1 }
  set sqlite_open_file_count

} {3}
do_test stmt-1.7 {
  execsql COMMIT
  set sqlite_open_file_count

} {1}


proc filecount {testname sql expected} {
  uplevel [list do_test $testname [subst -nocommand {
    execsql BEGIN
    execsql { $sql }
    set ret [set sqlite_open_file_count]
    execsql ROLLBACK
    set ret
  }] $expected]
}

filecount stmt-2.1 { INSERT INTO t1 VALUES(9, 9)  } 2
filecount stmt-2.2 { REPLACE INTO t1 VALUES(9, 9) } 2
filecount stmt-2.3 { INSERT INTO t1 SELECT 9, 9   } 2
filecount stmt-2.4 { 
    INSERT INTO t1 SELECT 9, 9;
    INSERT INTO t1 SELECT 10, 10;
} 3

do_test stmt-2.5 {
  execsql { CREATE INDEX i1 ON t1(b) }
} {}
filecount stmt-2.6 { 
  REPLACE INTO t1 VALUES(5, 5);
  REPLACE INTO t1 VALUES(5, 5); 
} 3

finish_test







>
>
>
>
>
>
>
>
>
>


>







>






>




>







>




>




>



|






|


|
|
|



|







|


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#
# This only work if SQLITE_TEMP_STORE!=3
#
if {$::TEMP_STORE==3} {
  finish_test
  return
}

# if we're using proxy locks, we use 3 filedescriptors for a db
# that is open but NOT writing changes, normally
# sqlite uses 1 (proxy locking adds the conch and the local lock)
set extrafds 0
if {[forced_proxy_locking]} {
  set extrafds 2
} 


do_test stmt-1.2 {
  set sqlite_open_file_count
  expr $sqlite_open_file_count-$extrafds
} {1}
do_test stmt-1.3 {
  execsql {
    BEGIN;
      INSERT INTO t1 VALUES(1, 1);
  }
  set sqlite_open_file_count
  expr $sqlite_open_file_count-$extrafds
} {2}
do_test stmt-1.4 {
  execsql {
    INSERT INTO t1 SELECT a+1, b+1 FROM t1;
  }
  set sqlite_open_file_count
  expr $sqlite_open_file_count-$extrafds
} {3}
do_test stmt-1.5 {
  execsql COMMIT
  set sqlite_open_file_count
  expr $sqlite_open_file_count-$extrafds
} {1}
do_test stmt-1.6.1 {
  execsql {
    BEGIN;
      INSERT INTO t1 SELECT a+2, b+2 FROM t1;
  }
  set sqlite_open_file_count
  expr $sqlite_open_file_count-$extrafds
} {2}
do_test stmt-1.6.2 {
  execsql { INSERT INTO t1 SELECT a+4, b+4 FROM t1 }
  set sqlite_open_file_count
  expr $sqlite_open_file_count-$extrafds
} {3}
do_test stmt-1.7 {
  execsql COMMIT
  set sqlite_open_file_count
  expr $sqlite_open_file_count-$extrafds
} {1}


proc filecount {testname sql expected extrafds} {
  uplevel [list do_test $testname [subst -nocommand {
    execsql BEGIN
    execsql { $sql }
    set ret [set sqlite_open_file_count]
    execsql ROLLBACK
    set ret
  }] [ expr $expected+$extrafds ] ]
}

filecount stmt-2.1 { INSERT INTO t1 VALUES(9, 9)  } 2 $extrafds
filecount stmt-2.2 { REPLACE INTO t1 VALUES(9, 9) } 2 $extrafds
filecount stmt-2.3 { INSERT INTO t1 SELECT 9, 9   } 2 $extrafds
filecount stmt-2.4 { 
    INSERT INTO t1 SELECT 9, 9;
    INSERT INTO t1 SELECT 10, 10;
} 3 $extrafds

do_test stmt-2.5 {
  execsql { CREATE INDEX i1 ON t1(b) }
} {}
filecount stmt-2.6 { 
  REPLACE INTO t1 VALUES(5, 5);
  REPLACE INTO t1 VALUES(5, 5); 
} 3 $extrafds

finish_test

Changes to test/tempdb.test.

47
48
49
50
51
52
53





54
55
56
57
58
59
60
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# Verify that no writes occurred in t1.
#
do_test tempdb-1.2 {
  execsql {
    SELECT * FROM t1
  }
} {}






do_test tempdb-2.1 {
  # Set $::jrnl_in_memory if the journal file is expected to be in-memory.
  # Similarly, set $::subj_in_memory if the sub-journal file is expected
  # to be in memory. These variables are used to calculate the expected
  # number of open files in the test cases below.
  #
................................................................................
      INSERT INTO t1 VALUES(1, 2, 3);
      INSERT INTO t1 VALUES(4, 5, 6);
      INSERT INTO t2 VALUES(7, 8, 9);
      INSERT INTO t2 SELECT * FROM t1;
  }
  catchsql { INSERT INTO t1 SELECT * FROM t2 }
  set sqlite_open_file_count
} [expr 1 + (0==$jrnl_in_memory) + (0==$subj_in_memory)]
do_test tempdb-2.3 {
  execsql {
    PRAGMA temp_store = 'memory';
    ROLLBACK;
    BEGIN;
      INSERT INTO t1 VALUES(1, 2, 3);
      INSERT INTO t1 VALUES(4, 5, 6);
      INSERT INTO t2 SELECT * FROM t1;
  }
  catchsql { INSERT INTO t1 SELECT * FROM t2 }
  set sqlite_open_file_count
} [expr 1 + (0==$jrnl_in_memory)]

finish_test







>
>
>
>
>







 







|











|


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# Verify that no writes occurred in t1.
#
do_test tempdb-1.2 {
  execsql {
    SELECT * FROM t1
  }
} {}

set extrafds 0
if {[forced_proxy_locking]} {
  set extrafds 2
}

do_test tempdb-2.1 {
  # Set $::jrnl_in_memory if the journal file is expected to be in-memory.
  # Similarly, set $::subj_in_memory if the sub-journal file is expected
  # to be in memory. These variables are used to calculate the expected
  # number of open files in the test cases below.
  #
................................................................................
      INSERT INTO t1 VALUES(1, 2, 3);
      INSERT INTO t1 VALUES(4, 5, 6);
      INSERT INTO t2 VALUES(7, 8, 9);
      INSERT INTO t2 SELECT * FROM t1;
  }
  catchsql { INSERT INTO t1 SELECT * FROM t2 }
  set sqlite_open_file_count
} [expr 1 + $extrafds + (0==$jrnl_in_memory) + (0==$subj_in_memory)]
do_test tempdb-2.3 {
  execsql {
    PRAGMA temp_store = 'memory';
    ROLLBACK;
    BEGIN;
      INSERT INTO t1 VALUES(1, 2, 3);
      INSERT INTO t1 VALUES(4, 5, 6);
      INSERT INTO t2 SELECT * FROM t1;
  }
  catchsql { INSERT INTO t1 SELECT * FROM t2 }
  set sqlite_open_file_count
} [expr 1 + $extrafds + (0==$jrnl_in_memory)]

finish_test

Changes to test/tester.tcl.

1145
1146
1147
1148
1149
1150
1151





























1152
1153
1154
1155
1156
1157
1158
}

proc permutation {} {
  set perm ""
  catch {set perm $::G(perm:name)}
  set perm
}






























#-------------------------------------------------------------------------
#
proc slave_test_script {script} {

  # Create the interpreter used to run the test script.
  interp create tinterp







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
}

proc permutation {} {
  set perm ""
  catch {set perm $::G(perm:name)}
  set perm
}

proc forced_proxy_locking {} {
  ifcapable lock_proxy_pragmas&&prefer_proxy_locking {
    set force_proxy_value 0
    set force_key "SQLITE_FORCE_PROXY_LOCKING="
    foreach {env_pair} [exec env] { 
      if { [string first $force_key $env_pair] == 0} {
        set force_proxy_value [string range $env_pair [string length $force_key] end]
      }
    }
    if { "$force_proxy_value " == "1 " } {
      return 1
    } 
  }
  return 0
}

proc wal_is_ok {} {
  if { [forced_proxy_locking] } {
    return 0
  }
  if { ![path_is_local "."] } {
    return 0
  }
  if { [path_is_dos "."] } {
    return 0
  }
  return 1
}

#-------------------------------------------------------------------------
#
proc slave_test_script {script} {

  # Create the interpreter used to run the test script.
  interp create tinterp

Changes to test/tkt3457.test.

58
59
60
61
62
63
64

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

87
  seek $fd 0
  puts -nonewline $fd "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
  close $fd

  execsql COMMIT
} {}


do_test tkt3457-1.2 {
  file copy -force bak.db-journal test.db-journal
  file attributes test.db-journal -permissions ---------
  catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.3 {
  file copy -force bak.db-journal test.db-journal
  file attributes test.db-journal -permissions -w--w--w-
  catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test tkt3457-1.4 {
  file copy -force bak.db-journal test.db-journal
  file attributes test.db-journal -permissions r--r--r--
  catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}

do_test tkt3457-1.5 {
  file copy -force bak.db-journal test.db-journal
  file attributes test.db-journal -permissions rw-rw-rw-
  catchsql { SELECT * FROM t1 }
} {0 {1 2 3 4 5 6}}


finish_test







>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
>

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  seek $fd 0
  puts -nonewline $fd "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
  close $fd

  execsql COMMIT
} {}

if { ![path_is_dos "."] } {
  do_test tkt3457-1.2 {
    file copy -force bak.db-journal test.db-journal
    file attributes test.db-journal -permissions ---------
    catchsql { SELECT * FROM t1 }
  } {1 {unable to open database file}}
  do_test tkt3457-1.3 {
    file copy -force bak.db-journal test.db-journal
    file attributes test.db-journal -permissions -w--w--w-
    catchsql { SELECT * FROM t1 }
  } {1 {unable to open database file}}
  do_test tkt3457-1.4 {
    file copy -force bak.db-journal test.db-journal
    file attributes test.db-journal -permissions r--r--r--
    catchsql { SELECT * FROM t1 }
  } {1 {unable to open database file}}

  do_test tkt3457-1.5 {
    file copy -force bak.db-journal test.db-journal
    file attributes test.db-journal -permissions rw-rw-rw-
    catchsql { SELECT * FROM t1 }
  } {0 {1 2 3 4 5 6}}
}

finish_test

Changes to test/wal.test.

16
17
18
19
20
21
22




23
24
25
26
27
28
29
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

ifcapable !wal {finish_test ; return }





proc reopen_db {} {
  catch { db close }
  file delete -force test.db test.db-wal test.db-wal-summary
  sqlite3_wal db test.db
}








>
>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}

proc reopen_db {} {
  catch { db close }
  file delete -force test.db test.db-wal test.db-wal-summary
  sqlite3_wal db test.db
}

Changes to test/wal2.test.

16
17
18
19
20
21
22




23
24
25
26
27
28
29
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

ifcapable !wal {finish_test ; return }





proc set_tvfs_hdr {file args} {

  # Set $nHdr to the number of bytes in the wal-index header:
  set nHdr 48
  set nInt [expr {$nHdr/4}]








>
>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] || [path_is_dos "."]} {
  finish_test 
  return 
}

proc set_tvfs_hdr {file args} {

  # Set $nHdr to the number of bytes in the wal-index header:
  set nHdr 48
  set nInt [expr {$nHdr/4}]

Changes to test/wal3.test.

15
16
17
18
19
20
21




22
23
24
25
26
27
28

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
source $testdir/malloc_common.tcl
ifcapable !wal {finish_test ; return }





set a_string_counter 1
proc a_string {n} {
  global a_string_counter
  incr a_string_counter
  string range [string repeat "${a_string_counter}." $n] 1 $n
}







>
>
>
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
source $testdir/malloc_common.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}

set a_string_counter 1
proc a_string {n} {
  global a_string_counter
  incr a_string_counter
  string range [string repeat "${a_string_counter}." $n] 1 $n
}

Changes to test/wal4.test.

12
13
14
15
16
17
18




19
20
21
22
23
24
25
# result in database corruption
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
ifcapable !wal {finish_test ; return }





do_test wal4-1.1 {
  execsql {
    PRAGMA journal_mode=WAL;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);







>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# result in database corruption
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] || [path_is_dos "."]} {
  finish_test 
  return 
}

do_test wal4-1.1 {
  execsql {
    PRAGMA journal_mode=WAL;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);

Changes to test/walbak.test.

17
18
19
20
21
22
23




24
25
26
27
28
29
30
source $testdir/tester.tcl
source $testdir/wal_common.tcl
source $testdir/malloc_common.tcl

do_not_use_codec

ifcapable !wal {finish_test ; return }






# Test organization:
# 
#   walback-1.*: Simple tests.
#
#   walback-2.*: Test backups when the source db is modified mid-backup.







>
>
>
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
source $testdir/tester.tcl
source $testdir/wal_common.tcl
source $testdir/malloc_common.tcl

do_not_use_codec

ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}


# Test organization:
# 
#   walback-1.*: Simple tests.
#
#   walback-2.*: Test backups when the source db is modified mid-backup.

Changes to test/walbig.test.

22
23
24
25
26
27
28




29
30
31
32
33
34
35
#
do_not_use_codec

# If SQLITE_DISABLE_LFS is defined, omit this file.
ifcapable !lfs {
  finish_test
  return




}

set a_string_counter 1
proc a_string {n} {
  incr ::a_string_counter
  string range [string repeat "${::a_string_counter}." $n] 1 $n
}







>
>
>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#
do_not_use_codec

# If SQLITE_DISABLE_LFS is defined, omit this file.
ifcapable !lfs {
  finish_test
  return
}
if { ![wal_is_ok] } {
  finish_test 
  return 
}

set a_string_counter 1
proc a_string {n} {
  incr ::a_string_counter
  string range [string repeat "${::a_string_counter}." $n] 1 $n
}

Changes to test/walcksum.test.

12
13
14
15
16
17
18




19
20
21
22
23
24
25

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl

ifcapable !wal {finish_test ; return }





# Read and return the contents of file $filename. Treat the content as
# binary data.
#
proc readfile {filename} {
  set fd [open $filename]
  fconfigure $fd -encoding binary







>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl

ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}

# Read and return the contents of file $filename. Treat the content as
# binary data.
#
proc readfile {filename} {
  set fd [open $filename]
  fconfigure $fd -encoding binary

Changes to test/walcrash.test.

24
25
26
27
28
29
30




31
32
33
34
35
36
37
# walcrash-3.*: Recover multiple databases where the failed transaction 
#               was a multi-file transaction.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !wal {finish_test ; return }





db close

set seed 0
set REPEATS 100

# walcrash-1.*







>
>
>
>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# walcrash-3.*: Recover multiple databases where the failed transaction 
#               was a multi-file transaction.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}

db close

set seed 0
set REPEATS 100

# walcrash-1.*

Changes to test/walcrash2.test.

12
13
14
15
16
17
18




19
20
21
22
23
24
25


set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }






#-------------------------------------------------------------------------
# This test case demonstrates a flaw in the wal-index manipulation that
# existed at one point: If a process crashes mid-transaction, it may have
# already added some entries to one of the hash-tables in the wal-index.
# If the transaction were to be explicitly rolled back at this point, the







>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29


set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}


#-------------------------------------------------------------------------
# This test case demonstrates a flaw in the wal-index manipulation that
# existed at one point: If a process crashes mid-transaction, it may have
# already added some entries to one of the hash-tables in the wal-index.
# If the transaction were to be explicitly rolled back at this point, the

Changes to test/walfault.test.

15
16
17
18
19
20
21




22
23
24
25
26
27
28

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
source $testdir/lock_common.tcl

ifcapable !wal {finish_test ; return }





#-------------------------------------------------------------------------
# This test case, walfault-1-*, simulates faults while executing a
#
#   PRAGMA journal_mode = WAL;
#
# statement immediately after creating a new database.







>
>
>
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
source $testdir/lock_common.tcl

ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}

#-------------------------------------------------------------------------
# This test case, walfault-1-*, simulates faults while executing a
#
#   PRAGMA journal_mode = WAL;
#
# statement immediately after creating a new database.

Changes to test/walhook.test.

18
19
20
21
22
23
24




25
26
27
28
29
30
31
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/wal_common.tcl

ifcapable !wal {finish_test ; return }





set ::wal_hook [list]
proc wal_hook {zDb nEntry} {
  lappend ::wal_hook $zDb $nEntry
  return 0
}
db wal_hook wal_hook







>
>
>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/wal_common.tcl

ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}

set ::wal_hook [list]
proc wal_hook {zDb nEntry} {
  lappend ::wal_hook $zDb $nEntry
  return 0
}
db wal_hook wal_hook

Changes to test/walmode.test.

18
19
20
21
22
23
24














25
26
27
28
29
30
31
source $testdir/malloc_common.tcl

# If the library was compiled without WAL support, check that the 
# "PRAGMA journal_mode=WAL" treats "WAL" as an unrecognized mode.
#
ifcapable !wal {















  do_test walmode-0.1 {
    execsql { PRAGMA journal_mode = wal }
  } {delete}
  do_test walmode-0.2 {
    execsql { PRAGMA main.journal_mode = wal }
  } {delete}
  do_test walmode-0.3 {







>
>
>
>
>
>
>
>
>
>
>
>
>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
source $testdir/malloc_common.tcl

# If the library was compiled without WAL support, check that the 
# "PRAGMA journal_mode=WAL" treats "WAL" as an unrecognized mode.
#
ifcapable !wal {

  do_test walmode-0.1 {
    execsql { PRAGMA journal_mode = wal }
  } {delete}
  do_test walmode-0.2 {
    execsql { PRAGMA main.journal_mode = wal }
  } {delete}
  do_test walmode-0.3 {
    execsql { PRAGMA main.journal_mode }
  } {delete}

  finish_test
  return
}
if { ![wal_is_ok] } {
  do_test walmode-0.1 {
    execsql { PRAGMA journal_mode = wal }
  } {delete}
  do_test walmode-0.2 {
    execsql { PRAGMA main.journal_mode = wal }
  } {delete}
  do_test walmode-0.3 {

Changes to test/walslow.test.

14
15
16
17
18
19
20




21
22
23
24
25
26
27
# brute force methods, so may take a while to run.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !wal {finish_test ; return }





proc reopen_db {} {
  catch { db close }
  file delete -force test.db test.db-wal
  sqlite3 db test.db
  execsql { PRAGMA journal_mode = wal }
}







>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# brute force methods, so may take a while to run.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !wal {finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}

proc reopen_db {} {
  catch { db close }
  file delete -force test.db test.db-wal
  sqlite3 db test.db
  execsql { PRAGMA journal_mode = wal }
}

Changes to test/walthread.test.

15
16
17
18
19
20
21




22
23
24
25
26
27
28

set testdir [file dirname $argv0]

source $testdir/tester.tcl
source $testdir/lock_common.tcl
if {[run_thread_tests]==0} { finish_test ; return }
ifcapable !wal             { finish_test ; return }





set sqlite_walsummary_mmap_incr 64

# How long, in seconds, to run each test for. If a test is set to run for
# 0 seconds, it is omitted entirely.
#
unset -nocomplain seconds







>
>
>
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

set testdir [file dirname $argv0]

source $testdir/tester.tcl
source $testdir/lock_common.tcl
if {[run_thread_tests]==0} { finish_test ; return }
ifcapable !wal             { finish_test ; return }
if { ![wal_is_ok] } {
  finish_test 
  return 
}

set sqlite_walsummary_mmap_incr 64

# How long, in seconds, to run each test for. If a test is set to run for
# 0 seconds, it is omitted entirely.
#
unset -nocomplain seconds