SQLite

Changes On Branch winopen-retry-logic
Login

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

Changes In Branch winopen-retry-logic Excluding Merge-Ins

This is equivalent to a diff from 861a5b62 to 4cb17881

2011-08-03
22:06
Merge the winopen-retry-logic branch into trunk. The biggest change here is to test scripts, which should now use such as copy_file and delete_file from tester.tcl rather than the raw file commands of TCL. (check-in: b90c28be user: drh tags: trunk)
2011-08-02
23:45
Add explanatory comment to the win32lock-2.2 test case. (Closed-Leaf check-in: 4cb17881 user: mistachkin tags: winopen-retry-logic)
23:34
Correct subtle timing issues in the win32lock test cases and in the lock_win32_file Tcl command. Also, eliminate superfluous MSVC compiler warnings. (check-in: 7baf0294 user: mistachkin tags: winopen-retry-logic)
20:14
Exclude the 8_3_names.test script from the inmemory_journal permutation. (check-in: 78fc94c8 user: drh tags: trunk)
20:01
Merge in the permutation changes from trunk. (check-in: b30a5e30 user: drh tags: winopen-retry-logic)
19:59
Also exclude backcompat.test from inmemory_journal since inmemory_journal is not compatible with WAL mode. (check-in: 861a5b62 user: drh tags: trunk)
19:30
Omit backcompat.test from the journaltest permutation because it uses WAL mode which is incompatible with journaltest. (check-in: 2bbf3150 user: drh tags: trunk)

Changes to Makefile.msc.

39
40
41
42
43
44
45





46
47
48
49
50
51
52

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
#
TCC = $(TCC) -DNDEBUG






# The locations of the Tcl header and library files.  Also, the library that
# non-stubs enabled programs using Tcl must link against.  These variables
# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
!if "$(TCLINCDIR)" == ""







>
>
>
>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
#
TCC = $(TCC) -DNDEBUG

#
# Prevent warnings about "insecure" runtime library functions being used.
#
TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS

# The locations of the Tcl header and library files.  Also, the library that
# non-stubs enabled programs using Tcl must link against.  These variables
# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
!if "$(TCLINCDIR)" == ""

Changes to src/os_win.c.

2187
2188
2189
2190
2191
2192
2193

2194
2195
2196
2197
2198
2199
2200
  DWORD dwFlagsAndAttributes = 0;
#if SQLITE_OS_WINCE
  int isTemp = 0;
#endif
  winFile *pFile = (winFile*)id;
  void *zConverted;              /* Filename in OS encoding */
  const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */


  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
  */
  char zTmpname[MAX_PATH+1];     /* Buffer used to create temp filename */

  int rc = SQLITE_OK;            /* Function Return Code */







>







2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
  DWORD dwFlagsAndAttributes = 0;
#if SQLITE_OS_WINCE
  int isTemp = 0;
#endif
  winFile *pFile = (winFile*)id;
  void *zConverted;              /* Filename in OS encoding */
  const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
  int cnt = 0;

  /* If argument zPath is a NULL pointer, this function is required to open
  ** a temporary file. Use this buffer to store the file name in.
  */
  char zTmpname[MAX_PATH+1];     /* Buffer used to create temp filename */

  int rc = SQLITE_OK;            /* Function Return Code */
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320

2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334

2335
2336


2337
2338
2339
2340
2341
2342
2343
  /* Reports from the internet are that performance is always
  ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */
#if SQLITE_OS_WINCE
  dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
#endif

  if( isNT() ){
    h = CreateFileW((WCHAR*)zConverted,
       dwDesiredAccess,
       dwShareMode,
       NULL,
       dwCreationDisposition,
       dwFlagsAndAttributes,
       NULL
    );

/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{
    h = CreateFileA((char*)zConverted,
       dwDesiredAccess,
       dwShareMode,
       NULL,
       dwCreationDisposition,
       dwFlagsAndAttributes,
       NULL
    );

#endif
  }



  OSTRACE(("OPEN %d %s 0x%lx %s\n", 
           h, zName, dwDesiredAccess, 
           h==INVALID_HANDLE_VALUE ? "failed" : "ok"));

  if( h==INVALID_HANDLE_VALUE ){
    pFile->lastErrno = GetLastError();







|
|
|
<
|
|
|
<
>






|
|
|
<
|
|
|
<
>


>
>







2307
2308
2309
2310
2311
2312
2313
2314
2315
2316

2317
2318
2319

2320
2321
2322
2323
2324
2325
2326
2327
2328
2329

2330
2331
2332

2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
  /* Reports from the internet are that performance is always
  ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */
#if SQLITE_OS_WINCE
  dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
#endif

  if( isNT() ){
    while( (h = CreateFileW((WCHAR*)zConverted,
                            dwDesiredAccess,
                            dwShareMode, NULL,

                            dwCreationDisposition,
                            dwFlagsAndAttributes,
                            NULL))==INVALID_HANDLE_VALUE &&

                            retryIoerr(&cnt) ){}
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{
    while( (h = CreateFileA((char*)zConverted,
                            dwDesiredAccess,
                            dwShareMode, NULL,

                            dwCreationDisposition,
                            dwFlagsAndAttributes,
                            NULL))==INVALID_HANDLE_VALUE &&

                            retryIoerr(&cnt) ){}
#endif
  }

  logIoerr(cnt);

  OSTRACE(("OPEN %d %s 0x%lx %s\n", 
           h, zName, dwDesiredAccess, 
           h==INVALID_HANDLE_VALUE ? "failed" : "ok"));

  if( h==INVALID_HANDLE_VALUE ){
    pFile->lastErrno = GetLastError();

Changes to src/test1.c.

5641
5642
5643
5644
5645
5646
5647

5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662







5663
5664
5665
5666
5667
5668
5669

#if SQLITE_OS_WIN
/*
** Information passed from the main thread into the windows file locker
** background thread.
*/
struct win32FileLocker {

  HANDLE h;           /* Handle of the file to be locked */
  int delay1;         /* Delay before locking */
  int delay2;         /* Delay before unlocking */
  int ok;             /* Finished ok */
  int err;            /* True if an error occurs */
};
#endif


#if SQLITE_OS_WIN
/*
** The background thread that does file locking.
*/
static void win32_file_locker(void *pAppData){
  struct win32FileLocker *p = (struct win32FileLocker*)pAppData;







  if( p->delay1 ) Sleep(p->delay1);
  if( LockFile(p->h, 0, 0, 100000000, 0) ){
    Sleep(p->delay2);
    UnlockFile(p->h, 0, 0, 100000000, 0);
    p->ok = 1;
  }else{
    p->err = 1;







>















>
>
>
>
>
>
>







5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677

#if SQLITE_OS_WIN
/*
** Information passed from the main thread into the windows file locker
** background thread.
*/
struct win32FileLocker {
  char *evName;       /* Name of event to signal thread startup */
  HANDLE h;           /* Handle of the file to be locked */
  int delay1;         /* Delay before locking */
  int delay2;         /* Delay before unlocking */
  int ok;             /* Finished ok */
  int err;            /* True if an error occurs */
};
#endif


#if SQLITE_OS_WIN
/*
** The background thread that does file locking.
*/
static void win32_file_locker(void *pAppData){
  struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
  if( p->evName ){
    HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
    if ( ev ){
      SetEvent(ev);
      CloseHandle(ev);
    }
  }
  if( p->delay1 ) Sleep(p->delay1);
  if( LockFile(p->h, 0, 0, 100000000, 0) ){
    Sleep(p->delay2);
    UnlockFile(p->h, 0, 0, 100000000, 0);
    p->ok = 1;
  }else{
    p->err = 1;
5684
5685
5686
5687
5688
5689
5690
5691
5692

5693


5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
*/
static int win32_file_lock(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  static struct win32FileLocker x = { 0, 0, 0 };
  const char *zFilename;

  int retry = 0;


  
  if( objc!=4 && objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
    return TCL_ERROR;
  }
  if( objc==1 ){
    char zBuf[200];
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
                     x.ok, x.err, x.delay1, x.delay2, x.h);
    Tcl_AppendResult(interp, zBuf, (char*)0);
    return TCL_OK;
  }
  while( x.h && retry<30 ){
    retry++;







|

>

>
>






<







5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710

5711
5712
5713
5714
5715
5716
5717
*/
static int win32_file_lock(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
  const char *zFilename;
  char zBuf[200];
  int retry = 0;
  HANDLE ev;
  DWORD wResult;
  
  if( objc!=4 && objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
    return TCL_ERROR;
  }
  if( objc==1 ){

    sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
                     x.ok, x.err, x.delay1, x.delay2, x.h);
    Tcl_AppendResult(interp, zBuf, (char*)0);
    return TCL_OK;
  }
  while( x.h && retry<30 ){
    retry++;
5716
5717
5718
5719
5720
5721
5722





5723
5724
5725







5726
5727
5728
5729
5730
5731
5732
  zFilename = Tcl_GetString(objv[1]);
  x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
              FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
              FILE_ATTRIBUTE_NORMAL, 0);
  if( !x.h ){
    Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
    return TCL_ERROR;





  }
  _beginthread(win32_file_locker, 0, (void*)&x);
  Sleep(0);







  return TCL_OK;
}
#endif


/*
**      optimization_control DB OPT BOOLEAN







>
>
>
>
>



>
>
>
>
>
>
>







5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
  zFilename = Tcl_GetString(objv[1]);
  x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
              FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
              FILE_ATTRIBUTE_NORMAL, 0);
  if( !x.h ){
    Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
    return TCL_ERROR;
  }
  ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
  if ( !ev ){
    Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
    return TCL_ERROR;
  }
  _beginthread(win32_file_locker, 0, (void*)&x);
  Sleep(0);
  if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
    sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
    Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
    CloseHandle(ev);
    return TCL_ERROR;
  }
  CloseHandle(ev);
  return TCL_OK;
}
#endif


/*
**      optimization_control DB OPT BOOLEAN

Changes to test/8_3_names.test.

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  }
  file exists test.db-journal
} 0
do_test 8_3_names-2.1 {
  file exists test.nal
} 1
forcedelete test2.db test2.nal test2.db-journal
file copy test.db test2.db
file copy test.nal test2.nal
do_test 8_3_names-2.2 {
  db eval {
    COMMIT;
    SELECT length(x) FROM t1
  }
} 15000
do_test 8_3_names-2.3 {







|
|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  }
  file exists test.db-journal
} 0
do_test 8_3_names-2.1 {
  file exists test.nal
} 1
forcedelete test2.db test2.nal test2.db-journal
copy_file test.db test2.db
copy_file test.nal test2.nal
do_test 8_3_names-2.2 {
  db eval {
    COMMIT;
    SELECT length(x) FROM t1
  }
} 15000
do_test 8_3_names-2.3 {
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  }
  file exists test.db-journal
} 1
do_test 8_3_names-3.1 {
  file exists test.nal
} 0
forcedelete test2.db test2.nal test2.db-journal
file copy test.db test2.db
file copy test.db-journal test2.db-journal
do_test 8_3_names-3.2 {
  db eval {
    COMMIT;
    SELECT length(x) FROM t1
  }
} 15000
do_test 8_3_names-3.3 {







|
|







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  }
  file exists test.db-journal
} 1
do_test 8_3_names-3.1 {
  file exists test.nal
} 0
forcedelete test2.db test2.nal test2.db-journal
copy_file test.db test2.db
copy_file test.db-journal test2.db-journal
do_test 8_3_names-3.2 {
  db eval {
    COMMIT;
    SELECT length(x) FROM t1
  }
} 15000
do_test 8_3_names-3.3 {

Changes to test/alter.test.

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
     index {sqlite_autoindex_<t2>_2}    <t2>          \
  ]

# Check that ALTER TABLE works on attached databases.
#
ifcapable attach {
  do_test alter-1.8.1 {
    file delete -force test2.db
    file delete -force test2.db-journal
    execsql {
      ATTACH 'test2.db' AS aux;
    }
  } {}
  do_test alter-1.8.2 {
    execsql {
      CREATE TABLE t4(a PRIMARY KEY, b, c);







|
|







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
     index {sqlite_autoindex_<t2>_2}    <t2>          \
  ]

# Check that ALTER TABLE works on attached databases.
#
ifcapable attach {
  do_test alter-1.8.1 {
    forcedelete test2.db
    forcedelete test2.db-journal
    execsql {
      ATTACH 'test2.db' AS aux;
    }
  } {}
  do_test alter-1.8.2 {
    execsql {
      CREATE TABLE t4(a PRIMARY KEY, b, c);
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
    INSERT INTO t9 VALUES(4, 5, 6);
  }
  set ::TRIGGER
} {trig3 4 5 6}

# Make sure "ON" cannot be used as a database, table or column name without
# quoting. Otherwise the sqlite_alter_trigger() function might not work.
file delete -force test3.db
file delete -force test3.db-journal
ifcapable attach {
  do_test alter-3.2.1 {
    catchsql {
      ATTACH 'test3.db' AS ON;
    }
  } {1 {near "ON": syntax error}}
  do_test alter-3.2.2 {







|
|







408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
    INSERT INTO t9 VALUES(4, 5, 6);
  }
  set ::TRIGGER
} {trig3 4 5 6}

# Make sure "ON" cannot be used as a database, table or column name without
# quoting. Otherwise the sqlite_alter_trigger() function might not work.
forcedelete test3.db
forcedelete test3.db-journal
ifcapable attach {
  do_test alter-3.2.1 {
    catchsql {
      ATTACH 'test3.db' AS ON;
    }
  } {1 {near "ON": syntax error}}
  do_test alter-3.2.2 {

Changes to test/alter2.test.

311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  db close
  set_file_format 2
  sqlite3 db test.db
  get_file_format
} {2}
ifcapable attach {
  do_test alter2-6.2 {
    file delete -force test2.db-journal
    file delete -force test2.db
    execsql {
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t1(a, b);
    }
    get_file_format test2.db
  } $default_file_format
}







|
|







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  db close
  set_file_format 2
  sqlite3 db test.db
  get_file_format
} {2}
ifcapable attach {
  do_test alter2-6.2 {
    forcedelete test2.db-journal
    forcedelete test2.db
    execsql {
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t1(a, b);
    }
    get_file_format test2.db
  } $default_file_format
}

Changes to test/alter3.test.

192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
      PRAGMA schema_version;
    }
  } {11}
}

do_test alter3-4.1 {
  db close
  file delete -force test.db
  set ::DB [sqlite3 db test.db]
  execsql {
    PRAGMA legacy_file_format=ON;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 100);
    INSERT INTO t1 VALUES(2, 300);
    SELECT * FROM t1;







|







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
      PRAGMA schema_version;
    }
  } {11}
}

do_test alter3-4.1 {
  db close
  forcedelete test.db
  set ::DB [sqlite3 db test.db]
  execsql {
    PRAGMA legacy_file_format=ON;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 100);
    INSERT INTO t1 VALUES(2, 300);
    SELECT * FROM t1;
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  execsql {
    DROP TABLE t1;
  }
} {}

ifcapable attach {
  do_test alter3-5.1 {
    file delete -force test2.db
    file delete -force test2.db-journal
    execsql {
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 'one');
      INSERT INTO t1 VALUES(2, 'two');
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t1 AS SELECT * FROM t1;
      PRAGMA aux.schema_version = 30;







|
|







233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  execsql {
    DROP TABLE t1;
  }
} {}

ifcapable attach {
  do_test alter3-5.1 {
    forcedelete test2.db
    forcedelete test2.db-journal
    execsql {
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 'one');
      INSERT INTO t1 VALUES(2, 'two');
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t1 AS SELECT * FROM t1;
      PRAGMA aux.schema_version = 30;

Changes to test/alter4.test.

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
      PRAGMA schema_version;
    }
  } {10}
}

do_test alter4-4.1 {
  db close
  file delete -force test.db
  set ::DB [sqlite3 db test.db]
  execsql {
    CREATE TEMP TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 100);
    INSERT INTO t1 VALUES(2, 300);
    SELECT * FROM t1;
  }







|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
      PRAGMA schema_version;
    }
  } {10}
}

do_test alter4-4.1 {
  db close
  forcedelete test.db
  set ::DB [sqlite3 db test.db]
  execsql {
    CREATE TEMP TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 100);
    INSERT INTO t1 VALUES(2, 300);
    SELECT * FROM t1;
  }
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  execsql {
    DROP TABLE t1;
  }
} {}

ifcapable attach {
  do_test alter4-5.1 {
    file delete -force test2.db
    file delete -force test2.db-journal
    execsql {
      CREATE TEMP TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 'one');
      INSERT INTO t1 VALUES(2, 'two');
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t1 AS SELECT * FROM t1;
      PRAGMA aux.schema_version = 30;







|
|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  execsql {
    DROP TABLE t1;
  }
} {}

ifcapable attach {
  do_test alter4-5.1 {
    forcedelete test2.db
    forcedelete test2.db-journal
    execsql {
      CREATE TEMP TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 'one');
      INSERT INTO t1 VALUES(2, 'two');
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t1 AS SELECT * FROM t1;
      PRAGMA aux.schema_version = 30;

Changes to test/async.test.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
  set tail [file tail $testfile]
  if {[lsearch -exact $ASYNC_INCLUDE $tail]<0} continue
  source $testfile

  # Make sure everything is flushed through. This is because [source]ing 
  # the next test file will delete the database file on disk (using
  # [file delete]). If the asynchronous backend still has the file
  # open, it will become confused.
  #
  flush_async_queue
}

# Flush the write-queue and disable asynchronous IO. This should ensure
# all allocated memory is cleaned up.







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
  set tail [file tail $testfile]
  if {[lsearch -exact $ASYNC_INCLUDE $tail]<0} continue
  source $testfile

  # Make sure everything is flushed through. This is because [source]ing 
  # the next test file will delete the database file on disk (using
  # [delete_file]). If the asynchronous backend still has the file
  # open, it will become confused.
  #
  flush_async_queue
}

# Flush the write-queue and disable asynchronous IO. This should ensure
# all allocated memory is cleaned up.

Changes to test/async2.test.

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
db close

foreach err [list ioerr malloc-transient malloc-persistent] {
  set ::go 10
  for {set n 1} {$::go} {incr n} {
    set ::sqlite_io_error_pending 0
    sqlite3_memdebug_fail -1
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    execsql $::setup_script
    db close
  
    sqlite3async_initialize "" 1
    sqlite3 db test.db
    sqlite3_db_config_lookaside db 0 0 0







|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
db close

foreach err [list ioerr malloc-transient malloc-persistent] {
  set ::go 10
  for {set n 1} {$::go} {incr n} {
    set ::sqlite_io_error_pending 0
    sqlite3_memdebug_fail -1
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    execsql $::setup_script
    db close
  
    sqlite3async_initialize "" 1
    sqlite3 db test.db
    sqlite3_db_config_lookaside db 0 0 0

Changes to test/async3.test.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  chocolate/banana/./vanilla/file.db
  chocolate/banana/../banana/vanilla/file.db
  chocolate/banana/./vanilla/extra_bit/../file.db
}

do_test async3-1.0 {
  file mkdir [file join chocolate banana vanilla]
  file delete -force chocolate/banana/vanilla/file.db
  file delete -force chocolate/banana/vanilla/file.db-journal
} {}

do_test async3-1.1 {
  sqlite3 db chocolate/banana/vanilla/file.db
  execsql {
    CREATE TABLE abc(a, b, c);
    BEGIN;







|
|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  chocolate/banana/./vanilla/file.db
  chocolate/banana/../banana/vanilla/file.db
  chocolate/banana/./vanilla/extra_bit/../file.db
}

do_test async3-1.0 {
  file mkdir [file join chocolate banana vanilla]
  forcedelete chocolate/banana/vanilla/file.db
  forcedelete chocolate/banana/vanilla/file.db-journal
} {}

do_test async3-1.1 {
  sqlite3 db chocolate/banana/vanilla/file.db
  execsql {
    CREATE TABLE abc(a, b, c);
    BEGIN;

Changes to test/async5.test.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
if {[info commands sqlite3async_initialize] eq ""} {
  # The async logic is not built into this system
  finish_test
  return
}

db close
file delete -force test2.db
sqlite3async_initialize "" 1
sqlite3async_control halt never
sqlite3 db test.db

do_test async5-1.1 {
  execsql {
    ATTACH 'test2.db' AS next;







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
if {[info commands sqlite3async_initialize] eq ""} {
  # The async logic is not built into this system
  finish_test
  return
}

db close
forcedelete test2.db
sqlite3async_initialize "" 1
sqlite3async_control halt never
sqlite3 db test.db

do_test async5-1.1 {
  execsql {
    ATTACH 'test2.db' AS next;

Changes to test/attach.test.

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

ifcapable !attach {
  finish_test
  return
}

for {set i 2} {$i<=15} {incr i} {
  file delete -force test$i.db
  file delete -force test$i.db-journal
}

do_test attach-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
    INSERT INTO t1 VALUES(3,4);







|
|







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

ifcapable !attach {
  finish_test
  return
}

for {set i 2} {$i<=15} {incr i} {
  forcedelete test$i.db
  forcedelete test$i.db-journal
}

do_test attach-1.1 {
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
    INSERT INTO t1 VALUES(3,4);
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
# Tests for the sqliteFix...() routines in attach.c
#
ifcapable {trigger} {
do_test attach-5.1 {
  db close
  sqlite3 db test.db
  db2 close
  file delete -force test2.db
  sqlite3 db2 test2.db
  catchsql {
    ATTACH DATABASE 'test.db' AS orig;
    CREATE TRIGGER r1 AFTER INSERT ON orig.t1 BEGIN
      SELECT 'no-op';
    END;
  } db2







|







624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
# Tests for the sqliteFix...() routines in attach.c
#
ifcapable {trigger} {
do_test attach-5.1 {
  db close
  sqlite3 db test.db
  db2 close
  forcedelete test2.db
  sqlite3 db2 test2.db
  catchsql {
    ATTACH DATABASE 'test.db' AS orig;
    CREATE TRIGGER r1 AFTER INSERT ON orig.t1 BEGIN
      SELECT 'no-op';
    END;
  } db2
721
722
723
724
725
726
727
728
729
730
731
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
  do_test attach-6.2 {
    sqlite3 dbx cannot-read
    dbx eval {CREATE TABLE t1(a,b,c)}
    dbx close
    file attributes cannot-read -permission 0000
    if {[file writable cannot-read]} {
      puts "\n**** Tests do not work when run as root ****"
      file delete -force cannot-read
      exit 1
    }
    catchsql {
      ATTACH DATABASE 'cannot-read' AS noread;
    }
  } {1 {unable to open database: cannot-read}}
  do_test attach-6.2.2 {
    db errorcode
  } {14}
  file delete -force cannot-read
}

# Check the error message if we try to access a database that has
# not been attached.
do_test attach-6.3 {
  catchsql {
    CREATE TABLE no_such_db.t1(a, b, c);
  }
} {1 {unknown database no_such_db}}
for {set i 2} {$i<=15} {incr i} {
  catch {db$i close}
}
db close
file delete -force test2.db
file delete -force no-such-file

ifcapable subquery {
  do_test attach-7.1 {
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    catchsql {
      DETACH RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY 
      REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL )
    }
  } {1 {no such table: AAAAAA}}
}







|









|













|
|



|







721
722
723
724
725
726
727
728
729
730
731
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
  do_test attach-6.2 {
    sqlite3 dbx cannot-read
    dbx eval {CREATE TABLE t1(a,b,c)}
    dbx close
    file attributes cannot-read -permission 0000
    if {[file writable cannot-read]} {
      puts "\n**** Tests do not work when run as root ****"
      forcedelete cannot-read
      exit 1
    }
    catchsql {
      ATTACH DATABASE 'cannot-read' AS noread;
    }
  } {1 {unable to open database: cannot-read}}
  do_test attach-6.2.2 {
    db errorcode
  } {14}
  forcedelete cannot-read
}

# Check the error message if we try to access a database that has
# not been attached.
do_test attach-6.3 {
  catchsql {
    CREATE TABLE no_such_db.t1(a, b, c);
  }
} {1 {unknown database no_such_db}}
for {set i 2} {$i<=15} {incr i} {
  catch {db$i close}
}
db close
forcedelete test2.db
forcedelete no-such-file

ifcapable subquery {
  do_test attach-7.1 {
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    catchsql {
      DETACH RAISE ( IGNORE ) IN ( SELECT "AAAAAA" . * ORDER BY 
      REGISTER LIMIT "AAAAAA" . "AAAAAA" OFFSET RAISE ( IGNORE ) NOT NULL )
    }
  } {1 {no such table: AAAAAA}}
}
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
  catchsql {
    ATTACH 'test2.db' AS t2;
  }
} {1 {file is encrypted or is not a database}}
do_test attach-8.2 {
  db errorcode
} {26}
file delete -force test2.db
do_test attach-8.3 {
  sqlite3 db2 test2.db
  db2 eval {CREATE TABLE t1(x); BEGIN EXCLUSIVE}
  catchsql {
    ATTACH 'test2.db' AS t2;
  }
} {1 {database is locked}}
do_test attach-8.4 {
  db errorcode
} {5}
db2 close
file delete -force test2.db

# Test that it is possible to attach the same database more than
# once when not in shared-cache mode. That this is not possible in
# shared-cache mode is tested in shared7.test.
do_test attach-9.1 {
  file delete -force test4.db
  execsql {
    ATTACH 'test4.db' AS aux1;
    CREATE TABLE aux1.t1(a, b);
    INSERT INTO aux1.t1 VALUES(1, 2);
    ATTACH 'test4.db' AS aux2;
    SELECT * FROM aux2.t1;
  }







|











|





|







773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
  catchsql {
    ATTACH 'test2.db' AS t2;
  }
} {1 {file is encrypted or is not a database}}
do_test attach-8.2 {
  db errorcode
} {26}
forcedelete test2.db
do_test attach-8.3 {
  sqlite3 db2 test2.db
  db2 eval {CREATE TABLE t1(x); BEGIN EXCLUSIVE}
  catchsql {
    ATTACH 'test2.db' AS t2;
  }
} {1 {database is locked}}
do_test attach-8.4 {
  db errorcode
} {5}
db2 close
forcedelete test2.db

# Test that it is possible to attach the same database more than
# once when not in shared-cache mode. That this is not possible in
# shared-cache mode is tested in shared7.test.
do_test attach-9.1 {
  forcedelete test4.db
  execsql {
    ATTACH 'test4.db' AS aux1;
    CREATE TABLE aux1.t1(a, b);
    INSERT INTO aux1.t1 VALUES(1, 2);
    ATTACH 'test4.db' AS aux2;
    SELECT * FROM aux2.t1;
  }

Changes to test/attach2.test.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# sure we can attach test2.db from test.db.
#
do_test attach2-1.1 {
  db eval {
    CREATE TABLE t1(a,b);
    CREATE INDEX x1 ON t1(a);
  }
  file delete -force test2.db
  file delete -force test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {
    CREATE TABLE t1(a,b);
    CREATE INDEX x1 ON t1(a);
  }
  catchsql {
    ATTACH 'test2.db' AS t2;







|
|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# sure we can attach test2.db from test.db.
#
do_test attach2-1.1 {
  db eval {
    CREATE TABLE t1(a,b);
    CREATE INDEX x1 ON t1(a);
  }
  forcedelete test2.db
  forcedelete test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {
    CREATE TABLE t1(a,b);
    CREATE INDEX x1 ON t1(a);
  }
  catchsql {
    ATTACH 'test2.db' AS t2;
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
} {}
do_test attach2-4.15 {
  execsql {SELECT * FROM t1} db2
} {1 2 1 2}

db close
db2 close
file delete -force test2.db
sqlite3_soft_heap_limit $soft_limit

# These tests - attach2-5.* - check that the master journal file is deleted
# correctly when a multi-file transaction is committed or rolled back.
#
# Update: It's not actually created if a rollback occurs, so that test
# doesn't really prove too much.
foreach f [glob test.db*] {file delete -force $f}
do_test attach2-5.1 {
  sqlite3 db test.db
  execsql {
    ATTACH 'test.db2' AS aux;
  }
} {}
do_test attach2-5.2 {







|







|







323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
} {}
do_test attach2-4.15 {
  execsql {SELECT * FROM t1} db2
} {1 2 1 2}

db close
db2 close
forcedelete test2.db
sqlite3_soft_heap_limit $soft_limit

# These tests - attach2-5.* - check that the master journal file is deleted
# correctly when a multi-file transaction is committed or rolled back.
#
# Update: It's not actually created if a rollback occurs, so that test
# doesn't really prove too much.
foreach f [glob test.db*] {forcedelete $f}
do_test attach2-5.1 {
  sqlite3 db test.db
  execsql {
    ATTACH 'test.db2' AS aux;
  }
} {}
do_test attach2-5.2 {

Changes to test/attach3.test.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Create tables t1 and t2 in the main database
execsql {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
}

# Create tables t1 and t2 in database file test2.db
file delete -force test2.db
file delete -force test2.db-journal
sqlite3 db2 test2.db
execsql {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
} db2
db2 close








|
|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Create tables t1 and t2 in the main database
execsql {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
}

# Create tables t1 and t2 in database file test2.db
forcedelete test2.db
forcedelete test2.db-journal
sqlite3 db2 test2.db
execsql {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
} db2
db2 close

Changes to test/attachmalloc.test.

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

source $testdir/malloc_common.tcl

do_malloc_test attachmalloc-1 -tclprep {
  catch { db close }
  for {set i 2} {$i<=4} {incr i} {
    catch { db$i close }
    file delete -force test$i.db
    file delete -force test$i.db-journal
  }
} -tclbody {
  if {[catch {sqlite3 db test.db}]} {
    error "out of memory"
  }
  sqlite3_db_config_lookaside db 0 0 0
  sqlite3_extended_result_codes db 1
} -sqlbody {
  ATTACH 'test2.db' AS two;
  CREATE TABLE two.t1(x);
  ATTACH 'test3.db' AS three;
  CREATE TABLE three.t1(x);
  ATTACH 'test4.db' AS four;
  CREATE TABLE four.t1(x);
}

do_malloc_test attachmalloc-2 -tclprep {
  file delete -force test2.db
  file delete -force test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {
    CREATE TABLE t1(a, b, c);
    CREATE INDEX i1 ON t1(a, b);
  }
  db2 close
} -sqlbody {







|
|

















|
|







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

source $testdir/malloc_common.tcl

do_malloc_test attachmalloc-1 -tclprep {
  catch { db close }
  for {set i 2} {$i<=4} {incr i} {
    catch { db$i close }
    forcedelete test$i.db
    forcedelete test$i.db-journal
  }
} -tclbody {
  if {[catch {sqlite3 db test.db}]} {
    error "out of memory"
  }
  sqlite3_db_config_lookaside db 0 0 0
  sqlite3_extended_result_codes db 1
} -sqlbody {
  ATTACH 'test2.db' AS two;
  CREATE TABLE two.t1(x);
  ATTACH 'test3.db' AS three;
  CREATE TABLE three.t1(x);
  ATTACH 'test4.db' AS four;
  CREATE TABLE four.t1(x);
}

do_malloc_test attachmalloc-2 -tclprep {
  forcedelete test2.db
  forcedelete test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {
    CREATE TABLE t1(a, b, c);
    CREATE INDEX i1 ON t1(a, b);
  }
  db2 close
} -sqlbody {

Changes to test/autoinc.test.

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
  } {}
}

# Make sure AUTOINCREMENT works on ATTACH-ed tables.
#
ifcapable tempdb&&attach {
  do_test autoinc-5.1 {
    file delete -force test2.db
    file delete -force test2.db-journal
    sqlite3 db2 test2.db
    execsql {
      CREATE TABLE t4(m INTEGER PRIMARY KEY AUTOINCREMENT, n);
      CREATE TABLE t5(o, p INTEGER PRIMARY KEY AUTOINCREMENT);
    } db2;
    execsql {
      ATTACH 'test2.db' as aux;







|
|







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
  } {}
}

# Make sure AUTOINCREMENT works on ATTACH-ed tables.
#
ifcapable tempdb&&attach {
  do_test autoinc-5.1 {
    forcedelete test2.db
    forcedelete test2.db-journal
    sqlite3 db2 test2.db
    execsql {
      CREATE TABLE t4(m INTEGER PRIMARY KEY AUTOINCREMENT, n);
      CREATE TABLE t5(o, p INTEGER PRIMARY KEY AUTOINCREMENT);
    } db2;
    execsql {
      ATTACH 'test2.db' as aux;
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

# Ticket #1283.  Make sure that preparing but never running a statement
# that creates the sqlite_sequence table does not mess up the database.
#
do_test autoinc-8.1 {
  catch {db2 close}
  catch {db close}
  file delete -force test.db
  sqlite3 db test.db
  set DB [sqlite3_connection_pointer db]
  set STMT [sqlite3_prepare $DB {
     CREATE TABLE t1(
       x INTEGER PRIMARY KEY AUTOINCREMENT
     )
  } -1 TAIL]







|







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530

# Ticket #1283.  Make sure that preparing but never running a statement
# that creates the sqlite_sequence table does not mess up the database.
#
do_test autoinc-8.1 {
  catch {db2 close}
  catch {db close}
  forcedelete test.db
  sqlite3 db test.db
  set DB [sqlite3_connection_pointer db]
  set STMT [sqlite3_prepare $DB {
     CREATE TABLE t1(
       x INTEGER PRIMARY KEY AUTOINCREMENT
     )
  } -1 TAIL]

Changes to test/autovacuum.test.

463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
    PRAGMA auto_vacuum = 0;
    PRAGMA auto_vacuum;
  }
} {1}

do_test autovacuum-3.4 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum;
  }
} $AUTOVACUUM
do_test autovacuum-3.5 {
  execsql {







|







463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
    PRAGMA auto_vacuum = 0;
    PRAGMA auto_vacuum;
  }
} {1}

do_test autovacuum-3.4 {
  db close
  forcedelete test.db
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum;
  }
} $AUTOVACUUM
do_test autovacuum-3.5 {
  execsql {
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
# rolled back no corruption occurs.
#
do_test autovacuum-4.0 {
  # The last round of tests may have left the db in non-autovacuum mode.
  # Reset everything just in case.
  #
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum = 1;
    PRAGMA auto_vacuum;
  }
} {1}
do_test autovacuum-4.1 {







|







498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
# rolled back no corruption occurs.
#
do_test autovacuum-4.0 {
  # The last round of tests may have left the db in non-autovacuum mode.
  # Reset everything just in case.
  #
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum = 1;
    PRAGMA auto_vacuum;
  }
} {1}
do_test autovacuum-4.1 {
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
#---------------------------------------------------------------------
# Test cases autovacuum-7.X test the case where a page must be moved
# and the destination location collides with at least one other
# entry in the page hash-table (internal to the pager.c module. 
#
do_test autovacuum-7.1 {
  db close
  file delete -force test.db
  file delete -force test.db-journal
  sqlite3 db test.db

  execsql {
    PRAGMA auto_vacuum=1;
    CREATE TABLE t1(a, b, PRIMARY KEY(a, b));
    INSERT INTO t1 VALUES(randstr(400,400),randstr(400,400));
    INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2







|
|







595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
#---------------------------------------------------------------------
# Test cases autovacuum-7.X test the case where a page must be moved
# and the destination location collides with at least one other
# entry in the page hash-table (internal to the pager.c module. 
#
do_test autovacuum-7.1 {
  db close
  forcedelete test.db
  forcedelete test.db-journal
  sqlite3 db test.db

  execsql {
    PRAGMA auto_vacuum=1;
    CREATE TABLE t1(a, b, PRIMARY KEY(a, b));
    INSERT INTO t1 VALUES(randstr(400,400),randstr(400,400));
    INSERT INTO t1 SELECT randstr(400,400), randstr(400,400) FROM t1; -- 2

Changes to test/autovacuum_ioerr2.test.

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  BEGIN;
  INSERT INTO abc2 VALUES(10);
  DROP TABLE abc;
  COMMIT;
  DROP TABLE abc2;
}

file delete -force backup.db
ifcapable subquery {
  do_ioerr_test autovacuum-ioerr2-4 -tclprep {
    if {![file exists backup.db]} {
      sqlite3 dbb backup.db 
      execsql {
        PRAGMA auto_vacuum = 1;
        BEGIN;







|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  BEGIN;
  INSERT INTO abc2 VALUES(10);
  DROP TABLE abc;
  COMMIT;
  DROP TABLE abc2;
}

forcedelete backup.db
ifcapable subquery {
  do_ioerr_test autovacuum-ioerr2-4 -tclprep {
    if {![file exists backup.db]} {
      sqlite3 dbb backup.db 
      execsql {
        PRAGMA auto_vacuum = 1;
        BEGIN;
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
      execsql {
        COMMIT;
        PRAGMA cache_size = 10;
      } dbb
      dbb close
    }
    db close
    file delete -force test.db
    file delete -force test.db-journal
    copy_file backup.db test.db
    set ::DB [sqlite3 db test.db]
    execsql {
      PRAGMA cache_size = 10;
    }
  } -sqlbody {
    BEGIN;
    DELETE FROM abc WHERE oid < 3;







|
|
|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
      execsql {
        COMMIT;
        PRAGMA cache_size = 10;
      } dbb
      dbb close
    }
    db close
    forcedelete test.db
    forcedelete test.db-journal
    forcecopy backup.db test.db
    set ::DB [sqlite3 db test.db]
    execsql {
      PRAGMA cache_size = 10;
    }
  } -sqlbody {
    BEGIN;
    DELETE FROM abc WHERE oid < 3;

Changes to test/backcompat.test.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  puts -nonewline "Testing against $bin - "
  flush stdout
  puts "version [get_version $bin]"
}

proc do_backcompat_test {rv bin1 bin2 script} {

  file delete -force test.db

  if {$bin1 != ""} { set ::bc_chan1 [launch_testfixture $bin1] }
  set ::bc_chan2 [launch_testfixture $bin2]

  if { $rv } {
    proc code2 {tcl} { uplevel #0 $tcl }
    if {$bin1 != ""} { proc code2 {tcl} { testfixture $::bc_chan1 $tcl } }







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  puts -nonewline "Testing against $bin - "
  flush stdout
  puts "version [get_version $bin]"
}

proc do_backcompat_test {rv bin1 bin2 script} {

  forcedelete test.db

  if {$bin1 != ""} { set ::bc_chan1 [launch_testfixture $bin1] }
  set ::bc_chan2 [launch_testfixture $bin2]

  if { $rv } {
    proc code2 {tcl} { uplevel #0 $tcl }
    if {$bin1 != ""} { proc code2 {tcl} { testfixture $::bc_chan1 $tcl } }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  set ret [list]
  foreach f {test.db test.db-journal test.db-wal} { lappend ret [read_file $f] }
  set ret
}
proc write_file_system {data} {
  foreach f {test.db test.db-journal test.db-wal} d $data { 
    if {[string length $d] == 0} {
      file delete -force $f
    } else {
      write_file $f $d
    }
  }
}

#-------------------------------------------------------------------------







|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  set ret [list]
  foreach f {test.db test.db-journal test.db-wal} { lappend ret [read_file $f] }
  set ret
}
proc write_file_system {data} {
  foreach f {test.db test.db-journal test.db-wal} d $data { 
    if {[string length $d] == 0} {
      forcedelete $f
    } else {
      write_file $f $d
    }
  }
}

#-------------------------------------------------------------------------

Changes to test/backup.test.

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Sanity check to verify that the [test_contents] proc works.
#
test_contents backup-1.2 db main db main

# Check that it is possible to create and finish backup operations.
#
do_test backup-1.3.1 {
  file delete test2.db
  sqlite3 db2 test2.db
  sqlite3_backup B db2 main db main
} {B}
do_test backup-1.3.2 {
  B finish
} {SQLITE_OK}
do_test backup-1.3.3 {







|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Sanity check to verify that the [test_contents] proc works.
#
test_contents backup-1.2 db main db main

# Check that it is possible to create and finish backup operations.
#
do_test backup-1.3.1 {
  delete_file test2.db
  sqlite3 db2 test2.db
  sqlite3_backup B db2 main db main
} {B}
do_test backup-1.3.2 {
  B finish
} {SQLITE_OK}
do_test backup-1.3.3 {
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  set file_dest temp
}] {
foreach rows_dest {0 3 10} {
foreach pgsz_dest {512 1024 2048} {
foreach nPagePerStep {1 200} {

  # Open the databases.
  catch { file delete test.db }
  catch { file delete test2.db }
  eval $zOpenScript

  # Set to true if copying to an in-memory destination. Copying to an 
  # in-memory destination is only possible if the initial destination
  # page size is the same as the source page size (in this case 1024 bytes).
  #
  set isMemDest [expr {







|
|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  set file_dest temp
}] {
foreach rows_dest {0 3 10} {
foreach pgsz_dest {512 1024 2048} {
foreach nPagePerStep {1 200} {

  # Open the databases.
  catch { delete_file test.db }
  catch { delete_file test2.db }
  eval $zOpenScript

  # Set to true if copying to an in-memory destination. Copying to an 
  # in-memory destination is only possible if the initial destination
  # page size is the same as the source page size (in this case 1024 bytes).
  #
  set isMemDest [expr {
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#   * Target database page-size is smaller than the source.
#
set iTest 1
foreach nSrcPg {10 64 65 66 100} {
foreach nDestRow {10 100} {
foreach nDestPgsz {512 1024 2048 4096} {

  catch { file delete test.db }
  catch { file delete test2.db }
  sqlite3 db test.db
  sqlite3 db2 test2.db

  # Set up the content of the two databases.
  #
  execsql { PRAGMA page_size = 1024 }
  execsql "PRAGMA page_size = $nDestPgsz" db2







|
|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#   * Target database page-size is smaller than the source.
#
set iTest 1
foreach nSrcPg {10 64 65 66 100} {
foreach nDestRow {10 100} {
foreach nDestPgsz {512 1024 2048 4096} {

  catch { delete_file test.db }
  catch { delete_file test2.db }
  sqlite3 db test.db
  sqlite3 db2 test2.db

  # Set up the content of the two databases.
  #
  execsql { PRAGMA page_size = 1024 }
  execsql "PRAGMA page_size = $nDestPgsz" db2
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  incr iTest
}
}
}

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

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







|
|







323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  incr iTest
}
}
}

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

  db eval { PRAGMA page_size = 512 }
  while {[file size test.db] <= $::sqlite_pending_byte} {
    db eval "CREATE TABLE t${iTab}(a, b, c)"
    incr iTab
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  catch { sqlite3_backup B db main db2 aux }
} {1}
do_test backup-4.1.4 {
  sqlite3_errmsg db
} {unknown database aux}

do_test backup-4.2.1 {
  catch { file delete -force test3.db }
  catch { file delete -force test4.db }
  execsql { 
    ATTACH 'test3.db' AS aux1;
    CREATE TABLE aux1.t1(a, b);
  }
  execsql { 
    ATTACH 'test4.db' AS aux2;
    CREATE TABLE aux2.t2(a, b);







|
|







388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  catch { sqlite3_backup B db main db2 aux }
} {1}
do_test backup-4.1.4 {
  sqlite3_errmsg db
} {unknown database aux}

do_test backup-4.2.1 {
  catch { forcedelete test3.db }
  catch { forcedelete test4.db }
  execsql { 
    ATTACH 'test3.db' AS aux1;
    CREATE TABLE aux1.t1(a, b);
  }
  execsql { 
    ATTACH 'test4.db' AS aux2;
    CREATE TABLE aux2.t2(a, b);
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  set rc [catch {sqlite3_backup B db main db aux1}]
  list $rc [sqlite3_errcode db] [sqlite3_errmsg db]
} {1 SQLITE_ERROR {source and destination must be distinct}}
db close
db2 close

do_test backup-4.5.1 {
  catch { file delete -force test.db }
  sqlite3 db test.db
  sqlite3 db2 :memory:
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }
  execsql {







|







435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  set rc [catch {sqlite3_backup B db main db aux1}]
  list $rc [sqlite3_errcode db] [sqlite3_errmsg db]
} {1 SQLITE_ERROR {source and destination must be distinct}}
db close
db2 close

do_test backup-4.5.1 {
  catch { forcedelete test.db }
  sqlite3 db test.db
  sqlite3 db2 :memory:
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }
  execsql {
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
#
#   1) Backing up file-to-file. The writer writes via an external pager.
#   2) Backing up file-to-file. The writer writes via the same pager as
#      is used by the backup operation.
#   3) Backing up memory-to-file. 
#
set iTest 0
file delete -force bak.db-wal
foreach {writer file} {db test.db db3 test.db db :memory:} {
  incr iTest
  catch { file delete bak.db }
  sqlite3 db2 bak.db
  catch { file delete $file }
  sqlite3 db $file
  sqlite3 db3 $file

  do_test backup-5.$iTest.1.1 {
    execsql {
      BEGIN;
      CREATE TABLE t1(a, b);







|


|

|







487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
#
#   1) Backing up file-to-file. The writer writes via an external pager.
#   2) Backing up file-to-file. The writer writes via the same pager as
#      is used by the backup operation.
#   3) Backing up memory-to-file. 
#
set iTest 0
forcedelete bak.db-wal
foreach {writer file} {db test.db db3 test.db db :memory:} {
  incr iTest
  catch { delete_file bak.db }
  sqlite3 db2 bak.db
  catch { delete_file $file }
  sqlite3 db $file
  sqlite3 db3 $file

  do_test backup-5.$iTest.1.1 {
    execsql {
      BEGIN;
      CREATE TABLE t1(a, b);
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
  } {SQLITE_OK} 
  integrity_check backup-5.$iTest.4.5 db2
  test_contents backup-5.$iTest.4.6 db main db2 main

  catch {db close}
  catch {db2 close}
  catch {db3 close}
  catch { file delete bak.db }
  sqlite3 db2 bak.db
  catch { file delete $file }
  sqlite3 db $file
  sqlite3 db3 $file
  do_test backup-5.$iTest.5.1 {
    execsql {
      PRAGMA auto_vacuum = incremental;
      BEGIN;
      CREATE TABLE t1(a, b);







|

|







593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
  } {SQLITE_OK} 
  integrity_check backup-5.$iTest.4.5 db2
  test_contents backup-5.$iTest.4.6 db main db2 main

  catch {db close}
  catch {db2 close}
  catch {db3 close}
  catch { delete_file bak.db }
  sqlite3 db2 bak.db
  catch { delete_file $file }
  sqlite3 db $file
  sqlite3 db3 $file
  do_test backup-5.$iTest.5.1 {
    execsql {
      PRAGMA auto_vacuum = incremental;
      BEGIN;
      CREATE TABLE t1(a, b);
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
# End of backup-5.* tests.
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Test the sqlite3_backup_remaining() and backup_pagecount() APIs.
#
do_test backup-6.1 {
  catch { file delete -force test.db }
  catch { file delete -force test2.db }
  sqlite3 db test.db
  sqlite3 db2 test2.db
  execsql {
    BEGIN;
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(a, b);
    INSERT INTO t1 VALUES(1, randstr(1000,1000));







|
|







640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
# End of backup-5.* tests.
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Test the sqlite3_backup_remaining() and backup_pagecount() APIs.
#
do_test backup-6.1 {
  catch { forcedelete test.db }
  catch { forcedelete test2.db }
  sqlite3 db test.db
  sqlite3 db2 test2.db
  execsql {
    BEGIN;
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(a, b);
    INSERT INTO t1 VALUES(1, randstr(1000,1000));
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
# backup-7.2.*: Attempt to step the backup process while a 
#               write-transaction is underway on the source pager (return
#               SQLITE_LOCKED).
#
# backup-7.3.*: Destination database is externally locked (return SQLITE_BUSY).
#
do_test backup-7.0 {
  catch { file delete -force test.db }
  catch { file delete -force test2.db }
  sqlite3 db2 test2.db
  sqlite3 db test.db
  execsql {
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(a, b);
    INSERT INTO t1 VALUES(1, randstr(1000,1000));
    INSERT INTO t1 SELECT a+ 1, randstr(1000,1000) FROM t1;







|
|







697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
# backup-7.2.*: Attempt to step the backup process while a 
#               write-transaction is underway on the source pager (return
#               SQLITE_LOCKED).
#
# backup-7.3.*: Destination database is externally locked (return SQLITE_BUSY).
#
do_test backup-7.0 {
  catch { forcedelete test.db }
  catch { forcedelete test2.db }
  sqlite3 db2 test2.db
  sqlite3 db test.db
  execsql {
    CREATE TABLE t1(a, b);
    CREATE INDEX i1 ON t1(a, b);
    INSERT INTO t1 VALUES(1, randstr(1000,1000));
    INSERT INTO t1 SELECT a+ 1, randstr(1000,1000) FROM t1;
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
} {SQLITE_OK}
test_contents backup-7.2.5 db main db2 main
integrity_check backup-7.3.6 db2

do_test backup-7.3.1 {
  db2 close
  db3 close
  file delete -force test2.db
  sqlite3 db2 test2.db
  sqlite3 db3 test2.db

  sqlite3_backup B db2 main db main
  execsql { BEGIN ; CREATE TABLE t2(a, b); } db3

  B step 5







|







750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
} {SQLITE_OK}
test_contents backup-7.2.5 db main db2 main
integrity_check backup-7.3.6 db2

do_test backup-7.3.1 {
  db2 close
  db3 close
  forcedelete test2.db
  sqlite3 db2 test2.db
  sqlite3 db3 test2.db

  sqlite3_backup B db2 main db main
  execsql { BEGIN ; CREATE TABLE t2(a, b); } db3

  B step 5
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
# The following tests, backup-8.*, test attaching multiple backup
# processes to the same source database. Also, reading from the source
# database while a read transaction is active.
#
# These tests reuse the database "test.db" left over from backup-7.*.
#
do_test backup-8.1 {
  catch { file delete -force test2.db }
  catch { file delete -force test3.db }
  sqlite3 db2 test2.db
  sqlite3 db3 test3.db

  sqlite3_backup B2 db2 main db main
  sqlite3_backup B3 db3 main db main
  list [B2 finish] [B3 finish]
} {SQLITE_OK SQLITE_OK}







|
|







779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
# The following tests, backup-8.*, test attaching multiple backup
# processes to the same source database. Also, reading from the source
# database while a read transaction is active.
#
# These tests reuse the database "test.db" left over from backup-7.*.
#
do_test backup-8.1 {
  catch { forcedelete test2.db }
  catch { forcedelete test3.db }
  sqlite3 db2 test2.db
  sqlite3 db3 test3.db

  sqlite3_backup B2 db2 main db main
  sqlite3_backup B3 db3 main db main
  list [B2 finish] [B3 finish]
} {SQLITE_OK SQLITE_OK}
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
do_test backup-9.2.3 {
  B finish
} {SQLITE_OK}
catch {db2 close}

ifcapable memorymanage {
  db close
  file delete -force test.db
  file delete -force bak.db

  sqlite3 db test.db
  sqlite3 db2 test.db
  sqlite3 db3 bak.db

  do_test backup-10.1.1 {
    execsql {







|
|







861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
do_test backup-9.2.3 {
  B finish
} {SQLITE_OK}
catch {db2 close}

ifcapable memorymanage {
  db close
  forcedelete test.db
  forcedelete bak.db

  sqlite3 db test.db
  sqlite3 db2 test.db
  sqlite3 db3 bak.db

  do_test backup-10.1.1 {
    execsql {
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
# Test that if the database is written to via the same database handle being
# used as the source by a backup operation:
#
#   10.1.*: If the db is in-memory, the backup is restarted.
#   10.2.*: If the db is a file, the backup is not restarted.
#
db close
file delete -force test.db test.db-journal
foreach {tn file rc} {
  1 test.db  SQLITE_DONE
  2 :memory: SQLITE_OK
} {
  do_test backup-10.$tn.1 {
    sqlite3 db $file
    execsql { 







|







914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
# Test that if the database is written to via the same database handle being
# used as the source by a backup operation:
#
#   10.1.*: If the db is in-memory, the backup is restarted.
#   10.2.*: If the db is a file, the backup is not restarted.
#
db close
forcedelete test.db test.db-journal
foreach {tn file rc} {
  1 test.db  SQLITE_DONE
  2 :memory: SQLITE_OK
} {
  do_test backup-10.$tn.1 {
    sqlite3 db $file
    execsql { 
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958

  do_test backup-10.$tn.2 {
    set pgs [execsql {pragma page_count}]
    expr {$pgs > 50 && $pgs < 75}
  } {1}

  do_test backup-10.$tn.3 {
    file delete -force bak.db bak.db-journal
    sqlite3 db2 bak.db
    sqlite3_backup B db2 main db main
    B step 50
  } {SQLITE_OK}

  do_test backup-10.$tn.4 {
    execsql { UPDATE t1 SET b = randomblob(200) WHERE a IN (1, 250) }







|







944
945
946
947
948
949
950
951
952
953
954
955
956
957
958

  do_test backup-10.$tn.2 {
    set pgs [execsql {pragma page_count}]
    expr {$pgs > 50 && $pgs < 75}
  } {1}

  do_test backup-10.$tn.3 {
    forcedelete bak.db bak.db-journal
    sqlite3 db2 bak.db
    sqlite3_backup B db2 main db main
    B step 50
  } {SQLITE_OK}

  do_test backup-10.$tn.4 {
    execsql { UPDATE t1 SET b = randomblob(200) WHERE a IN (1, 250) }

Changes to test/backup2.test.

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
unset -nocomplain cksum
set cksum [dbcksum db main]

# Make a backup of the test data.  Verify that the backup copy
# is identical to the original.
#
do_test backup2-2 {
  file delete -force bu1.db
  db backup bu1.db
  sqlite3 db2 bu1.db
  dbcksum db2 main
} $cksum

# Delete the original.  Restore from backup.  Verify the content is
# unchanged.
#
do_test backup2-3.1 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  db2 eval {BEGIN EXCLUSIVE}
  set rc [catch {db restore bu1.db} res]
  lappend rc $res
  db2 eval {ROLLBACK}
  set rc
} {1 {restore failed: source database busy}}
do_test backup2-3.2 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  db restore bu1.db
  dbcksum db main
} $cksum

# Use alternative databases - other than "main".
#
do_test backup2-4 {
  db restore temp bu1.db
  dbcksum db temp
} $cksum
do_test backup2-5 {
  db2 close
  file delete -force bu1.db bu2.db
  db backup temp bu2.db
  sqlite3 db2 bu2.db
  dbcksum db2 main
} $cksum

# Try to backup to a readonly file.
#







|










|









|













|







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
unset -nocomplain cksum
set cksum [dbcksum db main]

# Make a backup of the test data.  Verify that the backup copy
# is identical to the original.
#
do_test backup2-2 {
  forcedelete bu1.db
  db backup bu1.db
  sqlite3 db2 bu1.db
  dbcksum db2 main
} $cksum

# Delete the original.  Restore from backup.  Verify the content is
# unchanged.
#
do_test backup2-3.1 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  db2 eval {BEGIN EXCLUSIVE}
  set rc [catch {db restore bu1.db} res]
  lappend rc $res
  db2 eval {ROLLBACK}
  set rc
} {1 {restore failed: source database busy}}
do_test backup2-3.2 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  db restore bu1.db
  dbcksum db main
} $cksum

# Use alternative databases - other than "main".
#
do_test backup2-4 {
  db restore temp bu1.db
  dbcksum db temp
} $cksum
do_test backup2-5 {
  db2 close
  forcedelete bu1.db bu2.db
  db backup temp bu2.db
  sqlite3 db2 bu2.db
  dbcksum db2 main
} $cksum

# Try to backup to a readonly file.
#
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
  set rc [catch {db backup temp bu2.db} res]
  lappend rc $res
} {1 {backup failed: file is encrypted or is not a database}}

# Try to backup database that does not exist
#
do_test backup2-8 {
  file delete -force bu1.db
  set rc [catch {db backup aux1 bu1.db} res]
  lappend rc $res
} {1 {backup failed: unknown database aux1}}

# Invalid syntax on the backup method
#
do_test backup2-9 {
  set rc [catch {db backup} res]
  lappend rc $res
} {1 {wrong # args: should be "db backup ?DATABASE? FILENAME"}}

# Try to restore from an unreadable file.
#
if {$tcl_platform(platform)=="windows"} {
  do_test backup2-10 {
    file delete -force bu3.db
    file mkdir bu3.db
    set rc [catch {db restore temp bu3.db} res]
    lappend rc $res
  } {1 {cannot open source database: unable to open database file}}
}
if {$tcl_platform(platform)!="windows"} {
  do_test backup2-10 {
    file delete -force bu3.db
    file mkdir bu3.db
    set rc [catch {db restore temp bu3.db} res]
    lappend rc $res
  } {1 {cannot open source database: disk I/O error}}
}

# Try to restore from something that is not a database file.
#
do_test backup2-11 {
  set rc [catch {db restore temp bu2.db} res]
  lappend rc $res
} {1 {restore failed: file is encrypted or is not a database}}

# Try to restore a database that does not exist
#
do_test backup2-12 {
  set rc [catch {db restore aux1 bu2.db} res]
  lappend rc $res
} {1 {restore failed: unknown database aux1}}
do_test backup2-13 {
  file delete -force bu4.db
  set rc [catch {db restore bu4.db} res]
  lappend rc $res
} {1 {cannot open source database: unable to open database file}}

# Invalid syntax on the restore method
#
do_test backup2-14 {
  set rc [catch {db restore} res]
  lappend rc $res
} {1 {wrong # args: should be "db restore ?DATABASE? FILENAME"}}
 
file delete -force bu1.db bu2.db bu3.db bu4.db

finish_test







|















|







|




















|











|


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
  set rc [catch {db backup temp bu2.db} res]
  lappend rc $res
} {1 {backup failed: file is encrypted or is not a database}}

# Try to backup database that does not exist
#
do_test backup2-8 {
  forcedelete bu1.db
  set rc [catch {db backup aux1 bu1.db} res]
  lappend rc $res
} {1 {backup failed: unknown database aux1}}

# Invalid syntax on the backup method
#
do_test backup2-9 {
  set rc [catch {db backup} res]
  lappend rc $res
} {1 {wrong # args: should be "db backup ?DATABASE? FILENAME"}}

# Try to restore from an unreadable file.
#
if {$tcl_platform(platform)=="windows"} {
  do_test backup2-10 {
    forcedelete bu3.db
    file mkdir bu3.db
    set rc [catch {db restore temp bu3.db} res]
    lappend rc $res
  } {1 {cannot open source database: unable to open database file}}
}
if {$tcl_platform(platform)!="windows"} {
  do_test backup2-10 {
    forcedelete bu3.db
    file mkdir bu3.db
    set rc [catch {db restore temp bu3.db} res]
    lappend rc $res
  } {1 {cannot open source database: disk I/O error}}
}

# Try to restore from something that is not a database file.
#
do_test backup2-11 {
  set rc [catch {db restore temp bu2.db} res]
  lappend rc $res
} {1 {restore failed: file is encrypted or is not a database}}

# Try to restore a database that does not exist
#
do_test backup2-12 {
  set rc [catch {db restore aux1 bu2.db} res]
  lappend rc $res
} {1 {restore failed: unknown database aux1}}
do_test backup2-13 {
  forcedelete bu4.db
  set rc [catch {db restore bu4.db} res]
  lappend rc $res
} {1 {cannot open source database: unable to open database file}}

# Invalid syntax on the restore method
#
do_test backup2-14 {
  set rc [catch {db restore} res]
  lappend rc $res
} {1 {wrong # args: should be "db restore ?DATABASE? FILENAME"}}
 
forcedelete bu1.db bu2.db bu3.db bu4.db

finish_test

Changes to test/backup_ioerr.test.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  expr {$nPage>130 && $nPage<160}
} {1}
do_test backup_ioerr-1.2 {
  expr {[file size test.db] > $sqlite_pending_byte}
} {1}
do_test backup_ioerr-1.3 {
  db close
  file delete -force test.db
} {}

# Turn off IO error simulation.
#
proc clear_ioerr_simulation {} {
  set ::sqlite_io_error_hit 0
  set ::sqlite_io_error_hardhit 0







|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  expr {$nPage>130 && $nPage<160}
} {1}
do_test backup_ioerr-1.2 {
  expr {[file size test.db] > $sqlite_pending_byte}
} {1}
do_test backup_ioerr-1.3 {
  db close
  forcedelete test.db
} {}

# Turn off IO error simulation.
#
proc clear_ioerr_simulation {} {
  set ::sqlite_io_error_hit 0
  set ::sqlite_io_error_hardhit 0
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  set bStop 0
for {set iError 1} {$bStop == 0} {incr iError} {
  # Disable IO error simulation.
  clear_ioerr_simulation

  catch { ddb close }
  catch { sdb close }
  catch { file delete -force test.db }
  catch { file delete -force bak.db }

  # Open the source and destination databases.
  sqlite3 sdb test.db
  sqlite3 ddb bak.db

  # Step 1: Populate the source and destination databases.
  populate_database sdb







|
|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  set bStop 0
for {set iError 1} {$bStop == 0} {incr iError} {
  # Disable IO error simulation.
  clear_ioerr_simulation

  catch { ddb close }
  catch { sdb close }
  catch { forcedelete test.db }
  catch { forcedelete bak.db }

  # Open the source and destination databases.
  sqlite3 sdb test.db
  sqlite3 ddb bak.db

  # Step 1: Populate the source and destination databases.
  populate_database sdb

Changes to test/capi3.test.

693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
  db close
}

if {![sqlite3 -has-codec]} {
  # Now test that the library correctly handles bogus entries in the
  # sqlite_master table (schema corruption).
  do_test capi3-8.1 {
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(a);
    }
    db close
  } {}
  do_test capi3-8.2 {







|







693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
  db close
}

if {![sqlite3 -has-codec]} {
  # Now test that the library correctly handles bogus entries in the
  # sqlite_master table (schema corruption).
  do_test capi3-8.1 {
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(a);
    }
    db close
  } {}
  do_test capi3-8.2 {
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema (?)}}
  do_test capi3-8.4 {
    # Build a 5-field row record. The first field is a string 'table', and
    # subsequent fields are all NULL.
    db close
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(a);
      PRAGMA writable_schema=ON;
      INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL);
    }
    db close
  } {};
  do_test capi3-8.5 {
    catch { sqlite3 db test.db }
    catchsql {
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema (?)}}
  db close
}
file delete -force test.db
file delete -force test.db-journal


# Test the english language string equivalents for sqlite error codes
set code2english [list \
SQLITE_OK         {not an error} \
SQLITE_ERROR      {SQL logic error or missing database} \
SQLITE_PERM       {access permission denied} \







|
















|
|







718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema (?)}}
  do_test capi3-8.4 {
    # Build a 5-field row record. The first field is a string 'table', and
    # subsequent fields are all NULL.
    db close
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(a);
      PRAGMA writable_schema=ON;
      INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL);
    }
    db close
  } {};
  do_test capi3-8.5 {
    catch { sqlite3 db test.db }
    catchsql {
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema (?)}}
  db close
}
forcedelete test.db
forcedelete test.db-journal


# Test the english language string equivalents for sqlite error codes
set code2english [list \
SQLITE_OK         {not an error} \
SQLITE_ERROR      {SQL logic error or missing database} \
SQLITE_PERM       {access permission denied} \

Changes to test/capi3c.test.

666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
  db close
}

if {![sqlite3 -has-codec]} {
  # Now test that the library correctly handles bogus entries in the
  # sqlite_master table (schema corruption).
  do_test capi3c-8.1 {
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(a);
    }
    db close
  } {}
  do_test capi3c-8.2 {







|







666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
  db close
}

if {![sqlite3 -has-codec]} {
  # Now test that the library correctly handles bogus entries in the
  # sqlite_master table (schema corruption).
  do_test capi3c-8.1 {
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(a);
    }
    db close
  } {}
  do_test capi3c-8.2 {
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema (?)}}
  do_test capi3c-8.4 {
    # Build a 5-field row record. The first field is a string 'table', and
    # subsequent fields are all NULL.
    db close
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(a);
      PRAGMA writable_schema=ON;
      INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL);
    }
    db close
  } {};
  do_test capi3c-8.5 {
    catch { sqlite3 db test.db }
    catchsql {
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema (?)}}
  db close
}
file delete -force test.db
file delete -force test.db-journal


# Test the english language string equivalents for sqlite error codes
set code2english [list \
SQLITE_OK         {not an error} \
SQLITE_ERROR      {SQL logic error or missing database} \
SQLITE_PERM       {access permission denied} \







|
















|
|







691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema (?)}}
  do_test capi3c-8.4 {
    # Build a 5-field row record. The first field is a string 'table', and
    # subsequent fields are all NULL.
    db close
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(a);
      PRAGMA writable_schema=ON;
      INSERT INTO sqlite_master VALUES('table',NULL,NULL,NULL,NULL);
    }
    db close
  } {};
  do_test capi3c-8.5 {
    catch { sqlite3 db test.db }
    catchsql {
      SELECT * FROM sqlite_master;
    }
  } {1 {malformed database schema (?)}}
  db close
}
forcedelete test.db
forcedelete test.db-journal


# Test the english language string equivalents for sqlite error codes
set code2english [list \
SQLITE_OK         {not an error} \
SQLITE_ERROR      {SQL logic error or missing database} \
SQLITE_PERM       {access permission denied} \

Changes to test/collate7.test.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
do_test collate7-1.4 {
  sqlite3_create_collation_v2 db CASELESS caseless_cmp {incr ::caseless_del}
  db close
  set ::caseless_del
} {2}

do_test collate7-2.1 {
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  sqlite3_create_collation_v2 db CASELESS caseless_cmp {incr ::caseless_del}
  execsql {
    PRAGMA encoding='utf-16';
    CREATE TABLE abc16(a COLLATE CASELESS, b, c);
  } db
  set ::caseless_del







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
do_test collate7-1.4 {
  sqlite3_create_collation_v2 db CASELESS caseless_cmp {incr ::caseless_del}
  db close
  set ::caseless_del
} {2}

do_test collate7-2.1 {
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  sqlite3_create_collation_v2 db CASELESS caseless_cmp {incr ::caseless_del}
  execsql {
    PRAGMA encoding='utf-16';
    CREATE TABLE abc16(a COLLATE CASELESS, b, c);
  } db
  set ::caseless_del

Changes to test/corrupt.test.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.
#
# $Id: corrupt.test,v 1.12 2009/07/13 09:41:45 danielk1977 Exp $

catch {file delete -force test.db test.db-journal test.bu}

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

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.
#
# $Id: corrupt.test,v 1.12 2009/07/13 09:41:45 danielk1977 Exp $

catch {forcedelete test.db test.db-journal test.bu}

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

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
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
    CREATE TABLE t2 AS SELECT * FROM t1;
    DELETE FROM t2 WHERE rowid%5!=0;
    COMMIT;
  }
} {}
integrity_check corrupt-1.2

# Copy file $from into $to
#
proc copy_file {from to} {
  set f [open $from]
  fconfigure $f -translation binary
  set t [open $to w]
  fconfigure $t -translation binary
  puts -nonewline $t [read $f [file size $from]]
  close $t
  close $f
}

# Setup for the tests.  Make a backup copy of the good database in test.bu.
# Create a string of garbage data that is 256 bytes long.
#
copy_file test.db test.bu
set fsize [file size test.db]
set junk "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
while {[string length $junk]<256} {append junk $junk}
set junk [string range $junk 0 255]

# Go through the database and write garbage data into each 256 segment
# of the file.  Then do various operations on the file to make sure that
# the database engine can recover gracefully from the corruption.
#
for {set i [expr {1*256}]} {$i<$fsize-256} {incr i 256} {
  set tn [expr {$i/256}]
  db close
  copy_file test.bu test.db
  set fd [open test.db r+]
  fconfigure $fd -translation binary
  seek $fd $i
  puts -nonewline $fd $junk
  close $fd
  do_test corrupt-2.$tn.1 {
    sqlite3 db test.db







<
<
<
<
<
<
<
<
<
<
<
<



|












|







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
    CREATE TABLE t2 AS SELECT * FROM t1;
    DELETE FROM t2 WHERE rowid%5!=0;
    COMMIT;
  }
} {}
integrity_check corrupt-1.2













# Setup for the tests.  Make a backup copy of the good database in test.bu.
# Create a string of garbage data that is 256 bytes long.
#
forcecopy test.db test.bu
set fsize [file size test.db]
set junk "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
while {[string length $junk]<256} {append junk $junk}
set junk [string range $junk 0 255]

# Go through the database and write garbage data into each 256 segment
# of the file.  Then do various operations on the file to make sure that
# the database engine can recover gracefully from the corruption.
#
for {set i [expr {1*256}]} {$i<$fsize-256} {incr i 256} {
  set tn [expr {$i/256}]
  db close
  forcecopy test.bu test.db
  set fd [open test.db r+]
  fconfigure $fd -translation binary
  seek $fd $i
  puts -nonewline $fd $junk
  close $fd
  do_test corrupt-2.$tn.1 {
    sqlite3 db test.db
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#------------------------------------------------------------------------
# For these tests, swap the rootpage entries of t1 (a table) and t1i1 (an
# index on t1) in sqlite_master. Then perform a few different queries
# and make sure this is detected as corruption.
#
do_test corrupt-3.1 {
  db close
  copy_file test.bu test.db
  sqlite3 db test.db
  list
} {}
do_test corrupt-3.2 {
  set t1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1i1'}]
  set t1i1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1'}]
  set cookie [expr [execsql {PRAGMA schema_version}] + 1]







|







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#------------------------------------------------------------------------
# For these tests, swap the rootpage entries of t1 (a table) and t1i1 (an
# index on t1) in sqlite_master. Then perform a few different queries
# and make sure this is detected as corruption.
#
do_test corrupt-3.1 {
  db close
  forcecopy test.bu test.db
  sqlite3 db test.db
  list
} {}
do_test corrupt-3.2 {
  set t1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1i1'}]
  set t1i1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1'}]
  set cookie [expr [execsql {PRAGMA schema_version}] + 1]
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  catchsql {
    SELECT * FROM t1 WHERE x = 'abcde';
  }
} {1 {database disk image is malformed}}

do_test corrupt-4.1 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
  }
  for {set i 0} {$i < 10} {incr i} {
    set text [string repeat $i 220]







|







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  catchsql {
    SELECT * FROM t1 WHERE x = 'abcde';
  }
} {1 {database disk image is malformed}}

do_test corrupt-4.1 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
  }
  for {set i 0} {$i < 10} {incr i} {
    set text [string repeat $i 220]
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  # index b-tree as expected. At one point this was causing an assert()
  # to fail.
  catchsql { DELETE FROM t1 WHERE rowid = 3 }
} {1 {database disk image is malformed}}

do_test corrupt-5.1 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db

  execsql { PRAGMA page_size = 1024 }
  set ct "CREATE TABLE t1(c0 "
  set i 0
  while {[string length $ct] < 950} { append ct ", c[incr i]" }
  append ct ")"







|







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  # index b-tree as expected. At one point this was causing an assert()
  # to fail.
  catchsql { DELETE FROM t1 WHERE rowid = 3 }
} {1 {database disk image is malformed}}

do_test corrupt-5.1 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db

  execsql { PRAGMA page_size = 1024 }
  set ct "CREATE TABLE t1(c0 "
  set i 0
  while {[string length $ct] < 950} { append ct ", c[incr i]" }
  append ct ")"
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
} {1 {database disk image is malformed}}

# At one point, the specific corruption caused by this test case was
# causing a buffer overwrite. Although a crash was never demonstrated,
# running this testcase under valgrind revealed the problem.
do_test corrupt-6.1 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql { 
    PRAGMA page_size = 1024; CREATE TABLE t1(x);
  }

  # The root page of t1 is 1024 bytes in size. The header is 8 bytes, and
  # each of the cells inserted by the following INSERT statements consume







|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
} {1 {database disk image is malformed}}

# At one point, the specific corruption caused by this test case was
# causing a buffer overwrite. Although a crash was never demonstrated,
# running this testcase under valgrind revealed the problem.
do_test corrupt-6.1 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  execsql { 
    PRAGMA page_size = 1024; CREATE TABLE t1(x);
  }

  # The root page of t1 is 1024 bytes in size. The header is 8 bytes, and
  # each of the cells inserted by the following INSERT statements consume
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  sqlite3 db test.db 

  catchsql { INSERT INTO t1 VALUES( randomblob(10) ) }
} {1 {database disk image is malformed}}

ifcapable oversize_cell_check {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql { 
    PRAGMA page_size = 1024; CREATE TABLE t1(x);
  }

  do_test corrupt-7.1 {
    for {set i 0} {$i < 39} {incr i} {







|







248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  sqlite3 db test.db 

  catchsql { INSERT INTO t1 VALUES( randomblob(10) ) }
} {1 {database disk image is malformed}}

ifcapable oversize_cell_check {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  execsql { 
    PRAGMA page_size = 1024; CREATE TABLE t1(x);
  }

  do_test corrupt-7.1 {
    for {set i 0} {$i < 39} {incr i} {
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
    catchsql {
      INSERT INTO t1 VALUES(X'000100020003000400050006000700080009000A');
    }
  } {1 {database disk image is malformed}}
}

db close
file delete -force test.db test.db-journal
do_test corrupt-8.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA secure_delete = on;
    PRAGMA auto_vacuum = 0;
    CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
    INSERT INTO t1 VALUES(5, randomblob(1900));
  }

  hexio_write test.db 2044 [hexio_render_int32 2]
  hexio_write test.db 24   [hexio_render_int32 45]

  catchsql { INSERT OR REPLACE INTO t1 VALUES(5, randomblob(1900)) }
} {1 {database disk image is malformed}}

db close
file delete -force test.db test.db-journal
do_test corrupt-8.2 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA secure_delete = on;
    PRAGMA auto_vacuum = 0;
    CREATE TABLE t1(x INTEGER PRIMARY KEY, y);







|

















|







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
    catchsql {
      INSERT INTO t1 VALUES(X'000100020003000400050006000700080009000A');
    }
  } {1 {database disk image is malformed}}
}

db close
forcedelete test.db test.db-journal
do_test corrupt-8.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA secure_delete = on;
    PRAGMA auto_vacuum = 0;
    CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
    INSERT INTO t1 VALUES(5, randomblob(1900));
  }

  hexio_write test.db 2044 [hexio_render_int32 2]
  hexio_write test.db 24   [hexio_render_int32 45]

  catchsql { INSERT OR REPLACE INTO t1 VALUES(5, randomblob(1900)) }
} {1 {database disk image is malformed}}

db close
forcedelete test.db test.db-journal
do_test corrupt-8.2 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA secure_delete = on;
    PRAGMA auto_vacuum = 0;
    CREATE TABLE t1(x INTEGER PRIMARY KEY, y);

Changes to test/corrupt2.test.

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
    CREATE TABLE abc(a, b, c);
  }
} {}

do_test corrupt2-1.2 {

  # Corrupt the 16 byte magic string at the start of the file
  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  copy_file test.db corrupt.db
  set f [open corrupt.db RDWR]
  seek $f 8 start
  puts $f blah
  close $f

  sqlite3 db2 corrupt.db
  catchsql "
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {file is encrypted or is not a database}}

do_test corrupt2-1.3 {
  db2 close

  # Corrupt the page-size (bytes 16 and 17 of page 1).
  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  copy_file test.db corrupt.db
  set f [open corrupt.db RDWR]
  fconfigure $f -encoding binary
  seek $f 16 start
  puts -nonewline $f "\x00\xFF"
  close $f

  sqlite3 db2 corrupt.db
  catchsql "
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {file is encrypted or is not a database}}

do_test corrupt2-1.4 {
  db2 close

  # Corrupt the free-block list on page 1.
  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  copy_file test.db corrupt.db
  set f [open corrupt.db RDWR]
  fconfigure $f -encoding binary
  seek $f 101 start
  puts -nonewline $f "\xFF\xFF"
  close $f

  sqlite3 db2 corrupt.db
  catchsql "
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {database disk image is malformed}}

do_test corrupt2-1.5 {
  db2 close

  # Corrupt the free-block list on page 1.
  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  copy_file test.db corrupt.db
  set f [open corrupt.db RDWR]
  fconfigure $f -encoding binary
  seek $f 101 start
  puts -nonewline $f "\x00\xC8"
  seek $f 200 start
  puts -nonewline $f "\x00\x00"
  puts -nonewline $f "\x10\x00"
  close $f

  sqlite3 db2 corrupt.db
  catchsql "
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {database disk image is malformed}}
db2 close

# Corrupt a database by having 2 indices of the same name:
do_test corrupt2-2.1 {

  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  copy_file test.db corrupt.db

  sqlite3 db2 corrupt.db 
  execsql "
    $::presql
    CREATE INDEX a1 ON abc(a);
    CREATE INDEX a2 ON abc(b);
    PRAGMA writable_schema = 1;







|
|
|
















|
|
|

















|
|
|

















|
|
|




















|
|
|







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
    CREATE TABLE abc(a, b, c);
  }
} {}

do_test corrupt2-1.2 {

  # Corrupt the 16 byte magic string at the start of the file
  forcedelete corrupt.db
  forcedelete corrupt.db-journal
  forcecopy test.db corrupt.db
  set f [open corrupt.db RDWR]
  seek $f 8 start
  puts $f blah
  close $f

  sqlite3 db2 corrupt.db
  catchsql "
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {file is encrypted or is not a database}}

do_test corrupt2-1.3 {
  db2 close

  # Corrupt the page-size (bytes 16 and 17 of page 1).
  forcedelete corrupt.db
  forcedelete corrupt.db-journal
  forcecopy test.db corrupt.db
  set f [open corrupt.db RDWR]
  fconfigure $f -encoding binary
  seek $f 16 start
  puts -nonewline $f "\x00\xFF"
  close $f

  sqlite3 db2 corrupt.db
  catchsql "
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {file is encrypted or is not a database}}

do_test corrupt2-1.4 {
  db2 close

  # Corrupt the free-block list on page 1.
  forcedelete corrupt.db
  forcedelete corrupt.db-journal
  forcecopy test.db corrupt.db
  set f [open corrupt.db RDWR]
  fconfigure $f -encoding binary
  seek $f 101 start
  puts -nonewline $f "\xFF\xFF"
  close $f

  sqlite3 db2 corrupt.db
  catchsql "
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {database disk image is malformed}}

do_test corrupt2-1.5 {
  db2 close

  # Corrupt the free-block list on page 1.
  forcedelete corrupt.db
  forcedelete corrupt.db-journal
  forcecopy test.db corrupt.db
  set f [open corrupt.db RDWR]
  fconfigure $f -encoding binary
  seek $f 101 start
  puts -nonewline $f "\x00\xC8"
  seek $f 200 start
  puts -nonewline $f "\x00\x00"
  puts -nonewline $f "\x10\x00"
  close $f

  sqlite3 db2 corrupt.db
  catchsql "
    $::presql
    SELECT * FROM sqlite_master;
  " db2
} {1 {database disk image is malformed}}
db2 close

# Corrupt a database by having 2 indices of the same name:
do_test corrupt2-2.1 {

  forcedelete corrupt.db
  forcedelete corrupt.db-journal
  forcecopy test.db corrupt.db

  sqlite3 db2 corrupt.db 
  execsql "
    $::presql
    CREATE INDEX a1 ON abc(a);
    CREATE INDEX a2 ON abc(b);
    PRAGMA writable_schema = 1;
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
    SELECT * FROM sqlite_master;
  " db2
} {1 {malformed database schema (a3) - index a3 already exists}}

db2 close

do_test corrupt2-3.1 {
  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  sqlite3 db2 corrupt.db 

  execsql "
    $::presql
    PRAGMA auto_vacuum = 1;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b, c);







|
|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
    SELECT * FROM sqlite_master;
  " db2
} {1 {malformed database schema (a3) - index a3 already exists}}

db2 close

do_test corrupt2-3.1 {
  forcedelete corrupt.db
  forcedelete corrupt.db-journal
  sqlite3 db2 corrupt.db 

  execsql "
    $::presql
    PRAGMA auto_vacuum = 1;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b, c);
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  } db2
} {1 {database disk image is malformed}}

db2 close

unset -nocomplain result
do_test corrupt2-5.1 {
  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  sqlite3 db2 corrupt.db 

  execsql "
    $::presql
    PRAGMA auto_vacuum = 0;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b, c);







|
|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  } db2
} {1 {database disk image is malformed}}

db2 close

unset -nocomplain result
do_test corrupt2-5.1 {
  forcedelete corrupt.db
  forcedelete corrupt.db-journal
  sqlite3 db2 corrupt.db 

  execsql "
    $::presql
    PRAGMA auto_vacuum = 0;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b, c);
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
proc corruption_test {args} {
  set A(-corrupt) {}
  set A(-sqlprep) {}
  set A(-tclprep) {}
  array set A $args

  catch {db close}
  file delete -force corrupt.db
  file delete -force corrupt.db-journal

  sqlite3 db corrupt.db 
  db eval $::presql
  eval $A(-tclprep)
  db eval $A(-sqlprep)
  db close








|
|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
proc corruption_test {args} {
  set A(-corrupt) {}
  set A(-sqlprep) {}
  set A(-tclprep) {}
  array set A $args

  catch {db close}
  forcedelete corrupt.db
  forcedelete corrupt.db-journal

  sqlite3 db corrupt.db 
  db eval $::presql
  eval $A(-tclprep)
  db eval $A(-sqlprep)
  db close

Changes to test/corrupt9.test.

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
} {1}
integrity_check corrupt9-1.2

# Corrupt the freelist by adding duplicate entries to the freelist.
# Make sure the corruption is detected.
#
db close
file copy -force test.db test.db-template

corrupt_freelist test.db 1
sqlite3 db test.db
do_test corrupt9-2.1 {
  set x [db eval {PRAGMA integrity_check}]
  expr {$x!="ok"}
} {1}
do_test corrupt9-2.2 {
  catchsql {
    CREATE INDEX i2 ON t2(b,a);
    REINDEX;
  }
} {1 {database disk image is malformed}}


db close
file copy -force test.db-template test.db
corrupt_freelist test.db 2
sqlite3 db test.db
do_test corrupt9-3.1 {
  set x [db eval {PRAGMA integrity_check}]
  expr {$x!="ok"}
} {1}
do_test corrupt9-3.2 {
  catchsql {
    CREATE INDEX i2 ON t2(b,a);
    REINDEX;
  }
} {1 {database disk image is malformed}}

db close
file copy -force test.db-template test.db
corrupt_freelist test.db 3
sqlite3 db test.db
do_test corrupt9-4.1 {
  set x [db eval {PRAGMA integrity_check}]
  expr {$x!="ok"}
} {1}
do_test corrupt9-4.2 {







|
















|














|







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
} {1}
integrity_check corrupt9-1.2

# Corrupt the freelist by adding duplicate entries to the freelist.
# Make sure the corruption is detected.
#
db close
forcecopy test.db test.db-template

corrupt_freelist test.db 1
sqlite3 db test.db
do_test corrupt9-2.1 {
  set x [db eval {PRAGMA integrity_check}]
  expr {$x!="ok"}
} {1}
do_test corrupt9-2.2 {
  catchsql {
    CREATE INDEX i2 ON t2(b,a);
    REINDEX;
  }
} {1 {database disk image is malformed}}


db close
forcecopy test.db-template test.db
corrupt_freelist test.db 2
sqlite3 db test.db
do_test corrupt9-3.1 {
  set x [db eval {PRAGMA integrity_check}]
  expr {$x!="ok"}
} {1}
do_test corrupt9-3.2 {
  catchsql {
    CREATE INDEX i2 ON t2(b,a);
    REINDEX;
  }
} {1 {database disk image is malformed}}

db close
forcecopy test.db-template test.db
corrupt_freelist test.db 3
sqlite3 db test.db
do_test corrupt9-4.1 {
  set x [db eval {PRAGMA integrity_check}]
  expr {$x!="ok"}
} {1}
do_test corrupt9-4.2 {

Changes to test/corruptA.test.

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
} {1}
integrity_check corruptA-1.2

# Corrupt the file header in various ways and make sure the corruption
# is detected when opening the database file.
#
db close
file copy -force test.db test.db-template

set unreadable_version 02
ifcapable wal { set unreadable_version 03 }
do_test corruptA-2.1 {
  file copy -force test.db-template test.db
  hexio_write test.db 19 $unreadable_version   ;# the read format number
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is encrypted or is not a database}}
 
do_test corruptA-2.2 {
  db close
  file copy -force test.db-template test.db
  hexio_write test.db 21 41   ;# max embedded payload fraction
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is encrypted or is not a database}}
 
do_test corruptA-2.3 {
  db close
  file copy -force test.db-template test.db
  hexio_write test.db 22 1f   ;# min embedded payload fraction
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is encrypted or is not a database}}
 
do_test corruptA-2.4 {
  db close
  file copy -force test.db-template test.db
  hexio_write test.db 23 21   ;# min leaf payload fraction
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is encrypted or is not a database}}
 

finish_test







|




|







|







|







|







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
} {1}
integrity_check corruptA-1.2

# Corrupt the file header in various ways and make sure the corruption
# is detected when opening the database file.
#
db close
forcecopy test.db test.db-template

set unreadable_version 02
ifcapable wal { set unreadable_version 03 }
do_test corruptA-2.1 {
  forcecopy test.db-template test.db
  hexio_write test.db 19 $unreadable_version   ;# the read format number
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is encrypted or is not a database}}
 
do_test corruptA-2.2 {
  db close
  forcecopy test.db-template test.db
  hexio_write test.db 21 41   ;# max embedded payload fraction
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is encrypted or is not a database}}
 
do_test corruptA-2.3 {
  db close
  forcecopy test.db-template test.db
  hexio_write test.db 22 1f   ;# min embedded payload fraction
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is encrypted or is not a database}}
 
do_test corruptA-2.4 {
  db close
  forcecopy test.db-template test.db
  hexio_write test.db 23 21   ;# min leaf payload fraction
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is encrypted or is not a database}}
 

finish_test

Changes to test/corruptB.test.

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
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
  }
  expr {[file size test.db] > (1024*9)}
} {1}
integrity_check corruptB-1.2

file copy -force test.db bak.db

# Set the right-child of a B-Tree rootpage to refer to the root-page itself.
#
do_test corruptB-1.3.1 {
  set ::root [execsql {SELECT rootpage FROM sqlite_master}]
  set ::offset [expr {($::root-1)*1024}]
  hexio_write test.db [expr $offset+8] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.3.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

# Set the left-child of a cell in a B-Tree rootpage to refer to the 
# root-page itself.
#
do_test corruptB-1.4.1 {
  db close
  file copy -force bak.db test.db
  set cell_offset [hexio_get_int [hexio_read test.db [expr $offset+12] 2]]
  hexio_write test.db [expr $offset+$cell_offset] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.4.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

# Now grow the table B-Tree so that it is more than 2 levels high.
#
do_test corruptB-1.5.1 {
  db close
  file copy -force bak.db test.db
  sqlite3 db test.db
  execsql {
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
  }
} {}

file copy -force test.db bak.db

# Set the right-child pointer of the right-child of the root page to point
# back to the root page.
#
do_test corruptB-1.6.1 {
  db close
  set iRightChild [hexio_get_int [hexio_read test.db [expr $offset+8] 4]]
  set c_offset [expr ($iRightChild-1)*1024]
  hexio_write test.db [expr $c_offset+8] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.6.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

# Set the left-child pointer of a cell of the right-child of the root page to
# point back to the root page.
#
do_test corruptB-1.7.1 {
  db close
  file copy -force bak.db test.db
  set cell_offset [hexio_get_int [hexio_read test.db [expr $c_offset+12] 2]]
  hexio_write test.db [expr $c_offset+$cell_offset] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.7.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}







|


















|












|












|




















|







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
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
  }
  expr {[file size test.db] > (1024*9)}
} {1}
integrity_check corruptB-1.2

forcecopy test.db bak.db

# Set the right-child of a B-Tree rootpage to refer to the root-page itself.
#
do_test corruptB-1.3.1 {
  set ::root [execsql {SELECT rootpage FROM sqlite_master}]
  set ::offset [expr {($::root-1)*1024}]
  hexio_write test.db [expr $offset+8] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.3.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

# Set the left-child of a cell in a B-Tree rootpage to refer to the 
# root-page itself.
#
do_test corruptB-1.4.1 {
  db close
  forcecopy bak.db test.db
  set cell_offset [hexio_get_int [hexio_read test.db [expr $offset+12] 2]]
  hexio_write test.db [expr $offset+$cell_offset] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.4.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

# Now grow the table B-Tree so that it is more than 2 levels high.
#
do_test corruptB-1.5.1 {
  db close
  forcecopy bak.db test.db
  sqlite3 db test.db
  execsql {
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
    INSERT INTO t1 SELECT randomblob(200) FROM t1;
  }
} {}

forcecopy test.db bak.db

# Set the right-child pointer of the right-child of the root page to point
# back to the root page.
#
do_test corruptB-1.6.1 {
  db close
  set iRightChild [hexio_get_int [hexio_read test.db [expr $offset+8] 4]]
  set c_offset [expr ($iRightChild-1)*1024]
  hexio_write test.db [expr $c_offset+8] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.6.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

# Set the left-child pointer of a cell of the right-child of the root page to
# point back to the root page.
#
do_test corruptB-1.7.1 {
  db close
  forcecopy bak.db test.db
  set cell_offset [hexio_get_int [hexio_read test.db [expr $c_offset+12] 2]]
  hexio_write test.db [expr $c_offset+$cell_offset] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.7.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}
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
} {1 {database disk image is malformed}}

# Set the left-child pointer of a cell of the right-child of the root page to
# point back to the root page.
#
do_test corruptB-1.9.1 {
  db close
  file copy -force bak.db test.db
  set cell_offset [hexio_get_int [hexio_read test.db [expr $c_offset+12] 2]]
  hexio_write test.db [expr $c_offset+$cell_offset] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.9.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

#---------------------------------------------------------------------------

do_test corruptB-2.1.1 {
  db close
  file copy -force bak.db test.db
  hexio_write test.db [expr $offset+8] [hexio_render_int32 0x6FFFFFFF]
} {4}
do_test corruptB-2.1.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

#---------------------------------------------------------------------------

# Corrupt the header-size field of a database record.
#
do_test corruptB-3.1.1 {
  db close
  file copy -force bak.db test.db
  sqlite3 db test.db
  set v [string repeat abcdefghij 200]
  execsql {
    CREATE TABLE t2(a);
    INSERT INTO t2 VALUES($v);
  }
  set t2_root [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't2'}]







|












|













|







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
} {1 {database disk image is malformed}}

# Set the left-child pointer of a cell of the right-child of the root page to
# point back to the root page.
#
do_test corruptB-1.9.1 {
  db close
  forcecopy bak.db test.db
  set cell_offset [hexio_get_int [hexio_read test.db [expr $c_offset+12] 2]]
  hexio_write test.db [expr $c_offset+$cell_offset] [hexio_render_int32 $::root]
} {4}
do_test corruptB-1.9.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

#---------------------------------------------------------------------------

do_test corruptB-2.1.1 {
  db close
  forcecopy bak.db test.db
  hexio_write test.db [expr $offset+8] [hexio_render_int32 0x6FFFFFFF]
} {4}
do_test corruptB-2.1.2 {
  sqlite3 db test.db
  catchsql { SELECT * FROM t1 }
} {1 {database disk image is malformed}}

#---------------------------------------------------------------------------

# Corrupt the header-size field of a database record.
#
do_test corruptB-3.1.1 {
  db close
  forcecopy bak.db test.db
  sqlite3 db test.db
  set v [string repeat abcdefghij 200]
  execsql {
    CREATE TABLE t2(a);
    INSERT INTO t2 VALUES($v);
  }
  set t2_root [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't2'}]

Changes to test/corruptC.test.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.  It creates a base
# data base file, then tests that single byte corruptions in 
# increasingly larger quantities are handled gracefully.
#
# $Id: corruptC.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $

catch {file delete -force test.db test.db-journal test.bu}

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

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.  It creates a base
# data base file, then tests that single byte corruptions in 
# increasingly larger quantities are handled gracefully.
#
# $Id: corruptC.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $

catch {forcedelete test.db test.db-journal test.bu}

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

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

# Generate random integer
#
proc random {range} {
  return [expr {round(rand()*$range)}]
}

# Copy file $from into $to
#
proc copy_file {from to} {
  file copy -force $from $to
}

# Setup for the tests.  Make a backup copy of the good database in test.bu.
#
db close
copy_file test.db test.bu
sqlite3 db test.db
set fsize [file size test.db]

# Set a quasi-random random seed. 
if {[info exists ::G(issoak)]} {
  # If we are doing SOAK tests, we want a different
  # random seed for each run.  Ideally we would like 







<
<
<
<
<
<



|







54
55
56
57
58
59
60






61
62
63
64
65
66
67
68
69
70
71

# Generate random integer
#
proc random {range} {
  return [expr {round(rand()*$range)}]
}







# Setup for the tests.  Make a backup copy of the good database in test.bu.
#
db close
forcecopy test.db test.bu
sqlite3 db test.db
set fsize [file size test.db]

# Set a quasi-random random seed. 
if {[info exists ::G(issoak)]} {
  # If we are doing SOAK tests, we want a different
  # random seed for each run.  Ideally we would like 
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
# First test some specific corruption tests found from earlier runs
# with specific seeds.
#

# test that a corrupt content offset size is handled (seed 5577)
do_test corruptC-2.1 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 2053 [format %02x 0x04]

  sqlite3 db test.db
  catchsql {PRAGMA integrity_check}
} {1 {database disk image is malformed}}

# test that a corrupt content offset size is handled (seed 5649)
do_test corruptC-2.2 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 27   [format %02x 0x08]
  hexio_write test.db 233  [format %02x 0x6a]
  hexio_write test.db 328  [format %02x 0x67]
  hexio_write test.db 750  [format %02x 0x1f]
  hexio_write test.db 1132 [format %02x 0x52]
  hexio_write test.db 1133 [format %02x 0x84]
  hexio_write test.db 1220 [format %02x 0x01]
  hexio_write test.db 3688 [format %02x 0xc1]
  hexio_write test.db 3714 [format %02x 0x58]
  hexio_write test.db 3746 [format %02x 0x9a]

  sqlite3 db test.db
  catchsql {UPDATE t1 SET y=1}
} {1 {database disk image is malformed}}

# test that a corrupt free cell size is handled (seed 13329)
do_test corruptC-2.3 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 1094 [format %02x 0x76]

  sqlite3 db test.db
  catchsql {UPDATE t1 SET y=1}
} {1 {database disk image is malformed}}

# test that a corrupt free cell size is handled (seed 169571)
do_test corruptC-2.4 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 3119 [format %02x 0xdf]

  sqlite3 db test.db
  catchsql {UPDATE t2 SET y='abcdef-uvwxyz'}
} {1 {database disk image is malformed}}

# test that a corrupt free cell size is handled (seed 169571)
do_test corruptC-2.5 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 3119 [format %02x 0xdf]
  hexio_write test.db 4073 [format %02x 0xbf]

  sqlite3 db test.db
  catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
  catchsql {PRAGMA integrity_check}
} {0 {{*** in database main ***
Page 4: btreeInitPage() returns error code 11}}}

# {0 {{*** in database main ***
# Corruption detected in cell 710 on page 4
# Multiple uses for byte 661 of page 4
# Fragmented space is 249 byte reported as 21 on page 4}}}

# test that a corrupt free cell size is handled (seed 169595)
do_test corruptC-2.6 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 619 [format %02x 0xe2]
  hexio_write test.db 3150 [format %02x 0xa8]

  sqlite3 db test.db
  catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 178692)
do_test corruptC-2.7 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 3074 [format %02x 0xa0]

  sqlite3 db test.db
  catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 179069)
do_test corruptC-2.8 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 1393 [format %02x 0x7d]
  hexio_write test.db 84 [format %02x 0x19]
  hexio_write test.db 3287 [format %02x 0x3b]
  hexio_write test.db 2564 [format %02x 0xed]
  hexio_write test.db 2139 [format %02x 0x55]

  sqlite3 db test.db
  catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 170434)
do_test corruptC-2.9 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 2095 [format %02x 0xd6]

  sqlite3 db test.db
  catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 186504)
do_test corruptC-2.10 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 3130 [format %02x 0x02]
  
  sqlite3 db test.db
  catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 1589)
do_test corruptC-2.11 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 55 [format %02x 0xa7]
  
  sqlite3 db test.db
  catchsql {BEGIN; CREATE TABLE t3 AS SELECT x,3 as y FROM t2 WHERE rowid%5!=0; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 14166)
do_test corruptC-2.12 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 974 [format %02x 0x2e]
  
  sqlite3 db test.db
  catchsql {SELECT count(*) FROM sqlite_master;}
} {1 {malformed database schema (t1i1) - corrupt database}}

# corruption (seed 218803)
do_test corruptC-2.13 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 102 [format %02x 0x12]
  
  sqlite3 db test.db
  catchsql {BEGIN; CREATE TABLE t3 AS SELECT x,3 as y FROM t2 WHERE rowid%5!=0; ROLLBACK;}
} {1 {database disk image is malformed}}

do_test corruptC-2.14 {
  db close
  copy_file test.bu test.db

  sqlite3 db test.db
  set blob [string repeat abcdefghij 10000]
  execsql { INSERT INTO t1 VALUES (1, $blob) }

  sqlite3 db test.db
  set filesize [file size test.db]
  hexio_write test.db [expr $filesize-2048] 00000001
  catchsql {DELETE FROM t1 WHERE rowid = (SELECT max(rowid) FROM t1)}
} {1 {database disk image is malformed}}

# At one point this particular corrupt database was causing a buffer
# overread. Which caused a crash in a run of all.test once.
#
do_test corruptC-2.15 {
  db close
  copy_file test.bu test.db
  hexio_write test.db 986 b9
  sqlite3 db test.db
  catchsql {SELECT count(*) FROM sqlite_master;}
} {1 {malformed database schema (t1i1) - no such table: main.t1}}

#
# Now test for a series of quasi-random seeds.
# We loop over the entire file size and touch
# each byte at least once.
for {set tn 0} {$tn<$fsize} {incr tn 1} {

  # setup for test
  db close
  copy_file test.bu test.db
  sqlite3 db test.db

  # Seek to a random location in the file, and write a random single byte
  # value.  Then do various operations on the file to make sure that
  # the database engine can handle the corruption gracefully.
  #
  set last 0







|











|




















|











|











|



















|












|











|















|











|











|











|











|










|
















|













|







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
# First test some specific corruption tests found from earlier runs
# with specific seeds.
#

# test that a corrupt content offset size is handled (seed 5577)
do_test corruptC-2.1 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 2053 [format %02x 0x04]

  sqlite3 db test.db
  catchsql {PRAGMA integrity_check}
} {1 {database disk image is malformed}}

# test that a corrupt content offset size is handled (seed 5649)
do_test corruptC-2.2 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 27   [format %02x 0x08]
  hexio_write test.db 233  [format %02x 0x6a]
  hexio_write test.db 328  [format %02x 0x67]
  hexio_write test.db 750  [format %02x 0x1f]
  hexio_write test.db 1132 [format %02x 0x52]
  hexio_write test.db 1133 [format %02x 0x84]
  hexio_write test.db 1220 [format %02x 0x01]
  hexio_write test.db 3688 [format %02x 0xc1]
  hexio_write test.db 3714 [format %02x 0x58]
  hexio_write test.db 3746 [format %02x 0x9a]

  sqlite3 db test.db
  catchsql {UPDATE t1 SET y=1}
} {1 {database disk image is malformed}}

# test that a corrupt free cell size is handled (seed 13329)
do_test corruptC-2.3 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 1094 [format %02x 0x76]

  sqlite3 db test.db
  catchsql {UPDATE t1 SET y=1}
} {1 {database disk image is malformed}}

# test that a corrupt free cell size is handled (seed 169571)
do_test corruptC-2.4 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 3119 [format %02x 0xdf]

  sqlite3 db test.db
  catchsql {UPDATE t2 SET y='abcdef-uvwxyz'}
} {1 {database disk image is malformed}}

# test that a corrupt free cell size is handled (seed 169571)
do_test corruptC-2.5 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 3119 [format %02x 0xdf]
  hexio_write test.db 4073 [format %02x 0xbf]

  sqlite3 db test.db
  catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
  catchsql {PRAGMA integrity_check}
} {0 {{*** in database main ***
Page 4: btreeInitPage() returns error code 11}}}

# {0 {{*** in database main ***
# Corruption detected in cell 710 on page 4
# Multiple uses for byte 661 of page 4
# Fragmented space is 249 byte reported as 21 on page 4}}}

# test that a corrupt free cell size is handled (seed 169595)
do_test corruptC-2.6 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 619 [format %02x 0xe2]
  hexio_write test.db 3150 [format %02x 0xa8]

  sqlite3 db test.db
  catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 178692)
do_test corruptC-2.7 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 3074 [format %02x 0xa0]

  sqlite3 db test.db
  catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 179069)
do_test corruptC-2.8 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 1393 [format %02x 0x7d]
  hexio_write test.db 84 [format %02x 0x19]
  hexio_write test.db 3287 [format %02x 0x3b]
  hexio_write test.db 2564 [format %02x 0xed]
  hexio_write test.db 2139 [format %02x 0x55]

  sqlite3 db test.db
  catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 170434)
do_test corruptC-2.9 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 2095 [format %02x 0xd6]

  sqlite3 db test.db
  catchsql {BEGIN; DELETE FROM t1 WHERE x>13; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 186504)
do_test corruptC-2.10 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 3130 [format %02x 0x02]
  
  sqlite3 db test.db
  catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 1589)
do_test corruptC-2.11 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 55 [format %02x 0xa7]
  
  sqlite3 db test.db
  catchsql {BEGIN; CREATE TABLE t3 AS SELECT x,3 as y FROM t2 WHERE rowid%5!=0; ROLLBACK;}
} {1 {database disk image is malformed}}

# corruption (seed 14166)
do_test corruptC-2.12 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 974 [format %02x 0x2e]
  
  sqlite3 db test.db
  catchsql {SELECT count(*) FROM sqlite_master;}
} {1 {malformed database schema (t1i1) - corrupt database}}

# corruption (seed 218803)
do_test corruptC-2.13 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 102 [format %02x 0x12]
  
  sqlite3 db test.db
  catchsql {BEGIN; CREATE TABLE t3 AS SELECT x,3 as y FROM t2 WHERE rowid%5!=0; ROLLBACK;}
} {1 {database disk image is malformed}}

do_test corruptC-2.14 {
  db close
  forcecopy test.bu test.db

  sqlite3 db test.db
  set blob [string repeat abcdefghij 10000]
  execsql { INSERT INTO t1 VALUES (1, $blob) }

  sqlite3 db test.db
  set filesize [file size test.db]
  hexio_write test.db [expr $filesize-2048] 00000001
  catchsql {DELETE FROM t1 WHERE rowid = (SELECT max(rowid) FROM t1)}
} {1 {database disk image is malformed}}

# At one point this particular corrupt database was causing a buffer
# overread. Which caused a crash in a run of all.test once.
#
do_test corruptC-2.15 {
  db close
  forcecopy test.bu test.db
  hexio_write test.db 986 b9
  sqlite3 db test.db
  catchsql {SELECT count(*) FROM sqlite_master;}
} {1 {malformed database schema (t1i1) - no such table: main.t1}}

#
# Now test for a series of quasi-random seeds.
# We loop over the entire file size and touch
# each byte at least once.
for {set tn 0} {$tn<$fsize} {incr tn 1} {

  # setup for test
  db close
  forcecopy test.bu test.db
  sqlite3 db test.db

  # Seek to a random location in the file, and write a random single byte
  # value.  Then do various operations on the file to make sure that
  # the database engine can handle the corruption gracefully.
  #
  set last 0

Changes to test/corruptD.test.

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
  }
  execsql {
    DELETE FROM t1 WHERE a = 10;
    DELETE FROM t1 WHERE a = 20;
    DELETE FROM t1 WHERE a = 30;
    DELETE FROM t1 WHERE a = 40;
  }
  copy_file test.db test.bu
} {}

proc incr_change_counter {} {
  hexio_write test.db 24 [
    hexio_render_int32 [expr [hexio_get_int [hexio_read test.db 24 4]] + 1]
  ]
}

proc restore_file {} {
  db close
  copy_file test.bu test.db
  sqlite3 db test.db
}

#-------------------------------------------------------------------------
# The following tests, corruptD-1.1.*, focus on the page header field
# containing the offset of the first free block in a page. 
#







|










|







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
  }
  execsql {
    DELETE FROM t1 WHERE a = 10;
    DELETE FROM t1 WHERE a = 20;
    DELETE FROM t1 WHERE a = 30;
    DELETE FROM t1 WHERE a = 40;
  }
  forcecopy test.db test.bu
} {}

proc incr_change_counter {} {
  hexio_write test.db 24 [
    hexio_render_int32 [expr [hexio_get_int [hexio_read test.db 24 4]] + 1]
  ]
}

proc restore_file {} {
  db close
  forcecopy test.bu test.db
  sqlite3 db test.db
}

#-------------------------------------------------------------------------
# The following tests, corruptD-1.1.*, focus on the page header field
# containing the offset of the first free block in a page. 
#

Changes to test/corruptE.test.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.  It specifcally
# focuses on rowid order corruption.
#
# $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $

catch {file delete -force test.db test.db-journal test.bu}

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

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.  It specifcally
# focuses on rowid order corruption.
#
# $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $

catch {forcedelete test.db test.db-journal test.bu}

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

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
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
  }
} {}

ifcapable {integrityck} {
  integrity_check corruptE-1.2
}

# Copy file $from into $to
#
proc copy_file {from to} {
  file copy -force $from $to
}

# Setup for the tests.  Make a backup copy of the good database in test.bu.
#
db close
copy_file test.db test.bu
sqlite3 db test.db
set fsize [file size test.db]


do_test corruptE-2.1 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 2041 [format %02x 0x2e]

  sqlite3 db test.db

  set res [ catchsql {PRAGMA integrity_check} ]
  set ans [lindex $res 1]

  list [regexp {out of order.*previous was} $ans] \
       [regexp {out of order.*max larger than parent max} $ans]
} {1 1}

do_test corruptE-2.2 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 2047 [format %02x 0x84]

  sqlite3 db test.db

  set res [ catchsql {PRAGMA integrity_check} ]
  set ans [lindex $res 1]

  list [regexp {out of order.*previous was} $ans] \
       [regexp {out of order.*min less than parent min} $ans]
} {1 1}

do_test corruptE-2.3 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 7420 [format %02x 0xa8]
  hexio_write test.db 10459 [format %02x 0x8d]

  sqlite3 db test.db

  set res [ catchsql {PRAGMA integrity_check} ]
  set ans [lindex $res 1]

  list [regexp {out of order.*max larger than parent min} $ans]
} {1}

do_test corruptE-2.4 {
  db close
  copy_file test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 10233 [format %02x 0xd0]

  sqlite3 db test.db

  set res [ catchsql {PRAGMA integrity_check} ]







<
<
<
<
<
<



|






|















|















|















|







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
  }
} {}

ifcapable {integrityck} {
  integrity_check corruptE-1.2
}







# Setup for the tests.  Make a backup copy of the good database in test.bu.
#
db close
forcecopy test.db test.bu
sqlite3 db test.db
set fsize [file size test.db]


do_test corruptE-2.1 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 2041 [format %02x 0x2e]

  sqlite3 db test.db

  set res [ catchsql {PRAGMA integrity_check} ]
  set ans [lindex $res 1]

  list [regexp {out of order.*previous was} $ans] \
       [regexp {out of order.*max larger than parent max} $ans]
} {1 1}

do_test corruptE-2.2 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 2047 [format %02x 0x84]

  sqlite3 db test.db

  set res [ catchsql {PRAGMA integrity_check} ]
  set ans [lindex $res 1]

  list [regexp {out of order.*previous was} $ans] \
       [regexp {out of order.*min less than parent min} $ans]
} {1 1}

do_test corruptE-2.3 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 7420 [format %02x 0xa8]
  hexio_write test.db 10459 [format %02x 0x8d]

  sqlite3 db test.db

  set res [ catchsql {PRAGMA integrity_check} ]
  set ans [lindex $res 1]

  list [regexp {out of order.*max larger than parent min} $ans]
} {1}

do_test corruptE-2.4 {
  db close
  forcecopy test.bu test.db

  # insert corrupt byte(s)
  hexio_write test.db 10233 [format %02x 0xd0]

  sqlite3 db test.db

  set res [ catchsql {PRAGMA integrity_check} ]
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
                {12297 0xd7} \
                {13303 0x53} ]

set tc 1
foreach test $tests {
  do_test corruptE-3.$tc {
    db close
    copy_file test.bu test.db

    # insert corrupt byte(s)
    hexio_write test.db [lindex $test 0] [format %02x [lindex $test 1]]

    sqlite3 db test.db

    set res [ catchsql {PRAGMA integrity_check} ]







|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
                {12297 0xd7} \
                {13303 0x53} ]

set tc 1
foreach test $tests {
  do_test corruptE-3.$tc {
    db close
    forcecopy test.bu test.db

    # insert corrupt byte(s)
    hexio_write test.db [lindex $test 0] [format %02x [lindex $test 1]]

    sqlite3 db test.db

    set res [ catchsql {PRAGMA integrity_check} ]

Changes to test/crash.test.

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# crash-4.2.*: Test recovery when crash occurs during sync() of an 
#              attached database journal file.
# crash-4.3.*: Test recovery when crash occurs during sync() of the master
#              journal file. 
#
ifcapable attach {
  do_test crash-4.0 {
    file delete -force test2.db
    file delete -force test2.db-journal
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA aux.default_cache_size = 10;
      CREATE TABLE aux.abc2 AS SELECT 2*a as a, 2*b as b, 2*c as c FROM abc;
    }
    expr ([file size test2.db] / 1024) > 450
  } {1}







|
|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# crash-4.2.*: Test recovery when crash occurs during sync() of an 
#              attached database journal file.
# crash-4.3.*: Test recovery when crash occurs during sync() of the master
#              journal file. 
#
ifcapable attach {
  do_test crash-4.0 {
    forcedelete test2.db
    forcedelete test2.db-journal
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA aux.default_cache_size = 10;
      CREATE TABLE aux.abc2 AS SELECT 2*a as a, 2*b as b, 2*c as c FROM abc;
    }
    expr ([file size test2.db] / 1024) > 450
  } {1}
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
#--------------------------------------------------------------------------
# The following test cases - crash-5.* - exposes a bug that existed in the
# sqlite3pager_movepage() API used by auto-vacuum databases.
# database when a crash occurs during a multi-file transaction. See comments
# in test crash-5.3 for details.
#
db close
file delete -force test.db
sqlite3 db test.db
do_test crash-5.1 {
  execsql {
    CREATE TABLE abc(a, b, c);                          -- Root page 3
    INSERT INTO abc VALUES(randstr(1500,1500), 0, 0);   -- Overflow page 4
    INSERT INTO abc SELECT * FROM abc;
    INSERT INTO abc SELECT * FROM abc;







|







314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
#--------------------------------------------------------------------------
# The following test cases - crash-5.* - exposes a bug that existed in the
# sqlite3pager_movepage() API used by auto-vacuum databases.
# database when a crash occurs during a multi-file transaction. See comments
# in test crash-5.3 for details.
#
db close
forcedelete test.db
sqlite3 db test.db
do_test crash-5.1 {
  execsql {
    CREATE TABLE abc(a, b, c);                          -- Root page 3
    INSERT INTO abc VALUES(randstr(1500,1500), 0, 0);   -- Overflow page 4
    INSERT INTO abc SELECT * FROM abc;
    INSERT INTO abc SELECT * FROM abc;

Changes to test/crash3.test.

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  {UPDATE abc SET a = 2}                               {2 2 3}       \
  {INSERT INTO abc VALUES(4, 5, randstr(1000,1000))}   {n/a} \
  {CREATE TABLE def(d, e, f)}                          {n/a} \
] {
  for {set ii 0} {$ii < 10} {incr ii} {

    db close
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    do_test crash3-1.$tn.1 {
      execsql {
        PRAGMA page_size = 1024;
        BEGIN;
        CREATE TABLE abc(a, b, c);
        INSERT INTO abc VALUES(1, 2, 3);







|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  {UPDATE abc SET a = 2}                               {2 2 3}       \
  {INSERT INTO abc VALUES(4, 5, randstr(1000,1000))}   {n/a} \
  {CREATE TABLE def(d, e, f)}                          {n/a} \
] {
  for {set ii 0} {$ii < 10} {incr ii} {

    db close
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    do_test crash3-1.$tn.1 {
      execsql {
        PRAGMA page_size = 1024;
        BEGIN;
        CREATE TABLE abc(a, b, c);
        INSERT INTO abc VALUES(1, 2, 3);
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
    incr tn
  }
}

# This block tests both the IOCAP_SEQUENTIAL and IOCAP_SAFE_APPEND flags.
#
db close
file delete -force test.db test.db-journal
sqlite3 db test.db
do_test crash3-2.0 {
  execsql {
    BEGIN;
    CREATE TABLE abc(a PRIMARY KEY, b, c);
    CREATE TABLE def(d PRIMARY KEY, e, f);
    PRAGMA default_cache_size = 10;







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
    incr tn
  }
}

# This block tests both the IOCAP_SEQUENTIAL and IOCAP_SAFE_APPEND flags.
#
db close
forcedelete test.db test.db-journal
sqlite3 db test.db
do_test crash3-2.0 {
  execsql {
    BEGIN;
    CREATE TABLE abc(a PRIMARY KEY, b, c);
    CREATE TABLE def(d PRIMARY KEY, e, f);
    PRAGMA default_cache_size = 10;
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# IOCAP_SEQUENTIAL. At one point, if both flags were set, small
# journal files that contained only a single page, but were required 
# for some other reason (i.e. nTrunk) were not being written to
# disk.
#
for {set ii 0} {$ii < 10} {incr ii} {
  db close
  file delete -force test.db test.db-journal
  crashsql -file test.db -char {sequential atomic} {
    CREATE TABLE abc(a, b, c);
  }
  sqlite3 db test.db
  do_test crash3-3.$ii {
    execsql {PRAGMA integrity_check}
  } {ok}
}

finish_test







|










173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# IOCAP_SEQUENTIAL. At one point, if both flags were set, small
# journal files that contained only a single page, but were required 
# for some other reason (i.e. nTrunk) were not being written to
# disk.
#
for {set ii 0} {$ii < 10} {incr ii} {
  db close
  forcedelete test.db test.db-journal
  crashsql -file test.db -char {sequential atomic} {
    CREATE TABLE abc(a, b, c);
  }
  sqlite3 db test.db
  do_test crash3-3.$ii {
    execsql {PRAGMA integrity_check}
  } {ok}
}

finish_test

Changes to test/crash4.test.

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#
# Slowly increase the delay before the crash, repeating the test
# over and over.  Stop testing when the entire sequence of SQL
# statements runs to completing without hitting the crash.
#
for {set cnt 1; set fin 0} {!$fin} {incr cnt} {
  db close
  file delete -force test.db test.db-journal
  do_test crash4-1.$cnt.1 {
    set seed [expr {int(abs(rand()*10000))}]
    set delay [expr {int($cnt/50)+1}]
    set file [expr {($cnt&1)?"test.db":"test.db-journal"}]
    set c [crashsql -delay $delay -file $file -seed $seed -tclbody {
      db eval {CREATE TABLE a(id INTEGER, name CHAR(50))}
      db eval {INSERT INTO a(id,name) VALUES(1,'one')}







|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#
# Slowly increase the delay before the crash, repeating the test
# over and over.  Stop testing when the entire sequence of SQL
# statements runs to completing without hitting the crash.
#
for {set cnt 1; set fin 0} {!$fin} {incr cnt} {
  db close
  forcedelete test.db test.db-journal
  do_test crash4-1.$cnt.1 {
    set seed [expr {int(abs(rand()*10000))}]
    set delay [expr {int($cnt/50)+1}]
    set file [expr {($cnt&1)?"test.db":"test.db-journal"}]
    set c [crashsql -delay $delay -file $file -seed $seed -tclbody {
      db eval {CREATE TABLE a(id INTEGER, name CHAR(50))}
      db eval {INSERT INTO a(id,name) VALUES(1,'one')}

Changes to test/crash5.test.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

for {set ii 0} {$ii < 10} {incr ii} {
  for {set jj 50} {$jj < 100} {incr jj} {

    # Set up the database so that it is an auto-vacuum database 
    # containing a single table (root page 3) with a single row. 
    # The row has an overflow page (page 4).
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    set c [string repeat 3 1500]
    db eval {
      pragma auto_vacuum = 1;
      CREATE TABLE t1(a, b, c);
      INSERT INTO t1 VALUES('1111111111', '2222222222', $c);
    }







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

for {set ii 0} {$ii < 10} {incr ii} {
  for {set jj 50} {$jj < 100} {incr jj} {

    # Set up the database so that it is an auto-vacuum database 
    # containing a single table (root page 3) with a single row. 
    # The row has an overflow page (page 4).
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    set c [string repeat 3 1500]
    db eval {
      pragma auto_vacuum = 1;
      CREATE TABLE t1(a, b, c);
      INSERT INTO t1 VALUES('1111111111', '2222222222', $c);
    }

Changes to test/crash6.test.

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
ifcapable !crashtest {
  finish_test
  return
}

for {set ii 0} {$ii < 10} {incr ii} {
  catch {db close}
  file delete -force test.db test.db-journal
  crashsql -delay 2 -file test.db {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size=4096;
    BEGIN;
    CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c;
    COMMIT;
    BEGIN;
    CREATE TABLE def AS SELECT 1 AS d, 2 AS e, 3 AS f;
    COMMIT;
  }
  sqlite3 db test.db
  integrity_check crash6-1.$ii
}

for {set ii 0} {$ii < 10} {incr ii} {
  catch {db close}
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size=2048;
    BEGIN;
    CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c;
    COMMIT;







|
















|







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
ifcapable !crashtest {
  finish_test
  return
}

for {set ii 0} {$ii < 10} {incr ii} {
  catch {db close}
  forcedelete test.db test.db-journal
  crashsql -delay 2 -file test.db {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size=4096;
    BEGIN;
    CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c;
    COMMIT;
    BEGIN;
    CREATE TABLE def AS SELECT 1 AS d, 2 AS e, 3 AS f;
    COMMIT;
  }
  sqlite3 db test.db
  integrity_check crash6-1.$ii
}

for {set ii 0} {$ii < 10} {incr ii} {
  catch {db close}
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size=2048;
    BEGIN;
    CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c;
    COMMIT;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
}

# Test case for crashing during database sync with page-size values 
# from 1024 to 8192.
#
for {set ii 0} {$ii < 30} {incr ii} {
  db close
  file delete -force test.db
  sqlite3 db test.db

  set pagesize [expr 1024 << ($ii % 4)]
  if {$pagesize>$::SQLITE_MAX_PAGE_SIZE} {
    set pagesize $::SQLITE_MAX_PAGE_SIZE
  }
  do_test crash6-3.$ii.0 {







|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
}

# Test case for crashing during database sync with page-size values 
# from 1024 to 8192.
#
for {set ii 0} {$ii < 30} {incr ii} {
  db close
  forcedelete test.db
  sqlite3 db test.db

  set pagesize [expr 1024 << ($ii % 4)]
  if {$pagesize>$::SQLITE_MAX_PAGE_SIZE} {
    set pagesize $::SQLITE_MAX_PAGE_SIZE
  }
  do_test crash6-3.$ii.0 {

Changes to test/crash7.test.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
proc signature {} {
  return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc}]
}

foreach f [list test.db test.db-journal] {
  for {set ii 1} {$ii < 64} {incr ii} {
    db close
    file delete test.db
    sqlite3 db test.db
  
    set from_size [expr 1024 << ($ii&3)]
    set to_size   [expr 1024 << (($ii>>2)&3)]
  
    execsql "
      PRAGMA page_size = $from_size;







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
proc signature {} {
  return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc}]
}

foreach f [list test.db test.db-journal] {
  for {set ii 1} {$ii < 64} {incr ii} {
    db close
    delete_file test.db
    sqlite3 db test.db
  
    set from_size [expr 1024 << ($ii&3)]
    set to_size   [expr 1024 << (($ii>>2)&3)]
  
    execsql "
      PRAGMA page_size = $from_size;

Changes to test/crash8.test.

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#
# This block of tests test that SQLite correctly truncates such
# journal files, and that the results behave correctly if a hot-journal
# rollback occurs.
#
ifcapable pragma {
  reset_db
  file delete -force test2.db

  do_test crash8-4.1 {
    execsql {
      PRAGMA journal_mode = persist;
      CREATE TABLE ab(a, b);
      INSERT INTO ab VALUES(0, 'abc');
      INSERT INTO ab VALUES(1, NULL);







|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#
# This block of tests test that SQLite correctly truncates such
# journal files, and that the results behave correctly if a hot-journal
# rollback occurs.
#
ifcapable pragma {
  reset_db
  forcedelete test2.db

  do_test crash8-4.1 {
    execsql {
      PRAGMA journal_mode = persist;
      CREATE TABLE ab(a, b);
      INSERT INTO ab VALUES(0, 'abc');
      INSERT INTO ab VALUES(1, NULL);
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  } {1}

  do_test crash8-4.9 {
    execsql { SELECT b FROM aux.ab WHERE a = 0 }
  } {def}

  do_test crash8-4.10 {
    file delete $zMasterJournal
    execsql { SELECT b FROM main.ab WHERE a = 0 }
  } {jkl}
}

for {set i 1} {$i < 10} {incr i} {
  catch { db close }
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  do_test crash8-5.$i.1 {
    execsql {
      CREATE TABLE t1(x PRIMARY KEY);
      INSERT INTO t1 VALUES(randomblob(900));
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;







|






|







332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  } {1}

  do_test crash8-4.9 {
    execsql { SELECT b FROM aux.ab WHERE a = 0 }
  } {def}

  do_test crash8-4.10 {
    delete_file $zMasterJournal
    execsql { SELECT b FROM main.ab WHERE a = 0 }
  } {jkl}
}

for {set i 1} {$i < 10} {incr i} {
  catch { db close }
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  do_test crash8-5.$i.1 {
    execsql {
      CREATE TABLE t1(x PRIMARY KEY);
      INSERT INTO t1 VALUES(randomblob(900));
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
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
      ROLLBACK;
      INSERT INTO t1 VALUES(randomblob(900));
    }
    execsql { PRAGMA integrity_check }
  } {ok}
  
  catch { db close }
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  do_test crash8-5.$i.2 {
    execsql {
      PRAGMA cache_size = 10;
      CREATE TABLE t1(x PRIMARY KEY);
      INSERT INTO t1 VALUES(randomblob(900));
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;          /* 64 rows */
      BEGIN;
        UPDATE t1 SET x = randomblob(900);
    }
    file delete -force testX.db testX.db-journal testX.db-wal
    copy_file test.db testX.db
    copy_file test.db-journal testX.db-journal
    db close

    crashsql -file test.db -delay [expr ($::i%2) + 1] {
      SELECT * FROM sqlite_master;
      INSERT INTO t1 VALUES(randomblob(900));
    }








|















|
|
|







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
      ROLLBACK;
      INSERT INTO t1 VALUES(randomblob(900));
    }
    execsql { PRAGMA integrity_check }
  } {ok}
  
  catch { db close }
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  do_test crash8-5.$i.2 {
    execsql {
      PRAGMA cache_size = 10;
      CREATE TABLE t1(x PRIMARY KEY);
      INSERT INTO t1 VALUES(randomblob(900));
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;
      INSERT INTO t1 SELECT randomblob(900) FROM t1;          /* 64 rows */
      BEGIN;
        UPDATE t1 SET x = randomblob(900);
    }
    forcedelete testX.db testX.db-journal testX.db-wal
    forcecopy test.db testX.db
    forcecopy test.db-journal testX.db-journal
    db close

    crashsql -file test.db -delay [expr ($::i%2) + 1] {
      SELECT * FROM sqlite_master;
      INSERT INTO t1 VALUES(randomblob(900));
    }

Changes to test/createtab.test.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  set upperBound 0
}

# Run these tests for all possible values of autovacuum.
#
for {set av 0} {$av<=$upperBound} {incr av} {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db

  # Create a table that spans multiple pages.  It is important
  # that part of the database be in pages beyond the root page.
  #
  do_test createtab-$av.1 {
    execsql "PRAGMA auto_vacuum=$av"







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  set upperBound 0
}

# Run these tests for all possible values of autovacuum.
#
for {set av 0} {$av<=$upperBound} {incr av} {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db

  # Create a table that spans multiple pages.  It is important
  # that part of the database be in pages beyond the root page.
  #
  do_test createtab-$av.1 {
    execsql "PRAGMA auto_vacuum=$av"

Changes to test/dbstatus.test.

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
      CREATE VIRTUAL TABLE t2 USING echo(t1);
    }
  } {
    set tn "$::lookaside_buffer_size-$tn"
  
    # Step 1.
    db close
    file delete -force test.db
    sqlite3 db test.db
    sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
    db cache size 0

    catch { register_echo_module db }
    ifcapable !vtab { if {[string match *x $tn]} continue }
  







|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
      CREATE VIRTUAL TABLE t2 USING echo(t1);
    }
  } {
    set tn "$::lookaside_buffer_size-$tn"
  
    # Step 1.
    db close
    forcedelete test.db
    sqlite3 db test.db
    sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
    db cache size 0

    catch { register_echo_module db }
    ifcapable !vtab { if {[string match *x $tn]} continue }
  
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
      SELECT * FROM t2 WHERE b='abcdefg';
    }
  } {
    set tn "$::lookaside_buffer_size-$tn"

    # Step 1.
    db close
    file delete -force test.db
    sqlite3 db test.db
    sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
    db cache size 1000

    catch { register_echo_module db }
    ifcapable !vtab { if {[string match *x $tn]} continue }
  







|







283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
      SELECT * FROM t2 WHERE b='abcdefg';
    }
  } {
    set tn "$::lookaside_buffer_size-$tn"

    # Step 1.
    db close
    forcedelete test.db
    sqlite3 db test.db
    sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
    db cache size 1000

    catch { register_echo_module db }
    ifcapable !vtab { if {[string match *x $tn]} continue }
  

Changes to test/delete.test.

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  execsql {
    PRAGMA count_changes=OFF;
    INSERT INTO t3 VALUES(123);
    SELECT * FROM t3;
  }
} {123}
db close
catch {file delete -force test.db-journal}
catch {file attributes test.db -permissions 0444}
catch {file attributes test.db -readonly 1}
sqlite3 db test.db
set ::DB [sqlite3_connection_pointer db]
do_test delete-8.1 {
  catchsql {
    DELETE FROM t3;







|







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  execsql {
    PRAGMA count_changes=OFF;
    INSERT INTO t3 VALUES(123);
    SELECT * FROM t3;
  }
} {123}
db close
catch {forcedelete test.db-journal}
catch {file attributes test.db -permissions 0444}
catch {file attributes test.db -readonly 1}
sqlite3 db test.db
set ::DB [sqlite3_connection_pointer db]
do_test delete-8.1 {
  catchsql {
    DELETE FROM t3;
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
} {1 {attempt to write a readonly database}}
do_test delete-8.6 {
  execsql {SELECT * FROM t3}
} {123}
integrity_check delete-8.7

# Need to do the following for tcl 8.5 on mac. On that configuration, the
# -readonly flag is taken so seriously that a subsequent [file delete -force]
# (required before the next test file can be executed) will fail.
#
catch {file attributes test.db -readonly 0}
db close
file delete -force test.db test.db-journal

# The following tests verify that SQLite correctly handles the case
# where an index B-Tree is being scanned, the rowid column being read
# from each index entry and another statement deletes some rows from
# the index B-Tree. At one point this (obscure) scenario was causing 
# SQLite to return spurious SQLITE_CORRUPT errors and arguably incorrect
# query results. 







|




|







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
} {1 {attempt to write a readonly database}}
do_test delete-8.6 {
  execsql {SELECT * FROM t3}
} {123}
integrity_check delete-8.7

# Need to do the following for tcl 8.5 on mac. On that configuration, the
# -readonly flag is taken so seriously that a subsequent [forcedelete]
# (required before the next test file can be executed) will fail.
#
catch {file attributes test.db -readonly 0}
db close
forcedelete test.db test.db-journal

# The following tests verify that SQLite correctly handles the case
# where an index B-Tree is being scanned, the rowid column being read
# from each index entry and another statement deletes some rows from
# the index B-Tree. At one point this (obscure) scenario was causing 
# SQLite to return spurious SQLITE_CORRUPT errors and arguably incorrect
# query results. 

Changes to test/descidx1.test.

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

# Test the legacy_file_format pragma here because we have access to
# the get_file_format command.
#
ifcapable legacyformat {
  do_test descidx1-6.1 {
    db close
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    execsql {PRAGMA legacy_file_format}
  } {1}
} else {
  do_test descidx1-6.1 {
    db close
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    execsql {PRAGMA legacy_file_format}
  } {0}
}
do_test descidx1-6.2 {
  execsql {PRAGMA legacy_file_format=YES}
  execsql {PRAGMA legacy_file_format}







|






|







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

# Test the legacy_file_format pragma here because we have access to
# the get_file_format command.
#
ifcapable legacyformat {
  do_test descidx1-6.1 {
    db close
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    execsql {PRAGMA legacy_file_format}
  } {1}
} else {
  do_test descidx1-6.1 {
    db close
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    execsql {PRAGMA legacy_file_format}
  } {0}
}
do_test descidx1-6.2 {
  execsql {PRAGMA legacy_file_format=YES}
  execsql {PRAGMA legacy_file_format}
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  do_test descidx1-6.3.1 {
    execsql {VACUUM}
    get_file_format
  } {1}
}
do_test descidx1-6.4 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql {PRAGMA legacy_file_format=NO}
  execsql {PRAGMA legacy_file_format}
} {0}
do_test descidx1-6.5 {
  execsql {
    CREATE TABLE t1(a,b,c);







|







324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  do_test descidx1-6.3.1 {
    execsql {VACUUM}
    get_file_format
  } {1}
}
do_test descidx1-6.4 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  execsql {PRAGMA legacy_file_format=NO}
  execsql {PRAGMA legacy_file_format}
} {0}
do_test descidx1-6.5 {
  execsql {
    CREATE TABLE t1(a,b,c);

Changes to test/diskfull.test.

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    integrity_check ${prefix}.$::i.2
  }
}

do_diskfull_test diskfull-2 VACUUM

# db close
# file delete -force test.db
# file delete -force test.db-journal
# sqlite3 db test.db
# 
# do_test diskfull-3.1 {
#   execsql {
#     PRAGMA default_cache_size = 10;
#     CREATE TABLE t3(a, b, UNIQUE(a, b));
#     INSERT INTO t3 VALUES( randstr(100, 100), randstr(100, 100) );







|
|







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    integrity_check ${prefix}.$::i.2
  }
}

do_diskfull_test diskfull-2 VACUUM

# db close
# forcedelete test.db
# forcedelete test.db-journal
# sqlite3 db test.db
# 
# do_test diskfull-3.1 {
#   execsql {
#     PRAGMA default_cache_size = 10;
#     CREATE TABLE t3(a, b, UNIQUE(a, b));
#     INSERT INTO t3 VALUES( randstr(100, 100), randstr(100, 100) );

Changes to test/e_expr.test.

653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
do_execsql_test e_expr-12.2.6 {SELECT CURRENT_TIME}      {00:00:01}
do_execsql_test e_expr-12.2.7 {SELECT CURRENT_DATE}      {1970-01-01}
do_execsql_test e_expr-12.2.8 {SELECT CURRENT_TIMESTAMP} {{1970-01-01 00:00:01}}
set sqlite_current_time 0

# EVIDENCE-OF: R-57598-59332 -- syntax diagram expr
#
file delete -force test.db2
execsql {
  ATTACH 'test.db2' AS dbname;
  CREATE TABLE dbname.tblname(cname);
}

proc glob {args} {return 1}
db function glob glob







|







653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
do_execsql_test e_expr-12.2.6 {SELECT CURRENT_TIME}      {00:00:01}
do_execsql_test e_expr-12.2.7 {SELECT CURRENT_DATE}      {1970-01-01}
do_execsql_test e_expr-12.2.8 {SELECT CURRENT_TIMESTAMP} {{1970-01-01 00:00:01}}
set sqlite_current_time 0

# EVIDENCE-OF: R-57598-59332 -- syntax diagram expr
#
forcedelete test.db2
execsql {
  ATTACH 'test.db2' AS dbname;
  CREATE TABLE dbname.tblname(cname);
}

proc glob {args} {return 1}
db function glob glob
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
db3 close
}

#-------------------------------------------------------------------------
# Test statements related to the EXISTS and NOT EXISTS operators.
#
catch { db close }
file delete -force test.db
sqlite3 db test.db

do_execsql_test e_expr-34.1 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(NULL, 2);
  INSERT INTO t1 VALUES(1, NULL);







|







1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
db3 close
}

#-------------------------------------------------------------------------
# Test statements related to the EXISTS and NOT EXISTS operators.
#
catch { db close }
forcedelete test.db
sqlite3 db test.db

do_execsql_test e_expr-34.1 {
  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(NULL, 2);
  INSERT INTO t1 VALUES(1, NULL);
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
}

#-------------------------------------------------------------------------
# Test statements related to scalar sub-queries.
#

catch { db close }
file delete -force test.db
sqlite3 db test.db
do_test e_expr-35.0 {
  execsql {
    CREATE TABLE t2(a, b);
    INSERT INTO t2 VALUES('one', 'two');
    INSERT INTO t2 VALUES('three', NULL);
    INSERT INTO t2 VALUES(4, 5.0);







|







1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
}

#-------------------------------------------------------------------------
# Test statements related to scalar sub-queries.
#

catch { db close }
forcedelete test.db
sqlite3 db test.db
do_test e_expr-35.0 {
  execsql {
    CREATE TABLE t2(a, b);
    INSERT INTO t2 VALUES('one', 'two');
    INSERT INTO t2 VALUES('three', NULL);
    INSERT INTO t2 VALUES(4, 5.0);

Changes to test/e_fts3.test.

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

#if {$DO_MALLOC_TEST} break

# Reset the database and database connection. If this iteration of the 
# [foreach] loop is testing with OOM errors, disable the lookaside buffer.
#
db close
file delete -force test.db test.db-journal
sqlite3 db test.db
if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }
db eval "PRAGMA encoding = '$enc'"

proc mit {blob} {
  set scan(littleEndian) i*
  set scan(bigEndian) I*







|







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

#if {$DO_MALLOC_TEST} break

# Reset the database and database connection. If this iteration of the 
# [foreach] loop is testing with OOM errors, disable the lookaside buffer.
#
db close
forcedelete test.db test.db-journal
sqlite3 db test.db
if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }
db eval "PRAGMA encoding = '$enc'"

proc mit {blob} {
  set scan(littleEndian) i*
  set scan(bigEndian) I*
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647

#-------------------------------------------------------------------------
# Test that FTS3 tables can be renamed using the ALTER RENAME command.
# OOM errors are tested during ALTER RENAME commands also.
#
foreach DO_MALLOC_TEST {0 1 2} {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }

  ddl_test   9.1.1             { CREATE VIRTUAL TABLE t10 USING fts3(x) }
  write_test 9.1.2 t10_content { INSERT INTO t10 VALUES('fts3 tables') }
  write_test 9.1.3 t10_content { INSERT INTO t10 VALUES('are renameable') }








|







633
634
635
636
637
638
639
640
641
642
643
644
645
646
647

#-------------------------------------------------------------------------
# Test that FTS3 tables can be renamed using the ALTER RENAME command.
# OOM errors are tested during ALTER RENAME commands also.
#
foreach DO_MALLOC_TEST {0 1 2} {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }

  ddl_test   9.1.1             { CREATE VIRTUAL TABLE t10 USING fts3(x) }
  write_test 9.1.2 t10_content { INSERT INTO t10 VALUES('fts3 tables') }
  write_test 9.1.3 t10_content { INSERT INTO t10 VALUES('are renameable') }

Changes to test/enc2.test.

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

# The three unicode encodings understood by SQLite.
set encodings [list UTF-8 UTF-16le UTF-16be]

set sqlite_os_trace 0
set i 1
foreach enc $encodings {
  file delete -force test.db
  sqlite3 db test.db
  db eval "PRAGMA encoding = \"$enc\""
  execsql $dbcontents
  do_test enc2-$i.0.1 {
    db eval {PRAGMA encoding}
  } $enc
  do_test enc2-$i.0.2 {







|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

# The three unicode encodings understood by SQLite.
set encodings [list UTF-8 UTF-16le UTF-16be]

set sqlite_os_trace 0
set i 1
foreach enc $encodings {
  forcedelete test.db
  sqlite3 db test.db
  db eval "PRAGMA encoding = \"$enc\""
  execsql $dbcontents
  do_test enc2-$i.0.1 {
    db eval {PRAGMA encoding}
  } $enc
  do_test enc2-$i.0.2 {
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  incr i
}

# Test that it is an error to try to attach a database with a different
# encoding to the main database.
ifcapable attach {
  do_test enc2-4.1 {
    file delete -force test.db
    sqlite3 db test.db
    db eval "PRAGMA encoding = 'UTF-8'"
    db eval "CREATE TABLE abc(a, b, c);"
  } {}
  do_test enc2-4.2 {
    file delete -force test2.db
    sqlite3 db2 test2.db
    db2 eval "PRAGMA encoding = 'UTF-16'"
    db2 eval "CREATE TABLE abc(a, b, c);"
  } {}
  do_test enc2-4.3 {
    catchsql {
      ATTACH 'test2.db' as aux;







|





|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  incr i
}

# Test that it is an error to try to attach a database with a different
# encoding to the main database.
ifcapable attach {
  do_test enc2-4.1 {
    forcedelete test.db
    sqlite3 db test.db
    db eval "PRAGMA encoding = 'UTF-8'"
    db eval "CREATE TABLE abc(a, b, c);"
  } {}
  do_test enc2-4.2 {
    forcedelete test2.db
    sqlite3 db2 test2.db
    db2 eval "PRAGMA encoding = 'UTF-16'"
    db2 eval "CREATE TABLE abc(a, b, c);"
  } {}
  do_test enc2-4.3 {
    catchsql {
      ATTACH 'test2.db' as aux;
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
  set l [lsearch -exact $::values $lhs]
  set r [lsearch -exact $::values $rhs]
  set res [expr $l - $r]
  # puts "enc=$enc lhs=$lhs/$l rhs=$rhs/$r res=$res"
  return $res
}

file delete -force test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
do_test enc2-5.0 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
    INSERT INTO t5 VALUES('two');
    INSERT INTO t5 VALUES('five');







|







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
  set l [lsearch -exact $::values $lhs]
  set r [lsearch -exact $::values $rhs]
  set res [expr $l - $r]
  # puts "enc=$enc lhs=$lhs/$l rhs=$rhs/$r res=$res"
  return $res
}

forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
do_test enc2-5.0 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
    INSERT INTO t5 VALUES('two');
    INSERT INTO t5 VALUES('five');
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
do_test enc2-5.3 {
  add_test_collate $DB 0 0 1
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-16BE}

db close
file delete -force test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16LE'}
do_test enc2-5.4 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
    INSERT INTO t5 VALUES('two');







|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
do_test enc2-5.3 {
  add_test_collate $DB 0 0 1
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-16BE}

db close
forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16LE'}
do_test enc2-5.4 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
    INSERT INTO t5 VALUES('two');
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
do_test enc2-5.7 {
  add_test_collate $DB 1 0 0
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-8}

db close
file delete -force test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16BE'}
do_test enc2-5.8 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
    INSERT INTO t5 VALUES('two');







|







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
do_test enc2-5.7 {
  add_test_collate $DB 1 0 0
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-8}

db close
forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16BE'}
do_test enc2-5.8 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
    INSERT INTO t5 VALUES('two');
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  lappend res $::test_collate_enc
} {one two three four five UTF-16BE}
do_test enc2-5.14 {
  set ::sqlite_last_needed_collation
} test_collate

db close
file delete -force test.db

do_test enc2-5.15 {
  sqlite3 db test.db; set ::DB [sqlite3_connection_pointer db]
  add_test_collate_needed $::DB
  set ::sqlite_last_needed_collation
} {}
do_test enc2-5.16 {







|







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  lappend res $::test_collate_enc
} {one two three four five UTF-16BE}
do_test enc2-5.14 {
  set ::sqlite_last_needed_collation
} test_collate

db close
forcedelete test.db

do_test enc2-5.15 {
  sqlite3 db test.db; set ::DB [sqlite3_connection_pointer db]
  add_test_collate_needed $::DB
  set ::sqlite_last_needed_collation
} {}
do_test enc2-5.16 {
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# user function when more than one is available.

proc test_function {enc arg} {
  return "$enc $arg"
}

db close
file delete -force test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-8'}
do_test enc2-6.0 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
  }







|







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# user function when more than one is available.

proc test_function {enc arg} {
  return "$enc $arg"
}

db close
forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-8'}
do_test enc2-6.0 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
  }
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

db close
file delete -force test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16LE'}
do_test enc2-6.3 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('sqlite');
  }







|







362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

db close
forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16LE'}
do_test enc2-6.3 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('sqlite');
  }
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

db close
file delete -force test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16BE'}
do_test enc2-6.7 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('sqlite');
  }







|







395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

db close
forcedelete test.db
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
execsql {pragma encoding = 'UTF-16BE'}
do_test enc2-6.7 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('sqlite');
  }
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}


db close
file delete -force test.db

# The following tests - enc2-7.* - function as follows:
#
# 1: Open an empty database file assuming UTF-16 encoding.
# 2: Open the same database with a different handle assuming UTF-8. Create
#    a table using this handle.
# 3: Read the sqlite_master table from the first handle. 







|







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}


db close
forcedelete test.db

# The following tests - enc2-7.* - function as follows:
#
# 1: Open an empty database file assuming UTF-16 encoding.
# 2: Open the same database with a different handle assuming UTF-8. Create
#    a table using this handle.
# 3: Read the sqlite_master table from the first handle. 
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
  do_test enc2-8.2 {
    sqlite3_complete16 [utf16 "SELECT * FROM"]
  } {0}
}

# Test that the encoding of an empty database may still be set after the
# (empty) schema has been initialized.
file delete -force test.db
do_test enc2-9.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA encoding = 'UTF-8';
    PRAGMA encoding;
  }
} {UTF-8}







|







489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
  do_test enc2-8.2 {
    sqlite3_complete16 [utf16 "SELECT * FROM"]
  } {0}
}

# Test that the encoding of an empty database may still be set after the
# (empty) schema has been initialized.
forcedelete test.db
do_test enc2-9.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA encoding = 'UTF-8';
    PRAGMA encoding;
  }
} {UTF-8}
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
} {UTF-16le}

# Ticket #1987.
# Disallow encoding changes once the encoding has been set.
#
do_test enc2-10.1 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  db eval {
    PRAGMA encoding=UTF16;
    CREATE TABLE t1(a);
    PRAGMA encoding=UTF8;
    CREATE TABLE t2(b);
  }







|







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
} {UTF-16le}

# Ticket #1987.
# Disallow encoding changes once the encoding has been set.
#
do_test enc2-10.1 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  db eval {
    PRAGMA encoding=UTF16;
    CREATE TABLE t1(a);
    PRAGMA encoding=UTF8;
    CREATE TABLE t2(b);
  }

Changes to test/enc3.test.

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
  } {1}
}

# Try to attach a database with a different encoding.
#
ifcapable {utf16 && shared_cache} {
  db close
  file delete -force test8.db test8.db-journal
  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
  sqlite3 dbaux test8.db
  sqlite3 db test.db
  db eval {SELECT 1 FROM sqlite_master LIMIT 1}
  do_test enc3-3.1 {
    dbaux eval {
      PRAGMA encoding='utf8';
      CREATE TABLE t1(x);
      PRAGMA encoding
    }
  } {UTF-8}
  do_test enc3-3.2 {
    catchsql {
      ATTACH 'test.db' AS utf16;
      SELECT 1 FROM utf16.sqlite_master LIMIT 1;
    } dbaux
  } {1 {attached databases must use the same text encoding as main database}}
  dbaux close
  file delete -force test8.db test8.db-journal
  sqlite3_enable_shared_cache $::enable_shared_cache
}

finish_test







|


















|




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
  } {1}
}

# Try to attach a database with a different encoding.
#
ifcapable {utf16 && shared_cache} {
  db close
  forcedelete test8.db test8.db-journal
  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
  sqlite3 dbaux test8.db
  sqlite3 db test.db
  db eval {SELECT 1 FROM sqlite_master LIMIT 1}
  do_test enc3-3.1 {
    dbaux eval {
      PRAGMA encoding='utf8';
      CREATE TABLE t1(x);
      PRAGMA encoding
    }
  } {UTF-8}
  do_test enc3-3.2 {
    catchsql {
      ATTACH 'test.db' AS utf16;
      SELECT 1 FROM utf16.sqlite_master LIMIT 1;
    } dbaux
  } {1 {attached databases must use the same text encoding as main database}}
  dbaux close
  forcedelete test8.db test8.db-journal
  sqlite3_enable_shared_cache $::enable_shared_cache
}

finish_test

Changes to test/enc4.test.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
"100000000000000000000000000000000000000000000000000000000"\
"1.0000000000000000000000000000000000000000000000000000000"\
]

set i 1
foreach enc $encodings {

  file delete -force test.db
  sqlite3 db test.db
  db eval "PRAGMA encoding = \"$enc\""

  do_test enc4-$i.1 {
    db eval {PRAGMA encoding}
  } $enc








|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
"100000000000000000000000000000000000000000000000000000000"\
"1.0000000000000000000000000000000000000000000000000000000"\
]

set i 1
foreach enc $encodings {

  forcedelete test.db
  sqlite3 db test.db
  db eval "PRAGMA encoding = \"$enc\""

  do_test enc4-$i.1 {
    db eval {PRAGMA encoding}
  } $enc

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
    incr j
  }

  db close
  incr i
}

file delete -force test.db
sqlite3 db test.db

do_test enc4-4.1 {
  db eval "select 1+1."
} {2.0}

do_test enc4-4.2.1 {







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
    incr j
  }

  db close
  incr i
}

forcedelete test.db
sqlite3 db test.db

do_test enc4-4.1 {
  db eval "select 1+1."
} {2.0}

do_test enc4-4.2.1 {

Changes to test/exclusive.test.

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

ifcapable {!pager_pragmas} {
  finish_test
  return
}

file delete -force test2.db-journal
file delete -force test2.db
file delete -force test3.db-journal
file delete -force test3.db
file delete -force test4.db-journal
file delete -force test4.db

#----------------------------------------------------------------------
# Test cases exclusive-1.X test the PRAGMA logic.
#
do_test exclusive-1.0 {
  execsql {
    pragma locking_mode;







|
|
|
|
|
|







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

ifcapable {!pager_pragmas} {
  finish_test
  return
}

forcedelete test2.db-journal
forcedelete test2.db
forcedelete test3.db-journal
forcedelete test3.db
forcedelete test4.db-journal
forcedelete test4.db

#----------------------------------------------------------------------
# Test cases exclusive-1.X test the PRAGMA logic.
#
do_test exclusive-1.0 {
  execsql {
    pragma locking_mode;
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  BEGIN;
    INSERT INTO t4 VALUES('Macmillan', 1957);
    INSERT INTO t4 VALUES('Douglas-Home', 1963);
    INSERT INTO t4 VALUES('Wilson', 1964);
}
do_test exclusive-6.2 {
  forcedelete test2.db test2.db-journal
  file copy test.db test2.db
  file copy test.db-journal test2.db-journal
  sqlite3 db test2.db
} {}

do_execsql_test exclusive-6.3 {
  PRAGMA locking_mode = EXCLUSIVE;
  SELECT * FROM t4;
} {exclusive Eden 1955}







|
|







477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  BEGIN;
    INSERT INTO t4 VALUES('Macmillan', 1957);
    INSERT INTO t4 VALUES('Douglas-Home', 1963);
    INSERT INTO t4 VALUES('Wilson', 1964);
}
do_test exclusive-6.2 {
  forcedelete test2.db test2.db-journal
  copy_file test.db test2.db
  copy_file test.db-journal test2.db-journal
  sqlite3 db test2.db
} {}

do_execsql_test exclusive-6.3 {
  PRAGMA locking_mode = EXCLUSIVE;
  SELECT * FROM t4;
} {exclusive Eden 1955}

Changes to test/exclusive2.test.

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# is only incremented by the first change when in exclusive access
# mode. In normal mode, the change-counter is incremented once
# per write-transaction.
#

db close
catch {close $::fd}
file delete -force test.db
file delete -force test.db-journal

do_test exclusive2-3.0 {
  sqlite3 db test.db
  execsql {
    BEGIN;
    CREATE TABLE t1(a UNIQUE);
    INSERT INTO t1 VALUES(randstr(200, 200));







|
|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# is only incremented by the first change when in exclusive access
# mode. In normal mode, the change-counter is incremented once
# per write-transaction.
#

db close
catch {close $::fd}
forcedelete test.db
forcedelete test.db-journal

do_test exclusive2-3.0 {
  sqlite3 db test.db
  execsql {
    BEGIN;
    CREATE TABLE t1(a UNIQUE);
    INSERT INTO t1 VALUES(randstr(200, 200));

Changes to test/fallocate.test.

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
set skipwaltests [expr {
  [permutation]=="journaltest" || [permutation]=="inmemory_journal"
}]
ifcapable !wal { set skipwaltests 1 }

if {!$skipwaltests} {
  db close
  file delete -force test.db
  sqlite3 db test.db
  file_control_chunksize_test db main [expr 32*1024]
  
  do_test fallocate-2.1 {
    execsql {
      PRAGMA page_size = 1024;
      PRAGMA journal_mode = WAL;







|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
set skipwaltests [expr {
  [permutation]=="journaltest" || [permutation]=="inmemory_journal"
}]
ifcapable !wal { set skipwaltests 1 }

if {!$skipwaltests} {
  db close
  forcedelete test.db
  sqlite3 db test.db
  file_control_chunksize_test db main [expr 32*1024]
  
  do_test fallocate-2.1 {
    execsql {
      PRAGMA page_size = 1024;
      PRAGMA journal_mode = WAL;

Changes to test/filectrl.test.

33
34
35
36
37
38
39
40
41
} {}
do_test filectrl-1.5 {
  db close
  sqlite3 db test_control_lockproxy.db
  file_control_lockproxy_test db [pwd]
} {}
db close
file delete -force .test_control_lockproxy.db-conch test.proxy
finish_test







|

33
34
35
36
37
38
39
40
41
} {}
do_test filectrl-1.5 {
  db close
  sqlite3 db test_control_lockproxy.db
  file_control_lockproxy_test db [pwd]
} {}
db close
forcedelete .test_control_lockproxy.db-conch test.proxy
finish_test

Changes to test/filefmt.test.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec

db close
file delete -force test.db test.db-journal

# Database begins with valid 16-byte header string.
#
do_test filefmt-1.1 {
  sqlite3 db test.db
  db eval {CREATE TABLE t1(x)}
  db close







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
do_not_use_codec

db close
forcedelete test.db test.db-journal

# Database begins with valid 16-byte header string.
#
do_test filefmt-1.1 {
  sqlite3 db test.db
  db eval {CREATE TABLE t1(x)}
  db close
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#
ifcapable pager_pragmas {
  foreach pagesize {512 1024 2048 4096 8192 16384 32768} {
     if {[info exists SQLITE_MAX_PAGE_SIZE]
          && $pagesize>$SQLITE_MAX_PAGE_SIZE} continue
     do_test filefmt-1.5.$pagesize.1 {
       db close
       file delete -force test.db
       sqlite3 db test.db
       db eval "PRAGMA auto_vacuum=OFF"
       db eval "PRAGMA page_size=$pagesize"
       db eval {CREATE TABLE t1(x)}
       file size test.db
     } [expr $pagesize*2]
     do_test filefmt-1.5.$pagesize.2 {







|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#
ifcapable pager_pragmas {
  foreach pagesize {512 1024 2048 4096 8192 16384 32768} {
     if {[info exists SQLITE_MAX_PAGE_SIZE]
          && $pagesize>$SQLITE_MAX_PAGE_SIZE} continue
     do_test filefmt-1.5.$pagesize.1 {
       db close
       forcedelete test.db
       sqlite3 db test.db
       db eval "PRAGMA auto_vacuum=OFF"
       db eval "PRAGMA page_size=$pagesize"
       db eval {CREATE TABLE t1(x)}
       file size test.db
     } [expr $pagesize*2]
     do_test filefmt-1.5.$pagesize.2 {
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

# Usable space per page (page-size minus unused space per page)
# must be at least 480 bytes
#
ifcapable pager_pragmas {
  do_test filefmt-1.8 {
    db close
    file delete -force test.db
    sqlite3 db test.db
    db eval {PRAGMA page_size=512; CREATE TABLE t1(x)}
    db close
    hexio_write test.db 20 21
    sqlite3 db test.db
    catchsql {
       SELECT count(*) FROM sqlite_master
    }
  } {1 {file is encrypted or is not a database}}
}

#-------------------------------------------------------------------------
# The following block of tests - filefmt-2.* - test that versions 3.7.0
# and later can read and write databases that have been modified or created
# by 3.6.23.1 and earlier. The difference difference is that 3.7.0 stores
# the size of the database in the database file header, whereas 3.6.23.1
# always derives this from the size of the file.
#
db close
file delete -force test.db

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







|



















|







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

# Usable space per page (page-size minus unused space per page)
# must be at least 480 bytes
#
ifcapable pager_pragmas {
  do_test filefmt-1.8 {
    db close
    forcedelete test.db
    sqlite3 db test.db
    db eval {PRAGMA page_size=512; CREATE TABLE t1(x)}
    db close
    hexio_write test.db 20 21
    sqlite3 db test.db
    catchsql {
       SELECT count(*) FROM sqlite_master
    }
  } {1 {file is encrypted or is not a database}}
}

#-------------------------------------------------------------------------
# The following block of tests - filefmt-2.* - test that versions 3.7.0
# and later can read and write databases that have been modified or created
# by 3.6.23.1 and earlier. The difference difference is that 3.7.0 stores
# the size of the database in the database file header, whereas 3.6.23.1
# always derives this from the size of the file.
#
db close
forcedelete test.db

set a_string_counter 1
proc a_string {n} {
  incr ::a_string_counter
  string range [string repeat "${::a_string_counter}." $n] 1 $n
}
sqlite3 db test.db
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
} {}

do_execsql_test filefmt-2.1.4 { INSERT INTO t2 VALUES(2) } {}
integrity_check filefmt-2.1.5
do_test         filefmt-2.1.6 { hexio_read test.db 28 4 } {00000010}

db close
file delete -force test.db
sqlite3 db test.db
db func a_string a_string

do_execsql_test filefmt-2.2.1 {
  PRAGMA page_size = 1024;
  PRAGMA auto_vacuum = 0;
  CREATE TABLE t1(a);







|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
} {}

do_execsql_test filefmt-2.1.4 { INSERT INTO t2 VALUES(2) } {}
integrity_check filefmt-2.1.5
do_test         filefmt-2.1.6 { hexio_read test.db 28 4 } {00000010}

db close
forcedelete test.db
sqlite3 db test.db
db func a_string a_string

do_execsql_test filefmt-2.2.1 {
  PRAGMA page_size = 1024;
  PRAGMA auto_vacuum = 0;
  CREATE TABLE t1(a);

Changes to test/fts1j.test.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# If SQLITE_ENABLE_FTS1 is defined, omit this file.
ifcapable !fts1 {
  finish_test
  return
}

# Clean up anything left over from a previous pass.
file delete -force test2.db
file delete -force test2.db-journal
sqlite3 db2 test2.db

db eval {
  CREATE VIRTUAL TABLE t3 USING fts1(content);
  INSERT INTO t3 (rowid, content) VALUES(1, "hello world");
}








|
|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# If SQLITE_ENABLE_FTS1 is defined, omit this file.
ifcapable !fts1 {
  finish_test
  return
}

# Clean up anything left over from a previous pass.
forcedelete test2.db
forcedelete test2.db-journal
sqlite3 db2 test2.db

db eval {
  CREATE VIRTUAL TABLE t3 USING fts1(content);
  INSERT INTO t3 (rowid, content) VALUES(1, "hello world");
}

80
81
82
83
84
85
86
87
88
89

    DETACH DATABASE two;
  } db2
} {2}
catch {db eval {DETACH DATABASE two}}

catch {db2 close}
file delete -force test2.db

finish_test







|


80
81
82
83
84
85
86
87
88
89

    DETACH DATABASE two;
  } db2
} {2}
catch {db eval {DETACH DATABASE two}}

catch {db2 close}
forcedelete test2.db

finish_test

Changes to test/fts1o.test.

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  execsql { SELECT a, b, c FROM fts_t1 WHERE c MATCH 'four'; }
} {{one three four} {one four} {one four two}}

#---------------------------------------------------------------------
# Test that it is possible to rename an fts1 table in an attached 
# database.
#
file delete -force test2.db test2.db-journal

do_test fts1o-4.1 {
  execsql {
    DROP TABLE t1_term;
    ALTER TABLE fts_t1 RENAME to t1;
    SELECT a, b, c FROM t1 WHERE c MATCH 'two';
  }







|







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  execsql { SELECT a, b, c FROM fts_t1 WHERE c MATCH 'four'; }
} {{one three four} {one four} {one four two}}

#---------------------------------------------------------------------
# Test that it is possible to rename an fts1 table in an attached 
# database.
#
forcedelete test2.db test2.db-journal

do_test fts1o-4.1 {
  execsql {
    DROP TABLE t1_term;
    ALTER TABLE fts_t1 RENAME to t1;
    SELECT a, b, c FROM t1 WHERE c MATCH 'two';
  }

Changes to test/fts2j.test.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# If SQLITE_ENABLE_FTS2 is defined, omit this file.
ifcapable !fts2 {
  finish_test
  return
}

# Clean up anything left over from a previous pass.
file delete -force test2.db
file delete -force test2.db-journal
sqlite3 db2 test2.db

db eval {
  CREATE VIRTUAL TABLE t3 USING fts2(content);
  INSERT INTO t3 (rowid, content) VALUES(1, "hello world");
}








|
|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# If SQLITE_ENABLE_FTS2 is defined, omit this file.
ifcapable !fts2 {
  finish_test
  return
}

# Clean up anything left over from a previous pass.
forcedelete test2.db
forcedelete test2.db-journal
sqlite3 db2 test2.db

db eval {
  CREATE VIRTUAL TABLE t3 USING fts2(content);
  INSERT INTO t3 (rowid, content) VALUES(1, "hello world");
}

80
81
82
83
84
85
86
87
88
89

    DETACH DATABASE two;
  } db2
} {2}
catch {db eval {DETACH DATABASE two}}

catch {db2 close}
file delete -force test2.db

finish_test







|


80
81
82
83
84
85
86
87
88
89

    DETACH DATABASE two;
  } db2
} {2}
catch {db eval {DETACH DATABASE two}}

catch {db2 close}
forcedelete test2.db

finish_test

Changes to test/fts2o.test.

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
} {{one three four} {one four} {one four two}}

#-------------------------------------------------------------------
# Close, delete and reopen the database. The following test should 
# be run on an initially empty db.
#
db close
file delete -force test.db test.db-journal
sqlite3 db test.db

do_test fts2o-3.1 {
  execsql {
    CREATE VIRTUAL TABLE t1 USING fts2(a, b, c);
    INSERT INTO t1(a, b, c) VALUES('one three four', 'one four', 'one two');
    SELECT a, b, c FROM t1 WHERE c MATCH 'two';







|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
} {{one three four} {one four} {one four two}}

#-------------------------------------------------------------------
# Close, delete and reopen the database. The following test should 
# be run on an initially empty db.
#
db close
forcedelete test.db test.db-journal
sqlite3 db test.db

do_test fts2o-3.1 {
  execsql {
    CREATE VIRTUAL TABLE t1 USING fts2(a, b, c);
    INSERT INTO t1(a, b, c) VALUES('one three four', 'one four', 'one two');
    SELECT a, b, c FROM t1 WHERE c MATCH 'two';
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  }
} {{one three four} {one four} {one two} {one three four} {one four} {one two}}

#---------------------------------------------------------------------
# Test that it is possible to rename an fts2 table in an attached 
# database.
#
file delete -force test2.db test2.db-journal

do_test fts2o-3.1 {
  execsql {
    ATTACH 'test2.db' AS aux;
    CREATE VIRTUAL TABLE aux.t1 USING fts2(a, b, c);
    INSERT INTO aux.t1(a, b, c) VALUES(
      'neung song sahm', 'neung see', 'neung see song'







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  }
} {{one three four} {one four} {one two} {one three four} {one four} {one two}}

#---------------------------------------------------------------------
# Test that it is possible to rename an fts2 table in an attached 
# database.
#
forcedelete test2.db test2.db-journal

do_test fts2o-3.1 {
  execsql {
    ATTACH 'test2.db' AS aux;
    CREATE VIRTUAL TABLE aux.t1 USING fts2(a, b, c);
    INSERT INTO aux.t1(a, b, c) VALUES(
      'neung song sahm', 'neung see', 'neung see song'

Changes to test/fts3aj.test.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

# Clean up anything left over from a previous pass.
file delete -force test2.db
file delete -force test2.db-journal
sqlite3 db2 test2.db

db eval {
  CREATE VIRTUAL TABLE t3 USING fts3(content);
  INSERT INTO t3 (rowid, content) VALUES(1, "hello world");
}








|
|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

# Clean up anything left over from a previous pass.
forcedelete test2.db
forcedelete test2.db-journal
sqlite3 db2 test2.db

db eval {
  CREATE VIRTUAL TABLE t3 USING fts3(content);
  INSERT INTO t3 (rowid, content) VALUES(1, "hello world");
}

80
81
82
83
84
85
86
87
88
89

    DETACH DATABASE two;
  } db2
} {2}
catch {db eval {DETACH DATABASE two}}

catch {db2 close}
file delete -force test2.db

finish_test







|


80
81
82
83
84
85
86
87
88
89

    DETACH DATABASE two;
  } db2
} {2}
catch {db eval {DETACH DATABASE two}}

catch {db2 close}
forcedelete test2.db

finish_test

Changes to test/fts3ao.test.

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
} {{one three four} {one four} {one four two}}

#-------------------------------------------------------------------
# Close, delete and reopen the database. The following test should 
# be run on an initially empty db.
#
db close
file delete -force test.db test.db-journal
sqlite3 db test.db

do_test fts3ao-3.1 {
  execsql {
    CREATE VIRTUAL TABLE t1 USING fts3(a, b, c);
    INSERT INTO t1(a, b, c) VALUES('one three four', 'one four', 'one two');
    SELECT a, b, c FROM t1 WHERE c MATCH 'two';







|







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
} {{one three four} {one four} {one four two}}

#-------------------------------------------------------------------
# Close, delete and reopen the database. The following test should 
# be run on an initially empty db.
#
db close
forcedelete test.db test.db-journal
sqlite3 db test.db

do_test fts3ao-3.1 {
  execsql {
    CREATE VIRTUAL TABLE t1 USING fts3(a, b, c);
    INSERT INTO t1(a, b, c) VALUES('one three four', 'one four', 'one two');
    SELECT a, b, c FROM t1 WHERE c MATCH 'two';
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  }
} {{one three four} {one four} {one two} {one three four} {one four} {one two}}

#---------------------------------------------------------------------
# Test that it is possible to rename an fts3 table in an attached 
# database.
#
file delete -force test2.db test2.db-journal

do_test fts3ao-3.1 {
  execsql {
    ATTACH 'test2.db' AS aux;
    CREATE VIRTUAL TABLE aux.t1 USING fts3(a, b, c);
    INSERT INTO aux.t1(a, b, c) VALUES(
      'neung song sahm', 'neung see', 'neung see song'







|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  }
} {{one three four} {one four} {one two} {one three four} {one four} {one two}}

#---------------------------------------------------------------------
# Test that it is possible to rename an fts3 table in an attached 
# database.
#
forcedelete test2.db test2.db-journal

do_test fts3ao-3.1 {
  execsql {
    ATTACH 'test2.db' AS aux;
    CREATE VIRTUAL TABLE aux.t1 USING fts3(a, b, c);
    INSERT INTO aux.t1(a, b, c) VALUES(
      'neung song sahm', 'neung see', 'neung see song'

Changes to test/fts3snippet.test.

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
foreach {DO_MALLOC_TEST enc} {
  0 utf8
  1 utf8
  1 utf16
} {

  db close
  file delete -force test.db
  sqlite3 db test.db
  sqlite3_db_config_lookaside db 0 0 0
  db eval "PRAGMA encoding = \"$enc\""

  # Set variable $T to the test name prefix for this iteration of the loop.
  #
  set T "fts3snippet-$enc"







|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
foreach {DO_MALLOC_TEST enc} {
  0 utf8
  1 utf8
  1 utf16
} {

  db close
  forcedelete test.db
  sqlite3 db test.db
  sqlite3_db_config_lookaside db 0 0 0
  db eval "PRAGMA encoding = \"$enc\""

  # Set variable $T to the test name prefix for this iteration of the loop.
  #
  set T "fts3snippet-$enc"

Changes to test/fts4aa.test.

1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
  } $r
}

# Should get the same search results when the page size is very large
#
do_test fts4aa-3.0 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  db eval {
    PRAGMA page_size=65536;
    CREATE VIRTUAL TABLE t1 USING fts4(words, tokenize porter);
  }
  fts4aa_fill_table
} {}







|







1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
  } $r
}

# Should get the same search results when the page size is very large
#
do_test fts4aa-3.0 {
  db close
  forcedelete test.db
  sqlite3 db test.db
  db eval {
    PRAGMA page_size=65536;
    CREATE VIRTUAL TABLE t1 USING fts4(words, tokenize porter);
  }
  fts4aa_fill_table
} {}

Changes to test/fuzz_malloc.test.

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
proc do_fuzzy_malloc_test {testname args} {
  set ::fuzzyopts(-repeats) $::REPEATS
  set ::fuzzyopts(-sqlprep) {}
  array set ::fuzzyopts $args

  sqlite3_memdebug_fail -1
  db close
  file delete test.db test.db-journal
  sqlite3 db test.db
  set ::prep $::fuzzyopts(-sqlprep)
  execsql $::prep
  set jj 0
  for {set ii 0} {$ii < $::fuzzyopts(-repeats)} {incr ii} {
    expr srand($jj)
    incr jj







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
proc do_fuzzy_malloc_test {testname args} {
  set ::fuzzyopts(-repeats) $::REPEATS
  set ::fuzzyopts(-sqlprep) {}
  array set ::fuzzyopts $args

  sqlite3_memdebug_fail -1
  db close
  delete_file test.db test.db-journal
  sqlite3 db test.db
  set ::prep $::fuzzyopts(-sqlprep)
  execsql $::prep
  set jj 0
  for {set ii 0} {$ii < $::fuzzyopts(-repeats)} {incr ii} {
    expr srand($jj)
    incr jj

Changes to test/hook.test.

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  }
  set ::commit_cnt
} {}

# Ticket #3564.
#
do_test hook-3.10 {
  file delete -force test2.db test2.db-journal
  sqlite3 db2 test2.db
  proc commit_hook {} {
    set y [db2 one {SELECT y FROM t3 WHERE y>10}]
    return [expr {$y>10}]
  }
  db2 eval {CREATE TABLE t3(x,y)}
  db2 commit_hook commit_hook







|







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  }
  set ::commit_cnt
} {}

# Ticket #3564.
#
do_test hook-3.10 {
  forcedelete test2.db test2.db-journal
  sqlite3 db2 test2.db
  proc commit_hook {} {
    set y [db2 one {SELECT y FROM t3 WHERE y>10}]
    return [expr {$y>10}]
  }
  db2 eval {CREATE TABLE t3(x,y)}
  db2 commit_hook commit_hook
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  }
}

# Update-hook + ATTACH
set ::update_hook {}
ifcapable attach {
  do_test hook-4.2.3 {
    file delete -force test2.db
    execsql {
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t3(a INTEGER PRIMARY KEY, b);
      INSERT INTO aux.t3 SELECT * FROM t1;
      UPDATE t3 SET b = 'two or so' WHERE a = 2;
      DELETE FROM t3 WHERE 1; -- Avoid the truncate optimization (for now)
    }







|







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  }
}

# Update-hook + ATTACH
set ::update_hook {}
ifcapable attach {
  do_test hook-4.2.3 {
    forcedelete test2.db
    execsql {
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t3(a INTEGER PRIMARY KEY, b);
      INSERT INTO aux.t3 SELECT * FROM t1;
      UPDATE t3 SET b = 'two or so' WHERE a = 2;
      DELETE FROM t3 WHERE 1; -- Avoid the truncate optimization (for now)
    }

Changes to test/incrblob.test.

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  if {$AutoVacuumMode>0} {
    ifcapable !autovacuum {
      break
    }
  }

  db close
  file delete -force test.db test.db-journal

  sqlite3 db test.db
  execsql "PRAGMA auto_vacuum = $AutoVacuumMode"

  do_test incrblob-2.$AutoVacuumMode.1 {
    set ::str [string repeat abcdefghij 2900]
    execsql {







|







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  if {$AutoVacuumMode>0} {
    ifcapable !autovacuum {
      break
    }
  }

  db close
  forcedelete test.db test.db-journal

  sqlite3 db test.db
  execsql "PRAGMA auto_vacuum = $AutoVacuumMode"

  do_test incrblob-2.$AutoVacuumMode.1 {
    set ::str [string repeat abcdefghij 2900]
    execsql {
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
#------------------------------------------------------------------------
# incrblob-5.*: 
#
#     Test that opening a blob in an attached database works.
#
ifcapable attach {
  do_test incrblob-5.1 {
    file delete -force test2.db test2.db-journal
    set ::size [expr [file size [info script]]]
    execsql {
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.files(name, text);
      INSERT INTO aux.files VALUES('this one', zeroblob($::size));
    }
    set fd  [db incrblob aux files text 1]







|







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
#------------------------------------------------------------------------
# incrblob-5.*: 
#
#     Test that opening a blob in an attached database works.
#
ifcapable attach {
  do_test incrblob-5.1 {
    forcedelete test2.db test2.db-journal
    set ::size [expr [file size [info script]]]
    execsql {
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.files(name, text);
      INSERT INTO aux.files VALUES('this one', zeroblob($::size));
    }
    set fd  [db incrblob aux files text 1]
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

set fd [open [info script]]
fconfigure $fd -translation binary
set ::data [read $fd 14000]
close $fd

db close
file delete -force test.db test.db-journal
sqlite3 db test.db

do_test incrblob-7.2.1 {
  execsql {
    PRAGMA auto_vacuum = "incremental";
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);        -- root@page3
    INSERT INTO t1 VALUES(123, $::data);







|







580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

set fd [open [info script]]
fconfigure $fd -translation binary
set ::data [read $fd 14000]
close $fd

db close
forcedelete test.db test.db-journal
sqlite3 db test.db

do_test incrblob-7.2.1 {
  execsql {
    PRAGMA auto_vacuum = "incremental";
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);        -- root@page3
    INSERT INTO t1 VALUES(123, $::data);

Changes to test/incrvacuum.test.

327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
    }] $control
  }
}

set ::str1 [string repeat abcdefghij 130]
set ::str2 [string repeat 1234567890 105]

file delete -force test1.db test1.db-journal test2.db test2.db-journal
sqlite3 db1 test1.db
sqlite3 db2 test2.db
execsql { PRAGMA auto_vacuum = 'none' } db1
execsql { PRAGMA auto_vacuum = 'incremental' } db2

set tn 1
foreach sql $::TestScriptList {







|







327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
    }] $control
  }
}

set ::str1 [string repeat abcdefghij 130]
set ::str2 [string repeat 1234567890 105]

forcedelete test1.db test1.db-journal test2.db test2.db-journal
sqlite3 db1 test1.db
sqlite3 db2 test2.db
execsql { PRAGMA auto_vacuum = 'none' } db1
execsql { PRAGMA auto_vacuum = 'incremental' } db2

set tn 1
foreach sql $::TestScriptList {
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
} {}

#---------------------------------------------------------------------
# At one point this test case was causing an assert() to fail.
#
do_test incrvacuum-9.1 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db

  execsql {
    PRAGMA auto_vacuum = 'incremental';
    CREATE TABLE t1(a, b, c);
    CREATE TABLE t2(a, b, c);
    INSERT INTO t2 VALUES(randstr(500,500),randstr(500,500),randstr(500,500));







|







471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
} {}

#---------------------------------------------------------------------
# At one point this test case was causing an assert() to fail.
#
do_test incrvacuum-9.1 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db

  execsql {
    PRAGMA auto_vacuum = 'incremental';
    CREATE TABLE t1(a, b, c);
    CREATE TABLE t2(a, b, c);
    INSERT INTO t2 VALUES(randstr(500,500),randstr(500,500),randstr(500,500));
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

#----------------------------------------------------------------
# Test that if we set the auto_vacuum mode to 'incremental', then
# create a database, thereafter that database defaults to incremental 
# vacuum mode.
#
db close
file delete -force test.db test.db-journal
sqlite3 db test.db

ifcapable default_autovacuum {
  do_test incrvacuum-11.1-av-dflt-on {
    execsql {
      PRAGMA auto_vacuum;
    }







|







589
590
591
592
593
594
595
596
597
598
599
600
601
602
603

#----------------------------------------------------------------
# Test that if we set the auto_vacuum mode to 'incremental', then
# create a database, thereafter that database defaults to incremental 
# vacuum mode.
#
db close
forcedelete test.db test.db-journal
sqlite3 db test.db

ifcapable default_autovacuum {
  do_test incrvacuum-11.1-av-dflt-on {
    execsql {
      PRAGMA auto_vacuum;
    }
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
} {1}

#----------------------------------------------------------------------
# Special case: What happens if the database is locked when a "PRAGMA
# auto_vacuum = XXX" statement is executed.
#
db close
file delete -force test.db test.db-journal
sqlite3 db test.db

do_test incrvacuum-12.1 {
  execsql {
    PRAGMA auto_vacuum = 1;
  }
  expr {[file size test.db]>0}







|







647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
} {1}

#----------------------------------------------------------------------
# Special case: What happens if the database is locked when a "PRAGMA
# auto_vacuum = XXX" statement is executed.
#
db close
forcedelete test.db test.db-journal
sqlite3 db test.db

do_test incrvacuum-12.1 {
  execsql {
    PRAGMA auto_vacuum = 1;
  }
  expr {[file size test.db]>0}
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
#----------------------------------------------------------------------
# Special case #2: What if one process prepares a "PRAGMA auto_vacuum = XXX"
# statement when the database is empty, but doesn't execute it until
# after some other process has created the database.
#
db2 close
db close
file delete -force test.db test.db-journal
sqlite3 db test.db  ;  set ::DB [sqlite3_connection_pointer db]
sqlite3 db2 test.db

do_test incrvacuum-13.1 {
  # File size is sometimes 1 instead of 0 due to the hack we put in
  # to work around ticket #3260.  Search for comments on #3260 in
  # os_unix.c.







|







688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
#----------------------------------------------------------------------
# Special case #2: What if one process prepares a "PRAGMA auto_vacuum = XXX"
# statement when the database is empty, but doesn't execute it until
# after some other process has created the database.
#
db2 close
db close
forcedelete test.db test.db-journal
sqlite3 db test.db  ;  set ::DB [sqlite3_connection_pointer db]
sqlite3 db2 test.db

do_test incrvacuum-13.1 {
  # File size is sometimes 1 instead of 0 due to the hack we put in
  # to work around ticket #3260.  Search for comments on #3260 in
  # os_unix.c.
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
  } {1 {file is encrypted or is not a database}}
  db3 close
}

do_test incrvacuum-15.1 {
  db close
  db2 close
  file delete -force test.db
  sqlite3 db test.db

  set str [string repeat "abcdefghij" 500]

  execsql {
    PRAGMA cache_size = 10;
    PRAGMA auto_vacuum = incremental;







|







739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
  } {1 {file is encrypted or is not a database}}
  db3 close
}

do_test incrvacuum-15.1 {
  db close
  db2 close
  forcedelete test.db
  sqlite3 db test.db

  set str [string repeat "abcdefghij" 500]

  execsql {
    PRAGMA cache_size = 10;
    PRAGMA auto_vacuum = incremental;

Changes to test/incrvacuum2.test.

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  file size test.db
} {3072}

# Make sure incremental vacuum works on attached databases.
#
ifcapable attach {
  do_test incrvacuum2-2.1 {
    file delete -force test2.db test2.db-journal
    execsql {
      ATTACH DATABASE 'test2.db' AS aux;
      PRAGMA aux.auto_vacuum=incremental;
      CREATE TABLE aux.t2(x);
      INSERT INTO t2 VALUES(zeroblob(30000));
      INSERT INTO t1 SELECT * FROM t2;
      DELETE FROM t2;







|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  file size test.db
} {3072}

# Make sure incremental vacuum works on attached databases.
#
ifcapable attach {
  do_test incrvacuum2-2.1 {
    forcedelete test2.db test2.db-journal
    execsql {
      ATTACH DATABASE 'test2.db' AS aux;
      PRAGMA aux.auto_vacuum=incremental;
      CREATE TABLE aux.t2(x);
      INSERT INTO t2 VALUES(zeroblob(30000));
      INSERT INTO t1 SELECT * FROM t2;
      DELETE FROM t2;

Changes to test/incrvacuum_ioerr.test.

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  db close
}


ifcapable shared_cache {

  catch { db close }
  file delete -force test.db
  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
  
  # Create two connections to a single shared-cache:
  #
  sqlite3 db1 test.db
  sqlite3 db2 test.db
  







|







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  db close
}


ifcapable shared_cache {

  catch { db close }
  forcedelete test.db
  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
  
  # Create two connections to a single shared-cache:
  #
  sqlite3 db1 test.db
  sqlite3 db2 test.db
  

Changes to test/insert5.test.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
proc uses_temp_table {sql} {
  return [expr {[lsearch [execsql "EXPLAIN $sql"] OpenEphemeral]>=0}]
}

# Construct the sample database.
#
do_test insert5-1.0 {
  file delete -force test2.db test2.db-journal
  execsql {
    CREATE TABLE MAIN(Id INTEGER, Id1 INTEGER); 
    CREATE TABLE B(Id INTEGER, Id1 INTEGER); 
    CREATE VIEW v1 AS SELECT * FROM B;
    CREATE VIEW v2 AS SELECT * FROM MAIN;
    INSERT INTO MAIN(Id,Id1) VALUES(2,3); 
    INSERT INTO B(Id,Id1) VALUES(2,3); 







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
proc uses_temp_table {sql} {
  return [expr {[lsearch [execsql "EXPLAIN $sql"] OpenEphemeral]>=0}]
}

# Construct the sample database.
#
do_test insert5-1.0 {
  forcedelete test2.db test2.db-journal
  execsql {
    CREATE TABLE MAIN(Id INTEGER, Id1 INTEGER); 
    CREATE TABLE B(Id INTEGER, Id1 INTEGER); 
    CREATE VIEW v1 AS SELECT * FROM B;
    CREATE VIEW v2 AS SELECT * FROM MAIN;
    INSERT INTO MAIN(Id,Id1) VALUES(2,3); 
    INSERT INTO B(Id,Id1) VALUES(2,3); 

Changes to test/io.test.

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
  file mkdir test.db-journal
  catchsql {
    INSERT INTO abc VALUES(9, randstr(1000,1000));
    COMMIT
  }
} {1 {unable to open database file}}
do_test io-2.6.3 {
  file delete -force test.db-journal
  catchsql { COMMIT }
} {0 {}}
do_test io-2.6.4 {
  execsql { SELECT * FROM abc }
} {1 2 3 4 5 6 7 8}

# Test that if the database modification is part of multi-file commit,
# the journal file is always created. In this case, the journal file
# is created during execution of the COMMIT statement, so we have to
# use the same technique to check that it is created as in the above 
# block.
file delete -force test2.db test2.db-journal
ifcapable attach {
  do_test io-2.7.1 {
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA aux.page_size = 1024;
      CREATE TABLE aux.abc2(a, b);
      BEGIN;







|











|







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
  file mkdir test.db-journal
  catchsql {
    INSERT INTO abc VALUES(9, randstr(1000,1000));
    COMMIT
  }
} {1 {unable to open database file}}
do_test io-2.6.3 {
  forcedelete test.db-journal
  catchsql { COMMIT }
} {0 {}}
do_test io-2.6.4 {
  execsql { SELECT * FROM abc }
} {1 2 3 4 5 6 7 8}

# Test that if the database modification is part of multi-file commit,
# the journal file is always created. In this case, the journal file
# is created during execution of the COMMIT statement, so we have to
# use the same technique to check that it is created as in the above 
# block.
forcedelete test2.db test2.db-journal
ifcapable attach {
  do_test io-2.7.1 {
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA aux.page_size = 1024;
      CREATE TABLE aux.abc2(a, b);
      BEGIN;
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
    execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 }
  } {1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10}
  do_test io-2.7.4 {
    file mkdir test2.db-journal
    catchsql { COMMIT }
  } {1 {unable to open database file}}
  do_test io-2.7.5 {
    file delete -force test2.db-journal
    catchsql { COMMIT }
  } {1 {cannot commit - no transaction is active}}
  do_test io-2.7.6 {
    execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 }
  } {1 2 3 4 5 6 7 8}
}








|







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
    execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 }
  } {1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10}
  do_test io-2.7.4 {
    file mkdir test2.db-journal
    catchsql { COMMIT }
  } {1 {unable to open database file}}
  do_test io-2.7.5 {
    forcedelete test2.db-journal
    catchsql { COMMIT }
  } {1 {cannot commit - no transaction is active}}
  do_test io-2.7.6 {
    execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 }
  } {1 2 3 4 5 6 7 8}
}

300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    INSERT INTO abc VALUES(9, 10);
  }
  file exists test.db-journal
} {1}
do_test io-2.9.2 {
  execsql { ROLLBACK; }
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db -vfs devsym
  execsql {
    PRAGMA auto_vacuum = OFF;
    PRAGMA page_size = 2048;
    CREATE TABLE abc(a, b);
  }
  execsql {







|







300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    INSERT INTO abc VALUES(9, 10);
  }
  file exists test.db-journal
} {1}
do_test io-2.9.2 {
  execsql { ROLLBACK; }
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db -vfs devsym
  execsql {
    PRAGMA auto_vacuum = OFF;
    PRAGMA page_size = 2048;
    CREATE TABLE abc(a, b);
  }
  execsql {
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
#----------------------------------------------------------------------
# Test cases io-3.* test the IOCAP_SEQUENTIAL optimization.
#
sqlite3_simulate_device -char sequential -sectorsize 0
ifcapable pager_pragmas {
  do_test io-3.1 {
    db close
    file delete -force test.db test.db-journal
    sqlite3 db test.db -vfs devsym
    db eval {
      PRAGMA auto_vacuum=OFF;
    }
    # File size might be 1 due to the hack to work around ticket #3260.
    # Search for #3260 in os_unix.c for additional information.
    expr {[file size test.db]>1}







|







371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
#----------------------------------------------------------------------
# Test cases io-3.* test the IOCAP_SEQUENTIAL optimization.
#
sqlite3_simulate_device -char sequential -sectorsize 0
ifcapable pager_pragmas {
  do_test io-3.1 {
    db close
    forcedelete test.db test.db-journal
    sqlite3 db test.db -vfs devsym
    db eval {
      PRAGMA auto_vacuum=OFF;
    }
    # File size might be 1 due to the hack to work around ticket #3260.
    # Search for #3260 in os_unix.c for additional information.
    expr {[file size test.db]>1}
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
         {atomic2K}            4096      4096
         {atomic2K atomic}      512      8192
         {atomic64K}            512      1024
} {
  incr tn
  if {$pgsize>$::SQLITE_MAX_PAGE_SIZE} continue
  db close
  file delete -force test.db test.db-journal
  sqlite3_simulate_device -char $char -sectorsize $sectorsize
  sqlite3 db test.db -vfs devsym
  db eval {
    PRAGMA auto_vacuum=OFF;
  }
  ifcapable !atomicwrite {
    if {[regexp {^atomic} $char]} continue







|







540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
         {atomic2K}            4096      4096
         {atomic2K atomic}      512      8192
         {atomic64K}            512      1024
} {
  incr tn
  if {$pgsize>$::SQLITE_MAX_PAGE_SIZE} continue
  db close
  forcedelete test.db test.db-journal
  sqlite3_simulate_device -char $char -sectorsize $sectorsize
  sqlite3 db test.db -vfs devsym
  db eval {
    PRAGMA auto_vacuum=OFF;
  }
  ifcapable !atomicwrite {
    if {[regexp {^atomic} $char]} continue

Changes to test/ioerr.test.

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
    db2 eval {
      PRAGMA synchronous = 0;
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 2);
      BEGIN;
      INSERT INTO t1 VALUES(3, 4);
    }
    copy_file test2.db test.db
    copy_file test2.db-journal test.db-journal
    db2 close
  } -tclbody {
    sqlite3 db test.db
    db eval {
      SELECT * FROM t1;
    }
  } -exclude 1







|
|







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
    db2 eval {
      PRAGMA synchronous = 0;
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 2);
      BEGIN;
      INSERT INTO t1 VALUES(3, 4);
    }
    forcecopy test2.db test.db
    forcecopy test2.db-journal test.db-journal
    db2 close
  } -tclbody {
    sqlite3 db test.db
    db eval {
      SELECT * FROM t1;
    }
  } -exclude 1
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  do_ioerr_test ioerr-9 -ckrefcount true -tclprep {
    execsql {
      CREATE TABLE t1(a,b,c);
      INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2);
      BEGIN;
      INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2);
    }
    copy_file test.db-journal test2.db-journal
    execsql {
      COMMIT;
    }
    copy_file test2.db-journal test.db-journal
    set f [open test.db-journal a]
    fconfigure $f -encoding binary
    puts -nonewline $f "hello"
    puts -nonewline $f "\x00\x00\x00\x05\x01\x02\x03\x04"
    puts -nonewline $f "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
    close $f
  } -sqlbody {







|



|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  do_ioerr_test ioerr-9 -ckrefcount true -tclprep {
    execsql {
      CREATE TABLE t1(a,b,c);
      INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2);
      BEGIN;
      INSERT INTO t1 VALUES(randstr(200,200), randstr(1000,1000), 2);
    }
    forcecopy test.db-journal test2.db-journal
    execsql {
      COMMIT;
    }
    forcecopy test2.db-journal test.db-journal
    set f [open test.db-journal a]
    fconfigure $f -encoding binary
    puts -nonewline $f "hello"
    puts -nonewline $f "\x00\x00\x00\x05\x01\x02\x03\x04"
    puts -nonewline $f "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
    close $f
  } -sqlbody {

Changes to test/ioerr4.test.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# Enable shared cache mode and incremental vacuum.
#
do_test ioerr4-1.1 {
  db close
  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
} {0}
do_test ioerr4-1.2 {
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  sqlite3 db2 test.db
  db eval {
    PRAGMA auto_vacuum=INCREMENTAL;
    CREATE TABLE a(i INTEGER, b BLOB);
  }
  db2 eval {







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# Enable shared cache mode and incremental vacuum.
#
do_test ioerr4-1.1 {
  db close
  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
} {0}
do_test ioerr4-1.2 {
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  sqlite3 db2 test.db
  db eval {
    PRAGMA auto_vacuum=INCREMENTAL;
    CREATE TABLE a(i INTEGER, b BLOB);
  }
  db2 eval {
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
} {64}

# Set up for an I/O error on incremental vacuum
# with two connections on shared cache.
#
db close
db2 close
file copy -force test.db test.db-bu
do_ioerr_test ioerr4-2 -tclprep {
  catch {db2 close}
  db close
  file delete -force test.db test.db-journal
  file copy -force test.db-bu test.db
  sqlite3_enable_shared_cache 1
  set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
  db eval {PRAGMA auto_vacuum=INCREMENTAL}
  sqlite3 db2 test.db
} -tclbody {
  db eval {PRAGMA incremental_vacuum(5)}
}

db2 close
file delete -force test.db-bu
sqlite3_enable_shared_cache $::enable_shared_cache

finish_test







|



|
|









|



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
} {64}

# Set up for an I/O error on incremental vacuum
# with two connections on shared cache.
#
db close
db2 close
forcecopy test.db test.db-bu
do_ioerr_test ioerr4-2 -tclprep {
  catch {db2 close}
  db close
  forcedelete test.db test.db-journal
  forcecopy test.db-bu test.db
  sqlite3_enable_shared_cache 1
  set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
  db eval {PRAGMA auto_vacuum=INCREMENTAL}
  sqlite3 db2 test.db
} -tclbody {
  db eval {PRAGMA incremental_vacuum(5)}
}

db2 close
forcedelete test.db-bu
sqlite3_enable_shared_cache $::enable_shared_cache

finish_test

Changes to test/journal1.test.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# $Id: journal1.test,v 1.2 2005/03/20 22:54:56 drh Exp $


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

# These tests will not work on windows because windows uses
# manditory file locking which breaks the file copy command.
#
if {$tcl_platform(platform)=="windows"} {
  finish_test
  return
}

# Create a smaple database







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# $Id: journal1.test,v 1.2 2005/03/20 22:54:56 drh Exp $


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

# These tests will not work on windows because windows uses
# manditory file locking which breaks the copy_file command.
#
if {$tcl_platform(platform)=="windows"} {
  finish_test
  return
}

# Create a smaple database
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# database.
#
do_test journal1-1.2 {
  execsql {
    BEGIN;
    DELETE FROM t1;
  }
  file copy -force test.db-journal test.db-journal-bu
  execsql {
    ROLLBACK;
  }
  db close
  file delete test.db
  file copy test.db-journal-bu test.db-journal
  sqlite3 db test.db
  catchsql {
    SELECT * FROM sqlite_master
  }
} {0 {}}

finish_test







|




|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# database.
#
do_test journal1-1.2 {
  execsql {
    BEGIN;
    DELETE FROM t1;
  }
  forcecopy test.db-journal test.db-journal-bu
  execsql {
    ROLLBACK;
  }
  db close
  delete_file test.db
  copy_file test.db-journal-bu test.db-journal
  sqlite3 db test.db
  catchsql {
    SELECT * FROM sqlite_master
  }
} {0 {}}

finish_test

Changes to test/journal2.test.

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
do_test journal2-1.13 {
  tvfs filter {xOpen xClose xDelete xWrite xTruncate}
  set ::tvfs_error_on_write 1
  catchsql { COMMIT } db2
} {1 {disk I/O error}}
db2 close
unset ::tvfs_error_on_write
file copy -force test.db testX.db

do_test journal2-1.14 { file exists test.db-journal } 1
do_test journal2-1.15 {
  execsql {
    SELECT count(*) FROM t2;
    PRAGMA integrity_check;
  }







|







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
do_test journal2-1.13 {
  tvfs filter {xOpen xClose xDelete xWrite xTruncate}
  set ::tvfs_error_on_write 1
  catchsql { COMMIT } db2
} {1 {disk I/O error}}
db2 close
unset ::tvfs_error_on_write
forcecopy test.db testX.db

do_test journal2-1.14 { file exists test.db-journal } 1
do_test journal2-1.15 {
  execsql {
    SELECT count(*) FROM t2;
    PRAGMA integrity_check;
  }

Changes to test/journal3.test.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   2 00666
   3 00600
   4 00755
  } {
    db close
    set effective [format %.5o [expr $permissions & ~$umask]]
    do_test journal3-1.2.$tn.1 {
      catch { file delete -force test.db-journal }
      file attributes test.db -permissions $permissions
      file attributes test.db -permissions
    } $permissions
    do_test journal3-1.2.$tn.2 { file exists test.db-journal } {0}
    do_test journal3-1.2.$tn.3 {
      sqlite3 db test.db
      execsql { 







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   2 00666
   3 00600
   4 00755
  } {
    db close
    set effective [format %.5o [expr $permissions & ~$umask]]
    do_test journal3-1.2.$tn.1 {
      catch { forcedelete test.db-journal }
      file attributes test.db -permissions $permissions
      file attributes test.db -permissions
    } $permissions
    do_test journal3-1.2.$tn.2 { file exists test.db-journal } {0}
    do_test journal3-1.2.$tn.3 {
      sqlite3 db test.db
      execsql { 

Changes to test/jrnlmode.test.

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
      DETACH aux2;
      DETACH aux3;
    }
  } {}
}

ifcapable attach {
  file delete -force test2.db
  do_test jrnlmode-2.1 {
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA main.journal_mode = persist;
      PRAGMA aux.journal_mode = persist;
      CREATE TABLE abc(a, b, c);
      CREATE TABLE aux.def(d, e, f);







|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
      DETACH aux2;
      DETACH aux3;
    }
  } {}
}

ifcapable attach {
  forcedelete test2.db
  do_test jrnlmode-2.1 {
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA main.journal_mode = persist;
      PRAGMA aux.journal_mode = persist;
      CREATE TABLE abc(a, b, c);
      CREATE TABLE aux.def(d, e, f);
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    }
  } {4 5 6}

#----------------------------------------------------------------------
# Test caes jrnlmode-3.X verify that ticket #3127 has been fixed.
#
  db close
  file delete -force test2.db
  file delete -force test.db
  sqlite3 db test.db

  do_test jrnlmode-3.1 {
    execsql { 
      CREATE TABLE x(n INTEGER); 
      ATTACH 'test2.db' AS a; 
      create table a.x ( n integer ); 







|
|







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    }
  } {4 5 6}

#----------------------------------------------------------------------
# Test caes jrnlmode-3.X verify that ticket #3127 has been fixed.
#
  db close
  forcedelete test2.db
  forcedelete test.db
  sqlite3 db test.db

  do_test jrnlmode-3.1 {
    execsql { 
      CREATE TABLE x(n INTEGER); 
      ATTACH 'test2.db' AS a; 
      create table a.x ( n integer ); 
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
      COMMIT;
    }
  } {}
}

ifcapable autovacuum&&pragma {
  db close
  file delete -force test.db
  sqlite3 db test.db
  do_test jrnlmode-4.1 {
    execsql {
      PRAGMA cache_size = 1;
      PRAGMA auto_vacuum = 1;
      CREATE TABLE abc(a, b, c);
    }







|







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
      COMMIT;
    }
  } {}
}

ifcapable autovacuum&&pragma {
  db close
  forcedelete test.db
  sqlite3 db test.db
  do_test jrnlmode-4.1 {
    execsql {
      PRAGMA cache_size = 1;
      PRAGMA auto_vacuum = 1;
      CREATE TABLE abc(a, b, c);
    }
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
}

#------------------------------------------------------------------------
# The following test caes, jrnlmode-5.*, test the journal_size_limit
# pragma.
ifcapable pragma {
  db close
  file delete -force test.db test2.db test3.db
  sqlite3 db test.db

  do_test jrnlmode-5.1 {
    execsql {pragma page_size=1024}
    execsql {pragma journal_mode=persist}
  } {persist}








|







299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
}

#------------------------------------------------------------------------
# The following test caes, jrnlmode-5.*, test the journal_size_limit
# pragma.
ifcapable pragma {
  db close
  forcedelete test.db test2.db test3.db
  sqlite3 db test.db

  do_test jrnlmode-5.1 {
    execsql {pragma page_size=1024}
    execsql {pragma journal_mode=persist}
  } {persist}

507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
    } {0}
  }
}

ifcapable pragma {
  catch { db close }
  do_test jrnlmode-7.1 {
    foreach f [glob -nocomplain test.db*] { file delete -force $f }
    sqlite3 db test.db
    execsql {
      PRAGMA journal_mode = memory;
      PRAGMA auto_vacuum = 0;
      PRAGMA page_size = 1024;
      PRAGMA user_version = 5;
      PRAGMA user_version;







|







507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
    } {0}
  }
}

ifcapable pragma {
  catch { db close }
  do_test jrnlmode-7.1 {
    foreach f [glob -nocomplain test.db*] { forcedelete $f }
    sqlite3 db test.db
    execsql {
      PRAGMA journal_mode = memory;
      PRAGMA auto_vacuum = 0;
      PRAGMA page_size = 1024;
      PRAGMA user_version = 5;
      PRAGMA user_version;

Changes to test/jrnlmode2.test.

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
do_test jrnlmode2-2.4 {
  sqlite3 db2 test.db -readonly 1
  catchsql { SELECT * FROM t1 } db2
} {0 {1 2 3 4 5 6}}

do_test jrnlmode2-2.5 {
  db close
  file delete test.db-journal
} {}
do_test jrnlmode2-2.6 {
  sqlite3 db2 test.db -readonly 1
  catchsql { SELECT * FROM t1 } db2
} {0 {1 2 3 4 5 6}}

catch { db2 close }







|







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
do_test jrnlmode2-2.4 {
  sqlite3 db2 test.db -readonly 1
  catchsql { SELECT * FROM t1 } db2
} {0 {1 2 3 4 5 6}}

do_test jrnlmode2-2.5 {
  db close
  delete_file test.db-journal
} {}
do_test jrnlmode2-2.6 {
  sqlite3 db2 test.db -readonly 1
  catchsql { SELECT * FROM t1 } db2
} {0 {1 2 3 4 5 6}}

catch { db2 close }

Changes to test/jrnlmode3.test.

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    INSERT INTO t1 VALUES(2);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {1}

db close
file delete -force test.db test.db-journal
sqlite3 db test.db

do_test jrnlmode3-2.1 {
  db eval {
    PRAGMA locking_mode=EXCLUSIVE;
    PRAGMA journal_mode=OFF;
    CREATE TABLE t1(x);







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    INSERT INTO t1 VALUES(2);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {1}

db close
forcedelete test.db test.db-journal
sqlite3 db test.db

do_test jrnlmode3-2.1 {
  db eval {
    PRAGMA locking_mode=EXCLUSIVE;
    PRAGMA journal_mode=OFF;
    CREATE TABLE t1(x);
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    # Skip the no-change cases
    if {$fromjmode==$tojmode} continue
    incr cnt

    # Start with a fresh database connection an empty database file.
    #
    db close
    file delete -force test.db test.db-journal
    sqlite3 db test.db

    # Initialize the journal mode.
    #
    do_test jrnlmode3-3.$cnt.1-($fromjmode-to-$tojmode) {
      db eval "PRAGMA journal_mode = $fromjmode;"
    } $fromjmode







|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    # Skip the no-change cases
    if {$fromjmode==$tojmode} continue
    incr cnt

    # Start with a fresh database connection an empty database file.
    #
    db close
    forcedelete test.db test.db-journal
    sqlite3 db test.db

    # Initialize the journal mode.
    #
    do_test jrnlmode3-3.$cnt.1-($fromjmode-to-$tojmode) {
      db eval "PRAGMA journal_mode = $fromjmode;"
    } $fromjmode

Changes to test/loadext.test.

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
db2 close
sqlite3 db test.db
sqlite3_enable_load_extension db 1

# Try to load an extension for which the file does not exist.
#
do_test loadext-2.1 {
  file delete -force ${testextension}xx
  set rc [catch {
    sqlite3_load_extension db "${testextension}xx"
  } msg]
  list $rc $msg
} [list 1 [format $dlerror_nosuchfile ${testextension}xx]]

# Try to load an extension for which the file is not a shared object







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
db2 close
sqlite3 db test.db
sqlite3_enable_load_extension db 1

# Try to load an extension for which the file does not exist.
#
do_test loadext-2.1 {
  forcedelete ${testextension}xx
  set rc [catch {
    sqlite3_load_extension db "${testextension}xx"
  } msg]
  list $rc $msg
} [list 1 [format $dlerror_nosuchfile ${testextension}xx]]

# Try to load an extension for which the file is not a shared object

Changes to test/lock4.test.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Initialize the test.db database so that it is non-empty
#
do_test lock4-1.1 {
  db eval {
     PRAGMA auto_vacuum=OFF;
     CREATE TABLE t1(x);
  }
  file delete -force test2.db test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {
     PRAGMA auto_vacuum=OFF;
     CREATE TABLE t2(x)
  }
  db2 close
  list [file size test.db] [file size test2.db]







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Initialize the test.db database so that it is non-empty
#
do_test lock4-1.1 {
  db eval {
     PRAGMA auto_vacuum=OFF;
     CREATE TABLE t1(x);
  }
  forcedelete test2.db test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {
     PRAGMA auto_vacuum=OFF;
     CREATE TABLE t2(x)
  }
  db2 close
  list [file size test.db] [file size test2.db]

Changes to test/lock5.test.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# SQLITE_ENABLE_LOCKING_STYLE macro.
db close
if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
  finish_test
  return
}
db close
file delete -force test.db.lock

ifcapable lock_proxy_pragmas {
  set ::using_proxy 0
  foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
    set ::using_proxy $value
  }
  # Disable the proxy locking for these tests







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# SQLITE_ENABLE_LOCKING_STYLE macro.
db close
if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
  finish_test
  return
}
db close
forcedelete test.db.lock

ifcapable lock_proxy_pragmas {
  set ::using_proxy 0
  foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
    set ::using_proxy $value
  }
  # Disable the proxy locking for these tests
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  execsql {BEGIN EXCLUSIVE}
  db close
  file exists test.db.lock
} {0}

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

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

do_test lock5-flock.1 {
  sqlite3 db test.db -vfs unix-flock







|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  execsql {BEGIN EXCLUSIVE}
  db close
  file exists test.db.lock
} {0}

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

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

do_test lock5-flock.1 {
  sqlite3 db test.db -vfs unix-flock

Changes to test/main.test.

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


# Try to open a database with a corrupt database file.
#
if {[permutation] == ""} {
  do_test main-2.0 {
    catch {db close}
    file delete -force test.db
    set fd [open test.db w]
    puts $fd hi!
    close $fd
    set v [catch {sqlite3 db test.db} msg]
    if {$v} {lappend v $msg} {lappend v {}}
  } {0 {}}
}

# Here are some tests for tokenize.c.  
#
do_test main-3.1 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
  file delete -force testdb
  sqlite3 db testdb
  set v [catch {execsql {SELECT * from T1 where x!!5}} msg]
  lappend v $msg
} {1 {unrecognized token: "!!"}}
do_test main-3.2 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
  file delete -force testdb
  sqlite3 db testdb
  set v [catch {execsql {SELECT * from T1 where ^x}} msg]
  lappend v $msg
} {1 {unrecognized token: "^"}}
do_test main-3.2.2 {
  catchsql {select 'abc}
} {1 {unrecognized token: "'abc"}}







|












|
|






|
|







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


# Try to open a database with a corrupt database file.
#
if {[permutation] == ""} {
  do_test main-2.0 {
    catch {db close}
    forcedelete test.db
    set fd [open test.db w]
    puts $fd hi!
    close $fd
    set v [catch {sqlite3 db test.db} msg]
    if {$v} {lappend v $msg} {lappend v {}}
  } {0 {}}
}

# Here are some tests for tokenize.c.  
#
do_test main-3.1 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {forcedelete $f}
  forcedelete testdb
  sqlite3 db testdb
  set v [catch {execsql {SELECT * from T1 where x!!5}} msg]
  lappend v $msg
} {1 {unrecognized token: "!!"}}
do_test main-3.2 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {forcedelete $f}
  forcedelete testdb
  sqlite3 db testdb
  set v [catch {execsql {SELECT * from T1 where ^x}} msg]
  lappend v $msg
} {1 {unrecognized token: "^"}}
do_test main-3.2.2 {
  catchsql {select 'abc}
} {1 {unrecognized token: "'abc"}}
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
do_test main-3.2.30 {
  catchsql {select 123--5}
} {0 123}


do_test main-3.3 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
  file delete -force testdb
  sqlite3 db testdb
  execsql {
    create table T1(X REAL);  /* C-style comments allowed */
    insert into T1 values(0.5);
    insert into T1 values(0.5e2);
    insert into T1 values(0.5e-002);
    insert into T1 values(5e-002);







|
|







438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
do_test main-3.2.30 {
  catchsql {select 123--5}
} {0 123}


do_test main-3.3 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {forcedelete $f}
  forcedelete testdb
  sqlite3 db testdb
  execsql {
    create table T1(X REAL);  /* C-style comments allowed */
    insert into T1 values(0.5);
    insert into T1 values(0.5e2);
    insert into T1 values(0.5e-002);
    insert into T1 values(5e-002);

Changes to test/malloc.test.

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
}

# This block tests malloc() failures that occur while opening a 
# connection to a database.
do_malloc_test 10 -tclprep {
  catch {db2 close}
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  sqlite3_extended_result_codes db 1
  db eval {CREATE TABLE abc(a, b, c)}
} -tclbody {
  db close
  sqlite3 db2 test.db
  sqlite3_extended_result_codes db2 1







|







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
}

# This block tests malloc() failures that occur while opening a 
# connection to a database.
do_malloc_test 10 -tclprep {
  catch {db2 close}
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  sqlite3_extended_result_codes db 1
  db eval {CREATE TABLE abc(a, b, c)}
} -tclbody {
  db close
  sqlite3 db2 test.db
  sqlite3_extended_result_codes db2 1
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
      PRAGMA journal_mode = DELETE;    /* For inmemory_journal permutation */
      PRAGMA synchronous = 0;
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 2);
      BEGIN;
      INSERT INTO t1 VALUES(3, 4);
    }
    copy_file test2.db test.db
    copy_file test2.db-journal test.db-journal
    db2 close
  } -tclbody {
    sqlite3 db test.db
    sqlite3_extended_result_codes db 1

    # If an out-of-memory occurs within a call to a VFS layer function during
    # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit







|
|







337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
      PRAGMA journal_mode = DELETE;    /* For inmemory_journal permutation */
      PRAGMA synchronous = 0;
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 2);
      BEGIN;
      INSERT INTO t1 VALUES(3, 4);
    }
    forcecopy test2.db test.db
    forcecopy test2.db-journal test.db-journal
    db2 close
  } -tclbody {
    sqlite3 db test.db
    sqlite3_extended_result_codes db 1

    # If an out-of-memory occurs within a call to a VFS layer function during
    # hot-journal rollback, sqlite will report SQLITE_CORRUPT. See commit
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509

# Make sure SQLITE_NOMEM is reported out on an ATTACH failure even
# when the malloc failure occurs within the nested parse.
#
ifcapable attach {
  do_malloc_test 20 -tclprep {
    db close
    file delete -force test2.db test2.db-journal
    sqlite3 db test2.db
    sqlite3_extended_result_codes db 1
    db eval {CREATE TABLE t1(x);}
    db close
  } -tclbody {
    if {[catch {sqlite3 db test.db}]} {
      error "out of memory"







|







495
496
497
498
499
500
501
502
503
504
505
506
507
508
509

# Make sure SQLITE_NOMEM is reported out on an ATTACH failure even
# when the malloc failure occurs within the nested parse.
#
ifcapable attach {
  do_malloc_test 20 -tclprep {
    db close
    forcedelete test2.db test2.db-journal
    sqlite3 db test2.db
    sqlite3_extended_result_codes db 1
    db eval {CREATE TABLE t1(x);}
    db close
  } -tclbody {
    if {[catch {sqlite3 db test.db}]} {
      error "out of memory"

Changes to test/malloc3.test.

459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
      SELECT * FROM v1 WHERE d = g;
    }
  } {a b c a b c 1 2 3 1 2 3}
}

# Test a simple multi-file transaction 
#
file delete -force test2.db
ifcapable attach {
  SQL {ATTACH 'test2.db' AS aux;}
  SQL {BEGIN}
  SQL {CREATE TABLE aux.tbl2(x, y, z)}
  SQL {INSERT INTO tbl2 VALUES(1, 2, 3)}
  SQL {INSERT INTO def VALUES(4, 5, 6)}
  TEST 30 {







|







459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
      SELECT * FROM v1 WHERE d = g;
    }
  } {a b c a b c 1 2 3 1 2 3}
}

# Test a simple multi-file transaction 
#
forcedelete test2.db
ifcapable attach {
  SQL {ATTACH 'test2.db' AS aux;}
  SQL {BEGIN}
  SQL {CREATE TABLE aux.tbl2(x, y, z)}
  SQL {INSERT INTO tbl2 VALUES(1, 2, 3)}
  SQL {INSERT INTO def VALUES(4, 5, 6)}
  TEST 30 {
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
# run the tests with "persistent" malloc failures.
sqlite3_extended_result_codes db 1
db cache size 0
run_test $::run_test_script 1

# Close and reopen the db.
db close
file delete -force test.db test.db-journal test2.db test2.db-journal
sqlite3 db test.db
sqlite3_extended_result_codes db 1
set ::DB [sqlite3_connection_pointer db]

# Turn off the Tcl interface's prepared statement caching facility in
# the new connnection. Then run the tests with "transient" malloc failures.
db cache size 0
run_test $::run_test_script 0

sqlite3_memdebug_fail -1
finish_test







|











646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
# run the tests with "persistent" malloc failures.
sqlite3_extended_result_codes db 1
db cache size 0
run_test $::run_test_script 1

# Close and reopen the db.
db close
forcedelete test.db test.db-journal test2.db test2.db-journal
sqlite3 db test.db
sqlite3_extended_result_codes db 1
set ::DB [sqlite3_connection_pointer db]

# Turn off the Tcl interface's prepared statement caching facility in
# the new connnection. Then run the tests with "transient" malloc failures.
db cache size 0
run_test $::run_test_script 0

sqlite3_memdebug_fail -1
finish_test

Changes to test/malloc5.test.

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#
proc nPage {db} {
  set bt [btree_from_db $db]
  array set stats [btree_pager_stats $bt]
  set stats(page)
}
db close
file delete -force test.db test.db-journal test2.db test2.db-journal

# This block of test-cases (malloc5-6.1.*) prepares two database files
# for the subsequent tests.
do_test malloc5-6.1.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size=1024;







|







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#
proc nPage {db} {
  set bt [btree_from_db $db]
  array set stats [btree_pager_stats $bt]
  set stats(page)
}
db close
forcedelete test.db test.db-journal test2.db test2.db-journal

# This block of test-cases (malloc5-6.1.*) prepares two database files
# for the subsequent tests.
do_test malloc5-6.1.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size=1024;
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    COMMIT;
  } 
  copy_file test.db test2.db
  sqlite3 db2 test2.db
  list \
    [expr ([file size test.db]/1024)>20] [expr ([file size test2.db]/1024)>20]
} {1 1}
do_test malloc5-6.1.2 {
  list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2]
} {10 10}







|







300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    COMMIT;
  } 
  forcecopy test.db test2.db
  sqlite3 db2 test2.db
  list \
    [expr ([file size test.db]/1024)>20] [expr ([file size test2.db]/1024)>20]
} {1 1}
do_test malloc5-6.1.2 {
  list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2]
} {10 10}

Changes to test/mallocA.test.

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
   finish_test
   return
}


# Construct a test database
#
file delete -force test.db.bu
db eval {
  CREATE TABLE t1(a COLLATE NOCASE,b,c);
  INSERT INTO t1 VALUES(1,2,3);
  INSERT INTO t1 VALUES(1,2,4);
  INSERT INTO t1 VALUES(2,3,4);
  CREATE INDEX t1i1 ON t1(a);
  CREATE INDEX t1i2 ON t1(b,c);
  CREATE TABLE t2(x,y,z);
}
db close
file copy test.db test.db.bu


do_malloc_test mallocA-1 -testdb test.db.bu -sqlbody {
  ANALYZE
}
do_malloc_test mallocA-1.1 -testdb test.db.bu -sqlbody {
  ANALYZE t1







|










|







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
   finish_test
   return
}


# Construct a test database
#
forcedelete test.db.bu
db eval {
  CREATE TABLE t1(a COLLATE NOCASE,b,c);
  INSERT INTO t1 VALUES(1,2,3);
  INSERT INTO t1 VALUES(1,2,4);
  INSERT INTO t1 VALUES(2,3,4);
  CREATE INDEX t1i1 ON t1(a);
  CREATE INDEX t1i2 ON t1(b,c);
  CREATE TABLE t2(x,y,z);
}
db close
copy_file test.db test.db.bu


do_malloc_test mallocA-1 -testdb test.db.bu -sqlbody {
  ANALYZE
}
do_malloc_test mallocA-1.1 -testdb test.db.bu -sqlbody {
  ANALYZE t1
70
71
72
73
74
75
76
77
78

# Ensure that no file descriptors were leaked.
do_test malloc-99.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

file delete -force test.db.bu
finish_test







|

70
71
72
73
74
75
76
77
78

# Ensure that no file descriptors were leaked.
do_test malloc-99.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

forcedelete test.db.bu
finish_test

Changes to test/malloc_common.tcl.

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
      # fails and then subsequent calls succeed. If $::iRepeat is 1, 
      # then the failure is persistent - once malloc() fails it keeps
      # failing.
      #
      set zRepeat "transient"
      if {$::iRepeat} {set zRepeat "persistent"}
      restore_prng_state
      foreach file [glob -nocomplain test.db-mj*] {file delete -force $file}

      do_test ${tn}.${zRepeat}.${::n} {
  
        # Remove all traces of database files test.db and test2.db 
        # from the file-system. Then open (empty database) "test.db" 
        # with the handle [db].
        # 
        catch {db close} 
        catch {db2 close} 
        forcedelete test.db
        forcedelete test.db-journal
        forcedelete test.db-wal
        forcedelete test2.db
        forcedelete test2.db-journal
        forcedelete test2.db-wal
        if {[info exists ::mallocopts(-testdb)]} {
          file copy $::mallocopts(-testdb) test.db
        }
        catch { sqlite3 db test.db }
        if {[info commands db] ne ""} {
          sqlite3_extended_result_codes db 1
        }
        sqlite3_db_config_lookaside db 0 0 0
  







|
















|







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
      # fails and then subsequent calls succeed. If $::iRepeat is 1, 
      # then the failure is persistent - once malloc() fails it keeps
      # failing.
      #
      set zRepeat "transient"
      if {$::iRepeat} {set zRepeat "persistent"}
      restore_prng_state
      foreach file [glob -nocomplain test.db-mj*] {forcedelete $file}

      do_test ${tn}.${zRepeat}.${::n} {
  
        # Remove all traces of database files test.db and test2.db 
        # from the file-system. Then open (empty database) "test.db" 
        # with the handle [db].
        # 
        catch {db close} 
        catch {db2 close} 
        forcedelete test.db
        forcedelete test.db-journal
        forcedelete test.db-wal
        forcedelete test2.db
        forcedelete test2.db-journal
        forcedelete test2.db-wal
        if {[info exists ::mallocopts(-testdb)]} {
          copy_file $::mallocopts(-testdb) test.db
        }
        catch { sqlite3 db test.db }
        if {[info commands db] ne ""} {
          sqlite3_extended_result_codes db 1
        }
        sqlite3_db_config_lookaside db 0 0 0
  

Changes to test/manydb.test.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
    lappend filehandles [open testfile.1 w]
  }
}
foreach fd $filehandles {
  close $fd
}
catch {
  file delete -force testfile.1
}
set N [expr $i / $num_fd_per_openwrite_db]

# Create a bunch of random database names
#
unset -nocomplain dbname
unset -nocomplain used







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
    lappend filehandles [open testfile.1 w]
  }
}
foreach fd $filehandles {
  close $fd
}
catch {
  forcedelete testfile.1
}
set N [expr $i / $num_fd_per_openwrite_db]

# Create a bunch of random database names
#
unset -nocomplain dbname
unset -nocomplain used
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102


# Close the databases and erase the files.
#
for {set i 0} {$i<$N} {incr i} {
  do_test manydb-3.$i {
    db$i close
    file delete -force $dbname($i)
  } {}
}




finish_test







|







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102


# Close the databases and erase the files.
#
for {set i 0} {$i<$N} {incr i} {
  do_test manydb-3.$i {
    db$i close
    forcedelete $dbname($i)
  } {}
}




finish_test

Changes to test/memsubsys1.test.

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# This procedure constructs a new database in test.db.  It fills
# this database with many small records (enough to force multiple
# rebalance operations in the btree-layer and to require a large
# page cache), verifies correct results, then returns.
#
proc build_test_db {testname pragmas} {
  catch {db close}
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  sqlite3_db_config_lookaside db 0 0 0
  db eval $pragmas
  db eval {
    CREATE TABLE t1(x, y);
    CREATE TABLE t2(a, b);
    CREATE INDEX i1 ON t1(x,y);







|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# This procedure constructs a new database in test.db.  It fills
# this database with many small records (enough to force multiple
# rebalance operations in the btree-layer and to require a large
# page cache), verifies correct results, then returns.
#
proc build_test_db {testname pragmas} {
  catch {db close}
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  sqlite3_db_config_lookaside db 0 0 0
  db eval $pragmas
  db eval {
    CREATE TABLE t1(x, y);
    CREATE TABLE t2(a, b);
    CREATE INDEX i1 ON t1(x,y);

Changes to test/memsubsys2.test.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# This procedure constructs a new database in test.db.  It fills
# this database with many small records (enough to force multiple
# rebalance operations in the btree-layer and to require a large
# page cache), verifies correct results, then returns.
#
proc build_test_db {testname pragmas} {
  catch {db close}
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  db eval $pragmas
  db eval {
    CREATE TABLE t1(x, y);
    CREATE TABLE t2(a, b);
    CREATE INDEX i1 ON t1(x,y);
    INSERT INTO t1 VALUES(1, 100);







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# This procedure constructs a new database in test.db.  It fills
# this database with many small records (enough to force multiple
# rebalance operations in the btree-layer and to require a large
# page cache), verifies correct results, then returns.
#
proc build_test_db {testname pragmas} {
  catch {db close}
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  db eval $pragmas
  db eval {
    CREATE TABLE t1(x, y);
    CREATE TABLE t2(a, b);
    CREATE INDEX i1 ON t1(x,y);
    INSERT INTO t1 VALUES(1, 100);

Changes to test/misc1.test.

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
} {0}
do_test misc1-14.2b {
  execsql {UPDATE t1 SET a=a||'y' WHERE 1}
  file exists ../test.db-journal
} {1}
do_test misc1-14.3 {
  cd ..
  file delete -force tempdir
  execsql {COMMIT}
  file exists ./test.db-journal
} {0}

# A failed create table should not leave the table in the internal
# data structures.  Ticket #238.
#







|







487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
} {0}
do_test misc1-14.2b {
  execsql {UPDATE t1 SET a=a||'y' WHERE 1}
  file exists ../test.db-journal
} {1}
do_test misc1-14.3 {
  cd ..
  forcedelete tempdir
  execsql {COMMIT}
  file exists ./test.db-journal
} {0}

# A failed create table should not leave the table in the internal
# data structures.  Ticket #238.
#

Changes to test/misc2.test.

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#
# 2006-08-16:  This has changed.  It is now permitted to update
# the table being SELECTed from within the callback of the query.
#
ifcapable tclvar {
  do_test misc2-7.1 {
    db close
    file delete -force test.db
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES(1);
      INSERT INTO t1 VALUES(2);
      INSERT INTO t1 VALUES(3);
      SELECT * FROM t1;







|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#
# 2006-08-16:  This has changed.  It is now permitted to update
# the table being SELECTed from within the callback of the query.
#
ifcapable tclvar {
  do_test misc2-7.1 {
    db close
    forcedelete test.db
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES(1);
      INSERT INTO t1 VALUES(2);
      INSERT INTO t1 VALUES(3);
      SELECT * FROM t1;
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  
  # Repeat the tests 7.1 through 7.8 about but this time do the SELECTs
  # in reverse order so that we exercise the sqlite3BtreePrev() routine
  # instead of sqlite3BtreeNext()
  #
  do_test misc2-7.11 {
    db close
    file delete -force test.db
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES(1);
      INSERT INTO t1 VALUES(2);
      INSERT INTO t1 VALUES(3);
      SELECT * FROM t1;







|







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  
  # Repeat the tests 7.1 through 7.8 about but this time do the SELECTs
  # in reverse order so that we exercise the sqlite3BtreePrev() routine
  # instead of sqlite3BtreeNext()
  #
  do_test misc2-7.11 {
    db close
    forcedelete test.db
    sqlite3 db test.db
    execsql {
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES(1);
      INSERT INTO t1 VALUES(2);
      INSERT INTO t1 VALUES(3);
      SELECT * FROM t1;
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
      }
    }
    execsql {SELECT * FROM t1}
  } {1 2 3 4 5 6 7 8 9 10}
}

db close
file delete -force test.db
sqlite3 db test.db
catchsql { pragma recursive_triggers = off } 

# Ticket #453.  If the SQL ended with "-", the tokenizer was calling that
# an incomplete token, which caused problem.  The solution was to just call
# it a minus sign.
#







|







357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
      }
    }
    execsql {SELECT * FROM t1}
  } {1 2 3 4 5 6 7 8 9 10}
}

db close
forcedelete test.db
sqlite3 db test.db
catchsql { pragma recursive_triggers = off } 

# Ticket #453.  If the SQL ended with "-", the tokenizer was calling that
# an incomplete token, which caused problem.  The solution was to just call
# it a minus sign.
#

Changes to test/misc5.test.

510
511
512
513
514
515
516
517
518
519
520
521
522
523
524

# Ticket #1370.  Do not overwrite small files (less than 1024 bytes)
# when trying to open them as a database.
#
if {[permutation] == ""} {
  do_test misc5-4.1 {
    db close
    file delete -force test.db
    set fd [open test.db w]
    puts $fd "This is not really a database"
    close $fd
    sqlite3 db test.db
    catchsql {
      CREATE TABLE t1(a,b,c);
    }







|







510
511
512
513
514
515
516
517
518
519
520
521
522
523
524

# Ticket #1370.  Do not overwrite small files (less than 1024 bytes)
# when trying to open them as a database.
#
if {[permutation] == ""} {
  do_test misc5-4.1 {
    db close
    forcedelete test.db
    set fd [open test.db w]
    puts $fd "This is not really a database"
    close $fd
    sqlite3 db test.db
    catchsql {
      CREATE TABLE t1(a,b,c);
    }
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  execsql {SELECT .4e+1}
} 4.0

# Ticket #1582.  Ensure that an unknown table in a LIMIT clause applied to
# a UNION ALL query causes an error, not a crash.
#
db close
file delete -force test.db
sqlite3 db test.db
ifcapable subquery&&compound {
  do_test misc5-6.1 {
    catchsql {
      SELECT * FROM sqlite_master 
      UNION ALL 
      SELECT * FROM sqlite_master







|







540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  execsql {SELECT .4e+1}
} 4.0

# Ticket #1582.  Ensure that an unknown table in a LIMIT clause applied to
# a UNION ALL query causes an error, not a crash.
#
db close
forcedelete test.db
sqlite3 db test.db
ifcapable subquery&&compound {
  do_test misc5-6.1 {
    catchsql {
      SELECT * FROM sqlite_master 
      UNION ALL 
      SELECT * FROM sqlite_master

Changes to test/misc7.test.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
do_test misc7-3 {
  c_collation_test
} {}

# Try to open a directory:
#
do_test misc7-4 {
  file delete mydir
  file mkdir mydir
  set rc [catch {
    sqlite3 db2 ./mydir
  } msg]
  list $rc $msg
} {1 {unable to open database file}}

# Try to open a file with a directory where its journal file should be.
#
do_test misc7-5 {
  file delete mydir
  file mkdir mydir-journal
  sqlite3 db2 ./mydir
  catchsql {
    CREATE TABLE abc(a, b, c);
  } db2
} {1 {unable to open database file}}
db2 close







|










|







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
do_test misc7-3 {
  c_collation_test
} {}

# Try to open a directory:
#
do_test misc7-4 {
  delete_file mydir
  file mkdir mydir
  set rc [catch {
    sqlite3 db2 ./mydir
  } msg]
  list $rc $msg
} {1 {unable to open database file}}

# Try to open a file with a directory where its journal file should be.
#
do_test misc7-5 {
  delete_file mydir
  file mkdir mydir-journal
  sqlite3 db2 ./mydir
  catchsql {
    CREATE TABLE abc(a, b, c);
  } db2
} {1 {unable to open database file}}
db2 close
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
db2 close

#--------------------------------------------------------------------
# Test that nothing goes horribly wrong when attaching a database
# after the omit_readlock pragma has been exercised.
#
do_test misc7-7.1 {
  file delete -force test2.db
  file delete -force test2.db-journal
  execsql {
    PRAGMA omit_readlock = 1;
    ATTACH 'test2.db' AS aux;
    CREATE TABLE aux.hello(world);
    SELECT name FROM aux.sqlite_master;
  }
} {hello}







|
|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
db2 close

#--------------------------------------------------------------------
# Test that nothing goes horribly wrong when attaching a database
# after the omit_readlock pragma has been exercised.
#
do_test misc7-7.1 {
  forcedelete test2.db
  forcedelete test2.db-journal
  execsql {
    PRAGMA omit_readlock = 1;
    ATTACH 'test2.db' AS aux;
    CREATE TABLE aux.hello(world);
    SELECT name FROM aux.sqlite_master;
  }
} {hello}
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    set ::echo_module_cost 2.0e+99
    execsql {SELECT * FROM t1 WHERE a = 1;}
  } {1 2 3}
  unset ::echo_module_cost
}

db close
file delete -force test.db
file delete -force test.db-journal
sqlite3 db test.db

ifcapable explain {
  do_execsql_test misc7-14.1 {
    CREATE TABLE abc(a PRIMARY KEY, b, c);
    EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 WHERE rowid = 1;
  } {







|
|







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    set ::echo_module_cost 2.0e+99
    execsql {SELECT * FROM t1 WHERE a = 1;}
  } {1 2 3}
  unset ::echo_module_cost
}

db close
forcedelete test.db
forcedelete test.db-journal
sqlite3 db test.db

ifcapable explain {
  do_execsql_test misc7-14.1 {
    CREATE TABLE abc(a PRIMARY KEY, b, c);
    EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 WHERE rowid = 1;
  } {
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
    EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 ORDER BY a;
  } {0 0 0 
     {SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (~1000000 rows)}
  }
}

db close
file delete -force test.db
file delete -force test.db-journal
sqlite3 db test.db

#--------------------------------------------------------------------
# This is all to force the pager_remove_from_stmt_list() function
# (inside pager.c) to remove a pager from the middle of the
# statement-list.
#







|
|







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
    EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 ORDER BY a;
  } {0 0 0 
     {SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (~1000000 rows)}
  }
}

db close
forcedelete test.db
forcedelete test.db-journal
sqlite3 db test.db

#--------------------------------------------------------------------
# This is all to force the pager_remove_from_stmt_list() function
# (inside pager.c) to remove a pager from the middle of the
# statement-list.
#
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
    DELETE FROM abc WHERE rowid > 12;
    INSERT INTO abc SELECT 
            randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
  }
} {}

db close
file delete -force test.db
file delete -force test.db-journal
sqlite3 db test.db

do_ioerr_test misc7-16 -sqlprep {
   PRAGMA cache_size = 10;
   PRAGMA default_cache_size = 10;
   CREATE TABLE t3(a, b, UNIQUE(a, b));
   INSERT INTO t3 VALUES( randstr(100, 100), randstr(100, 100) );







|
|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
    DELETE FROM abc WHERE rowid > 12;
    INSERT INTO abc SELECT 
            randstr(100,100), randstr(100,100), randstr(100,100) FROM abc;
  }
} {}

db close
forcedelete test.db
forcedelete test.db-journal
sqlite3 db test.db

do_ioerr_test misc7-16 -sqlprep {
   PRAGMA cache_size = 10;
   PRAGMA default_cache_size = 10;
   CREATE TABLE t3(a, b, UNIQUE(a, b));
   INSERT INTO t3 VALUES( randstr(100, 100), randstr(100, 100) );
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  if {[file attributes test.db -permissions]==0644} {

    do_test misc7-17.1 {
      execsql {
        BEGIN;
        DELETE FROM t3 WHERE (oid%3)==0;
      }
      copy_file test.db bak.db
      copy_file test.db-journal bak.db-journal
      execsql {
        COMMIT;
      }
    
      db close
      copy_file bak.db test.db
      copy_file bak.db-journal test.db-journal
      sqlite3 db test.db
    
      catch {file attributes test.db-journal -permissions r--------}
      catch {file attributes test.db-journal -readonly 1}
      catchsql {
        SELECT count(*) FROM t3;
      }







|
|





|
|







381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  if {[file attributes test.db -permissions]==0644} {

    do_test misc7-17.1 {
      execsql {
        BEGIN;
        DELETE FROM t3 WHERE (oid%3)==0;
      }
      forcecopy test.db bak.db
      forcecopy test.db-journal bak.db-journal
      execsql {
        COMMIT;
      }
    
      db close
      forcecopy bak.db test.db
      forcecopy bak.db-journal test.db-journal
      sqlite3 db test.db
    
      catch {file attributes test.db-journal -permissions r--------}
      catch {file attributes test.db-journal -readonly 1}
      catchsql {
        SELECT count(*) FROM t3;
      }
480
481
482
483
484
485
486
487
488
489
  set zFile [file join [pwd] "[string repeat abcde 104].db"]
  set rc [catch {sqlite3 db2 $zFile} msg]
  list $rc $msg
} {1 {unable to open database file}}


db close
file delete -force test.db

finish_test







|


480
481
482
483
484
485
486
487
488
489
  set zFile [file join [pwd] "[string repeat abcde 104].db"]
  set rc [catch {sqlite3 db2 $zFile} msg]
  list $rc $msg
} {1 {unable to open database file}}


db close
forcedelete test.db

finish_test

Changes to test/misuse.test.

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


# Make sure the test logic works
#
do_test misuse-1.1 {
  db close
  catch {file delete -force test2.db}
  catch {file delete -force test2.db-journal}
  sqlite3 db test2.db; set ::DB [sqlite3_connection_pointer db]
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
  }
  catchsql2 {
    SELECT * FROM t1







|
|







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


# Make sure the test logic works
#
do_test misuse-1.1 {
  db close
  catch {forcedelete test2.db}
  catch {forcedelete test2.db-journal}
  sqlite3 db test2.db; set ::DB [sqlite3_connection_pointer db]
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
  }
  catchsql2 {
    SELECT * FROM t1

Changes to test/multiplex.test.

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#
#   multiplex-2.7.*: Disable/enable tests.
#

sqlite3_multiplex_initialize "" 1
multiplex_set db main 32768 16

file delete -force test.x
do_test multiplex-2.1.2 {
  sqlite3 db test.x
  execsql {
    PRAGMA page_size=1024;
    PRAGMA auto_vacuum=OFF;
    PRAGMA journal_mode=DELETE;
  }







|







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#
#   multiplex-2.7.*: Disable/enable tests.
#

sqlite3_multiplex_initialize "" 1
multiplex_set db main 32768 16

forcedelete test.x
do_test multiplex-2.1.2 {
  sqlite3 db test.x
  execsql {
    PRAGMA page_size=1024;
    PRAGMA auto_vacuum=OFF;
    PRAGMA journal_mode=DELETE;
  }
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524

do_test multiplex-5.4.1 {
  catch { db close }
  multiplex_delete test.db
  file mkdir test.db
  list [catch { sqlite3 db test.db } msg] $msg
} {1 {unable to open database file}}
catch { file delete test.db }

do_faultsim_test multiplex-5.5 -prep {
  catch { sqlite3_multiplex_shutdown }
} -body {
  sqlite3_multiplex_initialize "" 1
  multiplex_set db main 32768 16
}







|







510
511
512
513
514
515
516
517
518
519
520
521
522
523
524

do_test multiplex-5.4.1 {
  catch { db close }
  multiplex_delete test.db
  file mkdir test.db
  list [catch { sqlite3 db test.db } msg] $msg
} {1 {unable to open database file}}
catch { delete_file test.db }

do_faultsim_test multiplex-5.5 -prep {
  catch { sqlite3_multiplex_shutdown }
} -body {
  sqlite3_multiplex_initialize "" 1
  multiplex_set db main 32768 16
}

Changes to test/notify1.test.

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#
# Test for slightly more complex deadlock involving three database
# connections: db, db2 and db3.
#
do_test notify1-2.3.1 {
  db close
  db2 close
  file delete -force test.db test2.db test3.db
  foreach con {db db2 db3} {
    sqlite3 $con test.db
    $con eval { ATTACH 'test2.db' AS aux2 }
    $con eval { ATTACH 'test3.db' AS aux3 }
  }
  execsql {
    CREATE TABLE main.t1(a, b);







|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#
# Test for slightly more complex deadlock involving three database
# connections: db, db2 and db3.
#
do_test notify1-2.3.1 {
  db close
  db2 close
  forcedelete test.db test2.db test3.db
  foreach con {db db2 db3} {
    sqlite3 $con test.db
    $con eval { ATTACH 'test2.db' AS aux2 }
    $con eval { ATTACH 'test3.db' AS aux3 }
  }
  execsql {
    CREATE TABLE main.t1(a, b);
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#
#   notify1-6.4.*: Like 6.3.*, except that instead of the second blocker
#                  committing its transaction, the first does. The 
#                  unlock-notify callback is therefore invoked.
#
db close
do_test notify1-6.1.1 {
  file delete -force test.db test2.db
  foreach conn {db db2 db3} {
    sqlite3 $conn test.db
    execsql { ATTACH 'test2.db' AS two } $conn
  }
  execsql {
    CREATE TABLE t1(a, b);
    CREATE TABLE two.t2(a, b);







|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#
#   notify1-6.4.*: Like 6.3.*, except that instead of the second blocker
#                  committing its transaction, the first does. The 
#                  unlock-notify callback is therefore invoked.
#
db close
do_test notify1-6.1.1 {
  forcedelete test.db test2.db
  foreach conn {db db2 db3} {
    sqlite3 $conn test.db
    execsql { ATTACH 'test2.db' AS two } $conn
  }
  execsql {
    CREATE TABLE t1(a, b);
    CREATE TABLE two.t2(a, b);

Changes to test/notify2.test.

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  expr 0
}

foreach {iTest xStep xPrepare} {
  1 sqlite3_blocking_step sqlite3_blocking_prepare_v2
  2 sqlite3_step          sqlite3_nonblocking_prepare_v2
} {
  file delete -force test.db test2.db test3.db

  set ThreadSetup "set xStep $xStep;set xPrepare $xPrepare;set nSecond $nSecond"

  # Set up the database schema used by this test. Each thread opens file
  # test.db as the main database, then attaches files test2.db and test3.db
  # as auxillary databases. Each file contains a single table (t1, t2 and t3, in
  # files test.db, test2.db and test3.db, respectively). 







|







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  expr 0
}

foreach {iTest xStep xPrepare} {
  1 sqlite3_blocking_step sqlite3_blocking_prepare_v2
  2 sqlite3_step          sqlite3_nonblocking_prepare_v2
} {
  forcedelete test.db test2.db test3.db

  set ThreadSetup "set xStep $xStep;set xPrepare $xPrepare;set nSecond $nSecond"

  # Set up the database schema used by this test. Each thread opens file
  # test.db as the main database, then attaches files test2.db and test3.db
  # as auxillary databases. Each file contains a single table (t1, t2 and t3, in
  # files test.db, test2.db and test3.db, respectively). 

Changes to test/notify3.test.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  finish_test 
  return 
}

set esc [sqlite3_enable_shared_cache 1]

sqlite3 db  test.db
file delete -force test.db2 test.db2-journal test.db2-wal
sqlite3 db2 test.db2

do_test notify3-1.1 {
  execsql { 
    CREATE TABLE t1(a, b); 
    INSERT INTO t1 VALUES('t1 A', 't1 B');
  }







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  finish_test 
  return 
}

set esc [sqlite3_enable_shared_cache 1]

sqlite3 db  test.db
forcedelete test.db2 test.db2-journal test.db2-wal
sqlite3 db2 test.db2

do_test notify3-1.1 {
  execsql { 
    CREATE TABLE t1(a, b); 
    INSERT INTO t1 VALUES('t1 A', 't1 B');
  }

Changes to test/openv2.test.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#
# $Id: openv2.test,v 1.2 2009/06/11 17:32:45 drh Exp $

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

db close
file delete -force test.db test.db-journal
do_test openv2-1.1 {
  set rc [catch {sqlite3 db test.db -create 0} msg]
  lappend rc $msg
} {1 {unable to open database file}}
do_test openv2-1.2 {
  info commands db
} {}







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#
# $Id: openv2.test,v 1.2 2009/06/11 17:32:45 drh Exp $

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

db close
forcedelete test.db test.db-journal
do_test openv2-1.1 {
  set rc [catch {sqlite3 db test.db -create 0} msg]
  lappend rc $msg
} {1 {unable to open database file}}
do_test openv2-1.2 {
  info commands db
} {}

Changes to test/pager1.test.

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {4 ok}
do_test pager1.4.2.3 {
  faultsim_restore_and_reopen
  foreach f [glob test.db-mj*] { file delete -force $f }
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {64 ok}
do_test pager1.4.2.4 {
  faultsim_restore_and_reopen
  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {4 ok}
do_test pager1.4.2.5 {
  faultsim_restore_and_reopen
  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
  foreach f [glob test.db-mj*] { file delete -force $f }
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {4 ok}
}








|
















|







448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {4 ok}
do_test pager1.4.2.3 {
  faultsim_restore_and_reopen
  foreach f [glob test.db-mj*] { forcedelete $f }
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {64 ok}
do_test pager1.4.2.4 {
  faultsim_restore_and_reopen
  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {4 ok}
do_test pager1.4.2.5 {
  faultsim_restore_and_reopen
  hexio_write test.db-journal [expr [file size test.db-journal]-20] 123456
  foreach f [glob test.db-mj*] { forcedelete $f }
  execsql {
    SELECT count(*) FROM t1;
    PRAGMA integrity_check;
  }
} {4 ok}
}

645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
    
    # Restore the file-system again. This time, before reopening the databases,
    # delete the master-journal file from the file-system. It now appears that
    # the transaction was committed (no master-journal file == no rollback).
    #
    do_test pager1-4.4.$tn.7 {
      faultsim_restore_and_reopen $prefix
      foreach f [glob ${prefix}-mj*] { file delete -force $f }
      execsql "ATTACH '${prefix}2' AS aux"
    } {}
    do_execsql_test pager1-4.4.$tn.8 {
      SELECT * FROM a
    } {double-you why zed won too free}
    do_execsql_test pager1-4.4.$tn.9 {
      SELECT * FROM b
    } {won too free double-you why zed}
  }

  cd $pwd
}
db close
tv delete
file delete -force $dirname


# Set up a VFS to make a copy of the file-system just before deleting a
# journal file to commit a transaction. The transaction modifies exactly
# two database pages (and page 1 - the change counter).
#
testvfs tv -default 1







|














|







645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
    
    # Restore the file-system again. This time, before reopening the databases,
    # delete the master-journal file from the file-system. It now appears that
    # the transaction was committed (no master-journal file == no rollback).
    #
    do_test pager1-4.4.$tn.7 {
      faultsim_restore_and_reopen $prefix
      foreach f [glob ${prefix}-mj*] { forcedelete $f }
      execsql "ATTACH '${prefix}2' AS aux"
    } {}
    do_execsql_test pager1-4.4.$tn.8 {
      SELECT * FROM a
    } {double-you why zed won too free}
    do_execsql_test pager1-4.4.$tn.9 {
      SELECT * FROM b
    } {won too free double-you why zed}
  }

  cd $pwd
}
db close
tv delete
forcedelete $dirname


# Set up a VFS to make a copy of the file-system just before deleting a
# journal file to commit a transaction. The transaction modifies exactly
# two database pages (and page 1 - the change counter).
#
testvfs tv -default 1
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
  catch {file attributes test.db-journal -readonly 1}
  catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test pager1.4.7.3 {
  db close
  catch {file attributes test.db-journal -permissions rw-rw-rw-}
  catch {file attributes test.db-journal -readonly 0}
  file delete test.db-journal
  file exists test.db-journal
} {0}

#-------------------------------------------------------------------------
# The following tests deal with multi-file commits.
#
# pager1-5.1.*: The case where a multi-file cannot be committed because







|







878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
  catch {file attributes test.db-journal -readonly 1}
  catchsql { SELECT * FROM t1 }
} {1 {unable to open database file}}
do_test pager1.4.7.3 {
  db close
  catch {file attributes test.db-journal -permissions rw-rw-rw-}
  catch {file attributes test.db-journal -readonly 0}
  delete_file test.db-journal
  file exists test.db-journal
} {0}

#-------------------------------------------------------------------------
# The following tests deal with multi-file commits.
#
# pager1-5.1.*: The case where a multi-file cannot be committed because
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
# Test that if an empty database file (size 0 bytes) is opened in 
# exclusive-locking mode, any journal file is deleted from the file-system
# without being rolled back. And that the RESERVED lock obtained while
# doing this is not released.
#
do_test pager1-30.1 {
  db close
  file delete test.db
  file delete test.db-journal
  set fd [open test.db-journal w]
  seek $fd [expr 512+1032*2]
  puts -nonewline $fd x
  close $fd

  sqlite3 db test.db
  execsql {







|
|







2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
# Test that if an empty database file (size 0 bytes) is opened in 
# exclusive-locking mode, any journal file is deleted from the file-system
# without being rolled back. And that the RESERVED lock obtained while
# doing this is not released.
#
do_test pager1-30.1 {
  db close
  delete_file test.db
  delete_file test.db-journal
  set fd [open test.db-journal w]
  seek $fd [expr 512+1032*2]
  puts -nonewline $fd x
  close $fd

  sqlite3 db test.db
  execsql {
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
    INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1;
    INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1;
    INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1;
    INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1;
    BEGIN;
      UPDATE t1 SET y = randomblob(1499);
  }
  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







|
|









2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
    INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1;
    INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1;
    INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1;
    INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1;
    BEGIN;
      UPDATE t1 SET y = randomblob(1499);
  }
  copy_file test.db test.db2
  copy_file 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/pagerfault.test.

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}
do_faultsim_test pagerfault-5.3 -faults oom-transient -prep {
  faultsim_restore_and_reopen
  db func a_string a_string
  file delete -force test2.db test2.db-journal test2.db-wal
  execsql { 
    PRAGMA journal_mode = PERSIST;
    ATTACH 'test2.db' AS aux;
    PRAGMA aux.journal_mode = PERSIST;
    PRAGMA aux.journal_size_limit = 0;
  }
} -body {







|







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}
do_faultsim_test pagerfault-5.3 -faults oom-transient -prep {
  faultsim_restore_and_reopen
  db func a_string a_string
  forcedelete test2.db test2.db-journal test2.db-wal
  execsql { 
    PRAGMA journal_mode = PERSIST;
    ATTACH 'test2.db' AS aux;
    PRAGMA aux.journal_mode = PERSIST;
    PRAGMA aux.journal_size_limit = 0;
  }
} -body {
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
    PRAGMA journal_mode = PERSIST;
    BEGIN;
      CREATE TABLE t1(x, y UNIQUE);
      INSERT INTO t1 VALUES(a_string(333), a_string(444));
    COMMIT;
  }
  db close
  file delete -force test.db
  faultsim_save
} {}
do_faultsim_test pagerfault-13 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { CREATE TABLE xx(a, b) }
} -test {







|







637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
    PRAGMA journal_mode = PERSIST;
    BEGIN;
      CREATE TABLE t1(x, y UNIQUE);
      INSERT INTO t1 VALUES(a_string(333), a_string(444));
    COMMIT;
  }
  db close
  forcedelete test.db
  faultsim_save
} {}
do_faultsim_test pagerfault-13 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { CREATE TABLE xx(a, b) }
} -test {
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
#   PagerCommitPhaseOne(<in-memory-db>)   ->   SQLITE_OK
#   PagerCommitPhaseOne(<file-db>)        ->   SQLITE_IOERR
#   PagerRollback(<in-memory-db>)
#   PagerRollback(<file-db>)
#
do_faultsim_test pagerfault-23 -prep {
  sqlite3 db :memory:
  foreach f [glob -nocomplain test.db*] { file delete -force $f }
  db eval { 
    ATTACH 'test.db2' AS aux;
    CREATE TABLE t1(a, b);
    CREATE TABLE aux.t2(a, b);
  }
} -body {
  execsql { 







|







1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
#   PagerCommitPhaseOne(<in-memory-db>)   ->   SQLITE_OK
#   PagerCommitPhaseOne(<file-db>)        ->   SQLITE_IOERR
#   PagerRollback(<in-memory-db>)
#   PagerRollback(<file-db>)
#
do_faultsim_test pagerfault-23 -prep {
  sqlite3 db :memory:
  foreach f [glob -nocomplain test.db*] { forcedelete $f }
  db eval { 
    ATTACH 'test.db2' AS aux;
    CREATE TABLE t1(a, b);
    CREATE TABLE aux.t2(a, b);
  }
} -body {
  execsql { 

Changes to test/pagesize.test.

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    PRAGMA page_size=2048;
    PRAGMA page_size;
  }
} 1024

do_test pagesize-1.4 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  execsql {
    PRAGMA page_size=511;
    PRAGMA page_size;
  }
} 1024
do_test pagesize-1.5 {







|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    PRAGMA page_size=2048;
    PRAGMA page_size;
  }
} 1024

do_test pagesize-1.4 {
  db close
  forcedelete test.db
  sqlite3 db test.db
  execsql {
    PRAGMA page_size=511;
    PRAGMA page_size;
  }
} 1024
do_test pagesize-1.5 {
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
        INSERT INTO t1 VALUES(2,3,4);
        SELECT * FROM t1;
      }
    } {1 2 3 2 3 4}
  }
  do_test pagesize-2.$PGSZ.1 {
    db close
    file delete -force test.db
    sqlite3 db test.db
    execsql "PRAGMA page_size=$PGSZ"
    execsql {
      CREATE TABLE t1(x);
      PRAGMA page_size;
    }
  } $PGSZ







|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
        INSERT INTO t1 VALUES(2,3,4);
        SELECT * FROM t1;
      }
    } {1 2 3 2 3 4}
  }
  do_test pagesize-2.$PGSZ.1 {
    db close
    forcedelete test.db
    sqlite3 db test.db
    execsql "PRAGMA page_size=$PGSZ"
    execsql {
      CREATE TABLE t1(x);
      PRAGMA page_size;
    }
  } $PGSZ
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
  do_test pagesize-2.$PGSZ.16 {
    execsql {DROP TABLE t1}
    ifcapable {vacuum} {execsql VACUUM}
  } {}
  integrity_check pagesize-2.$PGSZ.17

  db close
  file delete -force test.db
  sqlite3 db test.db
  do_test pagesize-2.$PGSZ.30 {
    execsql "
      CREATE TABLE t1(x);
      PRAGMA temp.page_size=$PGSZ;
      CREATE TEMP TABLE t2(y);
      PRAGMA main.page_size;
      PRAGMA temp.page_size;
    "
  } [list 1024 $PGSZ]

  db close
  file delete -force test.db
  sqlite3 db test.db
  do_test pagesize-2.$PGSZ.40 {
    execsql "
      PRAGMA page_size=$PGSZ;
      CREATE TABLE t1(x);
      CREATE TEMP TABLE t2(y);
      PRAGMA main.page_size;
      PRAGMA temp.page_size;
    "
  } [list $PGSZ $PGSZ]
}

finish_test







|












|













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
  do_test pagesize-2.$PGSZ.16 {
    execsql {DROP TABLE t1}
    ifcapable {vacuum} {execsql VACUUM}
  } {}
  integrity_check pagesize-2.$PGSZ.17

  db close
  forcedelete test.db
  sqlite3 db test.db
  do_test pagesize-2.$PGSZ.30 {
    execsql "
      CREATE TABLE t1(x);
      PRAGMA temp.page_size=$PGSZ;
      CREATE TEMP TABLE t2(y);
      PRAGMA main.page_size;
      PRAGMA temp.page_size;
    "
  } [list 1024 $PGSZ]

  db close
  forcedelete test.db
  sqlite3 db test.db
  do_test pagesize-2.$PGSZ.40 {
    execsql "
      PRAGMA page_size=$PGSZ;
      CREATE TABLE t1(x);
      CREATE TEMP TABLE t2(y);
      PRAGMA main.page_size;
      PRAGMA temp.page_size;
    "
  } [list $PGSZ $PGSZ]
}

finish_test

Changes to test/pcache2.test.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1
  sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0
} {0 0 0}

# Open up two database connections to separate files.
#
do_test pcache2-1.2 {
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  db eval {PRAGMA cache_size=10}
  lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
} {2}
do_test pcache2-1.3 {
  file delete -force test2.db test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {PRAGMA cache_size=50}
  lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
} {4}


# Make lots of changes on the first connection.  Verify that the







|





|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1
  sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0
} {0 0 0}

# Open up two database connections to separate files.
#
do_test pcache2-1.2 {
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  db eval {PRAGMA cache_size=10}
  lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
} {2}
do_test pcache2-1.3 {
  forcedelete test2.db test2.db-journal
  sqlite3 db2 test2.db
  db2 eval {PRAGMA cache_size=50}
  lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 1
} {4}


# Make lots of changes on the first connection.  Verify that the

Changes to test/pragma.test.

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  return
}

# Delete the preexisting database to avoid the special setup
# that the "all.test" script does.
#
db close
file delete test.db test.db-journal
file delete test3.db test3.db-journal
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]


ifcapable pager_pragmas {
set DFLT_CACHE_SZ [db one {PRAGMA default_cache_size}]
set TEMP_CACHE_SZ [db one {PRAGMA temp.default_cache_size}]
do_test pragma-1.1 {







|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  return
}

# Delete the preexisting database to avoid the special setup
# that the "all.test" script does.
#
db close
delete_file test.db test.db-journal
delete_file test3.db test3.db-journal
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]


ifcapable pager_pragmas {
set DFLT_CACHE_SZ [db one {PRAGMA default_cache_size}]
set TEMP_CACHE_SZ [db one {PRAGMA temp.default_cache_size}]
do_test pragma-1.1 {
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
    PRAGMA bogus = -1234;  -- Parsing of negative values
  }
} {}

# Test modifying the safety_level of an attached database.
ifcapable pager_pragmas&&attach {
  do_test pragma-2.1 {
    file delete -force test2.db
    file delete -force test2.db-journal
    execsql {
      ATTACH 'test2.db' AS aux;
    } 
  } {}
  do_test pragma-2.2 {
    execsql {
      pragma aux.synchronous;







|
|







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
    PRAGMA bogus = -1234;  -- Parsing of negative values
  }
} {}

# Test modifying the safety_level of an attached database.
ifcapable pager_pragmas&&attach {
  do_test pragma-2.1 {
    forcedelete test2.db
    forcedelete test2.db-journal
    execsql {
      ATTACH 'test2.db' AS aux;
    } 
  } {}
  do_test pragma-2.2 {
    execsql {
      pragma aux.synchronous;
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# Construct a corrupted index and make sure the integrity_check
# pragma finds it.
#
# These tests won't work if the database is encrypted
#
do_test pragma-3.1 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum=OFF;
    BEGIN;
    CREATE TABLE t2(a,b,c);
    CREATE INDEX i2 ON t2(a);
    INSERT INTO t2 VALUES(11,2,3);







|







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# Construct a corrupted index and make sure the integrity_check
# pragma finds it.
#
# These tests won't work if the database is encrypted
#
do_test pragma-3.1 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum=OFF;
    BEGIN;
    CREATE TABLE t2(a,b,c);
    CREATE INDEX i2 ON t2(a);
    INSERT INTO t2 VALUES(11,2,3);
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
    } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}}
  
    # Add additional corruption by appending unused pages to the end of
    # the database file testerr.db
    #
    do_test pragma-3.8 {
      execsql {DETACH t2}
      file delete -force testerr.db testerr.db-journal
      set out [open testerr.db w]
      fconfigure $out -translation binary
      set in [open test.db r]
      fconfigure $in -translation binary
      puts -nonewline $out [read $in]
      seek $in 0
      puts -nonewline $out [read $in]







|







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
    } {{rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {rowid 2 missing from index i2} {wrong # of entries in index i2}}
  
    # Add additional corruption by appending unused pages to the end of
    # the database file testerr.db
    #
    do_test pragma-3.8 {
      execsql {DETACH t2}
      forcedelete testerr.db testerr.db-journal
      set out [open testerr.db w]
      fconfigure $out -translation binary
      set in [open test.db r]
      fconfigure $in -translation binary
      puts -nonewline $out [read $in]
      seek $in 0
      puts -nonewline $out [read $in]
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
    } {{*** in database t2 ***
Page 4 is never used
Page 5 is never used
Page 6 is never used} {rowid 1 missing from index i2}}
  }
  do_test pragma-3.19 {
    catch {db close}
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    db eval {PRAGMA integrity_check}
  } {ok}
}
#exit

# Test modifying the cache_size of an attached database.







|







415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
    } {{*** in database t2 ***
Page 4 is never used
Page 5 is never used
Page 6 is never used} {rowid 1 missing from index i2}}
  }
  do_test pragma-3.19 {
    catch {db close}
    forcedelete test.db test.db-journal
    sqlite3 db test.db
    db eval {PRAGMA integrity_check}
  } {ok}
}
#exit

# Test modifying the cache_size of an attached database.
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
  sqlite3_step $::STMT
} SQLITE_ERROR
do_test pragma-8.1.10 {
  sqlite3_finalize $::STMT
} SQLITE_SCHEMA

# Make sure the schema-version can be manipulated in an attached database.
file delete -force test2.db
file delete -force test2.db-journal
ifcapable attach {
  do_test pragma-8.1.11 {
    execsql {
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t1(a, b, c);
      PRAGMA aux.schema_version = 205;
    }







|
|







737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
  sqlite3_step $::STMT
} SQLITE_ERROR
do_test pragma-8.1.10 {
  sqlite3_finalize $::STMT
} SQLITE_SCHEMA

# Make sure the schema-version can be manipulated in an attached database.
forcedelete test2.db
forcedelete test2.db-journal
ifcapable attach {
  do_test pragma-8.1.11 {
    execsql {
      ATTACH 'test2.db' AS aux;
      CREATE TABLE aux.t1(a, b, c);
      PRAGMA aux.schema_version = 205;
    }
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
  }
} {}

} ;# ifcapable bloblit 

ifcapable pager_pragmas {
  db close
  file delete -force test.db
  sqlite3 db test.db

  do_test pragma-14.1 {
    execsql { pragma auto_vacuum = 0 }
    execsql { pragma page_count }
  } {0}








|







1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
  }
} {}

} ;# ifcapable bloblit 

ifcapable pager_pragmas {
  db close
  forcedelete test.db
  sqlite3 db test.db

  do_test pragma-14.1 {
    execsql { pragma auto_vacuum = 0 }
    execsql { pragma page_count }
  } {0}

1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
    execsql {
      ROLLBACK;
      PRAGMA page_count;
    }
  } {2}

  do_test pragma-14.6 {
    file delete -force test2.db
    sqlite3 db2 test2.db
    execsql {
      PRAGMA auto_vacuum = 0;
      CREATE TABLE t1(a, b, c);
      CREATE TABLE t2(a, b, c);
      CREATE TABLE t3(a, b, c);
      CREATE TABLE t4(a, b, c);







|







1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
    execsql {
      ROLLBACK;
      PRAGMA page_count;
    }
  } {2}

  do_test pragma-14.6 {
    forcedelete test2.db
    sqlite3 db2 test2.db
    execsql {
      PRAGMA auto_vacuum = 0;
      CREATE TABLE t1(a, b, c);
      CREATE TABLE t2(a, b, c);
      CREATE TABLE t3(a, b, c);
      CREATE TABLE t4(a, b, c);

Changes to test/pragma2.test.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  return
}

# Delete the preexisting database to avoid the special setup
# that the "all.test" script does.
#
db close
file delete test.db test.db-journal
file delete test3.db test3.db-journal
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
db eval {PRAGMA auto_vacuum=0}

do_test pragma2-1.1 {
  execsql {
    PRAGMA freelist_count;
  }







|
|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  return
}

# Delete the preexisting database to avoid the special setup
# that the "all.test" script does.
#
db close
delete_file test.db test.db-journal
delete_file test3.db test3.db-journal
sqlite3 db test.db; set DB [sqlite3_connection_pointer db]
db eval {PRAGMA auto_vacuum=0}

do_test pragma2-1.1 {
  execsql {
    PRAGMA freelist_count;
  }
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
} {1}
do_test pragma2-1.4 {
  execsql {
    PRAGMA main.freelist_count;
  }
} {1}

file delete -force test2.db
file delete -force test2.db-journal

ifcapable attach {
  do_test pragma2-2.1 {
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA aux.auto_vacuum=OFF;
      PRAGMA aux.freelist_count;







|
|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
} {1}
do_test pragma2-1.4 {
  execsql {
    PRAGMA main.freelist_count;
  }
} {1}

forcedelete test2.db
forcedelete test2.db-journal

ifcapable attach {
  do_test pragma2-2.1 {
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA aux.auto_vacuum=OFF;
      PRAGMA aux.freelist_count;

Changes to test/quota.test.

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
proc quota_check {filename limitvar size} {
  upvar $limitvar limit
  lappend ::quota [set limit] $size
  if {[info exists ::quota_request_ok]} { set limit $size }
}

do_test quota-3.1.1 {
  file delete -force test.db
  sqlite3_quota_initialize "" 1
  sqlite3_quota_set *test.db 4096 quota_check
} {SQLITE_OK}
do_test quota-3.1.2 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;







|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
proc quota_check {filename limitvar size} {
  upvar $limitvar limit
  lappend ::quota [set limit] $size
  if {[info exists ::quota_request_ok]} { set limit $size }
}

do_test quota-3.1.1 {
  forcedelete test.db
  sqlite3_quota_initialize "" 1
  sqlite3_quota_set *test.db 4096 quota_check
} {SQLITE_OK}
do_test quota-3.1.2 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
do_test quota-3.1.6 {
  db close
  db2 close
  sqlite3_quota_set *test.db 0 {}
} {SQLITE_OK}

do_test quota-3.2.1 {
  file delete force test.db test2.db 

  sqlite3_quota_set * 4096 {}
  sqlite3 db1a test.db
  sqlite3 db2a test2.db

  foreach db {db1a db2a} {
    execsql {







|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
do_test quota-3.1.6 {
  db close
  db2 close
  sqlite3_quota_set *test.db 0 {}
} {SQLITE_OK}

do_test quota-3.2.1 {
  delete_file force test.db test2.db 

  sqlite3_quota_set * 4096 {}
  sqlite3 db1a test.db
  sqlite3 db2a test2.db

  foreach db {db1a db2a} {
    execsql {
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
  quota_list
} {*test.db *test2.db}
do_test quota-4.1.5 {
  sqlite3_quota_set *test.db 0 {}
  quota_list
} {*test2.db}
do_test quota-4.1.6 {
  file delete -force test2.db test2.db-journal test2.db-wal
  sqlite3 db test2.db
  db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');}
  quota_list
} {*test2.db}
do_test quota-4.1.7 {
  catchsql {INSERT INTO t2 VALUES(zeroblob(200000))}
} {1 {database or disk is full}}







|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
  quota_list
} {*test.db *test2.db}
do_test quota-4.1.5 {
  sqlite3_quota_set *test.db 0 {}
  quota_list
} {*test2.db}
do_test quota-4.1.6 {
  forcedelete test2.db test2.db-journal test2.db-wal
  sqlite3 db test2.db
  db eval {CREATE TABLE t2(x); INSERT INTO t2 VALUES('tab-t2');}
  quota_list
} {*test2.db}
do_test quota-4.1.7 {
  catchsql {INSERT INTO t2 VALUES(zeroblob(200000))}
} {1 {database or disk is full}}
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
do_faultsim_test quota-5.2 -prep {
  catch {db close}
} -body {
  sqlite3 db test.db
}

catch { db close }
file delete -force test.db

do_test quota-5.3.prep {
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum = 1;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(10, zeroblob(1200));
  }
  faultsim_save_and_close
} {}
do_faultsim_test quota-5.3 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { DELETE FROM t1 }
}

do_test quota-5.4.1 {
  catch { db close }
  file delete -force test.db
  file mkdir test.db
  list [catch { sqlite3 db test.db } msg] $msg
} {1 {unable to open database file}}

do_faultsim_test quota-5.5 -prep {
  catch { sqlite3_quota_shutdown }
} -body {







|



















|







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
do_faultsim_test quota-5.2 -prep {
  catch {db close}
} -body {
  sqlite3 db test.db
}

catch { db close }
forcedelete test.db

do_test quota-5.3.prep {
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum = 1;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(10, zeroblob(1200));
  }
  faultsim_save_and_close
} {}
do_faultsim_test quota-5.3 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { DELETE FROM t1 }
}

do_test quota-5.4.1 {
  catch { db close }
  forcedelete test.db
  file mkdir test.db
  list [catch { sqlite3 db test.db } msg] $msg
} {1 {unable to open database file}}

do_faultsim_test quota-5.5 -prep {
  catch { sqlite3_quota_shutdown }
} -body {

Changes to test/rollback.test.

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
 && [permutation] ne "inmemory_journal"
} {
  do_test rollback-2.1 {
    execsql {
      BEGIN;
      INSERT INTO t3 VALUES('hello world');
    }
    file copy -force test.db testA.db
    file copy -force test.db-journal testA.db-journal
    execsql {
      COMMIT;
    }
  } {}

  # At this point files testA.db and testA.db-journal are present in the
  # file system. This block adds a master-journal file pointer to the







|
|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
 && [permutation] ne "inmemory_journal"
} {
  do_test rollback-2.1 {
    execsql {
      BEGIN;
      INSERT INTO t3 VALUES('hello world');
    }
    forcecopy test.db testA.db
    forcecopy test.db-journal testA.db-journal
    execsql {
      COMMIT;
    }
  } {}

  # At this point files testA.db and testA.db-journal are present in the
  # file system. This block adds a master-journal file pointer to the

Changes to test/savepoint.test.

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

#-------------------------------------------------------------------------
# The following tests, savepoint-6.*, test an incr-vacuum inside of a
# couple of nested savepoints.
#
ifcapable {autovacuum && pragma} {
  db close
  file delete -force test.db
  sqlite3 db test.db

  do_test savepoint-6.1 {
    execsql { PRAGMA auto_vacuum = incremental }
    wal_set_journal_mode
    execsql {
      CREATE TABLE t1(a, b, c);







|







367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

#-------------------------------------------------------------------------
# The following tests, savepoint-6.*, test an incr-vacuum inside of a
# couple of nested savepoints.
#
ifcapable {autovacuum && pragma} {
  db close
  forcedelete test.db
  sqlite3 db test.db

  do_test savepoint-6.1 {
    execsql { PRAGMA auto_vacuum = incremental }
    wal_set_journal_mode
    execsql {
      CREATE TABLE t1(a, b, c);
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
}

#-------------------------------------------------------------------------
# The following tests, savepoint-7.*, attempt to break the logic 
# surrounding savepoints by growing and shrinking the database file.
#
db close
file delete -force test.db
sqlite3 db test.db

do_test savepoint-7.1 {
  execsql { PRAGMA auto_vacuum = incremental }
  wal_set_journal_mode
  execsql {
    PRAGMA cache_size = 10;







|







415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
}

#-------------------------------------------------------------------------
# The following tests, savepoint-7.*, attempt to break the logic 
# surrounding savepoints by growing and shrinking the database file.
#
db close
forcedelete test.db
sqlite3 db test.db

do_test savepoint-7.1 {
  execsql { PRAGMA auto_vacuum = incremental }
  wal_set_journal_mode
  execsql {
    PRAGMA cache_size = 10;
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
  }
  execsql { PRAGMA integrity_check }
} {ok}
wal_check_journal_mode savepoint-7.3.3

do_test savepoint-7.4.1 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  execsql { PRAGMA auto_vacuum = incremental }
  wal_set_journal_mode
  execsql {
    CREATE TABLE t1(a, b, PRIMARY KEY(a, b));
    INSERT INTO t1 VALUES(randstr(1000,1000), randstr(1000,1000));
    BEGIN;







|







486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
  }
  execsql { PRAGMA integrity_check }
} {ok}
wal_check_journal_mode savepoint-7.3.3

do_test savepoint-7.4.1 {
  db close
  forcedelete test.db
  sqlite3 db test.db
  execsql { PRAGMA auto_vacuum = incremental }
  wal_set_journal_mode
  execsql {
    CREATE TABLE t1(a, b, PRIMARY KEY(a, b));
    INSERT INTO t1 VALUES(randstr(1000,1000), randstr(1000,1000));
    BEGIN;
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
# of the aux1 and aux2 locks.  So record the current lock status of
# TEMP for use in the answers.
set templockstate [lindex [db eval {PRAGMA lock_status}] 3]


if {[wal_is_wal_mode]==0} {
  do_test savepoint-10.2.1 {
    file delete -force test3.db
    file delete -force test2.db
    execsql {
      ATTACH 'test2.db' AS aux1;
      ATTACH 'test3.db' AS aux2;
      DROP TABLE t1;
      CREATE TABLE main.t1(x, y);
      CREATE TABLE aux1.t2(x, y);
      CREATE TABLE aux2.t3(x, y);







|
|







636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
# of the aux1 and aux2 locks.  So record the current lock status of
# TEMP for use in the answers.
set templockstate [lindex [db eval {PRAGMA lock_status}] 3]


if {[wal_is_wal_mode]==0} {
  do_test savepoint-10.2.1 {
    forcedelete test3.db
    forcedelete test2.db
    execsql {
      ATTACH 'test2.db' AS aux1;
      ATTACH 'test3.db' AS aux2;
      DROP TABLE t1;
      CREATE TABLE main.t1(x, y);
      CREATE TABLE aux1.t2(x, y);
      CREATE TABLE aux2.t3(x, y);
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
#-------------------------------------------------------------------------
# The following tests - savepoint-11.* - test the interaction of 
# savepoints and creating or dropping tables and indexes in 
# auto-vacuum mode.
# 
do_test savepoint-11.1 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  execsql { PRAGMA auto_vacuum = full; }
  wal_set_journal_mode
  execsql {
    CREATE TABLE t1(a, b, UNIQUE(a, b));
    INSERT INTO t1 VALUES(1, randstr(1000,1000));
    INSERT INTO t1 VALUES(2, randstr(1000,1000));







|







758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
#-------------------------------------------------------------------------
# The following tests - savepoint-11.* - test the interaction of 
# savepoints and creating or dropping tables and indexes in 
# auto-vacuum mode.
# 
do_test savepoint-11.1 {
  db close
  forcedelete test.db
  sqlite3 db test.db
  execsql { PRAGMA auto_vacuum = full; }
  wal_set_journal_mode
  execsql {
    CREATE TABLE t1(a, b, UNIQUE(a, b));
    INSERT INTO t1 VALUES(1, randstr(1000,1000));
    INSERT INTO t1 VALUES(2, randstr(1000,1000));
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
#-------------------------------------------------------------------------
# The following tests - savepoint-13.* - test the interaction of 
# savepoints and "journal_mode = off".
# 
if {[wal_is_wal_mode]==0} {
  do_test savepoint-13.1 {
    db close
    catch {file delete -force test.db}
    sqlite3 db test.db
    execsql {
      BEGIN;
        CREATE TABLE t1(a PRIMARY KEY, b);
        INSERT INTO t1 VALUES(1, 2);
      COMMIT;
      PRAGMA journal_mode = off;







|







864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
#-------------------------------------------------------------------------
# The following tests - savepoint-13.* - test the interaction of 
# savepoints and "journal_mode = off".
# 
if {[wal_is_wal_mode]==0} {
  do_test savepoint-13.1 {
    db close
    catch {forcedelete test.db}
    sqlite3 db test.db
    execsql {
      BEGIN;
        CREATE TABLE t1(a PRIMARY KEY, b);
        INSERT INTO t1 VALUES(1, 2);
      COMMIT;
      PRAGMA journal_mode = off;
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
      ROLLBACK;
      SELECT * FROM t1;
    }
  } {1 2 3 4 5 6 7 8 9 10 11 12}
}

db close
file delete test.db
do_multiclient_test tn {
  do_test savepoint-14.$tn.1 {
    sql1 {
      CREATE TABLE foo(x);
      INSERT INTO foo VALUES(1);
      INSERT INTO foo VALUES(2);
    }







|







905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
      ROLLBACK;
      SELECT * FROM t1;
    }
  } {1 2 3 4 5 6 7 8 9 10 11 12}
}

db close
delete_file test.db
do_multiclient_test tn {
  do_test savepoint-14.$tn.1 {
    sql1 {
      CREATE TABLE foo(x);
      INSERT INTO foo VALUES(1);
      INSERT INTO foo VALUES(2);
    }

Changes to test/savepoint6.test.

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  sql { PRAGMA cache_size = 10 }
}] {

  unset -nocomplain ::lSavepoint
  unset -nocomplain ::aEntry

  catch { db close }
  file delete -force test.db test.db-wal test.db-journal
  eval $zSetup
  sql $DATABASE_SCHEMA

  wal_set_journal_mode

  do_test savepoint6-$testname.setup {
    savepoint one







|







242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  sql { PRAGMA cache_size = 10 }
}] {

  unset -nocomplain ::lSavepoint
  unset -nocomplain ::aEntry

  catch { db close }
  forcedelete test.db test.db-wal test.db-journal
  eval $zSetup
  sql $DATABASE_SCHEMA

  wal_set_journal_mode

  do_test savepoint6-$testname.setup {
    savepoint one

Changes to test/securedel.test.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
}


do_test securedel-1.0 {
  db eval {PRAGMA secure_delete;}
} $DEFAULT_SECDEL

file delete -force test2.db test2.db-journal
do_test securedel-1.1 {
  db eval {
    ATTACH 'test2.db' AS db2;
    PRAGMA main.secure_delete=ON;
    PRAGMA db2.secure_delete;
  }
} [list 1 $DEFAULT_SECDEL]







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
}


do_test securedel-1.0 {
  db eval {PRAGMA secure_delete;}
} $DEFAULT_SECDEL

forcedelete test2.db test2.db-journal
do_test securedel-1.1 {
  db eval {
    ATTACH 'test2.db' AS db2;
    PRAGMA main.secure_delete=ON;
    PRAGMA db2.secure_delete;
  }
} [list 1 $DEFAULT_SECDEL]

Changes to test/shared.test.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
}

set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

foreach av [list 0 1] {

# Open the database connection and execute the auto-vacuum pragma
file delete -force test.db
sqlite3 db test.db

ifcapable autovacuum {
  do_test shared-[expr $av+1].1.0 {
    execsql "pragma auto_vacuum=$::av"
    execsql {pragma auto_vacuum}
  } "$av"







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
}

set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

foreach av [list 0 1] {

# Open the database connection and execute the auto-vacuum pragma
forcedelete test.db
sqlite3 db test.db

ifcapable autovacuum {
  do_test shared-[expr $av+1].1.0 {
    execsql "pragma auto_vacuum=$::av"
    execsql {pragma auto_vacuum}
  } "$av"
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# (as well as main):
#
#     db.main   ->   ./test.db
#     db.test2  ->   ./test2.db
#     db2.main  ->   ./test2.db
#     db2.test  ->   ./test.db
#
file delete -force test.db
file delete -force test2.db
file delete -force test2.db-journal
sqlite3 db  test.db
sqlite3 db2 test2.db
do_test shared-$av.4.1.1 {
  set sqlite_open_file_count
  expr $sqlite_open_file_count-($extrafds_prelock*2)
} {2}
do_test shared-$av.4.1.2 {







|
|
|







289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# (as well as main):
#
#     db.main   ->   ./test.db
#     db.test2  ->   ./test2.db
#     db2.main  ->   ./test2.db
#     db2.test  ->   ./test.db
#
forcedelete test.db
forcedelete test2.db
forcedelete test2.db-journal
sqlite3 db  test.db
sqlite3 db2 test2.db
do_test shared-$av.4.1.1 {
  set sqlite_open_file_count
  expr $sqlite_open_file_count-($extrafds_prelock*2)
} {2}
do_test shared-$av.4.1.2 {
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
catch {db2 close}
catch {db close}

#--------------------------------------------------------------------------
# Tests shared-5.* 
#
foreach db [list test.db test1.db test2.db test3.db] {
  file delete -force $db ${db}-journal
}
do_test shared-$av.5.1.1 {
  sqlite3 db1 test.db
  sqlite3 db2 test.db
  execsql {
    ATTACH 'test1.db' AS test1;
    ATTACH 'test2.db' AS test2;







|







422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
catch {db2 close}
catch {db close}

#--------------------------------------------------------------------------
# Tests shared-5.* 
#
foreach db [list test.db test1.db test2.db test3.db] {
  forcedelete $db ${db}-journal
}
do_test shared-$av.5.1.1 {
  sqlite3 db1 test.db
  sqlite3 db2 test.db
  execsql {
    ATTACH 'test1.db' AS test1;
    ATTACH 'test2.db' AS test2;
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  }
  set ret
} {}

catch {db1 close}
catch {db2 close}
foreach f [list test.db test2.db] {
  file delete -force $f ${f}-journal
}

#--------------------------------------------------------------------------
# Tests shared-7.* test auto-vacuum does not invalidate cursors from
# other shared-cache users when it reorganizes the database on 
# COMMIT.
#







|







553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  }
  set ret
} {}

catch {db1 close}
catch {db2 close}
foreach f [list test.db test2.db] {
  forcedelete $f ${f}-journal
}

#--------------------------------------------------------------------------
# Tests shared-7.* test auto-vacuum does not invalidate cursors from
# other shared-cache users when it reorganizes the database on 
# COMMIT.
#
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
catch {db2 close}
unset -nocomplain contents

#--------------------------------------------------------------------------
# The following tests try to trick the shared-cache code into assuming
# the wrong encoding for a database.
#
file delete -force test.db test.db-journal
ifcapable utf16 {
  do_test shared-$av.8.1.1 {
    sqlite3 db test.db
    execsql {
      PRAGMA encoding = 'UTF-16';
      SELECT * FROM sqlite_master;
    }







|







639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
catch {db2 close}
unset -nocomplain contents

#--------------------------------------------------------------------------
# The following tests try to trick the shared-cache code into assuming
# the wrong encoding for a database.
#
forcedelete test.db test.db-journal
ifcapable utf16 {
  do_test shared-$av.8.1.1 {
    sqlite3 db test.db
    execsql {
      PRAGMA encoding = 'UTF-16';
      SELECT * FROM sqlite_master;
    }
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
  do_test shared-$av.8.1.5 {
    db2 close
    execsql {
      PRAGMA encoding;
    }
  } {UTF-8}

  file delete -force test2.db test2.db-journal
  do_test shared-$av.8.2.1 {
    execsql {
      ATTACH 'test2.db' AS aux;
      SELECT * FROM aux.sqlite_master;
    }
  } {}
  do_test shared-$av.8.2.2 {
    sqlite3 db2 test2.db
    execsql {
      PRAGMA encoding = 'UTF-16';
      CREATE TABLE def(d, e, f);
    } db2
    string range [execsql {PRAGMA encoding;} db2] 0 end-2
  } {UTF-16}

  catch {db close}
  catch {db2 close}
  file delete -force test.db test2.db

  do_test shared-$av.8.3.2 {
    sqlite3 db test.db
    execsql { CREATE TABLE def(d, e, f) }
    execsql { PRAGMA encoding }
  } {UTF-8}
  do_test shared-$av.8.3.3 {







|

















|







671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
  do_test shared-$av.8.1.5 {
    db2 close
    execsql {
      PRAGMA encoding;
    }
  } {UTF-8}

  forcedelete test2.db test2.db-journal
  do_test shared-$av.8.2.1 {
    execsql {
      ATTACH 'test2.db' AS aux;
      SELECT * FROM aux.sqlite_master;
    }
  } {}
  do_test shared-$av.8.2.2 {
    sqlite3 db2 test2.db
    execsql {
      PRAGMA encoding = 'UTF-16';
      CREATE TABLE def(d, e, f);
    } db2
    string range [execsql {PRAGMA encoding;} db2] 0 end-2
  } {UTF-16}

  catch {db close}
  catch {db2 close}
  forcedelete test.db test2.db

  do_test shared-$av.8.3.2 {
    sqlite3 db test.db
    execsql { CREATE TABLE def(d, e, f) }
    execsql { PRAGMA encoding }
  } {UTF-8}
  do_test shared-$av.8.3.3 {
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
    }
  } {1 {attached databases must use the same text encoding as main database}}
}
}

catch {db close}
catch {db2 close}
file delete -force test.db test2.db

#---------------------------------------------------------------------------
# The following tests - shared-9.* - test interactions between TEMP triggers
# and shared-schemas.
#
ifcapable trigger&&tempdb {








|







728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
    }
  } {1 {attached databases must use the same text encoding as main database}}
}
}

catch {db close}
catch {db2 close}
forcedelete test.db test2.db

#---------------------------------------------------------------------------
# The following tests - shared-9.* - test interactions between TEMP triggers
# and shared-schemas.
#
ifcapable trigger&&tempdb {

768
769
770
771
772
773
774
775
776
777
778
779
780
781
782

#---------------------------------------------------------------------------
# The following tests - shared-10.* - test that the library behaves 
# correctly when a connection to a shared-cache is closed. 
#
do_test shared-$av.10.1 {
  # Create a small sample database with two connections to it (db and db2).
  file delete -force test.db
  sqlite3 db  test.db
  sqlite3 db2 test.db
  execsql {
    CREATE TABLE ab(a PRIMARY KEY, b);
    CREATE TABLE de(d PRIMARY KEY, e);
    INSERT INTO ab VALUES('Chiang Mai', 100000);
    INSERT INTO ab VALUES('Bangkok', 8000000);







|







768
769
770
771
772
773
774
775
776
777
778
779
780
781
782

#---------------------------------------------------------------------------
# The following tests - shared-10.* - test that the library behaves 
# correctly when a connection to a shared-cache is closed. 
#
do_test shared-$av.10.1 {
  # Create a small sample database with two connections to it (db and db2).
  forcedelete test.db
  sqlite3 db  test.db
  sqlite3 db2 test.db
  execsql {
    CREATE TABLE ab(a PRIMARY KEY, b);
    CREATE TABLE de(d PRIMARY KEY, e);
    INSERT INTO ab VALUES('Chiang Mai', 100000);
    INSERT INTO ab VALUES('Bangkok', 8000000);
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
integrity_check shared-$av.10.10
do_test shared-$av.10.11 {
  db close
  db3 close
} {}

do_test shared-$av.11.1 {
  file delete -force test.db
  sqlite3 db  test.db
  sqlite3 db2 test.db
  execsql {
    CREATE TABLE abc(a, b, c);
    CREATE TABLE abc2(a, b, c);
    BEGIN;
    INSERT INTO abc VALUES(1, 2, 3);







|







849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
integrity_check shared-$av.10.10
do_test shared-$av.10.11 {
  db close
  db3 close
} {}

do_test shared-$av.11.1 {
  forcedelete test.db
  sqlite3 db  test.db
  sqlite3 db2 test.db
  execsql {
    CREATE TABLE abc(a, b, c);
    CREATE TABLE abc2(a, b, c);
    BEGIN;
    INSERT INTO abc VALUES(1, 2, 3);
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
do_test shared-$av.11.11 {
  db close
  db2 close
} {}

# This tests that if it is impossible to free any pages, SQLite will
# exceed the limit set by PRAGMA cache_size.
file delete -force test.db test.db-journal
sqlite3 db test.db 
ifcapable pager_pragmas {
  do_test shared-$av.12.1 {
    execsql {
      PRAGMA cache_size = 10;
      PRAGMA cache_size;
    }







|







912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
do_test shared-$av.11.11 {
  db close
  db2 close
} {}

# This tests that if it is impossible to free any pages, SQLite will
# exceed the limit set by PRAGMA cache_size.
forcedelete test.db test.db-journal
sqlite3 db test.db 
ifcapable pager_pragmas {
  do_test shared-$av.12.1 {
    execsql {
      PRAGMA cache_size = 10;
      PRAGMA cache_size;
    }
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
# Internally, locks are acquired on shared B-Tree structures in the order
# that the structures appear in the virtual memory address space. This
# test case attempts to cause the order of the structures in memory 
# to be different from the order in which they are attached to a given
# database handle. This covers an extra line or two.
#
do_test shared-$av.13.1 {
  file delete -force test2.db test3.db test4.db test5.db
  sqlite3 db :memory:
  execsql {
    ATTACH 'test2.db' AS aux2;
    ATTACH 'test3.db' AS aux3;
    ATTACH 'test4.db' AS aux4;
    ATTACH 'test5.db' AS aux5;
    DETACH aux2;







|







959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
# Internally, locks are acquired on shared B-Tree structures in the order
# that the structures appear in the virtual memory address space. This
# test case attempts to cause the order of the structures in memory 
# to be different from the order in which they are attached to a given
# database handle. This covers an extra line or two.
#
do_test shared-$av.13.1 {
  forcedelete test2.db test3.db test4.db test5.db
  sqlite3 db :memory:
  execsql {
    ATTACH 'test2.db' AS aux2;
    ATTACH 'test3.db' AS aux3;
    ATTACH 'test4.db' AS aux4;
    ATTACH 'test5.db' AS aux5;
    DETACH aux2;
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
# [db2]. This is to try to find any points where shared-schema elements
# are allocated using the lookaside buffer of [db].
# 
# Mutexes are enabled for this test as that activates a couple of useful
# assert() statements in the C code.
#
do_test shared-$av-15.1 {
  file delete -force test.db
  sqlite3 db test.db -fullmutex 1
  sqlite3 db2 test.db -fullmutex 1
  execsql {
    CREATE TABLE t1(a, b, c);
    CREATE INDEX i1 ON t1(a, b);
    CREATE VIEW v1 AS SELECT * FROM t1; 
    CREATE VIEW v2 AS SELECT * FROM t1, v1 







|







1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
# [db2]. This is to try to find any points where shared-schema elements
# are allocated using the lookaside buffer of [db].
# 
# Mutexes are enabled for this test as that activates a couple of useful
# assert() statements in the C code.
#
do_test shared-$av-15.1 {
  forcedelete test.db
  sqlite3 db test.db -fullmutex 1
  sqlite3 db2 test.db -fullmutex 1
  execsql {
    CREATE TABLE t1(a, b, c);
    CREATE INDEX i1 ON t1(a, b);
    CREATE VIEW v1 AS SELECT * FROM t1; 
    CREATE VIEW v2 AS SELECT * FROM t1, v1 

Changes to test/shared2.test.

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
db1 close
db2 close

do_test shared2-3.2 {
  sqlite3_enable_shared_cache 1
} {1}

file delete -force test.db

sqlite3 db test.db
do_test shared2-4.1 {
  execsql {
    CREATE TABLE t0(a, b);
    CREATE TABLE t1(a, b DEFAULT 'hello world');
  }







|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
db1 close
db2 close

do_test shared2-3.2 {
  sqlite3_enable_shared_cache 1
} {1}

forcedelete test.db

sqlite3 db test.db
do_test shared2-4.1 {
  execsql {
    CREATE TABLE t0(a, b);
    CREATE TABLE t1(a, b DEFAULT 'hello world');
  }

Changes to test/shared3.test.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  return
}
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

# Ticket #1824
#
do_test shared3-1.1 {
  file delete -force test.db test.db-journal
  sqlite3 db1 test.db
  db1 eval {
    PRAGMA encoding=UTF16;
    CREATE TABLE t1(x,y);
    INSERT INTO t1 VALUES('abc','This is a test string');
  }
  db1 close







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  return
}
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

# Ticket #1824
#
do_test shared3-1.1 {
  forcedelete test.db test.db-journal
  sqlite3 db1 test.db
  db1 eval {
    PRAGMA encoding=UTF16;
    CREATE TABLE t1(x,y);
    INSERT INTO t1 VALUES('abc','This is a test string');
  }
  db1 close

Changes to test/shared4.test.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  return
}
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

# Prepare multiple databases in shared cache mode.
#
do_test shared4-1.1 {
  file delete -force test1.db test1.db-journal
  file delete -force test2.db test2.db-journal
  file delete -force test3.db test3.db-journal
  file delete -force test4.db test4.db-journal
  sqlite3 db1 test1.db
  sqlite3 db2 test2.db
  sqlite3 db3 test3.db
  sqlite3 db4 test4.db
  db1 eval {
    CREATE TABLE t1(a);
    INSERT INTO t1 VALUES(111);







|
|
|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  return
}
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

# Prepare multiple databases in shared cache mode.
#
do_test shared4-1.1 {
  forcedelete test1.db test1.db-journal
  forcedelete test2.db test2.db-journal
  forcedelete test3.db test3.db-journal
  forcedelete test4.db test4.db-journal
  sqlite3 db1 test1.db
  sqlite3 db2 test2.db
  sqlite3 db3 test3.db
  sqlite3 db4 test4.db
  db1 eval {
    CREATE TABLE t1(a);
    INSERT INTO t1 VALUES(111);

Changes to test/shared6.test.

231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
do_test shared6-3.X {
  db1 close
  db2 close
  db3 close
} {}

do_test shared6-4.1 {
  #file delete -force test.db test.db-journal
  sqlite3 db1 test.db
  sqlite3 db2 test.db

  set ::STMT [sqlite3_prepare_v2 db1 "SELECT * FROM t1" -1 DUMMY]
  execsql { CREATE TABLE t5(a, b) } db2
} {}
do_test shared6-4.2 {







|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
do_test shared6-3.X {
  db1 close
  db2 close
  db3 close
} {}

do_test shared6-4.1 {
  #forcedelete test.db test.db-journal
  sqlite3 db1 test.db
  sqlite3 db2 test.db

  set ::STMT [sqlite3_prepare_v2 db1 "SELECT * FROM t1" -1 DUMMY]
  execsql { CREATE TABLE t5(a, b) } db2
} {}
do_test shared6-4.2 {

Changes to test/shared7.test.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  }
  catchsql {
    ATTACH 'test.db' AS err1;
  }
} {1 {database is already attached}}

do_test shared7-1.3 {
  file delete -force test2.db test2.db-journal
  db eval {
    ATTACH 'test2.db' AS test2;
    CREATE TABLE test2.t2(y);
  }
  catchsql {
    ATTACH 'test2.db' AS err2;
  }







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  }
  catchsql {
    ATTACH 'test.db' AS err1;
  }
} {1 {database is already attached}}

do_test shared7-1.3 {
  forcedelete test2.db test2.db-journal
  db eval {
    ATTACH 'test2.db' AS test2;
    CREATE TABLE test2.t2(y);
  }
  catchsql {
    ATTACH 'test2.db' AS err2;
  }

Changes to test/speed3.test.

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
    PRAGMA main.cache_size = 200000;
    PRAGMA main.auto_vacuum = 'incremental';
    ATTACH 'test2.db' AS 'aux'; 
    PRAGMA aux.auto_vacuum = 'none';
  }
}

file delete -force test2.db test2.db-journal
reset_db

# Set up a database in auto-vacuum mode and create a database schema.
#
do_test speed3-0.1 {
  execsql {
    CREATE TABLE main.t1(a INTEGER, b TEXT, c INTEGER);







|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
    PRAGMA main.cache_size = 200000;
    PRAGMA main.auto_vacuum = 'incremental';
    ATTACH 'test2.db' AS 'aux'; 
    PRAGMA aux.auto_vacuum = 'none';
  }
}

forcedelete test2.db test2.db-journal
reset_db

# Set up a database in auto-vacuum mode and create a database schema.
#
do_test speed3-0.1 {
  execsql {
    CREATE TABLE main.t1(a INTEGER, b TEXT, c INTEGER);

Changes to test/sqllimits1.test.

755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
#--------------------------------------------------------------------
# Test cases sqllimits1-12.*: Test the SQLITE_MAX_ATTACHED limit.
#
ifcapable attach {
  do_test sqllimits1-12.1 {
    set max $::SQLITE_MAX_ATTACHED
    for {set i 0} {$i < ($max)} {incr i} {
      file delete -force test${i}.db test${i}.db-journal
    }
    for {set i 0} {$i < ($max)} {incr i} {
      execsql "ATTACH 'test${i}.db' AS aux${i}"
    }
    catchsql "ATTACH 'test${i}.db' AS aux${i}"
  } "1 {too many attached databases - max $::SQLITE_MAX_ATTACHED}"
  do_test sqllimits1-12.2 {







|







755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
#--------------------------------------------------------------------
# Test cases sqllimits1-12.*: Test the SQLITE_MAX_ATTACHED limit.
#
ifcapable attach {
  do_test sqllimits1-12.1 {
    set max $::SQLITE_MAX_ATTACHED
    for {set i 0} {$i < ($max)} {incr i} {
      forcedelete test${i}.db test${i}.db-journal
    }
    for {set i 0} {$i < ($max)} {incr i} {
      execsql "ATTACH 'test${i}.db' AS aux${i}"
    }
    catchsql "ATTACH 'test${i}.db' AS aux${i}"
  } "1 {too many attached databases - max $::SQLITE_MAX_ATTACHED}"
  do_test sqllimits1-12.2 {

Changes to test/stat.test.

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  SELECT * FROM stat WHERE name = 't5' OR name = 'i5';
} [list  \
  i5 / 5 leaf 0 0 1016 0 \
  t5 / 4 leaf 0 0 1016 0 \
]

db close
file delete -force test.db
sqlite3 db test.db
register_dbstat_vtab db
breakpoint
do_execsql_test stat-5.1 {
  PRAGMA auto_vacuum = OFF;
  CREATE VIRTUAL TABLE temp.stat USING dbstat;
  CREATE TABLE t1(x);







|







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  SELECT * FROM stat WHERE name = 't5' OR name = 'i5';
} [list  \
  i5 / 5 leaf 0 0 1016 0 \
  t5 / 4 leaf 0 0 1016 0 \
]

db close
forcedelete test.db
sqlite3 db test.db
register_dbstat_vtab db
breakpoint
do_execsql_test stat-5.1 {
  PRAGMA auto_vacuum = OFF;
  CREATE VIRTUAL TABLE temp.stat USING dbstat;
  CREATE TABLE t1(x);

Changes to test/sync.test.

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
      incr sqlite_sync_count $adj
    }
  }
}

do_test sync-1.1 {
  set sqlite_sync_count 0
  file delete -force test2.db
  file delete -force test2.db-journal
  execsql {
    PRAGMA fullfsync=OFF;
    CREATE TABLE t1(a,b);
    ATTACH DATABASE 'test2.db' AS db2;
    CREATE TABLE db2.t2(x,y);
  }
  cond_incr_sync_count 2







|
|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
      incr sqlite_sync_count $adj
    }
  }
}

do_test sync-1.1 {
  set sqlite_sync_count 0
  forcedelete test2.db
  forcedelete test2.db-journal
  execsql {
    PRAGMA fullfsync=OFF;
    CREATE TABLE t1(a,b);
    ATTACH DATABASE 'test2.db' AS db2;
    CREATE TABLE db2.t2(x,y);
  }
  cond_incr_sync_count 2

Changes to test/table.test.

663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
  set result [list $rc $msg]
} {1 {database table is locked}}

ifcapable attach {
  # Now attach a database and ensure that a table can be created in the 
  # attached database whilst in a callback from a query on the main database.
  do_test table-14.3 {
    file delete -force test2.db
    file delete -force test2.db-journal
    execsql {
      ATTACH 'test2.db' as aux;
    }
    db eval {SELECT * FROM tablet8 LIMIT 1} {} {
      db eval {CREATE TABLE aux.t1(a, b, c)}
    }
  } {}







|
|







663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
  set result [list $rc $msg]
} {1 {database table is locked}}

ifcapable attach {
  # Now attach a database and ensure that a table can be created in the 
  # attached database whilst in a callback from a query on the main database.
  do_test table-14.3 {
    forcedelete test2.db
    forcedelete test2.db-journal
    execsql {
      ATTACH 'test2.db' as aux;
    }
    db eval {SELECT * FROM tablet8 LIMIT 1} {} {
      db eval {CREATE TABLE aux.t1(a, b, c)}
    }
  } {}

Changes to test/temptable.test.

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
  db close
  sqlite3 db test.db
  catchsql {
    SELECT * FROM t8,t9;
  }
} {1 {no such table: t9}}

file delete -force test2.db test2.db-journal
ifcapable attach {
  do_test temptable-7.1 {
    catchsql {
      ATTACH 'test2.db' AS two;
      CREATE TEMP TABLE two.abc(x,y);
    }
  } {1 {temporary table name must be unqualified}}
}

# Need to do the following for tcl 8.5 on mac. On that configuration, the
# -readonly flag is taken so seriously that a subsequent [file delete -force]
# (required before the next test file can be executed) will fail.
#
catch {file attributes test.db -readonly 0}

do_test temptable-8.0 {
  db close
  catch {file delete -force test.db}
  sqlite3 db test.db
} {}
do_test temptable-8.1 {
  execsql { CREATE TEMP TABLE tbl2(a, b); }
  execsql {
    CREATE TABLE tbl(a, b);
    INSERT INTO tbl VALUES(1, 2);







|










|






|







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
  db close
  sqlite3 db test.db
  catchsql {
    SELECT * FROM t8,t9;
  }
} {1 {no such table: t9}}

forcedelete test2.db test2.db-journal
ifcapable attach {
  do_test temptable-7.1 {
    catchsql {
      ATTACH 'test2.db' AS two;
      CREATE TEMP TABLE two.abc(x,y);
    }
  } {1 {temporary table name must be unqualified}}
}

# Need to do the following for tcl 8.5 on mac. On that configuration, the
# -readonly flag is taken so seriously that a subsequent [forcedelete]
# (required before the next test file can be executed) will fail.
#
catch {file attributes test.db -readonly 0}

do_test temptable-8.0 {
  db close
  catch {forcedelete test.db}
  sqlite3 db test.db
} {}
do_test temptable-8.1 {
  execsql { CREATE TEMP TABLE tbl2(a, b); }
  execsql {
    CREATE TABLE tbl(a, b);
    INSERT INTO tbl VALUES(1, 2);

Changes to test/temptrigger.test.

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#                    connection. This forces [db] to reload the 'test2.db'
#                    schema. Check that the temp trigger is still fired
#                    correctly.
#
#   temptrigger-3.4: Check that the temp trigger can be dropped without error.
# 
do_test temptrigger-3.1 {
  catch { file delete -force test2.db test2.db-journal }
  catch { file delete -force test.db test.db-journal }
  sqlite3 db test.db 
  sqlite3 db2 test2.db 
  execsql { CREATE TABLE t2(a, b) } db2
  execsql {
    ATTACH 'test2.db' AS aux;
    CREATE TEMP TABLE tt2(a, b);
    CREATE TEMP TRIGGER tr2 AFTER INSERT ON aux.t2 BEGIN







|
|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#                    connection. This forces [db] to reload the 'test2.db'
#                    schema. Check that the temp trigger is still fired
#                    correctly.
#
#   temptrigger-3.4: Check that the temp trigger can be dropped without error.
# 
do_test temptrigger-3.1 {
  catch { forcedelete test2.db test2.db-journal }
  catch { forcedelete test.db test.db-journal }
  sqlite3 db test.db 
  sqlite3 db2 test2.db 
  execsql { CREATE TABLE t2(a, b) } db2
  execsql {
    ATTACH 'test2.db' AS aux;
    CREATE TEMP TABLE tt2(a, b);
    CREATE TEMP TRIGGER tr2 AFTER INSERT ON aux.t2 BEGIN

Changes to test/tester.tcl.

16
17
18
19
20
21
22

23

24
25
26
27
28
29
30
#-------------------------------------------------------------------------
# The commands provided by the code in this file to help with creating 
# test cases are as follows:
#
# Commands to manipulate the db and the file-system at a high level:
#
#      copy_file              FROM TO

#      drop_all_tables        ?DB?

#      forcedelete            FILENAME
#
# Test the capability of the SQLite version built into the interpreter to
# determine if a specific test can be run:
#
#      ifcapable              EXPR
#







>

>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#-------------------------------------------------------------------------
# The commands provided by the code in this file to help with creating 
# test cases are as follows:
#
# Commands to manipulate the db and the file-system at a high level:
#
#      copy_file              FROM TO
#      delete_file            FILENAME
#      drop_all_tables        ?DB?
#      forcecopy              FROM TO
#      forcedelete            FILENAME
#
# Test the capability of the SQLite version built into the interpreter to
# determine if a specific test can be run:
#
#      ifcapable              EXPR
#
118
119
120
121
122
123
124



















































































































125
126
127
128
129
130
131
      # This command is not opening a new database connection. Pass the 
      # arguments through to the C implemenation as the are.
      #
      uplevel 1 sqlite_orig $args
    }
  }
}




















































































































proc execpresql {handle args} {
  trace remove execution $handle enter [list execpresql $handle]
  if {[info exists ::G(perm:presql)]} {
    $handle eval $::G(perm:presql)
  }
}







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







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
      # This command is not opening a new database connection. Pass the 
      # arguments through to the C implemenation as the are.
      #
      uplevel 1 sqlite_orig $args
    }
  }
}

proc getFileRetries {} {
  if {![info exists ::G(file-retries)]} {
    #
    # NOTE: Return the default number of retries for [file] operations.  A
    #       value of zero or less here means "disabled".
    #
    return [expr {$::tcl_platform(platform) eq "windows" ? 10 : 0}]
  }
  return $::G(file-retries)
}

proc getFileRetryDelay {} {
  if {![info exists ::G(file-retry-delay)]} {
    #
    # NOTE: Return the default number of milliseconds to wait when retrying
    #       failed [file] operations.  A value of zero or less means "do not
    #       wait".
    #
    return 100; # TODO: Good default?
  }
  return $::G(file-retry-delay)
}

# Copy file $from into $to. This is used because some versions of
# TCL for windows (notably the 8.4.1 binary package shipped with the
# current mingw release) have a broken "file copy" command.
#
proc copy_file {from to} {
  do_copy_file false $from $to
}

proc forcecopy {from to} {
  do_copy_file true $from $to
}

proc do_copy_file {force from to} {
  set nRetry [getFileRetries]     ;# Maximum number of retries.
  set nDelay [getFileRetryDelay]  ;# Delay in ms before retrying.

  # On windows, sometimes even a [file copy -force] can fail. The cause is
  # usually "tag-alongs" - programs like anti-virus software, automatic backup
  # tools and various explorer extensions that keep a file open a little longer
  # than we expect, causing the delete to fail.
  #
  # The solution is to wait a short amount of time before retrying the copy.
  #
  if {$nRetry > 0} {
    for {set i 0} {$i<$nRetry} {incr i} {
      set rc [catch {
        if {$force} {
          file copy -force $from $to
        } else {
          file copy $from $to
        }
      } msg]
      if {$rc==0} break
      if {$nDelay > 0} { after $nDelay }
    }
    if {$rc} { error $msg }
  } else {
    if {$force} {
      file copy -force $from $to
    } else {
      file copy $from $to
    }
  }
}

# Delete a file or directory
#
proc delete_file {args} {
  do_delete_file false {*}$args
}

proc forcedelete {args} {
  do_delete_file true {*}$args
}

proc do_delete_file {force args} {
  set nRetry [getFileRetries]     ;# Maximum number of retries.
  set nDelay [getFileRetryDelay]  ;# Delay in ms before retrying.

  foreach filename $args {
    # On windows, sometimes even a [file delete -force] can fail just after
    # a file is closed. The cause is usually "tag-alongs" - programs like
    # anti-virus software, automatic backup tools and various explorer
    # extensions that keep a file open a little longer than we expect, causing
    # the delete to fail.
    #
    # The solution is to wait a short amount of time before retrying the
    # delete.
    #
    if {$nRetry > 0} {
      for {set i 0} {$i<$nRetry} {incr i} {
        set rc [catch {
          if {$force} {
            file delete -force $filename
          } else {
            file delete $filename
          }
        } msg]
        if {$rc==0} break
        if {$nDelay > 0} { after $nDelay }
      }
      if {$rc} { error $msg }
    } else {
      if {$force} {
        file delete -force $filename
      } else {
        file delete $filename
      }
    }
  }
}

proc execpresql {handle args} {
  trace remove execution $handle enter [list execpresql $handle]
  if {[info exists ::G(perm:presql)]} {
    $handle eval $::G(perm:presql)
  }
}
150
151
152
153
154
155
156


157
158
159
160
161
162
163
164


165
166
167
168
169
170
171
  #   --pause
  #   --soft-heap-limit=NN
  #   --maxerror=NN
  #   --malloctrace=N
  #   --backtrace=N
  #   --binarylog=N
  #   --soak=N


  #   --start=[$permutation:]$testfile
  #
  set cmdlinearg(soft-heap-limit)    0
  set cmdlinearg(maxerror)        1000
  set cmdlinearg(malloctrace)        0
  set cmdlinearg(backtrace)         10
  set cmdlinearg(binarylog)          0
  set cmdlinearg(soak)               0


  set cmdlinearg(start)             "" 

  set leftover [list]
  foreach a $argv {
    switch -regexp -- $a {
      {^-+pause$} {
        # Wait for user input before continuing. This is to give the user an 







>
>








>
>







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
  #   --pause
  #   --soft-heap-limit=NN
  #   --maxerror=NN
  #   --malloctrace=N
  #   --backtrace=N
  #   --binarylog=N
  #   --soak=N
  #   --file-retries=N
  #   --file-retry-delay=N
  #   --start=[$permutation:]$testfile
  #
  set cmdlinearg(soft-heap-limit)    0
  set cmdlinearg(maxerror)        1000
  set cmdlinearg(malloctrace)        0
  set cmdlinearg(backtrace)         10
  set cmdlinearg(binarylog)          0
  set cmdlinearg(soak)               0
  set cmdlinearg(file-retries)       0
  set cmdlinearg(file-retry-delay)   0
  set cmdlinearg(start)             "" 

  set leftover [list]
  foreach a $argv {
    switch -regexp -- $a {
      {^-+pause$} {
        # Wait for user input before continuing. This is to give the user an 
193
194
195
196
197
198
199








200
201
202
203
204
205
206
      {^-+binarylog=.+$} {
        foreach {dummy cmdlinearg(binarylog)} [split $a =] break
      }
      {^-+soak=.+$} {
        foreach {dummy cmdlinearg(soak)} [split $a =] break
        set ::G(issoak) $cmdlinearg(soak)
      }








      {^-+start=.+$} {
        foreach {dummy cmdlinearg(start)} [split $a =] break

        set ::G(start:file) $cmdlinearg(start)
        if {[regexp {(.*):(.*)} $cmdlinearg(start) -> s.perm s.file]} {
          set ::G(start:permutation) ${s.perm}
          set ::G(start:file)        ${s.file}







>
>
>
>
>
>
>
>







314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
      {^-+binarylog=.+$} {
        foreach {dummy cmdlinearg(binarylog)} [split $a =] break
      }
      {^-+soak=.+$} {
        foreach {dummy cmdlinearg(soak)} [split $a =] break
        set ::G(issoak) $cmdlinearg(soak)
      }
      {^-+file-retries=.+$} {
        foreach {dummy cmdlinearg(file-retries)} [split $a =] break
        set ::G(file-retries) $cmdlinearg(file-retries)
      }
      {^-+file-retry-delay=.+$} {
        foreach {dummy cmdlinearg(file-retry-delay)} [split $a =] break
        set ::G(file-retry-delay) $cmdlinearg(file-retry-delay)
      }
      {^-+start=.+$} {
        foreach {dummy cmdlinearg(start)} [split $a =] break

        set ::G(start:file) $cmdlinearg(start)
        if {[regexp {(.*):(.*)} $cmdlinearg(start) -> s.perm s.file]} {
          set ::G(start:permutation) ${s.perm}
          set ::G(start:file)        ${s.file}
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#
sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)

# Create a test database
#
proc reset_db {} {
  catch {db close}
  file delete -force test.db
  file delete -force test.db-journal
  file delete -force test.db-wal
  sqlite3 db ./test.db
  set ::DB [sqlite3_connection_pointer db]
  if {[info exists ::SETUP_SQL]} {
    db eval $::SETUP_SQL
  }
}
reset_db







|
|
|







371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
#
sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)

# Create a test database
#
proc reset_db {} {
  catch {db close}
  forcedelete test.db
  forcedelete test.db-journal
  forcedelete test.db-wal
  sqlite3 db ./test.db
  set ::DB [sqlite3_connection_pointer db]
  if {[info exists ::SETUP_SQL]} {
    db eval $::SETUP_SQL
  }
}
reset_db
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
    if {[sqlite3_memory_used]>0} {
      puts "Writing leaks.sql..."
      sqlite3_memdebug_log sync
      memdebug_log_sql leaks.sql
    }
  }
  foreach f [glob -nocomplain test.db-*-journal] {
    file delete -force $f
  }
  foreach f [glob -nocomplain test.db-mj*] {
    file delete -force $f
  }
  exit [expr {$nErr>0}]
}

# Display memory statistics for analysis and debugging purposes.
#
proc show_memstats {} {







|


|







747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
    if {[sqlite3_memory_used]>0} {
      puts "Writing leaks.sql..."
      sqlite3_memdebug_log sync
      memdebug_log_sql leaks.sql
    }
  }
  foreach f [glob -nocomplain test.db-*-journal] {
    forcedelete $f
  }
  foreach f [glob -nocomplain test.db-mj*] {
    forcedelete $f
  }
  exit [expr {$nErr>0}]
}

# Display memory statistics for analysis and debugging purposes.
#
proc show_memstats {} {
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
    if {[catch {sqlite3_finalize $vm} errmsg]} {
      return [list 1 $errmsg]
    }
  }
  return $r
}

# Delete a file or directory
#
proc forcedelete {args} {
  foreach filename $args {
    # On windows, sometimes even a [file delete -force] can fail just after
    # a file is closed. The cause is usually "tag-alongs" - programs like
    # anti-virus software, automatic backup tools and various explorer
    # extensions that keep a file open a little longer than we expect, causing
    # the delete to fail.
    #
    # The solution is to wait a short amount of time before retrying the 
    # delete.
    #
    set nRetry  50                  ;# Maximum number of retries.
    set nDelay 100                  ;# Delay in ms before retrying.
    for {set i 0} {$i<$nRetry} {incr i} {
      set rc [catch {file delete -force $filename} msg]
      if {$rc==0} break
      after $nDelay
    }
    if {$rc} { error $msg }
  }
}

# Do an integrity check of the entire database
#
proc integrity_check {name {db db}} {
  ifcapable integrityck {
    do_test $name [list execsql {PRAGMA integrity_check} $db] {ok}
  }
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







865
866
867
868
869
870
871
























872
873
874
875
876
877
878
    if {[catch {sqlite3_finalize $vm} errmsg]} {
      return [list 1 $errmsg]
    }
  }
  return $r
}

























# Do an integrity check of the entire database
#
proc integrity_check {name {db db}} {
  ifcapable integrityck {
    do_test $name [list execsql {PRAGMA integrity_check} $db] {ok}
  }
}
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977

    # Delete the files test.db and test2.db, then execute the TCL and 
    # SQL (in that order) to prepare for the test case.
    do_test $testname.$n.1 {
      set ::sqlite_io_error_pending 0
      catch {db close}
      catch {db2 close}
      catch {file delete -force test.db}
      catch {file delete -force test.db-journal}
      catch {file delete -force test2.db}
      catch {file delete -force test2.db-journal}
      set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
      sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
      if {[info exists ::ioerropts(-tclprep)]} {
        eval $::ioerropts(-tclprep)
      }
      if {[info exists ::ioerropts(-sqlprep)]} {
        execsql $::ioerropts(-sqlprep)







|
|
|
|







1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082

    # Delete the files test.db and test2.db, then execute the TCL and 
    # SQL (in that order) to prepare for the test case.
    do_test $testname.$n.1 {
      set ::sqlite_io_error_pending 0
      catch {db close}
      catch {db2 close}
      catch {forcedelete test.db}
      catch {forcedelete test.db-journal}
      catch {forcedelete test2.db}
      catch {forcedelete test2.db-journal}
      set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
      sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
      if {[info exists ::ioerropts(-tclprep)]} {
        eval $::ioerropts(-tclprep)
      }
      if {[info exists ::ioerropts(-sqlprep)]} {
        execsql $::ioerropts(-sqlprep)
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
  }

  set fd [open $filename w]
  puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;"
  close $fd
}

# Copy file $from into $to. This is used because some versions of
# TCL for windows (notably the 8.4.1 binary package shipped with the
# current mingw release) have a broken "file copy" command.
#
proc copy_file {from to} {
  if {$::tcl_platform(platform)=="unix"} {
    file copy -force $from $to
  } else {
    set f [open $from]
    fconfigure $f -translation binary
    set t [open $to w]
    fconfigure $t -translation binary
    puts -nonewline $t [read $f [file size $from]]
    close $t
    close $f
  }
}

# Drop all tables in database [db]
proc drop_all_tables {{db db}} {
  ifcapable trigger&&foreignkey {
    set pk [$db one "PRAGMA foreign_keys"]
    $db eval "PRAGMA foreign_keys = OFF"
  }
  foreach {idx name file} [db eval {PRAGMA database_list}] {







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1342
1343
1344
1345
1346
1347
1348


















1349
1350
1351
1352
1353
1354
1355
  }

  set fd [open $filename w]
  puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;"
  close $fd
}



















# Drop all tables in database [db]
proc drop_all_tables {{db db}} {
  ifcapable trigger&&foreignkey {
    set pk [$db one "PRAGMA foreign_keys"]
    $db eval "PRAGMA foreign_keys = OFF"
  }
  foreach {idx name file} [db eval {PRAGMA database_list}] {
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
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
  return ""
}

proc db_save {} {
  foreach f [glob -nocomplain sv_test.db*] { forcedelete $f }
  foreach f [glob -nocomplain test.db*] {
    set f2 "sv_$f"
    file copy -force $f $f2
  }
}
proc db_save_and_close {} {
  db_save
  catch { db close }
  return ""
}
proc db_restore {} {
  foreach f [glob -nocomplain test.db*] { forcedelete $f }
  foreach f2 [glob -nocomplain sv_test.db*] {
    set f [string range $f2 3 end]
    file copy -force $f2 $f
  }
}
proc db_restore_and_reopen {{dbfile test.db}} {
  catch { db close }
  db_restore
  sqlite3 db $dbfile
}
proc db_delete_and_reopen {{file test.db}} {
  catch { db close }
  foreach f [glob -nocomplain test.db*] { file delete -force $f }
  sqlite3 db $file
}

# If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set
# to non-zero, then set the global variable $AUTOVACUUM to 1.
set AUTOVACUUM $sqlite_options(default_autovacuum)

source $testdir/thread_common.tcl
source $testdir/malloc_common.tcl







|











|









|









1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
  return ""
}

proc db_save {} {
  foreach f [glob -nocomplain sv_test.db*] { forcedelete $f }
  foreach f [glob -nocomplain test.db*] {
    set f2 "sv_$f"
    forcecopy $f $f2
  }
}
proc db_save_and_close {} {
  db_save
  catch { db close }
  return ""
}
proc db_restore {} {
  foreach f [glob -nocomplain test.db*] { forcedelete $f }
  foreach f2 [glob -nocomplain sv_test.db*] {
    set f [string range $f2 3 end]
    forcecopy $f2 $f
  }
}
proc db_restore_and_reopen {{dbfile test.db}} {
  catch { db close }
  db_restore
  sqlite3 db $dbfile
}
proc db_delete_and_reopen {{file test.db}} {
  catch { db close }
  foreach f [glob -nocomplain test.db*] { forcedelete $f }
  sqlite3 db $file
}

# If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set
# to non-zero, then set the global variable $AUTOVACUUM to 1.
set AUTOVACUUM $sqlite_options(default_autovacuum)

source $testdir/thread_common.tcl
source $testdir/malloc_common.tcl

Changes to test/thread002.test.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

set ::NTHREAD 10

do_test thread002.1 {
  # Create 3 databases with identical schemas:
  for {set ii 0} {$ii < 3} {incr ii} {
    file delete -force test${ii}.db
    sqlite3 db test${ii}.db
    execsql {
      CREATE TABLE t1(k, v);
      CREATE INDEX t1_i ON t1(v);
      INSERT INTO t1(v) VALUES(1.0);
    }
    db close







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]

set ::NTHREAD 10

do_test thread002.1 {
  # Create 3 databases with identical schemas:
  for {set ii 0} {$ii < 3} {incr ii} {
    forcedelete test${ii}.db
    sqlite3 db test${ii}.db
    execsql {
      CREATE TABLE t1(k, v);
      CREATE INDEX t1_i ON t1(v);
      INSERT INTO t1(v) VALUES(1.0);
    }
    db close

Changes to test/thread003.test.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  }
} {}
do_test thread003.1.2 {
  expr {([file size test.db] / 1024) > 2000}
} {1}
do_test thread003.1.3 {
  db close
  file delete -force test2.db
  sqlite3 db test2.db
} {}
do_test thread003.1.4 {
  execsql {
    BEGIN;
    CREATE TABLE t1(a, b, c);
  }







|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  }
} {}
do_test thread003.1.2 {
  expr {([file size test.db] / 1024) > 2000}
} {1}
do_test thread003.1.3 {
  db close
  forcedelete test2.db
  sqlite3 db test2.db
} {}
do_test thread003.1.4 {
  execsql {
    BEGIN;
    CREATE TABLE t1(a, b, c);
  }

Changes to test/thread005.test.

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# when using an ATTACHed database. There doesn't seem to be any reason
# for this, other than that operating on an ATTACHed database means there
# are a few more mutex grabs and releases during the window of time open
# for the race-condition. Maybe this encourages the scheduler to context
# switch or something...
#

file delete -force test.db test2.db
unset -nocomplain finished

do_test thread005-2.1 {
  sqlite3 db test.db
  execsql { ATTACH 'test2.db' AS aux }
  execsql {
    CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b UNIQUE);







|







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# when using an ATTACHed database. There doesn't seem to be any reason
# for this, other than that operating on an ATTACHed database means there
# are a few more mutex grabs and releases during the window of time open
# for the race-condition. Maybe this encourages the scheduler to context
# switch or something...
#

forcedelete test.db test2.db
unset -nocomplain finished

do_test thread005-2.1 {
  sqlite3 db test.db
  execsql { ATTACH 'test2.db' AS aux }
  execsql {
    CREATE TABLE aux.t1(a INTEGER PRIMARY KEY, b UNIQUE);

Changes to test/tkt-2d1a5c67d.test.

114
115
116
117
118
119
120
121
122
123
124
125
126
127
  execsql { SELECT * FROM t4 WHERE a = 'xyz' }
} {xyz}

# Check that recovery works on the WAL file.
#
forcedelete test.db2-wal test.db2
do_test 3.6 {
  file copy test.db-wal test.db2-wal
  file copy test.db test.db2
  sqlite3 db2 test.db2
  execsql { SELECT * FROM t4 WHERE a = 'xyz' } db2
} {xyz}

finish_test







|
|





114
115
116
117
118
119
120
121
122
123
124
125
126
127
  execsql { SELECT * FROM t4 WHERE a = 'xyz' }
} {xyz}

# Check that recovery works on the WAL file.
#
forcedelete test.db2-wal test.db2
do_test 3.6 {
  copy_file test.db-wal test.db2-wal
  copy_file test.db test.db2
  sqlite3 db2 test.db2
  execsql { SELECT * FROM t4 WHERE a = 'xyz' } db2
} {xyz}

finish_test

Changes to test/tkt-5ee23731f.test.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#

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

do_test tkt-5ee237-1.1 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  db eval {
    CREATE TABLE t1(x UNIQUE);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 SELECT x+2 FROM t1;
    INSERT INTO t1 SELECT x+4 FROM t1;







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#

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

do_test tkt-5ee237-1.1 {
  db close
  forcedelete test.db
  sqlite3 db test.db
  db eval {
    CREATE TABLE t1(x UNIQUE);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 SELECT x+2 FROM t1;
    INSERT INTO t1 SELECT x+4 FROM t1;

Changes to test/tkt-f3e5abed55.test.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#***********************************************************************
#

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

foreach f [glob -nocomplain test.db*mj*] { file delete -force $f }
file delete -force test.db2

do_test tkt-f3e5abed55-1.1 {
  execsql {
    ATTACH 'test.db2' AS aux;
    CREATE TABLE main.t1(a, b);
    CREATE TABLE aux.t2(c, d);
  }







|
|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#***********************************************************************
#

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

foreach f [glob -nocomplain test.db*mj*] { forcedelete $f }
forcedelete test.db2

do_test tkt-f3e5abed55-1.1 {
  execsql {
    ATTACH 'test.db2' AS aux;
    CREATE TABLE main.t1(a, b);
    CREATE TABLE aux.t2(c, d);
  }
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  execsql COMMIT db2
  execsql COMMIT
} {}

do_test tkt-f3e5abed55-1.6 {
  glob -nocomplain test.db*mj*
} {}
foreach f [glob -nocomplain test.db*mj*] { file delete -force $f }
db close
db2 close



# Set up a testvfs so that the next time SQLite tries to delete the
# file "test.db-journal", a snapshot of the current file-system contents







|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  execsql COMMIT db2
  execsql COMMIT
} {}

do_test tkt-f3e5abed55-1.6 {
  glob -nocomplain test.db*mj*
} {}
foreach f [glob -nocomplain test.db*mj*] { forcedelete $f }
db close
db2 close



# Set up a testvfs so that the next time SQLite tries to delete the
# file "test.db-journal", a snapshot of the current file-system contents

Changes to test/tkt1667.test.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

ifcapable !autovacuum||!tclvar {
  finish_test
  return
}

db close
file delete -force test.db test.db-journal

# Set the pending byte offset such that the page it is on is
# the first autovacuum pointer map page in the file (assume a page 
# size of 1024).

set first_ptrmap_page   [expr 1024/5 + 3]
sqlite3_test_control_pending_byte [expr 1024 * ($first_ptrmap_page-1)]







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

ifcapable !autovacuum||!tclvar {
  finish_test
  return
}

db close
forcedelete test.db test.db-journal

# Set the pending byte offset such that the page it is on is
# the first autovacuum pointer map page in the file (assume a page 
# size of 1024).

set first_ptrmap_page   [expr 1024/5 + 3]
sqlite3_test_control_pending_byte [expr 1024 * ($first_ptrmap_page-1)]

Changes to test/tkt1873.test.

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

ifcapable !attach {
  finish_test
  return
}

file delete -force test2.db test2.db-journal

do_test tkt1873-1.1 {
  execsql {
    CREATE TABLE t1(x, y);
    ATTACH 'test2.db' AS aux;
    CREATE TABLE aux.t2(x, y);
    INSERT INTO t1 VALUES(1, 2);







|







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

ifcapable !attach {
  finish_test
  return
}

forcedelete test2.db test2.db-journal

do_test tkt1873-1.1 {
  execsql {
    CREATE TABLE t1(x, y);
    ATTACH 'test2.db' AS aux;
    CREATE TABLE aux.t2(x, y);
    INSERT INTO t1 VALUES(1, 2);

Changes to test/tkt2686.test.

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    }
  } {}
  integrity_check tkt2686-$i.3
  catch {db eval COMMIT}
}

db close
file delete -force test.db test.db-journal
sqlite3 db test.db

db eval {
  PRAGMA page_size=1024;
  PRAGMA max_page_count=50;
  PRAGMA auto_vacuum=1;
  CREATE TABLE filler (fill);







|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    }
  } {}
  integrity_check tkt2686-$i.3
  catch {db eval COMMIT}
}

db close
forcedelete test.db test.db-journal
sqlite3 db test.db

db eval {
  PRAGMA page_size=1024;
  PRAGMA max_page_count=50;
  PRAGMA auto_vacuum=1;
  CREATE TABLE filler (fill);

Changes to test/tkt2817.test.

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


# These tests - tkt2817-2.* - are the same as the previous block, except
# for the fact that the temp-table and the main table do not share the
# same name. #2817 did not cause a problem with these tests.
#
db close
file delete -force test.db
sqlite3 db test.db
do_test tkt2817-2.0 {
  execsql {
    CREATE TEMP TABLE tmp(a, b, c);
    INSERT INTO tmp VALUES(1, 'abc', 'def');
    INSERT INTO tmp VALUES(2, 'ghi', 'jkl');
  }







|







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


# These tests - tkt2817-2.* - are the same as the previous block, except
# for the fact that the temp-table and the main table do not share the
# same name. #2817 did not cause a problem with these tests.
#
db close
forcedelete test.db
sqlite3 db test.db
do_test tkt2817-2.0 {
  execsql {
    CREATE TEMP TABLE tmp(a, b, c);
    INSERT INTO tmp VALUES(1, 'abc', 'def');
    INSERT INTO tmp VALUES(2, 'ghi', 'jkl');
  }

Changes to test/tkt2820.test.

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

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

proc test_schema_change {testid init ddl res} {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql $init
  do_test tkt2820-$testid.1 {
    set STMT [sqlite3_prepare db {SELECT * FROM sqlite_master} -1 DUMMY]
    sqlite3_step $STMT
  } {SQLITE_ROW}
#if {$testid==3} {execsql {PRAGMA vdbe_trace=ON}}







|







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

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

proc test_schema_change {testid init ddl res} {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  execsql $init
  do_test tkt2820-$testid.1 {
    set STMT [sqlite3_prepare db {SELECT * FROM sqlite_master} -1 DUMMY]
    sqlite3_step $STMT
  } {SQLITE_ROW}
#if {$testid==3} {execsql {PRAGMA vdbe_trace=ON}}
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# We further observe that prior to the fix associated with ticket #2820,
# no statement journal would be created on an SQL statement that was run
# while a second statement was active, as long as we are in autocommit
# mode.  This is incorrect.
#
do_test tkt2820-4.1 {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  db eval {
    CREATE TABLE t1(a INTEGER PRIMARY KEY);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
  }








|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# We further observe that prior to the fix associated with ticket #2820,
# no statement journal would be created on an SQL statement that was run
# while a second statement was active, as long as we are in autocommit
# mode.  This is incorrect.
#
do_test tkt2820-4.1 {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  db eval {
    CREATE TABLE t1(a INTEGER PRIMARY KEY);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
  }

Changes to test/tkt2854.test.

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  execsql { SELECT * FROM abc } db2
} {}

# Check that if an attempt to obtain an exclusive lock fails because an
# attached db cannot be locked, the internal exclusive flag used by
# shared-cache users is correctly cleared.
do_test tkt2854-1.19 {
  file delete -force test2.db test2.db-journal
  sqlite3 db4 test2.db
  execsql { CREATE TABLE def(d, e, f) } db4
  execsql { ATTACH 'test2.db' AS aux } db
} {}
do_test tkt2854-1.20 {
  execsql {BEGIN IMMEDIATE} db4
  catchsql {BEGIN EXCLUSIVE} db







|







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  execsql { SELECT * FROM abc } db2
} {}

# Check that if an attempt to obtain an exclusive lock fails because an
# attached db cannot be locked, the internal exclusive flag used by
# shared-cache users is correctly cleared.
do_test tkt2854-1.19 {
  forcedelete test2.db test2.db-journal
  sqlite3 db4 test2.db
  execsql { CREATE TABLE def(d, e, f) } db4
  execsql { ATTACH 'test2.db' AS aux } db
} {}
do_test tkt2854-1.20 {
  execsql {BEGIN IMMEDIATE} db4
  catchsql {BEGIN EXCLUSIVE} db

Changes to test/tkt3457.test.

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
  execsql {
    CREATE TABLE t1(a, b, c);
    INSERT INTO t1 VALUES(1, 2, 3);
    BEGIN;
    INSERT INTO t1 VALUES(4, 5, 6);
  }

  file copy -force test.db bak.db
  file copy -force test.db-journal bak.db-journal

  # Fix the first journal-header in the journal-file. Because the
  # journal file has not yet been synced, the 8-byte magic string at the
  # start of the first journal-header has not been written by SQLite.
  # So write it now.
  set fd [open bak.db-journal a+]
  fconfigure $fd -encoding binary -translation binary
  seek $fd 0
  puts -nonewline $fd "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
  close $fd

  execsql COMMIT
} {}

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

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

finish_test







|
|















|




|




|





|





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
  execsql {
    CREATE TABLE t1(a, b, c);
    INSERT INTO t1 VALUES(1, 2, 3);
    BEGIN;
    INSERT INTO t1 VALUES(4, 5, 6);
  }

  forcecopy test.db bak.db
  forcecopy test.db-journal bak.db-journal

  # Fix the first journal-header in the journal-file. Because the
  # journal file has not yet been synced, the 8-byte magic string at the
  # start of the first journal-header has not been written by SQLite.
  # So write it now.
  set fd [open bak.db-journal a+]
  fconfigure $fd -encoding binary -translation binary
  seek $fd 0
  puts -nonewline $fd "\xd9\xd5\x05\xf9\x20\xa1\x63\xd7"
  close $fd

  execsql COMMIT
} {}

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

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

finish_test

Changes to test/tkt35xx.test.

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    INSERT INTO t1 VALUES(1, 1, zeroblob(676));
  }
} {}

# Trigger the problem using statement rollback.
#
db close
file delete test.db
sqlite3 db test.db
set big [string repeat abcdefghij 22]    ;# 220 byte string
do_test tkt35xx-1.2.1 {
  execsql {
    PRAGMA auto_vacuum = 0;
    PRAGMA page_size = 1024;
    CREATE TABLE t3(a INTEGER PRIMARY KEY, b);







|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    INSERT INTO t1 VALUES(1, 1, zeroblob(676));
  }
} {}

# Trigger the problem using statement rollback.
#
db close
delete_file test.db
sqlite3 db test.db
set big [string repeat abcdefghij 22]    ;# 220 byte string
do_test tkt35xx-1.2.1 {
  execsql {
    PRAGMA auto_vacuum = 0;
    PRAGMA page_size = 1024;
    CREATE TABLE t3(a INTEGER PRIMARY KEY, b);

Changes to test/trigger1.test.

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
# correctly re-installed.
#
# Also verify that references within trigger programs are resolved at
# statement compile time, not trigger installation time. This means, for
# example, that you can drop and re-create tables referenced by triggers. 
ifcapable tempdb&&attach {
  do_test trigger1-10.0 {
    file delete -force test2.db
    file delete -force test2.db-journal
    execsql {
      ATTACH 'test2.db' AS aux;
    }
  } {}
  do_test trigger1-10.1 {
    execsql {
      CREATE TABLE main.t4(a, b, c);







|
|







530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
# correctly re-installed.
#
# Also verify that references within trigger programs are resolved at
# statement compile time, not trigger installation time. This means, for
# example, that you can drop and re-create tables referenced by triggers. 
ifcapable tempdb&&attach {
  do_test trigger1-10.0 {
    forcedelete test2.db
    forcedelete test2.db-journal
    execsql {
      ATTACH 'test2.db' AS aux;
    }
  } {}
  do_test trigger1-10.1 {
    execsql {
      CREATE TABLE main.t4(a, b, c);

Changes to test/trigger4.test.

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    update test set b=99 where id=7;
    select * from test2;
  }
} {7 99}

do_test trigger4-4.1 {
    db close
    file delete -force trigtest.db
    file delete -force trigtest.db-journal
    sqlite3 db trigtest.db
    catchsql {drop table tbl; drop view vw}
    execsql {
	create table tbl(a integer primary key, b integer);
	create view vw as select * from tbl;
	create trigger t_del_tbl instead of delete on vw for each row begin
	  delete from tbl where a = old.a;







|
|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    update test set b=99 where id=7;
    select * from test2;
  }
} {7 99}

do_test trigger4-4.1 {
    db close
    forcedelete trigtest.db
    forcedelete trigtest.db-journal
    sqlite3 db trigtest.db
    catchsql {drop table tbl; drop view vw}
    execsql {
	create table tbl(a integer primary key, b integer);
	create view vw as select * from tbl;
	create trigger t_del_tbl instead of delete on vw for each row begin
	  delete from tbl where a = old.a;
191
192
193
194
195
196
197
198
199
200
} {0 {}}
do_test trigger4-7.2 {
    execsql {select a, b from vw where a<=102 or a>=227 order by a}
} {101 1001 102 2002 227 2127 228 2128}

integrity_check trigger4-99.9
db close
file delete -force trigtest.db trigtest.db-journal

finish_test







|


191
192
193
194
195
196
197
198
199
200
} {0 {}}
do_test trigger4-7.2 {
    execsql {select a, b from vw where a<=102 or a>=227 order by a}
} {101 1001 102 2002 227 2127 228 2128}

integrity_check trigger4-99.9
db close
forcedelete trigtest.db trigtest.db-journal

finish_test

Changes to test/triggerA.test.

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
   return
}
source $testdir/malloc_common.tcl

# Save a copy of the current database configuration.
#
db close
file delete -force test.db-triggerA
file copy test.db test.db-triggerA
sqlite3 db test.db

# Run malloc tests on the INSTEAD OF trigger firing.
#
do_malloc_test triggerA-3 -tclprep {
  db close
  file delete -force test.db test.db-journal
  file copy -force test.db-triggerA test.db
  sqlite3 db test.db
  sqlite3_extended_result_codes db 1  
  db eval {SELECT * FROM v5; -- warm up the cache}
} -sqlbody {
   DELETE FROM v5 WHERE x=5;
   UPDATE v5 SET b=b+9900000 WHERE x BETWEEN 3 AND 5;
}

# Clean up the saved database copy.
#
file delete -force test.db-triggerA

finish_test







|
|






|
|










|


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
   return
}
source $testdir/malloc_common.tcl

# Save a copy of the current database configuration.
#
db close
forcedelete test.db-triggerA
copy_file test.db test.db-triggerA
sqlite3 db test.db

# Run malloc tests on the INSTEAD OF trigger firing.
#
do_malloc_test triggerA-3 -tclprep {
  db close
  forcedelete test.db test.db-journal
  forcecopy test.db-triggerA test.db
  sqlite3 db test.db
  sqlite3_extended_result_codes db 1  
  db eval {SELECT * FROM v5; -- warm up the cache}
} -sqlbody {
   DELETE FROM v5 WHERE x=5;
   UPDATE v5 SET b=b+9900000 WHERE x BETWEEN 3 AND 5;
}

# Clean up the saved database copy.
#
forcedelete test.db-triggerA

finish_test

Changes to test/triggerC.test.

914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
    INSERT INTO v2 DEFAULT VALUES;
    SELECT a, b, a IS NULL, b IS NULL FROM log;
  }
} {{} {} 1 1}

do_test triggerC-12.1 {
  db close
  file delete -force test.db
  sqlite3 db test.db

  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);
    INSERT INTO t1 VALUES(5, 6);







|







914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
    INSERT INTO v2 DEFAULT VALUES;
    SELECT a, b, a IS NULL, b IS NULL FROM log;
  }
} {{} {} 1 1}

do_test triggerC-12.1 {
  db close
  forcedelete test.db
  sqlite3 db test.db

  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);
    INSERT INTO t1 VALUES(5, 6);

Changes to test/triggerD.test.

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# the sqlite_master table.  We cannot fix the bug simply by disallowing
# "xyz.tab" since that could break legacy applications.  We have to 
# fix the system so that the "xyz." on "xyz.tab" is ignored.
# Verify that this is the case.
#
do_test triggerD-4.1 {
  db close
  file delete -force test.db test2.db
  sqlite3 db test.db
  db eval {
    CREATE TABLE t1(x);
    ATTACH 'test2.db' AS db2;
    CREATE TABLE db2.t2(y);
    CREATE TABLE db2.log(z);
    CREATE TRIGGER db2.trig AFTER INSERT ON db2.t2 BEGIN







|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# the sqlite_master table.  We cannot fix the bug simply by disallowing
# "xyz.tab" since that could break legacy applications.  We have to 
# fix the system so that the "xyz." on "xyz.tab" is ignored.
# Verify that this is the case.
#
do_test triggerD-4.1 {
  db close
  forcedelete test.db test2.db
  sqlite3 db test.db
  db eval {
    CREATE TABLE t1(x);
    ATTACH 'test2.db' AS db2;
    CREATE TABLE db2.t2(y);
    CREATE TABLE db2.log(z);
    CREATE TRIGGER db2.trig AFTER INSERT ON db2.t2 BEGIN

Changes to test/vacuum.test.

204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

# Ticket #427.  Make sure VACUUM works when the EMPTY_RESULT_CALLBACKS
# pragma is turned on.
#
do_test vacuum-3.1 {
  db close
  db2 close
  file delete test.db
  sqlite3 db test.db
  execsql {
    PRAGMA empty_result_callbacks=on;
    VACUUM;
  }
} {}








|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

# Ticket #427.  Make sure VACUUM works when the EMPTY_RESULT_CALLBACKS
# pragma is turned on.
#
do_test vacuum-3.1 {
  db close
  db2 close
  delete_file test.db
  sqlite3 db test.db
  execsql {
    PRAGMA empty_result_callbacks=on;
    VACUUM;
  }
} {}

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

# Ticket #515.  VACUUM after deleting and recreating the table that
# a view refers to. Omit this test if the library is not view-enabled.
#
ifcapable view {
do_test vacuum-5.1 {
  db close
  file delete -force test.db
  sqlite3 db test.db
  catchsql {
    CREATE TABLE Test (TestID int primary key);
    INSERT INTO Test VALUES (NULL);
    CREATE VIEW viewTest AS SELECT * FROM Test;

    BEGIN;







|







230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

# Ticket #515.  VACUUM after deleting and recreating the table that
# a view refers to. Omit this test if the library is not view-enabled.
#
ifcapable view {
do_test vacuum-5.1 {
  db close
  forcedelete test.db
  sqlite3 db test.db
  catchsql {
    CREATE TABLE Test (TestID int primary key);
    INSERT INTO Test VALUES (NULL);
    CREATE VIEW viewTest AS SELECT * FROM Test;

    BEGIN;
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
    execsql {
      select count(*) from "abc abc" WHERE a = X'00112233';
    }
  } {1}
}

# Check what happens when an in-memory database is vacuumed. The
# [file delete] command covers us in case the library was compiled
# without in-memory database support.
#
file delete -force :memory:
do_test vacuum-7.0 {
  sqlite3 db2 :memory:
  execsql {
    CREATE TABLE t1(t);
    VACUUM;
  } db2
} {}







|


|







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
    execsql {
      select count(*) from "abc abc" WHERE a = X'00112233';
    }
  } {1}
}

# Check what happens when an in-memory database is vacuumed. The
# [delete_file] command covers us in case the library was compiled
# without in-memory database support.
#
forcedelete :memory:
do_test vacuum-7.0 {
  sqlite3 db2 :memory:
  execsql {
    CREATE TABLE t1(t);
    VACUUM;
  } db2
} {}
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
  } {1}
}
db2 close

# Ticket #873.  VACUUM a database that has ' in its name.
#
do_test vacuum-8.1 {
  file delete -force a'z.db
  file delete -force a'z.db-journal
  sqlite3 db2 a'z.db
  execsql {
    CREATE TABLE t1(t);
    VACUUM;
  } db2
} {}
db2 close







|
|







333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
  } {1}
}
db2 close

# Ticket #873.  VACUUM a database that has ' in its name.
#
do_test vacuum-8.1 {
  forcedelete a'z.db
  forcedelete a'z.db-journal
  sqlite3 db2 a'z.db
  execsql {
    CREATE TABLE t1(t);
    VACUUM;
  } db2
} {}
db2 close
379
380
381
382
383
384
385
386
387
388
    execsql {
      VACUUM;
    }
    cksum
  } $::cksum
}

file delete -force {a'z.db}

finish_test







|


379
380
381
382
383
384
385
386
387
388
    execsql {
      VACUUM;
    }
    cksum
  } $::cksum
}

forcedelete {a'z.db}

finish_test

Changes to test/vacuum2.test.

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
} {ok}

db2 close

ifcapable autovacuum {
  do_test vacuum2-4.1 {
    db close
    file delete -force test.db
    sqlite3 db test.db
    execsql {
      pragma auto_vacuum=1;
      create table t(a, b);
      insert into t values(1, 2);
      insert into t values(1, 2);
      pragma auto_vacuum=0;







|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
} {ok}

db2 close

ifcapable autovacuum {
  do_test vacuum2-4.1 {
    db close
    forcedelete test.db
    sqlite3 db test.db
    execsql {
      pragma auto_vacuum=1;
      create table t(a, b);
      insert into t values(1, 2);
      insert into t values(1, 2);
      pragma auto_vacuum=0;

Changes to test/vacuum3.test.

192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  integrity_check vacuum3-3.$I.3

  incr I
}

do_test vacuum3-4.1 {
  db close
  file delete test.db
  sqlite3 db test.db
  execsql {
    PRAGMA page_size=1024;
    CREATE TABLE abc(a, b, c);
    INSERT INTO abc VALUES(1, 2, 3);
    INSERT INTO abc VALUES(4, 5, 6);
  }







|







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  integrity_check vacuum3-3.$I.3

  incr I
}

do_test vacuum3-4.1 {
  db close
  delete_file test.db
  sqlite3 db test.db
  execsql {
    PRAGMA page_size=1024;
    CREATE TABLE abc(a, b, c);
    INSERT INTO abc VALUES(1, 2, 3);
    INSERT INTO abc VALUES(4, 5, 6);
  }

Changes to test/view.test.

454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  catchsql {
    CREATE VIEW v12 AS SELECT a FROM t1 WHERE b=?
  }
} {1 {parameters are not allowed in views}}

ifcapable attach {
  do_test view-13.1 {
    file delete -force test2.db
    catchsql {
      ATTACH 'test2.db' AS two;
      CREATE TABLE two.t2(x,y);
      CREATE VIEW v13 AS SELECT y FROM two.t2;
    }
  } {1 {view v13 cannot reference objects in database two}}
}







|







454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  catchsql {
    CREATE VIEW v12 AS SELECT a FROM t1 WHERE b=?
  }
} {1 {parameters are not allowed in views}}

ifcapable attach {
  do_test view-13.1 {
    forcedelete test2.db
    catchsql {
      ATTACH 'test2.db' AS two;
      CREATE TABLE two.t2(x,y);
      CREATE VIEW v13 AS SELECT y FROM two.t2;
    }
  } {1 {view v13 cannot reference objects in database two}}
}

Changes to test/vtab1.test.

720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
do_test vtab1-6-8.4 {
  execsql {
    SELECT * FROM techo ORDER BY a;
  }
} {}
execsql {PRAGMA count_changes=OFF}

file delete -force test2.db
file delete -force test2.db-journal
sqlite3 db2 test2.db
execsql {
  CREATE TABLE techo(a PRIMARY KEY, b, c);
} db2
proc check_echo_table {tn} {
  set ::data1 [execsql {SELECT rowid, * FROM techo}]
  set ::data2 [execsql {SELECT rowid, * FROM techo} db2]







|
|







720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
do_test vtab1-6-8.4 {
  execsql {
    SELECT * FROM techo ORDER BY a;
  }
} {}
execsql {PRAGMA count_changes=OFF}

forcedelete test2.db
forcedelete test2.db-journal
sqlite3 db2 test2.db
execsql {
  CREATE TABLE techo(a PRIMARY KEY, b, c);
} db2
proc check_echo_table {tn} {
  set ::data1 [execsql {SELECT rowid, * FROM techo}]
  set ::data2 [execsql {SELECT rowid, * FROM techo} db2]

Changes to test/vtab7.test.

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  set ::rc
} {1 {database table is locked}}
execsql {DROP TABLE newtab}

# Write to an attached database from xSync().
ifcapable attach {
  do_test vtab7-3.1 {
    file delete -force test2.db
    file delete -force test2.db-journal
    execsql {
      ATTACH 'test2.db' AS db2;
      CREATE TABLE db2.stuff(description, shape, color);
    }
    set ::callbacks(xSync,abc) {
      execsql { INSERT INTO db2.stuff VALUES('abc', 'square', 'green'); }
    }







|
|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  set ::rc
} {1 {database table is locked}}
execsql {DROP TABLE newtab}

# Write to an attached database from xSync().
ifcapable attach {
  do_test vtab7-3.1 {
    forcedelete test2.db
    forcedelete test2.db-journal
    execsql {
      ATTACH 'test2.db' AS db2;
      CREATE TABLE db2.stuff(description, shape, color);
    }
    set ::callbacks(xSync,abc) {
      execsql { INSERT INTO db2.stuff VALUES('abc', 'square', 'green'); }
    }

Changes to test/vtabC.test.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41


# N will be the number of virtual tables we have defined.
#
unset -nocomplain N
for {set N 1} {$N<=20} {incr N} {
  db close
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  register_echo_module [sqlite3_connection_pointer db]

  # Create $N tables and $N virtual tables to echo them.
  #
  unset -nocomplain tablist
  set tablist {}







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41


# N will be the number of virtual tables we have defined.
#
unset -nocomplain N
for {set N 1} {$N<=20} {incr N} {
  db close
  forcedelete test.db test.db-journal
  sqlite3 db test.db
  register_echo_module [sqlite3_connection_pointer db]

  # Create $N tables and $N virtual tables to echo them.
  #
  unset -nocomplain tablist
  set tablist {}

Changes to test/wal.test.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

set testprefix wal

ifcapable !wal {finish_test ; return }

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

set ::blobcnt 0
proc blob {nByte} {
  incr ::blobcnt
  return [string range [string repeat "${::blobcnt}x" $nByte] 1 $nByte]







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

set testprefix wal

ifcapable !wal {finish_test ; return }

proc reopen_db {} {
  catch { db close }
  forcedelete test.db test.db-wal test.db-wal-summary
  sqlite3_wal db test.db
}

set ::blobcnt 0
proc blob {nByte} {
  incr ::blobcnt
  return [string range [string repeat "${::blobcnt}x" $nByte] 1 $nByte]
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  }
  expr { $logsize == [file size test.db-wal] }
} {1}
do_test wal-4.4.5 {
  execsql { SELECT count(*) FROM t2 }
} {1}
do_test wal-4.4.6 {
  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal
  sqlite3 db2 test2.db
  execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
} {1 2}
do_test wal-4.4.7 {
  execsql { PRAGMA integrity_check } db2
} {ok}
db2 close







|
|







207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  }
  expr { $logsize == [file size test.db-wal] }
} {1}
do_test wal-4.4.5 {
  execsql { SELECT count(*) FROM t2 }
} {1}
do_test wal-4.4.6 {
  forcecopy test.db test2.db
  forcecopy test.db-wal test2.db-wal
  sqlite3 db2 test2.db
  execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
} {1 2}
do_test wal-4.4.7 {
  execsql { PRAGMA integrity_check } db2
} {ok}
db2 close
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  }
  expr { $logsize == [file size test.db-wal] }
} {1}
do_test wal-4.5.5 {
  execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 }
} {1 2}
do_test wal-4.5.6 {
  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal
  sqlite3 db2 test2.db
  execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
} {1 2}
do_test wal-4.5.7 {
  execsql { PRAGMA integrity_check } db2
} {ok}
db2 close







|
|







265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  }
  expr { $logsize == [file size test.db-wal] }
} {1}
do_test wal-4.5.5 {
  execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 }
} {1 2}
do_test wal-4.5.6 {
  forcecopy test.db test2.db
  forcecopy test.db-wal test2.db-wal
  sqlite3 db2 test2.db
  execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
} {1 2}
do_test wal-4.5.7 {
  execsql { PRAGMA integrity_check } db2
} {ok}
db2 close
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  }
} {1 2 3 4}
db close

foreach sector {512 4096} {
  sqlite3_simulate_device -sectorsize $sector
  foreach pgsz {512 1024 2048 4096} {
    file delete -force test.db test.db-wal
    do_test wal-6.$sector.$pgsz.1 {
      sqlite3 db test.db -vfs devsym
      execsql "
        PRAGMA page_size = $pgsz;
        PRAGMA auto_vacuum = 0;
        PRAGMA journal_mode = wal;
      "







|







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  }
} {1 2 3 4}
db close

foreach sector {512 4096} {
  sqlite3_simulate_device -sectorsize $sector
  foreach pgsz {512 1024 2048 4096} {
    forcedelete test.db test.db-wal
    do_test wal-6.$sector.$pgsz.1 {
      sqlite3 db test.db -vfs devsym
      execsql "
        PRAGMA page_size = $pgsz;
        PRAGMA auto_vacuum = 0;
        PRAGMA journal_mode = wal;
      "
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
    do_test wal-6.$sector.$pgsz.2 {
      log_deleted test.db-wal
    } {1}
  }
}

do_test wal-7.1 {
  file delete -force test.db test.db-wal
  sqlite3_wal db test.db
  execsql {
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }
  list [file size test.db] [file size test.db-wal]
} [list 1024 [wal_file_size 3 1024]]
do_test wal-7.2 {
  execsql { PRAGMA wal_checkpoint }
  list [file size test.db] [file size test.db-wal]
} [list 2048 [wal_file_size 3 1024]]

# Execute some transactions in auto-vacuum mode to test database file
# truncation.
#
do_test wal-8.1 {
  reopen_db
  catch { db close }
  file delete -force test.db test.db-wal

  sqlite3 db test.db
  db function blob blob
  execsql {
    PRAGMA auto_vacuum = 1;
    PRAGMA journal_mode = wal;
    PRAGMA auto_vacuum;







|



















|







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
    do_test wal-6.$sector.$pgsz.2 {
      log_deleted test.db-wal
    } {1}
  }
}

do_test wal-7.1 {
  forcedelete test.db test.db-wal
  sqlite3_wal db test.db
  execsql {
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
  }
  list [file size test.db] [file size test.db-wal]
} [list 1024 [wal_file_size 3 1024]]
do_test wal-7.2 {
  execsql { PRAGMA wal_checkpoint }
  list [file size test.db] [file size test.db-wal]
} [list 2048 [wal_file_size 3 1024]]

# Execute some transactions in auto-vacuum mode to test database file
# truncation.
#
do_test wal-8.1 {
  reopen_db
  catch { db close }
  forcedelete test.db test.db-wal

  sqlite3 db test.db
  db function blob blob
  execsql {
    PRAGMA auto_vacuum = 1;
    PRAGMA journal_mode = wal;
    PRAGMA auto_vacuum;
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
} 1024
do_test wal-9.2 {
  sqlite3_wal db2 test.db
  execsql {PRAGMA integrity_check } db2
} {ok}

do_test wal-9.3 {
  file delete -force test2.db test2.db-wal
  file copy test.db test2.db
  file copy test.db-wal test2.db-wal
  sqlite3_wal db3 test2.db 
  execsql {PRAGMA integrity_check } db3
} {ok}
db3 close

do_test wal-9.4 {
  execsql { PRAGMA wal_checkpoint }







|
|
|







431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
} 1024
do_test wal-9.2 {
  sqlite3_wal db2 test.db
  execsql {PRAGMA integrity_check } db2
} {ok}

do_test wal-9.3 {
  forcedelete test2.db test2.db-wal
  copy_file test.db test2.db
  copy_file test.db-wal test2.db-wal
  sqlite3_wal db3 test2.db 
  execsql {PRAGMA integrity_check } db3
} {ok}
db3 close

do_test wal-9.4 {
  execsql { PRAGMA wal_checkpoint }
782
783
784
785
786
787
788
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
814
815
  list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
} {3 1}
do_test wal-12.3 {
  execsql { INSERT INTO t2 VALUES('B', 1) }
  list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
} {3 2}
do_test wal-12.4 {
  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal
  sqlite3_wal db2 test2.db
  execsql { SELECT * FROM t2 } db2
} {B 1}
db2 close
do_test wal-12.5 {
  execsql {
    PRAGMA wal_checkpoint;
    UPDATE t2 SET y = 2 WHERE x = 'B'; 
    PRAGMA wal_checkpoint;
    UPDATE t1 SET y = 1 WHERE x = 'A';
    PRAGMA wal_checkpoint;
    UPDATE t1 SET y = 0 WHERE x = 'A';
  }
  execsql {  SELECT * FROM t2 }
} {B 2}
do_test wal-12.6 {
  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal
  sqlite3_wal db2 test2.db
  execsql { SELECT * FROM t2 } db2
} {B 2}
db2 close
db close

#-------------------------------------------------------------------------







|
|
















|
|







782
783
784
785
786
787
788
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
814
815
  list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
} {3 1}
do_test wal-12.3 {
  execsql { INSERT INTO t2 VALUES('B', 1) }
  list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
} {3 2}
do_test wal-12.4 {
  forcecopy test.db test2.db
  forcecopy test.db-wal test2.db-wal
  sqlite3_wal db2 test2.db
  execsql { SELECT * FROM t2 } db2
} {B 1}
db2 close
do_test wal-12.5 {
  execsql {
    PRAGMA wal_checkpoint;
    UPDATE t2 SET y = 2 WHERE x = 'B'; 
    PRAGMA wal_checkpoint;
    UPDATE t1 SET y = 1 WHERE x = 'A';
    PRAGMA wal_checkpoint;
    UPDATE t1 SET y = 0 WHERE x = 'A';
  }
  execsql {  SELECT * FROM t2 }
} {B 2}
do_test wal-12.6 {
  forcecopy test.db test2.db
  forcecopy test.db-wal test2.db-wal
  sqlite3_wal db2 test2.db
  execsql { SELECT * FROM t2 } db2
} {B 2}
db2 close
db close

#-------------------------------------------------------------------------
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
# that had an out-of-date pager-cache, the next time the connection was
# used it did not realize the cache was out-of-date and proceeded to
# operate with an inconsistent cache. Leading to corruption.
#
catch { db close }
catch { db2 close }
catch { db3 close }
file delete -force test.db test.db-wal
sqlite3 db test.db
sqlite3 db2 test.db
do_test wal-14 {
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a PRIMARY KEY, b);
    INSERT INTO t1 VALUES(randomblob(10), randomblob(100));







|







905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
# that had an out-of-date pager-cache, the next time the connection was
# used it did not realize the cache was out-of-date and proceeded to
# operate with an inconsistent cache. Leading to corruption.
#
catch { db close }
catch { db2 close }
catch { db3 close }
forcedelete test.db test.db-wal
sqlite3 db test.db
sqlite3 db2 test.db
do_test wal-14 {
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a PRIMARY KEY, b);
    INSERT INTO t1 VALUES(randomblob(10), randomblob(100));
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
catch { db close }
catch { db2 close }

#-------------------------------------------------------------------------
# The following block of tests - wal-15.* - focus on testing the 
# implementation of the sqlite3_wal_checkpoint() interface.
#
file delete -force test.db test.db-wal
sqlite3 db test.db
do_test wal-15.1 {
  execsql {
    PRAGMA auto_vacuum = 0;
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = WAL;
  }







|







943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
catch { db close }
catch { db2 close }

#-------------------------------------------------------------------------
# The following block of tests - wal-15.* - focus on testing the 
# implementation of the sqlite3_wal_checkpoint() interface.
#
forcedelete test.db test.db-wal
sqlite3 db test.db
do_test wal-15.1 {
  execsql {
    PRAGMA auto_vacuum = 0;
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = WAL;
  }
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
  5 {sqlite3_wal_checkpoint db aux}          SQLITE_OK     0 1
  6 {sqlite3_wal_checkpoint db temp}         SQLITE_OK     0 0
  7 {db eval "PRAGMA main.wal_checkpoint"}   {0 10 10}     1 0
  8 {db eval "PRAGMA aux.wal_checkpoint"}    {0 16 16}     0 1
  9 {db eval "PRAGMA temp.wal_checkpoint"}   {0 -1 -1}     0 0
} {
  do_test wal-16.$tn.1 {
    file delete -force test2.db test2.db-wal test2.db-journal
    file delete -force test.db test.db-wal test.db-journal

    sqlite3 db test.db
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA main.auto_vacuum = 0;
      PRAGMA aux.auto_vacuum = 0;
      PRAGMA main.journal_mode = WAL;







|
|







1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
  5 {sqlite3_wal_checkpoint db aux}          SQLITE_OK     0 1
  6 {sqlite3_wal_checkpoint db temp}         SQLITE_OK     0 0
  7 {db eval "PRAGMA main.wal_checkpoint"}   {0 10 10}     1 0
  8 {db eval "PRAGMA aux.wal_checkpoint"}    {0 16 16}     0 1
  9 {db eval "PRAGMA temp.wal_checkpoint"}   {0 -1 -1}     0 0
} {
  do_test wal-16.$tn.1 {
    forcedelete test2.db test2.db-wal test2.db-journal
    forcedelete test.db test.db-wal test.db-journal

    sqlite3 db test.db
    execsql {
      ATTACH 'test2.db' AS aux;
      PRAGMA main.auto_vacuum = 0;
      PRAGMA aux.auto_vacuum = 0;
      PRAGMA main.journal_mode = WAL;
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
  2   256  [wal_file_size 172 512]
  3   512  [wal_file_size 172 512] 
  4  1024  [wal_file_size 172 512]
  5  2048  [wal_file_size 172 512]
  6  4096  [wal_file_size 176 512]
  7  8192  [wal_file_size 184 512]
" {
  file delete -force test.db test.db-wal test.db-journal
  sqlite3_simulate_device -sectorsize $sectorsize
  sqlite3 db test.db -vfs devsym

  do_test wal-17.$tn.1 {
    execsql {
      PRAGMA auto_vacuum = 0;
      PRAGMA page_size = 512;







|







1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
  2   256  [wal_file_size 172 512]
  3   512  [wal_file_size 172 512] 
  4  1024  [wal_file_size 172 512]
  5  2048  [wal_file_size 172 512]
  6  4096  [wal_file_size 176 512]
  7  8192  [wal_file_size 184 512]
" {
  forcedelete test.db test.db-wal test.db-journal
  sqlite3_simulate_device -sectorsize $sectorsize
  sqlite3 db test.db -vfs devsym

  do_test wal-17.$tn.1 {
    execsql {
      PRAGMA auto_vacuum = 0;
      PRAGMA page_size = 512;
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
#
#   wal-18.1.* When the first 32-bits of a frame checksum is correct but 
#              the second 32-bits are false, and
#
#   wal-18.2.* When the page-size field that occurs at the start of a log
#              file is a power of 2 greater than 16384 or smaller than 512.
#
file delete -force test.db test.db-wal test.db-journal
do_test wal-18.0 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA auto_vacuum = 0;
    PRAGMA journal_mode = WAL;
    PRAGMA synchronous = OFF;

    CREATE TABLE t1(a, b, UNIQUE(a, b));
    INSERT INTO t1 VALUES(0, 0);
    PRAGMA wal_checkpoint;

    INSERT INTO t1 VALUES(1, 2);          -- frames 1 and 2
    INSERT INTO t1 VALUES(3, 4);          -- frames 3 and 4
    INSERT INTO t1 VALUES(5, 6);          -- frames 5 and 6
  }

  file copy -force test.db testX.db
  file copy -force test.db-wal testX.db-wal
  db close
  list [file size testX.db] [file size testX.db-wal]
} [list [expr 3*1024] [wal_file_size 6 1024]]

unset -nocomplain nFrame result
foreach {nFrame result} {
         0      {0 0}
         1      {0 0}
         2      {0 0 1 2}
         3      {0 0 1 2}
         4      {0 0 1 2 3 4}
         5      {0 0 1 2 3 4}
         6      {0 0 1 2 3 4 5 6}
} {
  do_test wal-18.1.$nFrame {
    file copy -force testX.db test.db
    file copy -force testX.db-wal test.db-wal

    hexio_write test.db-wal [expr 24 + $nFrame*(24+1024) + 20] 00000000

    sqlite3 db test.db
    execsql { 
      SELECT * FROM t1;
      PRAGMA integrity_check; 







|

















|
|















|
|







1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
#
#   wal-18.1.* When the first 32-bits of a frame checksum is correct but 
#              the second 32-bits are false, and
#
#   wal-18.2.* When the page-size field that occurs at the start of a log
#              file is a power of 2 greater than 16384 or smaller than 512.
#
forcedelete test.db test.db-wal test.db-journal
do_test wal-18.0 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA auto_vacuum = 0;
    PRAGMA journal_mode = WAL;
    PRAGMA synchronous = OFF;

    CREATE TABLE t1(a, b, UNIQUE(a, b));
    INSERT INTO t1 VALUES(0, 0);
    PRAGMA wal_checkpoint;

    INSERT INTO t1 VALUES(1, 2);          -- frames 1 and 2
    INSERT INTO t1 VALUES(3, 4);          -- frames 3 and 4
    INSERT INTO t1 VALUES(5, 6);          -- frames 5 and 6
  }

  forcecopy test.db testX.db
  forcecopy test.db-wal testX.db-wal
  db close
  list [file size testX.db] [file size testX.db-wal]
} [list [expr 3*1024] [wal_file_size 6 1024]]

unset -nocomplain nFrame result
foreach {nFrame result} {
         0      {0 0}
         1      {0 0}
         2      {0 0 1 2}
         3      {0 0 1 2}
         4      {0 0 1 2 3 4}
         5      {0 0 1 2 3 4}
         6      {0 0 1 2 3 4 5 6}
} {
  do_test wal-18.1.$nFrame {
    forcecopy testX.db test.db
    forcecopy testX.db-wal test.db-wal

    hexio_write test.db-wal [expr 24 + $nFrame*(24+1024) + 20] 00000000

    sqlite3 db test.db
    execsql { 
      SELECT * FROM t1;
      PRAGMA integrity_check; 
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
  binary scan $blob $scanpattern values
  foreach {v1 v2} $values {
    set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}]
    set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}]
  }
}

file copy -force test.db testX.db
foreach {tn pgsz works} { 
  1    128    0
  2    256    0
  3    512    1
  4   1024    1
  5   2048    1
  6   4096    1
  7   8192    1
  8  16384    1
  9  32768    1
 10  65536    1
 11 131072    0
 11   1016    0
} {

  if {$::SQLITE_MAX_PAGE_SIZE < $pgsz} {
    set works 0
  }

  for {set pg 1} {$pg <= 3} {incr pg} {
    file copy -force testX.db test.db
    file delete -force test.db-wal
  
    # Check that the database now exists and consists of three pages. And
    # that there is no associated wal file.
    #
    do_test wal-18.2.$tn.$pg.1 { file exists test.db-wal } 0
    do_test wal-18.2.$tn.$pg.2 { file exists test.db } 1
    do_test wal-18.2.$tn.$pg.3 { file size test.db } [expr 1024*3]







|




















|
|







1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
  binary scan $blob $scanpattern values
  foreach {v1 v2} $values {
    set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}]
    set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}]
  }
}

forcecopy test.db testX.db
foreach {tn pgsz works} { 
  1    128    0
  2    256    0
  3    512    1
  4   1024    1
  5   2048    1
  6   4096    1
  7   8192    1
  8  16384    1
  9  32768    1
 10  65536    1
 11 131072    0
 11   1016    0
} {

  if {$::SQLITE_MAX_PAGE_SIZE < $pgsz} {
    set works 0
  }

  for {set pg 1} {$pg <= 3} {incr pg} {
    forcecopy testX.db test.db
    forcedelete test.db-wal
  
    # Check that the database now exists and consists of three pages. And
    # that there is no associated wal file.
    #
    do_test wal-18.2.$tn.$pg.1 { file exists test.db-wal } 0
    do_test wal-18.2.$tn.$pg.2 { file exists test.db } 1
    do_test wal-18.2.$tn.$pg.3 { file size test.db } [expr 1024*3]
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
# connection knows that it is the last connection to disconnect from
# the database, so it runs a checkpoint operation. The bug was that
# the connection was not updating its private copy of the wal-index 
# header before doing so, meaning that it could checkpoint an old
# snapshot.
#
do_test wal-19.1 {
  file delete -force test.db test.db-wal test.db-journal
  sqlite3 db test.db
  sqlite3 db2 test.db
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);







|







1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
# connection knows that it is the last connection to disconnect from
# the database, so it runs a checkpoint operation. The bug was that
# the connection was not updating its private copy of the wal-index 
# header before doing so, meaning that it could checkpoint an old
# snapshot.
#
do_test wal-19.1 {
  forcedelete test.db test.db-wal test.db-journal
  sqlite3 db test.db
  sqlite3 db2 test.db
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
#      the data is present and the database is not corrupt.
#
# At one point, SQLite was failing to grow the mapping of the wal-index
# file in step 3 and the checkpoint was corrupting the database file.
#
do_test wal-20.1 {
  catch {db close}
  file delete -force test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(randomblob(900));
    SELECT count(*) FROM t1;
  }







|







1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
#      the data is present and the database is not corrupt.
#
# At one point, SQLite was failing to grow the mapping of the wal-index
# file in step 3 and the checkpoint was corrupting the database file.
#
do_test wal-20.1 {
  catch {db close}
  forcedelete test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(randomblob(900));
    SELECT count(*) FROM t1;
  }
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486

#-------------------------------------------------------------------------
# Test that when 1 or more pages are recovered from a WAL file, 
# sqlite3_log() is invoked to report this to the user.
#
set walfile [file nativename [file join [pwd] test.db-wal]]
catch {db close}
file delete -force test.db
do_test wal-23.1 {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t1(a, b);
    PRAGMA journal_mode = WAL;
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);







|







1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486

#-------------------------------------------------------------------------
# Test that when 1 or more pages are recovered from a WAL file, 
# sqlite3_log() is invoked to report this to the user.
#
set walfile [file nativename [file join [pwd] test.db-wal]]
catch {db close}
forcedelete test.db
do_test wal-23.1 {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t1(a, b);
    PRAGMA journal_mode = WAL;
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);

Changes to test/wal2.test.

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
  do_test wal2-1.$tn.2 {
    set ::locks
  } $wal_locks
}
db close
db2 close
tvfs delete
file delete -force test.db test.db-wal test.db-journal

#-------------------------------------------------------------------------
# This test case is very similar to the previous one, except, after
# the reader reads the corrupt wal-index header, but before it has
# a chance to re-read it under the cover of the RECOVER lock, the
# wal-index header is replaced with a valid, but out-of-date, header.
#







|







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
  do_test wal2-1.$tn.2 {
    set ::locks
  } $wal_locks
}
db close
db2 close
tvfs delete
forcedelete test.db test.db-wal test.db-journal

#-------------------------------------------------------------------------
# This test case is very similar to the previous one, except, after
# the reader reads the corrupt wal-index header, but before it has
# a chance to re-read it under the cover of the RECOVER lock, the
# wal-index header is replaced with a valid, but out-of-date, header.
#
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
    }
    execsql { SELECT count(a), sum(a) FROM t1 } db2
  } $res1
}
db close
db2 close
tvfs delete
file delete -force test.db test.db-wal test.db-journal


if 0 {
#-------------------------------------------------------------------------
# This test case - wal2-3.* - tests the response of the library to an
# SQLITE_BUSY when attempting to obtain a READ or RECOVER lock.
#







|







267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
    }
    execsql { SELECT count(a), sum(a) FROM t1 } db2
  } $res1
}
db close
db2 close
tvfs delete
forcedelete test.db test.db-wal test.db-journal


if 0 {
#-------------------------------------------------------------------------
# This test case - wal2-3.* - tests the response of the library to an
# SQLITE_BUSY when attempting to obtain a READ or RECOVER lock.
#
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  execsql { SELECT count(a), sum(a) FROM t1 }
} {4 10}
do_test wal2-3.5 {
  list [info exists ::sabotage] [info exists ::locked]
} {0 0}
db close
tvfs delete
file delete -force test.db test.db-wal test.db-journal

}

#-------------------------------------------------------------------------
# Test that a database connection using a VFS that does not support the
# xShmXXX interfaces cannot open a WAL database.
#







|







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  execsql { SELECT count(a), sum(a) FROM t1 }
} {4 10}
do_test wal2-3.5 {
  list [info exists ::sabotage] [info exists ::locked]
} {0 0}
db close
tvfs delete
forcedelete test.db test.db-wal test.db-journal

}

#-------------------------------------------------------------------------
# Test that a database connection using a VFS that does not support the
# xShmXXX interfaces cannot open a WAL database.
#
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
#   wal2-6.5.*: 
#
#   wal2-6.6.*: Check that if the xShmLock() to reaquire a WAL read-lock when
#               exiting exclusive mode fails (i.e. SQLITE_IOERR), then the
#               connection silently remains in exclusive mode.
#
do_test wal2-6.1.1 {
  file delete -force test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    Pragma Journal_Mode = Wal;
  }
} {wal}
do_test wal2-6.1.2 {
  execsql { PRAGMA lock_status }







|







437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
#   wal2-6.5.*: 
#
#   wal2-6.6.*: Check that if the xShmLock() to reaquire a WAL read-lock when
#               exiting exclusive mode fails (i.e. SQLITE_IOERR), then the
#               connection silently remains in exclusive mode.
#
do_test wal2-6.1.1 {
  forcedelete test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    Pragma Journal_Mode = Wal;
  }
} {wal}
do_test wal2-6.1.2 {
  execsql { PRAGMA lock_status }
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
    INSERT INTO t1 VALUES(3, 4);
    PRAGMA lock_status;
  }
} {main shared temp closed}
db close

do_test wal2-6.2.1 {
  file delete -force test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    Pragma Locking_Mode = Exclusive;
    Pragma Journal_Mode = Wal;
    Pragma Lock_Status;
  }
} {exclusive wal main exclusive temp closed}







|







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
    INSERT INTO t1 VALUES(3, 4);
    PRAGMA lock_status;
  }
} {main shared temp closed}
db close

do_test wal2-6.2.1 {
  forcedelete test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    Pragma Locking_Mode = Exclusive;
    Pragma Journal_Mode = Wal;
    Pragma Lock_Status;
  }
} {exclusive wal main exclusive temp closed}
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
    SELECT * FROM t1;
    pragma lock_status;
  }
} {1 2 3 4 5 6 main shared temp closed}
db close

do_test wal2-6.3.1 {
  file delete -force test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA journal_mode = WAL;
    PRAGMA locking_mode = exclusive;
    BEGIN;
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES('Chico');







|







548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
    SELECT * FROM t1;
    pragma lock_status;
  }
} {1 2 3 4 5 6 main shared temp closed}
db close

do_test wal2-6.3.1 {
  forcedelete test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA journal_mode = WAL;
    PRAGMA locking_mode = exclusive;
    BEGIN;
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES('Chico');
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607


# This test - wal2-6.4.* - uses a single database connection and the
# [testvfs] instrumentation to test that xShmLock() is being called
# as expected when a WAL database is used with locking_mode=exclusive.
#
do_test wal2-6.4.1 {
  file delete -force test.db test.db-wal test.db-journal
  proc tvfs_cb {method args} {
    set ::shm_file [lindex $args 0]
    if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] }
    return "SQLITE_OK"
  }
  testvfs tvfs
  tvfs script tvfs_cb







|







593
594
595
596
597
598
599
600
601
602
603
604
605
606
607


# This test - wal2-6.4.* - uses a single database connection and the
# [testvfs] instrumentation to test that xShmLock() is being called
# as expected when a WAL database is used with locking_mode=exclusive.
#
do_test wal2-6.4.1 {
  forcedelete test.db test.db-wal test.db-journal
  proc tvfs_cb {method args} {
    set ::shm_file [lindex $args 0]
    if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] }
    return "SQLITE_OK"
  }
  testvfs tvfs
  tvfs script tvfs_cb
788
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
814
815
816
817
818
819
820
821
822
823
824
db2 close
T delete

#-------------------------------------------------------------------------
# Test a theory about the checksum algorithm. Theory was false and this
# test did not provoke a bug.
#
file delete -force test.db test.db-wal test.db-journal
do_test wal2-7.1.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 4096;
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a, b);
  }
  file size test.db
} {4096}
do_test wal2-7.1.2 {
  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal
  hexio_write test2.db-wal 48 FF
} {1}
do_test wal2-7.1.3 {
  sqlite3 db2 test2.db
  execsql { PRAGMA wal_checkpoint } db2
  execsql { SELECT * FROM sqlite_master } db2
} {}
db close
db2 close
file delete -force test.db test.db-wal test.db-journal
do_test wal2-8.1.2 {
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(x);







|










|
|









|







788
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
814
815
816
817
818
819
820
821
822
823
824
db2 close
T delete

#-------------------------------------------------------------------------
# Test a theory about the checksum algorithm. Theory was false and this
# test did not provoke a bug.
#
forcedelete test.db test.db-wal test.db-journal
do_test wal2-7.1.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 4096;
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a, b);
  }
  file size test.db
} {4096}
do_test wal2-7.1.2 {
  forcecopy test.db test2.db
  forcecopy test.db-wal test2.db-wal
  hexio_write test2.db-wal 48 FF
} {1}
do_test wal2-7.1.3 {
  sqlite3 db2 test2.db
  execsql { PRAGMA wal_checkpoint } db2
  execsql { SELECT * FROM sqlite_master } db2
} {}
db close
db2 close
forcedelete test.db test.db-wal test.db-journal
do_test wal2-8.1.2 {
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(x);
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
# 
#
proc get_name {method args} { set ::filename [lindex $args 0] ; tvfs filter {} }
testvfs tvfs
tvfs script get_name
tvfs filter xShmOpen

file delete -force test.db test.db-wal test.db-journal
do_test wal2-9.1 {
  sqlite3 db test.db -vfs tvfs
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE x(y);
    INSERT INTO x VALUES('Barton');
    INSERT INTO x VALUES('Deakin');







|







866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
# 
#
proc get_name {method args} { set ::filename [lindex $args 0] ; tvfs filter {} }
testvfs tvfs
tvfs script get_name
tvfs filter xShmOpen

forcedelete test.db test.db-wal test.db-journal
do_test wal2-9.1 {
  sqlite3 db test.db -vfs tvfs
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE x(y);
    INSERT INTO x VALUES('Barton');
    INSERT INTO x VALUES('Deakin');

Changes to test/wal3.test.

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  do_test wal3-1.$i.4 {
    execsql { PRAGMA integrity_check } db2
  } {ok}
  db2 close
  
  # Check that the file-system in its current state can be recovered.
  # 
  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal
  file delete -force test2.db-journal
  sqlite3 db2 test2.db
  do_test wal3-1.$i.5 {
    execsql { SELECT count(*) FROM t1 } db2
  } 4018
  do_test wal3-1.$i.6 {
    execsql { SELECT x FROM t1 WHERE rowid = $i }
  } $str







|
|
|







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  do_test wal3-1.$i.4 {
    execsql { PRAGMA integrity_check } db2
  } {ok}
  db2 close
  
  # Check that the file-system in its current state can be recovered.
  # 
  forcecopy test.db test2.db
  forcecopy test.db-wal test2.db-wal
  forcedelete test2.db-journal
  sqlite3 db2 test2.db
  do_test wal3-1.$i.5 {
    execsql { SELECT count(*) FROM t1 } db2
  } 4018
  do_test wal3-1.$i.6 {
    execsql { SELECT x FROM t1 WHERE rowid = $i }
  } $str
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
} {

  proc sync_counter {args} { 
    foreach {method filename id flags} $args break
    lappend ::syncs [file tail $filename] $flags
  }
  do_test wal3-3.$tn {
    file delete -force test.db test.db-wal test.db-journal
  
    testvfs T
    T filter {} 
    T script sync_counter
    sqlite3 db test.db -vfs T
  
    execsql "PRAGMA synchronous = $syncmode"







|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
} {

  proc sync_counter {args} { 
    foreach {method filename id flags} $args break
    lappend ::syncs [file tail $filename] $flags
  }
  do_test wal3-3.$tn {
    forcedelete test.db test.db-wal test.db-journal
  
    testvfs T
    T filter {} 
    T script sync_counter
    sqlite3 db test.db -vfs T
  
    execsql "PRAGMA synchronous = $syncmode"
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
#   + The attempt to obtain the lock on aReadMark[0] fails with SQLITE_BUSY.
#     This can happen if a checkpoint is ongoing. In this case also simply
#     obtain a different read-lock.
#
catch {db close}
testvfs T -default 1
do_test wal3-6.1.1 {
  file delete -force test.db test.db-journal test.db wal
  sqlite3 db test.db
  execsql { PRAGMA auto_vacuum = off }
  execsql { PRAGMA journal_mode = WAL }
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES('o', 't');
    INSERT INTO t1 VALUES('t', 'f');







|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
#   + The attempt to obtain the lock on aReadMark[0] fails with SQLITE_BUSY.
#     This can happen if a checkpoint is ongoing. In this case also simply
#     obtain a different read-lock.
#
catch {db close}
testvfs T -default 1
do_test wal3-6.1.1 {
  forcedelete test.db test.db-journal test.db wal
  sqlite3 db test.db
  execsql { PRAGMA auto_vacuum = off }
  execsql { PRAGMA journal_mode = WAL }
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES('o', 't');
    INSERT INTO t1 VALUES('t', 'f');
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
} {1}

db3 close
db2 close
db close

do_test wal3-6.2.1 {
  file delete -force test.db test.db-journal test.db wal
  sqlite3 db test.db
  sqlite3 db2 test.db
  execsql { PRAGMA auto_vacuum = off }
  execsql { PRAGMA journal_mode = WAL }
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES('h', 'h');







|







488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
} {1}

db3 close
db2 close
db close

do_test wal3-6.2.1 {
  forcedelete test.db test.db-journal test.db wal
  sqlite3 db test.db
  sqlite3 db2 test.db
  execsql { PRAGMA auto_vacuum = off }
  execsql { PRAGMA journal_mode = WAL }
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES('h', 'h');
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
#
#   + The value in the aReadMark[x] slot has been modified since it was
#     read.
#
catch {db close}
testvfs T -default 1
do_test wal3-7.1.1 {
  file delete -force test.db test.db-journal test.db wal
  sqlite3 db test.db
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE blue(red PRIMARY KEY, green);
  }
} {wal}








|







554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
#
#   + The value in the aReadMark[x] slot has been modified since it was
#     read.
#
catch {db close}
testvfs T -default 1
do_test wal3-7.1.1 {
  forcedelete test.db test.db-journal test.db wal
  sqlite3 db test.db
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE blue(red PRIMARY KEY, green);
  }
} {wal}

611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
db close
db2 close
T delete

#-------------------------------------------------------------------------
# 
do_test wal3-8.1 {
  file delete -force test.db test.db-journal test.db wal
  sqlite3 db test.db
  sqlite3 db2 test.db
  execsql {
    PRAGMA auto_vacuum = off;
    PRAGMA journal_mode = WAL;
    CREATE TABLE b(c);
    INSERT INTO b VALUES('Tehran');







|







611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
db close
db2 close
T delete

#-------------------------------------------------------------------------
# 
do_test wal3-8.1 {
  forcedelete test.db test.db-journal test.db wal
  sqlite3 db test.db
  sqlite3 db2 test.db
  execsql {
    PRAGMA auto_vacuum = off;
    PRAGMA journal_mode = WAL;
    CREATE TABLE b(c);
    INSERT INTO b VALUES('Tehran');
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
# on any aReadMark[] slot (because there are already several readers),
# the client takes a shared-lock on a slot without modifying the value
# and continues.
#
set nConn 50
if { [string match *BSD $tcl_platform(os)] } { set nConn 25 }
do_test wal3-9.0 {
  file delete -force test.db test.db-journal test.db wal
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = WAL;
    CREATE TABLE whoami(x);
    INSERT INTO whoami VALUES('nobody');
  }







|







705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
# on any aReadMark[] slot (because there are already several readers),
# the client takes a shared-lock on a slot without modifying the value
# and continues.
#
set nConn 50
if { [string match *BSD $tcl_platform(os)] } { set nConn 25 }
do_test wal3-9.0 {
  forcedelete test.db test.db-journal test.db wal
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = WAL;
    CREATE TABLE whoami(x);
    INSERT INTO whoami VALUES('nobody');
  }

Changes to test/wal4.test.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  }
} {wal 1 2}

do_test wal4-1.2 {
  # Save a copy of the file-system containing the wal and wal-index files 
  # only (no database file).
  faultsim_save_and_close
  file delete -force sv_test.db
} {}

do_test wal4-1.3 {
  faultsim_restore_and_reopen
  catchsql { SELECT * FROM t1 }
} {1 {no such table: t1}}








|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  }
} {wal 1 2}

do_test wal4-1.2 {
  # Save a copy of the file-system containing the wal and wal-index files 
  # only (no database file).
  faultsim_save_and_close
  forcedelete sv_test.db
} {}

do_test wal4-1.3 {
  faultsim_restore_and_reopen
  catchsql { SELECT * FROM t1 }
} {1 {no such table: t1}}

Changes to test/walbak.test.

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    BEGIN;
      CREATE TABLE t1(a PRIMARY KEY, b);
      INSERT INTO t1 VALUES('I', 'one');
    COMMIT;
  }
} {wal}
do_test walbak-1.1 {
  file delete -force bak.db bak.db-journal bak.db-wal
  db backup bak.db
  file size bak.db
} [expr 3*1024]
do_test walbak-1.2 {
  sqlite3 db2 bak.db
  execsql { 
    SELECT * FROM t1;







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    BEGIN;
      CREATE TABLE t1(a PRIMARY KEY, b);
      INSERT INTO t1 VALUES('I', 'one');
    COMMIT;
  }
} {wal}
do_test walbak-1.1 {
  forcedelete bak.db bak.db-journal bak.db-wal
  db backup bak.db
  file size bak.db
} [expr 3*1024]
do_test walbak-1.2 {
  sqlite3 db2 bak.db
  execsql { 
    SELECT * FROM t1;
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
proc sig {{db db}} {
  $db eval { 
    PRAGMA integrity_check;
    SELECT md5sum(a, b) FROM t1; 
  }
}
db close
file delete test.db
sqlite3 db test.db
do_test walbak-2.1 {
  execsql { PRAGMA journal_mode = WAL }
  execsql {
    CREATE TABLE t1(a PRIMARY KEY, b);
    BEGIN;
      INSERT INTO t1 VALUES(randomblob(500), randomblob(500));







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
proc sig {{db db}} {
  $db eval { 
    PRAGMA integrity_check;
    SELECT md5sum(a, b) FROM t1; 
  }
}
db close
delete_file test.db
sqlite3 db test.db
do_test walbak-2.1 {
  execsql { PRAGMA journal_mode = WAL }
  execsql {
    CREATE TABLE t1(a PRIMARY KEY, b);
    BEGIN;
      INSERT INTO t1 VALUES(randomblob(500), randomblob(500));
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
      PRAGMA page_size = 2048;
      PRAGMA journal_mode = PERSIST;
      CREATE TABLE xx(x);
    }
  }

} {
  foreach f [glob -nocomplain test.db*] { file delete -force $f }

  eval $setup

  do_test walbak-3.$tn.1 {
    execsql {
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 2);







|







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
      PRAGMA page_size = 2048;
      PRAGMA journal_mode = PERSIST;
      CREATE TABLE xx(x);
    }
  }

} {
  foreach f [glob -nocomplain test.db*] { forcedelete $f }

  eval $setup

  do_test walbak-3.$tn.1 {
    execsql {
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 2);

Changes to test/walcksum.test.

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
if {$::tcl_platform(byteOrder) == "littleEndian"} { set native "little" }
foreach endian {big little} {

  # Create a database. Leave some data in the log file.
  #
  do_test walcksum-1.$endian.1 {
    catch { db close }
    file delete -force test.db test.db-wal test.db-journal
    sqlite3 db test.db
    execsql {
      PRAGMA page_size = 1024;
      PRAGMA auto_vacuum = 0;
      PRAGMA synchronous = NORMAL;

      CREATE TABLE t1(a PRIMARY KEY, b);
      INSERT INTO t1 VALUES(1,  'one');
      INSERT INTO t1 VALUES(2,  'two');
      INSERT INTO t1 VALUES(3,  'three');
      INSERT INTO t1 VALUES(5,  'five');

      PRAGMA journal_mode = WAL;
      INSERT INTO t1 VALUES(8,  'eight');
      INSERT INTO t1 VALUES(13, 'thirteen');
      INSERT INTO t1 VALUES(21, 'twentyone');
    }

    file copy -force test.db test2.db
    file copy -force test.db-wal test2.db-wal
    db close

    list [file size test2.db] [file size test2.db-wal]
  } [list [expr 1024*3] [wal_file_size 6 1024]]

  # Verify that the checksums are valid for all frames and that they
  # are calculated by interpreting data in native byte-order.







|


















|
|







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
if {$::tcl_platform(byteOrder) == "littleEndian"} { set native "little" }
foreach endian {big little} {

  # Create a database. Leave some data in the log file.
  #
  do_test walcksum-1.$endian.1 {
    catch { db close }
    forcedelete test.db test.db-wal test.db-journal
    sqlite3 db test.db
    execsql {
      PRAGMA page_size = 1024;
      PRAGMA auto_vacuum = 0;
      PRAGMA synchronous = NORMAL;

      CREATE TABLE t1(a PRIMARY KEY, b);
      INSERT INTO t1 VALUES(1,  'one');
      INSERT INTO t1 VALUES(2,  'two');
      INSERT INTO t1 VALUES(3,  'three');
      INSERT INTO t1 VALUES(5,  'five');

      PRAGMA journal_mode = WAL;
      INSERT INTO t1 VALUES(8,  'eight');
      INSERT INTO t1 VALUES(13, 'thirteen');
      INSERT INTO t1 VALUES(21, 'twentyone');
    }

    forcecopy test.db test2.db
    forcecopy test.db-wal test2.db-wal
    db close

    list [file size test2.db] [file size test2.db-wal]
  } [list [expr 1024*3] [wal_file_size 6 1024]]

  # Verify that the checksums are valid for all frames and that they
  # are calculated by interpreting data in native byte-order.
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  for {set f 1} {$f <= 6} {incr f} {
    do_test walcksum-1.$endian.3.$f {
      log_checksum_write test2.db-wal $f $endian
      log_checksum_verify test2.db-wal $f $endian
    } {1}
  }
  do_test walcksum-1.$endian.4.1 {
    file copy -force test2.db test.db
    file copy -force test2.db-wal test.db-wal
    sqlite3 db test.db
    execsql { SELECT a FROM t1 }
  } {1 2 3 5 8 13 21}

  # Following recovery, any frames written to the log should use the same 
  # endianness as the existing frames. Check that this is the case.
  #







|
|







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  for {set f 1} {$f <= 6} {incr f} {
    do_test walcksum-1.$endian.3.$f {
      log_checksum_write test2.db-wal $f $endian
      log_checksum_verify test2.db-wal $f $endian
    } {1}
  }
  do_test walcksum-1.$endian.4.1 {
    forcecopy test2.db test.db
    forcecopy test2.db-wal test.db-wal
    sqlite3 db test.db
    execsql { SELECT a FROM t1 }
  } {1 2 3 5 8 13 21}

  # Following recovery, any frames written to the log should use the same 
  # endianness as the existing frames. Check that this is the case.
  #
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
      log_checksum_verify test.db-wal $f $endian
    } {1}
  }

  # Now that both the recoverer and non-recoverer have added frames to the
  # log file, check that it can still be recovered.
  #
  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal
  do_test walcksum-1.$endian.7.11 {
    sqlite3 db3 test2.db
    execsql { 
      PRAGMA integrity_check;
      SELECT a FROM t1;
    } db3
  } {ok 1 2 3 5 8 13 21 34 55}







|
|







244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
      log_checksum_verify test.db-wal $f $endian
    } {1}
  }

  # Now that both the recoverer and non-recoverer have added frames to the
  # log file, check that it can still be recovered.
  #
  forcecopy test.db test2.db
  forcecopy test.db-wal test2.db-wal
  do_test walcksum-1.$endian.7.11 {
    sqlite3 db3 test2.db
    execsql { 
      PRAGMA integrity_check;
      SELECT a FROM t1;
    } db3
  } {ok 1 2 3 5 8 13 21 34 55}
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#-------------------------------------------------------------------------
# Test case walcksum-2.* tests that if a statement transaction is rolled
# back after frames are written to the WAL, and then (after writing some
# more) the outer transaction is committed, the WAL file is still correctly
# formatted (and can be recovered by a second process if required).
#
do_test walcksum-2.1 {
  file delete -force test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA synchronous = NORMAL;
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = WAL;
    PRAGMA cache_size = 10;
    CREATE TABLE t1(x PRIMARY KEY);







|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#-------------------------------------------------------------------------
# Test case walcksum-2.* tests that if a statement transaction is rolled
# back after frames are written to the WAL, and then (after writing some
# more) the outer transaction is committed, the WAL file is still correctly
# formatted (and can be recovered by a second process if required).
#
do_test walcksum-2.1 {
  forcedelete test.db test.db-wal test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA synchronous = NORMAL;
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = WAL;
    PRAGMA cache_size = 10;
    CREATE TABLE t1(x PRIMARY KEY);
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
      INSERT INTO t1 SELECT randomblob(800) FROM t1;   /*  32 */
      INSERT INTO t1 SELECT randomblob(800) FROM t1;   /*  64 */
      INSERT INTO t1 SELECT randomblob(800) FROM t1;   /* 128 */
      INSERT INTO t1 SELECT randomblob(800) FROM t1;   /* 256 */
    COMMIT;
  }

  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal

  sqlite3 db2 test2.db
  execsql {
    PRAGMA integrity_check;
    SELECT count(*) FROM t1;
  } db2
} {ok 256}
catch { db close }
catch { db2 close }

#-------------------------------------------------------------------------
# Test case walcksum-3.* tests that the checksum calculation detects single 
# byte changes to frame or frame-header data and considers the frame
# invalid as a result.
#
do_test walcksum-3.1 {
  file delete -force test.db test.db-wal test.db-journal
  sqlite3 db test.db

  execsql {
    PRAGMA synchronous = NORMAL;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, randomblob(300));
    INSERT INTO t1 VALUES(2, randomblob(300));
    PRAGMA journal_mode = WAL;
    INSERT INTO t1 VALUES(3, randomblob(300));
  }

  file size test.db-wal
} [wal_file_size 1 1024]
do_test walcksum-3.2 {
  file copy -force test.db-wal test2.db-wal
  file copy -force test.db test2.db
  sqlite3 db2 test2.db
  execsql { SELECT a FROM t1 } db2
} {1 2 3}
db2 close
file copy -force test.db test2.db


foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} {
  do_test walcksum-3.3.$incr {
    set FAIL 0
    for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} {

      file copy -force test.db-wal test2.db-wal
      set fd [open test2.db-wal r+]
      fconfigure $fd -encoding binary
      fconfigure $fd -translation binary
  
      seek $fd $iOff
      binary scan [read $fd 1] c x
      seek $fd $iOff







|
|
















|















|
|




|







|







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
      INSERT INTO t1 SELECT randomblob(800) FROM t1;   /*  32 */
      INSERT INTO t1 SELECT randomblob(800) FROM t1;   /*  64 */
      INSERT INTO t1 SELECT randomblob(800) FROM t1;   /* 128 */
      INSERT INTO t1 SELECT randomblob(800) FROM t1;   /* 256 */
    COMMIT;
  }

  forcecopy test.db test2.db
  forcecopy test.db-wal test2.db-wal

  sqlite3 db2 test2.db
  execsql {
    PRAGMA integrity_check;
    SELECT count(*) FROM t1;
  } db2
} {ok 256}
catch { db close }
catch { db2 close }

#-------------------------------------------------------------------------
# Test case walcksum-3.* tests that the checksum calculation detects single 
# byte changes to frame or frame-header data and considers the frame
# invalid as a result.
#
do_test walcksum-3.1 {
  forcedelete test.db test.db-wal test.db-journal
  sqlite3 db test.db

  execsql {
    PRAGMA synchronous = NORMAL;
    PRAGMA page_size = 1024;
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, randomblob(300));
    INSERT INTO t1 VALUES(2, randomblob(300));
    PRAGMA journal_mode = WAL;
    INSERT INTO t1 VALUES(3, randomblob(300));
  }

  file size test.db-wal
} [wal_file_size 1 1024]
do_test walcksum-3.2 {
  forcecopy test.db-wal test2.db-wal
  forcecopy test.db test2.db
  sqlite3 db2 test2.db
  execsql { SELECT a FROM t1 } db2
} {1 2 3}
db2 close
forcecopy test.db test2.db


foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} {
  do_test walcksum-3.3.$incr {
    set FAIL 0
    for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} {

      forcecopy test.db-wal test2.db-wal
      set fd [open test2.db-wal r+]
      fconfigure $fd -encoding binary
      fconfigure $fd -translation binary
  
      seek $fd $iOff
      binary scan [read $fd 1] c x
      seek $fd $iOff

Changes to test/walcrash.test.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

set seed 0
set REPEATS 100

# walcrash-1.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  file delete -force test.db test.db-wal
  do_test walcrash-1.$i.1 {
    crashsql -delay 4 -file test.db-wal -seed [incr seed] {
      PRAGMA journal_mode = WAL;
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 1);
      INSERT INTO t1 VALUES(2, 3);
      INSERT INTO t1 VALUES(3, 6);







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

set seed 0
set REPEATS 100

# walcrash-1.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  forcedelete test.db test.db-wal
  do_test walcrash-1.$i.1 {
    crashsql -delay 4 -file test.db-wal -seed [incr seed] {
      PRAGMA journal_mode = WAL;
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 1);
      INSERT INTO t1 VALUES(2, 3);
      INSERT INTO t1 VALUES(3, 6);
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  } {wal}
  db close
}

# walcrash-2.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  file delete -force test.db test.db-wal
  do_test walcrash-2.$i.1 {
    crashsql -delay 4 -file test.db-wal -seed [incr seed] {
      PRAGMA journal_mode = WAL;
      CREATE TABLE t1(a PRIMARY KEY, b);
      INSERT INTO t1 VALUES(1, 2);
      INSERT INTO t1 VALUES(3, 4);
      INSERT INTO t1 VALUES(5, 9);







|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  } {wal}
  db close
}

# walcrash-2.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  forcedelete test.db test.db-wal
  do_test walcrash-2.$i.1 {
    crashsql -delay 4 -file test.db-wal -seed [incr seed] {
      PRAGMA journal_mode = WAL;
      CREATE TABLE t1(a PRIMARY KEY, b);
      INSERT INTO t1 VALUES(1, 2);
      INSERT INTO t1 VALUES(3, 4);
      INSERT INTO t1 VALUES(5, 9);
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  } {wal}
  db close
}

# walcrash-3.*
#
# for {set i 1} {$i < $REPEATS} {incr i} {
#   file delete -force test.db test.db-wal
#   file delete -force test2.db test2.db-wal
# 
#   do_test walcrash-3.$i.1 {
#     crashsql -delay 2 -file test2.db-wal -seed [incr seed] {
#       PRAGMA journal_mode = WAL;
#       ATTACH 'test2.db' AS aux;
#       CREATE TABLE t1(a PRIMARY KEY, b);
#       CREATE TABLE aux.t2(a PRIMARY KEY, b);







|
|







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  } {wal}
  db close
}

# walcrash-3.*
#
# for {set i 1} {$i < $REPEATS} {incr i} {
#   forcedelete test.db test.db-wal
#   forcedelete test2.db test2.db-wal
# 
#   do_test walcrash-3.$i.1 {
#     crashsql -delay 2 -file test2.db-wal -seed [incr seed] {
#       PRAGMA journal_mode = WAL;
#       ATTACH 'test2.db' AS aux;
#       CREATE TABLE t1(a PRIMARY KEY, b);
#       CREATE TABLE aux.t2(a PRIMARY KEY, b);
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# 
#   db close
# }

# walcrash-4.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  file delete -force test.db test.db-wal
  file delete -force test2.db test2.db-wal

  do_test walcrash-4.$i.1 {
    crashsql -delay 3 -file test.db-wal -seed [incr seed] -blocksize 4096 {
      PRAGMA journal_mode = WAL;
      PRAGMA page_size = 1024;
      CREATE TABLE t1(a PRIMARY KEY, b);
      INSERT INTO t1 VALUES(1, 2);







|
|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# 
#   db close
# }

# walcrash-4.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  forcedelete test.db test.db-wal
  forcedelete test2.db test2.db-wal

  do_test walcrash-4.$i.1 {
    crashsql -delay 3 -file test.db-wal -seed [incr seed] -blocksize 4096 {
      PRAGMA journal_mode = WAL;
      PRAGMA page_size = 1024;
      CREATE TABLE t1(a PRIMARY KEY, b);
      INSERT INTO t1 VALUES(1, 2);
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

  db close
}

# walcrash-5.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  file delete -force test.db test.db-wal
  file delete -force test2.db test2.db-wal

  do_test walcrash-5.$i.1 {
    crashsql -delay 11 -file test.db-wal -seed [incr seed] -blocksize 4096 {
      PRAGMA journal_mode = WAL;
      PRAGMA page_size = 1024;
      BEGIN;
        CREATE TABLE t1(x PRIMARY KEY);







|
|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

  db close
}

# walcrash-5.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  forcedelete test.db test.db-wal
  forcedelete test2.db test2.db-wal

  do_test walcrash-5.$i.1 {
    crashsql -delay 11 -file test.db-wal -seed [incr seed] -blocksize 4096 {
      PRAGMA journal_mode = WAL;
      PRAGMA page_size = 1024;
      BEGIN;
        CREATE TABLE t1(x PRIMARY KEY);
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

  db close
}

# walcrash-6.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  file delete -force test.db test.db-wal
  file delete -force test2.db test2.db-wal

  do_test walcrash-6.$i.1 {
    crashsql -delay 12 -file test.db-wal -seed [incr seed] -blocksize 512 {
      PRAGMA journal_mode = WAL;
      PRAGMA page_size = 1024;
      BEGIN;
        CREATE TABLE t1(x PRIMARY KEY);







|
|







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

  db close
}

# walcrash-6.*
#
for {set i 1} {$i < $REPEATS} {incr i} {
  forcedelete test.db test.db-wal
  forcedelete test2.db test2.db-wal

  do_test walcrash-6.$i.1 {
    crashsql -delay 12 -file test.db-wal -seed [incr seed] -blocksize 512 {
      PRAGMA journal_mode = WAL;
      PRAGMA page_size = 1024;
      BEGIN;
        CREATE TABLE t1(x PRIMARY KEY);
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#
#   (a) that the database is a WAL database, and 
#   (b) the database page-size
#
# based on the log file.
#
for {set i 1} {$i < $REPEATS} {incr i} {
  file delete -force test.db test.db-wal

  # Select a page-size for this test.
  #
  set pgsz [lindex {512 1024 2048 4096 8192 16384} [expr $i%6]]

  do_test walcrash-7.$i.1 {
    crashsql -delay 3 -file test.db -seed [incr seed] -blocksize 512 "







|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#
#   (a) that the database is a WAL database, and 
#   (b) the database page-size
#
# based on the log file.
#
for {set i 1} {$i < $REPEATS} {incr i} {
  forcedelete test.db test.db-wal

  # Select a page-size for this test.
  #
  set pgsz [lindex {512 1024 2048 4096 8192 16384} [expr $i%6]]

  do_test walcrash-7.$i.1 {
    crashsql -delay 3 -file test.db -seed [incr seed] -blocksize 512 "

Changes to test/walfault.test.

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
    BEGIN;
      CREATE TABLE abc(a PRIMARY KEY);
      INSERT INTO abc VALUES(randomblob(1500));
      INSERT INTO abc VALUES(randomblob(1500));
    COMMIT;
  }
  faultsim_save_and_close
  file delete sv_test.db-shm
} {}

do_faultsim_test walfault-13.1 -prep {
  faultsim_restore_and_reopen
} -body {
  db eval { PRAGMA locking_mode = exclusive }
  db eval { SELECT count(*) FROM abc }







|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
    BEGIN;
      CREATE TABLE abc(a PRIMARY KEY);
      INSERT INTO abc VALUES(randomblob(1500));
      INSERT INTO abc VALUES(randomblob(1500));
    COMMIT;
  }
  faultsim_save_and_close
  delete_file sv_test.db-shm
} {}

do_faultsim_test walfault-13.1 -prep {
  faultsim_restore_and_reopen
} -body {
  db eval { PRAGMA locking_mode = exclusive }
  db eval { SELECT count(*) FROM abc }

Changes to test/walmode.test.

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

#-------------------------------------------------------------------------
# Test the effect of a "PRAGMA journal_mode" command being the first 
# thing executed by a new connection. This means that the schema is not
# loaded when sqlite3_prepare_v2() is called to compile the statement.
#
do_test walmode-7.0 {
  file delete -force test.db
  sqlite3 db test.db
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a, b);
  }
} {wal}
foreach {tn sql result} {







|







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

#-------------------------------------------------------------------------
# Test the effect of a "PRAGMA journal_mode" command being the first 
# thing executed by a new connection. This means that the schema is not
# loaded when sqlite3_prepare_v2() is called to compile the statement.
#
do_test walmode-7.0 {
  forcedelete test.db
  sqlite3 db test.db
  execsql {
    PRAGMA journal_mode = WAL;
    CREATE TABLE t1(a, b);
  }
} {wal}
foreach {tn sql result} {

Changes to test/walnoshm.test.

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
  PRAGMA locking_mode = exclusive;
  PRAGMA journal_mode = WAL;
  INSERT INTO t2 VALUES('e', 'f');
  INSERT INTO t2 VALUES('g', 'h');
} {exclusive wal}

do_test 2.1.3 {
  file copy -force test.db     test2.db
  file copy -force test.db-wal test2.db-wal
  sqlite3 db2 test2.db
  catchsql { SELECT * FROM t2 } db2
} {1 {unable to open database file}}
do_test 2.1.4 {
  catchsql { PRAGMA journal_mode = delete } db2
} {1 {unable to open database file}}
do_test 2.1.5 {
  execsql { 
    PRAGMA locking_mode = exclusive; 
    PRAGMA journal_mode = delete;
    SELECT * FROM t2;
  } db2
} {exclusive delete a b c d e f g h}

do_test 2.2.1 {
  file copy -force test.db     test2.db
  file copy -force test.db-wal test2.db-wal
  sqlite3 db3 test2.db -vfs tvfsshm
  sqlite3 db2 test2.db
  execsql { SELECT * FROM t2 } db3
} {a b c d e f g h}

do_test 2.2.2 {
  execsql  { PRAGMA locking_mode = exclusive }  db2







|
|















|
|







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
  PRAGMA locking_mode = exclusive;
  PRAGMA journal_mode = WAL;
  INSERT INTO t2 VALUES('e', 'f');
  INSERT INTO t2 VALUES('g', 'h');
} {exclusive wal}

do_test 2.1.3 {
  forcecopy test.db     test2.db
  forcecopy test.db-wal test2.db-wal
  sqlite3 db2 test2.db
  catchsql { SELECT * FROM t2 } db2
} {1 {unable to open database file}}
do_test 2.1.4 {
  catchsql { PRAGMA journal_mode = delete } db2
} {1 {unable to open database file}}
do_test 2.1.5 {
  execsql { 
    PRAGMA locking_mode = exclusive; 
    PRAGMA journal_mode = delete;
    SELECT * FROM t2;
  } db2
} {exclusive delete a b c d e f g h}

do_test 2.2.1 {
  forcecopy test.db     test2.db
  forcecopy test.db-wal test2.db-wal
  sqlite3 db3 test2.db -vfs tvfsshm
  sqlite3 db2 test2.db
  execsql { SELECT * FROM t2 } db3
} {a b c d e f g h}

do_test 2.2.2 {
  execsql  { PRAGMA locking_mode = exclusive }  db2

Changes to test/walslow.test.

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

ifcapable !wal {finish_test ; return }

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

db close
save_prng_state
for {set seed 1} {$seed<10} {incr seed} {







|







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

ifcapable !wal {finish_test ; return }

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

db close
save_prng_state
for {set seed 1} {$seed<10} {incr seed} {
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

    do_test walslow-1.seed=$seed.$iTest.2 {
      execsql "PRAGMA wal_checkpoint;"
      execsql { PRAGMA integrity_check }
    } {ok}

    do_test walslow-1.seed=$seed.$iTest.3 {
      file delete -force testX.db testX.db-wal
      file copy test.db testX.db
      file copy test.db-wal testX.db-wal
  
      sqlite3 db2 testX.db
      execsql { PRAGMA journal_mode = WAL } db2
      execsql { PRAGMA integrity_check } db2
    } {ok}
  
    do_test walslow-1.seed=$seed.$iTest.4 {







|
|
|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

    do_test walslow-1.seed=$seed.$iTest.2 {
      execsql "PRAGMA wal_checkpoint;"
      execsql { PRAGMA integrity_check }
    } {ok}

    do_test walslow-1.seed=$seed.$iTest.3 {
      forcedelete testX.db testX.db-wal
      copy_file test.db testX.db
      copy_file test.db-wal testX.db-wal
  
      sqlite3 db2 testX.db
      execsql { PRAGMA journal_mode = WAL } db2
      execsql { PRAGMA integrity_check } db2
    } {ok}
  
    do_test walslow-1.seed=$seed.$iTest.4 {

Changes to test/walthread.test.

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
    puts "Skipping $P(testname)"
    return
  }

  puts "Running $P(testname) for $P(seconds) seconds..."

  catch { db close }
  file delete -force test.db test.db-journal test.db-wal

  sqlite3 db test.db
  eval $P(init)
  catch { db close }

  foreach T $P(threads) {
    set name  [lindex $T 0]







|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
    puts "Skipping $P(testname)"
    return
  }

  puts "Running $P(testname) for $P(seconds) seconds..."

  catch { db close }
  forcedelete test.db test.db-journal test.db-wal

  sqlite3 db test.db
  eval $P(init)
  catch { db close }

  foreach T $P(threads) {
    set name  [lindex $T 0]
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
      INSERT INTO t1 SELECT randomblob(900) FROM t1;      /*  8192 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;      /* 16384 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;      /* 32768 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;      /* 65536 */
    COMMIT;
  }

  file copy -force test.db-wal bak.db-wal
  file copy -force test.db bak.db
  db close

  file copy -force bak.db-wal test.db-wal
  file copy -force bak.db test.db

  if {[file size test.db-wal] < [log_file_size [expr 64*1024] 1024]} {
    error "Somehow failed to create a large log file"
  }
  puts "Database with large log file recovered. Now running clients..."
} -thread T 5 {
  db eval { SELECT count(*) FROM t1 }
}
unset -nocomplain seconds

finish_test







|
|


|
|











504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
      INSERT INTO t1 SELECT randomblob(900) FROM t1;      /*  8192 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;      /* 16384 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;      /* 32768 */
      INSERT INTO t1 SELECT randomblob(900) FROM t1;      /* 65536 */
    COMMIT;
  }

  forcecopy test.db-wal bak.db-wal
  forcecopy test.db bak.db
  db close

  forcecopy bak.db-wal test.db-wal
  forcecopy bak.db test.db

  if {[file size test.db-wal] < [log_file_size [expr 64*1024] 1024]} {
    error "Somehow failed to create a large log file"
  }
  puts "Database with large log file recovered. Now running clients..."
} -thread T 5 {
  db eval { SELECT count(*) FROM t1 }
}
unset -nocomplain seconds

finish_test

Changes to test/win32lock.test.

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
    INSERT INTO t1 VALUES(3,randomblob(25000));
    INSERT INTO t1 VALUES(4,randomblob(12500));
    SELECT x, length(y) FROM t1 ORDER BY rowid;
  }
} {1 100000 2 50000 3 25000 4 12500}

unset -nocomplain delay1 rc msg
set delay1 50
set rc 0
set old_pending_byte [sqlite3_test_control_pending_byte 0x40000000]




while {1} {
  sqlite3_sleep 10
  lock_win32_file test.db 0 $::delay1

  set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
  if {$rc} {

    do_test win32lock-1.2-$delay1-fin {
       set ::msg
    } {disk I/O error}
    break
  } else {

    do_test win32lock-1.2-$delay1 {
       set ::msg
    } {1 100000 2 50000 3 25000 4 12500}
    if {[info exists ::log] && $::log!=""} {
      do_test win32lock-1.2-$delay1-log1 {
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }
    incr delay1 50
  }

  set ::log {}

}

do_test win32lock-2.0 {
  file_control_win32_av_retry db -1 -1
} {0 10 25}
do_test win32lock-2.1 {
  file_control_win32_av_retry db 1 1
} {0 1 1}











set delay1 50
while {1} {
  sqlite3_sleep 10
  lock_win32_file test.db 0 $::delay1

  set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
  if {$rc} {

    do_test win32lock-2.2-$delay1-fin {
       set ::msg
    } {disk I/O error}
    break
  } else {

    do_test win32lock-2.2-$delay1 {
       set ::msg
    } {1 100000 2 50000 3 25000 4 12500}
    if {$::log!=""} {
      do_test win32lock-2.2-$delay1-log1 {
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }
    incr delay1 50
  }

  set ::log {}

}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize







<
<

>
>
>
>

<

>


>
|


<

>
|








<

>
|
>









>
>
>
>
>
>
>
>
>
>
|

<

>


>
|


<

>
|


|





<

>
|
>







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
    INSERT INTO t1 VALUES(3,randomblob(25000));
    INSERT INTO t1 VALUES(4,randomblob(12500));
    SELECT x, length(y) FROM t1 ORDER BY rowid;
  }
} {1 100000 2 50000 3 25000 4 12500}

unset -nocomplain delay1 rc msg


set old_pending_byte [sqlite3_test_control_pending_byte 0x40000000]

set win32_lock_ok [list]
set win32_lock_error [list]
set delay1 25
while {1} {

  lock_win32_file test.db 0 $::delay1
  set ::log {}
  set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
  if {$rc} {
    lappend win32_lock_error $::delay1
    do_test win32lock-1.2-$delay1-error {
       set ::msg
    } {disk I/O error}

  } else {
    lappend win32_lock_ok $::delay1
    do_test win32lock-1.2-$delay1-ok {
       set ::msg
    } {1 100000 2 50000 3 25000 4 12500}
    if {[info exists ::log] && $::log!=""} {
      do_test win32lock-1.2-$delay1-log1 {
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }

  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  incr delay1 25
  sqlite3_sleep 10
}

do_test win32lock-2.0 {
  file_control_win32_av_retry db -1 -1
} {0 10 25}
do_test win32lock-2.1 {
  file_control_win32_av_retry db 1 1
} {0 1 1}

#
# NOTE: It is known that the win32lock-2.2-* tests may fail if the system is
#       experiencing heavy load (i.e. they are very timing sensitive).  This is
#       primarily due to the AV retry delay being set to 1 millisecond in the
#       win32lock-2.1 test (above).  While it is important to test this corner
#       case for the AV retry logic, a failure of this test should probably not
#       be interpreted as a bug in SQLite or these test cases.
#
set win32_lock_ok [list]
set win32_lock_error [list]
set delay1 1
while {1} {

  lock_win32_file test.db 0 $::delay1
  set ::log {}
  set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
  if {$rc} {
    lappend win32_lock_error $::delay1
    do_test win32lock-2.2-$delay1-error {
       set ::msg
    } {disk I/O error}

  } else {
    lappend win32_lock_ok $::delay1
    do_test win32lock-2.2-$delay1-ok {
       set ::msg
    } {1 100000 2 50000 3 25000 4 12500}
    if {[info exists ::log] && $::log!=""} {
      do_test win32lock-2.2-$delay1-log1 {
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }

  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  incr delay1 1
  sqlite3_sleep 10
}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize