/ Check-in [e77d29f6]
Login

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

Overview
Comment:Only open a db in server-mode if there is a directory named "db-journal" in the file-system and the VFS is an exclusive locking VFS.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | server-process-edition
Files: files | file ages | folders
SHA3-256: e77d29f64480179d7aae7d88adab2ba9ff042701e1f4e624a3a7775cb56a51cc
User & Date: dan 2017-07-24 19:23:20
Context
2017-07-24
19:43
Update this branch with latest changes from trunk. check-in: d0719ad7 user: dan tags: server-process-edition
19:23
Only open a db in server-mode if there is a directory named "db-journal" in the file-system and the VFS is an exclusive locking VFS. check-in: e77d29f6 user: dan tags: server-process-edition
2017-07-19
18:54
Merge latest trunk changes with this branch. check-in: be0df0a6 user: dan tags: server-process-edition
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

  3773   3773   
  3774   3774   /*
  3775   3775   ** Information and control of an open file handle.
  3776   3776   */
  3777   3777   static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  3778   3778     unixFile *pFile = (unixFile*)id;
  3779   3779     switch( op ){
         3780  +    case SQLITE_FCNTL_SERVER_MODE: {
         3781  +      int rc = SQLITE_OK;
         3782  +      int eServer = 0;
         3783  +      if( pFile->ctrlFlags | UNIXFILE_EXCL ){
         3784  +        char *zJrnl = sqlite3_mprintf("%s-journal", pFile->zPath);
         3785  +        if( zJrnl==0 ){
         3786  +          rc = SQLITE_NOMEM;
         3787  +        }else{
         3788  +          struct stat buf;        /* Used to hold return values of stat() */
         3789  +          if( osStat(zJrnl, &buf) ){
         3790  +            rc = SQLITE_IOERR_FSTAT;
         3791  +          }else{
         3792  +            eServer = ((buf.st_mode & S_IFDIR) ? 1 : 0);
         3793  +          }
         3794  +        }
         3795  +        sqlite3_free(zJrnl);
         3796  +      }
         3797  +      *((int*)pArg) = eServer;
         3798  +      return rc;
         3799  +    }
  3780   3800       case SQLITE_FCNTL_FILEID: {
  3781         -      i64 *aId = (i64)pArg;
         3801  +      i64 *aId = (i64*)pArg;
  3782   3802         aId[0] = (i64)(pFile->pInode->fileId.dev);
  3783   3803         aId[1] = (i64)(pFile->pInode->fileId.ino);
  3784   3804         return SQLITE_OK;
  3785   3805       }
  3786   3806       case SQLITE_FCNTL_LOCKSTATE: {
  3787   3807         *(int*)pArg = pFile->eFileLock;
  3788   3808         return SQLITE_OK;
................................................................................
  5626   5646   #endif
  5627   5647         nDb--;
  5628   5648       }
  5629   5649       memcpy(zDb, zPath, nDb);
  5630   5650       zDb[nDb] = '\0';
  5631   5651   
  5632   5652       rc = getFileMode(zDb, pMode, pUid, pGid);
         5653  +#ifdef SQLITE_SERVER_EDITION
         5654  +    if( rc==SQLITE_IOERR_FSTAT ){
         5655  +      while( nDb && zDb[nDb]!='/' ) nDb--;
         5656  +      if( nDb>8 && memcmp("-journal/", &zDb[nDb-8], 9)==0 ){
         5657  +        zDb[nDb-8] = '\0';
         5658  +        rc = getFileMode(zDb, pMode, pUid, pGid);
         5659  +      }
         5660  +    }
         5661  +#endif
  5633   5662     }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
  5634   5663       *pMode = 0600;
  5635   5664     }else if( flags & SQLITE_OPEN_URI ){
  5636   5665       /* If this is a main database file and the file was opened using a URI
  5637   5666       ** filename, check for the "modeof" parameter. If present, interpret
  5638   5667       ** its value as a filename and try to copy the mode, uid and gid from
  5639   5668       ** that file.  */

Changes to src/pager.c.

  5062   5062   **
  5063   5063   ** If a hot-journal file is found to exist, *pExists is set to 1 and 
  5064   5064   ** SQLITE_OK returned. If no hot-journal file is present, *pExists is
  5065   5065   ** set to 0 and SQLITE_OK returned. If an IO error occurs while trying
  5066   5066   ** to determine whether or not a hot-journal file exists, the IO error
  5067   5067   ** code is returned and the value of *pExists is undefined.
  5068   5068   */
  5069         -static int hasHotJournal(Pager *pPager, int *pExists){
         5069  +static int hasHotJournal(Pager *pPager, int *pExists, int *peServer){
  5070   5070     sqlite3_vfs * const pVfs = pPager->pVfs;
  5071   5071     int rc = SQLITE_OK;           /* Return code */
  5072   5072     int exists = 1;               /* True if a journal file is present */
  5073   5073     int jrnlOpen = !!isOpen(pPager->jfd);
  5074   5074   
  5075   5075     assert( pPager->useJournal );
  5076   5076     assert( isOpen(pPager->fd) );
................................................................................
  5082   5082   
  5083   5083     *pExists = 0;
  5084   5084     if( !jrnlOpen ){
  5085   5085       rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
  5086   5086     }
  5087   5087     if( rc==SQLITE_OK && exists ){
  5088   5088       int locked = 0;             /* True if some process holds a RESERVED lock */
         5089  +
         5090  +#ifdef SQLITE_SERVER_EDITION
         5091  +    rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SERVER_MODE, peServer);
         5092  +    if( rc!=SQLITE_NOTFOUND ){
         5093  +      if( rc!=SQLITE_OK || *peServer ) return rc;
         5094  +    }
         5095  +#endif
  5089   5096   
  5090   5097       /* Race condition here:  Another process might have been holding the
  5091   5098       ** the RESERVED lock and have a journal open at the sqlite3OsAccess() 
  5092   5099       ** call above, but then delete the journal and drop the lock before
  5093   5100       ** we get to the following sqlite3OsCheckReservedLock() call.  If that
  5094   5101       ** is the case, this routine might think there is a hot journal when
  5095   5102       ** in fact there is none.  This results in a false-positive which will
................................................................................
  5196   5203   }
  5197   5204   
  5198   5205   void sqlite3PagerServerJournal(
  5199   5206     Pager *pPager, 
  5200   5207     sqlite3_file *jfd,
  5201   5208     const char *zJournal
  5202   5209   ){
  5203         -  pPager->zJournal = zJournal;
         5210  +  pPager->zJournal = (char*)zJournal;
  5204   5211     pPager->jfd = jfd;
  5205   5212   }
  5206         -
  5207         -#else
  5208         -# define pagerServerConnect(pPager) SQLITE_OK
  5209   5213   #endif
  5210   5214   
  5211   5215   
  5212   5216   /*
  5213   5217   ** This function is called to obtain a shared lock on the database file.
  5214   5218   ** It is illegal to call sqlite3PagerGet() until after this function
  5215   5219   ** has been successfully called. If a shared-lock is already held when
................................................................................
  5234   5238   **
  5235   5239   ** If everything is successful, SQLITE_OK is returned. If an IO error 
  5236   5240   ** occurs while locking the database, checking for a hot-journal file or 
  5237   5241   ** rolling back a journal file, the IO error code is returned.
  5238   5242   */
  5239   5243   int sqlite3PagerSharedLock(Pager *pPager, int bReadonly){
  5240   5244     int rc = SQLITE_OK;                /* Return code */
         5245  +#ifdef SQLITE_SERVER_EDITION
         5246  +  int eServer = 0;
         5247  +#endif
  5241   5248   
  5242   5249     /* This routine is only called from b-tree and only when there are no
  5243   5250     ** outstanding pages. This implies that the pager state should either
  5244   5251     ** be OPEN or READER. READER is only possible if the pager is or was in 
  5245   5252     ** exclusive access mode.  */
  5246   5253     assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
  5247   5254     assert( assert_pager_state(pPager) );
................................................................................
  5262   5269         goto failed;
  5263   5270       }
  5264   5271   
  5265   5272       /* If a journal file exists, and there is no RESERVED lock on the
  5266   5273       ** database file, then it either needs to be played back or deleted.
  5267   5274       */
  5268   5275       if( pPager->eLock<=SHARED_LOCK ){
  5269         -      rc = hasHotJournal(pPager, &bHotJournal);
         5276  +      rc = hasHotJournal(pPager, &bHotJournal, &eServer);
         5277  +      assert( bHotJournal==0 || eServer==0 );
  5270   5278       }
  5271   5279       if( rc!=SQLITE_OK ){
  5272   5280         goto failed;
  5273   5281       }
  5274   5282       if( bHotJournal ){
  5275   5283         if( pPager->readOnly ){
  5276   5284           rc = SQLITE_READONLY_ROLLBACK;
................................................................................
  5395   5403   
  5396   5404         IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
  5397   5405         rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
  5398   5406         if( rc!=SQLITE_OK ){
  5399   5407           if( rc!=SQLITE_IOERR_SHORT_READ ){
  5400   5408             goto failed;
  5401   5409           }
         5410  +        rc = SQLITE_OK;
  5402   5411           memset(dbFileVers, 0, sizeof(dbFileVers));
  5403   5412         }
  5404   5413   
  5405   5414         if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
  5406   5415           pager_reset(pPager);
  5407   5416   
  5408   5417           /* Unmap the database file. It is possible that external processes
................................................................................
  5413   5422           ** possibility by unmapping the db here. */
  5414   5423           if( USEFETCH(pPager) ){
  5415   5424             sqlite3OsUnfetch(pPager->fd, 0, 0);
  5416   5425           }
  5417   5426         }
  5418   5427       }
  5419   5428   
  5420         -    rc = pagerServerConnect(pPager);
         5429  +#ifdef SQLITE_SERVER_EDITION
         5430  +    if( eServer ){
         5431  +      rc = pagerServerConnect(pPager);
         5432  +    }
         5433  +#endif
  5421   5434   
  5422   5435       /* If there is a WAL file in the file-system, open this database in WAL
  5423   5436       ** mode. Otherwise, the following function call is a no-op.
  5424   5437       */
  5425   5438       if( rc==SQLITE_OK ){
  5426   5439         rc = pagerOpenWalIfPresent(pPager);
  5427   5440       }
................................................................................
  5430   5443   #endif
  5431   5444     }
  5432   5445   
  5433   5446   #ifdef SQLITE_SERVER_EDITION
  5434   5447     if( pagerIsServer(pPager) ){
  5435   5448       assert( rc==SQLITE_OK );
  5436   5449       assert( sqlite3PagerRefcount(pPager)==0 );
         5450  +    assert( pagerUseWal(pPager)==0 );
  5437   5451       pager_reset(pPager);
  5438   5452       rc = sqlite3ServerBegin(pPager->pServer, bReadonly);
  5439   5453       if( rc==SQLITE_OK ){
  5440   5454         rc = sqlite3ServerLock(pPager->pServer, 1, 0, 0);
  5441   5455       }
  5442   5456     }
  5443   5457   #endif
................................................................................
  7730   7744   #endif
  7731   7745   
  7732   7746   #ifdef SQLITE_SERVER_EDITION
  7733   7747   int sqlite3PagerIsServer(Pager *pPager){
  7734   7748     return pagerIsServer(pPager);
  7735   7749   }
  7736   7750   int sqlite3PagerPagelock(Pager *pPager, Pgno pgno, int bWrite){
         7751  +  if( pagerIsServer(pPager)==0 ) return SQLITE_OK;
  7737   7752     return sqlite3ServerLock(pPager->pServer, pgno, bWrite, 0);
  7738   7753   }
  7739   7754   #endif
  7740   7755   
  7741   7756   #endif /* SQLITE_OMIT_DISKIO */

Changes to src/server.c.

   243    243     }else{
   244    244       u8 *a = pDb->aJrnlFdSpace;
   245    245       int i;
   246    246       for(i=0; rc==SQLITE_OK && i<HMA_MAX_TRANSACTIONID; i++){
   247    247         int bExists = 0;
   248    248         ServerJournal *pJ = &pDb->aJrnl[i];
   249    249         pJ->jfd = (sqlite3_file*)&a[ROUND8(pVfs->szOsFile)*i];
   250         -      pJ->zJournal = sqlite3_mprintf("%s-journal%d", zFilename, i);
          250  +      pJ->zJournal = sqlite3_mprintf("%s-journal/%d-journal", zFilename, i);
   251    251         if( pJ->zJournal==0 ){
   252    252           rc = SQLITE_NOMEM_BKPT;
   253    253           break;
   254    254         }
   255    255   
   256    256         rc = sqlite3OsAccess(pVfs, pJ->zJournal, SQLITE_ACCESS_EXISTS, &bExists);
   257    257         if( rc==SQLITE_OK && bExists ){

Changes to src/sqlite.h.in.

  1041   1041   #define SQLITE_FCNTL_ZIPVFS                 25
  1042   1042   #define SQLITE_FCNTL_RBU                    26
  1043   1043   #define SQLITE_FCNTL_VFS_POINTER            27
  1044   1044   #define SQLITE_FCNTL_JOURNAL_POINTER        28
  1045   1045   #define SQLITE_FCNTL_WIN32_GET_HANDLE       29
  1046   1046   #define SQLITE_FCNTL_PDB                    30
  1047   1047   #define SQLITE_FCNTL_FILEID                 31
         1048  +#define SQLITE_FCNTL_SERVER_MODE            32
  1048   1049   
  1049   1050   /* deprecated names */
  1050   1051   #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
  1051   1052   #define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
  1052   1053   #define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO
  1053   1054   
  1054   1055   

Changes to src/test_config.c.

   721    721   #endif
   722    722   
   723    723   #ifdef SQLITE_ENABLE_URI_00_ERROR
   724    724     Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "1", TCL_GLOBAL_ONLY);
   725    725   #else
   726    726     Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY);
   727    727   #endif
          728  +
          729  +#ifdef SQLITE_SERVER_EDITION
          730  +  Tcl_SetVar2(interp, "sqlite_options", "server", "1", TCL_GLOBAL_ONLY);
          731  +#else
          732  +  Tcl_SetVar2(interp, "sqlite_options", "server", "0", TCL_GLOBAL_ONLY);
          733  +#endif
   728    734   
   729    735   #define LINKVAR(x) { \
   730    736       static const int cv_ ## x = SQLITE_ ## x; \
   731    737       Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
   732    738                   TCL_LINK_INT | TCL_LINK_READ_ONLY); }
   733    739   
   734    740     LINKVAR( MAX_LENGTH );

Changes to test/permutations.test.

   274    274     All FTS5 tests.
   275    275   } -files [glob -nocomplain $::testdir/../ext/fts5/test/*.test]
   276    276   
   277    277   test_suite "server" -prefix "" -description {
   278    278     All server-edition tests.
   279    279   } -files [
   280    280     test_set \
   281         -      select1.test server2.test server3.test server4.test
          281  +      select1.test server2.test server3.test server4.test server5.test
   282    282   ]
   283    283   
   284    284   test_suite "fts5-light" -prefix "" -description {
   285    285     All FTS5 tests.
   286    286   } -files [
   287    287     test_set \
   288    288         [glob -nocomplain $::testdir/../ext/fts5/test/*.test] \

Changes to test/server2.test.

    13     13   #
    14     14   
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   set testprefix server2
    19     19   
           20  +source $testdir/server_common.tcl
           21  +return_if_no_server
           22  +
    20     23   db close
    21     24   foreach f [glob -nocomplain test.db*] {
    22     25     forcedelete $f
    23     26   }
    24     27   
    25     28   #-------------------------------------------------------------------------
    26     29   # Check that the *-journal* files are deleted correctly.
    27     30   #
    28         -reset_db
           31  +server_reset_db
    29     32   do_execsql_test 1.0 {
    30     33     CREATE TABLE t1(a, b);
    31     34   } {}
    32     35   
    33     36   do_test 1.1 {
    34         -  lsort [glob test.db*]
    35         -} {test.db test.db-journal0}
           37  +  lsort [glob -nocomplain test.db-journal/*]
           38  +} {test.db-journal/0-journal}
    36     39   
    37     40   do_test 1.2 {
    38     41     db close
    39         -  lsort [glob test.db*]
    40         -} {test.db}
           42  +  lsort [glob -nocomplain test.db-journal/*]
           43  +} {}
    41     44   
    42         -sqlite3 db test.db
           45  +server_sqlite3 db test.db
    43     46   do_execsql_test 1.3 {
    44     47     CREATE TABLE t2(a, b);
    45     48   } {}
    46     49   
    47         -sqlite3 db2 test.db
           50  +server_sqlite3 db2 test.db
    48     51   do_test 1.4 {
    49     52     db eval {
    50     53       BEGIN;
    51     54         INSERT INTO t1 VALUES(1, 2);
    52     55     }
    53     56     db2 eval {
    54     57       BEGIN;
................................................................................
    55     58         INSERT INTO t2 VALUES(3, 4);
    56     59     }
    57     60   } {}
    58     61   
    59     62   do_test 1.5 {
    60     63     db2 eval COMMIT
    61     64     db eval COMMIT
    62         -  lsort [glob test.db*]
    63         -} {test.db test.db-journal0 test.db-journal1}
           65  +  lsort [glob -nocomplain test.db-journal/*]
           66  +} {test.db-journal/0-journal test.db-journal/1-journal}
    64     67   
    65     68   do_test 1.6 {
    66     69     db close
    67         -  lsort [glob test.db*]
    68         -} {test.db test.db-journal0 test.db-journal1}
           70  +  lsort [glob -nocomplain test.db-journal/*]
           71  +} {test.db-journal/0-journal test.db-journal/1-journal}
    69     72   
    70     73   do_test 1.7 {
    71     74     db2 close
    72         -  lsort [glob test.db*]
    73         -} {test.db}
           75  +  lsort [glob -nocomplain test.db-journal/*]
           76  +} {}
    74     77   
    75     78   #-------------------------------------------------------------------------
    76     79   #
    77         -reset_db
    78         -sqlite3 db2 test.db
           80  +server_reset_db
           81  +server_sqlite3 db2 test.db
    79     82   
    80     83   do_execsql_test 2.0 {
    81     84     CREATE TABLE t1(a, b);
    82     85     CREATE TABLE t2(c, d);
    83     86   }
    84     87   
    85     88   # Two concurrent transactions committed.
................................................................................
    91     94     }
    92     95     db2 eval {
    93     96       BEGIN;
    94     97         INSERT INTO t2 VALUES(3, 4);
    95     98     }
    96     99   } {}
    97    100   do_test 2.2 {
    98         -  lsort [glob test.db*]
    99         -} {test.db test.db-journal0 test.db-journal1}
          101  +  lsort [glob -nocomplain test.db-journal/*]
          102  +} {test.db-journal/0-journal test.db-journal/1-journal}
   100    103   do_test 2.3.1 { db eval COMMIT  } {}
   101    104   do_test 2.3.2 { db2 eval COMMIT } {}
   102    105   do_execsql_test 2.4 {SELECT * FROM t1, t2} {1 2 3 4}
   103    106   do_test 2.5 {
   104         -  lsort [glob test.db*]
   105         -} {test.db test.db-journal0 test.db-journal1}
          107  +  lsort [glob -nocomplain test.db-journal/*]
          108  +} {test.db-journal/0-journal test.db-journal/1-journal}
   106    109   
   107    110   do_test 2.6 {
   108    111     execsql {BEGIN}
   109    112     execsql {INSERT INTO t1 VALUES(5, 6)}
   110    113   
   111    114     execsql {BEGIN} db2
   112    115     catchsql {INSERT INTO t1 VALUES(7, 8)} db2
................................................................................
   119    122     execsql COMMIT
   120    123     execsql { SELECT * FROM t1 } db2
   121    124   } {1 2 5 6}
   122    125   db2 close
   123    126   
   124    127   #-------------------------------------------------------------------------
   125    128   #
   126         -reset_db
          129  +server_reset_db
   127    130   do_execsql_test 3.0 {
   128    131     CREATE TABLE t1(a, b);
   129    132   }
   130    133   
   131    134   do_test 3.1 {
   132         -  glob test.db*
   133         -} {test.db-journal0 test.db}
          135  +  lsort [glob -nocomplain test.db-journal/*]
          136  +} {test.db-journal/0-journal}
   134    137   
   135    138   do_test 3.2 {
   136    139     db close
   137         -  glob test.db*
   138         -} {test.db}
   139         -
          140  +  lsort [glob -nocomplain test.db-journal/*]
          141  +} {}
   140    142   finish_test
   141    143   

Changes to test/server3.test.

    14     14   
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   source $testdir/lock_common.tcl
    19     19   set testprefix server3
    20     20   
    21         -db close
           21  +source $testdir/server_common.tcl
           22  +return_if_no_server
           23  +
           24  +server_reset_db
           25  +server_sqlite3 db2 test.db
    22     26   
    23         -do_multiclient_test tn {
    24         -  if {$tn==1} continue
           27  +do_test 1.1 {
           28  +  db eval { CREATE TABLE t1(a, b) }
           29  +  db2 eval { CREATE TABLE t2(a, b) }
           30  +} {}
    25     31   
    26         -  do_test $tn.1 {
    27         -    sql1 { CREATE TABLE t1(a, b) }
    28         -    sql2 { CREATE TABLE t2(a, b) }
    29         -  } {}
           32  +do_test 1.2 {
           33  +  db eval {
           34  +    INSERT INTO t2 VALUES(1, 2);
           35  +    BEGIN;
           36  +    INSERT INTO t1 VALUES(1, 2);
           37  +  }
           38  +} {}
    30     39   
    31         -  do_test $tn.2 {
    32         -    sql1 {
    33         -      INSERT INTO t2 VALUES(1, 2);
    34         -      BEGIN;
    35         -        INSERT INTO t1 VALUES(1, 2);
    36         -    }
    37         -  } {}
           40  +do_test 1.3 { 
           41  +  list [catch { db2 eval { SELECT * FROM t1 } } msg] $msg
           42  +} {1 {database is locked}}
           43  +do_test 1.4 { 
           44  +  list [catch { db2 eval { SELECT * FROM t1 } } msg] $msg
           45  +} {1 {database is locked}}
    38     46   
    39         -  do_test $tn.3 { csql2 { SELECT * FROM t1 } } {1 {database is locked}}
    40         -  do_test $tn.4 { csql2 { SELECT * FROM t1 } } {1 {database is locked}}
    41         -  do_test $tn.5 {  sql2 { SELECT * FROM t2 } } {1 2}
    42         -
    43         -
    44         -}
           47  +do_test 1.4 { 
           48  +  db2 eval { SELECT * FROM t2 }
           49  +} {1 2}
    45     50   
    46     51   finish_test
    47     52   

Changes to test/server4.test.

    15     15   # transaction.
    16     16   #
    17     17   
    18     18   
    19     19   set testdir [file dirname $argv0]
    20     20   source $testdir/tester.tcl
    21     21   source $testdir/lock_common.tcl
    22         -set testprefix server3
           22  +set testprefix server4
           23  +
           24  +source $testdir/server_common.tcl
           25  +return_if_no_server
    23     26   
    24         -sqlite3 db2 test.db
           27  +server_reset_db
           28  +server_sqlite3 db2 test.db
    25     29   
    26     30   do_execsql_test 1.0 {
    27     31     CREATE TABLE t1(x);
    28     32     INSERT INTO t1 VALUES(1);
    29     33     CREATE TABLE t2(x);
    30     34     INSERT INTO t2 VALUES(1);
    31     35     BEGIN;
................................................................................
    52     56     SELECT * FROM t2;
    53     57   } {1}
    54     58   
    55     59   do_execsql_test -db db2 1.4 {
    56     60     ROLLBACK;
    57     61     SELECT * FROM t1;
    58     62   } {1 2 3}
    59         -
    60     63   
    61     64   finish_test
    62     65   

Changes to test/server5.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  
    12     12   #
    13     13   # The focus of this script is testing the server mode of SQLite.
    14         -# Specifically, that "BEGIN READONLY" starts a read-only MVCC
    15         -# transaction.
           14  +# Specifically, that "PRAGMA freelist_format" works.
    16     15   #
    17     16   
    18     17   
    19     18   set testdir [file dirname $argv0]
    20     19   source $testdir/tester.tcl
    21     20   set testprefix server5
    22     21   
    23     22   do_execsql_test 1.0 {
    24     23     PRAGMA freelist_format;
    25     24   } {1}
    26     25   
    27         -explain_i {
    28         -  PRAGMA freelist_format = 2;
    29         -}
    30         -
    31     26   do_execsql_test 1.1 {
    32     27     PRAGMA freelist_format = 2;
    33     28   } {2}
    34     29   
    35     30   do_execsql_test 1.2 {
    36     31     PRAGMA freelist_format;
    37     32   } {2}
................................................................................
    52     47   do_execsql_test 1.6 {
    53     48     CREATE TABLE t2(y);
    54     49   }
    55     50   
    56     51   do_execsql_test 1.6 {
    57     52     PRAGMA freelist_format = 1;
    58     53   } {2}
    59         -
    60         -
    61     54   
    62     55   finish_test
    63     56   

Added test/server_common.tcl.

            1  +# 2017 July 25
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +#
           13  +
           14  +ifcapable !server {
           15  +  proc return_if_no_server {} {
           16  +    finish_test
           17  +    return -code return
           18  +  }
           19  +  return
           20  +} else {
           21  +  proc return_if_no_server {} {}
           22  +}
           23  +
           24  +proc server_sqlite3 {cmd file} {
           25  +  sqlite3 $cmd $file -vfs unix-excl
           26  +}
           27  +
           28  +proc server_reset_db {} {
           29  +  catch {db close}
           30  +  forcedelete test.db test.db-journal test.db-wal
           31  +  file mkdir test.db-journal
           32  +  server_sqlite3 db test.db 
           33  +}
           34  +
           35  +

Deleted test/serverwal.test.

     1         -# 2017 April 25
     2         -#
     3         -# The author disclaims copyright to this source code.  In place of
     4         -# a legal notice, here is a blessing:
     5         -#
     6         -#    May you do good and not evil.
     7         -#    May you find forgiveness for yourself and forgive others.
     8         -#    May you share freely, never taking more than you give.
     9         -#
    10         -#***********************************************************************
    11         -# This file implements regression tests for SQLite library.  The
    12         -# focus of this script is testing the server mode of SQLite.
    13         -#
    14         -
    15         -
    16         -set testdir [file dirname $argv0]
    17         -source $testdir/tester.tcl
    18         -set testprefix serverwal
    19         -
    20         -# Check files are created and deleted as expected.
    21         -#
    22         -do_execsql_test 1.0 {
    23         -  PRAGMA journal_mode = wal;
    24         -} {wal}
    25         -do_execsql_test 1.1 {
    26         -  CREATE TABLE t1(a, b);
    27         -}
    28         -do_execsql_test 1.2 {
    29         -  SELECT * FROM t1;
    30         -} {}
    31         -do_test 1.3 {
    32         -  lsort [glob test.db*]
    33         -} {test.db test.db-hma test.db-shm test.db-wal}
    34         -do_test 1.4 {
    35         -  db close
    36         -  glob test.db*
    37         -} {test.db}
    38         -
    39         -#-------------------------------------------------------------------------
    40         -# Two concurrent transactions.
    41         -#
    42         -do_test 2.0 {
    43         -  sqlite3 db  test.db
    44         -  sqlite3 db2 test.db
    45         -  db eval {
    46         -    CREATE TABLE t2(a, b);
    47         -  }
    48         -} {}
    49         -do_test 2.1 {
    50         -  execsql {
    51         -    BEGIN;
    52         -      INSERT INTO t1 VALUES(1, 2);
    53         -  } db
    54         -  execsql {
    55         -    BEGIN;
    56         -      INSERT INTO t2 VALUES(1, 2);
    57         -  } db2
    58         -} {}
    59         -do_test 2.2 {
    60         -  execsql COMMIT db
    61         -  execsql COMMIT db2
    62         -} {}
    63         -db close
    64         -db2 close
    65         -
    66         -#-------------------------------------------------------------------------
    67         -# That the wal file can be wrapped around.
    68         -#
    69         -reset_db
    70         -do_execsql_test 3.0 {
    71         -  PRAGMA journal_mode = wal;
    72         -  CREATE TABLE ttt(a, b);
    73         -  INSERT INTO ttt VALUES(1, 2);
    74         -  INSERT INTO ttt VALUES(3, 4);
    75         -  INSERT INTO ttt VALUES(5, 6);
    76         -  INSERT INTO ttt VALUES(7, 8);
    77         -  INSERT INTO ttt VALUES(9, 10);
    78         -} {wal}
    79         -
    80         -do_test 3.1 {
    81         -  set N [file size test.db-wal]
    82         -  execsql {
    83         -    PRAGMA wal_checkpoint = restart;
    84         -    INSERT INTO ttt VALUES(11, 12);
    85         -    INSERT INTO ttt VALUES(13, 14);
    86         -  }
    87         -  expr {$N == [file size test.db-wal]}
    88         -} {1}
    89         -
    90         -#-------------------------------------------------------------------------
    91         -# That ROLLBACK appears to work.
    92         -#
    93         -reset_db
    94         -do_execsql_test 4.0 {
    95         -  PRAGMA cache_size = 10;
    96         -  CREATE TABLE ttt(a, b);
    97         -  CREATE INDEX yyy ON ttt(b, a);
    98         -  PRAGMA journal_mode = wal;
    99         -  WITH s(i) AS (
   100         -    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
   101         -  )
   102         -  INSERT INTO ttt SELECT randomblob(100), randomblob(100) FROM s;
   103         -} {wal}
   104         -
   105         -do_execsql_test 4.1 {
   106         -  PRAGMA integrity_check;
   107         -  BEGIN;
   108         -    UPDATE ttt SET b=a;
   109         -  ROLLBACK;
   110         -  PRAGMA integrity_check;
   111         -} {ok ok}
   112         -
   113         -reset_db
   114         -do_execsql_test 5.1 {
   115         -  CREATE TABLE xyz(a);
   116         -  PRAGMA journal_mode = wal;
   117         -  INSERT INTO xyz VALUES(1);
   118         -  INSERT INTO xyz VALUES(2);
   119         -  INSERT INTO xyz VALUES(3);
   120         -} {wal}
   121         -
   122         -breakpoint
   123         -
   124         -do_test 5.2 {
   125         -  sqlite3 db2 test.db
   126         -  execsql { SELECT * FROM xyz } db2
   127         -} {1 2 3}
   128         -
   129         -do_execsql_test 5.3 {
   130         -  PRAGMA wal_checkpoint = restart 
   131         -} {0 0 0}
   132         -
   133         -do_test 5.4 {
   134         -  execsql { SELECT * FROM xyz } db2
   135         -} {1 2 3}
   136         -
   137         -finish_test
   138         -