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
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
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
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() ){
    h = CreateFileW((WCHAR*)zConverted,
       dwDesiredAccess,
       dwShareMode,
    while( (h = CreateFileW((WCHAR*)zConverted,
                            dwDesiredAccess,
                            dwShareMode, NULL,
       NULL,
       dwCreationDisposition,
       dwFlagsAndAttributes,
       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{
    h = CreateFileA((char*)zConverted,
       dwDesiredAccess,
       dwShareMode,
    while( (h = CreateFileA((char*)zConverted,
                            dwDesiredAccess,
                            dwShareMode, NULL,
       NULL,
       dwCreationDisposition,
       dwFlagsAndAttributes,
       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
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
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 = { 0, 0, 0 };
  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 ){
    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++;
5716
5717
5718
5719
5720
5721
5722





5723
5724
5725







5726
5727
5728
5729
5730
5731
5732
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
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
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
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
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
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
    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
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
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
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
    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
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
  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
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
    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
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
  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
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
    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
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
  # [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
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
    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
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
  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
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
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
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
  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
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
  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
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
      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}
  file delete -force cannot-read
  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
file delete -force test2.db
file delete -force no-such-file
forcedelete test2.db
forcedelete no-such-file

ifcapable subquery {
  do_test attach-7.1 {
    file delete -force test.db test.db-journal
    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
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
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
file delete -force test2.db
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 {
  file delete -force test4.db
  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
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
  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
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
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*] {file delete -force $f}
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
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
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
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
    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 {
  file delete -force test2.db
  file delete -force test2.db-journal
  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
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
    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
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
  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
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
  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
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
  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
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
  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
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
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
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
    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
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
  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
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
      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
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
  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
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 }
  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
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 }
  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
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 }
  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
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 }
  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
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 }
  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
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
forcedelete bak.db-wal
foreach {writer file} {db test.db db3 test.db db :memory:} {
  incr iTest
  catch { file delete bak.db }
  catch { delete_file bak.db }
  sqlite3 db2 bak.db
  catch { file delete $file }
  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
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 }
  catch { delete_file bak.db }
  sqlite3 db2 bak.db
  catch { file delete $file }
  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
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 }
  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
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 }
  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
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
  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
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 }
  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
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
  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
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
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
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
    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
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
  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
  file delete -force test.db test.db-journal
  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
  file delete -force test.db test.db-journal
  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
  file delete -force bu1.db bu2.db
  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
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
  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 {
    file delete -force bu3.db
    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 {
    file delete -force bu3.db
    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 {
  file delete -force bu4.db
  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"}}
 
file delete -force bu1.db bu2.db bu3.db bu4.db
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
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
  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
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 }
  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
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
    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
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
    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
}
file delete -force test.db
file delete -force test.db-journal
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
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
    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
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
    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
}
file delete -force test.db
file delete -force test.db-journal
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
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
  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
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}
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
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

# 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
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
  copy_file test.bu test.db
  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
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
  copy_file test.bu test.db
  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
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
  file delete -force test.db test.db-journal
  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
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
  file delete -force test.db test.db-journal
  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
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
  file delete -force test.db test.db-journal
  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
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
  file delete -force test.db test.db-journal
  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
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
file delete -force test.db test.db-journal
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
file delete -force test.db test.db-journal
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
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
  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).
  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  copy_file test.db corrupt.db
  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.
  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  copy_file test.db corrupt.db
  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.
  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  copy_file test.db corrupt.db
  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 {

  file delete -force corrupt.db
  file delete -force corrupt.db-journal
  copy_file test.db corrupt.db
  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
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
  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
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
  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
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
  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
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
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
file copy -force test.db-template test.db
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
file copy -force test.db-template test.db
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
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
forcecopy 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
  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
  file copy -force test.db-template test.db
  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
  file copy -force test.db-template test.db
  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
  file copy -force test.db-template test.db
  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
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
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
  file copy -force bak.db test.db
  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
  file copy -force bak.db test.db
  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;
  }
} {}

file copy -force test.db bak.db
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
  file copy -force bak.db test.db
  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
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
  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
  file copy -force bak.db test.db
  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
  file copy -force bak.db test.db
  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
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}
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
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)}]
}

# 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
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
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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
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
  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
  copy_file test.bu test.db
  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
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}
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
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
}

# 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
forcecopy 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
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
  copy_file test.bu test.db
  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
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
    copy_file test.bu test.db
    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
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
    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
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
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
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
    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
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
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
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
  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
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
  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
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
    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
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
  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}
  file delete -force test.db test.db-journal
  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
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
  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
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
    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
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
  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
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
    delete_file $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
  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
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
  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);
    }
    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
    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
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
  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
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
    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
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
    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
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 {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
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]
# -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
file delete -force test.db test.db-journal
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
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
    forcedelete 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
    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
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
  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
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
# 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
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
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
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
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
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
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
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
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
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
  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
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
  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
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
    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 {
    file delete -force test2.db
    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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
  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
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
  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
  file delete -force test8.db test8.db-journal
  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
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
  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
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
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
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
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
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
  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
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
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
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
  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
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
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
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
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
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
       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
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
    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
file delete -force test.db
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
  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
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
  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
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
  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
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
  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
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
    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
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
  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
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
    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
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
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
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
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
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
  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
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
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
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
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
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
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
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
  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
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
    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
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
  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
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
  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
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
  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.
file delete -force test2.db test2.db-journal
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
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
    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
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
  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
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
    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
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
  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
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
    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
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
    forcecopy test.db-journal test2.db-journal
    execsql {
      COMMIT;
    }
    copy_file test2.db-journal test.db-journal
    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
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
  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
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
forcecopy 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
  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
file delete -force test.db-bu
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
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.
# 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
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
  forcecopy test.db-journal test.db-journal-bu
  execsql {
    ROLLBACK;
  }
  db close
  file delete test.db
  file copy test.db-journal-bu test.db-journal
  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
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
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
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 }
      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
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
  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
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
  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
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
  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
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
  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
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 }
    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
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
  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
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
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
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
    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
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
  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
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
  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
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
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
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
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
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
    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/*] {file delete -force $f}
  file delete -force testdb
  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/*] {file delete -force $f}
  file delete -force testdb
  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
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
  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
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
  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
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
    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
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
    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
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
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
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
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
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
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
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
  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
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
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
file copy test.db test.db.bu
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
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
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
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}
      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)]} {
          file copy $::mallocopts(-testdb) test.db
          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
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
  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
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)
    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
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
  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
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
  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
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
  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
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
    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
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
    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
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
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
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
    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
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
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
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
  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 {
  file delete mydir
  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
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
  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
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
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
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
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
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
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
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
      forcecopy test.db bak.db
      forcecopy test.db-journal bak.db-journal
      execsql {
        COMMIT;
      }
    
      db close
      copy_file bak.db test.db
      copy_file bak.db-journal test.db-journal
      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
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
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
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}
  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
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
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
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 }
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
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
  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
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
  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
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
  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
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
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
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
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
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 }
  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*] { file delete -force $f }
  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
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 }
      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
file delete -force $dirname
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
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
  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
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
  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
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
  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
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
  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
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
  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
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 }
  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
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
  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
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
    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
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
  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
  file delete -force test.db
  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
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
  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 {
  file delete -force test2.db test2.db-journal
  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
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
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
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
    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
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
  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
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
      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
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
    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
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
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
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
  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
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
    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
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
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
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
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
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
  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
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 
  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
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
  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
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
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 }
  file delete -force test.db
  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
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
    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
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
  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
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
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
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
  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
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
    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
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
  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
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}
    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
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
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
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
  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
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
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
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
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
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
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
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
  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
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
  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
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
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
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
  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}
  file delete -force test.db test2.db
  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
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
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
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
  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
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
  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
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
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
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
  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
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
  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
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
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
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
  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
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
  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
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
  #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
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
  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
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
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
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
      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
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
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
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
  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
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
    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
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
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 [file delete -force]
# -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 {file delete -force test.db}
  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
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 }
  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
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
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
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
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
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}
  file delete -force test.db
  file delete -force test.db-journal
  file delete -force test.db-wal
  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
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] {
    file delete -force $f
    forcedelete $f
  }
  foreach f [glob -nocomplain test.db-mj*] {
    file delete -force $f
    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
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
}

# 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}
  }
}
960
961
962
963
964
965
966
967
968
969
970




971
972
973
974
975
976
977
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 {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}
      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
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
}

# 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}] {
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
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"
    file copy -force $f $f2
    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]
    file copy -force $f2 $f
    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*] { file delete -force $f }
  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
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
    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
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
  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
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
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
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
  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
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
  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
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
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
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 }
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
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
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
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
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
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
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
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
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
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
  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
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
  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
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
  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
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
  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 {
  file copy -force bak.db-journal test.db-journal
  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 {
  file copy -force bak.db-journal test.db-journal
  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 {
  file copy -force bak.db-journal test.db-journal
  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 {
  file copy -force bak.db-journal test.db-journal
  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
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
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
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
    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
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
    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
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
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
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
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
  file delete -force test.db test.db-journal
  file copy -force test.db-triggerA test.db
  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.
#
file delete -force test.db-triggerA
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
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
  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
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
  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
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
  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
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
  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
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
# [delete_file] command covers us in case the library was compiled
# without in-memory database support.
#
file delete -force :memory:
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
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
  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
379
380
381
382
383
384
385

386
387
388







-
+


    execsql {
      VACUUM;
    }
    cksum
  } $::cksum
}

file delete -force {a'z.db}
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
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
    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
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
  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
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
    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
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
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
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
    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
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
  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
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
  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
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
  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
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
  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
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
    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
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
  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 }
  file delete -force test.db test.db-wal
  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
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
  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
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
  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 {
  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal
  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
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
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
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
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
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
    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
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
  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
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
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
  }

  file copy -force test.db testX.db
  file copy -force test.db-wal testX.db-wal
  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 {
    file copy -force testX.db test.db
    file copy -force testX.db-wal test.db-wal
    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
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
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} {
    file copy -force testX.db test.db
    file delete -force test.db-wal
    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
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
  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
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
  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
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
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
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
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
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
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
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
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
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
  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
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
  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
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
  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
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
  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
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
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 {
  file copy -force test.db test2.db
  file copy -force test.db-wal test2.db-wal
  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
file delete -force test.db test.db-wal test.db-journal
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
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
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
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
  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
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
    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
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
  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
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
  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
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
  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
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
  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
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
  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
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
  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
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
  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
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
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
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 }
  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
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
    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');
    }

    file copy -force test.db test2.db
    file copy -force test.db-wal test2.db-wal
    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
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
    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
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
  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
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
  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
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
  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 {
  file delete -force test.db test.db-wal test.db-journal
  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 {
  file copy -force test.db-wal test2.db-wal
  file copy -force test.db test2.db
  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
file copy -force test.db test2.db
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} {

      file copy -force test.db-wal test2.db-wal
      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
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
  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
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
  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
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
#   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
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
  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
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
  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
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
  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
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
  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
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
  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
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
  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
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
  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 {
  file copy -force test.db     test2.db
  file copy -force test.db-wal test2.db-wal
  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
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
  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
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
      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
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
  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
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
  forcecopy test.db-wal bak.db-wal
  forcecopy test.db bak.db
  db close

  file copy -force bak.db-wal test.db-wal
  file copy -force bak.db test.db
  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
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 delay1 50
set rc 0
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} {
  sqlite3_sleep 10
  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-fin {
    do_test win32lock-1.2-$delay1-error {
       set ::msg
    } {disk I/O error}
    break
  } else {
    lappend win32_lock_ok $::delay1
    do_test win32lock-1.2-$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}}
    }
    incr delay1 50
  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  set ::log {}
  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 50
set delay1 1
while {1} {
  sqlite3_sleep 10
  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-fin {
    do_test win32lock-2.2-$delay1-error {
       set ::msg
    } {disk I/O error}
    break
  } else {
    lappend win32_lock_ok $::delay1
    do_test win32lock-2.2-$delay1 {
    do_test win32lock-2.2-$delay1-ok {
       set ::msg
    } {1 100000 2 50000 3 25000 4 12500}
    if {$::log!=""} {
    if {[info exists ::log] && $::log!=""} {
      do_test win32lock-2.2-$delay1-log1 {
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }
    incr delay1 50
  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  set ::log {}
  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