/ 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 Unified Diffs Show Whitespace Changes Patch

Changes to ext/fts3/fts3.c.

3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
}
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  sqlite3Fts3PendingTermsClear((Fts3Table *)pVtab);
  return SQLITE_OK;
}

static const sqlite3_module fts3Module = {
  /* iVersion      */ 1,
  /* xCreate       */ fts3CreateMethod,
  /* xConnect      */ fts3ConnectMethod,
  /* xBestIndex    */ fts3BestIndexMethod,
  /* xDisconnect   */ fts3DisconnectMethod,
  /* xDestroy      */ fts3DestroyMethod,
  /* xOpen         */ fts3OpenMethod,
  /* xClose        */ fts3CloseMethod,







|







3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
}
static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  sqlite3Fts3PendingTermsClear((Fts3Table *)pVtab);
  return SQLITE_OK;
}

static const sqlite3_module fts3Module = {
  /* iVersion      */ 2,
  /* xCreate       */ fts3CreateMethod,
  /* xConnect      */ fts3ConnectMethod,
  /* xBestIndex    */ fts3BestIndexMethod,
  /* xDisconnect   */ fts3DisconnectMethod,
  /* xDestroy      */ fts3DestroyMethod,
  /* xOpen         */ fts3OpenMethod,
  /* xClose        */ fts3CloseMethod,

Changes to src/attach.c.

66
67
68
69
70
71
72



73
74



75
76
77
78
79
80
81
...
120
121
122
123
124
125
126
127








128


129
130
131
132
133
134
135
  sqlite3_value **argv
){
  int i;
  int rc = 0;
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zName;
  const char *zFile;



  Db *aNew;
  char *zErrDyn = 0;




  UNUSED_PARAMETER(NotUsed);

  zFile = (const char *)sqlite3_value_text(argv[0]);
  zName = (const char *)sqlite3_value_text(argv[1]);
  if( zFile==0 ) zFile = "";
  if( zName==0 ) zName = "";
................................................................................
  aNew = &db->aDb[db->nDb];
  memset(aNew, 0, sizeof(*aNew));

  /* Open the database file. If the btree is successfully opened, use
  ** it to obtain the database schema. At this point the schema may
  ** or may not be initialised.
  */
  rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0,








                        db->openFlags | SQLITE_OPEN_MAIN_DB);


  db->nDb++;
  if( rc==SQLITE_CONSTRAINT ){
    rc = SQLITE_ERROR;
    zErrDyn = sqlite3MPrintf(db, "database is already attached");
  }else if( rc==SQLITE_OK ){
    Pager *pPager;
    aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);







>
>
>


>
>
>







 







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







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  sqlite3_value **argv
){
  int i;
  int rc = 0;
  sqlite3 *db = sqlite3_context_db_handle(context);
  const char *zName;
  const char *zFile;
  char *zPath = 0;
  char *zErr = 0;
  unsigned int flags;
  Db *aNew;
  char *zErrDyn = 0;
  sqlite3_vfs *pVfs;
  const char *zVfs = db->pVfs->zName;       /* Name of default (main) VFS */
  int btflags = 0;

  UNUSED_PARAMETER(NotUsed);

  zFile = (const char *)sqlite3_value_text(argv[0]);
  zName = (const char *)sqlite3_value_text(argv[1]);
  if( zFile==0 ) zFile = "";
  if( zName==0 ) zName = "";
................................................................................
  aNew = &db->aDb[db->nDb];
  memset(aNew, 0, sizeof(*aNew));

  /* Open the database file. If the btree is successfully opened, use
  ** it to obtain the database schema. At this point the schema may
  ** or may not be initialised.
  */
  flags = db->openFlags;
  rc = sqlite3ParseUri(zVfs, zFile, &flags, &btflags, &pVfs, &zPath, &zErr);
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
    sqlite3_result_error(context, zErr, -1);
    sqlite3_free(zErr);
    return;
  }
  assert( pVfs );
  flags |= SQLITE_OPEN_MAIN_DB;
  rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, btflags, flags);
  sqlite3_free( zPath );
  db->nDb++;
  if( rc==SQLITE_CONSTRAINT ){
    rc = SQLITE_ERROR;
    zErrDyn = sqlite3MPrintf(db, "database is already attached");
  }else if( rc==SQLITE_OK ){
    Pager *pPager;
    aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);

Changes to src/btree.c.

1684
1685
1686
1687
1688
1689
1690

1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
....
1712
1713
1714
1715
1716
1717
1718

1719
1720
1721
1722
1723
1724
1725
....
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
** If the database is already opened in the same database connection
** and we are in shared cache mode, then the open will fail with an
** SQLITE_CONSTRAINT error.  We cannot allow two or more BtShared
** objects in the same database connection since doing so will lead
** to problems with locking.
*/
int sqlite3BtreeOpen(

  const char *zFilename,  /* Name of the file containing the BTree database */
  sqlite3 *db,            /* Associated database handle */
  Btree **ppBtree,        /* Pointer to new Btree object written here */
  int flags,              /* Options */
  int vfsFlags            /* Flags passed through to sqlite3_vfs.xOpen() */
){
  sqlite3_vfs *pVfs;             /* The VFS to use for this btree */
  BtShared *pBt = 0;             /* Shared part of btree structure */
  Btree *p;                      /* Handle to return */
  sqlite3_mutex *mutexOpen = 0;  /* Prevents a race condition. Ticket #3537 */
  int rc = SQLITE_OK;            /* Result code from this function */
  u8 nReserve;                   /* Byte of unused space on each page */
  unsigned char zDbHeader[100];  /* Database header content */

................................................................................
  const int isMemdb = 0;
#else
  const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
                       || (isTempDb && sqlite3TempInMemory(db));
#endif

  assert( db!=0 );

  assert( sqlite3_mutex_held(db->mutex) );
  assert( (flags&0xff)==flags );   /* flags fit in 8 bits */

  /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
  assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );

  /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
................................................................................
  }
  if( isMemdb ){
    flags |= BTREE_MEMORY;
  }
  if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
    vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
  }
  pVfs = db->pVfs;
  p = sqlite3MallocZero(sizeof(Btree));
  if( !p ){
    return SQLITE_NOMEM;
  }
  p->inTrans = TRANS_NONE;
  p->db = db;
#ifndef SQLITE_OMIT_SHARED_CACHE







>






<







 







>







 







<







1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697

1698
1699
1700
1701
1702
1703
1704
....
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
....
1731
1732
1733
1734
1735
1736
1737

1738
1739
1740
1741
1742
1743
1744
** If the database is already opened in the same database connection
** and we are in shared cache mode, then the open will fail with an
** SQLITE_CONSTRAINT error.  We cannot allow two or more BtShared
** objects in the same database connection since doing so will lead
** to problems with locking.
*/
int sqlite3BtreeOpen(
  sqlite3_vfs *pVfs,      /* VFS to use for this b-tree */
  const char *zFilename,  /* Name of the file containing the BTree database */
  sqlite3 *db,            /* Associated database handle */
  Btree **ppBtree,        /* Pointer to new Btree object written here */
  int flags,              /* Options */
  int vfsFlags            /* Flags passed through to sqlite3_vfs.xOpen() */
){

  BtShared *pBt = 0;             /* Shared part of btree structure */
  Btree *p;                      /* Handle to return */
  sqlite3_mutex *mutexOpen = 0;  /* Prevents a race condition. Ticket #3537 */
  int rc = SQLITE_OK;            /* Result code from this function */
  u8 nReserve;                   /* Byte of unused space on each page */
  unsigned char zDbHeader[100];  /* Database header content */

................................................................................
  const int isMemdb = 0;
#else
  const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
                       || (isTempDb && sqlite3TempInMemory(db));
#endif

  assert( db!=0 );
  assert( pVfs!=0 );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( (flags&0xff)==flags );   /* flags fit in 8 bits */

  /* Only a BTREE_SINGLE database can be BTREE_UNORDERED */
  assert( (flags & BTREE_UNORDERED)==0 || (flags & BTREE_SINGLE)!=0 );

  /* A BTREE_SINGLE database is always a temporary and/or ephemeral */
................................................................................
  }
  if( isMemdb ){
    flags |= BTREE_MEMORY;
  }
  if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
    vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
  }

  p = sqlite3MallocZero(sizeof(Btree));
  if( !p ){
    return SQLITE_NOMEM;
  }
  p->inTrans = TRANS_NONE;
  p->db = db;
#ifndef SQLITE_OMIT_SHARED_CACHE

Changes to src/btree.h.

38
39
40
41
42
43
44

45
46
47
48
49
50
51
..
56
57
58
59
60
61
62

63
64
65
66
67
68
69
*/
typedef struct Btree Btree;
typedef struct BtCursor BtCursor;
typedef struct BtShared BtShared;


int sqlite3BtreeOpen(

  const char *zFilename,   /* Name of database file to open */
  sqlite3 *db,             /* Associated database connection */
  Btree **ppBtree,         /* Return open Btree* here */
  int flags,               /* Flags */
  int vfsFlags             /* Flags passed through to VFS open */
);

................................................................................
** pager.h.
*/
#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
#define BTREE_NO_READLOCK   2  /* Omit readlocks on readonly files */
#define BTREE_MEMORY        4  /* This is an in-memory DB */
#define BTREE_SINGLE        8  /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED    16  /* Use of a hash implementation is OK */


int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
int sqlite3BtreeGetPageSize(Btree*);







>







 







>







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
*/
typedef struct Btree Btree;
typedef struct BtCursor BtCursor;
typedef struct BtShared BtShared;


int sqlite3BtreeOpen(
  sqlite3_vfs *pVfs,       /* VFS to use with this b-tree */
  const char *zFilename,   /* Name of database file to open */
  sqlite3 *db,             /* Associated database connection */
  Btree **ppBtree,         /* Return open Btree* here */
  int flags,               /* Flags */
  int vfsFlags             /* Flags passed through to VFS open */
);

................................................................................
** pager.h.
*/
#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
#define BTREE_NO_READLOCK   2  /* Omit readlocks on readonly files */
#define BTREE_MEMORY        4  /* This is an in-memory DB */
#define BTREE_SINGLE        8  /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED    16  /* Use of a hash implementation is OK */
#define BTREE_READONLYSHM  32  /* Read-only SHM access is acceptable */

int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
int sqlite3BtreeGetPageSize(Btree*);

Changes to src/build.c.

3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
    static const int flags = 
          SQLITE_OPEN_READWRITE |
          SQLITE_OPEN_CREATE |
          SQLITE_OPEN_EXCLUSIVE |
          SQLITE_OPEN_DELETEONCLOSE |
          SQLITE_OPEN_TEMP_DB;

    rc = sqlite3BtreeOpen(0, db, &pBt, 0, flags);
    if( rc!=SQLITE_OK ){
      sqlite3ErrorMsg(pParse, "unable to open a temporary database "
        "file for storing temporary tables");
      pParse->rc = rc;
      return 1;
    }
    db->aDb[1].pBt = pBt;







|







3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
    static const int flags = 
          SQLITE_OPEN_READWRITE |
          SQLITE_OPEN_CREATE |
          SQLITE_OPEN_EXCLUSIVE |
          SQLITE_OPEN_DELETEONCLOSE |
          SQLITE_OPEN_TEMP_DB;

    rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
    if( rc!=SQLITE_OK ){
      sqlite3ErrorMsg(pParse, "unable to open a temporary database "
        "file for storing temporary tables");
      pParse->rc = rc;
      return 1;
    }
    db->aDb[1].pBt = pBt;

Changes to src/global.c.

125
126
127
128
129
130
131
132


133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e0..e7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e8..ef    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* f0..f7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40   /* f8..ff    ........ */
};
#endif





/*
** The following singleton contains the global configuration for
** the SQLite library.
*/
SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
   1,                         /* bCoreMutex */
   SQLITE_THREADSAFE==1,      /* bFullMutex */

   0x7ffffffe,                /* mxStrlen */
   100,                       /* szLookaside */
   500,                       /* nLookaside */
   {0,0,0,0,0,0,0,0},         /* m */
   {0,0,0,0,0,0,0,0,0},       /* mutex */
   {0,0,0,0,0,0,0,0,0,0,0},   /* pcache */
   (void*)0,                  /* pHeap */







|
>
>









>







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e0..e7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e8..ef    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* f0..f7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40   /* f8..ff    ........ */
};
#endif

#ifndef SQLITE_USE_URI
# define  SQLITE_USE_URI 0
#endif

/*
** The following singleton contains the global configuration for
** the SQLite library.
*/
SQLITE_WSD struct Sqlite3Config sqlite3Config = {
   SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
   1,                         /* bCoreMutex */
   SQLITE_THREADSAFE==1,      /* bFullMutex */
   SQLITE_USE_URI,            /* bOpenUri */
   0x7ffffffe,                /* mxStrlen */
   100,                       /* szLookaside */
   500,                       /* nLookaside */
   {0,0,0,0,0,0,0,0},         /* m */
   {0,0,0,0,0,0,0,0,0},       /* mutex */
   {0,0,0,0,0,0,0,0,0,0,0},   /* pcache */
   (void*)0,                  /* pHeap */

Changes to src/main.c.

424
425
426
427
428
429
430





431
432
433
434
435
436
437
....
1793
1794
1795
1796
1797
1798
1799
1800
1801


















































































































































































































































1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813


1814



1815
1816
1817
1818
1819
1820
1821
....
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
....
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
....
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950










1951
1952
1953
1954
1955
1956
1957
....
2036
2037
2038
2039
2040
2041
2042

2043
2044
2045
2046
2047
2048
2049
....
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
      ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
      */
      typedef void(*LOGFUNC_t)(void*,int,const char*);
      sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
      sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
      break;
    }






    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);
................................................................................
}
#if defined(SQLITE_ENABLE_AUTO_PROFILE)
static void profile_sql(void *aux, const char *sql, u64 ns) {
#pragma unused(aux)
	fprintf(stderr, "Query: %s\n Execution Time: %llu ms\n", sql, ns / 1000000);
}
#endif

/*


















































































































































































































































** This routine does the work of opening a database on behalf of
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"  
** is UTF-8 encoded.
*/
static int openDatabase(
  const char *zFilename, /* Database filename UTF-8 encoded */
  sqlite3 **ppDb,        /* OUT: Returned database handle */
  unsigned flags,        /* Operational flags */
  const char *zVfs       /* Name of the VFS to use */
){
  sqlite3 *db;
  int rc;


  int isThreadsafe;




  *ppDb = 0;
#ifndef SQLITE_OMIT_AUTOINIT
  rc = sqlite3_initialize();
  if( rc ) return rc;
#endif

................................................................................
  */
  assert( SQLITE_OPEN_READONLY  == 0x01 );
  assert( SQLITE_OPEN_READWRITE == 0x02 );
  assert( SQLITE_OPEN_CREATE    == 0x04 );
  testcase( (1<<(flags&7))==0x02 ); /* READONLY */
  testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
  testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
  if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE;

  if( sqlite3GlobalConfig.bCoreMutex==0 ){
    isThreadsafe = 0;
  }else if( flags & SQLITE_OPEN_NOMUTEX ){
    isThreadsafe = 0;
  }else if( flags & SQLITE_OPEN_FULLMUTEX ){
    isThreadsafe = 1;
................................................................................
#endif
      ;
  sqlite3HashInit(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3HashInit(&db->aModule);
#endif

  db->pVfs = sqlite3_vfs_find(zVfs);
  if( !db->pVfs ){
    rc = SQLITE_ERROR;
    sqlite3Error(db, rc, "no such vfs: %s", zVfs);
    goto opendb_out;
  }

  /* Add the default collation sequence BINARY. BINARY works for both UTF-8
  ** and UTF-16, so add a version for each to avoid any unnecessary
  ** conversions. The only error that can occur here is a malloc() failure.
  */
  createCollation(db, "BINARY", SQLITE_UTF8, SQLITE_COLL_BINARY, 0,
                  binCollFunc, 0);
  createCollation(db, "BINARY", SQLITE_UTF16BE, SQLITE_COLL_BINARY, 0,
................................................................................
  db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
  assert( db->pDfltColl!=0 );

  /* Also add a UTF-8 case-insensitive collation sequence. */
  createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0,
                  nocaseCollatingFunc, 0);

  /* Open the backend database driver */
  db->openFlags = flags;
  rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0,










                        flags | SQLITE_OPEN_MAIN_DB);
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_IOERR_NOMEM ){
      rc = SQLITE_NOMEM;
    }
    sqlite3Error(db, rc, 0);
    goto opendb_out;
................................................................................
  /* Enable the lookaside-malloc subsystem */
  setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
                        sqlite3GlobalConfig.nLookaside);

  sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);

opendb_out:

  if( db ){
    assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
    sqlite3_mutex_leave(db->mutex);
  }
  rc = sqlite3_errcode(db);
  if( rc==SQLITE_NOMEM ){
    sqlite3_close(db);
................................................................................
}
int sqlite3_open_v2(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb,         /* OUT: SQLite db handle */
  int flags,              /* Flags */
  const char *zVfs        /* Name of VFS module to use */
){
  return openDatabase(filename, ppDb, flags, zVfs);
}

#ifndef SQLITE_OMIT_UTF16
/*
** Open a new database handle.
*/
int sqlite3_open16(







>
>
>
>
>







 









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







|


<
<
>
>
|
>
>
>







 







|







 







<
<
<
<
<
<
<







 







|

|
>
>
>
>
>
>
>
>
>
>







 







>







 







|







424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
....
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058


2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
....
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
....
2162
2163
2164
2165
2166
2167
2168







2169
2170
2171
2172
2173
2174
2175
....
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
....
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
....
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
      ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
      */
      typedef void(*LOGFUNC_t)(void*,int,const char*);
      sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
      sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
      break;
    }

    case SQLITE_CONFIG_URI: {
      sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
      break;
    }

    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);
................................................................................
}
#if defined(SQLITE_ENABLE_AUTO_PROFILE)
static void profile_sql(void *aux, const char *sql, u64 ns) {
#pragma unused(aux)
	fprintf(stderr, "Query: %s\n Execution Time: %llu ms\n", sql, ns / 1000000);
}
#endif

/*
** This function is used to parse both URIs and non-URI filenames passed by the
** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
** URIs specified as part of ATTACH statements.
**
** The first argument to this function is the name of the VFS to use (or
** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
** query parameter. The second argument contains the URI (or non-URI filename)
** itself. When this function is called the *pFlags variable should contain
** the default flags to open the database handle with. The value stored in
** *pFlags may be updated before returning if the URI filename contains 
** "cache=xxx" or "mode=xxx" query parameters.
**
** The third argument, pBtflags, points to an integer containing the flags
** that will be passed as the 5th argument to sqlite3BtreeOpen (BTREE_XXX
** flags). This value will be edited if the URI filename contains a
** "readonly_shm=1" or "readonly_shm=0" query parameter.
**
** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
** the VFS that should be used to open the database file. *pzFile is set to
** point to a buffer containing the name of the file to open. It is the 
** responsibility of the caller to eventually call sqlite3_free() to release
** this buffer.
**
** If an error occurs, then an SQLite error code is returned and *pzErrMsg
** may be set to point to a buffer containing an English language error 
** message. It is the responsibility of the caller to eventually release
** this buffer by calling sqlite3_free().
*/
int sqlite3ParseUri(
  const char *zDefaultVfs,        /* VFS to use if no "vfs=xxx" query option */
  const char *zUri,               /* Nul-terminated URI to parse */
  unsigned int *pFlags,           /* IN/OUT: SQLITE_OPEN_XXX flags */
  int *pBtflags,                  /* IN/OUT: BTREE_XXX flags */
  sqlite3_vfs **ppVfs,            /* OUT: VFS to use */ 
  char **pzFile,                  /* OUT: Filename component of URI */
  char **pzErrMsg                 /* OUT: Error message (if rc!=SQLITE_OK) */
){
  int rc = SQLITE_OK;
  unsigned int flags = *pFlags;
  const char *zVfs = zDefaultVfs;
  char *zFile;
  char c;
  int nUri = sqlite3Strlen30(zUri);

  assert( *pzErrMsg==0 );

  if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri) 
   && nUri>=5 && memcmp(zUri, "file:", 5)==0 
  ){
    char *zOpt;
    int eState;                   /* Parser state when parsing URI */
    int iIn;                      /* Input character index */
    int iOut = 0;                 /* Output character index */
    int nByte = nUri+2;           /* Bytes of space to allocate */

    /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen 
    ** method that there may be extra parameters following the file-name.  */
    flags |= SQLITE_OPEN_URI;

    for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
    zFile = sqlite3_malloc(nByte);
    if( !zFile ) return SQLITE_NOMEM;

    /* Discard the scheme and authority segments of the URI. */
    if( zUri[5]=='/' && zUri[6]=='/' ){
      iIn = 7;
      while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;

      if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
        *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s", 
            iIn-7, &zUri[7]);
        rc = SQLITE_ERROR;
        goto parse_uri_out;
      }
    }else{
      iIn = 5;
    }

    /* Copy the filename and any query parameters into the zFile buffer. 
    ** Decode %HH escape codes along the way. 
    **
    ** Within this loop, variable eState may be set to 0, 1 or 2, depending
    ** on the parsing context. As follows:
    **
    **   0: Parsing file-name.
    **   1: Parsing name section of a name=value query parameter.
    **   2: Parsing value section of a name=value query parameter.
    */
    eState = 0;
    while( (c = zUri[iIn])!=0 && c!='#' ){
      iIn++;
      if( c=='%' 
       && sqlite3Isxdigit(zUri[iIn]) 
       && sqlite3Isxdigit(zUri[iIn+1]) 
      ){
        int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
        octet += sqlite3HexToInt(zUri[iIn++]);

        assert( octet>=0 && octet<256 );
        if( octet==0 ){
          /* This branch is taken when "%00" appears within the URI. In this
          ** case we ignore all text in the remainder of the path, name or
          ** value currently being parsed. So ignore the current character
          ** and skip to the next "?", "=" or "&", as appropriate. */
          while( (c = zUri[iIn])!=0 && c!='#' 
              && (eState!=0 || c!='?')
              && (eState!=1 || (c!='=' && c!='&'))
              && (eState!=2 || c!='&')
          ){
            iIn++;
          }
          continue;
        }
        c = octet;
      }else if( eState==1 && (c=='&' || c=='=') ){
        if( zFile[iOut-1]==0 ){
          /* An empty option name. Ignore this option altogether. */
          while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
          continue;
        }
        if( c=='&' ){
          zFile[iOut++] = '\0';
        }else{
          eState = 2;
        }
        c = 0;
      }else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
        c = 0;
        eState = 1;
      }
      zFile[iOut++] = c;
    }
    if( eState==1 ) zFile[iOut++] = '\0';
    zFile[iOut++] = '\0';
    zFile[iOut++] = '\0';

    /* Check if there were any options specified that should be interpreted 
    ** here. Options that are interpreted here include "vfs" and those that
    ** correspond to flags that may be passed to the sqlite3_open_v2()
    ** method. */
    zOpt = &zFile[sqlite3Strlen30(zFile)+1];
    while( zOpt[0] ){
      int nOpt = sqlite3Strlen30(zOpt);
      char *zVal = &zOpt[nOpt+1];
      int nVal = sqlite3Strlen30(zVal);

      if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
        zVfs = zVal;
      }else if( nOpt==12 && memcmp("readonly_shm", zOpt, 12)==0 ){
        if( sqlite3Atoi(zVal) ){
          *pBtflags |= BTREE_READONLYSHM;
        }else{
          *pBtflags &= ~BTREE_READONLYSHM;
        }
      }else{
        struct OpenMode {
          const char *z;
          int mode;
        } *aMode = 0;
        char *zModeType;
        int mask;
        int limit;

        if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
          static struct OpenMode aCacheMode[] = {
            { "shared",  SQLITE_OPEN_SHAREDCACHE },
            { "private", SQLITE_OPEN_PRIVATECACHE },
            { 0, 0 }
          };

          mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
          aMode = aCacheMode;
          limit = mask;
          zModeType = "cache";
        }
        if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
          static struct OpenMode aOpenMode[] = {
            { "ro",  SQLITE_OPEN_READONLY },
            { "rw",  SQLITE_OPEN_READWRITE }, 
            { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
            { 0, 0 }
          };

          mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
          aMode = aOpenMode;
          limit = mask & flags;
          zModeType = "access";
        }

        if( aMode ){
          int i;
          int mode = 0;
          for(i=0; aMode[i].z; i++){
            const char *z = aMode[i].z;
            if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
              mode = aMode[i].mode;
              break;
            }
          }
          if( mode==0 ){
            *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
            rc = SQLITE_ERROR;
            goto parse_uri_out;
          }
          if( mode>limit ){
            *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
                                        zModeType, zVal);
            rc = SQLITE_PERM;
            goto parse_uri_out;
          }
          flags = (flags & ~mask) | mode;
        }
      }

      zOpt = &zVal[nVal+1];
    }

  }else{
    zFile = sqlite3_malloc(nUri+2);
    if( !zFile ) return SQLITE_NOMEM;
    memcpy(zFile, zUri, nUri);
    zFile[nUri] = '\0';
    zFile[nUri+1] = '\0';
  }

  *ppVfs = sqlite3_vfs_find(zVfs);
  if( *ppVfs==0 ){
    *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
    rc = SQLITE_ERROR;
  }
 parse_uri_out:
  if( rc!=SQLITE_OK ){
    sqlite3_free(zFile);
    zFile = 0;
  }
  *pFlags = flags;
  *pzFile = zFile;
  return rc;
}


/*
** This routine does the work of opening a database on behalf of
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"  
** is UTF-8 encoded.
*/
static int openDatabase(
  const char *zFilename, /* Database filename UTF-8 encoded */
  sqlite3 **ppDb,        /* OUT: Returned database handle */
  unsigned int flags,    /* Operational flags */
  const char *zVfs       /* Name of the VFS to use */
){


  sqlite3 *db;                    /* Store allocated handle here */
  int rc;                         /* Return code */
  int isThreadsafe;               /* True for threadsafe connections */
  char *zOpen = 0;                /* Filename argument to pass to BtreeOpen() */
  char *zErrMsg = 0;              /* Error message from sqlite3ParseUri() */
  int btflags = 0;                /* Mask of BTREE_XXX flags */

  *ppDb = 0;
#ifndef SQLITE_OMIT_AUTOINIT
  rc = sqlite3_initialize();
  if( rc ) return rc;
#endif

................................................................................
  */
  assert( SQLITE_OPEN_READONLY  == 0x01 );
  assert( SQLITE_OPEN_READWRITE == 0x02 );
  assert( SQLITE_OPEN_CREATE    == 0x04 );
  testcase( (1<<(flags&7))==0x02 ); /* READONLY */
  testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
  testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
  if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT;

  if( sqlite3GlobalConfig.bCoreMutex==0 ){
    isThreadsafe = 0;
  }else if( flags & SQLITE_OPEN_NOMUTEX ){
    isThreadsafe = 0;
  }else if( flags & SQLITE_OPEN_FULLMUTEX ){
    isThreadsafe = 1;
................................................................................
#endif
      ;
  sqlite3HashInit(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3HashInit(&db->aModule);
#endif








  /* Add the default collation sequence BINARY. BINARY works for both UTF-8
  ** and UTF-16, so add a version for each to avoid any unnecessary
  ** conversions. The only error that can occur here is a malloc() failure.
  */
  createCollation(db, "BINARY", SQLITE_UTF8, SQLITE_COLL_BINARY, 0,
                  binCollFunc, 0);
  createCollation(db, "BINARY", SQLITE_UTF16BE, SQLITE_COLL_BINARY, 0,
................................................................................
  db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
  assert( db->pDfltColl!=0 );

  /* Also add a UTF-8 case-insensitive collation sequence. */
  createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0,
                  nocaseCollatingFunc, 0);

  /* Parse the filename/URI argument. */
  db->openFlags = flags;
  rc = sqlite3ParseUri(
      zVfs, zFilename, &flags, &btflags, &db->pVfs, &zOpen, &zErrMsg);
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
    sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
    sqlite3_free(zErrMsg);
    goto opendb_out;
  }

  /* Open the backend database driver */
  rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, btflags,
                        flags | SQLITE_OPEN_MAIN_DB);
  if( rc!=SQLITE_OK ){
    if( rc==SQLITE_IOERR_NOMEM ){
      rc = SQLITE_NOMEM;
    }
    sqlite3Error(db, rc, 0);
    goto opendb_out;
................................................................................
  /* Enable the lookaside-malloc subsystem */
  setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
                        sqlite3GlobalConfig.nLookaside);

  sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);

opendb_out:
  sqlite3_free(zOpen);
  if( db ){
    assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
    sqlite3_mutex_leave(db->mutex);
  }
  rc = sqlite3_errcode(db);
  if( rc==SQLITE_NOMEM ){
    sqlite3_close(db);
................................................................................
}
int sqlite3_open_v2(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb,         /* OUT: SQLite db handle */
  int flags,              /* Flags */
  const char *zVfs        /* Name of VFS module to use */
){
  return openDatabase(filename, ppDb, (unsigned int)flags, zVfs);
}

#ifndef SQLITE_OMIT_UTF16
/*
** Open a new database handle.
*/
int sqlite3_open16(

Changes to src/malloc.c.

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







|










|







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

Changes to src/os_unix.c.

208
209
210
211
212
213
214

215
216
217
218
219
220
221
....
3469
3470
3471
3472
3473
3474
3475




3476
3477
3478
3479
3480
3481
3482
....
3771
3772
3773
3774
3775
3776
3777

3778
3779
3780
3781
3782
3783
3784
....
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039

4040
4041
4042
4043







4044
4045
4046



4047
4048
4049
4050
4051
4052
4053
4054
4055










4056
4057
4058
4059
4060
4061
4062
....
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
  unsigned char eFileLock;            /* The type of lock held on this fd */
  unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */

  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_ENABLE_LOCKING_STYLE
  int openFlags;                      /* The flags specified at open() */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
  unsigned fsFlags;                   /* cached details from statfs() */
#endif
................................................................................
    case SQLITE_FCNTL_CHUNK_SIZE: {
      ((unixFile*)id)->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
      return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
    }




#ifndef NDEBUG
    /* The pager calls this method to signal that it has done
    ** a rollback and that the database is therefore unchanged and
    ** it hence it is OK for the transaction change counter to be
    ** unchanged.
    */
    case SQLITE_FCNTL_DB_UNCHANGED: {
................................................................................
  char *zFilename;           /* Name of the mmapped file */
  int h;                     /* Open file descriptor */
  int szRegion;              /* Size of shared-memory regions */
  int nRegion;               /* Size of array apRegion */
  char **apRegion;           /* Array of mapped shared-memory regions */
  int nRef;                  /* Number of unixShm objects pointing to this */
  unixShm *pFirst;           /* All unixShm objects pointing to this */

#ifdef SQLITE_DEBUG
  u8 exclMask;               /* Mask of exclusive locks held */
  u8 sharedMask;             /* Mask of shared locks held */
  u8 nextShmId;              /* Next available unixShm.id value */
#endif
};

................................................................................
    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
    if( pShmNode->mutex==0 ){
      rc = SQLITE_NOMEM;
      goto shm_open_err;
    }

    if( pInode->bProcessLock==0 ){
      pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
                               (sStat.st_mode & 0777));
      if( pShmNode->h<0 ){
        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
        goto shm_open_err;
      }

  
      /* Check to see if another process is holding the dead-man switch.
      ** If not, truncate the file to zero length. 
      */







      rc = SQLITE_OK;
      if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
        if( robust_ftruncate(pShmNode->h, 0) ){



          rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
        }
      }
      if( rc==SQLITE_OK ){
        rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
      }
      if( rc ) goto shm_open_err;
    }
  }











  /* Make the new connection a child of the unixShmNode */
  p->pShmNode = pShmNode;
#ifdef SQLITE_DEBUG
  p->id = pShmNode->nextShmId++;
#endif
  pShmNode->nRef++;
................................................................................
      rc = SQLITE_IOERR_NOMEM;
      goto shmpage_out;
    }
    pShmNode->apRegion = apNew;
    while(pShmNode->nRegion<=iRegion){
      void *pMem;
      if( pShmNode->h>=0 ){
        pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE, 
            MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
        );
        if( pMem==MAP_FAILED ){
          rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
          goto shmpage_out;
        }
      }else{







>







 







>
>
>
>







 







>







 







|
|




>


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









>
>
>
>
>
>
>
>
>
>







 







|







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
....
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
....
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
....
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048

4049
4050
4051
4052
4053
4054
4055
4056
4057
4058

4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
....
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
  unsigned char eFileLock;            /* The type of lock held on this fd */
  unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
  int lastErrno;                      /* The unix errno from last I/O error */
  void *lockingContext;               /* Locking style specific state */
  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
  const char *zPath;                  /* Name of the file */
  unixShm *pShm;                      /* Shared memory segment information */
  int readOnlyShm;                    /* True to open shared-memory read-only */
  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_ENABLE_LOCKING_STYLE
  int openFlags;                      /* The flags specified at open() */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
  unsigned fsFlags;                   /* cached details from statfs() */
#endif
................................................................................
    case SQLITE_FCNTL_CHUNK_SIZE: {
      ((unixFile*)id)->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
      return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
    }
    case SQLITE_FCNTL_READONLY_SHM: {
      ((unixFile*)id)->readOnlyShm = (pArg!=0);
      return SQLITE_OK;
    }
#ifndef NDEBUG
    /* The pager calls this method to signal that it has done
    ** a rollback and that the database is therefore unchanged and
    ** it hence it is OK for the transaction change counter to be
    ** unchanged.
    */
    case SQLITE_FCNTL_DB_UNCHANGED: {
................................................................................
  char *zFilename;           /* Name of the mmapped file */
  int h;                     /* Open file descriptor */
  int szRegion;              /* Size of shared-memory regions */
  int nRegion;               /* Size of array apRegion */
  char **apRegion;           /* Array of mapped shared-memory regions */
  int nRef;                  /* Number of unixShm objects pointing to this */
  unixShm *pFirst;           /* All unixShm objects pointing to this */
  u8 readOnly;               /* True if this is a read-only mapping */
#ifdef SQLITE_DEBUG
  u8 exclMask;               /* Mask of exclusive locks held */
  u8 sharedMask;             /* Mask of shared locks held */
  u8 nextShmId;              /* Next available unixShm.id value */
#endif
};

................................................................................
    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
    if( pShmNode->mutex==0 ){
      rc = SQLITE_NOMEM;
      goto shm_open_err;
    }

    if( pInode->bProcessLock==0 ){
      int flags = (pDbFd->readOnlyShm ? O_RDONLY : O_RDWR|O_CREAT);
      pShmNode->h = robust_open(zShmFilename, flags, (sStat.st_mode & 0777));
      if( pShmNode->h<0 ){
        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
        goto shm_open_err;
      }
      pShmNode->readOnly = pDbFd->readOnlyShm;
  
      /* Check to see if another process is holding the dead-man switch.

      ** If not, zero the first few bytes of the shared-memory file to make
      ** sure it is not mistaken for valid by code in wal.c. Except, if this 
      ** is a read-only connection to the shared-memory then it is not possible
      ** to check check if another process is holding a read-lock on the DMS
      ** byte, as we cannot attempt a write-lock via a read-only file 
      ** descriptor. So in this case, we just assume the shared-memory 
      ** contents are Ok and proceed.  */
      if( pShmNode->readOnly==0 ){
        rc = SQLITE_OK;
        if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){

          if( pDbFd->readOnlyShm ){
            rc = SQLITE_IOERR_SHMOPEN;
          }else if( 4!=osWrite(pShmNode->h, "\00\00\00\00", 4) ){
            rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
          }
        }
        if( rc==SQLITE_OK ){
          rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
        }
        if( rc ) goto shm_open_err;
      }
    }
  }

  /* If the unixShmNode is read-only, but SQLITE_FCNTL_READONLY_SHM has not
  ** been set for file-descriptor pDbFd, return an error. The wal.c module
  ** will then call this function again with SQLITE_FCNTL_READONLY_SHM set.
  */
  else if( pShmNode->readOnly && !pDbFd->readOnlyShm ){
    rc = SQLITE_IOERR_SHMOPEN;
    goto shm_open_err;
  }

  /* Make the new connection a child of the unixShmNode */
  p->pShmNode = pShmNode;
#ifdef SQLITE_DEBUG
  p->id = pShmNode->nextShmId++;
#endif
  pShmNode->nRef++;
................................................................................
      rc = SQLITE_IOERR_NOMEM;
      goto shmpage_out;
    }
    pShmNode->apRegion = apNew;
    while(pShmNode->nRegion<=iRegion){
      void *pMem;
      if( pShmNode->h>=0 ){
        pMem = mmap(0, szRegion, PROT_READ|(!pShmNode->readOnly?PROT_WRITE:0), 
            MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
        );
        if( pMem==MAP_FAILED ){
          rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
          goto shmpage_out;
        }
      }else{

Changes to src/os_win.c.

2460
2461
2462
2463
2464
2465
2466







2467
2468
2469
2470
2471
2472
2473
  return SQLITE_OK;
#endif

#if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
  int nByte;
  void *zConverted;
  char *zOut;








  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. This function could fail if, for example, the
  ** current working directory has been unlinked.
  */
  SimulateIOError( return SQLITE_ERROR );







>
>
>
>
>
>
>







2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
  return SQLITE_OK;
#endif

#if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
  int nByte;
  void *zConverted;
  char *zOut;

  /* If this path name begins with "/X:", where "X" is any alphabetic
  ** character, discard the initial "/" from the pathname.
  */
  if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
    zRelative++;
  }

  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. This function could fail if, for example, the
  ** current working directory has been unlinked.
  */
  SimulateIOError( return SQLITE_ERROR );

Changes to src/pager.c.

616
617
618
619
620
621
622

623
624
625
626
627
628
629
....
3013
3014
3015
3016
3017
3018
3019

3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
....
4295
4296
4297
4298
4299
4300
4301


4302
4303
4304
4305
4306
4307
4308
....
4325
4326
4327
4328
4329
4330
4331

4332
4333
4334
4335
4336
4337
4338
4339






4340
4341
4342
4343
4344
4345
4346
....
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
....
4387
4388
4389
4390
4391
4392
4393
4394
4395

4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406

4407
4408
4409
4410
4411
4412
4413
  u8 noSync;                  /* Do not sync the journal if true */
  u8 fullSync;                /* Do extra syncs of the journal for robustness */
  u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
  u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
  u8 tempFile;                /* zFilename is a temporary file */
  u8 readOnly;                /* True for a read-only database */
  u8 memDb;                   /* True to inhibit all file I/O */


  /**************************************************************************
  ** The following block contains those class members that change during
  ** routine opertion.  Class members not in this block are either fixed
  ** when the pager is first created or else only change when there is a
  ** significant mode change (such as changing the page_size, locking_mode,
  ** or the journal_mode).  From another view, these class members describe
................................................................................
** makes a snapshot of the database at the current point in time and preserves
** that snapshot for use by the reader in spite of concurrently changes by
** other writers or checkpointers.
*/
static int pagerBeginReadTransaction(Pager *pPager){
  int rc;                         /* Return code */
  int changed = 0;                /* True if cache must be reset */


  assert( pagerUseWal(pPager) );
  assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );

  /* sqlite3WalEndReadTransaction() was not called for the previous
  ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
  ** are in locking_mode=NORMAL and EndRead() was previously called,
  ** the duplicate call is harmless.
  */
  sqlite3WalEndReadTransaction(pPager->pWal);

  rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
  if( rc!=SQLITE_OK || changed ){
    pager_reset(pPager);
  }

  return rc;
}
#endif
................................................................................
  int journalFileSize;     /* Bytes to allocate for each journal fd */
  char *zPathname = 0;     /* Full path to database file */
  int nPathname = 0;       /* Number of bytes in zPathname */
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;  /* True to omit read-lock */
  int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
  u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */



  /* Figure out how much space is required for each journal file-handle
  ** (there are two of them, the main journal and the sub-journal). This
  ** is the maximum space required for an in-memory journal file handle 
  ** and a regular journal file-handle. Note that a "regular journal-handle"
  ** may be a wrapper capable of caching the first portion of the journal
  ** file in memory to implement the atomic-write optimization (see 
................................................................................
#endif

  /* Compute and store the full pathname in an allocated buffer pointed
  ** to by zPathname, length nPathname. Or, if this is a temporary file,
  ** leave both nPathname and zPathname set to 0.
  */
  if( zFilename && zFilename[0] ){

    nPathname = pVfs->mxPathname+1;
    zPathname = sqlite3Malloc(nPathname*2);
    if( zPathname==0 ){
      return SQLITE_NOMEM;
    }
    zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
    rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
    nPathname = sqlite3Strlen30(zPathname);






    if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
      /* This branch is taken when the journal path required by
      ** the database being opened will be more than pVfs->mxPathname
      ** bytes in length. This means the database cannot be opened,
      ** as it will not be possible to open the journal file or even
      ** check for a hot-journal before reading.
      */
................................................................................
  **     Journal file name               (nPathname+8+1 bytes)
  */
  pPtr = (u8 *)sqlite3MallocZero(
    ROUND8(sizeof(*pPager)) +      /* Pager structure */
    ROUND8(pcacheSize) +           /* PCache object */
    ROUND8(pVfs->szOsFile) +       /* The main db file */
    journalFileSize * 2 +          /* The two journal files */ 
    nPathname + 1 +                /* zFilename */
    nPathname + 8 + 1              /* zJournal */
#ifndef SQLITE_OMIT_WAL
    + nPathname + 4 + 1              /* zWal */
#endif
  );
  assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
  if( !pPtr ){
................................................................................
  pPager->jfd =  (sqlite3_file*)(pPtr += journalFileSize);
  pPager->zFilename =    (char*)(pPtr += journalFileSize);
  assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );

  /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
  if( zPathname ){
    assert( nPathname>0 );
    pPager->zJournal =   (char*)(pPtr += nPathname + 1);
    memcpy(pPager->zFilename, zPathname, nPathname);

    memcpy(pPager->zJournal, zPathname, nPathname);
    memcpy(&pPager->zJournal[nPathname], "-journal", 8);
#ifndef SQLITE_OMIT_WAL
    pPager->zWal = &pPager->zJournal[nPathname+8+1];
    memcpy(pPager->zWal, zPathname, nPathname);
    memcpy(&pPager->zWal[nPathname], "-wal", 4);
#endif
    sqlite3_free(zPathname);
  }
  pPager->pVfs = pVfs;
  pPager->vfsFlags = vfsFlags;


  /* Open the pager file.
  */
  if( zFilename && zFilename[0] ){
    int fout = 0;                    /* VFS flags returned by xOpen() */
    rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
    assert( !memDb );







>







 







>









|

|







 







>
>







 







>








>
>
>
>
>
>







 







|







 







|

>











>







616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
....
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
....
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
....
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
....
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
....
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
  u8 noSync;                  /* Do not sync the journal if true */
  u8 fullSync;                /* Do extra syncs of the journal for robustness */
  u8 ckptSyncFlags;           /* SYNC_NORMAL or SYNC_FULL for checkpoint */
  u8 syncFlags;               /* SYNC_NORMAL or SYNC_FULL otherwise */
  u8 tempFile;                /* zFilename is a temporary file */
  u8 readOnly;                /* True for a read-only database */
  u8 memDb;                   /* True to inhibit all file I/O */
  u8 readOnlyShm;             /* True if read-only shm access is Ok */

  /**************************************************************************
  ** The following block contains those class members that change during
  ** routine opertion.  Class members not in this block are either fixed
  ** when the pager is first created or else only change when there is a
  ** significant mode change (such as changing the page_size, locking_mode,
  ** or the journal_mode).  From another view, these class members describe
................................................................................
** makes a snapshot of the database at the current point in time and preserves
** that snapshot for use by the reader in spite of concurrently changes by
** other writers or checkpointers.
*/
static int pagerBeginReadTransaction(Pager *pPager){
  int rc;                         /* Return code */
  int changed = 0;                /* True if cache must be reset */
  Wal *pWal = pPager->pWal;

  assert( pagerUseWal(pPager) );
  assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );

  /* sqlite3WalEndReadTransaction() was not called for the previous
  ** transaction in locking_mode=EXCLUSIVE.  So call it now.  If we
  ** are in locking_mode=NORMAL and EndRead() was previously called,
  ** the duplicate call is harmless.
  */
  sqlite3WalEndReadTransaction(pWal);

  rc = sqlite3WalBeginReadTransaction(pWal, pPager->readOnlyShm, &changed);
  if( rc!=SQLITE_OK || changed ){
    pager_reset(pPager);
  }

  return rc;
}
#endif
................................................................................
  int journalFileSize;     /* Bytes to allocate for each journal fd */
  char *zPathname = 0;     /* Full path to database file */
  int nPathname = 0;       /* Number of bytes in zPathname */
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */
  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;  /* True to omit read-lock */
  int pcacheSize = sqlite3PcacheSize();       /* Bytes to allocate for PCache */
  u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;  /* Default page size */
  const char *zUri = 0;    /* URI args to copy */
  int nUri = 0;            /* Number of bytes of URI args at *zUri */

  /* Figure out how much space is required for each journal file-handle
  ** (there are two of them, the main journal and the sub-journal). This
  ** is the maximum space required for an in-memory journal file handle 
  ** and a regular journal file-handle. Note that a "regular journal-handle"
  ** may be a wrapper capable of caching the first portion of the journal
  ** file in memory to implement the atomic-write optimization (see 
................................................................................
#endif

  /* Compute and store the full pathname in an allocated buffer pointed
  ** to by zPathname, length nPathname. Or, if this is a temporary file,
  ** leave both nPathname and zPathname set to 0.
  */
  if( zFilename && zFilename[0] ){
    const char *z;
    nPathname = pVfs->mxPathname+1;
    zPathname = sqlite3Malloc(nPathname*2);
    if( zPathname==0 ){
      return SQLITE_NOMEM;
    }
    zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
    rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
    nPathname = sqlite3Strlen30(zPathname);
    z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
    while( *z ){
      z += sqlite3Strlen30(z)+1;
      z += sqlite3Strlen30(z)+1;
    }
    nUri = &z[1] - zUri;
    if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
      /* This branch is taken when the journal path required by
      ** the database being opened will be more than pVfs->mxPathname
      ** bytes in length. This means the database cannot be opened,
      ** as it will not be possible to open the journal file or even
      ** check for a hot-journal before reading.
      */
................................................................................
  **     Journal file name               (nPathname+8+1 bytes)
  */
  pPtr = (u8 *)sqlite3MallocZero(
    ROUND8(sizeof(*pPager)) +      /* Pager structure */
    ROUND8(pcacheSize) +           /* PCache object */
    ROUND8(pVfs->szOsFile) +       /* The main db file */
    journalFileSize * 2 +          /* The two journal files */ 
    nPathname + 1 + nUri +         /* zFilename */
    nPathname + 8 + 1              /* zJournal */
#ifndef SQLITE_OMIT_WAL
    + nPathname + 4 + 1              /* zWal */
#endif
  );
  assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
  if( !pPtr ){
................................................................................
  pPager->jfd =  (sqlite3_file*)(pPtr += journalFileSize);
  pPager->zFilename =    (char*)(pPtr += journalFileSize);
  assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );

  /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
  if( zPathname ){
    assert( nPathname>0 );
    pPager->zJournal =   (char*)(pPtr += nPathname + 1 + nUri);
    memcpy(pPager->zFilename, zPathname, nPathname);
    memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
    memcpy(pPager->zJournal, zPathname, nPathname);
    memcpy(&pPager->zJournal[nPathname], "-journal", 8);
#ifndef SQLITE_OMIT_WAL
    pPager->zWal = &pPager->zJournal[nPathname+8+1];
    memcpy(pPager->zWal, zPathname, nPathname);
    memcpy(&pPager->zWal[nPathname], "-wal", 4);
#endif
    sqlite3_free(zPathname);
  }
  pPager->pVfs = pVfs;
  pPager->vfsFlags = vfsFlags;
  pPager->readOnlyShm = (flags & PAGER_READONLYSHM)!=0;

  /* Open the pager file.
  */
  if( zFilename && zFilename[0] ){
    int fout = 0;                    /* VFS flags returned by xOpen() */
    rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
    assert( !memDb );

Changes to src/pager.h.

56
57
58
59
60
61
62

63
64
65
66
67
68
69
** Allowed values for the flags parameter to sqlite3PagerOpen().
**
** NOTE: These values must match the corresponding BTREE_ values in btree.h.
*/
#define PAGER_OMIT_JOURNAL  0x0001    /* Do not use a rollback journal */
#define PAGER_NO_READLOCK   0x0002    /* Omit readlocks on readonly files */
#define PAGER_MEMORY        0x0004    /* In-memory database */


/*
** Valid values for the second argument to sqlite3PagerLockingMode().
*/
#define PAGER_LOCKINGMODE_QUERY      -1
#define PAGER_LOCKINGMODE_NORMAL      0
#define PAGER_LOCKINGMODE_EXCLUSIVE   1







>







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

/*
** Valid values for the second argument to sqlite3PagerLockingMode().
*/
#define PAGER_LOCKINGMODE_QUERY      -1
#define PAGER_LOCKINGMODE_NORMAL      0
#define PAGER_LOCKINGMODE_EXCLUSIVE   1

Changes to src/sqlite.h.in.

450
451
452
453
454
455
456



457
458
459
460
461
462
463
...
476
477
478
479
480
481
482

483
484
485
486
487
488
489
...
728
729
730
731
732
733
734





















735
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750
...
753
754
755
756
757
758
759

760
761
762
763
764
765
766
....
1423
1424
1425
1426
1427
1428
1429












1430
1431
1432
1433
1434
1435
1436
....
1441
1442
1443
1444
1445
1446
1447

1448
1449
1450
1451
1452
1453
1454
....
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
....
2382
2383
2384
2385
2386
2387
2388
2389





2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401






























2402
2403
2404
2405















































































2406
2407
2408
2409
2410
2411
2412
....
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
....
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447

6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
#define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
#define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
#define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))




/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the xOpen method of the
** [sqlite3_vfs] object.
................................................................................
#define SQLITE_OPEN_SUBJOURNAL       0x00002000  /* VFS only */
#define SQLITE_OPEN_MASTER_JOURNAL   0x00004000  /* VFS only */
#define SQLITE_OPEN_NOMUTEX          0x00008000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_FULLMUTEX        0x00010000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_SHAREDCACHE      0x00020000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_PRIVATECACHE     0x00040000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_WAL              0x00080000  /* VFS only */


/* Reserved:                         0x00F00000 */

/*
** CAPI3REF: Device Characteristics
**
** The xDeviceCharacteristics method of the [sqlite3_io_methods]
................................................................................
** when the database connection has [PRAGMA synchronous] set to OFF.)^
** Some specialized VFSes need this signal in order to operate correctly
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  





















*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
#define SQLITE_SET_LOCKPROXYFILE      3
#define SQLITE_LAST_ERRNO             4
#define SQLITE_FCNTL_SIZE_HINT        5
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7
#define SQLITE_FCNTL_SYNC_OMITTED     8



/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
................................................................................
**
** Mutexes are created using [sqlite3_mutex_alloc()].
*/
typedef struct sqlite3_mutex sqlite3_mutex;

/*
** CAPI3REF: OS Interface Object

**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system.  The "vfs"
** in the name of the object stands for "virtual file system".
**
** The value of the iVersion field is initially 1 but may be larger in
** future versions of SQLite.  Additional fields may be appended to this
................................................................................
** [extended result code].  ^The third parameter passed to the logger is
** log message after formatting via [sqlite3_snprintf()].
** The SQLite logging interface is not reentrant; the logger function
** supplied by the application must not invoke any SQLite interface.
** In a multi-threaded application, the application-defined logger
** function must be threadsafe. </dd>
**












** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
#define SQLITE_CONFIG_SERIALIZED    3  /* nil */
#define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
................................................................................
#define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ 
#define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
#define SQLITE_CONFIG_PCACHE       14  /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_GETPCACHE    15  /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */


/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
**
................................................................................
**
*/
void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);

/*
** CAPI3REF: Opening A New Database Connection
**
** ^These routines open an SQLite database file whose name is given by the
** filename argument. ^The filename argument is interpreted as UTF-8 for
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
** order for sqlite3_open16(). ^(A [database connection] handle is usually
** returned in *ppDb, even if an error occurs.  The only exception is that
** if SQLite is unable to allocate memory to hold the [sqlite3] object,
** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
** object.)^ ^(If the database is opened (and/or created) successfully, then
................................................................................
** in the serialized [threading mode] unless single-thread was
** previously selected at compile-time or start-time.
** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
** eligible to use [shared cache mode], regardless of whether or not shared
** cache is enabled using [sqlite3_enable_shared_cache()].  ^The
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
** participate in [shared cache mode] even if it is enabled.
**





** ^If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection.  ^This in-memory database will vanish when
** the database connection is closed.  Future versions of SQLite might
** make use of additional special filenames that begin with the ":" character.
** It is recommended that when a database filename actually does begin with
** a ":" character you should prefix the filename with a pathname such as
** "./" to avoid ambiguity.
**
** ^If the filename is an empty string, then a private, temporary
** on-disk database will be created.  ^This private database will be
** automatically deleted as soon as the database connection is closed.
**






























** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that
** the new database connection should use.  ^If the fourth parameter is
** a NULL pointer then the default [sqlite3_vfs] object is used.















































































**
** <b>Note to Windows users:</b>  The encoding used for the filename argument
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
** codepage is currently defined.  Filenames containing international
** characters must be converted to UTF-8 prior to passing them into
** sqlite3_open() or sqlite3_open_v2().
*/
................................................................................
  int (*xSync)(sqlite3_vtab *pVTab);
  int (*xCommit)(sqlite3_vtab *pVTab);
  int (*xRollback)(sqlite3_vtab *pVTab);
  int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
                       void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
                       void **ppArg);
  int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
  /* The methods above are in version 0 of the sqlite_module object. Those 
  ** below are for version 1 and greater. */
  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
  int (*xRelease)(sqlite3_vtab *pVTab, int);
  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
};

/*
** CAPI3REF: Virtual Table Indexing Information
................................................................................
**
** These macros define the various options to the
** [sqlite3_vtab_config()] interface that [virtual table] implementations
** can use to customize and optimize their behavior.
**
** <dl>
**   <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
**   <dd>If the second argument to [sqlite3_vtab_config()] is
**       SQLITE_VTAB_CONSTRAINT_SUPPORT, then SQLite expects this function to
**       have been called with three arguments, the third of which being of
**       type 'int'. If the third argument is zero, then the virtual table
**       is indicating that it does not support constraints. In this case if
**       a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], the entire
**       statement is rolled back as if [ON CONFLICT | OR ABORT] had been
**       specified as part of the users SQL statement, regardless of the actual
**       ON CONFLICT mode specified.
**
**       If the third argument passed is non-zero, then the virtual table
**       implementation must guarantee that if [xUpdate] returns 
**       [SQLITE_CONSTRAINT], it does so before any modifications to internal
**       or persistent data structures have been made. If the [ON CONFLICT]
**       mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite is able to roll back
**       a statement or database transaction, and abandon or continue processing
**       the current SQL statement as appropriate. If the ON CONFLICT mode is
**       REPLACE and the [xUpdate] method returns [SQLITE_CONSTRAINT], SQLite
**       handles this as if the ON CONFLICT mode had been ABORT.

**
**       Virtual table implementations that are required to handle OR REPLACE
**       must do so within the xUpdate method. If a call to the 
**       [sqlite3_vtab_on_conflict()] function indicates that the current ON 
**       CONFLICT policy is REPLACE, the virtual table implementation should 
**       silently replace the appropriate rows within the xUpdate callback and
**       return SQLITE_OK. Or, if this is not possible, it may return
**       SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT 
**       constraint handling.
** </dl>
** 
*/
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1

/*
** CAPI3REF: Determine The Virtual Table Conflict Policy
**
** This function may only be called from within a call to the [xUpdate] method







>
>
>







 







>







 







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









>







 







>







 







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







 







>







 







|







 








>
>
>
>
>












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







 







|
|







 







|
|
|
|
|
|




|
|
<
|
|
|
|
|
|
>

|
|







<







450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
...
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
....
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
....
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
....
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
....
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477



2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
....
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
....
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591

6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608

6609
6610
6611
6612
6613
6614
6615
#define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
#define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
#define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))

#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))

/*
** CAPI3REF: Flags For File Open Operations
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the xOpen method of the
** [sqlite3_vfs] object.
................................................................................
#define SQLITE_OPEN_SUBJOURNAL       0x00002000  /* VFS only */
#define SQLITE_OPEN_MASTER_JOURNAL   0x00004000  /* VFS only */
#define SQLITE_OPEN_NOMUTEX          0x00008000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_FULLMUTEX        0x00010000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_SHAREDCACHE      0x00020000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_PRIVATECACHE     0x00040000  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_WAL              0x00080000  /* VFS only */
#define SQLITE_OPEN_URI              0x00100000  /* Ok for sqlite3_open_v2() */

/* Reserved:                         0x00F00000 */

/*
** CAPI3REF: Device Characteristics
**
** The xDeviceCharacteristics method of the [sqlite3_io_methods]
................................................................................
** when the database connection has [PRAGMA synchronous] set to OFF.)^
** Some specialized VFSes need this signal in order to operate correctly
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most 
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  
**
** The [SQLITE_FCNTL_READONLY_SHM] may be generated internally by SQLite if
** the "readonly_shm=1" URI option is specified when the database is opened.
** The fourth argument passed to the VFS xFileControl methods is a pointer
** to a variable of type "int" containing the value 1 or 0. If the variable
** contains the value 1, then this indicates to the VFS that a read-only
** mapping of the shared-memory region is acceptable. If it is set to 0, then
** this indicates that a read-write mapping is required (as normal). If
** a read-only mapping is returned, then the VFS may also return read-only
** mappings for any subsequent requests via the same file-descriptor -
** regardless of the value most recently configured using
** SQLITE_FCNTL_READONLY_SHM.
**
** In practice, if "readonly_shm=1" is specified and the first attempt to
** map a shared-memory region fails, then this file-control is invoked with
** the argument variable set to 1 and a second attempt to map the shared-memory
** region is made. If this mapping succeeds, then the connection continues
** with the read-only mapping. Otherwise, if it fails, SQLITE_CANTOPEN is
** returned to the caller. Whether or not the second (read-only) mapping
** attempt succeeds, the file-control is invoked again with the argument
** variable set to 0.
*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
#define SQLITE_SET_LOCKPROXYFILE      3
#define SQLITE_LAST_ERRNO             4
#define SQLITE_FCNTL_SIZE_HINT        5
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7
#define SQLITE_FCNTL_SYNC_OMITTED     8
#define SQLITE_FCNTL_READONLY_SHM     9


/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
................................................................................
**
** Mutexes are created using [sqlite3_mutex_alloc()].
*/
typedef struct sqlite3_mutex sqlite3_mutex;

/*
** CAPI3REF: OS Interface Object
** KEYWORDS: VFS VFSes
**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system.  The "vfs"
** in the name of the object stands for "virtual file system".
**
** The value of the iVersion field is initially 1 but may be larger in
** future versions of SQLite.  Additional fields may be appended to this
................................................................................
** [extended result code].  ^The third parameter passed to the logger is
** log message after formatting via [sqlite3_snprintf()].
** The SQLite logging interface is not reentrant; the logger function
** supplied by the application must not invoke any SQLite interface.
** In a multi-threaded application, the application-defined logger
** function must be threadsafe. </dd>
**
** <dt>SQLITE_CONFIG_URI
** <dd> This option takes a single argument of type int. If non-zero, then
** URI handling is globally enabled. If the parameter is zero, then URI handling
** is globally disabled. If URI handling is globally enabled, all filenames
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
** connection is opened. If it is globally disabled, filenames are
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
** database connection is opened. By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
#define SQLITE_CONFIG_SERIALIZED    3  /* nil */
#define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
................................................................................
#define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ 
#define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
#define SQLITE_CONFIG_PCACHE       14  /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_GETPCACHE    15  /* sqlite3_pcache_methods* */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
#define SQLITE_CONFIG_URI          17  /* int */

/*
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite3_db_config()] interface.
**
................................................................................
**
*/
void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);

/*
** CAPI3REF: Opening A New Database Connection
**
** ^These routines open an SQLite database file as specified by the 
** filename argument. ^The filename argument is interpreted as UTF-8 for
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
** order for sqlite3_open16(). ^(A [database connection] handle is usually
** returned in *ppDb, even if an error occurs.  The only exception is that
** if SQLite is unable to allocate memory to hold the [sqlite3] object,
** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
** object.)^ ^(If the database is opened (and/or created) successfully, then
................................................................................
** in the serialized [threading mode] unless single-thread was
** previously selected at compile-time or start-time.
** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
** eligible to use [shared cache mode], regardless of whether or not shared
** cache is enabled using [sqlite3_enable_shared_cache()].  ^The
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
** participate in [shared cache mode] even if it is enabled.
**
** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that
** the new database connection should use.  ^If the fourth parameter is
** a NULL pointer then the default [sqlite3_vfs] object is used.
**
** ^If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection.  ^This in-memory database will vanish when
** the database connection is closed.  Future versions of SQLite might
** make use of additional special filenames that begin with the ":" character.
** It is recommended that when a database filename actually does begin with
** a ":" character you should prefix the filename with a pathname such as
** "./" to avoid ambiguity.
**
** ^If the filename is an empty string, then a private, temporary
** on-disk database will be created.  ^This private database will be
** automatically deleted as soon as the database connection is closed.
**
** ^If URI filename interpretation is enabled, and the filename argument
** begins with "file:", then the filename is interpreted as a URI. ^URI
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
** is set in the fourth argument to sqlite3_open_v2(), or if it has
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
** [sqlite3_config()] method. 
**
** URI filenames are parsed according to RFC 1738. If the URI contains an
** 'authority', then it must be either an empty string or the string 
** "localhost". ^If the authority is not an empty string or "localhost", an 
** error is returned to the caller. ^The 'fragment' component of a URI, if 
** present, is always ignored.
**
** ^SQLite uses the 'path' component of the URI as the path to the database file
** to open. ^If the path begins with a '/' character, then it is interpreted as
** an absolute path. ^If it does not begin with a '/', it is interpreted as a 
** relative path. ^On windows, the first component of an absolute path 
** is a drive specification (e.g. "C:").
**
** The query component of a URI may contain parameters that are interpreted
** either by SQLite itself, or by a [sqlite3_vfs | custom VFS implementation].
** SQLite interprets the following four query parameters:
**
** <ul>
**   <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
**     a VFS object that provides the operating system interface that should
**     be used to access the database file on disk. ^If this option is set to
**     an empty string the default VFS object is used. ^Specifying an unknown
**     VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
**     present, then the VFS specified by the option takes precedence over
**     the value passed as the fourth parameter to sqlite3_open_v2().



**
**   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
**     "rwc". Attempting to set it to any other value is an error)^. 
**     ^If "ro" is specified, then the database is opened for read-only 
**     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the 
**     third argument to sqlite3_prepare_v2(). ^If the mode option is set to 
**     "rw", then the database is opened for read-write (but not create) 
**     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had 
**     been set. ^Value "rwc" is equivalent to setting both 
**     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is 
**     used, it is an error to specify a value for the mode parameter that is 
**     less restrictive than that specified by the flags passed as the third 
**     parameter.
**
**   <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
**     "private". ^Setting it to "shared" is equivalent to setting the
**     SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
**     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
**     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
**     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
**     a URI filename, its value overrides any behaviour requested by setting
**     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
**   <li> <b>readonly_shm</b>: ^The readonly_shm parameter may be set to 
**     either "1" or "0". Setting it to "1" indicates that if the database
**     is in WAL mode and read-write access to the associated shared 
**     memory region cannot be obtained, then an attempt should be made to open
**     the shared-memory in read-only mode instead. If there exist one or
**     more other database clients that have read-write connections to the
**     database shared-memory, then a read-only shared-memory connection works 
**     fine. However, if there exist no clients with read-write connections 
**     to the shared-memory and the most recent such crashed or was interrupted
**     by a power failure, then it is possible for a database client using a
**     read-only connection to return incorrect data, incorrectly report 
**     database corruption, or return an SQLITE_READONLY error. Or if the
**     most recent read-write connection shut down cleanly, it may not be
**     possible to open the shared-memory in read-only mode at all, and SQLite
**     will return SQLITE_CANTOPEN.
** </ul>
**
** ^Specifying an unknown parameter in the query component of a URI is not an
** error.
**
** URI filename examples:
**
** <table border="1" align=center cellpadding=5>
** <tr><th> URI filenames <th> Results
** <tr><td> file:data.db <td> 
**          Open the file "data.db" in the current directory.
** <tr><td> file:/home/fred/data.db<br>
**          file:///home/fred/data.db <br> 
**          file://localhost/home/fred/data.db <br> <td> 
**          Open the database file "/home/fred/data.db".
** <tr><td> file://darkstar/home/fred/data.db <td> 
**          An error. "darkstar" is not a recognized authority.
** <tr><td style="white-space:nowrap"> 
**          file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
**     <td> Windows only: Open the file "data.db" on fred's desktop on drive
**          C:. Note that the %20 escaping in this example is not strictly 
**          necessary - space characters can be used literally
**          in URI filenames.
** <tr><td> file:data.db?mode=ro&cache=private <td> 
**          Open file "data.db" in the current directory for read-only access.
**          Regardless of whether or not shared-cache mode is enabled by
**          default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
**          Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
** <tr><td> file:data.db?mode=readonly <td> 
**          An error. "readonly" is not a valid option for the "mode" parameter.
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
** query components of a URI. A hexadecimal escape sequence consists of a
** percent sign - "%" - followed by exactly two hexadecimal digits 
** specifying an octet value. ^Before the path or query components of a
** URI filename are interpreted, they are encoded using UTF-8 and all 
** hexadecimal escape sequences replaced by a single byte containing the
** corresponding octet. If this process generates an invalid UTF-8 encoding,
** the results are undefined.
**
** <b>Note to Windows users:</b>  The encoding used for the filename argument
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
** codepage is currently defined.  Filenames containing international
** characters must be converted to UTF-8 prior to passing them into
** sqlite3_open() or sqlite3_open_v2().
*/
................................................................................
  int (*xSync)(sqlite3_vtab *pVTab);
  int (*xCommit)(sqlite3_vtab *pVTab);
  int (*xRollback)(sqlite3_vtab *pVTab);
  int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
                       void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
                       void **ppArg);
  int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
  /* The methods above are in version 1 of the sqlite_module object. Those 
  ** below are for version 2 and greater. */
  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
  int (*xRelease)(sqlite3_vtab *pVTab, int);
  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
};

/*
** CAPI3REF: Virtual Table Indexing Information
................................................................................
**
** These macros define the various options to the
** [sqlite3_vtab_config()] interface that [virtual table] implementations
** can use to customize and optimize their behavior.
**
** <dl>
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
** where X is an integer.  If X is zero, then the [virtual table] whose
** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
** support constraints.  In this configuration (which is the default) if
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
** specified as part of the users SQL statement, regardless of the actual
** ON CONFLICT mode specified.
**
** If X is non-zero, then the virtual table implementation guarantees
** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before

** any modifications to internal or persistent data structures have been made.
** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite 
** is able to roll back a statement or database transaction, and abandon
** or continue processing the current SQL statement as appropriate. 
** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
** had been ABORT.
**
** Virtual table implementations that are required to handle OR REPLACE
** must do so within the [xUpdate] method. If a call to the 
** [sqlite3_vtab_on_conflict()] function indicates that the current ON 
** CONFLICT policy is REPLACE, the virtual table implementation should 
** silently replace the appropriate rows within the xUpdate callback and
** return SQLITE_OK. Or, if this is not possible, it may return
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT 
** constraint handling.
** </dl>

*/
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1

/*
** CAPI3REF: Determine The Virtual Table Conflict Policy
**
** This function may only be called from within a call to the [xUpdate] method

Changes to src/sqliteInt.h.

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
....
2419
2420
2421
2422
2423
2424
2425

2426
2427
2428
2429
2430
2431
2432
....
2668
2669
2670
2671
2672
2673
2674


2675
2676
2677
2678
2679
2680
2681
....
2918
2919
2920
2921
2922
2923
2924

2925
2926
2927
2928
2929
2930
2931
** consistently.
*/
struct sqlite3 {
  sqlite3_vfs *pVfs;            /* OS Interface */
  int nDb;                      /* Number of backends currently in use */
  Db *aDb;                      /* All backends */
  int flags;                    /* Miscellaneous flags. See below */
  int openFlags;                /* Flags passed to sqlite3_vfs.xOpen() */
  int errCode;                  /* Most recent error code (SQLITE_*) */
  int errMask;                  /* & result codes with this before returning */
  u8 autoCommit;                /* The auto-commit flag. */
  u8 temp_store;                /* 1: file 2: memory 0: default */
  u8 mallocFailed;              /* True if we have seen a malloc failure */
  u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
................................................................................
**
** This structure also contains some state information.
*/
struct Sqlite3Config {
  int bMemstat;                     /* True to enable memory status */
  int bCoreMutex;                   /* True to enable core mutexing */
  int bFullMutex;                   /* True to enable full mutexing */

  int mxStrlen;                     /* Maximum string length */
  int szLookaside;                  /* Default lookaside buffer size */
  int nLookaside;                   /* Default lookaside buffer count */
  sqlite3_mem_methods m;            /* Low-level memory allocation interface */
  sqlite3_mutex_methods mutex;      /* Low-level mutex interface */
  sqlite3_pcache_methods pcache;    /* Low-level page-cache interface */
  void *pHeap;                      /* Heap storage space */
................................................................................
void sqlite3AddNotNull(Parse*, int);
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
void sqlite3AddCheckConstraint(Parse*, Expr*);
void sqlite3AddColumnType(Parse*,Token*);
void sqlite3AddDefaultValue(Parse*,ExprSpan*);
void sqlite3AddCollateType(Parse*, Token*);
void sqlite3EndTable(Parse*,Token*,Token*,Select*);



Bitvec *sqlite3BitvecCreate(u32);
int sqlite3BitvecTest(Bitvec*, u32);
int sqlite3BitvecSet(Bitvec*, u32);
void sqlite3BitvecClear(Bitvec*, u32, void*);
void sqlite3BitvecDestroy(Bitvec*);
u32 sqlite3BitvecSize(Bitvec*);
................................................................................
void sqlite3TableAffinityStr(Vdbe *, Table *);
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
char sqlite3ExprAffinity(Expr *pExpr);
int sqlite3Atoi64(const char*, i64*, int, u8);
void sqlite3Error(sqlite3*, int, const char*,...);
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);

int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
Expr *sqlite3ExprSetColl(Expr*, CollSeq*);







|







 







>







 







>
>







 







>







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

Bitvec *sqlite3BitvecCreate(u32);
int sqlite3BitvecTest(Bitvec*, u32);
int sqlite3BitvecSet(Bitvec*, u32);
void sqlite3BitvecClear(Bitvec*, u32, void*);
void sqlite3BitvecDestroy(Bitvec*);
u32 sqlite3BitvecSize(Bitvec*);
................................................................................
void sqlite3TableAffinityStr(Vdbe *, Table *);
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
char sqlite3ExprAffinity(Expr *pExpr);
int sqlite3Atoi64(const char*, i64*, int, u8);
void sqlite3Error(sqlite3*, int, const char*,...);
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
u8 sqlite3HexToInt(int h);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
Expr *sqlite3ExprSetColl(Expr*, CollSeq*);

Changes to src/test1.c.

159
160
161
162
163
164
165



166
167
168
169
170
171
172
....
3858
3859
3860
3861
3862
3863
3864






































































3865
3866
3867
3868
3869
3870
3871
....
5699
5700
5701
5702
5703
5704
5705

5706
5707
5708
5709
5710
5711
5712
    case SQLITE_IOERR_DELETE:        zName = "SQLITE_IOERR_DELETE";      break;
    case SQLITE_IOERR_BLOCKED:       zName = "SQLITE_IOERR_BLOCKED";     break;
    case SQLITE_IOERR_NOMEM:         zName = "SQLITE_IOERR_NOMEM";       break;
    case SQLITE_IOERR_ACCESS:        zName = "SQLITE_IOERR_ACCESS";      break;
    case SQLITE_IOERR_CHECKRESERVEDLOCK:
                               zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
    case SQLITE_IOERR_LOCK:          zName = "SQLITE_IOERR_LOCK";        break;



    default:                         zName = "SQLITE_Unknown";           break;
  }
  return zName;
}
#define t1ErrorName sqlite3TestErrorName

/*
................................................................................
  zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
  rc = sqlite3_open(zFilename, &db);
  
  if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}







































































/*
** Usage: sqlite3_open16 filename options
*/
static int test_open16(
  void * clientData,
  Tcl_Interp *interp,
................................................................................
     { "sqlite3_sleep",                 test_sleep,          0},
     { "sqlite3_errcode",               test_errcode       ,0 },
     { "sqlite3_extended_errcode",      test_ex_errcode    ,0 },
     { "sqlite3_errmsg",                test_errmsg        ,0 },
     { "sqlite3_errmsg16",              test_errmsg16      ,0 },
     { "sqlite3_open",                  test_open          ,0 },
     { "sqlite3_open16",                test_open16        ,0 },

     { "sqlite3_complete16",            test_complete16    ,0 },

     { "sqlite3_prepare",               test_prepare       ,0 },
     { "sqlite3_prepare16",             test_prepare16     ,0 },
     { "sqlite3_prepare_v2",            test_prepare_v2    ,0 },
     { "sqlite3_prepare_tkt3134",       test_prepare_tkt3134, 0},
     { "sqlite3_prepare16_v2",          test_prepare16_v2  ,0 },







>
>
>







 







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







 







>







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
....
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
....
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
    case SQLITE_IOERR_DELETE:        zName = "SQLITE_IOERR_DELETE";      break;
    case SQLITE_IOERR_BLOCKED:       zName = "SQLITE_IOERR_BLOCKED";     break;
    case SQLITE_IOERR_NOMEM:         zName = "SQLITE_IOERR_NOMEM";       break;
    case SQLITE_IOERR_ACCESS:        zName = "SQLITE_IOERR_ACCESS";      break;
    case SQLITE_IOERR_CHECKRESERVEDLOCK:
                               zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
    case SQLITE_IOERR_LOCK:          zName = "SQLITE_IOERR_LOCK";        break;

    case SQLITE_READONLY_RECOVERY:   zName = "SQLITE_READONLY_RECOVERY"; break;
    case SQLITE_READONLY_CANTLOCK:   zName = "SQLITE_READONLY_CANTLOCK"; break;
    default:                         zName = "SQLITE_Unknown";           break;
  }
  return zName;
}
#define t1ErrorName sqlite3TestErrorName

/*
................................................................................
  zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
  rc = sqlite3_open(zFilename, &db);
  
  if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}

/*
** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
*/
static int test_open_v2(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  const char *zFilename;
  const char *zVfs;
  int flags = 0;
  sqlite3 *db;
  int rc;
  char zBuf[100];

  int nFlag;
  Tcl_Obj **apFlag;
  int i;

  if( objc!=4 ){
    Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
    return TCL_ERROR;
  }
  zFilename = Tcl_GetString(objv[1]);
  zVfs = Tcl_GetString(objv[3]);
  if( zVfs[0]==0x00 ) zVfs = 0;

  rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
  if( rc!=TCL_OK ) return rc;
  for(i=0; i<nFlag; i++){
    int iFlag;
    struct OpenFlag {
      const char *zFlag;
      int flag;
    } aFlag[] = {
      { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
      { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
      { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
      { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
      { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
      { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
      { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
      { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
      { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
      { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
      { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
      { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
      { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
      { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
      { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
      { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
      { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
      { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
      { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
      { 0, 0 }
    };
    rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]), 
        "flag", 0, &iFlag
    );
    if( rc!=TCL_OK ) return rc;
    flags |= aFlag[iFlag].flag;
  }

  rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
  if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}

/*
** Usage: sqlite3_open16 filename options
*/
static int test_open16(
  void * clientData,
  Tcl_Interp *interp,
................................................................................
     { "sqlite3_sleep",                 test_sleep,          0},
     { "sqlite3_errcode",               test_errcode       ,0 },
     { "sqlite3_extended_errcode",      test_ex_errcode    ,0 },
     { "sqlite3_errmsg",                test_errmsg        ,0 },
     { "sqlite3_errmsg16",              test_errmsg16      ,0 },
     { "sqlite3_open",                  test_open          ,0 },
     { "sqlite3_open16",                test_open16        ,0 },
     { "sqlite3_open_v2",               test_open_v2       ,0 },
     { "sqlite3_complete16",            test_complete16    ,0 },

     { "sqlite3_prepare",               test_prepare       ,0 },
     { "sqlite3_prepare16",             test_prepare16     ,0 },
     { "sqlite3_prepare_v2",            test_prepare_v2    ,0 },
     { "sqlite3_prepare_tkt3134",       test_prepare_tkt3134, 0},
     { "sqlite3_prepare16_v2",          test_prepare16_v2  ,0 },

Changes to src/test3.c.

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







|







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

Changes to src/test_malloc.c.

1169
1170
1171
1172
1173
1174
1175





























1176
1177
1178
1179
1180
1181
1182
....
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431
          "sqlite3_config(99999) does not return SQLITE_ERROR",
          (char*)0);
      return TCL_ERROR;
    }
  }
  return TCL_OK;
}






























/*
** Usage:    
**
**   sqlite3_dump_memsys3  FILENAME
**   sqlite3_dump_memsys5  FILENAME
**
................................................................................
     { "sqlite3_status",             test_status                   ,0 },
     { "sqlite3_db_status",          test_db_status                ,0 },
     { "install_malloc_faultsim",    test_install_malloc_faultsim  ,0 },
     { "sqlite3_config_heap",        test_config_heap              ,0 },
     { "sqlite3_config_memstatus",   test_config_memstatus         ,0 },
     { "sqlite3_config_lookaside",   test_config_lookaside         ,0 },
     { "sqlite3_config_error",       test_config_error             ,0 },

     { "sqlite3_db_config_lookaside",test_db_config_lookaside      ,0 },
     { "sqlite3_dump_memsys3",       test_dump_memsys3             ,3 },
     { "sqlite3_dump_memsys5",       test_dump_memsys3             ,5 },
     { "sqlite3_install_memsys3",    test_install_memsys3          ,0 },
     { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test          ,0 },
  };
  int i;







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







 







>







1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
....
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
          "sqlite3_config(99999) does not return SQLITE_ERROR",
          (char*)0);
      return TCL_ERROR;
    }
  }
  return TCL_OK;
}

/*
** tclcmd:     sqlite3_config_uri  BOOLEAN
**
** Invoke sqlite3_config() or sqlite3_db_config() with invalid
** opcodes and verify that they return errors.
*/
static int test_config_uri(
  void * clientData, 
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc;
  int bOpenUri;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
    return TCL_ERROR;
  }
  if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){
    return TCL_ERROR;
  }

  rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);

  return TCL_OK;
}

/*
** Usage:    
**
**   sqlite3_dump_memsys3  FILENAME
**   sqlite3_dump_memsys5  FILENAME
**
................................................................................
     { "sqlite3_status",             test_status                   ,0 },
     { "sqlite3_db_status",          test_db_status                ,0 },
     { "install_malloc_faultsim",    test_install_malloc_faultsim  ,0 },
     { "sqlite3_config_heap",        test_config_heap              ,0 },
     { "sqlite3_config_memstatus",   test_config_memstatus         ,0 },
     { "sqlite3_config_lookaside",   test_config_lookaside         ,0 },
     { "sqlite3_config_error",       test_config_error             ,0 },
     { "sqlite3_config_uri",         test_config_uri               ,0 },
     { "sqlite3_db_config_lookaside",test_db_config_lookaside      ,0 },
     { "sqlite3_dump_memsys3",       test_dump_memsys3             ,3 },
     { "sqlite3_dump_memsys5",       test_dump_memsys3             ,5 },
     { "sqlite3_install_memsys3",    test_install_memsys3          ,0 },
     { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test          ,0 },
  };
  int i;

Changes to src/test_vfs.c.

123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556











557

558
559
560
561
562
563
564
...
659
660
661
662
663
664
665








666
667
668
669
670
671
672
....
1036
1037
1038
1039
1040
1041
1042

1043
1044
1045
1046
1047
1048
1049
#define TESTVFS_OPEN_MASK       0x00000100
#define TESTVFS_SYNC_MASK       0x00000200
#define TESTVFS_DELETE_MASK     0x00000400
#define TESTVFS_CLOSE_MASK      0x00000800
#define TESTVFS_WRITE_MASK      0x00001000
#define TESTVFS_TRUNCATE_MASK   0x00002000
#define TESTVFS_ACCESS_MASK     0x00004000

#define TESTVFS_ALL_MASK        0x00007FFF


#define TESTVFS_MAX_PAGES 1024

/*
** A shared-memory buffer. There is one of these objects for each shared
** memory region opened by clients. If two clients open the same file,
................................................................................
  pFd->pVfs = pVfs;
  pFd->pReal = (sqlite3_file *)&pFd[1];
  memset(pTestfile, 0, sizeof(TestvfsFile));
  pTestfile->pFd = pFd;

  /* Evaluate the Tcl script: 
  **
  **   SCRIPT xOpen FILENAME
  **
  ** If the script returns an SQLite error code other than SQLITE_OK, an
  ** error is returned to the caller. If it returns SQLITE_OK, the new
  ** connection is named "anon". Otherwise, the value returned by the
  ** script is used as the connection name.
  */
  Tcl_ResetResult(p->interp);
  if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){











    tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);

    if( tvfsResultCode(p, &rc) ){
      if( rc!=SQLITE_OK ) return rc;
    }else{
      pId = Tcl_GetObjResult(p->interp);
    }
  }

................................................................................
*/
static int tvfsFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){








  return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
}

#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Open the dynamic library located at zPath and return a handle.
*/
................................................................................
        { "xSync",       TESTVFS_SYNC_MASK },
        { "xDelete",     TESTVFS_DELETE_MASK },
        { "xWrite",      TESTVFS_WRITE_MASK },
        { "xTruncate",   TESTVFS_TRUNCATE_MASK },
        { "xOpen",       TESTVFS_OPEN_MASK },
        { "xClose",      TESTVFS_CLOSE_MASK },
        { "xAccess",     TESTVFS_ACCESS_MASK },

      };
      Tcl_Obj **apElem = 0;
      int nElem = 0;
      int i;
      int mask = 0;
      if( objc!=3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "LIST");







>
|







 







|








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







 







>
>
>
>
>
>
>
>







 







>







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
...
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
...
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
....
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
#define TESTVFS_OPEN_MASK         0x00000100
#define TESTVFS_SYNC_MASK         0x00000200
#define TESTVFS_DELETE_MASK       0x00000400
#define TESTVFS_CLOSE_MASK        0x00000800
#define TESTVFS_WRITE_MASK        0x00001000
#define TESTVFS_TRUNCATE_MASK     0x00002000
#define TESTVFS_ACCESS_MASK       0x00004000
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
#define TESTVFS_ALL_MASK          0x0001FFFF


#define TESTVFS_MAX_PAGES 1024

/*
** A shared-memory buffer. There is one of these objects for each shared
** memory region opened by clients. If two clients open the same file,
................................................................................
  pFd->pVfs = pVfs;
  pFd->pReal = (sqlite3_file *)&pFd[1];
  memset(pTestfile, 0, sizeof(TestvfsFile));
  pTestfile->pFd = pFd;

  /* Evaluate the Tcl script: 
  **
  **   SCRIPT xOpen FILENAME KEY-VALUE-ARGS
  **
  ** If the script returns an SQLite error code other than SQLITE_OK, an
  ** error is returned to the caller. If it returns SQLITE_OK, the new
  ** connection is named "anon". Otherwise, the value returned by the
  ** script is used as the connection name.
  */
  Tcl_ResetResult(p->interp);
  if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){
    Tcl_Obj *pArg = Tcl_NewObj();
    Tcl_IncrRefCount(pArg);
    if( flags&SQLITE_OPEN_MAIN_DB ){
      const char *z = &zName[strlen(zName)+1];
      while( *z ){
        Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
        z += strlen(z) + 1;
        Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
        z += strlen(z) + 1;
      }
    }
    tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0);
    Tcl_DecrRefCount(pArg);
    if( tvfsResultCode(p, &rc) ){
      if( rc!=SQLITE_OK ) return rc;
    }else{
      pId = Tcl_GetObjResult(p->interp);
    }
  }

................................................................................
*/
static int tvfsFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){
  Testvfs *p = (Testvfs *)pVfs->pAppData;
  if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){
    int rc;
    tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0);
    if( tvfsResultCode(p, &rc) ){
      if( rc!=SQLITE_OK ) return rc;
    }
  }
  return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
}

#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Open the dynamic library located at zPath and return a handle.
*/
................................................................................
        { "xSync",         TESTVFS_SYNC_MASK },
        { "xDelete",       TESTVFS_DELETE_MASK },
        { "xWrite",        TESTVFS_WRITE_MASK },
        { "xTruncate",     TESTVFS_TRUNCATE_MASK },
        { "xOpen",         TESTVFS_OPEN_MASK },
        { "xClose",        TESTVFS_CLOSE_MASK },
        { "xAccess",       TESTVFS_ACCESS_MASK },
        { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
      };
      Tcl_Obj **apElem = 0;
      int nElem = 0;
      int i;
      int mask = 0;
      if( objc!=3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "LIST");

Changes to src/util.c.

979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
....
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  p[1] = (u8)(v>>16);
  p[2] = (u8)(v>>8);
  p[3] = (u8)v;
}



#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/
static u8 hexToInt(int h){
  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
  h += 9*(1&(h>>6));
#endif
#ifdef SQLITE_EBCDIC
  h += 9*(1&~(h>>4));
#endif
  return (u8)(h & 0xf);
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */

#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
** value.  Return a pointer to its binary value.  Space to hold the
** binary value has been obtained from malloc and must be freed by
** the calling routine.
................................................................................
  char *zBlob;
  int i;

  zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
  n--;
  if( zBlob ){
    for(i=0; i<n; i+=2){
      zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
    }
    zBlob[i/2] = 0;
  }
  return zBlob;
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */








<





|









<







 







|







979
980
981
982
983
984
985

986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
....
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
  p[1] = (u8)(v>>16);
  p[2] = (u8)(v>>8);
  p[3] = (u8)v;
}




/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/
u8 sqlite3HexToInt(int h){
  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
  h += 9*(1&(h>>6));
#endif
#ifdef SQLITE_EBCDIC
  h += 9*(1&~(h>>4));
#endif
  return (u8)(h & 0xf);
}


#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
** value.  Return a pointer to its binary value.  Space to hold the
** binary value has been obtained from malloc and must be freed by
** the calling routine.
................................................................................
  char *zBlob;
  int i;

  zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
  n--;
  if( zBlob ){
    for(i=0; i<n; i+=2){
      zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
    }
    zBlob[i/2] = 0;
  }
  return zBlob;
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */

Changes to src/vdbe.c.

3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
      SQLITE_OPEN_DELETEONCLOSE |
      SQLITE_OPEN_TRANSIENT_DB;

  assert( pOp->p1>=0 );
  pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
  if( pCx==0 ) goto no_mem;
  pCx->nullRow = 1;
  rc = sqlite3BtreeOpen(0, db, &pCx->pBt, 
                        BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
  if( rc==SQLITE_OK ){
    rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
  }
  if( rc==SQLITE_OK ){
    /* If a transient index is required, create it by calling
    ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before







|







3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
      SQLITE_OPEN_DELETEONCLOSE |
      SQLITE_OPEN_TRANSIENT_DB;

  assert( pOp->p1>=0 );
  pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
  if( pCx==0 ) goto no_mem;
  pCx->nullRow = 1;
  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, 
                        BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
  if( rc==SQLITE_OK ){
    rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
  }
  if( rc==SQLITE_OK ){
    /* If a transient index is required, create it by calling
    ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before

Changes to src/vtab.c.

870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
....
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
  int rc = SQLITE_OK;

  assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
  if( db->aVTrans ){
    int i;
    for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
      const sqlite3_module *pMod = db->aVTrans[i]->pMod->pModule;
      if( pMod->iVersion>=1 ){
        int (*xMethod)(sqlite3_vtab *, int);
        switch( op ){
          case SAVEPOINT_BEGIN:
            xMethod = pMod->xSavepoint;
            break;
          case SAVEPOINT_ROLLBACK:
            xMethod = pMod->xRollbackTo;
................................................................................
** table update operation currently in progress.
**
** The results of this routine are undefined unless it is called from
** within an xUpdate method.
*/
int sqlite3_vtab_on_conflict(sqlite3 *db){
  static const unsigned char aMap[] = { 
    SQLITE_ROLLBACK, SQLITE_IGNORE, SQLITE_ABORT, SQLITE_FAIL, SQLITE_REPLACE 
  };
  assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
  assert( OE_Ignore==4 && OE_Replace==5 );
  assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 );
  return (int)aMap[db->vtabOnConflict-1];
}

................................................................................
  va_start(ap, op);
  switch( op ){
    case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
      VtabCtx *p = db->pVtabCtx;
      if( !p ){
        rc = SQLITE_MISUSE_BKPT;
      }else{
        assert( (p->pTab->tabFlags & TF_Virtual)!=0 );
        p->pVTable->bConstraint = (u8)va_arg(ap, int);
      }
      break;
    }
    default:
      rc = SQLITE_MISUSE_BKPT;
      break;







|







 







|







 







|







870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
....
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
  int rc = SQLITE_OK;

  assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
  if( db->aVTrans ){
    int i;
    for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
      const sqlite3_module *pMod = db->aVTrans[i]->pMod->pModule;
      if( pMod->iVersion>=2 ){
        int (*xMethod)(sqlite3_vtab *, int);
        switch( op ){
          case SAVEPOINT_BEGIN:
            xMethod = pMod->xSavepoint;
            break;
          case SAVEPOINT_ROLLBACK:
            xMethod = pMod->xRollbackTo;
................................................................................
** table update operation currently in progress.
**
** The results of this routine are undefined unless it is called from
** within an xUpdate method.
*/
int sqlite3_vtab_on_conflict(sqlite3 *db){
  static const unsigned char aMap[] = { 
    SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE 
  };
  assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
  assert( OE_Ignore==4 && OE_Replace==5 );
  assert( db->vtabOnConflict>=1 && db->vtabOnConflict<=5 );
  return (int)aMap[db->vtabOnConflict-1];
}

................................................................................
  va_start(ap, op);
  switch( op ){
    case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
      VtabCtx *p = db->pVtabCtx;
      if( !p ){
        rc = SQLITE_MISUSE_BKPT;
      }else{
        assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
        p->pVTable->bConstraint = (u8)va_arg(ap, int);
      }
      break;
    }
    default:
      rc = SQLITE_MISUSE_BKPT;
      break;

Changes to src/wal.c.

402
403
404
405
406
407
408








409
410
411
412
413
414
415
...
416
417
418
419
420
421
422

423
424
425
426
427
428
429
...
524
525
526
527
528
529
530








531

532
533

534

535

536
537
538
539
540
541
542
...
768
769
770
771
772
773
774

775
776
777
778
779
780
781
782
783

784
785
786
787
788
789
790
....
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
....
1891
1892
1893
1894
1895
1896
1897

1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909






1910
1911
1912
1913
1914
1915
1916
1917
....
1919
1920
1921
1922
1923
1924
1925

1926
1927
1928
1929
1930
1931
1932
....
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
....
2119
2120
2121
2122
2123
2124
2125
2126

2127
2128
2129
2130
2131
2132
2133
....
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184




2185
2186
2187

2188
2189
2190
2191
2192
2193
2194
....
2355
2356
2357
2358
2359
2360
2361

2362
2363
2364
2365
2366
2367
2368
....
2744
2745
2746
2747
2748
2749
2750




2751
2752
2753
2754
2755
2756
2757
#define walFrameOffset(iFrame, szPage) (                               \
  WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE)         \
)

/*
** An open write-ahead log file is represented by an instance of the
** following object.








*/
struct Wal {
  sqlite3_vfs *pVfs;         /* The VFS used to create pDbFd */
  sqlite3_file *pDbFd;       /* File handle for the database file */
  sqlite3_file *pWalFd;      /* File handle for WAL file */
  u32 iCallback;             /* Value to pass to log callback (or 0) */
  int nWiData;               /* Size of array apWiData */
................................................................................
  volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
  u32 szPage;                /* Database page size */
  i16 readLock;              /* Which read lock is being held.  -1 for none */
  u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
  u8 writeLock;              /* True if in a write transaction */
  u8 ckptLock;               /* True if holding a checkpoint lock */
  u8 readOnly;               /* True if the WAL file is open read-only */

  WalIndexHdr hdr;           /* Wal-index header for current transaction */
  const char *zWalName;      /* Name of WAL file */
  u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
#ifdef SQLITE_DEBUG
  u8 lockError;              /* True if a locking error has occurred */
#endif
};
................................................................................
    if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
      pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
      if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
    }else{
      rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
          pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
      );








    }

  }


  *ppPage = pWal->apWiData[iPage];

  assert( iPage==0 || *ppPage || rc!=SQLITE_OK );

  return rc;
}

/*
** Return a pointer to the WalCkptInfo structure in the wal-index.
*/
static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
................................................................................
  if( pWal->exclusiveMode ) return;
  (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
                         SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
  WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
}
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
  int rc;

  if( pWal->exclusiveMode ) return SQLITE_OK;
  rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
                        SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
  WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
            walLockName(lockIdx), n, rc ? "failed" : "ok"));
  VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
  return rc;
}
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){

  if( pWal->exclusiveMode ) return;
  (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
                         SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
  WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
             walLockName(lockIdx), n));
}

................................................................................
  ** If successful, the same bytes that are locked here are unlocked before
  ** this function returns.
  */
  assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
  assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
  assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
  assert( pWal->writeLock );

  iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
  nLock = SQLITE_SHM_NLOCK - iLock;
  rc = walLockExclusive(pWal, iLock, nLock);
  if( rc ){
    return rc;
  }
  WALTRACE(("WAL%p: recovery begin...\n", pWal));
................................................................................
  */
  assert( pChanged );
  rc = walIndexPage(pWal, 0, &page0);
  if( rc!=SQLITE_OK ){
    return rc;
  };
  assert( page0 || pWal->writeLock==0 );


  /* If the first page of the wal-index has been mapped, try to read the
  ** wal-index header immediately, without holding any lock. This usually
  ** works, but may fail if the wal-index header is corrupt or currently 
  ** being modified by another thread or process.
  */
  badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);

  /* If the first attempt failed, it might have been due to a race
  ** with a writer.  So get a WRITE lock and try again.
  */
  assert( badHdr==0 || pWal->writeLock==0 );






  if( badHdr && SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
    pWal->writeLock = 1;
    if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
      badHdr = walIndexTryHdr(pWal, pChanged);
      if( badHdr ){
        /* If the wal-index header is still malformed even while holding
        ** a WRITE lock, it can only mean that the header is corrupted and
        ** needs to be reconstructed.  So run recovery to do exactly that.
................................................................................
        rc = walIndexRecover(pWal);
        *pChanged = 1;
      }
    }
    pWal->writeLock = 0;
    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
  }


  /* If the header is read successfully, check the version number to make
  ** sure the wal-index was not constructed with some future format that
  ** this version of SQLite cannot understand.
  */
  if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
    rc = SQLITE_CANTOPEN_BKPT;
................................................................................
      assert( thisMark!=READMARK_NOT_USED );
      mxReadMark = thisMark;
      mxI = i;
    }
  }
  /* There was once an "if" here. The extra "{" is to preserve indentation. */
  {
    if( mxReadMark < pWal->hdr.mxFrame || mxI==0 ){
      for(i=1; i<WAL_NREADER; i++){
        rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
        if( rc==SQLITE_OK ){
          mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame;
          mxI = i;
          walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
          break;
................................................................................
        }else if( rc!=SQLITE_BUSY ){
          return rc;
        }
      }
    }
    if( mxI==0 ){
      assert( rc==SQLITE_BUSY );
      return WAL_RETRY;

    }

    rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
    if( rc ){
      return rc==SQLITE_BUSY ? WAL_RETRY : rc;
    }
    /* Now that the read-lock has been obtained, check that neither the
................................................................................
** that extra content is ignored by the current thread.
**
** If the database contents have changes since the previous read
** transaction, then *pChanged is set to 1 before returning.  The
** Pager layer will use this to know that is cache is stale and
** needs to be flushed.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
  int rc;                         /* Return code */
  int cnt = 0;                    /* Number of TryBeginRead attempts */





  do{
    rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
  }while( rc==WAL_RETRY );

  testcase( (rc&0xff)==SQLITE_BUSY );
  testcase( (rc&0xff)==SQLITE_IOERR );
  testcase( rc==SQLITE_PROTOCOL );
  testcase( rc==SQLITE_OK );
  return rc;
}

................................................................................
  /* Cannot start a write transaction without first holding a read
  ** transaction. */
  assert( pWal->readLock>=0 );

  if( pWal->readOnly ){
    return SQLITE_READONLY;
  }


  /* Only one writer allowed at a time.  Get the write lock.  Return
  ** SQLITE_BUSY if unable.
  */
  rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
  if( rc ){
    return rc;
................................................................................
  int isChanged = 0;              /* True if a new wal-index header is loaded */
  int eMode2 = eMode;             /* Mode to pass to walCheckpoint() */

  assert( pWal->ckptLock==0 );
  assert( pWal->writeLock==0 );

  WALTRACE(("WAL%p: checkpoint begins\n", pWal));




  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
  if( rc ){
    /* Usually this is SQLITE_BUSY meaning that another thread or process
    ** is already running a checkpoint, or maybe a recovery.  But it might
    ** also be SQLITE_IOERR. */
    return rc;
  }







>
>
>
>
>
>
>
>







 







>







 







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

>

>







 







>









>







 







>







 







>









|


>
>
>
>
>
>
|







 







>







 







|







 







|
>







 







|



>
>
>
>



>







 







>







 







>
>
>
>







402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
...
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
...
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
....
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
....
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
....
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
....
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
....
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
....
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
....
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
....
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
#define walFrameOffset(iFrame, szPage) (                               \
  WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE)         \
)

/*
** An open write-ahead log file is represented by an instance of the
** following object.
**
** The readOnlyShm variable is normally set to 0. If it is set to 1, then
** the connection to shared-memory is read-only. This means it cannot
** be written at all (even when read-locking the database). If it is set
** to 2, then the shared-memory region is not yet open, but a read-only
** connection is acceptable. In this case when the shared-memory is opened
** (see function walIndexPage()), readOnlyShm is set to either 0 or 1 as
** appropriate.
*/
struct Wal {
  sqlite3_vfs *pVfs;         /* The VFS used to create pDbFd */
  sqlite3_file *pDbFd;       /* File handle for the database file */
  sqlite3_file *pWalFd;      /* File handle for WAL file */
  u32 iCallback;             /* Value to pass to log callback (or 0) */
  int nWiData;               /* Size of array apWiData */
................................................................................
  volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
  u32 szPage;                /* Database page size */
  i16 readLock;              /* Which read lock is being held.  -1 for none */
  u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
  u8 writeLock;              /* True if in a write transaction */
  u8 ckptLock;               /* True if holding a checkpoint lock */
  u8 readOnly;               /* True if the WAL file is open read-only */
  u8 readOnlyShm;            /* True if the SHM file is open read-only */
  WalIndexHdr hdr;           /* Wal-index header for current transaction */
  const char *zWalName;      /* Name of WAL file */
  u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
#ifdef SQLITE_DEBUG
  u8 lockError;              /* True if a locking error has occurred */
#endif
};
................................................................................
    if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
      pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
      if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
    }else{
      rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
          pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
      );
      if( rc==SQLITE_CANTOPEN && pWal->readOnlyShm>1 ){
        assert( iPage==0 );
        sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_READONLY_SHM, (void*)1);
        rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
            pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
        );
        if( rc==SQLITE_OK ){
          pWal->readOnly = pWal->readOnlyShm = 1;
        }
        sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_READONLY_SHM, (void*)0);
      }
    }
  }
  *ppPage = pWal->apWiData[iPage];

  assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
  if( pWal->readOnlyShm>1 ) pWal->readOnlyShm = 0;
  return rc;
}

/*
** Return a pointer to the WalCkptInfo structure in the wal-index.
*/
static volatile WalCkptInfo *walCkptInfo(Wal *pWal){
................................................................................
  if( pWal->exclusiveMode ) return;
  (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1,
                         SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
  WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
}
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
  int rc;
  assert( pWal->readOnlyShm==0 );
  if( pWal->exclusiveMode ) return SQLITE_OK;
  rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
                        SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
  WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
            walLockName(lockIdx), n, rc ? "failed" : "ok"));
  VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
  return rc;
}
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
  assert( pWal->readOnlyShm==0 );
  if( pWal->exclusiveMode ) return;
  (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
                         SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE);
  WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal,
             walLockName(lockIdx), n));
}

................................................................................
  ** If successful, the same bytes that are locked here are unlocked before
  ** this function returns.
  */
  assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
  assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
  assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
  assert( pWal->writeLock );
  assert( pWal->readOnlyShm==0 );
  iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
  nLock = SQLITE_SHM_NLOCK - iLock;
  rc = walLockExclusive(pWal, iLock, nLock);
  if( rc ){
    return rc;
  }
  WALTRACE(("WAL%p: recovery begin...\n", pWal));
................................................................................
  */
  assert( pChanged );
  rc = walIndexPage(pWal, 0, &page0);
  if( rc!=SQLITE_OK ){
    return rc;
  };
  assert( page0 || pWal->writeLock==0 );
  assert( pWal->readOnlyShm==0 || pWal->readOnlyShm==1 );

  /* If the first page of the wal-index has been mapped, try to read the
  ** wal-index header immediately, without holding any lock. This usually
  ** works, but may fail if the wal-index header is corrupt or currently 
  ** being modified by another thread or process.
  */
  badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);

  /* If the first attempt failed, it might have been due to a race
  ** with a writer. So lock the WAL_WRITE_LOCK byte and try again.
  */
  assert( badHdr==0 || pWal->writeLock==0 );
  if( badHdr ){
    if( pWal->readOnlyShm ){
      if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
        walUnlockShared(pWal, WAL_WRITE_LOCK);
        rc = SQLITE_READONLY_RECOVERY;
      }
    }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
      pWal->writeLock = 1;
      if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
        badHdr = walIndexTryHdr(pWal, pChanged);
        if( badHdr ){
          /* If the wal-index header is still malformed even while holding
          ** a WRITE lock, it can only mean that the header is corrupted and
          ** needs to be reconstructed.  So run recovery to do exactly that.
................................................................................
          rc = walIndexRecover(pWal);
          *pChanged = 1;
        }
      }
      pWal->writeLock = 0;
      walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
    }
  }

  /* If the header is read successfully, check the version number to make
  ** sure the wal-index was not constructed with some future format that
  ** this version of SQLite cannot understand.
  */
  if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
    rc = SQLITE_CANTOPEN_BKPT;
................................................................................
      assert( thisMark!=READMARK_NOT_USED );
      mxReadMark = thisMark;
      mxI = i;
    }
  }
  /* There was once an "if" here. The extra "{" is to preserve indentation. */
  {
    if( pWal->readOnlyShm==0 && (mxReadMark < pWal->hdr.mxFrame || mxI==0) ){
      for(i=1; i<WAL_NREADER; i++){
        rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
        if( rc==SQLITE_OK ){
          mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame;
          mxI = i;
          walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
          break;
................................................................................
        }else if( rc!=SQLITE_BUSY ){
          return rc;
        }
      }
    }
    if( mxI==0 ){
      assert( rc==SQLITE_BUSY );
      assert( rc==SQLITE_BUSY || (pWal->readOnlyShm && rc==SQLITE_OK) );
      return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
    }

    rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
    if( rc ){
      return rc==SQLITE_BUSY ? WAL_RETRY : rc;
    }
    /* Now that the read-lock has been obtained, check that neither the
................................................................................
** that extra content is ignored by the current thread.
**
** If the database contents have changes since the previous read
** transaction, then *pChanged is set to 1 before returning.  The
** Pager layer will use this to know that is cache is stale and
** needs to be flushed.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int readOnlyShm, int *pChanged){
  int rc;                         /* Return code */
  int cnt = 0;                    /* Number of TryBeginRead attempts */

  if( pWal->nWiData==0 || pWal->apWiData[0]==0 ){
    assert( readOnlyShm==0 || readOnlyShm==1 );
    pWal->readOnlyShm = readOnlyShm*2;
  }
  do{
    rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
  }while( rc==WAL_RETRY );
  assert( rc || pWal->readOnlyShm==0 || (readOnlyShm && pWal->readOnlyShm==1) );
  testcase( (rc&0xff)==SQLITE_BUSY );
  testcase( (rc&0xff)==SQLITE_IOERR );
  testcase( rc==SQLITE_PROTOCOL );
  testcase( rc==SQLITE_OK );
  return rc;
}

................................................................................
  /* Cannot start a write transaction without first holding a read
  ** transaction. */
  assert( pWal->readLock>=0 );

  if( pWal->readOnly ){
    return SQLITE_READONLY;
  }
  assert( pWal->readOnlyShm==0 );

  /* Only one writer allowed at a time.  Get the write lock.  Return
  ** SQLITE_BUSY if unable.
  */
  rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
  if( rc ){
    return rc;
................................................................................
  int isChanged = 0;              /* True if a new wal-index header is loaded */
  int eMode2 = eMode;             /* Mode to pass to walCheckpoint() */

  assert( pWal->ckptLock==0 );
  assert( pWal->writeLock==0 );

  WALTRACE(("WAL%p: checkpoint begins\n", pWal));
  if( pWal->readOnlyShm ){
    return SQLITE_READONLY;
  }

  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
  if( rc ){
    /* Usually this is SQLITE_BUSY meaning that another thread or process
    ** is already running a checkpoint, or maybe a recovery.  But it might
    ** also be SQLITE_IOERR. */
    return rc;
  }

Changes to src/wal.h.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#define _WAL_H_

#include "sqliteInt.h"

#ifdef SQLITE_OMIT_WAL
# define sqlite3WalOpen(x,y,z)                   0
# define sqlite3WalClose(w,x,y,z)                0
# define sqlite3WalBeginReadTransaction(y,z)     0
# define sqlite3WalEndReadTransaction(z)
# define sqlite3WalRead(v,w,x,y,z)               0
# define sqlite3WalDbsize(y)                     0
# define sqlite3WalBeginWriteTransaction(y)      0
# define sqlite3WalEndWriteTransaction(x)        0
# define sqlite3WalUndo(x,y,z)                   0
# define sqlite3WalSavepoint(y,z)
................................................................................
/* Used by readers to open (lock) and close (unlock) a snapshot.  A 
** snapshot is like a read-transaction.  It is the state of the database
** at an instant in time.  sqlite3WalOpenSnapshot gets a read lock and
** preserves the current state even if the other threads or processes
** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
** transaction and releases the lock.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
void sqlite3WalEndReadTransaction(Wal *pWal);

/* Read a page from the write-ahead log, if it is present. */
int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);

/* If the WAL is not empty, return the size of the database. */
Pgno sqlite3WalDbsize(Wal *pWal);







|







 







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#define _WAL_H_

#include "sqliteInt.h"

#ifdef SQLITE_OMIT_WAL
# define sqlite3WalOpen(x,y,z)                   0
# define sqlite3WalClose(w,x,y,z)                0
# define sqlite3WalBeginReadTransaction(x,y,z)   0
# define sqlite3WalEndReadTransaction(z)
# define sqlite3WalRead(v,w,x,y,z)               0
# define sqlite3WalDbsize(y)                     0
# define sqlite3WalBeginWriteTransaction(y)      0
# define sqlite3WalEndWriteTransaction(x)        0
# define sqlite3WalUndo(x,y,z)                   0
# define sqlite3WalSavepoint(y,z)
................................................................................
/* Used by readers to open (lock) and close (unlock) a snapshot.  A 
** snapshot is like a read-transaction.  It is the state of the database
** at an instant in time.  sqlite3WalOpenSnapshot gets a read lock and
** preserves the current state even if the other threads or processes
** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
** transaction and releases the lock.
*/
int sqlite3WalBeginReadTransaction(Wal *pWal, int, int *);
void sqlite3WalEndReadTransaction(Wal *pWal);

/* Read a page from the write-ahead log, if it is present. */
int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);

/* If the WAL is not empty, return the size of the database. */
Pgno sqlite3WalDbsize(Wal *pWal);

Changes to test/alter.test.

646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
    SELECT $::col_name, $::col_name2 FROM $::tbl_name;
  "
} {4 5}

# Ticket #1665:  Make sure ALTER TABLE ADD COLUMN works on a table
# that includes a COLLATE clause.
#
do_test alter-7.1 {
  execsql {
    CREATE TABLE t1(a TEXT COLLATE BINARY);
    ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE;
    INSERT INTO t1 VALUES(1,'-2');
    INSERT INTO t1 VALUES(5.4e-08,'5.4e-08');
    SELECT typeof(a), a, typeof(b), b FROM t1;
  }







|







646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
    SELECT $::col_name, $::col_name2 FROM $::tbl_name;
  "
} {4 5}

# Ticket #1665:  Make sure ALTER TABLE ADD COLUMN works on a table
# that includes a COLLATE clause.
#
do_realnum_test alter-7.1 {
  execsql {
    CREATE TABLE t1(a TEXT COLLATE BINARY);
    ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE;
    INSERT INTO t1 VALUES(1,'-2');
    INSERT INTO t1 VALUES(5.4e-08,'5.4e-08');
    SELECT typeof(a), a, typeof(b), b FROM t1;
  }

Changes to test/cast.test.

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







|











|











|













|







 







|







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

Added test/e_uri.test.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
# 2011 May 06
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#

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

db close

proc parse_uri {uri} {
  testvfs tvfs2
  testvfs tvfs 
  tvfs filter xOpen
  tvfs script parse_uri_open_cb

  set ::uri_open [list]
  set DB [sqlite3_open_v2 $uri {
    SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL
  } tvfs]
  sqlite3_close $DB
  tvfs delete
  tvfs2 delete

  set ::uri_open
}
proc parse_uri_open_cb {method file arglist} {
  set ::uri_open [list $file $arglist]
}

proc open_uri_error {uri} {
  set flags {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL}
  set DB [sqlite3_open_v2 $uri $flags ""]
  set e [sqlite3_errmsg $DB]
  sqlite3_close $DB
  set e
}

# EVIDENCE-OF: R-35840-33204 If URI filename interpretation is enabled,
# and the filename argument begins with "file:", then the filename is
# interpreted as a URI.
#
# EVIDENCE-OF: R-00067-59538 URI filename interpretation is enabled if
# the SQLITE_OPEN_URI flag is is set in the fourth argument to
# sqlite3_open_v2(), or if it has been enabled globally using the
# SQLITE_CONFIG_URI option with the sqlite3_config() method.
#
if {$tcl_platform(platform) == "unix"} {
  set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE]

  # Tests with SQLITE_CONFIG_URI configured to false. URI intepretation is
  # only enabled if the SQLITE_OPEN_URI flag is specified.
  sqlite3_shutdown
  sqlite3_config_uri 0
  do_test 1.1 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
    list [file exists file:test.db] [file exists test.db]
  } {0 1}
  do_test 1.2 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT
    list [file exists file:test.db2] [file exists test.db2]
  } {0 1}
  sqlite3_close $DB
  do_test 1.3 {
    forcedelete file:test.db test.db
    set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
    list [file exists file:test.db] [file exists test.db]
  } {1 0}
  do_test 1.4 {
    forcedelete file:test.db2 test.db2
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT
    list [file exists file:test.db2] [file exists test.db2]
  } {1 0}
  sqlite3_close $DB

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

# EVIDENCE-OF: R-17482-00398 If the authority is not an empty string or
# "localhost", an error is returned to the caller.
#
if {$tcl_platform(platform) == "unix"} {
  set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
  foreach {tn uri error} "
    1    {file://localhost[pwd]/test.db}     {not an error}
    2    {file://[pwd]/test.db}              {not an error}
    3    {file://x[pwd]/test.db}             {invalid uri authority: x}
    4    {file://invalid[pwd]/test.db}       {invalid uri authority: invalid}
  " {
    do_test 2.$tn {
      set DB [sqlite3_open_v2 $uri $flags ""]
      set e [sqlite3_errmsg $DB]
      sqlite3_close $DB
      set e
    } $error
  }
}

# EVIDENCE-OF: R-43804-65312 The 'fragment' component of a URI, if
# present, is always ignored.
#
#   It is difficult to test that something is ignore correctly. So these tests
#   just show that adding a fragment does not interfere with the pathname or
#   parameters passed through to the VFS xOpen() methods.
#
if {$tcl_platform(platform) == "unix"} {
  foreach {tn uri parse} "
    1    {file:test.db#abc}     {[pwd]/test.db {}}
    2    {file:test.db?a=b#abc} {[pwd]/test.db {a b}}
    3    {file:test.db?a=b#?c=d} {[pwd]/test.db {a b}}
  " {
    do_test 3.$tn { parse_uri $uri } $parse
  }
}

# EVIDENCE-OF: R-00273-20588 SQLite uses the 'path' component of the URI
# as the path to the database file to open.
#
# EVIDENCE-OF: R-28659-11035 If the path begins with a '/' character,
# then it is interpreted as an absolute path.
#
# EVIDENCE-OF: R-39349-47203 If it does not begin with a '/', it is
# interpreted as a relative path.
#
if {$tcl_platform(platform) == "unix"} {
  foreach {tn uri parse} "
    1    {file:test.db}             {[pwd]/test.db {}}
    2    {file:/test.db}            {/test.db {}}
    3    {file:///test.db}          {/test.db {}}
    4    {file://localhost/test.db} {/test.db {}}
    5    {file:/a/b/c/test.db}      {/a/b/c/test.db {}}
  " {
    do_test 4.$tn { parse_uri $uri } $parse
  }
}

# EVIDENCE-OF: R-01612-30877 The "vfs" parameter may be used to specify
# the name of a VFS object that provides the operating system interface
# that should be used to access the database file on disk.
#
#   The above is tested by cases 1.* below.
#
# EVIDENCE-OF: R-52293-58497 If this option is set to an empty string
# the default VFS object is used.
#
#   The above is tested by cases 2.* below.
#
# EVIDENCE-OF: R-31855-18665 If sqlite3_open_v2() is used and the vfs
# option is present, then the VFS specified by the option takes
# precedence over the value passed as the fourth parameter to
# sqlite3_open_v2().
#
#   The above is tested by cases 3.* below.
#
proc vfs_open_cb {name args} {
  set ::vfs $name
}
foreach {name default} {vfs1 0 vfs2 0 vfs3 1} {
  testvfs $name -default $default
  $name filter xOpen
  $name script [list vfs_open_cb $name]
}
foreach {tn uri defvfs vfs} {
  1.1    "file:test.db?vfs=vfs1"    ""    vfs1
  1.2    "file:test.db?vfs=vfs2"    ""    vfs2

  2.1    "file:test.db"             vfs1  vfs1
  2.2    "file:test.db?vfs="        vfs1  vfs3

  3.1    "file:test.db?vfs=vfs1"    vfs2  vfs1
  3.2    "file:test.db?vfs=vfs2"    vfs1  vfs2
  3.3    "file:test.db?xvfs=vfs1"   vfs2  vfs2
  3.4    "file:test.db?xvfs=vfs2"   vfs1  vfs1
} {
  do_test 5.$tn {
    set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
    sqlite3_close [
      sqlite3_open_v2 $uri $flags $defvfs
    ]
    set ::vfs
  } $vfs
}
vfs1 delete
vfs2 delete
vfs3 delete

# EVIDENCE-OF: R-48365-36308 Specifying an unknown VFS is an error.
#
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
do_test 6.1 {
  set DB [sqlite3_open_v2 file:test.db?vfs=nosuchvfs $flags ""]
  set errmsg [sqlite3_errmsg $DB]
  sqlite3_close $DB
  set errmsg
} {no such vfs: nosuchvfs}


# EVIDENCE-OF: R-60479-64270 The mode parameter may be set to either
# "ro", "rw" or "rwc". Attempting to set it to any other value is an
# error
#
sqlite3 db test.db
db close
foreach {tn uri error} "
  1    {file:test.db?mode=ro}    {not an error}
  2    {file:test.db?mode=rw}    {not an error}
  3    {file:test.db?mode=rwc}   {not an error}
  4    {file:test.db?mode=Ro}    {no such access mode: Ro}
  5    {file:test.db?mode=Rw}    {no such access mode: Rw}
  6    {file:test.db?mode=Rwc}   {no such access mode: Rwc}
" {
  do_test 7.$tn { open_uri_error $uri } $error
}


# EVIDENCE-OF: R-09651-31805 If "ro" is specified, then the database is
# opened for read-only access, just as if the SQLITE_OPEN_READONLY flag
# had been set in the third argument to sqlite3_prepare_v2().
#
# EVIDENCE-OF: R-40137-26050 If the mode option is set to "rw", then the
# database is opened for read-write (but not create) access, as if
# SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had been set.
#
# EVIDENCE-OF: R-26845-32976 Value "rwc" is equivalent to setting both
# SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.
#
sqlite3_shutdown
sqlite3_config_uri 1
foreach {tn uri read write create} {
  1    {file:test.db?mode=ro}     1 0 0
  2    {file:test.db?mode=rw}     1 1 0
  3    {file:test.db?mode=rwc}    1 1 1
} {
  set RES(c,0) {1 {unable to open database file}}
  set RES(c,1) {0 {}}
  set RES(w,0) {1 {attempt to write a readonly database}}
  set RES(w,1) {0 {}}
  set RES(r,0) {1 {this never happens}}
  set RES(r,1) {0 {a b}}

  # Test CREATE access:
  forcedelete test.db
  do_test 8.$tn.c { list [catch { sqlite3 db $uri } msg] $msg } $RES(c,$create)
  catch { db close }

  sqlite3 db test.db
  db eval { CREATE TABLE t1(a, b) ; INSERT INTO t1 VALUES('a', 'b') ;}
  db close
  
  # Test READ access:
  do_test 8.$tn.r { 
    sqlite3 db $uri
    catchsql { SELECT * FROM t1 }
  } $RES(r,$read)
  
  # Test WRITE access:
  do_test 8.$tn.w { 
    sqlite3 db $uri
    catchsql { INSERT INTO t1 VALUES(1, 2) }
  } $RES(w,$write)

  catch {db close}
}

# EVIDENCE-OF: R-56032-32287 If sqlite3_open_v2() is used, it is an
# error to specify a value for the mode parameter that is less
# restrictive than that specified by the flags passed as the third
# parameter.
#
forcedelete test.db
sqlite3 db test.db
db close
foreach {tn uri flags error} {
  1   {file:test.db?mode=ro}   ro    {not an error}
  2   {file:test.db?mode=ro}   rw    {not an error}
  3   {file:test.db?mode=ro}   rwc   {not an error}

  4   {file:test.db?mode=rw}   ro    {access mode not allowed: rw}
  5   {file:test.db?mode=rw}   rw    {not an error}
  6   {file:test.db?mode=rw}   rwc   {not an error}

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

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

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

# EVIDENCE-OF: R-23182-54295 The cache parameter may be set to either
# "shared" or "private".
sqlite3 db test.db
db close
foreach {tn uri error} "
  1    {file:test.db?cache=private}    {not an error}
  2    {file:test.db?cache=shared}     {not an error}
  3    {file:test.db?cache=yes}        {no such cache mode: yes}
  4    {file:test.db?cache=}           {no such cache mode: }
" {
  do_test 10.$tn { open_uri_error $uri } $error
}

# EVIDENCE-OF: R-23027-03515 Setting it to "shared" is equivalent to
# setting the SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed
# to sqlite3_open_v2().
#
# EVIDENCE-OF: R-49793-28525 Setting the cache parameter to "private" is
# equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
#
# EVIDENCE-OF: R-19510-48080 If sqlite3_open_v2() is used and the
# "cache" parameter is present in a URI filename, its value overrides
# any behaviour requested by setting SQLITE_OPEN_PRIVATECACHE or
# SQLITE_OPEN_SHAREDCACHE flag.
#
set orig [sqlite3_enable_shared_cache]
foreach {tn uri flags shared_default isshared} {
  1.1   "file:test.db"                  ""         0    0
  1.2   "file:test.db"                  ""         1    1
  1.3   "file:test.db"                  private    0    0
  1.4   "file:test.db"                  private    1    0
  1.5   "file:test.db"                  shared     0    1
  1.6   "file:test.db"                  shared     1    1

  2.1   "file:test.db?cache=private"    ""         0    0
  2.2   "file:test.db?cache=private"    ""         1    0
  2.3   "file:test.db?cache=private"    private    0    0
  2.4   "file:test.db?cache=private"    private    1    0
  2.5   "file:test.db?cache=private"    shared     0    0
  2.6   "file:test.db?cache=private"    shared     1    0

  3.1   "file:test.db?cache=shared"     ""         0    1
  3.2   "file:test.db?cache=shared"     ""         1    1
  3.3   "file:test.db?cache=shared"     private    0    1
  3.4   "file:test.db?cache=shared"     private    1    1
  3.5   "file:test.db?cache=shared"     shared     0    1
  3.6   "file:test.db?cache=shared"     shared     1    1
} {
  forcedelete test.db
  sqlite3_enable_shared_cache 1
  sqlite3 db test.db
  sqlite3_enable_shared_cache 0

  db eval {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES('ok');
  }

  unset -nocomplain f
  set f()        {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI}
  set f(shared)  [concat $f() SQLITE_OPEN_SHAREDCACHE]
  set f(private) [concat $f() SQLITE_OPEN_PRIVATECACHE]

  sqlite3_enable_shared_cache $shared_default
  set DB [sqlite3_open_v2 $uri $f($flags) ""]

  set STMT [sqlite3_prepare $DB "SELECT * FROM t1" -1 dummy]

  db eval {
    BEGIN;
      INSERT INTO t1 VALUES('ko');
  }

  sqlite3_step $STMT
  sqlite3_finalize $STMT

  set RES(0) {not an error}
  set RES(1) {database table is locked: t1}

  do_test 11.$tn { sqlite3_errmsg $DB } $RES($isshared)

  sqlite3_close $DB
  db close
}
sqlite3_enable_shared_cache $orig

# EVIDENCE-OF: R-63472-46769 Specifying an unknown parameter in the
# query component of a URI is not an error.
#
do_test 12.1 {
  parse_uri file://localhost/test.db?an=unknown&parameter=is&ok=
} {/test.db {an unknown parameter is ok {}}}
do_test 12.2 {
  parse_uri file://localhost/test.db?an&unknown&parameter&is&ok
} {/test.db {an {} unknown {} parameter {} is {} ok {}}}

# EVIDENCE-OF: R-27458-04043 URI hexadecimal escape sequences (%HH) are
# supported within the path and query components of a URI.
#
# EVIDENCE-OF: R-52765-50368 Before the path or query components of a
# URI filename are interpreted, they are encoded using UTF-8 and all
# hexadecimal escape sequences replaced by a single byte containing the
# corresponding octet.
#
#   The second of the two statements above is tested by creating a
#   multi-byte utf-8 character using a sequence of %HH escapes.
#
foreach {tn uri parse} "
  1  {file:/test.%64%62}                             {/test.db {}}
  2  {file:/test.db?%68%65%6c%6c%6f=%77%6f%72%6c%64} {/test.db {hello world}}
  3  {file:/%C3%BF.db}                               {/\xFF.db {}}
" {
  do_test 13.$tn { parse_uri $uri } $parse
}

finish_test

Changes to test/expr.test.

28
29
30
31
32
33
34





35
36
37
38
39
40
41
...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
...
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
...
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
}

proc test_expr {name settings expr result} {
  do_test $name [format {
    execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
  } $settings $expr] $result
}






test_expr expr-1.1 {i1=10, i2=20} {i1+i2} 30
test_expr expr-1.2 {i1=10, i2=20} {i1-i2} -10
test_expr expr-1.3 {i1=10, i2=20} {i1*i2} 200
test_expr expr-1.4 {i1=10, i2=20} {i1/i2} 0
test_expr expr-1.5 {i1=10, i2=20} {i2/i1} 2
test_expr expr-1.6 {i1=10, i2=20} {i2<i1} 0
................................................................................
ifcapable floatingpoint {
  test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0
  test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0
  test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1
}

if {[working_64bit_int]} {
  test_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18
}

test_expr expr-1.107 {i1=0} {-9223372036854775808%-1} 0
test_expr expr-1.108 {i1=0} {1%0} {{}}
test_expr expr-1.109 {i1=0} {1/0} {{}}

if {[working_64bit_int]} {
................................................................................
  {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.126 {i1=8, i2=8} \
  {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no

ifcapable floatingpoint {if {[working_64bit_int]} {
  test_expr expr-1.200\
      {i1=9223372036854775806, i2=1} {i1+i2}      9223372036854775807
  test_expr expr-1.201\
      {i1=9223372036854775806, i2=2} {i1+i2}      9.22337203685478e+18
  test_expr expr-1.202\
      {i1=9223372036854775806, i2=100000} {i1+i2} 9.22337203685488e+18
  test_expr expr-1.203\
      {i1=9223372036854775807, i2=0} {i1+i2}      9223372036854775807
  test_expr expr-1.204\
      {i1=9223372036854775807, i2=1} {i1+i2}      9.22337203685478e+18
  test_expr expr-1.205\
      {i2=9223372036854775806, i1=1} {i1+i2}      9223372036854775807
  test_expr expr-1.206\
      {i2=9223372036854775806, i1=2} {i1+i2}      9.22337203685478e+18
  test_expr expr-1.207\
      {i2=9223372036854775806, i1=100000} {i1+i2} 9.22337203685488e+18
  test_expr expr-1.208\
      {i2=9223372036854775807, i1=0} {i1+i2}      9223372036854775807
  test_expr expr-1.209\
      {i2=9223372036854775807, i1=1} {i1+i2}      9.22337203685478e+18
  test_expr expr-1.210\
      {i1=-9223372036854775807, i2=-1} {i1+i2}    -9223372036854775808
  test_expr expr-1.211\
      {i1=-9223372036854775807, i2=-2} {i1+i2}    -9.22337203685478e+18
  test_expr expr-1.212\
      {i1=-9223372036854775807, i2=-100000} {i1+i2} -9.22337203685488e+18
  test_expr expr-1.213\
      {i1=-9223372036854775808, i2=0} {i1+i2}     -9223372036854775808
  test_expr expr-1.214\
      {i1=-9223372036854775808, i2=-1} {i1+i2}    -9.22337203685478e+18
  test_expr expr-1.215\
      {i2=-9223372036854775807, i1=-1} {i1+i2}    -9223372036854775808
  test_expr expr-1.216\
      {i2=-9223372036854775807, i1=-2} {i1+i2}    -9.22337203685478e+18
  test_expr expr-1.217\
      {i2=-9223372036854775807, i1=-100000} {i1+i2} -9.22337203685488e+18
  test_expr expr-1.218\
      {i2=-9223372036854775808, i1=0} {i1+i2}     -9223372036854775808
  test_expr expr-1.219\
      {i2=-9223372036854775808, i1=-1} {i1+i2}    -9.22337203685478e+18
  test_expr expr-1.220\
      {i1=9223372036854775806, i2=-1} {i1-i2}     9223372036854775807
  test_expr expr-1.221\
      {i1=9223372036854775806, i2=-2} {i1-i2}      9.22337203685478e+18
  test_expr expr-1.222\
      {i1=9223372036854775806, i2=-100000} {i1-i2} 9.22337203685488e+18
  test_expr expr-1.223\
      {i1=9223372036854775807, i2=0} {i1-i2}      9223372036854775807
  test_expr expr-1.224\
      {i1=9223372036854775807, i2=-1} {i1-i2}      9.22337203685478e+18
  test_expr expr-1.225\
      {i2=-9223372036854775806, i1=1} {i1-i2}      9223372036854775807
  test_expr expr-1.226\
      {i2=-9223372036854775806, i1=2} {i1-i2}      9.22337203685478e+18
  test_expr expr-1.227\
      {i2=-9223372036854775806, i1=100000} {i1-i2} 9.22337203685488e+18
  test_expr expr-1.228\
      {i2=-9223372036854775807, i1=0} {i1-i2}      9223372036854775807
  test_expr expr-1.229\
      {i2=-9223372036854775807, i1=1} {i1-i2}      9.22337203685478e+18
  test_expr expr-1.230\
      {i1=-9223372036854775807, i2=1} {i1-i2}    -9223372036854775808
  test_expr expr-1.231\
      {i1=-9223372036854775807, i2=2} {i1-i2}    -9.22337203685478e+18
  test_expr expr-1.232\
      {i1=-9223372036854775807, i2=100000} {i1-i2} -9.22337203685488e+18
  test_expr expr-1.233\
      {i1=-9223372036854775808, i2=0} {i1-i2}     -9223372036854775808
  test_expr expr-1.234\
      {i1=-9223372036854775808, i2=1} {i1-i2}    -9.22337203685478e+18
  test_expr expr-1.235\
      {i2=9223372036854775807, i1=-1} {i1-i2}    -9223372036854775808
  test_expr expr-1.236\
      {i2=9223372036854775807, i1=-2} {i1-i2}    -9.22337203685478e+18
  test_expr expr-1.237\
      {i2=9223372036854775807, i1=-100000} {i1-i2} -9.22337203685488e+18
  test_expr expr-1.238\
      {i2=9223372036854775807, i1=0} {i1-i2}     -9223372036854775807
  test_expr expr-1.239\
      {i2=9223372036854775807, i1=-1} {i1-i2}    -9223372036854775808

  test_expr expr-1.250\
      {i1=4294967296, i2=2147483648} {i1*i2}      9.22337203685478e+18
  test_expr expr-1.251\
      {i1=4294967296, i2=2147483647} {i1*i2}      9223372032559808512
  test_expr expr-1.252\
      {i1=-4294967296, i2=2147483648} {i1*i2}     -9223372036854775808
  test_expr expr-1.253\
      {i1=-4294967296, i2=2147483647} {i1*i2}     -9223372032559808512
  test_expr expr-1.254\
      {i1=4294967296, i2=-2147483648} {i1*i2}     -9223372036854775808
  test_expr expr-1.255\
      {i1=4294967296, i2=-2147483647} {i1*i2}     -9223372032559808512
  test_expr expr-1.256\
      {i1=-4294967296, i2=-2147483648} {i1*i2}    9.22337203685478e+18
  test_expr expr-1.257\
      {i1=-4294967296, i2=-2147483647} {i1*i2}    9223372032559808512

}}

ifcapable floatingpoint {
  test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
  test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
................................................................................
do_test expr-12.2 {
  catchsql {
    SELECT (CASE WHEN a>4 THEN 1 ELSE 0) FROM test1;
  }
} {1 {near ")": syntax error}}

ifcapable floatingpoint {
  do_test expr-13.1 {
    execsql {
      SELECT 12345678901234567890;
    }
  } {1.23456789012346e+19}
}

# Implicit String->Integer conversion is used when possible.
................................................................................
    }
  } {9223372036854775807}
}

# If the value is too large, use String->Float conversion.
#
ifcapable floatingpoint {
  do_test expr-13.4 {
    execsql {
      SELECT 0+'9223372036854775808'
    }
  } {9.22337203685478e+18}
  do_test expr-13.5 {
    execsql {
      SELECT '9223372036854775808'+0
    }
  } {9.22337203685478e+18}
}

# Use String->float conversion if the value is explicitly a floating
# point value.
#
do_test expr-13.6 {
  execsql {
    SELECT 0+'9223372036854775807.0'
  }
} {9.22337203685478e+18}
do_test expr-13.7 {
  execsql {
    SELECT '9223372036854775807.0'+0
  }
} {9.22337203685478e+18}


finish_test







>
>
>
>
>







 







|







 







|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|


|

|

|

|

|

|

|

|







 







|







 







|




|









|




|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
...
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
...
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
}

proc test_expr {name settings expr result} {
  do_test $name [format {
    execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
  } $settings $expr] $result
}
proc test_realnum_expr {name settings expr result} {
  do_realnum_test $name [format {
    execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
  } $settings $expr] $result
}

test_expr expr-1.1 {i1=10, i2=20} {i1+i2} 30
test_expr expr-1.2 {i1=10, i2=20} {i1-i2} -10
test_expr expr-1.3 {i1=10, i2=20} {i1*i2} 200
test_expr expr-1.4 {i1=10, i2=20} {i1/i2} 0
test_expr expr-1.5 {i1=10, i2=20} {i2/i1} 2
test_expr expr-1.6 {i1=10, i2=20} {i2<i1} 0
................................................................................
ifcapable floatingpoint {
  test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0
  test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0
  test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1
}

if {[working_64bit_int]} {
  test_realnum_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18
}

test_expr expr-1.107 {i1=0} {-9223372036854775808%-1} 0
test_expr expr-1.108 {i1=0} {1%0} {{}}
test_expr expr-1.109 {i1=0} {1/0} {{}}

if {[working_64bit_int]} {
................................................................................
  {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} yes
test_expr expr-1.126 {i1=8, i2=8} \
  {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no

ifcapable floatingpoint {if {[working_64bit_int]} {
  test_expr expr-1.200\
      {i1=9223372036854775806, i2=1} {i1+i2}      9223372036854775807
  test_realnum_expr expr-1.201\
      {i1=9223372036854775806, i2=2} {i1+i2}      9.22337203685478e+18
  test_realnum_expr expr-1.202\
      {i1=9223372036854775806, i2=100000} {i1+i2} 9.22337203685488e+18
  test_realnum_expr expr-1.203\
      {i1=9223372036854775807, i2=0} {i1+i2}      9223372036854775807
  test_realnum_expr expr-1.204\
      {i1=9223372036854775807, i2=1} {i1+i2}      9.22337203685478e+18
  test_realnum_expr expr-1.205\
      {i2=9223372036854775806, i1=1} {i1+i2}      9223372036854775807
  test_realnum_expr expr-1.206\
      {i2=9223372036854775806, i1=2} {i1+i2}      9.22337203685478e+18
  test_realnum_expr expr-1.207\
      {i2=9223372036854775806, i1=100000} {i1+i2} 9.22337203685488e+18
  test_realnum_expr expr-1.208\
      {i2=9223372036854775807, i1=0} {i1+i2}      9223372036854775807
  test_realnum_expr expr-1.209\
      {i2=9223372036854775807, i1=1} {i1+i2}      9.22337203685478e+18
  test_realnum_expr expr-1.210\
      {i1=-9223372036854775807, i2=-1} {i1+i2}    -9223372036854775808
  test_realnum_expr expr-1.211\
      {i1=-9223372036854775807, i2=-2} {i1+i2}    -9.22337203685478e+18
  test_realnum_expr expr-1.212\
      {i1=-9223372036854775807, i2=-100000} {i1+i2} -9.22337203685488e+18
  test_realnum_expr expr-1.213\
      {i1=-9223372036854775808, i2=0} {i1+i2}     -9223372036854775808
  test_realnum_expr expr-1.214\
      {i1=-9223372036854775808, i2=-1} {i1+i2}    -9.22337203685478e+18
  test_realnum_expr expr-1.215\
      {i2=-9223372036854775807, i1=-1} {i1+i2}    -9223372036854775808
  test_realnum_expr expr-1.216\
      {i2=-9223372036854775807, i1=-2} {i1+i2}    -9.22337203685478e+18
  test_realnum_expr expr-1.217\
      {i2=-9223372036854775807, i1=-100000} {i1+i2} -9.22337203685488e+18
  test_realnum_expr expr-1.218\
      {i2=-9223372036854775808, i1=0} {i1+i2}     -9223372036854775808
  test_realnum_expr expr-1.219\
      {i2=-9223372036854775808, i1=-1} {i1+i2}    -9.22337203685478e+18
  test_realnum_expr expr-1.220\
      {i1=9223372036854775806, i2=-1} {i1-i2}     9223372036854775807
  test_realnum_expr expr-1.221\
      {i1=9223372036854775806, i2=-2} {i1-i2}      9.22337203685478e+18
  test_realnum_expr expr-1.222\
      {i1=9223372036854775806, i2=-100000} {i1-i2} 9.22337203685488e+18
  test_realnum_expr expr-1.223\
      {i1=9223372036854775807, i2=0} {i1-i2}      9223372036854775807
  test_realnum_expr expr-1.224\
      {i1=9223372036854775807, i2=-1} {i1-i2}      9.22337203685478e+18
  test_realnum_expr expr-1.225\
      {i2=-9223372036854775806, i1=1} {i1-i2}      9223372036854775807
  test_realnum_expr expr-1.226\
      {i2=-9223372036854775806, i1=2} {i1-i2}      9.22337203685478e+18
  test_realnum_expr expr-1.227\
      {i2=-9223372036854775806, i1=100000} {i1-i2} 9.22337203685488e+18
  test_realnum_expr expr-1.228\
      {i2=-9223372036854775807, i1=0} {i1-i2}      9223372036854775807
  test_realnum_expr expr-1.229\
      {i2=-9223372036854775807, i1=1} {i1-i2}      9.22337203685478e+18
  test_realnum_expr expr-1.230\
      {i1=-9223372036854775807, i2=1} {i1-i2}    -9223372036854775808
  test_realnum_expr expr-1.231\
      {i1=-9223372036854775807, i2=2} {i1-i2}    -9.22337203685478e+18
  test_realnum_expr expr-1.232\
      {i1=-9223372036854775807, i2=100000} {i1-i2} -9.22337203685488e+18
  test_realnum_expr expr-1.233\
      {i1=-9223372036854775808, i2=0} {i1-i2}     -9223372036854775808
  test_realnum_expr expr-1.234\
      {i1=-9223372036854775808, i2=1} {i1-i2}    -9.22337203685478e+18
  test_realnum_expr expr-1.235\
      {i2=9223372036854775807, i1=-1} {i1-i2}    -9223372036854775808
  test_realnum_expr expr-1.236\
      {i2=9223372036854775807, i1=-2} {i1-i2}    -9.22337203685478e+18
  test_realnum_expr expr-1.237\
      {i2=9223372036854775807, i1=-100000} {i1-i2} -9.22337203685488e+18
  test_realnum_expr expr-1.238\
      {i2=9223372036854775807, i1=0} {i1-i2}     -9223372036854775807
  test_realnum_expr expr-1.239\
      {i2=9223372036854775807, i1=-1} {i1-i2}    -9223372036854775808

  test_realnum_expr expr-1.250\
      {i1=4294967296, i2=2147483648} {i1*i2}      9.22337203685478e+18
  test_realnum_expr expr-1.251\
      {i1=4294967296, i2=2147483647} {i1*i2}      9223372032559808512
  test_realnum_expr expr-1.252\
      {i1=-4294967296, i2=2147483648} {i1*i2}     -9223372036854775808
  test_realnum_expr expr-1.253\
      {i1=-4294967296, i2=2147483647} {i1*i2}     -9223372032559808512
  test_realnum_expr expr-1.254\
      {i1=4294967296, i2=-2147483648} {i1*i2}     -9223372036854775808
  test_realnum_expr expr-1.255\
      {i1=4294967296, i2=-2147483647} {i1*i2}     -9223372032559808512
  test_realnum_expr expr-1.256\
      {i1=-4294967296, i2=-2147483648} {i1*i2}    9.22337203685478e+18
  test_realnum_expr expr-1.257\
      {i1=-4294967296, i2=-2147483647} {i1*i2}    9223372032559808512

}}

ifcapable floatingpoint {
  test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
  test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
................................................................................
do_test expr-12.2 {
  catchsql {
    SELECT (CASE WHEN a>4 THEN 1 ELSE 0) FROM test1;
  }
} {1 {near ")": syntax error}}

ifcapable floatingpoint {
  do_realnum_test expr-13.1 {
    execsql {
      SELECT 12345678901234567890;
    }
  } {1.23456789012346e+19}
}

# Implicit String->Integer conversion is used when possible.
................................................................................
    }
  } {9223372036854775807}
}

# If the value is too large, use String->Float conversion.
#
ifcapable floatingpoint {
  do_realnum_test expr-13.4 {
    execsql {
      SELECT 0+'9223372036854775808'
    }
  } {9.22337203685478e+18}
  do_realnum_test expr-13.5 {
    execsql {
      SELECT '9223372036854775808'+0
    }
  } {9.22337203685478e+18}
}

# Use String->float conversion if the value is explicitly a floating
# point value.
#
do_realnum_test expr-13.6 {
  execsql {
    SELECT 0+'9223372036854775807.0'
  }
} {9.22337203685478e+18}
do_realnum_test expr-13.7 {
  execsql {
    SELECT '9223372036854775807.0'+0
  }
} {9.22337203685478e+18}


finish_test

Changes to test/lock_common.tcl.

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
    proc csql1 {sql} { list [catch { sql1 $sql } msg] $msg }
    proc csql2 {sql} { list [catch { sql2 $sql } msg] $msg }
    proc csql3 {sql} { list [catch { sql3 $sql } msg] $msg }

    uplevel set $varname $tn
    uplevel $script

    code2 { db2 close }
    code3 { db3 close }
    catch { close $::code2_chan }
    catch { close $::code3_chan }
    catch { db close }
  }
}

# Launch another testfixture process to be controlled by this one. A







|
|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
    proc csql1 {sql} { list [catch { sql1 $sql } msg] $msg }
    proc csql2 {sql} { list [catch { sql2 $sql } msg] $msg }
    proc csql3 {sql} { list [catch { sql3 $sql } msg] $msg }

    uplevel set $varname $tn
    uplevel $script

    catch { code2 { db2 close } }
    catch { code3 { db3 close } }
    catch { close $::code2_chan }
    catch { close $::code3_chan }
    catch { db close }
  }
}

# Launch another testfixture process to be controlled by this one. A

Changes to test/nan.test.

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  set ::STMT [sqlite3_prepare db "INSERT INTO t1 VALUES(?)" -1 TAIL]
  sqlite3_bind_double $::STMT 1 NaN
  sqlite3_step $::STMT
  sqlite3_reset $::STMT
  db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
if {$tcl_platform(platform) != "symbian"} {
  do_test nan-1.1.2 {
    sqlite3_bind_double $::STMT 1 +Inf
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real}
  do_test nan-1.1.3 {
    sqlite3_bind_double $::STMT 1 -Inf
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real -inf real}
  do_test nan-1.1.4 {
    sqlite3_bind_double $::STMT 1 -NaN
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real -inf real {} null}
  do_test nan-1.1.5 {
    sqlite3_bind_double $::STMT 1 NaN0
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real -inf real {} null {} null}
  do_test nan-1.1.6 {
    sqlite3_bind_double $::STMT 1 -NaN0
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real -inf real {} null {} null {} null}
  do_test nan-1.1.7 {
    db eval {
................................................................................
  db eval {SELECT x, typeof(x) FROM t1}
} {1e+308 real}

if {$tcl_platform(platform) != "symbian"} {
  # Do not run these tests on Symbian, as the Tcl port doesn't like to
  # convert from floating point value "-inf" to a string.
  #
  do_test nan-4.7 {
    db eval {DELETE FROM t1}
    db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)"
    db eval {SELECT x, typeof(x) FROM t1}
  } {inf real}
  do_test nan-4.8 {
    db eval {DELETE FROM t1}
    db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)"
    db eval {SELECT x, typeof(x) FROM t1}
  } {-inf real}
}
do_test nan-4.9 {
  db eval {DELETE FROM t1}
................................................................................
  db eval {DELETE FROM t1}
  set small \
      -[string repeat 0 10000].[string repeat 0 323][string repeat 9 10000]
  db eval "INSERT INTO t1 VALUES($small)"
  db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
} {-9.88131291682493e-324 real}

do_test nan-4.20 {
  db eval {DELETE FROM t1}
  set big [string repeat 9 10000].0e-9000
  db eval "INSERT INTO t1 VALUES($big)"
  db eval {SELECT x, typeof(x) FROM t1}
} {inf real}



finish_test







|





|





|





|





|







 







|




|







 







|









38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  set ::STMT [sqlite3_prepare db "INSERT INTO t1 VALUES(?)" -1 TAIL]
  sqlite3_bind_double $::STMT 1 NaN
  sqlite3_step $::STMT
  sqlite3_reset $::STMT
  db eval {SELECT x, typeof(x) FROM t1}
} {{} null}
if {$tcl_platform(platform) != "symbian"} {
  do_realnum_test nan-1.1.2 {
    sqlite3_bind_double $::STMT 1 +Inf
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real}
  do_realnum_test nan-1.1.3 {
    sqlite3_bind_double $::STMT 1 -Inf
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real -inf real}
  do_realnum_test nan-1.1.4 {
    sqlite3_bind_double $::STMT 1 -NaN
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real -inf real {} null}
  do_realnum_test nan-1.1.5 {
    sqlite3_bind_double $::STMT 1 NaN0
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real -inf real {} null {} null}
  do_realnum_test nan-1.1.6 {
    sqlite3_bind_double $::STMT 1 -NaN0
    sqlite3_step $::STMT
    sqlite3_reset $::STMT
    db eval {SELECT x, typeof(x) FROM t1}
  } {{} null inf real -inf real {} null {} null {} null}
  do_test nan-1.1.7 {
    db eval {
................................................................................
  db eval {SELECT x, typeof(x) FROM t1}
} {1e+308 real}

if {$tcl_platform(platform) != "symbian"} {
  # Do not run these tests on Symbian, as the Tcl port doesn't like to
  # convert from floating point value "-inf" to a string.
  #
  do_realnum_test nan-4.7 {
    db eval {DELETE FROM t1}
    db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)"
    db eval {SELECT x, typeof(x) FROM t1}
  } {inf real}
  do_realnum_test nan-4.8 {
    db eval {DELETE FROM t1}
    db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)"
    db eval {SELECT x, typeof(x) FROM t1}
  } {-inf real}
}
do_test nan-4.9 {
  db eval {DELETE FROM t1}
................................................................................
  db eval {DELETE FROM t1}
  set small \
      -[string repeat 0 10000].[string repeat 0 323][string repeat 9 10000]
  db eval "INSERT INTO t1 VALUES($small)"
  db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
} {-9.88131291682493e-324 real}

do_realnum_test nan-4.20 {
  db eval {DELETE FROM t1}
  set big [string repeat 9 10000].0e-9000
  db eval "INSERT INTO t1 VALUES($big)"
  db eval {SELECT x, typeof(x) FROM t1}
} {inf real}



finish_test

Changes to test/pager1.test.

1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
....
2377
2378
2379
2380
2381
2382
2383

2384
2385
2386
2387
2388
2389
2390
....
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
#-------------------------------------------------------------------------
# Check that it is not possible to open a database file if the full path
# to the associated journal file will be longer than sqlite3_vfs.mxPathname.
#
testvfs tv -default 1
tv script xOpenCb
tv filter xOpen
proc xOpenCb {method filename} {
  set ::file_len [string length $filename]
}
sqlite3 db test.db
db close
tv delete

for {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} {
................................................................................
} {exclusive 0 main reserved temp closed}

#-------------------------------------------------------------------------
# Test that if the "page-size" field in a journal-header is 0, the journal
# file can still be rolled back. This is required for backward compatibility -
# versions of SQLite prior to 3.5.8 always set this field to zero.
#

do_test pager1-31.1 {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA cache_size = 10;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(x, y, UNIQUE(x, y));
    INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500));
................................................................................
  file copy test.db test.db2
  file copy test.db-journal test.db2-journal
  
  hexio_write test.db2-journal 24 00000000
  sqlite3 db2 test.db2
  execsql { PRAGMA integrity_check } db2
} {ok}



finish_test







|







 







>







 







|



1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
....
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
....
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
#-------------------------------------------------------------------------
# Check that it is not possible to open a database file if the full path
# to the associated journal file will be longer than sqlite3_vfs.mxPathname.
#
testvfs tv -default 1
tv script xOpenCb
tv filter xOpen
proc xOpenCb {method filename args} {
  set ::file_len [string length $filename]
}
sqlite3 db test.db
db close
tv delete

for {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} {
................................................................................
} {exclusive 0 main reserved temp closed}

#-------------------------------------------------------------------------
# Test that if the "page-size" field in a journal-header is 0, the journal
# file can still be rolled back. This is required for backward compatibility -
# versions of SQLite prior to 3.5.8 always set this field to zero.
#
if {$tcl_platform(platform)=="unix"} {
do_test pager1-31.1 {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA cache_size = 10;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(x, y, UNIQUE(x, y));
    INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500));
................................................................................
  file copy test.db test.db2
  file copy test.db-journal test.db2-journal
  
  hexio_write test.db2-journal 24 00000000
  sqlite3 db2 test.db2
  execsql { PRAGMA integrity_check } db2
} {ok}
}


finish_test

Changes to test/tester.tcl.

349
350
351
352
353
354
355









356
357
358
359
360
361
362
    puts "\nExpected: \[$expected\]\n     Got: \[$result\]"
    fail_test $name
  } else {
    puts " Ok"
  }
  flush stdout
}










proc fix_testname {varname} {
  upvar $varname testname
  if {[info exists ::testprefix] 
   && [string is digit [string range $testname 0 0]]
  } {
    set testname "${::testprefix}-$testname"







>
>
>
>
>
>
>
>
>







349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
    puts "\nExpected: \[$expected\]\n     Got: \[$result\]"
    fail_test $name
  } else {
    puts " Ok"
  }
  flush stdout
}

proc realnum_normalize {r} {
  string map {1.#INF inf} [regsub -all {(e[+-])0+} $r {\1}]
}
proc do_realnum_test {name cmd expected} {
  uplevel [list do_test $name [
    subst -nocommands { realnum_normalize [ $cmd ] }
  ] [realnum_normalize $expected]]
}

proc fix_testname {varname} {
  upvar $varname testname
  if {[info exists ::testprefix] 
   && [string is digit [string range $testname 0 0]]
  } {
    set testname "${::testprefix}-$testname"

Changes to test/tkt3838.test.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
source $testdir/tester.tcl

ifcapable !altertable {
  finish_test
  return
}

do_test tkt3838-1.1 {
  db eval {
    PRAGMA encoding=UTF16;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    ALTER TABLE t1 ADD COLUMN b INTEGER DEFAULT '999';
    ALTER TABLE t1 ADD COLUMN c REAL DEFAULT '9e99';
    ALTER TABLE t1 ADD COLUMN d TEXT DEFAULT 'xyzzy';
    UPDATE t1 SET x=x+1;
    SELECT * FROM t1;
  }
} {2 999 9e+99 xyzzy}

finish_test







|













21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
source $testdir/tester.tcl

ifcapable !altertable {
  finish_test
  return
}

do_realnum_test tkt3838-1.1 {
  db eval {
    PRAGMA encoding=UTF16;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    ALTER TABLE t1 ADD COLUMN b INTEGER DEFAULT '999';
    ALTER TABLE t1 ADD COLUMN c REAL DEFAULT '9e99';
    ALTER TABLE t1 ADD COLUMN d TEXT DEFAULT 'xyzzy';
    UPDATE t1 SET x=x+1;
    SELECT * FROM t1;
  }
} {2 999 9e+99 xyzzy}

finish_test

Changes to test/tkt3922.test.

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

finish_test







|






|






|







 







|








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

finish_test

Added test/uri.test.











































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# 2011 April 22
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#

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

# Test organization:
#
#   1.*: That file names are correctly extracted from URIs.
#   2.*: That URI options (query parameters) are correctly extracted from URIs.
#   3.*: That specifying an unknown VFS causes an error.
#   4.*: Tests for specifying other options (other than "vfs").
#   5.*: Test using a different VFS with an attached database.
#   6.*: Test that authorities other than "" and localhost cause errors.
#   7.*: Test that a read-write db can be attached to a read-only connection.
#

set testprefix uri
db close
sqlite3_shutdown
sqlite3_config_uri 1

#-------------------------------------------------------------------------
# Test that file names are correctly extracted from URIs.
#
foreach {tn uri file} {
  1      test.db                              test.db
  2      file:test.db                         test.db
  3      file://PWD/test.db                   test.db
  4      file:PWD/test.db                     test.db
  5      file:test.db?mork=1                  test.db
  6      file:test.db?mork=1&tonglor=2        test.db
  7      file:test.db?mork=1#boris            test.db
  8      file:test.db#boris                   test.db
  9      test.db#boris                        test.db#boris
  10     file:test%2Edb                       test.db
  11     file                                 file
  12     http:test.db                         http:test.db
  13     file:test.db%00extra                 test.db
  14     file:test%00.db%00extra              test

  15     test.db?mork=1#boris                 test.db?mork=1#boris
  16     file://localhostPWD/test.db%3Fhello  test.db?hello
} {
  
  if {$tcl_platform(platform)=="windows"} {
    if {$tn>14} break
    set uri  [string map [list PWD /[pwd]] $uri]
  } else {
    set uri  [string map [list PWD [pwd]] $uri]
  }

  forcedelete $file
  do_test 1.$tn.1 { file exists $file } 0
  set DB [sqlite3_open $uri]
  do_test 1.$tn.2 { file exists $file } 1
  sqlite3_close $DB
  forcedelete $file

  do_test 1.$tn.3 { file exists $file } 0
  sqlite3 db xxx.db
  catchsql { ATTACH $uri AS aux }
  do_test 1.$tn.4 { file exists $file } 1
  db close
}

#-------------------------------------------------------------------------
# Test that URI query parameters are passed through to the VFS layer
# correctly.
#
testvfs tvfs2
testvfs tvfs -default 1
tvfs filter xOpen
tvfs script open_method
proc open_method {method file arglist} {
  set ::arglist $arglist
}
foreach {tn uri kvlist} {
  1      file:test.db?hello=world                     {hello world}
  2      file:test.db?hello&world                     {hello {} world {}}
  3      file:test.db?hello=1&world=2&vfs=tvfs        {hello 1 world 2 vfs tvfs}
  4      file:test.db?hello=1&world=2&vfs=tvfs2        {}
  5      file:test.db?%68%65%6C%6C%6F=%77%6F%72%6C%64 {hello world}
  6      file:test%00.db?hello%00extra=world%00ex     {hello world}
  7      file:test%00.db?hello%00=world%00            {hello world}
  8      file:test%00.db?=world&xyz=abc               {xyz abc}
  9      file:test.db?%00hello=world&xyz=abc          {xyz abc}
  10     file:test.db?hello=%00world&xyz=             {hello {} xyz {}}
  11     file:test.db?=#ravada                        {}
  12     file:test.db?&&&&&&&&hello=world&&&&&&&      {hello world}

  13     test.db?&&&&&&&&hello=world&&&&&&&           {}
  14     http:test.db?hello&world                     {}
} {

  if {$tcl_platform(platform) == "windows" && $tn>12} {
    continue
  }

  set ::arglist ""
  set DB [sqlite3_open $uri]
  do_test 2.$tn.1 { set ::arglist } $kvlist
  sqlite3_close $DB

  sqlite3 db xxx.db
  set ::arglist ""
  execsql { ATTACH $uri AS aux }
  do_test 2.$tn.2 { set ::arglist } $kvlist
  db close
}
tvfs delete
tvfs2 delete

#-------------------------------------------------------------------------
# Test that specifying a non-existent VFS raises an error.
#
do_test 3.1 {
  list [catch { sqlite3 db "file:test.db?vfs=nosuchvfs" } msg] $msg
} {1 {no such vfs: nosuchvfs}}

#-------------------------------------------------------------------------
# Test some of the other options (other than "vfs").
#
foreach {tn mode create_ok write_ok readonly_ok} {
  1    ro    0   0   1
  2    rw    0   1   0
  3    rwc   1   1   0
} {
  catch { db close }
  forcedelete test.db

  set A(1) {0 {}}
  set A(0) {1 {unable to open database file}}
  do_test 4.1.$tn.1 {
    list [catch {sqlite3 db "file:test.db?mode=$mode"} msg] $msg
  } $A($create_ok)

  catch { db close }
  forcedelete test.db
  sqlite3 db test.db
  db eval { CREATE TABLE t1(a, b) }
  db close

  set A(1) {0 {}}
  set A(0) {1 {attempt to write a readonly database}}
  do_test 4.1.$tn.2 {
    sqlite3 db "file:test.db?mode=$mode"
    catchsql { INSERT INTO t1 VALUES(1, 2) }
  } $A($write_ok)

  set A(1) {0 {}}
  set A(0) [list 1 "access mode not allowed: $mode"]
  do_test 4.1.$tn.3 {
    list [catch {sqlite3 db "file:test.db?mode=$mode" -readonly 1} msg] $msg
  } $A($readonly_ok)
}

set orig [sqlite3_enable_shared_cache]
foreach {tn options sc_default is_shared} {
  1    ""                1   1
  2    "cache=private"   1   0
  3    "cache=shared"    1   1
  4    ""                0   0
  5    "cache=private"   0   0
  6    "cache=shared"    0   1
} {
  catch { db close }
  forcedelete test.db

  sqlite3_enable_shared_cache 1
  sqlite3 db2 test.db
  db2 eval {CREATE TABLE t1(a, b)}

  sqlite3_enable_shared_cache $sc_default
  sqlite3 db "file:test.db?$options"
  db eval {SELECT * FROM t1}

  set A(1) {1 {database table is locked: t1}}
  set A(0) {0 {}}
  do_test 4.2.$tn {
    db2 eval {BEGIN; INSERT INTO t1 VALUES(1, 2);}
    catchsql { SELECT * FROM t1 }
  } $A($is_shared)

  db2 close
}

do_test 4.3.1 {
  list [catch {sqlite3 db "file:test.db?mode=rc"} msg] $msg
} {1 {no such access mode: rc}}
do_test 4.3.2 {
  list [catch {sqlite3 db "file:test.db?cache=public"} msg] $msg
} {1 {no such cache mode: public}}

#-------------------------------------------------------------------------
# Test that things work if an ATTACHed database uses a different VFS than
# the main database. The important point is that for all operations 
# involving the ATTACHed database, the correct versions of the following
# VFS are used for all operations involving the attached database.
#
#     xOpen
#     xDelete
#     xAccess
#     xFullPathname
#

# This block of code creates two VFS - "tvfs1" and "tvfs2". Each time one
# of the above methods is called using "tvfs1", global variable ::T1(X) is
# set, where X is the file-name the method is called on. Calls to the above
# methods using "tvfs2" set entries in the global T2 array.
#
testvfs tvfs1 
tvfs1 filter {xOpen xDelete xAccess xFullPathname}
tvfs1 script tvfs1_callback
proc tvfs1_callback {method filename args} { 
  set ::T1([file tail $filename]) 1 
}
testvfs tvfs2 
tvfs2 filter {xOpen xDelete xAccess xFullPathname}
tvfs2 script tvfs2_callback
proc tvfs2_callback {method filename args} { 
  set ::T2([file tail $filename]) 1 
}

catch {db close}
eval forcedelete [glob test.db*]
do_test 5.1.1 {
  sqlite3 db file:test.db1?vfs=tvfs1
  execsql {
    ATTACH 'file:test.db2?vfs=tvfs2' AS aux;
    PRAGMA main.journal_mode = PERSIST;
    PRAGMA aux.journal_mode = PERSIST;
    CREATE TABLE t1(a, b);
    CREATE TABLE aux.t2(a, b);
    PRAGMA main.journal_mode = WAL;
    PRAGMA aux.journal_mode = WAL;
    INSERT INTO t1 VALUES('x', 'y');
    INSERT INTO t2 VALUES('x', 'y');
  }
  lsort [array names ::T1]
} {test.db1 test.db1-journal test.db1-wal}

do_test 5.1.2 {
  lsort [array names ::T2]
} {test.db2 test.db2-journal test.db2-wal}

db close
tvfs1 delete
tvfs2 delete

#-------------------------------------------------------------------------
# Check that only "" and "localhost" are acceptable as authorities.
#
catch {db close}
foreach {tn uri res} {
  1     "file://localhost/PWD/test.db"   {not an error}
  2     "file:///PWD/test.db"            {not an error}
  3     "file:/PWD/test.db"              {not an error}
  4     "file://l%6Fcalhost/PWD/test.db" {invalid uri authority: l%6Fcalhost}
  5     "file://lbcalhost/PWD/test.db"   {invalid uri authority: lbcalhost}
  6     "file://x/PWD/test.db"           {invalid uri authority: x}
} {

  if {$tcl_platform(platform)=="windows"} {
    set uri  [string map [list PWD [string range [pwd] 3 end]] $uri]
  } else {
    set uri  [string map [list PWD [string range [pwd] 1 end]] $uri]
  }

  do_test 6.$tn {
    set DB [sqlite3_open $uri]
    sqlite3_errmsg $DB
  } $res
  catch { sqlite3_close $DB }
}

forcedelete test.db test.db2
do_test 7.1 {
  sqlite3 db test.db
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
    ATTACH 'test.db2' AS aux;
    CREATE TABLE aux.t2(a, b);
    INSERT INTO t1 VALUES('a', 'b');
  }
  db close
} {}
do_test 7.2 {
  sqlite3 db file:test.db?mode=ro
  execsql { ATTACH 'file:test.db2?mode=rw' AS aux }
} {}
do_execsql_test  7.3 { 
  INSERT INTO t2 VALUES('c', 'd') 
} {}
do_catchsql_test 7.4 { 
  INSERT INTO t1 VALUES(3, 4) 
} {1 {attempt to write a readonly database}}

finish_test

Added test/walro.test.































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# 2011 May 09
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for using WAL databases in read-only mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set ::testprefix walro


do_multiclient_test tn {
  # These tests are only going to work on unix.
  #
  if {$tcl_platform(platform) != "unix"} continue

  # Do not run tests with the connections in the same process.
  #
  if {$tn==2} continue
  
  # Close all connections and delete the database.
  #
  code1 { db close  }
  code2 { db2 close }
  code3 { db3 close }
  forcedelete test.db
  forcedelete walro

  foreach c {code1 code2 code3} {
    $c {
      sqlite3_shutdown
      sqlite3_config_uri 1
    }
  }

  file mkdir walro

  do_test 1.1.1 {
    code2 { sqlite3 db2 test.db }
    sql2 { 
      PRAGMA journal_mode = WAL;
      CREATE TABLE t1(x, y);
      INSERT INTO t1 VALUES('a', 'b');
    }
    file exists test.db-shm
  } {1}

  do_test 1.1.2 {
    file attributes test.db-shm -permissions r--r--r--
    code1 { sqlite3 db file:test.db?readonly_shm=1 }
  } {}

  do_test 1.1.3 { sql1 "SELECT * FROM t1" }                {a b}
  do_test 1.1.4 { sql2 "INSERT INTO t1 VALUES('c', 'd')" } {}
  do_test 1.1.5 { sql1 "SELECT * FROM t1" }                {a b c d}

  # Check that the read-only connection cannot write or checkpoint the db.
  #
  do_test 1.1.6 { 
    csql1 "INSERT INTO t1 VALUES('e', 'f')" 
  } {1 {attempt to write a readonly database}}
  do_test 1.1.7 { 
    csql1 "PRAGMA wal_checkpoint"
  } {1 {attempt to write a readonly database}}

  do_test 1.1.9  { sql2 "INSERT INTO t1 VALUES('e', 'f')" } {}
  do_test 1.1.10 { sql1 "SELECT * FROM t1" }                {a b c d e f}

  do_test 1.1.11 { 
    sql2 {
      INSERT INTO t1 VALUES('g', 'h');
      PRAGMA wal_checkpoint;
    }
    set {} {}
  } {}
  do_test 1.1.12 { sql1 "SELECT * FROM t1" }                {a b c d e f g h}
  do_test 1.1.13  { sql2 "INSERT INTO t1 VALUES('i', 'j')" } {}

  do_test 1.2.1 {
    code2 { db2 close }
    code1 { db close }
    list [file exists test.db-wal] [file exists test.db-shm]
  } {1 1}
  do_test 1.2.2 {
    code1 { sqlite3 db file:test.db?readonly_shm=1 }
    sql1 { SELECT * FROM t1 }
  } {a b c d e f g h i j}

  do_test 1.2.3 {
    code1 { db close }
    file attributes test.db-shm -permissions rw-r--r--
    hexio_write test.db-shm 0 01020304 
    file attributes test.db-shm -permissions r--r--r--
    code1 { sqlite3 db file:test.db?readonly_shm=1 }
    csql1 { SELECT * FROM t1 }
  } {1 {attempt to write a readonly database}}
  do_test 1.2.4 {
    code1 { sqlite3_extended_errcode db } 
  } {SQLITE_READONLY_RECOVERY}

  do_test 1.2.5 {
    file attributes test.db-shm -permissions rw-r--r--
    code2 { sqlite3 db2 test.db }
    sql2 "SELECT * FROM t1" 
  } {a b c d e f g h i j}
  file attributes test.db-shm -permissions r--r--r--
  do_test 1.2.6 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j}

  do_test 1.2.7 { 
    sql2 {
      PRAGMA wal_checkpoint;
      INSERT INTO t1 VALUES('k', 'l');
    }
    set {} {}
  } {}
  do_test 1.2.8 { sql1 "SELECT * FROM t1" } {a b c d e f g h i j k l}

  # Now check that if the readonly_shm option is not supplied, or if it
  # is set to zero, it is not possible to connect to the database without
  # read-write access to the shm.
  do_test 1.3.1 {
    code1 { db close }
    code1 { sqlite3 db test.db }
    csql1 { SELECT * FROM t1 }
  } {1 {unable to open database file}}

  # Also test that if the -shm file can be opened for read/write access,
  # it is, even if readonly_shm=1 is present in the URI.
  do_test 1.3.2.1 {
    code1 { db close }
    code2 { db2 close }
    file exists test.db-shm
  } {0}
  do_test 1.3.2.2 {
    code1 { sqlite3 db file:test.db?readonly_shm=1 }
    sql1 { SELECT * FROM t1 }
  } {a b c d e f g h i j k l}
  do_test 1.3.2.3 {
    code1 { db close }
    close [open test.db-shm w]
    file attributes test.db-shm -permissions r--r--r--
    code1 { sqlite3 db file:test.db?readonly_shm=1 }
    csql1 { SELECT * FROM t1 }
  } {1 {attempt to write a readonly database}}
  do_test 1.3.2.4 {
    code1 { sqlite3_extended_errcode db } 
  } {SQLITE_READONLY_RECOVERY}
}

finish_test