/ Check-in [8ef97420]
Login
Overview
Comment:Test case updates to account for the fact that database files are not created until they are first written.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | deferred-open
Files: files | file ages | folders
SHA1:8ef97420b2614f50de6e6d7c758483b8b888f325
User & Date: dan 2014-02-11 19:35:42
Context
2014-02-12
14:43
Merge latest trunk changes. check-in: 4d7057c4 user: dan tags: deferred-open
2014-02-11
19:35
Test case updates to account for the fact that database files are not created until they are first written. check-in: 8ef97420 user: dan tags: deferred-open
05:26
Merge latest trunk changes. check-in: 1f2e1b0c user: dan tags: deferred-open
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

1526
1527
1528
1529
1530
1531
1532
1533


1534
1535
1536
1537

1538
1539

1540
1541
1542
1543
1544



1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
....
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
....
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
....
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
....
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
....
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
....
5661
5662
5663
5664
5665
5666
5667





5668
5669
5670
5671
5672
5673
5674
....
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
....
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
....
5886
5887
5888
5889
5890
5891
5892











5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920

5921
5922
5923
5924

5925


5926
5927
5928
5929
5930
5931
5932
  if( pFile->eFileLock>=eFileLock ){
    OSTRACE(("LOCK    %d %s ok (already held) (unix)\n", pFile->h,
            azFileLock(eFileLock)));
    return SQLITE_OK;
  }

  if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
    int eOrigLock = pFile->eFileLock;


    if( eFileLock==SHARED_LOCK ){
      int statrc;
      struct stat sBuf;
      memset(&sBuf, 0, sizeof(sBuf));

      statrc = osStat(pFile->zPath, &sBuf);
      if( statrc && errno==ENOENT ){

        pFile->eFileLock = SHARED_LOCK;
        return SQLITE_OK;
      }
    }




    rc = unixOpen(pFile->pVfs, pFile->zPath, id, pFile->openFlags, 0);
    if( rc==SQLITE_OK && eOrigLock ){
      rc = unixLock(id, eOrigLock);
    }
    if( rc!=SQLITE_OK ) return rc;
  }
  assert( (pFile->ctrlFlags & UNIXFILE_DEFERRED)==0 );

  /* Make sure the locking sequence is correct.
  **  (1) We never move from unlocked to anything higher than shared lock.
  **  (2) SQLite never explicitly requests a pendig lock.
  **  (3) A shared lock is always held when a reserve lock is requested.
  */
  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
  assert( eFileLock!=PENDING_LOCK );
  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );

  /* This mutex is needed because pFile->pInode is shared across threads
................................................................................
static int unixClose(sqlite3_file *id){
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile *)id;
  verifyDbFile(pFile);
  unixUnlock(id, NO_LOCK);
  unixEnterMutex();

  /* unixFile.pInode is always valid here. Otherwise, a different close
  ** routine (e.g. nolockClose()) would be called instead.  */
  assert( pFile->pInode==0 
       || pFile->pInode->nLock>0 
       || pFile->pInode->bProcessLock==0 
  );
  if( pFile->pInode ){
    if( pFile->pInode->nLock ){
      /* If there are outstanding locks, do not actually close the file just
................................................................................
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
  );
#endif

  if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
    int rc;
    struct stat sBuf;
    memset(&sBuf, 0, sizeof(sBuf));
    rc = osStat(pFile->zPath, &sBuf);
    if( rc!=0 ){
      memset(pBuf, 0, amt);
      rc = (errno==ENOENT ? SQLITE_IOERR_SHORT_READ : SQLITE_IOERR_FSTAT);
    }else{
      rc = unixOpen(pFile->pVfs, pFile->zPath, id, pFile->openFlags, 0);
    }
    if( rc!=SQLITE_OK ){
      return rc;
    }
  }
................................................................................
  pNew->h = h;
  pNew->pVfs = pVfs;
  pNew->zPath = zFilename;
  pNew->ctrlFlags = (unsigned short)ctrlFlags;
#if SQLITE_MAX_MMAP_SIZE>0
  pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
#endif
  if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
    pNew->ctrlFlags |= UNIXFILE_PSOW;
  }
  if( strcmp(pVfs->zName,"unix-excl")==0 ){
    pNew->ctrlFlags |= UNIXFILE_EXCL;
  }

#if OS_VXWORKS
  pNew->pId = vxworksFindFileId(zFilename);
  if( pNew->pId==0 ){
................................................................................
    pNew->ctrlFlags |= UNIXFILE_DELETE;
  }
#endif
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pNew->pMethod = pLockingStyle;
    OpenCounter(+1);
    verifyDbFile(pNew);
  }
  return rc;
}

/*
** Return the name of a directory in which to put temporary files.
................................................................................
){
  unixFile *p = (unixFile *)pFile;
  int fd = -1;                   /* File descriptor returned by open() */
  int openFlags = 0;             /* Flags to pass to open() */
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
  int noLock;                    /* True to omit locking primitives */
  int rc = SQLITE_OK;            /* Function Return Code */
  int ctrlFlags = 0;             /* UNIXFILE_* flags */

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
#if SQLITE_ENABLE_LOCKING_STYLE
................................................................................
  ));

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
  */
  char zTmpname[MAX_PATHNAME+2];
  const char *zName = zPath;






  /* Check the following statements are true: 
  **
  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
  **   (b) if CREATE is set, then READWRITE must also be set, and
  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
................................................................................
  ** are harmless.
  */
  if( randomnessPid!=getpid() ){
    randomnessPid = getpid();
    sqlite3_randomness(0,0);
  }

  memset(p, 0, sizeof(unixFile));

  if( eType==SQLITE_OPEN_MAIN_DB ){
    UnixUnusedFd *pUnused;
    pUnused = findReusableFd(zName, flags);
    if( pUnused ){
      fd = pUnused->fd;
    }else{
................................................................................
    }
  }
#endif
  
  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);

open_finished:
  if( rc!=SQLITE_OK ){
    sqlite3_free(p->pUnused);
  }
  return rc;
}

static int unixOpenDeferred(
  sqlite3_vfs *pVfs,           /* The VFS for which this is the xOpen method */
  const char *zPath,           /* Pathname of file to be opened */
  sqlite3_file *pFile,         /* The file descriptor to be filled in */
................................................................................
  int flags,                   /* Input flags to control the opening */
  int *pOutFlags               /* Output flags returned to SQLite core */
){
  const int mask1 = SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_READWRITE
                  | SQLITE_OPEN_CREATE;
  const int mask2 = SQLITE_OPEN_READONLY  | SQLITE_OPEN_DELETEONCLOSE
                  | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_AUTOPROXY;












  /* If all the flags in mask1 are set, and all the flags in mask2 are
  ** clear, the file does not exist but the directory does and is
  ** writable, then this is a deferred open.  */
  if( 0 && zPath && (flags & (mask1 | mask2))==mask1 ){
    int posixrc;
    posixrc = osAccess(zPath, F_OK);
    if( posixrc && errno==ENOENT ){
      char zDirname[MAX_PATHNAME+1];
      int i;
      for(i=(int)strlen(zPath); i>1 && zPath[i]!='/'; i--);
      memcpy(zDirname, zPath, i);
      zDirname[i] = '\0';
      posixrc = osAccess(zDirname, W_OK);
      if( posixrc==0 ){
        unixFile *p = (unixFile*)pFile;
        memset(p, 0, sizeof(unixFile));
        p->pMethod = (**(finder_type*)pVfs->pAppData)(0, 0);
        p->pVfs = pVfs;
        p->h = -1;
        p->ctrlFlags = UNIXFILE_DEFERRED;
        if( sqlite3_uri_boolean(((flags & UNIXFILE_URI) ? zPath : 0),
                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
          p->ctrlFlags |= UNIXFILE_PSOW;
        }
        p->openFlags = flags;
        p->zPath = zPath;
        if( pOutFlags ) *pOutFlags = flags;

        return SQLITE_OK;
      }
    }
  }

  return unixOpen(pVfs, zPath, pFile, flags, pOutFlags);


}

/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
** the directory after deleting the file.
*/
static int unixDelete(







|
>
>
|
<
<
<
>
|
|
>
|
|
|
|
<
>
>
>
|









|







 







|
|







 







|
<
<
<

|







 







<
<
<
<







 







<







 







|







 







>
>
>
>
>







 







<







 







<
<
<







 







>
>
>
>
>
>
>
>
>
>
>




|










<
<



<
<
<
|
<



>




>
|
>
>







1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536



1537
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
....
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
....
3206
3207
3208
3209
3210
3211
3212
3213



3214
3215
3216
3217
3218
3219
3220
3221
3222
....
5233
5234
5235
5236
5237
5238
5239




5240
5241
5242
5243
5244
5245
5246
....
5371
5372
5373
5374
5375
5376
5377

5378
5379
5380
5381
5382
5383
5384
....
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
....
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
....
5698
5699
5700
5701
5702
5703
5704

5705
5706
5707
5708
5709
5710
5711
....
5868
5869
5870
5871
5872
5873
5874



5875
5876
5877
5878
5879
5880
5881
....
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914


5915
5916
5917



5918

5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
  if( pFile->eFileLock>=eFileLock ){
    OSTRACE(("LOCK    %d %s ok (already held) (unix)\n", pFile->h,
            azFileLock(eFileLock)));
    return SQLITE_OK;
  }

  if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
    const char *zPath = pFile->zPath;       /* Full-path to database file */
    int eOrigLock;                          /* Current lock held on pFile */

    assert( pFile->eFileLock==SHARED_LOCK || pFile->eFileLock==NO_LOCK );




    /* If SQLite is requesting a SHARED lock and the database file does
    ** not exist, return early without opening the file. */ 
    if( eFileLock==SHARED_LOCK && osAccess(zPath, F_OK) && errno==ENOENT ){
      pFile->eFileLock = SHARED_LOCK;
      return SQLITE_OK;
    }


    /* Or, if the database file has been created or a write lock is 
    ** requested, open the database file now.  */
    eOrigLock = pFile->eFileLock;
    rc = unixOpen(pFile->pVfs, zPath, id, pFile->openFlags, 0);
    if( rc==SQLITE_OK && eOrigLock ){
      rc = unixLock(id, eOrigLock);
    }
    if( rc!=SQLITE_OK ) return rc;
  }
  assert( (pFile->ctrlFlags & UNIXFILE_DEFERRED)==0 );

  /* Make sure the locking sequence is correct.
  **  (1) We never move from unlocked to anything higher than shared lock.
  **  (2) SQLite never explicitly requests a pending lock.
  **  (3) A shared lock is always held when a reserve lock is requested.
  */
  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
  assert( eFileLock!=PENDING_LOCK );
  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );

  /* This mutex is needed because pFile->pInode is shared across threads
................................................................................
static int unixClose(sqlite3_file *id){
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile *)id;
  verifyDbFile(pFile);
  unixUnlock(id, NO_LOCK);
  unixEnterMutex();

  /* unixFile.pInode may be NULL here if the file was never opened.
  */
  assert( pFile->pInode==0 
       || pFile->pInode->nLock>0 
       || pFile->pInode->bProcessLock==0 
  );
  if( pFile->pInode ){
    if( pFile->pInode->nLock ){
      /* If there are outstanding locks, do not actually close the file just
................................................................................
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
  );
#endif

  if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
    int rc;
    if( osAccess(pFile->zPath, F_OK) && errno==ENOENT ){



      memset(pBuf, 0, amt);
      rc = SQLITE_IOERR_SHORT_READ;
    }else{
      rc = unixOpen(pFile->pVfs, pFile->zPath, id, pFile->openFlags, 0);
    }
    if( rc!=SQLITE_OK ){
      return rc;
    }
  }
................................................................................
  pNew->h = h;
  pNew->pVfs = pVfs;
  pNew->zPath = zFilename;
  pNew->ctrlFlags = (unsigned short)ctrlFlags;
#if SQLITE_MAX_MMAP_SIZE>0
  pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
#endif




  if( strcmp(pVfs->zName,"unix-excl")==0 ){
    pNew->ctrlFlags |= UNIXFILE_EXCL;
  }

#if OS_VXWORKS
  pNew->pId = vxworksFindFileId(zFilename);
  if( pNew->pId==0 ){
................................................................................
    pNew->ctrlFlags |= UNIXFILE_DELETE;
  }
#endif
  if( rc!=SQLITE_OK ){
    if( h>=0 ) robust_close(pNew, h, __LINE__);
  }else{
    pNew->pMethod = pLockingStyle;

    verifyDbFile(pNew);
  }
  return rc;
}

/*
** Return the name of a directory in which to put temporary files.
................................................................................
){
  unixFile *p = (unixFile *)pFile;
  int fd = -1;                   /* File descriptor returned by open() */
  int openFlags = 0;             /* Flags to pass to open() */
  int eType = flags&0xFFFFFF00;  /* Type of file to open */
  int noLock;                    /* True to omit locking primitives */
  int rc = SQLITE_OK;            /* Function Return Code */
  int ctrlFlags;                 /* UNIXFILE_* flags */

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
#if SQLITE_ENABLE_LOCKING_STYLE
................................................................................
  ));

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
  */
  char zTmpname[MAX_PATHNAME+2];
  const char *zName = zPath;

  assert( p->pInode==0 && (p->h==-1 || p->h==0) );
  p->ctrlFlags &= ~UNIXFILE_DEFERRED;
  p->eFileLock = NO_LOCK;
  ctrlFlags = p->ctrlFlags;

  /* Check the following statements are true: 
  **
  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
  **   (b) if CREATE is set, then READWRITE must also be set, and
  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
................................................................................
  ** are harmless.
  */
  if( randomnessPid!=getpid() ){
    randomnessPid = getpid();
    sqlite3_randomness(0,0);
  }



  if( eType==SQLITE_OPEN_MAIN_DB ){
    UnixUnusedFd *pUnused;
    pUnused = findReusableFd(zName, flags);
    if( pUnused ){
      fd = pUnused->fd;
    }else{
................................................................................
    }
  }
#endif
  
  rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);

open_finished:



  return rc;
}

static int unixOpenDeferred(
  sqlite3_vfs *pVfs,           /* The VFS for which this is the xOpen method */
  const char *zPath,           /* Pathname of file to be opened */
  sqlite3_file *pFile,         /* The file descriptor to be filled in */
................................................................................
  int flags,                   /* Input flags to control the opening */
  int *pOutFlags               /* Output flags returned to SQLite core */
){
  const int mask1 = SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_READWRITE
                  | SQLITE_OPEN_CREATE;
  const int mask2 = SQLITE_OPEN_READONLY  | SQLITE_OPEN_DELETEONCLOSE
                  | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_AUTOPROXY;

  int rc;                         /* Return code */
  unixFile *p = (unixFile*)pFile; /* File object to populate */

  /* Zero the file object */
  memset(p, 0, sizeof(unixFile));
  if( (flags & UNIXFILE_URI) 
   && sqlite3_uri_boolean(zPath, "psow", SQLITE_POWERSAFE_OVERWRITE) 
  ){
    p->ctrlFlags |= UNIXFILE_PSOW;
  }

  /* If all the flags in mask1 are set, and all the flags in mask2 are
  ** clear, the file does not exist but the directory does and is
  ** writable, then this is a deferred open.  */
  if( zPath && (flags & (mask1 | mask2))==mask1 ){
    int posixrc;
    posixrc = osAccess(zPath, F_OK);
    if( posixrc && errno==ENOENT ){
      char zDirname[MAX_PATHNAME+1];
      int i;
      for(i=(int)strlen(zPath); i>1 && zPath[i]!='/'; i--);
      memcpy(zDirname, zPath, i);
      zDirname[i] = '\0';
      posixrc = osAccess(zDirname, W_OK);
      if( posixrc==0 ){


        p->pMethod = (**(finder_type*)pVfs->pAppData)(0, 0);
        p->pVfs = pVfs;
        p->h = -1;



        p->ctrlFlags |= UNIXFILE_DEFERRED;

        p->openFlags = flags;
        p->zPath = zPath;
        if( pOutFlags ) *pOutFlags = flags;
        OpenCounter(+1);
        return SQLITE_OK;
      }
    }
  }

  rc = unixOpen(pVfs, zPath, pFile, flags, pOutFlags);
  OpenCounter( rc==SQLITE_OK );
  return rc;
}

/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
** the directory after deleting the file.
*/
static int unixDelete(

Changes to test/backup.test.

320
321
322
323
324
325
326







327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350

  db close
  db2 close
  incr iTest
}
}
}








#--------------------------------------------------------------------
do_test backup-3.$iTest.1 {
  catch { forcedelete test.db }
  catch { forcedelete test2.db }
  sqlite3 db test.db
  set iTab 1

  db eval { PRAGMA page_size = 512 }
  while {[file size test.db] <= $::sqlite_pending_byte} {
    db eval "CREATE TABLE t${iTab}(a, b, c)"
    incr iTab
  }

  sqlite3 db2 test2.db
  db2 eval { PRAGMA page_size = 4096 }
  while {[file size test2.db] < $::sqlite_pending_byte} {
    db2 eval "CREATE TABLE t${iTab}(a, b, c)"
    incr iTab
  }

  sqlite3_backup B db2 main db main
  B step -1
} {SQLITE_DONE}







>
>
>
>
>
>
>









|






|







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

  db close
  db2 close
  incr iTest
}
}
}

proc file_size {zFile} {
  if {[file exists $zFile]} {
    return [file size $zFile]
  }
  return 0
}

#--------------------------------------------------------------------
do_test backup-3.$iTest.1 {
  catch { forcedelete test.db }
  catch { forcedelete test2.db }
  sqlite3 db test.db
  set iTab 1

  db eval { PRAGMA page_size = 512 }
  while {[file_size test.db] <= $::sqlite_pending_byte} {
    db eval "CREATE TABLE t${iTab}(a, b, c)"
    incr iTab
  }

  sqlite3 db2 test2.db
  db2 eval { PRAGMA page_size = 4096 }
  while {[file_size test2.db] < $::sqlite_pending_byte} {
    db2 eval "CREATE TABLE t${iTab}(a, b, c)"
    incr iTab
  }

  sqlite3_backup B db2 main db main
  B step -1
} {SQLITE_DONE}

Changes to test/backup4.test.

18
19
20
21
22
23
24







25
26
27
28
29
30
31
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
..
94
95
96
97
98
99
100
101
102
103
# schema cookie and change counter. Doing that could cause other clients
# to become confused and continue using out-of-date cache data.
#

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








#-------------------------------------------------------------------------
# At one point this test was failing because [db] was using an out of
# date schema in test case 1.2.
#
do_execsql_test 1.0 {
  CREATE TABLE t1(x, y, UNIQUE(x, y));
................................................................................
do_test 2.3 {
  sqlite3 db1 test.db2
  db1 backup test.db
  db1 close
  file size test.db
} {1024}

do_test 2.4 { file size test.db2 } 0

db close
forcedelete test.db
forcedelete test.db2
sqlite3 db test.db

#-------------------------------------------------------------------------
................................................................................
do_test 3.3 {
  sqlite3 db1 test.db2
  db1 backup test.db
  db1 close
  file size test.db
} {1024}

do_test 3.4 { file size test.db2 } 0

finish_test







>
>
>
>
>
>
>







 







|







 







|


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
101
102
103
104
105
106
107
108
109
110
# schema cookie and change counter. Doing that could cause other clients
# to become confused and continue using out-of-date cache data.
#

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

proc file_size {zFile} {
  if {[file exists $zFile]} {
    return [file size $zFile]
  }
  return 0
}

#-------------------------------------------------------------------------
# At one point this test was failing because [db] was using an out of
# date schema in test case 1.2.
#
do_execsql_test 1.0 {
  CREATE TABLE t1(x, y, UNIQUE(x, y));
................................................................................
do_test 2.3 {
  sqlite3 db1 test.db2
  db1 backup test.db
  db1 close
  file size test.db
} {1024}

do_test 2.4 { file_size test.db2 } 0

db close
forcedelete test.db
forcedelete test.db2
sqlite3 db test.db

#-------------------------------------------------------------------------
................................................................................
do_test 3.3 {
  sqlite3 db1 test.db2
  db1 backup test.db
  db1 close
  file size test.db
} {1024}

do_test 3.4 { file_size test.db2 } 0

finish_test

Changes to test/capi3e.test.

66
67
68
69
70
71
72



73
74
75
76
77
78
79
80
81
82
foreach name $names {
  incr i
  do_test capi3e-1.1.$i {
    set db2 [sqlite3_open $name {}]
    sqlite3_errcode $db2
  } {SQLITE_OK}
  do_test capi3e-1.2.$i {



    sqlite3_close $db2
  } {SQLITE_OK}
  do_test capi3e-1.3.$i {
    file isfile $name
  } {1}
}

ifcapable {utf16} {
  set i 0
  foreach name $names {







>
>
>


|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
foreach name $names {
  incr i
  do_test capi3e-1.1.$i {
    set db2 [sqlite3_open $name {}]
    sqlite3_errcode $db2
  } {SQLITE_OK}
  do_test capi3e-1.2.$i {
    sqlite3_exec $db2 { CREATE TABLE t1(x) }
  } {0 {}}
  do_test capi3e-1.3.$i {
    sqlite3_close $db2
  } {SQLITE_OK}
  do_test capi3e-1.4.$i {
    file isfile $name
  } {1}
}

ifcapable {utf16} {
  set i 0
  foreach name $names {

Changes to test/e_uri.test.

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
...
310
311
312
313
314
315
316

317
318
319
320
321
322
323
...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  # Tests with SQLITE_CONFIG_URI configured to false. URI intepretation is
  # only enabled if the SQLITE_OPEN_URI flag is specified.
  sqlite3_shutdown
  sqlite3_config_uri 0
  do_test 1.1 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]

    list [file exists file:test.db] [file exists test.db]
  } {0 1}
  do_test 1.2 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT

    list [file exists file:test.db2] [file exists test.db2]
  } {0 1}
  sqlite3_close $DB
  do_test 1.3 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]

    list [file exists file:test.db] [file exists test.db]
  } {1 0}
  do_test 1.4 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT

    list [file exists file:test.db2] [file exists test.db2]
  } {1 0}
  sqlite3_close $DB

  # Tests with SQLITE_CONFIG_URI configured to true. URI intepretation is
  # enabled with or without SQLITE_OPEN_URI.
  #
  sqlite3_shutdown
  sqlite3_config_uri 1
  do_test 1.5 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]

    list [file exists file:test.db] [file exists test.db]
  } {0 1}
  do_test 1.6 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT

    list [file exists file:test.db2] [file exists test.db2]
  } {0 1}
  sqlite3_close $DB
  do_test 1.7 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]

    list [file exists file:test.db] [file exists test.db]
  } {0 1}
  do_test 1.8 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT

    list [file exists file:test.db2] [file exists test.db2]
  } {0 1}
  sqlite3_close $DB
}

# ensure uri processing enabled for the rest of the tests
sqlite3_shutdown
................................................................................

# EVIDENCE-OF: R-20590-08726 It is an error to specify a value for the
# mode parameter that is less restrictive than that specified by the
# flags passed in the third parameter to sqlite3_open_v2().
#
forcedelete test.db
sqlite3 db test.db

db close
foreach {tn uri flags error} {
  1   {file:test.db?mode=ro}   ro    {not an error}
  2   {file:test.db?mode=ro}   rw    {not an error}
  3   {file:test.db?mode=ro}   rwc   {not an error}

  4   {file:test.db?mode=rw}   ro    {access mode not allowed: rw}
................................................................................
  7   {file:test.db?mode=rwc}  ro    {access mode not allowed: rwc}
  8   {file:test.db?mode=rwc}  rw    {access mode not allowed: rwc}
  9   {file:test.db?mode=rwc}  rwc   {not an error}
} {
  set f(ro)  [list SQLITE_OPEN_READONLY SQLITE_OPEN_URI]
  set f(rw)  [list SQLITE_OPEN_READWRITE SQLITE_OPEN_URI]
  set f(rwc) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]

  set DB [sqlite3_open_v2 $uri $f($flags) ""]
  set e [sqlite3_errmsg $DB]
  sqlite3_close $DB

  do_test 9.$tn { set e } $error
}








>







>






>







>












>







>






>







>







 







>







 







|







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
126
127
128
129
130
131
132
133
...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
  # Tests with SQLITE_CONFIG_URI configured to false. URI intepretation is
  # only enabled if the SQLITE_OPEN_URI flag is specified.
  sqlite3_shutdown
  sqlite3_config_uri 0
  do_test 1.1 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
    sqlite3_exec $DB {CREATE TABLE t1(x)}
    list [file exists file:test.db] [file exists test.db]
  } {0 1}
  do_test 1.2 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT
    sqlite3_exec $DB {CREATE TABLE aux.t1(x)}
    list [file exists file:test.db2] [file exists test.db2]
  } {0 1}
  sqlite3_close $DB
  do_test 1.3 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
    sqlite3_exec $DB {CREATE TABLE t1(x)}
    list [file exists file:test.db] [file exists test.db]
  } {1 0}
  do_test 1.4 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT
    sqlite3_exec $DB {CREATE TABLE aux.t1(x)}
    list [file exists file:test.db2] [file exists test.db2]
  } {1 0}
  sqlite3_close $DB

  # Tests with SQLITE_CONFIG_URI configured to true. URI intepretation is
  # enabled with or without SQLITE_OPEN_URI.
  #
  sqlite3_shutdown
  sqlite3_config_uri 1
  do_test 1.5 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
    sqlite3_exec $DB {CREATE TABLE t1(x)}
    list [file exists file:test.db] [file exists test.db]
  } {0 1}
  do_test 1.6 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT
    sqlite3_exec $DB {CREATE TABLE aux.t1(x)}
    list [file exists file:test.db2] [file exists test.db2]
  } {0 1}
  sqlite3_close $DB
  do_test 1.7 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
    sqlite3_exec $DB {CREATE TABLE t1(x)}
    list [file exists file:test.db] [file exists test.db]
  } {0 1}
  do_test 1.8 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT
    sqlite3_exec $DB {CREATE TABLE aux.t1(x)}
    list [file exists file:test.db2] [file exists test.db2]
  } {0 1}
  sqlite3_close $DB
}

# ensure uri processing enabled for the rest of the tests
sqlite3_shutdown
................................................................................

# EVIDENCE-OF: R-20590-08726 It is an error to specify a value for the
# mode parameter that is less restrictive than that specified by the
# flags passed in the third parameter to sqlite3_open_v2().
#
forcedelete test.db
sqlite3 db test.db
db eval {CREATE TABLE t1(x)}
db close
foreach {tn uri flags error} {
  1   {file:test.db?mode=ro}   ro    {not an error}
  2   {file:test.db?mode=ro}   rw    {not an error}
  3   {file:test.db?mode=ro}   rwc   {not an error}

  4   {file:test.db?mode=rw}   ro    {access mode not allowed: rw}
................................................................................
  7   {file:test.db?mode=rwc}  ro    {access mode not allowed: rwc}
  8   {file:test.db?mode=rwc}  rw    {access mode not allowed: rwc}
  9   {file:test.db?mode=rwc}  rwc   {not an error}
} {
  set f(ro)  [list SQLITE_OPEN_READONLY SQLITE_OPEN_URI]
  set f(rw)  [list SQLITE_OPEN_READWRITE SQLITE_OPEN_URI]
  set f(rwc) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
breakpoint
  set DB [sqlite3_open_v2 $uri $f($flags) ""]
  set e [sqlite3_errmsg $DB]
  sqlite3_close $DB

  do_test 9.$tn { set e } $error
}

Changes to test/exclusive2.test.

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
  incr ret [expr ($d&0x000000FF)<<0]

  if {$needClose} {close $fd}
  return $ret
}

proc readPagerChangeCounter {filename} {

  set fd [open $filename RDONLY]
  fconfigure $fd -translation binary -encoding binary

  seek $fd 24
  foreach {a b c d} [list 0 0 0 0] {}
  binary scan [read $fd 4] cccc a b c d
  set  ret [expr ($a&0x000000FF)<<24]
  incr ret [expr ($b&0x000000FF)<<16]
  incr ret [expr ($c&0x000000FF)<<8]
  incr ret [expr ($d&0x000000FF)<<0]

  close $fd



  return $ret
}


proc t1sig {{db db}} {
  execsql {SELECT count(*), md5sum(a) FROM t1} $db
}







>
|
|
<
|
|
|
|
|
|
|
<
|
>
>
>







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
  incr ret [expr ($d&0x000000FF)<<0]

  if {$needClose} {close $fd}
  return $ret
}

proc readPagerChangeCounter {filename} {
  if {[file exists $filename]} {
    set fd [open $filename RDONLY]
    fconfigure $fd -translation binary -encoding binary

    seek $fd 24
    foreach {a b c d} [list 0 0 0 0] {}
    binary scan [read $fd 4] cccc a b c d
    set  ret [expr ($a&0x000000FF)<<24]
    incr ret [expr ($b&0x000000FF)<<16]
    incr ret [expr ($c&0x000000FF)<<8]
    incr ret [expr ($d&0x000000FF)<<0]

    close $fd
  } else {
    set ret 0
  }
  return $ret
}


proc t1sig {{db db}} {
  execsql {SELECT count(*), md5sum(a) FROM t1} $db
}

Changes to test/tkt4018.test.

42
43
44
45
46
47
48

49
50
51
52
53
54
55
  }
} {}

# The database is locked by connection [db]. Open and close a second
# connection to test.db 10000 times. If file-descriptors are not being
# reused, then the process will quickly exceed its maximum number of
# file descriptors (1024 by default on linux).

do_test tkt4018-1.2 {
  for {set i 0} {$i < 10000} {incr i} {
    sqlite3 db2 test.db
    db2 close
  }
} {}








>







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

# The database is locked by connection [db]. Open and close a second
# connection to test.db 10000 times. If file-descriptors are not being
# reused, then the process will quickly exceed its maximum number of
# file descriptors (1024 by default on linux).
breakpoint
do_test tkt4018-1.2 {
  for {set i 0} {$i < 10000} {incr i} {
    sqlite3 db2 test.db
    db2 close
  }
} {}