/ Check-in [97b98010]
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:Pull in the patches to support read-only WAL databases into a new branch off of the apple-osx branch. This also pulls in all the other pending 3.7.7 changes such as URI support.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-wal-readonly
Files: files | file ages | folders
SHA1: 97b980107676b2ea45a07c9c1a7de2e1ca74881f
User & Date: drh 2011-05-12 15:32:51
Context
2011-05-19
02:34
Bring the apple-wal-readonly branch up to date with the latest changes in apple-osx, and especially the fix for disappearing WAL transactions. Leaf check-in: 57912327 user: drh tags: apple-wal-readonly
2011-05-12
15:32
Pull in the patches to support read-only WAL databases into a new branch off of the apple-osx branch. This also pulls in all the other pending 3.7.7 changes such as URI support. check-in: 97b98010 user: drh tags: apple-wal-readonly
2011-05-11
17:36
Add missing comments associated with readonly shm changes. check-in: 6a2ea52e user: dan tags: wal-readonly
2011-05-05
15:52
Merge the latest trunk changes into the apple-osx branch. check-in: f9b149e5 user: drh tags: apple-osx
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  3657   3657   }
  3658   3658   static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  3659   3659     sqlite3Fts3PendingTermsClear((Fts3Table *)pVtab);
  3660   3660     return SQLITE_OK;
  3661   3661   }
  3662   3662   
  3663   3663   static const sqlite3_module fts3Module = {
  3664         -  /* iVersion      */ 1,
         3664  +  /* iVersion      */ 2,
  3665   3665     /* xCreate       */ fts3CreateMethod,
  3666   3666     /* xConnect      */ fts3ConnectMethod,
  3667   3667     /* xBestIndex    */ fts3BestIndexMethod,
  3668   3668     /* xDisconnect   */ fts3DisconnectMethod,
  3669   3669     /* xDestroy      */ fts3DestroyMethod,
  3670   3670     /* xOpen         */ fts3OpenMethod,
  3671   3671     /* xClose        */ fts3CloseMethod,

Changes to src/attach.c.

    66     66     sqlite3_value **argv
    67     67   ){
    68     68     int i;
    69     69     int rc = 0;
    70     70     sqlite3 *db = sqlite3_context_db_handle(context);
    71     71     const char *zName;
    72     72     const char *zFile;
           73  +  char *zPath = 0;
           74  +  char *zErr = 0;
           75  +  unsigned int flags;
    73     76     Db *aNew;
    74     77     char *zErrDyn = 0;
           78  +  sqlite3_vfs *pVfs;
           79  +  const char *zVfs = db->pVfs->zName;       /* Name of default (main) VFS */
           80  +  int btflags = 0;
    75     81   
    76     82     UNUSED_PARAMETER(NotUsed);
    77     83   
    78     84     zFile = (const char *)sqlite3_value_text(argv[0]);
    79     85     zName = (const char *)sqlite3_value_text(argv[1]);
    80     86     if( zFile==0 ) zFile = "";
    81     87     if( zName==0 ) zName = "";
................................................................................
   120    126     aNew = &db->aDb[db->nDb];
   121    127     memset(aNew, 0, sizeof(*aNew));
   122    128   
   123    129     /* Open the database file. If the btree is successfully opened, use
   124    130     ** it to obtain the database schema. At this point the schema may
   125    131     ** or may not be initialised.
   126    132     */
   127         -  rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0,
   128         -                        db->openFlags | SQLITE_OPEN_MAIN_DB);
          133  +  flags = db->openFlags;
          134  +  rc = sqlite3ParseUri(zVfs, zFile, &flags, &btflags, &pVfs, &zPath, &zErr);
          135  +  if( rc!=SQLITE_OK ){
          136  +    if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
          137  +    sqlite3_result_error(context, zErr, -1);
          138  +    sqlite3_free(zErr);
          139  +    return;
          140  +  }
          141  +  assert( pVfs );
          142  +  flags |= SQLITE_OPEN_MAIN_DB;
          143  +  rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, btflags, flags);
          144  +  sqlite3_free( zPath );
   129    145     db->nDb++;
   130    146     if( rc==SQLITE_CONSTRAINT ){
   131    147       rc = SQLITE_ERROR;
   132    148       zErrDyn = sqlite3MPrintf(db, "database is already attached");
   133    149     }else if( rc==SQLITE_OK ){
   134    150       Pager *pPager;
   135    151       aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);

Changes to src/btree.c.

  1684   1684   ** If the database is already opened in the same database connection
  1685   1685   ** and we are in shared cache mode, then the open will fail with an
  1686   1686   ** SQLITE_CONSTRAINT error.  We cannot allow two or more BtShared
  1687   1687   ** objects in the same database connection since doing so will lead
  1688   1688   ** to problems with locking.
  1689   1689   */
  1690   1690   int sqlite3BtreeOpen(
         1691  +  sqlite3_vfs *pVfs,      /* VFS to use for this b-tree */
  1691   1692     const char *zFilename,  /* Name of the file containing the BTree database */
  1692   1693     sqlite3 *db,            /* Associated database handle */
  1693   1694     Btree **ppBtree,        /* Pointer to new Btree object written here */
  1694   1695     int flags,              /* Options */
  1695   1696     int vfsFlags            /* Flags passed through to sqlite3_vfs.xOpen() */
  1696   1697   ){
  1697         -  sqlite3_vfs *pVfs;             /* The VFS to use for this btree */
  1698   1698     BtShared *pBt = 0;             /* Shared part of btree structure */
  1699   1699     Btree *p;                      /* Handle to return */
  1700   1700     sqlite3_mutex *mutexOpen = 0;  /* Prevents a race condition. Ticket #3537 */
  1701   1701     int rc = SQLITE_OK;            /* Result code from this function */
  1702   1702     u8 nReserve;                   /* Byte of unused space on each page */
  1703   1703     unsigned char zDbHeader[100];  /* Database header content */
  1704   1704   
................................................................................
  1712   1712     const int isMemdb = 0;
  1713   1713   #else
  1714   1714     const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
  1715   1715                          || (isTempDb && sqlite3TempInMemory(db));
  1716   1716   #endif
  1717   1717   
  1718   1718     assert( db!=0 );
         1719  +  assert( pVfs!=0 );
  1719   1720     assert( sqlite3_mutex_held(db->mutex) );
  1720   1721     assert( (flags&0xff)==flags );   /* flags fit in 8 bits */
  1721   1722   
  1722   1723     /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
  1723   1724     assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );
  1724   1725   
  1725   1726     /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
................................................................................
  1730   1731     }
  1731   1732     if( isMemdb ){
  1732   1733       flags |= BTREE_MEMORY;
  1733   1734     }
  1734   1735     if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
  1735   1736       vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
  1736   1737     }
  1737         -  pVfs = db->pVfs;
  1738   1738     p = sqlite3MallocZero(sizeof(Btree));
  1739   1739     if( !p ){
  1740   1740       return SQLITE_NOMEM;
  1741   1741     }
  1742   1742     p->inTrans = TRANS_NONE;
  1743   1743     p->db = db;
  1744   1744   #ifndef SQLITE_OMIT_SHARED_CACHE

Changes to src/btree.h.

    38     38   */
    39     39   typedef struct Btree Btree;
    40     40   typedef struct BtCursor BtCursor;
    41     41   typedef struct BtShared BtShared;
    42     42   
    43     43   
    44     44   int sqlite3BtreeOpen(
           45  +  sqlite3_vfs *pVfs,       /* VFS to use with this b-tree */
    45     46     const char *zFilename,   /* Name of database file to open */
    46     47     sqlite3 *db,             /* Associated database connection */
    47     48     Btree **ppBtree,         /* Return open Btree* here */
    48     49     int flags,               /* Flags */
    49     50     int vfsFlags             /* Flags passed through to VFS open */
    50     51   );
    51     52   
................................................................................
    56     57   ** pager.h.
    57     58   */
    58     59   #define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
    59     60   #define BTREE_NO_READLOCK   2  /* Omit readlocks on readonly files */
    60     61   #define BTREE_MEMORY        4  /* This is an in-memory DB */
    61     62   #define BTREE_SINGLE        8  /* The file contains at most 1 b-tree */
    62     63   #define BTREE_UNORDERED    16  /* Use of a hash implementation is OK */
           64  +#define BTREE_READONLYSHM  32  /* Read-only SHM access is acceptable */
    63     65   
    64     66   int sqlite3BtreeClose(Btree*);
    65     67   int sqlite3BtreeSetCacheSize(Btree*,int);
    66     68   int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
    67     69   int sqlite3BtreeSyncDisabled(Btree*);
    68     70   int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
    69     71   int sqlite3BtreeGetPageSize(Btree*);

Changes to src/build.c.

  3439   3439       static const int flags = 
  3440   3440             SQLITE_OPEN_READWRITE |
  3441   3441             SQLITE_OPEN_CREATE |
  3442   3442             SQLITE_OPEN_EXCLUSIVE |
  3443   3443             SQLITE_OPEN_DELETEONCLOSE |
  3444   3444             SQLITE_OPEN_TEMP_DB;
  3445   3445   
  3446         -    rc = sqlite3BtreeOpen(0, db, &pBt, 0, flags);
         3446  +    rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
  3447   3447       if( rc!=SQLITE_OK ){
  3448   3448         sqlite3ErrorMsg(pParse, "unable to open a temporary database "
  3449   3449           "file for storing temporary tables");
  3450   3450         pParse->rc = rc;
  3451   3451         return 1;
  3452   3452       }
  3453   3453       db->aDb[1].pBt = pBt;

Changes to src/global.c.

   125    125     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e0..e7    ........ */
   126    126     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e8..ef    ........ */
   127    127     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* f0..f7    ........ */
   128    128     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40   /* f8..ff    ........ */
   129    129   };
   130    130   #endif
   131    131   
   132         -
          132  +#ifndef SQLITE_USE_URI
          133  +# define  SQLITE_USE_URI 0
          134  +#endif
   133    135   
   134    136   /*
   135    137   ** The following singleton contains the global configuration for
   136    138   ** the SQLite library.
   137    139   */
   138    140   SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   139    141      SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
   140    142      1,                         /* bCoreMutex */
   141    143      SQLITE_THREADSAFE==1,      /* bFullMutex */
          144  +   SQLITE_USE_URI,            /* bOpenUri */
   142    145      0x7ffffffe,                /* mxStrlen */
   143    146      100,                       /* szLookaside */
   144    147      500,                       /* nLookaside */
   145    148      {0,0,0,0,0,0,0,0},         /* m */
   146    149      {0,0,0,0,0,0,0,0,0},       /* mutex */
   147    150      {0,0,0,0,0,0,0,0,0,0,0},   /* pcache */
   148    151      (void*)0,                  /* pHeap */

Changes to src/main.c.

   424    424         ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
   425    425         */
   426    426         typedef void(*LOGFUNC_t)(void*,int,const char*);
   427    427         sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
   428    428         sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
   429    429         break;
   430    430       }
          431  +
          432  +    case SQLITE_CONFIG_URI: {
          433  +      sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
          434  +      break;
          435  +    }
   431    436   
   432    437       default: {
   433    438         rc = SQLITE_ERROR;
   434    439         break;
   435    440       }
   436    441     }
   437    442     va_end(ap);
................................................................................
  1793   1798   }
  1794   1799   #if defined(SQLITE_ENABLE_AUTO_PROFILE)
  1795   1800   static void profile_sql(void *aux, const char *sql, u64 ns) {
  1796   1801   #pragma unused(aux)
  1797   1802   	fprintf(stderr, "Query: %s\n Execution Time: %llu ms\n", sql, ns / 1000000);
  1798   1803   }
  1799   1804   #endif
         1805  +
         1806  +/*
         1807  +** This function is used to parse both URIs and non-URI filenames passed by the
         1808  +** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
         1809  +** URIs specified as part of ATTACH statements.
         1810  +**
         1811  +** The first argument to this function is the name of the VFS to use (or
         1812  +** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
         1813  +** query parameter. The second argument contains the URI (or non-URI filename)
         1814  +** itself. When this function is called the *pFlags variable should contain
         1815  +** the default flags to open the database handle with. The value stored in
         1816  +** *pFlags may be updated before returning if the URI filename contains 
         1817  +** "cache=xxx" or "mode=xxx" query parameters.
         1818  +**
         1819  +** The third argument, pBtflags, points to an integer containing the flags
         1820  +** that will be passed as the 5th argument to sqlite3BtreeOpen (BTREE_XXX
         1821  +** flags). This value will be edited if the URI filename contains a
         1822  +** "readonly_shm=1" or "readonly_shm=0" query parameter.
         1823  +**
         1824  +** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
         1825  +** the VFS that should be used to open the database file. *pzFile is set to
         1826  +** point to a buffer containing the name of the file to open. It is the 
         1827  +** responsibility of the caller to eventually call sqlite3_free() to release
         1828  +** this buffer.
         1829  +**
         1830  +** If an error occurs, then an SQLite error code is returned and *pzErrMsg
         1831  +** may be set to point to a buffer containing an English language error 
         1832  +** message. It is the responsibility of the caller to eventually release
         1833  +** this buffer by calling sqlite3_free().
         1834  +*/
         1835  +int sqlite3ParseUri(
         1836  +  const char *zDefaultVfs,        /* VFS to use if no "vfs=xxx" query option */
         1837  +  const char *zUri,               /* Nul-terminated URI to parse */
         1838  +  unsigned int *pFlags,           /* IN/OUT: SQLITE_OPEN_XXX flags */
         1839  +  int *pBtflags,                  /* IN/OUT: BTREE_XXX flags */
         1840  +  sqlite3_vfs **ppVfs,            /* OUT: VFS to use */ 
         1841  +  char **pzFile,                  /* OUT: Filename component of URI */
         1842  +  char **pzErrMsg                 /* OUT: Error message (if rc!=SQLITE_OK) */
         1843  +){
         1844  +  int rc = SQLITE_OK;
         1845  +  unsigned int flags = *pFlags;
         1846  +  const char *zVfs = zDefaultVfs;
         1847  +  char *zFile;
         1848  +  char c;
         1849  +  int nUri = sqlite3Strlen30(zUri);
         1850  +
         1851  +  assert( *pzErrMsg==0 );
         1852  +
         1853  +  if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri) 
         1854  +   && nUri>=5 && memcmp(zUri, "file:", 5)==0 
         1855  +  ){
         1856  +    char *zOpt;
         1857  +    int eState;                   /* Parser state when parsing URI */
         1858  +    int iIn;                      /* Input character index */
         1859  +    int iOut = 0;                 /* Output character index */
         1860  +    int nByte = nUri+2;           /* Bytes of space to allocate */
         1861  +
         1862  +    /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen 
         1863  +    ** method that there may be extra parameters following the file-name.  */
         1864  +    flags |= SQLITE_OPEN_URI;
         1865  +
         1866  +    for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
         1867  +    zFile = sqlite3_malloc(nByte);
         1868  +    if( !zFile ) return SQLITE_NOMEM;
         1869  +
         1870  +    /* Discard the scheme and authority segments of the URI. */
         1871  +    if( zUri[5]=='/' && zUri[6]=='/' ){
         1872  +      iIn = 7;
         1873  +      while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
         1874  +
         1875  +      if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
         1876  +        *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s", 
         1877  +            iIn-7, &zUri[7]);
         1878  +        rc = SQLITE_ERROR;
         1879  +        goto parse_uri_out;
         1880  +      }
         1881  +    }else{
         1882  +      iIn = 5;
         1883  +    }
         1884  +
         1885  +    /* Copy the filename and any query parameters into the zFile buffer. 
         1886  +    ** Decode %HH escape codes along the way. 
         1887  +    **
         1888  +    ** Within this loop, variable eState may be set to 0, 1 or 2, depending
         1889  +    ** on the parsing context. As follows:
         1890  +    **
         1891  +    **   0: Parsing file-name.
         1892  +    **   1: Parsing name section of a name=value query parameter.
         1893  +    **   2: Parsing value section of a name=value query parameter.
         1894  +    */
         1895  +    eState = 0;
         1896  +    while( (c = zUri[iIn])!=0 && c!='#' ){
         1897  +      iIn++;
         1898  +      if( c=='%' 
         1899  +       && sqlite3Isxdigit(zUri[iIn]) 
         1900  +       && sqlite3Isxdigit(zUri[iIn+1]) 
         1901  +      ){
         1902  +        int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
         1903  +        octet += sqlite3HexToInt(zUri[iIn++]);
         1904  +
         1905  +        assert( octet>=0 && octet<256 );
         1906  +        if( octet==0 ){
         1907  +          /* This branch is taken when "%00" appears within the URI. In this
         1908  +          ** case we ignore all text in the remainder of the path, name or
         1909  +          ** value currently being parsed. So ignore the current character
         1910  +          ** and skip to the next "?", "=" or "&", as appropriate. */
         1911  +          while( (c = zUri[iIn])!=0 && c!='#' 
         1912  +              && (eState!=0 || c!='?')
         1913  +              && (eState!=1 || (c!='=' && c!='&'))
         1914  +              && (eState!=2 || c!='&')
         1915  +          ){
         1916  +            iIn++;
         1917  +          }
         1918  +          continue;
         1919  +        }
         1920  +        c = octet;
         1921  +      }else if( eState==1 && (c=='&' || c=='=') ){
         1922  +        if( zFile[iOut-1]==0 ){
         1923  +          /* An empty option name. Ignore this option altogether. */
         1924  +          while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
         1925  +          continue;
         1926  +        }
         1927  +        if( c=='&' ){
         1928  +          zFile[iOut++] = '\0';
         1929  +        }else{
         1930  +          eState = 2;
         1931  +        }
         1932  +        c = 0;
         1933  +      }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
         1934  +        c = 0;
         1935  +        eState = 1;
         1936  +      }
         1937  +      zFile[iOut++] = c;
         1938  +    }
         1939  +    if( eState==1 ) zFile[iOut++] = '\0';
         1940  +    zFile[iOut++] = '\0';
         1941  +    zFile[iOut++] = '\0';
         1942  +
         1943  +    /* Check if there were any options specified that should be interpreted 
         1944  +    ** here. Options that are interpreted here include "vfs" and those that
         1945  +    ** correspond to flags that may be passed to the sqlite3_open_v2()
         1946  +    ** method. */
         1947  +    zOpt = &zFile[sqlite3Strlen30(zFile)+1];
         1948  +    while( zOpt[0] ){
         1949  +      int nOpt = sqlite3Strlen30(zOpt);
         1950  +      char *zVal = &zOpt[nOpt+1];
         1951  +      int nVal = sqlite3Strlen30(zVal);
         1952  +
         1953  +      if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
         1954  +        zVfs = zVal;
         1955  +      }else if( nOpt==12 && memcmp("readonly_shm", zOpt, 12)==0 ){
         1956  +        if( sqlite3Atoi(zVal) ){
         1957  +          *pBtflags |= BTREE_READONLYSHM;
         1958  +        }else{
         1959  +          *pBtflags &= ~BTREE_READONLYSHM;
         1960  +        }
         1961  +      }else{
         1962  +        struct OpenMode {
         1963  +          const char *z;
         1964  +          int mode;
         1965  +        } *aMode = 0;
         1966  +        char *zModeType;
         1967  +        int mask;
         1968  +        int limit;
         1969  +
         1970  +        if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
         1971  +          static struct OpenMode aCacheMode[] = {
         1972  +            { "shared",  SQLITE_OPEN_SHAREDCACHE },
         1973  +            { "private", SQLITE_OPEN_PRIVATECACHE },
         1974  +            { 0, 0 }
         1975  +          };
         1976  +
         1977  +          mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
         1978  +          aMode = aCacheMode;
         1979  +          limit = mask;
         1980  +          zModeType = "cache";
         1981  +        }
         1982  +        if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
         1983  +          static struct OpenMode aOpenMode[] = {
         1984  +            { "ro",  SQLITE_OPEN_READONLY },
         1985  +            { "rw",  SQLITE_OPEN_READWRITE }, 
         1986  +            { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
         1987  +            { 0, 0 }
         1988  +          };
         1989  +
         1990  +          mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
         1991  +          aMode = aOpenMode;
         1992  +          limit = mask & flags;
         1993  +          zModeType = "access";
         1994  +        }
         1995  +
         1996  +        if( aMode ){
         1997  +          int i;
         1998  +          int mode = 0;
         1999  +          for(i=0; aMode[i].z; i++){
         2000  +            const char *z = aMode[i].z;
         2001  +            if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
         2002  +              mode = aMode[i].mode;
         2003  +              break;
         2004  +            }
         2005  +          }
         2006  +          if( mode==0 ){
         2007  +            *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
         2008  +            rc = SQLITE_ERROR;
         2009  +            goto parse_uri_out;
         2010  +          }
         2011  +          if( mode>limit ){
         2012  +            *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
         2013  +                                        zModeType, zVal);
         2014  +            rc = SQLITE_PERM;
         2015  +            goto parse_uri_out;
         2016  +          }
         2017  +          flags = (flags & ~mask) | mode;
         2018  +        }
         2019  +      }
         2020  +
         2021  +      zOpt = &zVal[nVal+1];
         2022  +    }
         2023  +
         2024  +  }else{
         2025  +    zFile = sqlite3_malloc(nUri+2);
         2026  +    if( !zFile ) return SQLITE_NOMEM;
         2027  +    memcpy(zFile, zUri, nUri);
         2028  +    zFile[nUri] = '\0';
         2029  +    zFile[nUri+1] = '\0';
         2030  +  }
         2031  +
         2032  +  *ppVfs = sqlite3_vfs_find(zVfs);
         2033  +  if( *ppVfs==0 ){
         2034  +    *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
         2035  +    rc = SQLITE_ERROR;
         2036  +  }
         2037  + parse_uri_out:
         2038  +  if( rc!=SQLITE_OK ){
         2039  +    sqlite3_free(zFile);
         2040  +    zFile = 0;
         2041  +  }
         2042  +  *pFlags = flags;
         2043  +  *pzFile = zFile;
         2044  +  return rc;
         2045  +}
         2046  +
  1800   2047   
  1801   2048   /*
  1802   2049   ** This routine does the work of opening a database on behalf of
  1803   2050   ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"  
  1804   2051   ** is UTF-8 encoded.
  1805   2052   */
  1806   2053   static int openDatabase(
  1807   2054     const char *zFilename, /* Database filename UTF-8 encoded */
  1808   2055     sqlite3 **ppDb,        /* OUT: Returned database handle */
  1809         -  unsigned flags,        /* Operational flags */
         2056  +  unsigned int flags,    /* Operational flags */
  1810   2057     const char *zVfs       /* Name of the VFS to use */
  1811   2058   ){
  1812         -  sqlite3 *db;
  1813         -  int rc;
  1814         -  int isThreadsafe;
         2059  +  sqlite3 *db;                    /* Store allocated handle here */
         2060  +  int rc;                         /* Return code */
         2061  +  int isThreadsafe;               /* True for threadsafe connections */
         2062  +  char *zOpen = 0;                /* Filename argument to pass to BtreeOpen() */
         2063  +  char *zErrMsg = 0;              /* Error message from sqlite3ParseUri() */
         2064  +  int btflags = 0;                /* Mask of BTREE_XXX flags */
  1815   2065   
  1816   2066     *ppDb = 0;
  1817   2067   #ifndef SQLITE_OMIT_AUTOINIT
  1818   2068     rc = sqlite3_initialize();
  1819   2069     if( rc ) return rc;
  1820   2070   #endif
  1821   2071   
................................................................................
  1831   2081     */
  1832   2082     assert( SQLITE_OPEN_READONLY  == 0x01 );
  1833   2083     assert( SQLITE_OPEN_READWRITE == 0x02 );
  1834   2084     assert( SQLITE_OPEN_CREATE    == 0x04 );
  1835   2085     testcase( (1<<(flags&7))==0x02 ); /* READONLY */
  1836   2086     testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
  1837   2087     testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
  1838         -  if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE;
         2088  +  if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT;
  1839   2089   
  1840   2090     if( sqlite3GlobalConfig.bCoreMutex==0 ){
  1841   2091       isThreadsafe = 0;
  1842   2092     }else if( flags & SQLITE_OPEN_NOMUTEX ){
  1843   2093       isThreadsafe = 0;
  1844   2094     }else if( flags & SQLITE_OPEN_FULLMUTEX ){
  1845   2095       isThreadsafe = 1;
................................................................................
  1912   2162   #endif
  1913   2163         ;
  1914   2164     sqlite3HashInit(&db->aCollSeq);
  1915   2165   #ifndef SQLITE_OMIT_VIRTUALTABLE
  1916   2166     sqlite3HashInit(&db->aModule);
  1917   2167   #endif
  1918   2168   
  1919         -  db->pVfs = sqlite3_vfs_find(zVfs);
  1920         -  if( !db->pVfs ){
  1921         -    rc = SQLITE_ERROR;
  1922         -    sqlite3Error(db, rc, "no such vfs: %s", zVfs);
  1923         -    goto opendb_out;
  1924         -  }
  1925         -
  1926   2169     /* Add the default collation sequence BINARY. BINARY works for both UTF-8
  1927   2170     ** and UTF-16, so add a version for each to avoid any unnecessary
  1928   2171     ** conversions. The only error that can occur here is a malloc() failure.
  1929   2172     */
  1930   2173     createCollation(db, "BINARY", SQLITE_UTF8, SQLITE_COLL_BINARY, 0,
  1931   2174                     binCollFunc, 0);
  1932   2175     createCollation(db, "BINARY", SQLITE_UTF16BE, SQLITE_COLL_BINARY, 0,
................................................................................
  1941   2184     db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
  1942   2185     assert( db->pDfltColl!=0 );
  1943   2186   
  1944   2187     /* Also add a UTF-8 case-insensitive collation sequence. */
  1945   2188     createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0,
  1946   2189                     nocaseCollatingFunc, 0);
  1947   2190   
  1948         -  /* Open the backend database driver */
         2191  +  /* Parse the filename/URI argument. */
  1949   2192     db->openFlags = flags;
  1950         -  rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0,
         2193  +  rc = sqlite3ParseUri(
         2194  +      zVfs, zFilename, &flags, &btflags, &db->pVfs, &zOpen, &zErrMsg);
         2195  +  if( rc!=SQLITE_OK ){
         2196  +    if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
         2197  +    sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
         2198  +    sqlite3_free(zErrMsg);
         2199  +    goto opendb_out;
         2200  +  }
         2201  +
         2202  +  /* Open the backend database driver */
         2203  +  rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, btflags,
  1951   2204                           flags | SQLITE_OPEN_MAIN_DB);
  1952   2205     if( rc!=SQLITE_OK ){
  1953   2206       if( rc==SQLITE_IOERR_NOMEM ){
  1954   2207         rc = SQLITE_NOMEM;
  1955   2208       }
  1956   2209       sqlite3Error(db, rc, 0);
  1957   2210       goto opendb_out;
................................................................................
  2036   2289     /* Enable the lookaside-malloc subsystem */
  2037   2290     setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
  2038   2291                           sqlite3GlobalConfig.nLookaside);
  2039   2292   
  2040   2293     sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
  2041   2294   
  2042   2295   opendb_out:
         2296  +  sqlite3_free(zOpen);
  2043   2297     if( db ){
  2044   2298       assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
  2045   2299       sqlite3_mutex_leave(db->mutex);
  2046   2300     }
  2047   2301     rc = sqlite3_errcode(db);
  2048   2302     if( rc==SQLITE_NOMEM ){
  2049   2303       sqlite3_close(db);
................................................................................
  2079   2333   }
  2080   2334   int sqlite3_open_v2(
  2081   2335     const char *filename,   /* Database filename (UTF-8) */
  2082   2336     sqlite3 **ppDb,         /* OUT: SQLite db handle */
  2083   2337     int flags,              /* Flags */
  2084   2338     const char *zVfs        /* Name of VFS module to use */
  2085   2339   ){
  2086         -  return openDatabase(filename, ppDb, flags, zVfs);
         2340  +  return openDatabase(filename, ppDb, (unsigned int)flags, zVfs);
  2087   2341   }
  2088   2342   
  2089   2343   #ifndef SQLITE_OMIT_UTF16
  2090   2344   /*
  2091   2345   ** Open a new database handle.
  2092   2346   */
  2093   2347   int sqlite3_open16(

Changes to src/malloc.c.

   529    529       pNew = pOld;
   530    530     }else if( sqlite3GlobalConfig.bMemstat ){
   531    531       sqlite3_mutex_enter(mem0.mutex);
   532    532       sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
   533    533       nDiff = nNew - nOld;
   534    534       if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= 
   535    535             mem0.alarmThreshold-nDiff ){
   536         -      sqlite3MallocAlarm(nNew-nOld);
          536  +      sqlite3MallocAlarm(nDiff);
   537    537       }
   538    538       assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
   539    539       assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
   540    540       pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
   541    541       if( pNew==0 && mem0.alarmCallback ){
   542    542         sqlite3MallocAlarm(nBytes);
   543    543         pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
   544    544       }
   545    545       if( pNew ){
   546    546         nNew = sqlite3MallocSize(pNew);
   547         -      sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nDiff);
          547  +      sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
   548    548       }
   549    549       sqlite3_mutex_leave(mem0.mutex);
   550    550     }else{
   551    551       pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
   552    552     }
   553    553     assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */
   554    554     return pNew;

Changes to src/os_unix.c.

   208    208     unsigned char eFileLock;            /* The type of lock held on this fd */
   209    209     unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
   210    210     int lastErrno;                      /* The unix errno from last I/O error */
   211    211     void *lockingContext;               /* Locking style specific state */
   212    212     UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
   213    213     const char *zPath;                  /* Name of the file */
   214    214     unixShm *pShm;                      /* Shared memory segment information */
          215  +  int readOnlyShm;                    /* True to open shared-memory read-only */
   215    216     int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
   216    217   #if SQLITE_ENABLE_LOCKING_STYLE
   217    218     int openFlags;                      /* The flags specified at open() */
   218    219   #endif
   219    220   #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
   220    221     unsigned fsFlags;                   /* cached details from statfs() */
   221    222   #endif
................................................................................
  3469   3470       case SQLITE_FCNTL_CHUNK_SIZE: {
  3470   3471         ((unixFile*)id)->szChunk = *(int *)pArg;
  3471   3472         return SQLITE_OK;
  3472   3473       }
  3473   3474       case SQLITE_FCNTL_SIZE_HINT: {
  3474   3475         return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
  3475   3476       }
         3477  +    case SQLITE_FCNTL_READONLY_SHM: {
         3478  +      ((unixFile*)id)->readOnlyShm = (pArg!=0);
         3479  +      return SQLITE_OK;
         3480  +    }
  3476   3481   #ifndef NDEBUG
  3477   3482       /* The pager calls this method to signal that it has done
  3478   3483       ** a rollback and that the database is therefore unchanged and
  3479   3484       ** it hence it is OK for the transaction change counter to be
  3480   3485       ** unchanged.
  3481   3486       */
  3482   3487       case SQLITE_FCNTL_DB_UNCHANGED: {
................................................................................
  3771   3776     char *zFilename;           /* Name of the mmapped file */
  3772   3777     int h;                     /* Open file descriptor */
  3773   3778     int szRegion;              /* Size of shared-memory regions */
  3774   3779     int nRegion;               /* Size of array apRegion */
  3775   3780     char **apRegion;           /* Array of mapped shared-memory regions */
  3776   3781     int nRef;                  /* Number of unixShm objects pointing to this */
  3777   3782     unixShm *pFirst;           /* All unixShm objects pointing to this */
         3783  +  u8 readOnly;               /* True if this is a read-only mapping */
  3778   3784   #ifdef SQLITE_DEBUG
  3779   3785     u8 exclMask;               /* Mask of exclusive locks held */
  3780   3786     u8 sharedMask;             /* Mask of shared locks held */
  3781   3787     u8 nextShmId;              /* Next available unixShm.id value */
  3782   3788   #endif
  3783   3789   };
  3784   3790   
................................................................................
  4027   4033       pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  4028   4034       if( pShmNode->mutex==0 ){
  4029   4035         rc = SQLITE_NOMEM;
  4030   4036         goto shm_open_err;
  4031   4037       }
  4032   4038   
  4033   4039       if( pInode->bProcessLock==0 ){
  4034         -      pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
  4035         -                               (sStat.st_mode & 0777));
         4040  +      int flags = (pDbFd->readOnlyShm ? O_RDONLY : O_RDWR|O_CREAT);
         4041  +      pShmNode->h = robust_open(zShmFilename, flags, (sStat.st_mode & 0777));
  4036   4042         if( pShmNode->h<0 ){
  4037   4043           rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
  4038   4044           goto shm_open_err;
  4039   4045         }
         4046  +      pShmNode->readOnly = pDbFd->readOnlyShm;
  4040   4047     
  4041   4048         /* Check to see if another process is holding the dead-man switch.
  4042         -      ** If not, truncate the file to zero length. 
  4043         -      */
  4044         -      rc = SQLITE_OK;
  4045         -      if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
  4046         -        if( robust_ftruncate(pShmNode->h, 0) ){
  4047         -          rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
  4048         -        }
  4049         -      }
  4050         -      if( rc==SQLITE_OK ){
  4051         -        rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
  4052         -      }
  4053         -      if( rc ) goto shm_open_err;
  4054         -    }
         4049  +      ** If not, zero the first few bytes of the shared-memory file to make
         4050  +      ** sure it is not mistaken for valid by code in wal.c. Except, if this 
         4051  +      ** is a read-only connection to the shared-memory then it is not possible
         4052  +      ** to check check if another process is holding a read-lock on the DMS
         4053  +      ** byte, as we cannot attempt a write-lock via a read-only file 
         4054  +      ** descriptor. So in this case, we just assume the shared-memory 
         4055  +      ** contents are Ok and proceed.  */
         4056  +      if( pShmNode->readOnly==0 ){
         4057  +        rc = SQLITE_OK;
         4058  +        if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
         4059  +          if( pDbFd->readOnlyShm ){
         4060  +            rc = SQLITE_IOERR_SHMOPEN;
         4061  +          }else if( 4!=osWrite(pShmNode->h, "\00\00\00\00", 4) ){
         4062  +            rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
         4063  +          }
         4064  +        }
         4065  +        if( rc==SQLITE_OK ){
         4066  +          rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
         4067  +        }
         4068  +        if( rc ) goto shm_open_err;
         4069  +      }
         4070  +    }
         4071  +  }
         4072  +
         4073  +  /* If the unixShmNode is read-only, but SQLITE_FCNTL_READONLY_SHM has not
         4074  +  ** been set for file-descriptor pDbFd, return an error. The wal.c module
         4075  +  ** will then call this function again with SQLITE_FCNTL_READONLY_SHM set.
         4076  +  */
         4077  +  else if( pShmNode->readOnly && !pDbFd->readOnlyShm ){
         4078  +    rc = SQLITE_IOERR_SHMOPEN;
         4079  +    goto shm_open_err;
  4055   4080     }
  4056   4081   
  4057   4082     /* Make the new connection a child of the unixShmNode */
  4058   4083     p->pShmNode = pShmNode;
  4059   4084   #ifdef SQLITE_DEBUG
  4060   4085     p->id = pShmNode->nextShmId++;
  4061   4086   #endif
................................................................................
  4170   4195         rc = SQLITE_IOERR_NOMEM;
  4171   4196         goto shmpage_out;
  4172   4197       }
  4173   4198       pShmNode->apRegion = apNew;
  4174   4199       while(pShmNode->nRegion<=iRegion){
  4175   4200         void *pMem;
  4176   4201         if( pShmNode->h>=0 ){
  4177         -        pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE, 
         4202  +        pMem = mmap(0, szRegion, PROT_READ|(!pShmNode->readOnly?PROT_WRITE:0), 
  4178   4203               MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
  4179   4204           );
  4180   4205           if( pMem==MAP_FAILED ){
  4181   4206             rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
  4182   4207             goto shmpage_out;
  4183   4208           }
  4184   4209         }else{

Changes to src/os_win.c.

  2460   2460     return SQLITE_OK;
  2461   2461   #endif
  2462   2462   
  2463   2463   #if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
  2464   2464     int nByte;
  2465   2465     void *zConverted;
  2466   2466     char *zOut;
         2467  +
         2468  +  /* If this path name begins with "/X:", where "X" is any alphabetic
         2469  +  ** character, discard the initial "/" from the pathname.
         2470  +  */
         2471  +  if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
         2472  +    zRelative++;
         2473  +  }
  2467   2474   
  2468   2475     /* It's odd to simulate an io-error here, but really this is just
  2469   2476     ** using the io-error infrastructure to test that SQLite handles this
  2470   2477     ** function failing. This function could fail if, for example, the
  2471   2478     ** current working directory has been unlinked.
  2472   2479     */
  2473   2480     SimulateIOError( return SQLITE_ERROR );

Changes to src/pager.c.

   616    616     u8 noSync;                  /* Do not sync the journal if true */
   617    617     u8 fullSync;                /* Do extra syncs of the journal for robustness */
   618    618     u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
   619    619     u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
   620    620     u8 tempFile;                /* zFilename is a temporary file */
   621    621     u8 readOnly;                /* True for a read-only database */
   622    622     u8 memDb;                   /* True to inhibit all file I/O */
          623  +  u8 readOnlyShm;             /* True if read-only shm access is Ok */
   623    624   
   624    625     /**************************************************************************
   625    626     ** The following block contains those class members that change during
   626    627     ** routine opertion.  Class members not in this block are either fixed
   627    628     ** when the pager is first created or else only change when there is a
   628    629     ** significant mode change (such as changing the page_size, locking_mode,
   629    630     ** or the journal_mode).  From another view, these class members describe
................................................................................
  3013   3014   ** makes a snapshot of the database at the current point in time and preserves
  3014   3015   ** that snapshot for use by the reader in spite of concurrently changes by
  3015   3016   ** other writers or checkpointers.
  3016   3017   */
  3017   3018   static int pagerBeginReadTransaction(Pager *pPager){
  3018   3019     int rc;                         /* Return code */
  3019   3020     int changed = 0;                /* True if cache must be reset */
         3021  +  Wal *pWal = pPager->pWal;
  3020   3022   
  3021   3023     assert( pagerUseWal(pPager) );
  3022   3024     assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
  3023   3025   
  3024   3026     /* sqlite3WalEndReadTransaction() was not called for the previous
  3025   3027     ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
  3026   3028     ** are in locking_mode=NORMAL and EndRead() was previously called,
  3027   3029     ** the duplicate call is harmless.
  3028   3030     */
  3029         -  sqlite3WalEndReadTransaction(pPager->pWal);
         3031  +  sqlite3WalEndReadTransaction(pWal);
  3030   3032   
  3031         -  rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
         3033  +  rc = sqlite3WalBeginReadTransaction(pWal, pPager->readOnlyShm, &changed);
  3032   3034     if( rc!=SQLITE_OK || changed ){
  3033   3035       pager_reset(pPager);
  3034   3036     }
  3035   3037   
  3036   3038     return rc;
  3037   3039   }
  3038   3040   #endif
................................................................................
  4295   4297     int journalFileSize;     /* Bytes to allocate for each journal fd */
  4296   4298     char *zPathname = 0;     /* Full path to database file */
  4297   4299     int nPathname = 0;       /* Number of bytes in zPathname */
  4298   4300     int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
  4299   4301     int noReadlock = (flags & PAGER_NO_READLOCK)!=0;  /* True to omit read-lock */
  4300   4302     int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
  4301   4303     u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */
         4304  +  const char *zUri = 0;    /* URI args to copy */
         4305  +  int nUri = 0;            /* Number of bytes of URI args at *zUri */
  4302   4306   
  4303   4307     /* Figure out how much space is required for each journal file-handle
  4304   4308     ** (there are two of them, the main journal and the sub-journal). This
  4305   4309     ** is the maximum space required for an in-memory journal file handle 
  4306   4310     ** and a regular journal file-handle. Note that a "regular journal-handle"
  4307   4311     ** may be a wrapper capable of caching the first portion of the journal
  4308   4312     ** file in memory to implement the atomic-write optimization (see 
................................................................................
  4325   4329   #endif
  4326   4330   
  4327   4331     /* Compute and store the full pathname in an allocated buffer pointed
  4328   4332     ** to by zPathname, length nPathname. Or, if this is a temporary file,
  4329   4333     ** leave both nPathname and zPathname set to 0.
  4330   4334     */
  4331   4335     if( zFilename && zFilename[0] ){
         4336  +    const char *z;
  4332   4337       nPathname = pVfs->mxPathname+1;
  4333   4338       zPathname = sqlite3Malloc(nPathname*2);
  4334   4339       if( zPathname==0 ){
  4335   4340         return SQLITE_NOMEM;
  4336   4341       }
  4337   4342       zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
  4338   4343       rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
  4339   4344       nPathname = sqlite3Strlen30(zPathname);
         4345  +    z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
         4346  +    while( *z ){
         4347  +      z += sqlite3Strlen30(z)+1;
         4348  +      z += sqlite3Strlen30(z)+1;
         4349  +    }
         4350  +    nUri = &z[1] - zUri;
  4340   4351       if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
  4341   4352         /* This branch is taken when the journal path required by
  4342   4353         ** the database being opened will be more than pVfs->mxPathname
  4343   4354         ** bytes in length. This means the database cannot be opened,
  4344   4355         ** as it will not be possible to open the journal file or even
  4345   4356         ** check for a hot-journal before reading.
  4346   4357         */
................................................................................
  4365   4376     **     Journal file name               (nPathname+8+1 bytes)
  4366   4377     */
  4367   4378     pPtr = (u8 *)sqlite3MallocZero(
  4368   4379       ROUND8(sizeof(*pPager)) +      /* Pager structure */
  4369   4380       ROUND8(pcacheSize) +           /* PCache object */
  4370   4381       ROUND8(pVfs->szOsFile) +       /* The main db file */
  4371   4382       journalFileSize * 2 +          /* The two journal files */ 
  4372         -    nPathname + 1 +                /* zFilename */
         4383  +    nPathname + 1 + nUri +         /* zFilename */
  4373   4384       nPathname + 8 + 1              /* zJournal */
  4374   4385   #ifndef SQLITE_OMIT_WAL
  4375   4386       + nPathname + 4 + 1              /* zWal */
  4376   4387   #endif
  4377   4388     );
  4378   4389     assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
  4379   4390     if( !pPtr ){
................................................................................
  4387   4398     pPager->jfd =  (sqlite3_file*)(pPtr += journalFileSize);
  4388   4399     pPager->zFilename =    (char*)(pPtr += journalFileSize);
  4389   4400     assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
  4390   4401   
  4391   4402     /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
  4392   4403     if( zPathname ){
  4393   4404       assert( nPathname>0 );
  4394         -    pPager->zJournal =   (char*)(pPtr += nPathname + 1);
         4405  +    pPager->zJournal =   (char*)(pPtr += nPathname + 1 + nUri);
  4395   4406       memcpy(pPager->zFilename, zPathname, nPathname);
         4407  +    memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
  4396   4408       memcpy(pPager->zJournal, zPathname, nPathname);
  4397   4409       memcpy(&pPager->zJournal[nPathname], "-journal", 8);
  4398   4410   #ifndef SQLITE_OMIT_WAL
  4399   4411       pPager->zWal = &pPager->zJournal[nPathname+8+1];
  4400   4412       memcpy(pPager->zWal, zPathname, nPathname);
  4401   4413       memcpy(&pPager->zWal[nPathname], "-wal", 4);
  4402   4414   #endif
  4403   4415       sqlite3_free(zPathname);
  4404   4416     }
  4405   4417     pPager->pVfs = pVfs;
  4406   4418     pPager->vfsFlags = vfsFlags;
         4419  +  pPager->readOnlyShm = (flags & PAGER_READONLYSHM)!=0;
  4407   4420   
  4408   4421     /* Open the pager file.
  4409   4422     */
  4410   4423     if( zFilename && zFilename[0] ){
  4411   4424       int fout = 0;                    /* VFS flags returned by xOpen() */
  4412   4425       rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
  4413   4426       assert( !memDb );

Changes to src/pager.h.

    56     56   ** Allowed values for the flags parameter to sqlite3PagerOpen().
    57     57   **
    58     58   ** NOTE: These values must match the corresponding BTREE_ values in btree.h.
    59     59   */
    60     60   #define PAGER_OMIT_JOURNAL  0x0001    /* Do not use a rollback journal */
    61     61   #define PAGER_NO_READLOCK   0x0002    /* Omit readlocks on readonly files */
    62     62   #define PAGER_MEMORY        0x0004    /* In-memory database */
           63  +#define PAGER_READONLYSHM   0x0020    /* Read-only SHM access is acceptable */
    63     64   
    64     65   /*
    65     66   ** Valid values for the second argument to sqlite3PagerLockingMode().
    66     67   */
    67     68   #define PAGER_LOCKINGMODE_QUERY      -1
    68     69   #define PAGER_LOCKINGMODE_NORMAL      0
    69     70   #define PAGER_LOCKINGMODE_EXCLUSIVE   1

Changes to src/sqlite.h.in.

   450    450   #define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
   451    451   #define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
   452    452   #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
   453    453   #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
   454    454   #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
   455    455   #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
   456    456   
          457  +#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
          458  +#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
          459  +
   457    460   /*
   458    461   ** CAPI3REF: Flags For File Open Operations
   459    462   **
   460    463   ** These bit values are intended for use in the
   461    464   ** 3rd parameter to the [sqlite3_open_v2()] interface and
   462    465   ** in the 4th parameter to the xOpen method of the
   463    466   ** [sqlite3_vfs] object.
................................................................................
   476    479   #define SQLITE_OPEN_SUBJOURNAL       0x00002000  /* VFS only */
   477    480   #define SQLITE_OPEN_MASTER_JOURNAL   0x00004000  /* VFS only */
   478    481   #define SQLITE_OPEN_NOMUTEX          0x00008000  /* Ok for sqlite3_open_v2() */
   479    482   #define SQLITE_OPEN_FULLMUTEX        0x00010000  /* Ok for sqlite3_open_v2() */
   480    483   #define SQLITE_OPEN_SHAREDCACHE      0x00020000  /* Ok for sqlite3_open_v2() */
   481    484   #define SQLITE_OPEN_PRIVATECACHE     0x00040000  /* Ok for sqlite3_open_v2() */
   482    485   #define SQLITE_OPEN_WAL              0x00080000  /* VFS only */
          486  +#define SQLITE_OPEN_URI              0x00100000  /* Ok for sqlite3_open_v2() */
   483    487   
   484    488   /* Reserved:                         0x00F00000 */
   485    489   
   486    490   /*
   487    491   ** CAPI3REF: Device Characteristics
   488    492   **
   489    493   ** The xDeviceCharacteristics method of the [sqlite3_io_methods]
................................................................................
   728    732   ** when the database connection has [PRAGMA synchronous] set to OFF.)^
   729    733   ** Some specialized VFSes need this signal in order to operate correctly
   730    734   ** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
   731    735   ** VFSes do not need this signal and should silently ignore this opcode.
   732    736   ** Applications should not call [sqlite3_file_control()] with this
   733    737   ** opcode as doing so may disrupt the operation of the specialized VFSes
   734    738   ** that do require it.  
          739  +**
          740  +** The [SQLITE_FCNTL_READONLY_SHM] may be generated internally by SQLite if
          741  +** the "readonly_shm=1" URI option is specified when the database is opened.
          742  +** The fourth argument passed to the VFS xFileControl methods is a pointer
          743  +** to a variable of type "int" containing the value 1 or 0. If the variable
          744  +** contains the value 1, then this indicates to the VFS that a read-only
          745  +** mapping of the shared-memory region is acceptable. If it is set to 0, then
          746  +** this indicates that a read-write mapping is required (as normal). If
          747  +** a read-only mapping is returned, then the VFS may also return read-only
          748  +** mappings for any subsequent requests via the same file-descriptor -
          749  +** regardless of the value most recently configured using
          750  +** SQLITE_FCNTL_READONLY_SHM.
          751  +**
          752  +** In practice, if "readonly_shm=1" is specified and the first attempt to
          753  +** map a shared-memory region fails, then this file-control is invoked with
          754  +** the argument variable set to 1 and a second attempt to map the shared-memory
          755  +** region is made. If this mapping succeeds, then the connection continues
          756  +** with the read-only mapping. Otherwise, if it fails, SQLITE_CANTOPEN is
          757  +** returned to the caller. Whether or not the second (read-only) mapping
          758  +** attempt succeeds, the file-control is invoked again with the argument
          759  +** variable set to 0.
   735    760   */
   736    761   #define SQLITE_FCNTL_LOCKSTATE        1
   737    762   #define SQLITE_GET_LOCKPROXYFILE      2
   738    763   #define SQLITE_SET_LOCKPROXYFILE      3
   739    764   #define SQLITE_LAST_ERRNO             4
   740    765   #define SQLITE_FCNTL_SIZE_HINT        5
   741    766   #define SQLITE_FCNTL_CHUNK_SIZE       6
   742    767   #define SQLITE_FCNTL_FILE_POINTER     7
   743    768   #define SQLITE_FCNTL_SYNC_OMITTED     8
          769  +#define SQLITE_FCNTL_READONLY_SHM     9
   744    770   
   745    771   
   746    772   /*
   747    773   ** CAPI3REF: Mutex Handle
   748    774   **
   749    775   ** The mutex module within SQLite defines [sqlite3_mutex] to be an
   750    776   ** abstract type for a mutex object.  The SQLite core never looks
................................................................................
   753    779   **
   754    780   ** Mutexes are created using [sqlite3_mutex_alloc()].
   755    781   */
   756    782   typedef struct sqlite3_mutex sqlite3_mutex;
   757    783   
   758    784   /*
   759    785   ** CAPI3REF: OS Interface Object
          786  +** KEYWORDS: VFS VFSes
   760    787   **
   761    788   ** An instance of the sqlite3_vfs object defines the interface between
   762    789   ** the SQLite core and the underlying operating system.  The "vfs"
   763    790   ** in the name of the object stands for "virtual file system".
   764    791   **
   765    792   ** The value of the iVersion field is initially 1 but may be larger in
   766    793   ** future versions of SQLite.  Additional fields may be appended to this
................................................................................
  1423   1450   ** [extended result code].  ^The third parameter passed to the logger is
  1424   1451   ** log message after formatting via [sqlite3_snprintf()].
  1425   1452   ** The SQLite logging interface is not reentrant; the logger function
  1426   1453   ** supplied by the application must not invoke any SQLite interface.
  1427   1454   ** In a multi-threaded application, the application-defined logger
  1428   1455   ** function must be threadsafe. </dd>
  1429   1456   **
         1457  +** <dt>SQLITE_CONFIG_URI
         1458  +** <dd> This option takes a single argument of type int. If non-zero, then
         1459  +** URI handling is globally enabled. If the parameter is zero, then URI handling
         1460  +** is globally disabled. If URI handling is globally enabled, all filenames
         1461  +** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
         1462  +** specified as part of [ATTACH] commands are interpreted as URIs, regardless
         1463  +** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
         1464  +** connection is opened. If it is globally disabled, filenames are
         1465  +** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
         1466  +** database connection is opened. By default, URI handling is globally
         1467  +** disabled. The default value may be changed by compiling with the
         1468  +** [SQLITE_USE_URI] symbol defined.
  1430   1469   ** </dl>
  1431   1470   */
  1432   1471   #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
  1433   1472   #define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
  1434   1473   #define SQLITE_CONFIG_SERIALIZED    3  /* nil */
  1435   1474   #define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
  1436   1475   #define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
................................................................................
  1441   1480   #define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
  1442   1481   #define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
  1443   1482   /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ 
  1444   1483   #define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
  1445   1484   #define SQLITE_CONFIG_PCACHE       14  /* sqlite3_pcache_methods* */
  1446   1485   #define SQLITE_CONFIG_GETPCACHE    15  /* sqlite3_pcache_methods* */
  1447   1486   #define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
         1487  +#define SQLITE_CONFIG_URI          17  /* int */
  1448   1488   
  1449   1489   /*
  1450   1490   ** CAPI3REF: Database Connection Configuration Options
  1451   1491   **
  1452   1492   ** These constants are the available integer configuration options that
  1453   1493   ** can be passed as the second argument to the [sqlite3_db_config()] interface.
  1454   1494   **
................................................................................
  2320   2360   **
  2321   2361   */
  2322   2362   void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
  2323   2363   
  2324   2364   /*
  2325   2365   ** CAPI3REF: Opening A New Database Connection
  2326   2366   **
  2327         -** ^These routines open an SQLite database file whose name is given by the
         2367  +** ^These routines open an SQLite database file as specified by the 
  2328   2368   ** filename argument. ^The filename argument is interpreted as UTF-8 for
  2329   2369   ** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
  2330   2370   ** order for sqlite3_open16(). ^(A [database connection] handle is usually
  2331   2371   ** returned in *ppDb, even if an error occurs.  The only exception is that
  2332   2372   ** if SQLite is unable to allocate memory to hold the [sqlite3] object,
  2333   2373   ** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
  2334   2374   ** object.)^ ^(If the database is opened (and/or created) successfully, then
................................................................................
  2382   2422   ** in the serialized [threading mode] unless single-thread was
  2383   2423   ** previously selected at compile-time or start-time.
  2384   2424   ** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
  2385   2425   ** eligible to use [shared cache mode], regardless of whether or not shared
  2386   2426   ** cache is enabled using [sqlite3_enable_shared_cache()].  ^The
  2387   2427   ** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
  2388   2428   ** participate in [shared cache mode] even if it is enabled.
         2429  +**
         2430  +** ^The fourth parameter to sqlite3_open_v2() is the name of the
         2431  +** [sqlite3_vfs] object that defines the operating system interface that
         2432  +** the new database connection should use.  ^If the fourth parameter is
         2433  +** a NULL pointer then the default [sqlite3_vfs] object is used.
  2389   2434   **
  2390   2435   ** ^If the filename is ":memory:", then a private, temporary in-memory database
  2391   2436   ** is created for the connection.  ^This in-memory database will vanish when
  2392   2437   ** the database connection is closed.  Future versions of SQLite might
  2393   2438   ** make use of additional special filenames that begin with the ":" character.
  2394   2439   ** It is recommended that when a database filename actually does begin with
  2395   2440   ** a ":" character you should prefix the filename with a pathname such as
  2396   2441   ** "./" to avoid ambiguity.
  2397   2442   **
  2398   2443   ** ^If the filename is an empty string, then a private, temporary
  2399   2444   ** on-disk database will be created.  ^This private database will be
  2400   2445   ** automatically deleted as soon as the database connection is closed.
  2401   2446   **
  2402         -** ^The fourth parameter to sqlite3_open_v2() is the name of the
  2403         -** [sqlite3_vfs] object that defines the operating system interface that
  2404         -** the new database connection should use.  ^If the fourth parameter is
  2405         -** a NULL pointer then the default [sqlite3_vfs] object is used.
         2447  +** ^If URI filename interpretation is enabled, and the filename argument
         2448  +** begins with "file:", then the filename is interpreted as a URI. ^URI
         2449  +** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
         2450  +** is set in the fourth argument to sqlite3_open_v2(), or if it has
         2451  +** been enabled globally using the [SQLITE_CONFIG_URI] option with the
         2452  +** [sqlite3_config()] method. 
         2453  +**
         2454  +** URI filenames are parsed according to RFC 1738. If the URI contains an
         2455  +** 'authority', then it must be either an empty string or the string 
         2456  +** "localhost". ^If the authority is not an empty string or "localhost", an 
         2457  +** error is returned to the caller. ^The 'fragment' component of a URI, if 
         2458  +** present, is always ignored.
         2459  +**
         2460  +** ^SQLite uses the 'path' component of the URI as the path to the database file
         2461  +** to open. ^If the path begins with a '/' character, then it is interpreted as
         2462  +** an absolute path. ^If it does not begin with a '/', it is interpreted as a 
         2463  +** relative path. ^On windows, the first component of an absolute path 
         2464  +** is a drive specification (e.g. "C:").
         2465  +**
         2466  +** The query component of a URI may contain parameters that are interpreted
         2467  +** either by SQLite itself, or by a [sqlite3_vfs | custom VFS implementation].
         2468  +** SQLite interprets the following four query parameters:
         2469  +**
         2470  +** <ul>
         2471  +**   <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
         2472  +**     a VFS object that provides the operating system interface that should
         2473  +**     be used to access the database file on disk. ^If this option is set to
         2474  +**     an empty string the default VFS object is used. ^Specifying an unknown
         2475  +**     VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
         2476  +**     present, then the VFS specified by the option takes precedence over
         2477  +**     the value passed as the fourth parameter to sqlite3_open_v2().
         2478  +**
         2479  +**   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
         2480  +**     "rwc". Attempting to set it to any other value is an error)^. 
         2481  +**     ^If "ro" is specified, then the database is opened for read-only 
         2482  +**     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the 
         2483  +**     third argument to sqlite3_prepare_v2(). ^If the mode option is set to 
         2484  +**     "rw", then the database is opened for read-write (but not create) 
         2485  +**     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had 
         2486  +**     been set. ^Value "rwc" is equivalent to setting both 
         2487  +**     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is 
         2488  +**     used, it is an error to specify a value for the mode parameter that is 
         2489  +**     less restrictive than that specified by the flags passed as the third 
         2490  +**     parameter.
         2491  +**
         2492  +**   <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
         2493  +**     "private". ^Setting it to "shared" is equivalent to setting the
         2494  +**     SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
         2495  +**     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
         2496  +**     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
         2497  +**     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
         2498  +**     a URI filename, its value overrides any behaviour requested by setting
         2499  +**     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
         2500  +**
         2501  +**   <li> <b>readonly_shm</b>: ^The readonly_shm parameter may be set to 
         2502  +**     either "1" or "0". Setting it to "1" indicates that if the database
         2503  +**     is in WAL mode and read-write access to the associated shared 
         2504  +**     memory region cannot be obtained, then an attempt should be made to open
         2505  +**     the shared-memory in read-only mode instead. If there exist one or
         2506  +**     more other database clients that have read-write connections to the
         2507  +**     database shared-memory, then a read-only shared-memory connection works 
         2508  +**     fine. However, if there exist no clients with read-write connections 
         2509  +**     to the shared-memory and the most recent such crashed or was interrupted
         2510  +**     by a power failure, then it is possible for a database client using a
         2511  +**     read-only connection to return incorrect data, incorrectly report 
         2512  +**     database corruption, or return an SQLITE_READONLY error. Or if the
         2513  +**     most recent read-write connection shut down cleanly, it may not be
         2514  +**     possible to open the shared-memory in read-only mode at all, and SQLite
         2515  +**     will return SQLITE_CANTOPEN.
         2516  +** </ul>
         2517  +**
         2518  +** ^Specifying an unknown parameter in the query component of a URI is not an
         2519  +** error.
         2520  +**
         2521  +** URI filename examples:
         2522  +**
         2523  +** <table border="1" align=center cellpadding=5>
         2524  +** <tr><th> URI filenames <th> Results
         2525  +** <tr><td> file:data.db <td> 
         2526  +**          Open the file "data.db" in the current directory.
         2527  +** <tr><td> file:/home/fred/data.db<br>
         2528  +**          file:///home/fred/data.db <br> 
         2529  +**          file://localhost/home/fred/data.db <br> <td> 
         2530  +**          Open the database file "/home/fred/data.db".
         2531  +** <tr><td> file://darkstar/home/fred/data.db <td> 
         2532  +**          An error. "darkstar" is not a recognized authority.
         2533  +** <tr><td style="white-space:nowrap"> 
         2534  +**          file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
         2535  +**     <td> Windows only: Open the file "data.db" on fred's desktop on drive
         2536  +**          C:. Note that the %20 escaping in this example is not strictly 
         2537  +**          necessary - space characters can be used literally
         2538  +**          in URI filenames.
         2539  +** <tr><td> file:data.db?mode=ro&cache=private <td> 
         2540  +**          Open file "data.db" in the current directory for read-only access.
         2541  +**          Regardless of whether or not shared-cache mode is enabled by
         2542  +**          default, use a private cache.
         2543  +** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
         2544  +**          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
         2545  +** <tr><td> file:data.db?mode=readonly <td> 
         2546  +**          An error. "readonly" is not a valid option for the "mode" parameter.
         2547  +** </table>
         2548  +**
         2549  +** ^URI hexadecimal escape sequences (%HH) are supported within the path and
         2550  +** query components of a URI. A hexadecimal escape sequence consists of a
         2551  +** percent sign - "%" - followed by exactly two hexadecimal digits 
         2552  +** specifying an octet value. ^Before the path or query components of a
         2553  +** URI filename are interpreted, they are encoded using UTF-8 and all 
         2554  +** hexadecimal escape sequences replaced by a single byte containing the
         2555  +** corresponding octet. If this process generates an invalid UTF-8 encoding,
         2556  +** the results are undefined.
  2406   2557   **
  2407   2558   ** <b>Note to Windows users:</b>  The encoding used for the filename argument
  2408   2559   ** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
  2409   2560   ** codepage is currently defined.  Filenames containing international
  2410   2561   ** characters must be converted to UTF-8 prior to passing them into
  2411   2562   ** sqlite3_open() or sqlite3_open_v2().
  2412   2563   */
................................................................................
  4607   4758     int (*xSync)(sqlite3_vtab *pVTab);
  4608   4759     int (*xCommit)(sqlite3_vtab *pVTab);
  4609   4760     int (*xRollback)(sqlite3_vtab *pVTab);
  4610   4761     int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
  4611   4762                          void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
  4612   4763                          void **ppArg);
  4613   4764     int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
  4614         -  /* The methods above are in version 0 of the sqlite_module object. Those 
  4615         -  ** below are for version 1 and greater. */
         4765  +  /* The methods above are in version 1 of the sqlite_module object. Those 
         4766  +  ** below are for version 2 and greater. */
  4616   4767     int (*xSavepoint)(sqlite3_vtab *pVTab, int);
  4617   4768     int (*xRelease)(sqlite3_vtab *pVTab, int);
  4618   4769     int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
  4619   4770   };
  4620   4771   
  4621   4772   /*
  4622   4773   ** CAPI3REF: Virtual Table Indexing Information
................................................................................
  6421   6572   ** CAPI3REF: Virtual Table Configuration Options
  6422   6573   **
  6423   6574   ** These macros define the various options to the
  6424   6575   ** [sqlite3_vtab_config()] interface that [virtual table] implementations
  6425   6576   ** can use to customize and optimize their behavior.
  6426   6577   **
  6427   6578   ** <dl>
  6428         -**   <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
  6429         -**   <dd>If the second argument to [sqlite3_vtab_config()] is
  6430         -**       SQLITE_VTAB_CONSTRAINT_SUPPORT, then SQLite expects this function to
  6431         -**       have been called with three arguments, the third of which being of
  6432         -**       type 'int'. If the third argument is zero, then the virtual table
  6433         -**       is indicating that it does not support constraints. In this case if
  6434         -**       a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], the entire
  6435         -**       statement is rolled back as if [ON CONFLICT | OR ABORT] had been
  6436         -**       specified as part of the users SQL statement, regardless of the actual
  6437         -**       ON CONFLICT mode specified.
         6579  +** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
         6580  +** <dd>Calls of the form
         6581  +** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
         6582  +** where X is an integer.  If X is zero, then the [virtual table] whose
         6583  +** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
         6584  +** support constraints.  In this configuration (which is the default) if
         6585  +** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
         6586  +** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
         6587  +** specified as part of the users SQL statement, regardless of the actual
         6588  +** ON CONFLICT mode specified.
  6438   6589   **
  6439         -**       If the third argument passed is non-zero, then the virtual table
  6440         -**       implementation must guarantee that if [xUpdate] returns 
  6441         -**       [SQLITE_CONSTRAINT], it does so before any modifications to internal
  6442         -**       or persistent data structures have been made. If the [ON CONFLICT]
  6443         -**       mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite is able to roll back
  6444         -**       a statement or database transaction, and abandon or continue processing
  6445         -**       the current SQL statement as appropriate. If the ON CONFLICT mode is
  6446         -**       REPLACE and the [xUpdate] method returns [SQLITE_CONSTRAINT], SQLite
  6447         -**       handles this as if the ON CONFLICT mode had been ABORT.
         6590  +** If X is non-zero, then the virtual table implementation guarantees
         6591  +** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
         6592  +** any modifications to internal or persistent data structures have been made.
         6593  +** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite 
         6594  +** is able to roll back a statement or database transaction, and abandon
         6595  +** or continue processing the current SQL statement as appropriate. 
         6596  +** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
         6597  +** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
         6598  +** had been ABORT.
  6448   6599   **
  6449         -**       Virtual table implementations that are required to handle OR REPLACE
  6450         -**       must do so within the xUpdate method. If a call to the 
  6451         -**       [sqlite3_vtab_on_conflict()] function indicates that the current ON 
  6452         -**       CONFLICT policy is REPLACE, the virtual table implementation should 
  6453         -**       silently replace the appropriate rows within the xUpdate callback and
  6454         -**       return SQLITE_OK. Or, if this is not possible, it may return
  6455         -**       SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT 
  6456         -**       constraint handling.
         6600  +** Virtual table implementations that are required to handle OR REPLACE
         6601  +** must do so within the [xUpdate] method. If a call to the 
         6602  +** [sqlite3_vtab_on_conflict()] function indicates that the current ON 
         6603  +** CONFLICT policy is REPLACE, the virtual table implementation should 
         6604  +** silently replace the appropriate rows within the xUpdate callback and
         6605  +** return SQLITE_OK. Or, if this is not possible, it may return
         6606  +** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT 
         6607  +** constraint handling.
  6457   6608   ** </dl>
  6458         -** 
  6459   6609   */
  6460   6610   #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
  6461   6611   
  6462   6612   /*
  6463   6613   ** CAPI3REF: Determine The Virtual Table Conflict Policy
  6464   6614   **
  6465   6615   ** This function may only be called from within a call to the [xUpdate] method

Changes to src/sqliteInt.h.

   799    799   ** consistently.
   800    800   */
   801    801   struct sqlite3 {
   802    802     sqlite3_vfs *pVfs;            /* OS Interface */
   803    803     int nDb;                      /* Number of backends currently in use */
   804    804     Db *aDb;                      /* All backends */
   805    805     int flags;                    /* Miscellaneous flags. See below */
   806         -  int openFlags;                /* Flags passed to sqlite3_vfs.xOpen() */
          806  +  unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
   807    807     int errCode;                  /* Most recent error code (SQLITE_*) */
   808    808     int errMask;                  /* & result codes with this before returning */
   809    809     u8 autoCommit;                /* The auto-commit flag. */
   810    810     u8 temp_store;                /* 1: file 2: memory 0: default */
   811    811     u8 mallocFailed;              /* True if we have seen a malloc failure */
   812    812     u8 dfltLockMode;              /* Default locking-mode for attached dbs */
   813    813     signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
................................................................................
  2419   2419   **
  2420   2420   ** This structure also contains some state information.
  2421   2421   */
  2422   2422   struct Sqlite3Config {
  2423   2423     int bMemstat;                     /* True to enable memory status */
  2424   2424     int bCoreMutex;                   /* True to enable core mutexing */
  2425   2425     int bFullMutex;                   /* True to enable full mutexing */
         2426  +  int bOpenUri;                     /* True to interpret filenames as URIs */
  2426   2427     int mxStrlen;                     /* Maximum string length */
  2427   2428     int szLookaside;                  /* Default lookaside buffer size */
  2428   2429     int nLookaside;                   /* Default lookaside buffer count */
  2429   2430     sqlite3_mem_methods m;            /* Low-level memory allocation interface */
  2430   2431     sqlite3_mutex_methods mutex;      /* Low-level mutex interface */
  2431   2432     sqlite3_pcache_methods pcache;    /* Low-level page-cache interface */
  2432   2433     void *pHeap;                      /* Heap storage space */
................................................................................
  2668   2669   void sqlite3AddNotNull(Parse*, int);
  2669   2670   void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
  2670   2671   void sqlite3AddCheckConstraint(Parse*, Expr*);
  2671   2672   void sqlite3AddColumnType(Parse*,Token*);
  2672   2673   void sqlite3AddDefaultValue(Parse*,ExprSpan*);
  2673   2674   void sqlite3AddCollateType(Parse*, Token*);
  2674   2675   void sqlite3EndTable(Parse*,Token*,Token*,Select*);
         2676  +int sqlite3ParseUri(const char*,const char*,unsigned int*,int*,
         2677  +                    sqlite3_vfs**,char**,char **);
  2675   2678   
  2676   2679   Bitvec *sqlite3BitvecCreate(u32);
  2677   2680   int sqlite3BitvecTest(Bitvec*, u32);
  2678   2681   int sqlite3BitvecSet(Bitvec*, u32);
  2679   2682   void sqlite3BitvecClear(Bitvec*, u32, void*);
  2680   2683   void sqlite3BitvecDestroy(Bitvec*);
  2681   2684   u32 sqlite3BitvecSize(Bitvec*);
................................................................................
  2918   2921   void sqlite3TableAffinityStr(Vdbe *, Table *);
  2919   2922   char sqlite3CompareAffinity(Expr *pExpr, char aff2);
  2920   2923   int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
  2921   2924   char sqlite3ExprAffinity(Expr *pExpr);
  2922   2925   int sqlite3Atoi64(const char*, i64*, int, u8);
  2923   2926   void sqlite3Error(sqlite3*, int, const char*,...);
  2924   2927   void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
         2928  +u8 sqlite3HexToInt(int h);
  2925   2929   int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
  2926   2930   const char *sqlite3ErrStr(int);
  2927   2931   int sqlite3ReadSchema(Parse *pParse);
  2928   2932   CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
  2929   2933   CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
  2930   2934   CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
  2931   2935   Expr *sqlite3ExprSetColl(Expr*, CollSeq*);

Changes to src/test1.c.

   159    159       case SQLITE_IOERR_DELETE:        zName = "SQLITE_IOERR_DELETE";      break;
   160    160       case SQLITE_IOERR_BLOCKED:       zName = "SQLITE_IOERR_BLOCKED";     break;
   161    161       case SQLITE_IOERR_NOMEM:         zName = "SQLITE_IOERR_NOMEM";       break;
   162    162       case SQLITE_IOERR_ACCESS:        zName = "SQLITE_IOERR_ACCESS";      break;
   163    163       case SQLITE_IOERR_CHECKRESERVEDLOCK:
   164    164                                  zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
   165    165       case SQLITE_IOERR_LOCK:          zName = "SQLITE_IOERR_LOCK";        break;
          166  +
          167  +    case SQLITE_READONLY_RECOVERY:   zName = "SQLITE_READONLY_RECOVERY"; break;
          168  +    case SQLITE_READONLY_CANTLOCK:   zName = "SQLITE_READONLY_CANTLOCK"; break;
   166    169       default:                         zName = "SQLITE_Unknown";           break;
   167    170     }
   168    171     return zName;
   169    172   }
   170    173   #define t1ErrorName sqlite3TestErrorName
   171    174   
   172    175   /*
................................................................................
  3858   3861     zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
  3859   3862     rc = sqlite3_open(zFilename, &db);
  3860   3863     
  3861   3864     if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
  3862   3865     Tcl_AppendResult(interp, zBuf, 0);
  3863   3866     return TCL_OK;
  3864   3867   }
         3868  +
         3869  +/*
         3870  +** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
         3871  +*/
         3872  +static int test_open_v2(
         3873  +  void * clientData,
         3874  +  Tcl_Interp *interp,
         3875  +  int objc,
         3876  +  Tcl_Obj *CONST objv[]
         3877  +){
         3878  +  const char *zFilename;
         3879  +  const char *zVfs;
         3880  +  int flags = 0;
         3881  +  sqlite3 *db;
         3882  +  int rc;
         3883  +  char zBuf[100];
         3884  +
         3885  +  int nFlag;
         3886  +  Tcl_Obj **apFlag;
         3887  +  int i;
         3888  +
         3889  +  if( objc!=4 ){
         3890  +    Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
         3891  +    return TCL_ERROR;
         3892  +  }
         3893  +  zFilename = Tcl_GetString(objv[1]);
         3894  +  zVfs = Tcl_GetString(objv[3]);
         3895  +  if( zVfs[0]==0x00 ) zVfs = 0;
         3896  +
         3897  +  rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
         3898  +  if( rc!=TCL_OK ) return rc;
         3899  +  for(i=0; i<nFlag; i++){
         3900  +    int iFlag;
         3901  +    struct OpenFlag {
         3902  +      const char *zFlag;
         3903  +      int flag;
         3904  +    } aFlag[] = {
         3905  +      { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
         3906  +      { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
         3907  +      { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
         3908  +      { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
         3909  +      { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
         3910  +      { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
         3911  +      { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
         3912  +      { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
         3913  +      { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
         3914  +      { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
         3915  +      { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
         3916  +      { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
         3917  +      { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
         3918  +      { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
         3919  +      { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
         3920  +      { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
         3921  +      { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
         3922  +      { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
         3923  +      { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
         3924  +      { 0, 0 }
         3925  +    };
         3926  +    rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]), 
         3927  +        "flag", 0, &iFlag
         3928  +    );
         3929  +    if( rc!=TCL_OK ) return rc;
         3930  +    flags |= aFlag[iFlag].flag;
         3931  +  }
         3932  +
         3933  +  rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
         3934  +  if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
         3935  +  Tcl_AppendResult(interp, zBuf, 0);
         3936  +  return TCL_OK;
         3937  +}
  3865   3938   
  3866   3939   /*
  3867   3940   ** Usage: sqlite3_open16 filename options
  3868   3941   */
  3869   3942   static int test_open16(
  3870   3943     void * clientData,
  3871   3944     Tcl_Interp *interp,
................................................................................
  5699   5772        { "sqlite3_sleep",                 test_sleep,          0},
  5700   5773        { "sqlite3_errcode",               test_errcode       ,0 },
  5701   5774        { "sqlite3_extended_errcode",      test_ex_errcode    ,0 },
  5702   5775        { "sqlite3_errmsg",                test_errmsg        ,0 },
  5703   5776        { "sqlite3_errmsg16",              test_errmsg16      ,0 },
  5704   5777        { "sqlite3_open",                  test_open          ,0 },
  5705   5778        { "sqlite3_open16",                test_open16        ,0 },
         5779  +     { "sqlite3_open_v2",               test_open_v2       ,0 },
  5706   5780        { "sqlite3_complete16",            test_complete16    ,0 },
  5707   5781   
  5708   5782        { "sqlite3_prepare",               test_prepare       ,0 },
  5709   5783        { "sqlite3_prepare16",             test_prepare16     ,0 },
  5710   5784        { "sqlite3_prepare_v2",            test_prepare_v2    ,0 },
  5711   5785        { "sqlite3_prepare_tkt3134",       test_prepare_tkt3134, 0},
  5712   5786        { "sqlite3_prepare16_v2",          test_prepare16_v2  ,0 },

Changes to src/test3.c.

    74     74     if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
    75     75     nRefSqlite3++;
    76     76     if( nRefSqlite3==1 ){
    77     77       sDb.pVfs = sqlite3_vfs_find(0);
    78     78       sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
    79     79       sqlite3_mutex_enter(sDb.mutex);
    80     80     }
    81         -  rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, 0, 
           81  +  rc = sqlite3BtreeOpen(sDb.pVfs, argv[1], &sDb, &pBt, 0, 
    82     82        SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
    83     83     if( rc!=SQLITE_OK ){
    84     84       Tcl_AppendResult(interp, errorName(rc), 0);
    85     85       return TCL_ERROR;
    86     86     }
    87     87     sqlite3BtreeSetCacheSize(pBt, nCache);
    88     88     sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt);

Changes to src/test_malloc.c.

  1169   1169             "sqlite3_config(99999) does not return SQLITE_ERROR",
  1170   1170             (char*)0);
  1171   1171         return TCL_ERROR;
  1172   1172       }
  1173   1173     }
  1174   1174     return TCL_OK;
  1175   1175   }
         1176  +
         1177  +/*
         1178  +** tclcmd:     sqlite3_config_uri  BOOLEAN
         1179  +**
         1180  +** Invoke sqlite3_config() or sqlite3_db_config() with invalid
         1181  +** opcodes and verify that they return errors.
         1182  +*/
         1183  +static int test_config_uri(
         1184  +  void * clientData, 
         1185  +  Tcl_Interp *interp,
         1186  +  int objc,
         1187  +  Tcl_Obj *CONST objv[]
         1188  +){
         1189  +  int rc;
         1190  +  int bOpenUri;
         1191  +
         1192  +  if( objc!=2 ){
         1193  +    Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
         1194  +    return TCL_ERROR;
         1195  +  }
         1196  +  if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){
         1197  +    return TCL_ERROR;
         1198  +  }
         1199  +
         1200  +  rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
         1201  +  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
         1202  +
         1203  +  return TCL_OK;
         1204  +}
  1176   1205   
  1177   1206   /*
  1178   1207   ** Usage:    
  1179   1208   **
  1180   1209   **   sqlite3_dump_memsys3  FILENAME
  1181   1210   **   sqlite3_dump_memsys5  FILENAME
  1182   1211   **
................................................................................
  1418   1447        { "sqlite3_status",             test_status                   ,0 },
  1419   1448        { "sqlite3_db_status",          test_db_status                ,0 },
  1420   1449        { "install_malloc_faultsim",    test_install_malloc_faultsim  ,0 },
  1421   1450        { "sqlite3_config_heap",        test_config_heap              ,0 },
  1422   1451        { "sqlite3_config_memstatus",   test_config_memstatus         ,0 },
  1423   1452        { "sqlite3_config_lookaside",   test_config_lookaside         ,0 },
  1424   1453        { "sqlite3_config_error",       test_config_error             ,0 },
         1454  +     { "sqlite3_config_uri",         test_config_uri               ,0 },
  1425   1455        { "sqlite3_db_config_lookaside",test_db_config_lookaside      ,0 },
  1426   1456        { "sqlite3_dump_memsys3",       test_dump_memsys3             ,3 },
  1427   1457        { "sqlite3_dump_memsys5",       test_dump_memsys3             ,5 },
  1428   1458        { "sqlite3_install_memsys3",    test_install_memsys3          ,0 },
  1429   1459        { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test          ,0 },
  1430   1460     };
  1431   1461     int i;

Changes to src/test_vfs.c.

   110    110   ** The Testvfs.mask variable is set to a combination of the following.
   111    111   ** If a bit is clear in Testvfs.mask, then calls made by SQLite to the 
   112    112   ** corresponding VFS method is ignored for purposes of:
   113    113   **
   114    114   **   + Simulating IO errors, and
   115    115   **   + Invoking the Tcl callback script.
   116    116   */
   117         -#define TESTVFS_SHMOPEN_MASK    0x00000001
   118         -#define TESTVFS_SHMLOCK_MASK    0x00000010
   119         -#define TESTVFS_SHMMAP_MASK     0x00000020
   120         -#define TESTVFS_SHMBARRIER_MASK 0x00000040
   121         -#define TESTVFS_SHMCLOSE_MASK   0x00000080
          117  +#define TESTVFS_SHMOPEN_MASK      0x00000001
          118  +#define TESTVFS_SHMLOCK_MASK      0x00000010
          119  +#define TESTVFS_SHMMAP_MASK       0x00000020
          120  +#define TESTVFS_SHMBARRIER_MASK   0x00000040
          121  +#define TESTVFS_SHMCLOSE_MASK     0x00000080
   122    122   
   123         -#define TESTVFS_OPEN_MASK       0x00000100
   124         -#define TESTVFS_SYNC_MASK       0x00000200
   125         -#define TESTVFS_DELETE_MASK     0x00000400
   126         -#define TESTVFS_CLOSE_MASK      0x00000800
   127         -#define TESTVFS_WRITE_MASK      0x00001000
   128         -#define TESTVFS_TRUNCATE_MASK   0x00002000
   129         -#define TESTVFS_ACCESS_MASK     0x00004000
   130         -#define TESTVFS_ALL_MASK        0x00007FFF
          123  +#define TESTVFS_OPEN_MASK         0x00000100
          124  +#define TESTVFS_SYNC_MASK         0x00000200
          125  +#define TESTVFS_DELETE_MASK       0x00000400
          126  +#define TESTVFS_CLOSE_MASK        0x00000800
          127  +#define TESTVFS_WRITE_MASK        0x00001000
          128  +#define TESTVFS_TRUNCATE_MASK     0x00002000
          129  +#define TESTVFS_ACCESS_MASK       0x00004000
          130  +#define TESTVFS_FULLPATHNAME_MASK 0x00008000
          131  +#define TESTVFS_ALL_MASK          0x0001FFFF
   131    132   
   132    133   
   133    134   #define TESTVFS_MAX_PAGES 1024
   134    135   
   135    136   /*
   136    137   ** A shared-memory buffer. There is one of these objects for each shared
   137    138   ** memory region opened by clients. If two clients open the same file,
................................................................................
   541    542     pFd->pVfs = pVfs;
   542    543     pFd->pReal = (sqlite3_file *)&pFd[1];
   543    544     memset(pTestfile, 0, sizeof(TestvfsFile));
   544    545     pTestfile->pFd = pFd;
   545    546   
   546    547     /* Evaluate the Tcl script: 
   547    548     **
   548         -  **   SCRIPT xOpen FILENAME
          549  +  **   SCRIPT xOpen FILENAME KEY-VALUE-ARGS
   549    550     **
   550    551     ** If the script returns an SQLite error code other than SQLITE_OK, an
   551    552     ** error is returned to the caller. If it returns SQLITE_OK, the new
   552    553     ** connection is named "anon". Otherwise, the value returned by the
   553    554     ** script is used as the connection name.
   554    555     */
   555    556     Tcl_ResetResult(p->interp);
   556    557     if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){
   557         -    tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
          558  +    Tcl_Obj *pArg = Tcl_NewObj();
          559  +    Tcl_IncrRefCount(pArg);
          560  +    if( flags&SQLITE_OPEN_MAIN_DB ){
          561  +      const char *z = &zName[strlen(zName)+1];
          562  +      while( *z ){
          563  +        Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
          564  +        z += strlen(z) + 1;
          565  +        Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
          566  +        z += strlen(z) + 1;
          567  +      }
          568  +    }
          569  +    tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0);
          570  +    Tcl_DecrRefCount(pArg);
   558    571       if( tvfsResultCode(p, &rc) ){
   559    572         if( rc!=SQLITE_OK ) return rc;
   560    573       }else{
   561    574         pId = Tcl_GetObjResult(p->interp);
   562    575       }
   563    576     }
   564    577   
................................................................................
   659    672   */
   660    673   static int tvfsFullPathname(
   661    674     sqlite3_vfs *pVfs, 
   662    675     const char *zPath, 
   663    676     int nOut, 
   664    677     char *zOut
   665    678   ){
          679  +  Testvfs *p = (Testvfs *)pVfs->pAppData;
          680  +  if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){
          681  +    int rc;
          682  +    tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0);
          683  +    if( tvfsResultCode(p, &rc) ){
          684  +      if( rc!=SQLITE_OK ) return rc;
          685  +    }
          686  +  }
   666    687     return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
   667    688   }
   668    689   
   669    690   #ifndef SQLITE_OMIT_LOAD_EXTENSION
   670    691   /*
   671    692   ** Open the dynamic library located at zPath and return a handle.
   672    693   */
................................................................................
  1024   1045       }
  1025   1046   
  1026   1047       case CMD_FILTER: {
  1027   1048         static struct VfsMethod {
  1028   1049           char *zName;
  1029   1050           int mask;
  1030   1051         } vfsmethod [] = {
  1031         -        { "xShmOpen",    TESTVFS_SHMOPEN_MASK },
  1032         -        { "xShmLock",    TESTVFS_SHMLOCK_MASK },
  1033         -        { "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
  1034         -        { "xShmUnmap",   TESTVFS_SHMCLOSE_MASK },
  1035         -        { "xShmMap",     TESTVFS_SHMMAP_MASK },
  1036         -        { "xSync",       TESTVFS_SYNC_MASK },
  1037         -        { "xDelete",     TESTVFS_DELETE_MASK },
  1038         -        { "xWrite",      TESTVFS_WRITE_MASK },
  1039         -        { "xTruncate",   TESTVFS_TRUNCATE_MASK },
  1040         -        { "xOpen",       TESTVFS_OPEN_MASK },
  1041         -        { "xClose",      TESTVFS_CLOSE_MASK },
  1042         -        { "xAccess",     TESTVFS_ACCESS_MASK },
         1052  +        { "xShmOpen",      TESTVFS_SHMOPEN_MASK },
         1053  +        { "xShmLock",      TESTVFS_SHMLOCK_MASK },
         1054  +        { "xShmBarrier",   TESTVFS_SHMBARRIER_MASK },
         1055  +        { "xShmUnmap",     TESTVFS_SHMCLOSE_MASK },
         1056  +        { "xShmMap",       TESTVFS_SHMMAP_MASK },
         1057  +        { "xSync",         TESTVFS_SYNC_MASK },
         1058  +        { "xDelete",       TESTVFS_DELETE_MASK },
         1059  +        { "xWrite",        TESTVFS_WRITE_MASK },
         1060  +        { "xTruncate",     TESTVFS_TRUNCATE_MASK },
         1061  +        { "xOpen",         TESTVFS_OPEN_MASK },
         1062  +        { "xClose",        TESTVFS_CLOSE_MASK },
         1063  +        { "xAccess",       TESTVFS_ACCESS_MASK },
         1064  +        { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
  1043   1065         };
  1044   1066         Tcl_Obj **apElem = 0;
  1045   1067         int nElem = 0;
  1046   1068         int i;
  1047   1069         int mask = 0;
  1048   1070         if( objc!=3 ){
  1049   1071           Tcl_WrongNumArgs(interp, 2, objv, "LIST");

Changes to src/util.c.

   979    979     p[1] = (u8)(v>>16);
   980    980     p[2] = (u8)(v>>8);
   981    981     p[3] = (u8)v;
   982    982   }
   983    983   
   984    984   
   985    985   
   986         -#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
   987    986   /*
   988    987   ** Translate a single byte of Hex into an integer.
   989    988   ** This routine only works if h really is a valid hexadecimal
   990    989   ** character:  0..9a..fA..F
   991    990   */
   992         -static u8 hexToInt(int h){
          991  +u8 sqlite3HexToInt(int h){
   993    992     assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
   994    993   #ifdef SQLITE_ASCII
   995    994     h += 9*(1&(h>>6));
   996    995   #endif
   997    996   #ifdef SQLITE_EBCDIC
   998    997     h += 9*(1&~(h>>4));
   999    998   #endif
  1000    999     return (u8)(h & 0xf);
  1001   1000   }
  1002         -#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
  1003   1001   
  1004   1002   #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
  1005   1003   /*
  1006   1004   ** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
  1007   1005   ** value.  Return a pointer to its binary value.  Space to hold the
  1008   1006   ** binary value has been obtained from malloc and must be freed by
  1009   1007   ** the calling routine.
................................................................................
  1012   1010     char *zBlob;
  1013   1011     int i;
  1014   1012   
  1015   1013     zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
  1016   1014     n--;
  1017   1015     if( zBlob ){
  1018   1016       for(i=0; i<n; i+=2){
  1019         -      zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
         1017  +      zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
  1020   1018       }
  1021   1019       zBlob[i/2] = 0;
  1022   1020     }
  1023   1021     return zBlob;
  1024   1022   }
  1025   1023   #endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
  1026   1024   

Changes to src/vdbe.c.

  3145   3145         SQLITE_OPEN_DELETEONCLOSE |
  3146   3146         SQLITE_OPEN_TRANSIENT_DB;
  3147   3147   
  3148   3148     assert( pOp->p1>=0 );
  3149   3149     pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
  3150   3150     if( pCx==0 ) goto no_mem;
  3151   3151     pCx->nullRow = 1;
  3152         -  rc = sqlite3BtreeOpen(0, db, &pCx->pBt, 
         3152  +  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, 
  3153   3153                           BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
  3154   3154     if( rc==SQLITE_OK ){
  3155   3155       rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
  3156   3156     }
  3157   3157     if( rc==SQLITE_OK ){
  3158   3158       /* If a transient index is required, create it by calling
  3159   3159       ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before

Changes to src/vtab.c.

   870    870     int rc = SQLITE_OK;
   871    871   
   872    872     assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
   873    873     if( db->aVTrans ){
   874    874       int i;
   875    875       for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
   876    876         const sqlite3_module *pMod = db->aVTrans[i]->pMod->pModule;
   877         -      if( pMod->iVersion>=1 ){
          877  +      if( pMod->iVersion>=2 ){
   878    878           int (*xMethod)(sqlite3_vtab *, int);
   879    879           switch( op ){
   880    880             case SAVEPOINT_BEGIN:
   881    881               xMethod = pMod->xSavepoint;
   882    882               break;
   883    883             case SAVEPOINT_ROLLBACK:
   884    884               xMethod = pMod->xRollbackTo;
................................................................................
   997    997   ** table update operation currently in progress.
   998    998   **
   999    999   ** The results of this routine are undefined unless it is called from
  1000   1000   ** within an xUpdate method.
  1001   1001   */
  1002   1002   int sqlite3_vtab_on_conflict(sqlite3 *db){
  1003   1003     static const unsigned char aMap[] = { 
  1004         -    SQLITE_ROLLBACK, SQLITE_IGNORE, SQLITE_ABORT, SQLITE_FAIL, SQLITE_REPLACE 
         1004  +    SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE 
  1005   1005     };
  1006   1006     assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
  1007   1007     assert( OE_Ignore==4 && OE_Replace==5 );
  1008   1008     assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 );
  1009   1009     return (int)aMap[db->vtabOnConflict-1];
  1010   1010   }
  1011   1011   
................................................................................
  1023   1023     va_start(ap, op);
  1024   1024     switch( op ){
  1025   1025       case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
  1026   1026         VtabCtx *p = db->pVtabCtx;
  1027   1027         if( !p ){
  1028   1028           rc = SQLITE_MISUSE_BKPT;
  1029   1029         }else{
  1030         -        assert( (p->pTab->tabFlags & TF_Virtual)!=0 );
         1030  +        assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
  1031   1031           p->pVTable->bConstraint = (u8)va_arg(ap, int);
  1032   1032         }
  1033   1033         break;
  1034   1034       }
  1035   1035       default:
  1036   1036         rc = SQLITE_MISUSE_BKPT;
  1037   1037         break;

Changes to src/wal.c.

   402    402   #define walFrameOffset(iFrame, szPage) (                               \
   403    403     WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE)         \
   404    404   )
   405    405   
   406    406   /*
   407    407   ** An open write-ahead log file is represented by an instance of the
   408    408   ** following object.
          409  +**
          410  +** The readOnlyShm variable is normally set to 0. If it is set to 1, then
          411  +** the connection to shared-memory is read-only. This means it cannot
          412  +** be written at all (even when read-locking the database). If it is set
          413  +** to 2, then the shared-memory region is not yet open, but a read-only
          414  +** connection is acceptable. In this case when the shared-memory is opened
          415  +** (see function walIndexPage()), readOnlyShm is set to either 0 or 1 as
          416  +** appropriate.
   409    417   */
   410    418   struct Wal {
   411    419     sqlite3_vfs *pVfs;         /* The VFS used to create pDbFd */
   412    420     sqlite3_file *pDbFd;       /* File handle for the database file */
   413    421     sqlite3_file *pWalFd;      /* File handle for WAL file */
   414    422     u32 iCallback;             /* Value to pass to log callback (or 0) */
   415    423     int nWiData;               /* Size of array apWiData */
................................................................................
   416    424     volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
   417    425     u32 szPage;                /* Database page size */
   418    426     i16 readLock;              /* Which read lock is being held.  -1 for none */
   419    427     u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
   420    428     u8 writeLock;              /* True if in a write transaction */
   421    429     u8 ckptLock;               /* True if holding a checkpoint lock */
   422    430     u8 readOnly;               /* True if the WAL file is open read-only */
          431  +  u8 readOnlyShm;            /* True if the SHM file is open read-only */
   423    432     WalIndexHdr hdr;           /* Wal-index header for current transaction */
   424    433     const char *zWalName;      /* Name of WAL file */
   425    434     u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
   426    435   #ifdef SQLITE_DEBUG
   427    436     u8 lockError;              /* True if a locking error has occurred */
   428    437   #endif
   429    438   };
................................................................................
   524    533       if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
   525    534         pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
   526    535         if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
   527    536       }else{
   528    537         rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
   529    538             pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
   530    539         );
          540  +      if( rc==SQLITE_CANTOPEN && pWal->readOnlyShm>1 ){
          541  +        assert( iPage==0 );
          542  +        sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_READONLY_SHM, (void*)1);
          543  +        rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
          544  +            pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
          545  +        );
          546  +        if( rc==SQLITE_OK ){
          547  +          pWal->readOnly = pWal->readOnlyShm = 1;
          548  +        }
          549  +        sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_READONLY_SHM, (void*)0);
          550  +      }
   531    551       }
   532    552     }
   533         -
   534    553     *ppPage = pWal->apWiData[iPage];
          554  +
   535    555     assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
          556  +  if( pWal->readOnlyShm>1 ) pWal->readOnlyShm = 0;
   536    557     return rc;
   537    558   }
   538    559   
   539    560   /*
   540    561   ** Return a pointer to the WalCkptInfo structure in the wal-index.
   541    562   */
   542    563   static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
................................................................................
   768    789     if( pWal->exclusiveMode ) return;
   769    790     (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
   770    791                            SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
   771    792     WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
   772    793   }
   773    794   static int walLockExclusive(Wal *pWal, int lockIdx, int n){
   774    795     int rc;
          796  +  assert( pWal->readOnlyShm==0 );
   775    797     if( pWal->exclusiveMode ) return SQLITE_OK;
   776    798     rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
   777    799                           SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
   778    800     WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
   779    801               walLockName(lockIdx), n, rc ? "failed" : "ok"));
   780    802     VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
   781    803     return rc;
   782    804   }
   783    805   static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
          806  +  assert( pWal->readOnlyShm==0 );
   784    807     if( pWal->exclusiveMode ) return;
   785    808     (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
   786    809                            SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
   787    810     WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
   788    811                walLockName(lockIdx), n));
   789    812   }
   790    813   
................................................................................
  1052   1075     ** If successful, the same bytes that are locked here are unlocked before
  1053   1076     ** this function returns.
  1054   1077     */
  1055   1078     assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
  1056   1079     assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
  1057   1080     assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
  1058   1081     assert( pWal->writeLock );
         1082  +  assert( pWal->readOnlyShm==0 );
  1059   1083     iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
  1060   1084     nLock = SQLITE_SHM_NLOCK - iLock;
  1061   1085     rc = walLockExclusive(pWal, iLock, nLock);
  1062   1086     if( rc ){
  1063   1087       return rc;
  1064   1088     }
  1065   1089     WALTRACE(("WAL%p: recovery begin...\n", pWal));
................................................................................
  1891   1915     */
  1892   1916     assert( pChanged );
  1893   1917     rc = walIndexPage(pWal, 0, &page0);
  1894   1918     if( rc!=SQLITE_OK ){
  1895   1919       return rc;
  1896   1920     };
  1897   1921     assert( page0 || pWal->writeLock==0 );
         1922  +  assert( pWal->readOnlyShm==0 || pWal->readOnlyShm==1 );
  1898   1923   
  1899   1924     /* If the first page of the wal-index has been mapped, try to read the
  1900   1925     ** wal-index header immediately, without holding any lock. This usually
  1901   1926     ** works, but may fail if the wal-index header is corrupt or currently 
  1902   1927     ** being modified by another thread or process.
  1903   1928     */
  1904   1929     badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
  1905   1930   
  1906   1931     /* If the first attempt failed, it might have been due to a race
  1907         -  ** with a writer.  So get a WRITE lock and try again.
         1932  +  ** with a writer. So lock the WAL_WRITE_LOCK byte and try again.
  1908   1933     */
  1909   1934     assert( badHdr==0 || pWal->writeLock==0 );
  1910         -  if( badHdr && SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
  1911         -    pWal->writeLock = 1;
  1912         -    if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
  1913         -      badHdr = walIndexTryHdr(pWal, pChanged);
  1914         -      if( badHdr ){
  1915         -        /* If the wal-index header is still malformed even while holding
  1916         -        ** a WRITE lock, it can only mean that the header is corrupted and
  1917         -        ** needs to be reconstructed.  So run recovery to do exactly that.
  1918         -        */
  1919         -        rc = walIndexRecover(pWal);
  1920         -        *pChanged = 1;
         1935  +  if( badHdr ){
         1936  +    if( pWal->readOnlyShm ){
         1937  +      if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
         1938  +        walUnlockShared(pWal, WAL_WRITE_LOCK);
         1939  +        rc = SQLITE_READONLY_RECOVERY;
         1940  +      }
         1941  +    }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
         1942  +      pWal->writeLock = 1;
         1943  +      if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
         1944  +        badHdr = walIndexTryHdr(pWal, pChanged);
         1945  +        if( badHdr ){
         1946  +          /* If the wal-index header is still malformed even while holding
         1947  +          ** a WRITE lock, it can only mean that the header is corrupted and
         1948  +          ** needs to be reconstructed.  So run recovery to do exactly that.
         1949  +          */
         1950  +          rc = walIndexRecover(pWal);
         1951  +          *pChanged = 1;
         1952  +        }
  1921   1953         }
         1954  +      pWal->writeLock = 0;
         1955  +      walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
  1922   1956       }
  1923         -    pWal->writeLock = 0;
  1924         -    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
  1925   1957     }
  1926   1958   
  1927   1959     /* If the header is read successfully, check the version number to make
  1928   1960     ** sure the wal-index was not constructed with some future format that
  1929   1961     ** this version of SQLite cannot understand.
  1930   1962     */
  1931   1963     if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
................................................................................
  2104   2136         assert( thisMark!=READMARK_NOT_USED );
  2105   2137         mxReadMark = thisMark;
  2106   2138         mxI = i;
  2107   2139       }
  2108   2140     }
  2109   2141     /* There was once an "if" here. The extra "{" is to preserve indentation. */
  2110   2142     {
  2111         -    if( mxReadMark < pWal->hdr.mxFrame || mxI==0 ){
         2143  +    if( pWal->readOnlyShm==0 && (mxReadMark < pWal->hdr.mxFrame || mxI==0) ){
  2112   2144         for(i=1; i<WAL_NREADER; i++){
  2113   2145           rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
  2114   2146           if( rc==SQLITE_OK ){
  2115   2147             mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame;
  2116   2148             mxI = i;
  2117   2149             walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
  2118   2150             break;
................................................................................
  2119   2151           }else if( rc!=SQLITE_BUSY ){
  2120   2152             return rc;
  2121   2153           }
  2122   2154         }
  2123   2155       }
  2124   2156       if( mxI==0 ){
  2125   2157         assert( rc==SQLITE_BUSY );
  2126         -      return WAL_RETRY;
         2158  +      assert( rc==SQLITE_BUSY || (pWal->readOnlyShm && rc==SQLITE_OK) );
         2159  +      return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
  2127   2160       }
  2128   2161   
  2129   2162       rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
  2130   2163       if( rc ){
  2131   2164         return rc==SQLITE_BUSY ? WAL_RETRY : rc;
  2132   2165       }
  2133   2166       /* Now that the read-lock has been obtained, check that neither the
................................................................................
  2174   2207   ** that extra content is ignored by the current thread.
  2175   2208   **
  2176   2209   ** If the database contents have changes since the previous read
  2177   2210   ** transaction, then *pChanged is set to 1 before returning.  The
  2178   2211   ** Pager layer will use this to know that is cache is stale and
  2179   2212   ** needs to be flushed.
  2180   2213   */
  2181         -int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
         2214  +int sqlite3WalBeginReadTransaction(Wal *pWal, int readOnlyShm, int *pChanged){
  2182   2215     int rc;                         /* Return code */
  2183   2216     int cnt = 0;                    /* Number of TryBeginRead attempts */
  2184   2217   
         2218  +  if( pWal->nWiData==0 || pWal->apWiData[0]==0 ){
         2219  +    assert( readOnlyShm==0 || readOnlyShm==1 );
         2220  +    pWal->readOnlyShm = readOnlyShm*2;
         2221  +  }
  2185   2222     do{
  2186   2223       rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
  2187   2224     }while( rc==WAL_RETRY );
         2225  +  assert( rc || pWal->readOnlyShm==0 || (readOnlyShm && pWal->readOnlyShm==1) );
  2188   2226     testcase( (rc&0xff)==SQLITE_BUSY );
  2189   2227     testcase( (rc&0xff)==SQLITE_IOERR );
  2190   2228     testcase( rc==SQLITE_PROTOCOL );
  2191   2229     testcase( rc==SQLITE_OK );
  2192   2230     return rc;
  2193   2231   }
  2194   2232   
................................................................................
  2355   2393     /* Cannot start a write transaction without first holding a read
  2356   2394     ** transaction. */
  2357   2395     assert( pWal->readLock>=0 );
  2358   2396   
  2359   2397     if( pWal->readOnly ){
  2360   2398       return SQLITE_READONLY;
  2361   2399     }
         2400  +  assert( pWal->readOnlyShm==0 );
  2362   2401   
  2363   2402     /* Only one writer allowed at a time.  Get the write lock.  Return
  2364   2403     ** SQLITE_BUSY if unable.
  2365   2404     */
  2366   2405     rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
  2367   2406     if( rc ){
  2368   2407       return rc;
................................................................................
  2744   2783     int isChanged = 0;              /* True if a new wal-index header is loaded */
  2745   2784     int eMode2 = eMode;             /* Mode to pass to walCheckpoint() */
  2746   2785   
  2747   2786     assert( pWal->ckptLock==0 );
  2748   2787     assert( pWal->writeLock==0 );
  2749   2788   
  2750   2789     WALTRACE(("WAL%p: checkpoint begins\n", pWal));
         2790  +  if( pWal->readOnlyShm ){
         2791  +    return SQLITE_READONLY;
         2792  +  }
         2793  +
  2751   2794     rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
  2752   2795     if( rc ){
  2753   2796       /* Usually this is SQLITE_BUSY meaning that another thread or process
  2754   2797       ** is already running a checkpoint, or maybe a recovery.  But it might
  2755   2798       ** also be SQLITE_IOERR. */
  2756   2799       return rc;
  2757   2800     }

Changes to src/wal.h.

    18     18   #define _WAL_H_
    19     19   
    20     20   #include "sqliteInt.h"
    21     21   
    22     22   #ifdef SQLITE_OMIT_WAL
    23     23   # define sqlite3WalOpen(x,y,z)                   0
    24     24   # define sqlite3WalClose(w,x,y,z)                0
    25         -# define sqlite3WalBeginReadTransaction(y,z)     0
           25  +# define sqlite3WalBeginReadTransaction(x,y,z)   0
    26     26   # define sqlite3WalEndReadTransaction(z)
    27     27   # define sqlite3WalRead(v,w,x,y,z)               0
    28     28   # define sqlite3WalDbsize(y)                     0
    29     29   # define sqlite3WalBeginWriteTransaction(y)      0
    30     30   # define sqlite3WalEndWriteTransaction(x)        0
    31     31   # define sqlite3WalUndo(x,y,z)                   0
    32     32   # define sqlite3WalSavepoint(y,z)
................................................................................
    52     52   /* Used by readers to open (lock) and close (unlock) a snapshot.  A 
    53     53   ** snapshot is like a read-transaction.  It is the state of the database
    54     54   ** at an instant in time.  sqlite3WalOpenSnapshot gets a read lock and
    55     55   ** preserves the current state even if the other threads or processes
    56     56   ** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
    57     57   ** transaction and releases the lock.
    58     58   */
    59         -int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
           59  +int sqlite3WalBeginReadTransaction(Wal *pWal, int, int *);
    60     60   void sqlite3WalEndReadTransaction(Wal *pWal);
    61     61   
    62     62   /* Read a page from the write-ahead log, if it is present. */
    63     63   int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
    64     64   
    65     65   /* If the WAL is not empty, return the size of the database. */
    66     66   Pgno sqlite3WalDbsize(Wal *pWal);

Changes to test/alter.test.

   646    646       SELECT $::col_name, $::col_name2 FROM $::tbl_name;
   647    647     "
   648    648   } {4 5}
   649    649   
   650    650   # Ticket #1665:  Make sure ALTER TABLE ADD COLUMN works on a table
   651    651   # that includes a COLLATE clause.
   652    652   #
   653         -do_test alter-7.1 {
          653  +do_realnum_test alter-7.1 {
   654    654     execsql {
   655    655       CREATE TABLE t1(a TEXT COLLATE BINARY);
   656    656       ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE;
   657    657       INSERT INTO t1 VALUES(1,'-2');
   658    658       INSERT INTO t1 VALUES(5.4e-08,'5.4e-08');
   659    659       SELECT typeof(a), a, typeof(b), b FROM t1;
   660    660     }

Changes to test/cast.test.

   230    230   #
   231    231   do_test cast-3.1 {
   232    232     execsql {SELECT CAST(9223372036854774800 AS integer)}
   233    233   } 9223372036854774800
   234    234   do_test cast-3.2 {
   235    235     execsql {SELECT CAST(9223372036854774800 AS numeric)}
   236    236   } 9223372036854774800
   237         -do_test cast-3.3 {
          237  +do_realnum_test cast-3.3 {
   238    238     execsql {SELECT CAST(9223372036854774800 AS real)}
   239    239   } 9.22337203685477e+18
   240    240   do_test cast-3.4 {
   241    241     execsql {SELECT CAST(CAST(9223372036854774800 AS real) AS integer)}
   242    242   } 9223372036854774784
   243    243   do_test cast-3.5 {
   244    244     execsql {SELECT CAST(-9223372036854774800 AS integer)}
   245    245   } -9223372036854774800
   246    246   do_test cast-3.6 {
   247    247     execsql {SELECT CAST(-9223372036854774800 AS numeric)}
   248    248   } -9223372036854774800
   249         -do_test cast-3.7 {
          249  +do_realnum_test cast-3.7 {
   250    250     execsql {SELECT CAST(-9223372036854774800 AS real)}
   251    251   } -9.22337203685477e+18
   252    252   do_test cast-3.8 {
   253    253     execsql {SELECT CAST(CAST(-9223372036854774800 AS real) AS integer)}
   254    254   } -9223372036854774784
   255    255   do_test cast-3.11 {
   256    256     execsql {SELECT CAST('9223372036854774800' AS integer)}
   257    257   } 9223372036854774800
   258    258   do_test cast-3.12 {
   259    259     execsql {SELECT CAST('9223372036854774800' AS numeric)}
   260    260   } 9223372036854774800
   261         -do_test cast-3.13 {
          261  +do_realnum_test cast-3.13 {
   262    262     execsql {SELECT CAST('9223372036854774800' AS real)}
   263    263   } 9.22337203685477e+18
   264    264   ifcapable long_double {
   265    265     do_test cast-3.14 {
   266    266       execsql {SELECT CAST(CAST('9223372036854774800' AS real) AS integer)}
   267    267     } 9223372036854774784
   268    268   }
   269    269   do_test cast-3.15 {
   270    270     execsql {SELECT CAST('-9223372036854774800' AS integer)}
   271    271   } -9223372036854774800
   272    272   do_test cast-3.16 {
   273    273     execsql {SELECT CAST('-9223372036854774800' AS numeric)}
   274    274   } -9223372036854774800
   275         -do_test cast-3.17 {
          275  +do_realnum_test cast-3.17 {
   276    276     execsql {SELECT CAST('-9223372036854774800' AS real)}
   277    277   } -9.22337203685477e+18
   278    278   ifcapable long_double {
   279    279     do_test cast-3.18 {
   280    280       execsql {SELECT CAST(CAST('-9223372036854774800' AS real) AS integer)}
   281    281     } -9223372036854774784
   282    282   }
................................................................................
   283    283   if {[db eval {PRAGMA encoding}]=="UTF-8"} {
   284    284     do_test cast-3.21 {
   285    285       execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS integer)}
   286    286     } 9223372036854774800
   287    287     do_test cast-3.22 {
   288    288       execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS numeric)}
   289    289     } 9223372036854774800
   290         -  do_test cast-3.23 {
          290  +  do_realnum_test cast-3.23 {
   291    291       execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS real)}
   292    292     } 9.22337203685477e+18
   293    293     ifcapable long_double {
   294    294       do_test cast-3.24 {
   295    295         execsql {
   296    296           SELECT CAST(CAST(x'39323233333732303336383534373734383030' AS real)
   297    297                       AS integer)

Added test/e_uri.test.

            1  +# 2011 May 06
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +
           13  +set testdir [file dirname $argv0]
           14  +source $testdir/tester.tcl
           15  +set testprefix e_uri
           16  +
           17  +db close
           18  +
           19  +proc parse_uri {uri} {
           20  +  testvfs tvfs2
           21  +  testvfs tvfs 
           22  +  tvfs filter xOpen
           23  +  tvfs script parse_uri_open_cb
           24  +
           25  +  set ::uri_open [list]
           26  +  set DB [sqlite3_open_v2 $uri {
           27  +    SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL
           28  +  } tvfs]
           29  +  sqlite3_close $DB
           30  +  tvfs delete
           31  +  tvfs2 delete
           32  +
           33  +  set ::uri_open
           34  +}
           35  +proc parse_uri_open_cb {method file arglist} {
           36  +  set ::uri_open [list $file $arglist]
           37  +}
           38  +
           39  +proc open_uri_error {uri} {
           40  +  set flags {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL}
           41  +  set DB [sqlite3_open_v2 $uri $flags ""]
           42  +  set e [sqlite3_errmsg $DB]
           43  +  sqlite3_close $DB
           44  +  set e
           45  +}
           46  +
           47  +# EVIDENCE-OF: R-35840-33204 If URI filename interpretation is enabled,
           48  +# and the filename argument begins with "file:", then the filename is
           49  +# interpreted as a URI.
           50  +#
           51  +# EVIDENCE-OF: R-00067-59538 URI filename interpretation is enabled if
           52  +# the SQLITE_OPEN_URI flag is is set in the fourth argument to
           53  +# sqlite3_open_v2(), or if it has been enabled globally using the
           54  +# SQLITE_CONFIG_URI option with the sqlite3_config() method.
           55  +#
           56  +if {$tcl_platform(platform) == "unix"} {
           57  +  set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE]
           58  +
           59  +  # Tests with SQLITE_CONFIG_URI configured to false. URI intepretation is
           60  +  # only enabled if the SQLITE_OPEN_URI flag is specified.
           61  +  sqlite3_shutdown
           62  +  sqlite3_config_uri 0
           63  +  do_test 1.1 {
           64  +    forcedelete file:test.db test.db
           65  +    set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
           66  +    list [file exists file:test.db] [file exists test.db]
           67  +  } {0 1}
           68  +  do_test 1.2 {
           69  +    forcedelete file:test.db2 test.db2
           70  +    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
           71  +    sqlite3_step $STMT
           72  +    sqlite3_finalize $STMT
           73  +    list [file exists file:test.db2] [file exists test.db2]
           74  +  } {0 1}
           75  +  sqlite3_close $DB
           76  +  do_test 1.3 {
           77  +    forcedelete file:test.db test.db
           78  +    set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
           79  +    list [file exists file:test.db] [file exists test.db]
           80  +  } {1 0}
           81  +  do_test 1.4 {
           82  +    forcedelete file:test.db2 test.db2
           83  +    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
           84  +    sqlite3_step $STMT
           85  +    sqlite3_finalize $STMT
           86  +    list [file exists file:test.db2] [file exists test.db2]
           87  +  } {1 0}
           88  +  sqlite3_close $DB
           89  +
           90  +  # Tests with SQLITE_CONFIG_URI configured to true. URI intepretation is
           91  +  # enabled with or without SQLITE_OPEN_URI.
           92  +  #
           93  +  sqlite3_shutdown
           94  +  sqlite3_config_uri 1
           95  +  do_test 1.5 {
           96  +    forcedelete file:test.db test.db
           97  +    set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
           98  +    list [file exists file:test.db] [file exists test.db]
           99  +  } {0 1}
          100  +  do_test 1.6 {
          101  +    forcedelete file:test.db2 test.db2
          102  +    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
          103  +    sqlite3_step $STMT
          104  +    sqlite3_finalize $STMT
          105  +    list [file exists file:test.db2] [file exists test.db2]
          106  +  } {0 1}
          107  +  sqlite3_close $DB
          108  +  do_test 1.7 {
          109  +    forcedelete file:test.db test.db
          110  +    set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
          111  +    list [file exists file:test.db] [file exists test.db]
          112  +  } {0 1}
          113  +  do_test 1.8 {
          114  +    forcedelete file:test.db2 test.db2
          115  +    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
          116  +    sqlite3_step $STMT
          117  +    sqlite3_finalize $STMT
          118  +    list [file exists file:test.db2] [file exists test.db2]
          119  +  } {0 1}
          120  +  sqlite3_close $DB
          121  +}
          122  +
          123  +# EVIDENCE-OF: R-17482-00398 If the authority is not an empty string or
          124  +# "localhost", an error is returned to the caller.
          125  +#
          126  +if {$tcl_platform(platform) == "unix"} {
          127  +  set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
          128  +  foreach {tn uri error} "
          129  +    1    {file://localhost[pwd]/test.db}     {not an error}
          130  +    2    {file://[pwd]/test.db}              {not an error}
          131  +    3    {file://x[pwd]/test.db}             {invalid uri authority: x}
          132  +    4    {file://invalid[pwd]/test.db}       {invalid uri authority: invalid}
          133  +  " {
          134  +    do_test 2.$tn {
          135  +      set DB [sqlite3_open_v2 $uri $flags ""]
          136  +      set e [sqlite3_errmsg $DB]
          137  +      sqlite3_close $DB
          138  +      set e
          139  +    } $error
          140  +  }
          141  +}
          142  +
          143  +# EVIDENCE-OF: R-43804-65312 The 'fragment' component of a URI, if
          144  +# present, is always ignored.
          145  +#
          146  +#   It is difficult to test that something is ignore correctly. So these tests
          147  +#   just show that adding a fragment does not interfere with the pathname or
          148  +#   parameters passed through to the VFS xOpen() methods.
          149  +#
          150  +if {$tcl_platform(platform) == "unix"} {
          151  +  foreach {tn uri parse} "
          152  +    1    {file:test.db#abc}     {[pwd]/test.db {}}
          153  +    2    {file:test.db?a=b#abc} {[pwd]/test.db {a b}}
          154  +    3    {file:test.db?a=b#?c=d} {[pwd]/test.db {a b}}
          155  +  " {
          156  +    do_test 3.$tn { parse_uri $uri } $parse
          157  +  }
          158  +}
          159  +
          160  +# EVIDENCE-OF: R-00273-20588 SQLite uses the 'path' component of the URI
          161  +# as the path to the database file to open.
          162  +#
          163  +# EVIDENCE-OF: R-28659-11035 If the path begins with a '/' character,
          164  +# then it is interpreted as an absolute path.
          165  +#
          166  +# EVIDENCE-OF: R-39349-47203 If it does not begin with a '/', it is
          167  +# interpreted as a relative path.
          168  +#
          169  +if {$tcl_platform(platform) == "unix"} {
          170  +  foreach {tn uri parse} "
          171  +    1    {file:test.db}             {[pwd]/test.db {}}
          172  +    2    {file:/test.db}            {/test.db {}}
          173  +    3    {file:///test.db}          {/test.db {}}
          174  +    4    {file://localhost/test.db} {/test.db {}}
          175  +    5    {file:/a/b/c/test.db}      {/a/b/c/test.db {}}
          176  +  " {
          177  +    do_test 4.$tn { parse_uri $uri } $parse
          178  +  }
          179  +}
          180  +
          181  +# EVIDENCE-OF: R-01612-30877 The "vfs" parameter may be used to specify
          182  +# the name of a VFS object that provides the operating system interface
          183  +# that should be used to access the database file on disk.
          184  +#
          185  +#   The above is tested by cases 1.* below.
          186  +#
          187  +# EVIDENCE-OF: R-52293-58497 If this option is set to an empty string
          188  +# the default VFS object is used.
          189  +#
          190  +#   The above is tested by cases 2.* below.
          191  +#
          192  +# EVIDENCE-OF: R-31855-18665 If sqlite3_open_v2() is used and the vfs
          193  +# option is present, then the VFS specified by the option takes
          194  +# precedence over the value passed as the fourth parameter to
          195  +# sqlite3_open_v2().
          196  +#
          197  +#   The above is tested by cases 3.* below.
          198  +#
          199  +proc vfs_open_cb {name args} {
          200  +  set ::vfs $name
          201  +}
          202  +foreach {name default} {vfs1 0 vfs2 0 vfs3 1} {
          203  +  testvfs $name -default $default
          204  +  $name filter xOpen
          205  +  $name script [list vfs_open_cb $name]
          206  +}
          207  +foreach {tn uri defvfs vfs} {
          208  +  1.1    "file:test.db?vfs=vfs1"    ""    vfs1
          209  +  1.2    "file:test.db?vfs=vfs2"    ""    vfs2
          210  +
          211  +  2.1    "file:test.db"             vfs1  vfs1
          212  +  2.2    "file:test.db?vfs="        vfs1  vfs3
          213  +
          214  +  3.1    "file:test.db?vfs=vfs1"    vfs2  vfs1
          215  +  3.2    "file:test.db?vfs=vfs2"    vfs1  vfs2
          216  +  3.3    "file:test.db?xvfs=vfs1"   vfs2  vfs2
          217  +  3.4    "file:test.db?xvfs=vfs2"   vfs1  vfs1
          218  +} {
          219  +  do_test 5.$tn {
          220  +    set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
          221  +    sqlite3_close [
          222  +      sqlite3_open_v2 $uri $flags $defvfs
          223  +    ]
          224  +    set ::vfs
          225  +  } $vfs
          226  +}
          227  +vfs1 delete
          228  +vfs2 delete
          229  +vfs3 delete
          230  +
          231  +# EVIDENCE-OF: R-48365-36308 Specifying an unknown VFS is an error.
          232  +#
          233  +set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
          234  +do_test 6.1 {
          235  +  set DB [sqlite3_open_v2 file:test.db?vfs=nosuchvfs $flags ""]
          236  +  set errmsg [sqlite3_errmsg $DB]
          237  +  sqlite3_close $DB
          238  +  set errmsg
          239  +} {no such vfs: nosuchvfs}
          240  +
          241  +
          242  +# EVIDENCE-OF: R-60479-64270 The mode parameter may be set to either
          243  +# "ro", "rw" or "rwc". Attempting to set it to any other value is an
          244  +# error
          245  +#
          246  +sqlite3 db test.db
          247  +db close
          248  +foreach {tn uri error} "
          249  +  1    {file:test.db?mode=ro}    {not an error}
          250  +  2    {file:test.db?mode=rw}    {not an error}
          251  +  3    {file:test.db?mode=rwc}   {not an error}
          252  +  4    {file:test.db?mode=Ro}    {no such access mode: Ro}
          253  +  5    {file:test.db?mode=Rw}    {no such access mode: Rw}
          254  +  6    {file:test.db?mode=Rwc}   {no such access mode: Rwc}
          255  +" {
          256  +  do_test 7.$tn { open_uri_error $uri } $error
          257  +}
          258  +
          259  +
          260  +# EVIDENCE-OF: R-09651-31805 If "ro" is specified, then the database is
          261  +# opened for read-only access, just as if the SQLITE_OPEN_READONLY flag
          262  +# had been set in the third argument to sqlite3_prepare_v2().
          263  +#
          264  +# EVIDENCE-OF: R-40137-26050 If the mode option is set to "rw", then the
          265  +# database is opened for read-write (but not create) access, as if
          266  +# SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had been set.
          267  +#
          268  +# EVIDENCE-OF: R-26845-32976 Value "rwc" is equivalent to setting both
          269  +# SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.
          270  +#
          271  +sqlite3_shutdown
          272  +sqlite3_config_uri 1
          273  +foreach {tn uri read write create} {
          274  +  1    {file:test.db?mode=ro}     1 0 0
          275  +  2    {file:test.db?mode=rw}     1 1 0
          276  +  3    {file:test.db?mode=rwc}    1 1 1
          277  +} {
          278  +  set RES(c,0) {1 {unable to open database file}}
          279  +  set RES(c,1) {0 {}}
          280  +  set RES(w,0) {1 {attempt to write a readonly database}}
          281  +  set RES(w,1) {0 {}}
          282  +  set RES(r,0) {1 {this never happens}}
          283  +  set RES(r,1) {0 {a b}}
          284  +
          285  +  # Test CREATE access:
          286  +  forcedelete test.db
          287  +  do_test 8.$tn.c { list [catch { sqlite3 db $uri } msg] $msg } $RES(c,$create)
          288  +  catch { db close }
          289  +
          290  +  sqlite3 db test.db
          291  +  db eval { CREATE TABLE t1(a, b) ; INSERT INTO t1 VALUES('a', 'b') ;}
          292  +  db close
          293  +  
          294  +  # Test READ access:
          295  +  do_test 8.$tn.r { 
          296  +    sqlite3 db $uri
          297  +    catchsql { SELECT * FROM t1 }
          298  +  } $RES(r,$read)
          299  +  
          300  +  # Test WRITE access:
          301  +  do_test 8.$tn.w { 
          302  +    sqlite3 db $uri
          303  +    catchsql { INSERT INTO t1 VALUES(1, 2) }
          304  +  } $RES(w,$write)
          305  +
          306  +  catch {db close}
          307  +}
          308  +
          309  +# EVIDENCE-OF: R-56032-32287 If sqlite3_open_v2() is used, it is an
          310  +# error to specify a value for the mode parameter that is less
          311  +# restrictive than that specified by the flags passed as the third
          312  +# parameter.
          313  +#
          314  +forcedelete test.db
          315  +sqlite3 db test.db
          316  +db close
          317  +foreach {tn uri flags error} {
          318  +  1   {file:test.db?mode=ro}   ro    {not an error}
          319  +  2   {file:test.db?mode=ro}   rw    {not an error}
          320  +  3   {file:test.db?mode=ro}   rwc   {not an error}
          321  +
          322  +  4   {file:test.db?mode=rw}   ro    {access mode not allowed: rw}
          323  +  5   {file:test.db?mode=rw}   rw    {not an error}
          324  +  6   {file:test.db?mode=rw}   rwc   {not an error}
          325  +
          326  +  7   {file:test.db?mode=rwc}  ro    {access mode not allowed: rwc}
          327  +  8   {file:test.db?mode=rwc}  rw    {access mode not allowed: rwc}
          328  +  9   {file:test.db?mode=rwc}  rwc   {not an error}
          329  +} {
          330  +  set f(ro)  [list SQLITE_OPEN_READONLY SQLITE_OPEN_URI]
          331  +  set f(rw)  [list SQLITE_OPEN_READWRITE SQLITE_OPEN_URI]
          332  +  set f(rwc) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
          333  +
          334  +  set DB [sqlite3_open_v2 $uri $f($flags) ""]
          335  +  set e [sqlite3_errmsg $DB]
          336  +  sqlite3_close $DB
          337  +
          338  +  do_test 9.$tn { set e } $error
          339  +}
          340  +
          341  +# EVIDENCE-OF: R-23182-54295 The cache parameter may be set to either
          342  +# "shared" or "private".
          343  +sqlite3 db test.db
          344  +db close
          345  +foreach {tn uri error} "
          346  +  1    {file:test.db?cache=private}    {not an error}
          347  +  2    {file:test.db?cache=shared}     {not an error}
          348  +  3    {file:test.db?cache=yes}        {no such cache mode: yes}
          349  +  4    {file:test.db?cache=}           {no such cache mode: }
          350  +" {
          351  +  do_test 10.$tn { open_uri_error $uri } $error
          352  +}
          353  +
          354  +# EVIDENCE-OF: R-23027-03515 Setting it to "shared" is equivalent to
          355  +# setting the SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed
          356  +# to sqlite3_open_v2().
          357  +#
          358  +# EVIDENCE-OF: R-49793-28525 Setting the cache parameter to "private" is
          359  +# equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
          360  +#
          361  +# EVIDENCE-OF: R-19510-48080 If sqlite3_open_v2() is used and the
          362  +# "cache" parameter is present in a URI filename, its value overrides
          363  +# any behaviour requested by setting SQLITE_OPEN_PRIVATECACHE or
          364  +# SQLITE_OPEN_SHAREDCACHE flag.
          365  +#
          366  +set orig [sqlite3_enable_shared_cache]
          367  +foreach {tn uri flags shared_default isshared} {
          368  +  1.1   "file:test.db"                  ""         0    0
          369  +  1.2   "file:test.db"                  ""         1    1
          370  +  1.3   "file:test.db"                  private    0    0
          371  +  1.4   "file:test.db"                  private    1    0
          372  +  1.5   "file:test.db"                  shared     0    1
          373  +  1.6   "file:test.db"                  shared     1    1
          374  +
          375  +  2.1   "file:test.db?cache=private"    ""         0    0
          376  +  2.2   "file:test.db?cache=private"    ""         1    0
          377  +  2.3   "file:test.db?cache=private"    private    0    0
          378  +  2.4   "file:test.db?cache=private"    private    1    0
          379  +  2.5   "file:test.db?cache=private"    shared     0    0
          380  +  2.6   "file:test.db?cache=private"    shared     1    0
          381  +
          382  +  3.1   "file:test.db?cache=shared"     ""         0    1
          383  +  3.2   "file:test.db?cache=shared"     ""         1    1
          384  +  3.3   "file:test.db?cache=shared"     private    0    1
          385  +  3.4   "file:test.db?cache=shared"     private    1    1
          386  +  3.5   "file:test.db?cache=shared"     shared     0    1
          387  +  3.6   "file:test.db?cache=shared"     shared     1    1
          388  +} {
          389  +  forcedelete test.db
          390  +  sqlite3_enable_shared_cache 1
          391  +  sqlite3 db test.db
          392  +  sqlite3_enable_shared_cache 0
          393  +
          394  +  db eval {
          395  +    CREATE TABLE t1(x);
          396  +    INSERT INTO t1 VALUES('ok');
          397  +  }
          398  +
          399  +  unset -nocomplain f
          400  +  set f()        {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI}
          401  +  set f(shared)  [concat $f() SQLITE_OPEN_SHAREDCACHE]
          402  +  set f(private) [concat $f() SQLITE_OPEN_PRIVATECACHE]
          403  +
          404  +  sqlite3_enable_shared_cache $shared_default
          405  +  set DB [sqlite3_open_v2 $uri $f($flags) ""]
          406  +
          407  +  set STMT [sqlite3_prepare $DB "SELECT * FROM t1" -1 dummy]
          408  +
          409  +  db eval {
          410  +    BEGIN;
          411  +      INSERT INTO t1 VALUES('ko');
          412  +  }
          413  +
          414  +  sqlite3_step $STMT
          415  +  sqlite3_finalize $STMT
          416  +
          417  +  set RES(0) {not an error}
          418  +  set RES(1) {database table is locked: t1}
          419  +
          420  +  do_test 11.$tn { sqlite3_errmsg $DB } $RES($isshared)
          421  +
          422  +  sqlite3_close $DB
          423  +  db close
          424  +}
          425  +sqlite3_enable_shared_cache $orig
          426  +
          427  +# EVIDENCE-OF: R-63472-46769 Specifying an unknown parameter in the
          428  +# query component of a URI is not an error.
          429  +#
          430  +do_test 12.1 {
          431  +  parse_uri file://localhost/test.db?an=unknown&parameter=is&ok=
          432  +} {/test.db {an unknown parameter is ok {}}}
          433  +do_test 12.2 {
          434  +  parse_uri file://localhost/test.db?an&unknown&parameter&is&ok
          435  +} {/test.db {an {} unknown {} parameter {} is {} ok {}}}
          436  +
          437  +# EVIDENCE-OF: R-27458-04043 URI hexadecimal escape sequences (%HH) are
          438  +# supported within the path and query components of a URI.
          439  +#
          440  +# EVIDENCE-OF: R-52765-50368 Before the path or query components of a
          441  +# URI filename are interpreted, they are encoded using UTF-8 and all
          442  +# hexadecimal escape sequences replaced by a single byte containing the
          443  +# corresponding octet.
          444  +#
          445  +#   The second of the two statements above is tested by creating a
          446  +#   multi-byte utf-8 character using a sequence of %HH escapes.
          447  +#
          448  +foreach {tn uri parse} "
          449  +  1  {file:/test.%64%62}                             {/test.db {}}
          450  +  2  {file:/test.db?%68%65%6c%6c%6f=%77%6f%72%6c%64} {/test.db {hello world}}
          451  +  3  {file:/%C3%BF.db}                               {/\xFF.db {}}
          452  +" {
          453  +  do_test 13.$tn { parse_uri $uri } $parse
          454  +}
          455  +
          456  +finish_test

Changes to test/expr.test.

    28     28   }
    29     29   
    30     30   proc test_expr {name settings expr result} {
    31     31     do_test $name [format {
    32     32       execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
    33     33     } $settings $expr] $result
    34     34   }
           35  +proc test_realnum_expr {name settings expr result} {
           36  +  do_realnum_test $name [format {
           37  +    execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
           38  +  } $settings $expr] $result
           39  +}
    35     40   
    36     41   test_expr expr-1.1 {i1=10, i2=20} {i1+i2} 30
    37     42   test_expr expr-1.2 {i1=10, i2=20} {i1-i2} -10
    38     43   test_expr expr-1.3 {i1=10, i2=20} {i1*i2} 200
    39     44   test_expr expr-1.4 {i1=10, i2=20} {i1/i2} 0
    40     45   test_expr expr-1.5 {i1=10, i2=20} {i2/i1} 2
    41     46   test_expr expr-1.6 {i1=10, i2=20} {i2<i1} 0
................................................................................
   160    165   ifcapable floatingpoint {
   161    166     test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0
   162    167     test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0
   163    168     test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1
   164    169   }
   165    170   
   166    171   if {[working_64bit_int]} {
   167         -  test_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18
          172  +  test_realnum_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18
   168    173   }
   169    174   
   170    175   test_expr expr-1.107 {i1=0} {-9223372036854775808%-1} 0
   171    176   test_expr expr-1.108 {i1=0} {1%0} {{}}
   172    177   test_expr expr-1.109 {i1=0} {1/0} {{}}
   173    178   
   174    179   if {[working_64bit_int]} {
................................................................................
   199    204     {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} yes
   200    205   test_expr expr-1.126 {i1=8, i2=8} \
   201    206     {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no
   202    207   
   203    208   ifcapable floatingpoint {if {[working_64bit_int]} {
   204    209     test_expr expr-1.200\
   205    210         {i1=9223372036854775806, i2=1} {i1+i2}      9223372036854775807
   206         -  test_expr expr-1.201\
          211  +  test_realnum_expr expr-1.201\
   207    212         {i1=9223372036854775806, i2=2} {i1+i2}      9.22337203685478e+18
   208         -  test_expr expr-1.202\
          213  +  test_realnum_expr expr-1.202\
   209    214         {i1=9223372036854775806, i2=100000} {i1+i2} 9.22337203685488e+18
   210         -  test_expr expr-1.203\
          215  +  test_realnum_expr expr-1.203\
   211    216         {i1=9223372036854775807, i2=0} {i1+i2}      9223372036854775807
   212         -  test_expr expr-1.204\
          217  +  test_realnum_expr expr-1.204\
   213    218         {i1=9223372036854775807, i2=1} {i1+i2}      9.22337203685478e+18
   214         -  test_expr expr-1.205\
          219  +  test_realnum_expr expr-1.205\
   215    220         {i2=9223372036854775806, i1=1} {i1+i2}      9223372036854775807
   216         -  test_expr expr-1.206\
          221  +  test_realnum_expr expr-1.206\
   217    222         {i2=9223372036854775806, i1=2} {i1+i2}      9.22337203685478e+18
   218         -  test_expr expr-1.207\
          223  +  test_realnum_expr expr-1.207\
   219    224         {i2=9223372036854775806, i1=100000} {i1+i2} 9.22337203685488e+18
   220         -  test_expr expr-1.208\
          225  +  test_realnum_expr expr-1.208\
   221    226         {i2=9223372036854775807, i1=0} {i1+i2}      9223372036854775807
   222         -  test_expr expr-1.209\
          227  +  test_realnum_expr expr-1.209\
   223    228         {i2=9223372036854775807, i1=1} {i1+i2}      9.22337203685478e+18
   224         -  test_expr expr-1.210\
          229  +  test_realnum_expr expr-1.210\
   225    230         {i1=-9223372036854775807, i2=-1} {i1+i2}    -9223372036854775808
   226         -  test_expr expr-1.211\
          231  +  test_realnum_expr expr-1.211\
   227    232         {i1=-9223372036854775807, i2=-2} {i1+i2}    -9.22337203685478e+18
   228         -  test_expr expr-1.212\
          233  +  test_realnum_expr expr-1.212\
   229    234         {i1=-9223372036854775807, i2=-100000} {i1+i2} -9.22337203685488e+18
   230         -  test_expr expr-1.213\
          235  +  test_realnum_expr expr-1.213\
   231    236         {i1=-9223372036854775808, i2=0} {i1+i2}     -9223372036854775808
   232         -  test_expr expr-1.214\
          237  +  test_realnum_expr expr-1.214\
   233    238         {i1=-9223372036854775808, i2=-1} {i1+i2}    -9.22337203685478e+18
   234         -  test_expr expr-1.215\
          239  +  test_realnum_expr expr-1.215\
   235    240         {i2=-9223372036854775807, i1=-1} {i1+i2}    -9223372036854775808
   236         -  test_expr expr-1.216\
          241  +  test_realnum_expr expr-1.216\
   237    242         {i2=-9223372036854775807, i1=-2} {i1+i2}    -9.22337203685478e+18
   238         -  test_expr expr-1.217\
          243  +  test_realnum_expr expr-1.217\
   239    244         {i2=-9223372036854775807, i1=-100000} {i1+i2} -9.22337203685488e+18
   240         -  test_expr expr-1.218\
          245  +  test_realnum_expr expr-1.218\
   241    246         {i2=-9223372036854775808, i1=0} {i1+i2}     -9223372036854775808
   242         -  test_expr expr-1.219\
          247  +  test_realnum_expr expr-1.219\
   243    248         {i2=-9223372036854775808, i1=-1} {i1+i2}    -9.22337203685478e+18
   244         -  test_expr expr-1.220\
          249  +  test_realnum_expr expr-1.220\
   245    250         {i1=9223372036854775806, i2=-1} {i1-i2}     9223372036854775807
   246         -  test_expr expr-1.221\
          251  +  test_realnum_expr expr-1.221\
   247    252         {i1=9223372036854775806, i2=-2} {i1-i2}      9.22337203685478e+18
   248         -  test_expr expr-1.222\
          253  +  test_realnum_expr expr-1.222\
   249    254         {i1=9223372036854775806, i2=-100000} {i1-i2} 9.22337203685488e+18
   250         -  test_expr expr-1.223\
          255  +  test_realnum_expr expr-1.223\
   251    256         {i1=9223372036854775807, i2=0} {i1-i2}      9223372036854775807
   252         -  test_expr expr-1.224\
          257  +  test_realnum_expr expr-1.224\
   253    258         {i1=9223372036854775807, i2=-1} {i1-i2}      9.22337203685478e+18
   254         -  test_expr expr-1.225\
          259  +  test_realnum_expr expr-1.225\
   255    260         {i2=-9223372036854775806, i1=1} {i1-i2}      9223372036854775807
   256         -  test_expr expr-1.226\
          261  +  test_realnum_expr expr-1.226\
   257    262         {i2=-9223372036854775806, i1=2} {i1-i2}      9.22337203685478e+18
   258         -  test_expr expr-1.227\
          263  +  test_realnum_expr expr-1.227\
   259    264         {i2=-9223372036854775806, i1=100000} {i1-i2} 9.22337203685488e+18
   260         -  test_expr expr-1.228\
          265  +  test_realnum_expr expr-1.228\
   261    266         {i2=-9223372036854775807, i1=0} {i1-i2}      9223372036854775807
   262         -  test_expr expr-1.229\
          267  +  test_realnum_expr expr-1.229\
   263    268         {i2=-9223372036854775807, i1=1} {i1-i2}      9.22337203685478e+18
   264         -  test_expr expr-1.230\
          269  +  test_realnum_expr expr-1.230\
   265    270         {i1=-9223372036854775807, i2=1} {i1-i2}    -9223372036854775808
   266         -  test_expr expr-1.231\
          271  +  test_realnum_expr expr-1.231\
   267    272         {i1=-9223372036854775807, i2=2} {i1-i2}    -9.22337203685478e+18
   268         -  test_expr expr-1.232\
          273  +  test_realnum_expr expr-1.232\
   269    274         {i1=-9223372036854775807, i2=100000} {i1-i2} -9.22337203685488e+18
   270         -  test_expr expr-1.233\
          275  +  test_realnum_expr expr-1.233\
   271    276         {i1=-9223372036854775808, i2=0} {i1-i2}     -9223372036854775808
   272         -  test_expr expr-1.234\
          277  +  test_realnum_expr expr-1.234\
   273    278         {i1=-9223372036854775808, i2=1} {i1-i2}    -9.22337203685478e+18
   274         -  test_expr expr-1.235\
          279  +  test_realnum_expr expr-1.235\
   275    280         {i2=9223372036854775807, i1=-1} {i1-i2}    -9223372036854775808
   276         -  test_expr expr-1.236\
          281  +  test_realnum_expr expr-1.236\
   277    282         {i2=9223372036854775807, i1=-2} {i1-i2}    -9.22337203685478e+18
   278         -  test_expr expr-1.237\
          283  +  test_realnum_expr expr-1.237\
   279    284         {i2=9223372036854775807, i1=-100000} {i1-i2} -9.22337203685488e+18
   280         -  test_expr expr-1.238\
          285  +  test_realnum_expr expr-1.238\
   281    286         {i2=9223372036854775807, i1=0} {i1-i2}     -9223372036854775807
   282         -  test_expr expr-1.239\
          287  +  test_realnum_expr expr-1.239\
   283    288         {i2=9223372036854775807, i1=-1} {i1-i2}    -9223372036854775808
   284    289   
   285         -  test_expr expr-1.250\
          290  +  test_realnum_expr expr-1.250\
   286    291         {i1=4294967296, i2=2147483648} {i1*i2}      9.22337203685478e+18
   287         -  test_expr expr-1.251\
          292  +  test_realnum_expr expr-1.251\
   288    293         {i1=4294967296, i2=2147483647} {i1*i2}      9223372032559808512
   289         -  test_expr expr-1.252\
          294  +  test_realnum_expr expr-1.252\
   290    295         {i1=-4294967296, i2=2147483648} {i1*i2}     -9223372036854775808
   291         -  test_expr expr-1.253\
          296  +  test_realnum_expr expr-1.253\
   292    297         {i1=-4294967296, i2=2147483647} {i1*i2}     -9223372032559808512
   293         -  test_expr expr-1.254\
          298  +  test_realnum_expr expr-1.254\
   294    299         {i1=4294967296, i2=-2147483648} {i1*i2}     -9223372036854775808
   295         -  test_expr expr-1.255\
          300  +  test_realnum_expr expr-1.255\
   296    301         {i1=4294967296, i2=-2147483647} {i1*i2}     -9223372032559808512
   297         -  test_expr expr-1.256\
          302  +  test_realnum_expr expr-1.256\
   298    303         {i1=-4294967296, i2=-2147483648} {i1*i2}    9.22337203685478e+18
   299         -  test_expr expr-1.257\
          304  +  test_realnum_expr expr-1.257\
   300    305         {i1=-4294967296, i2=-2147483647} {i1*i2}    9223372032559808512
   301    306   
   302    307   }}
   303    308   
   304    309   ifcapable floatingpoint {
   305    310     test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
   306    311     test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
................................................................................
   879    884   do_test expr-12.2 {
   880    885     catchsql {
   881    886       SELECT (CASE WHEN a>4 THEN 1 ELSE 0) FROM test1;
   882    887     }
   883    888   } {1 {near ")": syntax error}}
   884    889   
   885    890   ifcapable floatingpoint {
   886         -  do_test expr-13.1 {
          891  +  do_realnum_test expr-13.1 {
   887    892       execsql {
   888    893         SELECT 12345678901234567890;
   889    894       }
   890    895     } {1.23456789012346e+19}
   891    896   }
   892    897   
   893    898   # Implicit String->Integer conversion is used when possible.
................................................................................
   904    909       }
   905    910     } {9223372036854775807}
   906    911   }
   907    912   
   908    913   # If the value is too large, use String->Float conversion.
   909    914   #
   910    915   ifcapable floatingpoint {
   911         -  do_test expr-13.4 {
          916  +  do_realnum_test expr-13.4 {
   912    917       execsql {
   913    918         SELECT 0+'9223372036854775808'
   914    919       }
   915    920     } {9.22337203685478e+18}
   916         -  do_test expr-13.5 {
          921  +  do_realnum_test expr-13.5 {
   917    922       execsql {
   918    923         SELECT '9223372036854775808'+0
   919    924       }
   920    925     } {9.22337203685478e+18}
   921    926   }
   922    927   
   923    928   # Use String->float conversion if the value is explicitly a floating
   924    929   # point value.
   925    930   #
   926         -do_test expr-13.6 {
          931  +do_realnum_test expr-13.6 {
   927    932     execsql {
   928    933       SELECT 0+'9223372036854775807.0'
   929    934     }
   930    935   } {9.22337203685478e+18}
   931         -do_test expr-13.7 {
          936  +do_realnum_test expr-13.7 {
   932    937     execsql {
   933    938       SELECT '9223372036854775807.0'+0
   934    939     }
   935    940   } {9.22337203685478e+18}
   936    941   
   937    942   
   938    943   finish_test

Changes to test/lock_common.tcl.

    51     51       proc csql1 {sql} { list [catch { sql1 $sql } msg] $msg }
    52     52       proc csql2 {sql} { list [catch { sql2 $sql } msg] $msg }
    53     53       proc csql3 {sql} { list [catch { sql3 $sql } msg] $msg }
    54     54   
    55     55       uplevel set $varname $tn
    56     56       uplevel $script
    57     57   
    58         -    code2 { db2 close }
    59         -    code3 { db3 close }
           58  +    catch { code2 { db2 close } }
           59  +    catch { code3 { db3 close } }
    60     60       catch { close $::code2_chan }
    61     61       catch { close $::code3_chan }
    62     62       catch { db close }
    63     63     }
    64     64   }
    65     65   
    66     66   # Launch another testfixture process to be controlled by this one. A

Changes to test/nan.test.

    38     38     set ::STMT [sqlite3_prepare db "INSERT INTO t1 VALUES(?)" -1 TAIL]
    39     39     sqlite3_bind_double $::STMT 1 NaN
    40     40     sqlite3_step $::STMT
    41     41     sqlite3_reset $::STMT
    42     42     db eval {SELECT x, typeof(x) FROM t1}
    43     43   } {{} null}
    44     44   if {$tcl_platform(platform) != "symbian"} {
    45         -  do_test nan-1.1.2 {
           45  +  do_realnum_test nan-1.1.2 {
    46     46       sqlite3_bind_double $::STMT 1 +Inf
    47     47       sqlite3_step $::STMT
    48     48       sqlite3_reset $::STMT
    49     49       db eval {SELECT x, typeof(x) FROM t1}
    50     50     } {{} null inf real}
    51         -  do_test nan-1.1.3 {
           51  +  do_realnum_test nan-1.1.3 {
    52     52       sqlite3_bind_double $::STMT 1 -Inf
    53     53       sqlite3_step $::STMT
    54     54       sqlite3_reset $::STMT
    55     55       db eval {SELECT x, typeof(x) FROM t1}
    56     56     } {{} null inf real -inf real}
    57         -  do_test nan-1.1.4 {
           57  +  do_realnum_test nan-1.1.4 {
    58     58       sqlite3_bind_double $::STMT 1 -NaN
    59     59       sqlite3_step $::STMT
    60     60       sqlite3_reset $::STMT
    61     61       db eval {SELECT x, typeof(x) FROM t1}
    62     62     } {{} null inf real -inf real {} null}
    63         -  do_test nan-1.1.5 {
           63  +  do_realnum_test nan-1.1.5 {
    64     64       sqlite3_bind_double $::STMT 1 NaN0
    65     65       sqlite3_step $::STMT
    66     66       sqlite3_reset $::STMT
    67     67       db eval {SELECT x, typeof(x) FROM t1}
    68     68     } {{} null inf real -inf real {} null {} null}
    69         -  do_test nan-1.1.6 {
           69  +  do_realnum_test nan-1.1.6 {
    70     70       sqlite3_bind_double $::STMT 1 -NaN0
    71     71       sqlite3_step $::STMT
    72     72       sqlite3_reset $::STMT
    73     73       db eval {SELECT x, typeof(x) FROM t1}
    74     74     } {{} null inf real -inf real {} null {} null {} null}
    75     75     do_test nan-1.1.7 {
    76     76       db eval {
................................................................................
   227    227     db eval {SELECT x, typeof(x) FROM t1}
   228    228   } {1e+308 real}
   229    229   
   230    230   if {$tcl_platform(platform) != "symbian"} {
   231    231     # Do not run these tests on Symbian, as the Tcl port doesn't like to
   232    232     # convert from floating point value "-inf" to a string.
   233    233     #
   234         -  do_test nan-4.7 {
          234  +  do_realnum_test nan-4.7 {
   235    235       db eval {DELETE FROM t1}
   236    236       db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)"
   237    237       db eval {SELECT x, typeof(x) FROM t1}
   238    238     } {inf real}
   239         -  do_test nan-4.8 {
          239  +  do_realnum_test nan-4.8 {
   240    240       db eval {DELETE FROM t1}
   241    241       db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)"
   242    242       db eval {SELECT x, typeof(x) FROM t1}
   243    243     } {-inf real}
   244    244   }
   245    245   do_test nan-4.9 {
   246    246     db eval {DELETE FROM t1}
................................................................................
   309    309     db eval {DELETE FROM t1}
   310    310     set small \
   311    311         -[string repeat 0 10000].[string repeat 0 323][string repeat 9 10000]
   312    312     db eval "INSERT INTO t1 VALUES($small)"
   313    313     db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
   314    314   } {-9.88131291682493e-324 real}
   315    315   
   316         -do_test nan-4.20 {
          316  +do_realnum_test nan-4.20 {
   317    317     db eval {DELETE FROM t1}
   318    318     set big [string repeat 9 10000].0e-9000
   319    319     db eval "INSERT INTO t1 VALUES($big)"
   320    320     db eval {SELECT x, typeof(x) FROM t1}
   321    321   } {inf real}
   322    322   
   323    323   
   324    324   
   325    325   finish_test

Changes to test/pager1.test.

  1649   1649   #-------------------------------------------------------------------------
  1650   1650   # Check that it is not possible to open a database file if the full path
  1651   1651   # to the associated journal file will be longer than sqlite3_vfs.mxPathname.
  1652   1652   #
  1653   1653   testvfs tv -default 1
  1654   1654   tv script xOpenCb
  1655   1655   tv filter xOpen
  1656         -proc xOpenCb {method filename} {
         1656  +proc xOpenCb {method filename args} {
  1657   1657     set ::file_len [string length $filename]
  1658   1658   }
  1659   1659   sqlite3 db test.db
  1660   1660   db close
  1661   1661   tv delete
  1662   1662   
  1663   1663   for {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} {
................................................................................
  2377   2377   } {exclusive 0 main reserved temp closed}
  2378   2378   
  2379   2379   #-------------------------------------------------------------------------
  2380   2380   # Test that if the "page-size" field in a journal-header is 0, the journal
  2381   2381   # file can still be rolled back. This is required for backward compatibility -
  2382   2382   # versions of SQLite prior to 3.5.8 always set this field to zero.
  2383   2383   #
         2384  +if {$tcl_platform(platform)=="unix"} {
  2384   2385   do_test pager1-31.1 {
  2385   2386     faultsim_delete_and_reopen
  2386   2387     execsql {
  2387   2388       PRAGMA cache_size = 10;
  2388   2389       PRAGMA page_size = 1024;
  2389   2390       CREATE TABLE t1(x, y, UNIQUE(x, y));
  2390   2391       INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500));
................................................................................
  2404   2405     file copy test.db test.db2
  2405   2406     file copy test.db-journal test.db2-journal
  2406   2407     
  2407   2408     hexio_write test.db2-journal 24 00000000
  2408   2409     sqlite3 db2 test.db2
  2409   2410     execsql { PRAGMA integrity_check } db2
  2410   2411   } {ok}
  2411         -
         2412  +}
  2412   2413   
  2413   2414   
  2414   2415   finish_test

Changes to test/tester.tcl.

   349    349       puts "\nExpected: \[$expected\]\n     Got: \[$result\]"
   350    350       fail_test $name
   351    351     } else {
   352    352       puts " Ok"
   353    353     }
   354    354     flush stdout
   355    355   }
          356  +
          357  +proc realnum_normalize {r} {
          358  +  string map {1.#INF inf} [regsub -all {(e[+-])0+} $r {\1}]
          359  +}
          360  +proc do_realnum_test {name cmd expected} {
          361  +  uplevel [list do_test $name [
          362  +    subst -nocommands { realnum_normalize [ $cmd ] }
          363  +  ] [realnum_normalize $expected]]
          364  +}
   356    365   
   357    366   proc fix_testname {varname} {
   358    367     upvar $varname testname
   359    368     if {[info exists ::testprefix] 
   360    369      && [string is digit [string range $testname 0 0]]
   361    370     } {
   362    371       set testname "${::testprefix}-$testname"

Changes to test/tkt3838.test.

    21     21   source $testdir/tester.tcl
    22     22   
    23     23   ifcapable !altertable {
    24     24     finish_test
    25     25     return
    26     26   }
    27     27   
    28         -do_test tkt3838-1.1 {
           28  +do_realnum_test tkt3838-1.1 {
    29     29     db eval {
    30     30       PRAGMA encoding=UTF16;
    31     31       CREATE TABLE t1(x);
    32     32       INSERT INTO t1 VALUES(1);
    33     33       ALTER TABLE t1 ADD COLUMN b INTEGER DEFAULT '999';
    34     34       ALTER TABLE t1 ADD COLUMN c REAL DEFAULT '9e99';
    35     35       ALTER TABLE t1 ADD COLUMN d TEXT DEFAULT 'xyzzy';
    36     36       UPDATE t1 SET x=x+1;
    37     37       SELECT * FROM t1;
    38     38     }
    39     39   } {2 999 9e+99 xyzzy}
    40     40   
    41     41   finish_test

Changes to test/tkt3922.test.

    32     32       execsql {
    33     33         CREATE TABLE t1(a NUMBER);
    34     34         INSERT INTO t1 VALUES('-1');
    35     35         SELECT a, typeof(a) FROM t1;
    36     36       }
    37     37     } {-1 integer}
    38     38   }
    39         -do_test tkt3922.2 {
           39  +do_realnum_test tkt3922.2 {
    40     40     execsql {
    41     41       DELETE FROM t1;
    42     42       INSERT INTO t1 VALUES('-9223372036854775809');
    43     43       SELECT a, typeof(a) FROM t1;
    44     44     }
    45     45   } {-9.22337203685478e+18 real}
    46         -do_test tkt3922.3 {
           46  +do_realnum_test tkt3922.3 {
    47     47     execsql {
    48     48       DELETE FROM t1;
    49     49       INSERT INTO t1 VALUES('-9223372036854776832');
    50     50       SELECT a, typeof(a) FROM t1;
    51     51     }
    52     52   } {-9.22337203685478e+18 real}
    53         -do_test tkt3922.4 {
           53  +do_realnum_test tkt3922.4 {
    54     54     execsql {
    55     55       DELETE FROM t1;
    56     56       INSERT INTO t1 VALUES('-9223372036854776833');
    57     57       SELECT a, typeof(a) FROM t1;
    58     58     }
    59     59   } {-9.22337203685478e+18 real}
    60     60   if {[working_64bit_int]} {
................................................................................
    74     74       execsql {
    75     75         DELETE FROM t1;
    76     76         INSERT INTO t1 VALUES('1');
    77     77         SELECT a, typeof(a) FROM t1;
    78     78       }
    79     79     } {1 integer}
    80     80   }
    81         -do_test tkt3922.6 {
           81  +do_realnum_test tkt3922.6 {
    82     82     execsql {
    83     83       DELETE FROM t1;
    84     84       INSERT INTO t1 VALUES('9223372036854775808');
    85     85       SELECT a, typeof(a) FROM t1;
    86     86     }
    87     87   } {9.22337203685478e+18 real}
    88     88   
    89     89   finish_test

Added test/uri.test.

            1  +# 2011 April 22
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +
           13  +set testdir [file dirname $argv0]
           14  +source $testdir/tester.tcl
           15  +
           16  +# Test organization:
           17  +#
           18  +#   1.*: That file names are correctly extracted from URIs.
           19  +#   2.*: That URI options (query parameters) are correctly extracted from URIs.
           20  +#   3.*: That specifying an unknown VFS causes an error.
           21  +#   4.*: Tests for specifying other options (other than "vfs").
           22  +#   5.*: Test using a different VFS with an attached database.
           23  +#   6.*: Test that authorities other than "" and localhost cause errors.
           24  +#   7.*: Test that a read-write db can be attached to a read-only connection.
           25  +#
           26  +
           27  +set testprefix uri
           28  +db close
           29  +sqlite3_shutdown
           30  +sqlite3_config_uri 1
           31  +
           32  +#-------------------------------------------------------------------------
           33  +# Test that file names are correctly extracted from URIs.
           34  +#
           35  +foreach {tn uri file} {
           36  +  1      test.db                              test.db
           37  +  2      file:test.db                         test.db
           38  +  3      file://PWD/test.db                   test.db
           39  +  4      file:PWD/test.db                     test.db
           40  +  5      file:test.db?mork=1                  test.db
           41  +  6      file:test.db?mork=1&tonglor=2        test.db
           42  +  7      file:test.db?mork=1#boris            test.db
           43  +  8      file:test.db#boris                   test.db
           44  +  9      test.db#boris                        test.db#boris
           45  +  10     file:test%2Edb                       test.db
           46  +  11     file                                 file
           47  +  12     http:test.db                         http:test.db
           48  +  13     file:test.db%00extra                 test.db
           49  +  14     file:test%00.db%00extra              test
           50  +
           51  +  15     test.db?mork=1#boris                 test.db?mork=1#boris
           52  +  16     file://localhostPWD/test.db%3Fhello  test.db?hello
           53  +} {
           54  +  
           55  +  if {$tcl_platform(platform)=="windows"} {
           56  +    if {$tn>14} break
           57  +    set uri  [string map [list PWD /[pwd]] $uri]
           58  +  } else {
           59  +    set uri  [string map [list PWD [pwd]] $uri]
           60  +  }
           61  +
           62  +  forcedelete $file
           63  +  do_test 1.$tn.1 { file exists $file } 0
           64  +  set DB [sqlite3_open $uri]
           65  +  do_test 1.$tn.2 { file exists $file } 1
           66  +  sqlite3_close $DB
           67  +  forcedelete $file
           68  +
           69  +  do_test 1.$tn.3 { file exists $file } 0
           70  +  sqlite3 db xxx.db
           71  +  catchsql { ATTACH $uri AS aux }
           72  +  do_test 1.$tn.4 { file exists $file } 1
           73  +  db close
           74  +}
           75  +
           76  +#-------------------------------------------------------------------------
           77  +# Test that URI query parameters are passed through to the VFS layer
           78  +# correctly.
           79  +#
           80  +testvfs tvfs2
           81  +testvfs tvfs -default 1
           82  +tvfs filter xOpen
           83  +tvfs script open_method
           84  +proc open_method {method file arglist} {
           85  +  set ::arglist $arglist
           86  +}
           87  +foreach {tn uri kvlist} {
           88  +  1      file:test.db?hello=world                     {hello world}
           89  +  2      file:test.db?hello&world                     {hello {} world {}}
           90  +  3      file:test.db?hello=1&world=2&vfs=tvfs        {hello 1 world 2 vfs tvfs}
           91  +  4      file:test.db?hello=1&world=2&vfs=tvfs2        {}
           92  +  5      file:test.db?%68%65%6C%6C%6F=%77%6F%72%6C%64 {hello world}
           93  +  6      file:test%00.db?hello%00extra=world%00ex     {hello world}
           94  +  7      file:test%00.db?hello%00=world%00            {hello world}
           95  +  8      file:test%00.db?=world&xyz=abc               {xyz abc}
           96  +  9      file:test.db?%00hello=world&xyz=abc          {xyz abc}
           97  +  10     file:test.db?hello=%00world&xyz=             {hello {} xyz {}}
           98  +  11     file:test.db?=#ravada                        {}
           99  +  12     file:test.db?&&&&&&&&hello=world&&&&&&&      {hello world}
          100  +
          101  +  13     test.db?&&&&&&&&hello=world&&&&&&&           {}
          102  +  14     http:test.db?hello&world                     {}
          103  +} {
          104  +
          105  +  if {$tcl_platform(platform) == "windows" && $tn>12} {
          106  +    continue
          107  +  }
          108  +
          109  +  set ::arglist ""
          110  +  set DB [sqlite3_open $uri]
          111  +  do_test 2.$tn.1 { set ::arglist } $kvlist
          112  +  sqlite3_close $DB
          113  +
          114  +  sqlite3 db xxx.db
          115  +  set ::arglist ""
          116  +  execsql { ATTACH $uri AS aux }
          117  +  do_test 2.$tn.2 { set ::arglist } $kvlist
          118  +  db close
          119  +}
          120  +tvfs delete
          121  +tvfs2 delete
          122  +
          123  +#-------------------------------------------------------------------------
          124  +# Test that specifying a non-existent VFS raises an error.
          125  +#
          126  +do_test 3.1 {
          127  +  list [catch { sqlite3 db "file:test.db?vfs=nosuchvfs" } msg] $msg
          128  +} {1 {no such vfs: nosuchvfs}}
          129  +
          130  +#-------------------------------------------------------------------------
          131  +# Test some of the other options (other than "vfs").
          132  +#
          133  +foreach {tn mode create_ok write_ok readonly_ok} {
          134  +  1    ro    0   0   1
          135  +  2    rw    0   1   0
          136  +  3    rwc   1   1   0
          137  +} {
          138  +  catch { db close }
          139  +  forcedelete test.db
          140  +
          141  +  set A(1) {0 {}}
          142  +  set A(0) {1 {unable to open database file}}
          143  +  do_test 4.1.$tn.1 {
          144  +    list [catch {sqlite3 db "file:test.db?mode=$mode"} msg] $msg
          145  +  } $A($create_ok)
          146  +
          147  +  catch { db close }
          148  +  forcedelete test.db
          149  +  sqlite3 db test.db
          150  +  db eval { CREATE TABLE t1(a, b) }
          151  +  db close
          152  +
          153  +  set A(1) {0 {}}
          154  +  set A(0) {1 {attempt to write a readonly database}}
          155  +  do_test 4.1.$tn.2 {
          156  +    sqlite3 db "file:test.db?mode=$mode"
          157  +    catchsql { INSERT INTO t1 VALUES(1, 2) }
          158  +  } $A($write_ok)
          159  +
          160  +  set A(1) {0 {}}
          161  +  set A(0) [list 1 "access mode not allowed: $mode"]
          162  +  do_test 4.1.$tn.3 {
          163  +    list [catch {sqlite3 db "file:test.db?mode=$mode" -readonly 1} msg] $msg
          164  +  } $A($readonly_ok)
          165  +}
          166  +
          167  +set orig [sqlite3_enable_shared_cache]
          168  +foreach {tn options sc_default is_shared} {
          169  +  1    ""                1   1
          170  +  2    "cache=private"   1   0
          171  +  3    "cache=shared"    1   1
          172  +  4    ""                0   0
          173  +  5    "cache=private"   0   0
          174  +  6    "cache=shared"    0   1
          175  +} {
          176  +  catch { db close }
          177  +  forcedelete test.db
          178  +
          179  +  sqlite3_enable_shared_cache 1
          180  +  sqlite3 db2 test.db
          181  +  db2 eval {CREATE TABLE t1(a, b)}
          182  +
          183  +  sqlite3_enable_shared_cache $sc_default
          184  +  sqlite3 db "file:test.db?$options"
          185  +  db eval {SELECT * FROM t1}
          186  +
          187  +  set A(1) {1 {database table is locked: t1}}
          188  +  set A(0) {0 {}}
          189  +  do_test 4.2.$tn {
          190  +    db2 eval {BEGIN; INSERT INTO t1 VALUES(1, 2);}
          191  +    catchsql { SELECT * FROM t1 }
          192  +  } $A($is_shared)
          193  +
          194  +  db2 close
          195  +}
          196  +
          197  +do_test 4.3.1 {
          198  +  list [catch {sqlite3 db "file:test.db?mode=rc"} msg] $msg
          199  +} {1 {no such access mode: rc}}
          200  +do_test 4.3.2 {
          201  +  list [catch {sqlite3 db "file:test.db?cache=public"} msg] $msg
          202  +} {1 {no such cache mode: public}}
          203  +
          204  +#-------------------------------------------------------------------------
          205  +# Test that things work if an ATTACHed database uses a different VFS than
          206  +# the main database. The important point is that for all operations 
          207  +# involving the ATTACHed database, the correct versions of the following
          208  +# VFS are used for all operations involving the attached database.
          209  +#
          210  +#     xOpen
          211  +#     xDelete
          212  +#     xAccess
          213  +#     xFullPathname
          214  +#
          215  +
          216  +# This block of code creates two VFS - "tvfs1" and "tvfs2". Each time one
          217  +# of the above methods is called using "tvfs1", global variable ::T1(X) is
          218  +# set, where X is the file-name the method is called on. Calls to the above
          219  +# methods using "tvfs2" set entries in the global T2 array.
          220  +#
          221  +testvfs tvfs1 
          222  +tvfs1 filter {xOpen xDelete xAccess xFullPathname}
          223  +tvfs1 script tvfs1_callback
          224  +proc tvfs1_callback {method filename args} { 
          225  +  set ::T1([file tail $filename]) 1 
          226  +}
          227  +testvfs tvfs2 
          228  +tvfs2 filter {xOpen xDelete xAccess xFullPathname}
          229  +tvfs2 script tvfs2_callback
          230  +proc tvfs2_callback {method filename args} { 
          231  +  set ::T2([file tail $filename]) 1 
          232  +}
          233  +
          234  +catch {db close}
          235  +eval forcedelete [glob test.db*]
          236  +do_test 5.1.1 {
          237  +  sqlite3 db file:test.db1?vfs=tvfs1
          238  +  execsql {
          239  +    ATTACH 'file:test.db2?vfs=tvfs2' AS aux;
          240  +    PRAGMA main.journal_mode = PERSIST;
          241  +    PRAGMA aux.journal_mode = PERSIST;
          242  +    CREATE TABLE t1(a, b);
          243  +    CREATE TABLE aux.t2(a, b);
          244  +    PRAGMA main.journal_mode = WAL;
          245  +    PRAGMA aux.journal_mode = WAL;
          246  +    INSERT INTO t1 VALUES('x', 'y');
          247  +    INSERT INTO t2 VALUES('x', 'y');
          248  +  }
          249  +  lsort [array names ::T1]
          250  +} {test.db1 test.db1-journal test.db1-wal}
          251  +
          252  +do_test 5.1.2 {
          253  +  lsort [array names ::T2]
          254  +} {test.db2 test.db2-journal test.db2-wal}
          255  +
          256  +db close
          257  +tvfs1 delete
          258  +tvfs2 delete
          259  +
          260  +#-------------------------------------------------------------------------
          261  +# Check that only "" and "localhost" are acceptable as authorities.
          262  +#
          263  +catch {db close}
          264  +foreach {tn uri res} {
          265  +  1     "file://localhost/PWD/test.db"   {not an error}
          266  +  2     "file:///PWD/test.db"            {not an error}
          267  +  3     "file:/PWD/test.db"              {not an error}
          268  +  4     "file://l%6Fcalhost/PWD/test.db" {invalid uri authority: l%6Fcalhost}
          269  +  5     "file://lbcalhost/PWD/test.db"   {invalid uri authority: lbcalhost}
          270  +  6     "file://x/PWD/test.db"           {invalid uri authority: x}
          271  +} {
          272  +
          273  +  if {$tcl_platform(platform)=="windows"} {
          274  +    set uri  [string map [list PWD [string range [pwd] 3 end]] $uri]
          275  +  } else {
          276  +    set uri  [string map [list PWD [string range [pwd] 1 end]] $uri]
          277  +  }
          278  +
          279  +  do_test 6.$tn {
          280  +    set DB [sqlite3_open $uri]
          281  +    sqlite3_errmsg $DB
          282  +  } $res
          283  +  catch { sqlite3_close $DB }
          284  +}
          285  +
          286  +forcedelete test.db test.db2
          287  +do_test 7.1 {
          288  +  sqlite3 db test.db
          289  +  execsql {
          290  +    CREATE TABLE t1(a, b);
          291  +    INSERT INTO t1 VALUES(1, 2);
          292  +    ATTACH 'test.db2' AS aux;
          293  +    CREATE TABLE aux.t2(a, b);
          294  +    INSERT INTO t1 VALUES('a', 'b');
          295  +  }
          296  +  db close
          297  +} {}
          298  +do_test 7.2 {
          299  +  sqlite3 db file:test.db?mode=ro
          300  +  execsql { ATTACH 'file:test.db2?mode=rw' AS aux }
          301  +} {}
          302  +do_execsql_test  7.3 { 
          303  +  INSERT INTO t2 VALUES('c', 'd') 
          304  +} {}
          305  +do_catchsql_test 7.4 { 
          306  +  INSERT INTO t1 VALUES(3, 4) 
          307  +} {1 {attempt to write a readonly database}}
          308  +
          309  +finish_test

Added test/walro.test.

            1  +# 2011 May 09
            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  +# This file contains tests for using WAL databases in read-only mode.
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +source $testdir/lock_common.tcl
           18  +set ::testprefix walro
           19  +
           20  +
           21  +do_multiclient_test tn {
           22  +  # These tests are only going to work on unix.
           23  +  #
           24  +  if {$tcl_platform(platform) != "unix"} continue
           25  +
           26  +  # Do not run tests with the connections in the same process.
           27  +  #
           28  +  if {$tn==2} continue
           29  +  
           30  +  # Close all connections and delete the database.
           31  +  #
           32  +  code1 { db close  }
           33  +  code2 { db2 close }
           34  +  code3 { db3 close }
           35  +  forcedelete test.db
           36  +  forcedelete walro
           37  +
           38  +  foreach c {code1 code2 code3} {
           39  +    $c {
           40  +      sqlite3_shutdown
           41  +      sqlite3_config_uri 1
           42  +    }
           43  +  }
           44  +
           45  +  file mkdir walro
           46  +
           47  +  do_test 1.1.1 {
           48  +    code2 { sqlite3 db2 test.db }
           49  +    sql2 { 
           50  +      PRAGMA journal_mode = WAL;
           51  +      CREATE TABLE t1(x, y);
           52  +      INSERT INTO t1 VALUES('a', 'b');
           53  +    }
           54  +    file exists test.db-shm
           55  +  } {1}
           56  +
           57  +  do_test 1.1.2 {
           58  +    file attributes test.db-shm -permissions r--r--r--
           59  +    code1 { sqlite3 db file:test.db?readonly_shm=1 }
           60  +  } {}
           61  +
           62  +  do_test 1.1.3 { sql1 "SELECT * FROM t1" }                {a b}
           63  +  do_test 1.1.4 { sql2 "INSERT INTO t1 VALUES('c', 'd')" } {}
           64  +  do_test 1.1.5 { sql1 "SELECT * FROM t1" }                {a b c d}
           65  +
           66  +  # Check that the read-only connection cannot write or checkpoint the db.
           67  +  #
           68  +  do_test 1.1.6 { 
           69  +    csql1 "INSERT INTO t1 VALUES('e', 'f')" 
           70  +  } {1 {attempt to write a readonly database}}
           71  +  do_test 1.1.7 { 
           72  +    csql1 "PRAGMA wal_checkpoint"
           73  +  } {1 {attempt to write a readonly database}}
           74  +
           75  +  do_test 1.1.9  { sql2 "INSERT INTO t1 VALUES('e', 'f')" } {}
           76  +  do_test 1.1.10 { sql1 "SELECT * FROM t1" }                {a b c d e f}
           77  +
           78  +  do_test 1.1.11 { 
           79  +    sql2 {
           80  +      INSERT INTO t1 VALUES('g', 'h');
           81  +      PRAGMA wal_checkpoint;
           82  +    }
           83  +    set {} {}
           84  +  } {}
           85  +  do_test 1.1.12 { sql1 "SELECT * FROM t1" }                {a b c d e f g h}
           86  +  do_test 1.1.13  { sql2 "INSERT INTO t1 VALUES('i', 'j')" } {}
           87  +
           88  +  do_test 1.2.1 {
           89  +    code2 { db2 close }
           90  +    code1 { db close }
           91  +    list [file exists test.db-wal] [file exists test.db-shm]
           92  +  } {1 1}
           93  +  do_test 1.2.2 {
           94  +    code1 { sqlite3 db file:test.db?readonly_shm=1 }
           95  +    sql1 { SELECT * FROM t1 }
           96  +  } {a b c d e f g h i j}
           97  +
           98  +  do_test 1.2.3 {
           99  +    code1 { db close }
          100  +    file attributes test.db-shm -permissions rw-r--r--
          101  +    hexio_write test.db-shm 0 01020304 
          102  +    file attributes test.db-shm -permissions r--r--r--
          103  +    code1 { sqlite3 db file:test.db?readonly_shm=1 }
          104  +    csql1 { SELECT * FROM t1 }
          105  +  } {1 {attempt to write a readonly database}}
          106  +  do_test 1.2.4 {
          107  +    code1 { sqlite3_extended_errcode db } 
          108  +  } {SQLITE_READONLY_RECOVERY}
          109  +
          110  +  do_test 1.2.5 {
          111  +    file attributes test.db-shm -permissions rw-r--r--
          112  +    code2 { sqlite3 db2 test.db }
          113  +    sql2 "SELECT * FROM t1" 
          114  +  } {a b c d e f g h i j}
          115  +  file attributes test.db-shm -permissions r--r--r--
          116  +  do_test 1.2.6 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j}
          117  +
          118  +  do_test 1.2.7 { 
          119  +    sql2 {
          120  +      PRAGMA wal_checkpoint;
          121  +      INSERT INTO t1 VALUES('k', 'l');
          122  +    }
          123  +    set {} {}
          124  +  } {}
          125  +  do_test 1.2.8 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j k l}
          126  +
          127  +  # Now check that if the readonly_shm option is not supplied, or if it
          128  +  # is set to zero, it is not possible to connect to the database without
          129  +  # read-write access to the shm.
          130  +  do_test 1.3.1 {
          131  +    code1 { db close }
          132  +    code1 { sqlite3 db test.db }
          133  +    csql1 { SELECT * FROM t1 }
          134  +  } {1 {unable to open database file}}
          135  +
          136  +  # Also test that if the -shm file can be opened for read/write access,
          137  +  # it is, even if readonly_shm=1 is present in the URI.
          138  +  do_test 1.3.2.1 {
          139  +    code1 { db close }
          140  +    code2 { db2 close }
          141  +    file exists test.db-shm
          142  +  } {0}
          143  +  do_test 1.3.2.2 {
          144  +    code1 { sqlite3 db file:test.db?readonly_shm=1 }
          145  +    sql1 { SELECT * FROM t1 }
          146  +  } {a b c d e f g h i j k l}
          147  +  do_test 1.3.2.3 {
          148  +    code1 { db close }
          149  +    close [open test.db-shm w]
          150  +    file attributes test.db-shm -permissions r--r--r--
          151  +    code1 { sqlite3 db file:test.db?readonly_shm=1 }
          152  +    csql1 { SELECT * FROM t1 }
          153  +  } {1 {attempt to write a readonly database}}
          154  +  do_test 1.3.2.4 {
          155  +    code1 { sqlite3_extended_errcode db } 
          156  +  } {SQLITE_READONLY_RECOVERY}
          157  +}
          158  +
          159  +finish_test