1# 2007 April 26
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
6#    May you do good and not evil.
7#    May you find forgiveness for yourself and forgive others.
8#    May you share freely, never taking more than you give.
9#
10#***********************************************************************
11# This file implements regression tests for SQLite library.  The
12# focus of this file is testing the incremental vacuum feature.
13#
14# Note: There are also some tests for incremental vacuum and IO 
15# errors in incrvacuum_ioerr.test.
16#
17# $Id: incrvacuum.test,v 1.23 2009/02/18 20:31:18 drh Exp $
18
19set testdir [file dirname $argv0]
20source $testdir/tester.tcl
21
22# If this build of the library does not support auto-vacuum, omit this
23# whole file.
24ifcapable {!autovacuum || !pragma} {
25  finish_test
26  return
27}
28
29#---------------------------------------------------------------------
30# Test the pragma on an empty database.
31#
32do_test incrvacuum-1.1 {
33  execsql {
34    pragma auto_vacuum;
35  }
36} $sqlite_options(default_autovacuum)
37do_test incrvacuum-1.2.0 {
38  # File size is sometimes 1 instead of 0 due to the hack we put in
39  # to work around ticket #3260.  Search for comments on #3260 in
40  # os_unix.c.
41  expr {[file size test.db] > 1}
42} {0}
43do_test incrvacuum-1.2 {
44  # This command will create the database.
45  execsql {
46    pragma auto_vacuum = 'full';
47    pragma auto_vacuum;
48  }
49} {1}
50do_test incrvacuum-1.2.1 {
51  expr {[file size test.db] > 0}
52} {1}
53do_test incrvacuum-1.3 {
54  execsql {
55    pragma auto_vacuum = 'incremental';
56    pragma auto_vacuum;
57  }
58} {2}
59do_test incrvacuum-1.4 {
60  # In this case the invalid value is ignored and the auto_vacuum
61  # setting remains unchanged.
62  execsql {
63    pragma auto_vacuum = 'invalid';
64    pragma auto_vacuum;
65  }
66} {2}
67do_test incrvacuum-1.5 {
68  execsql {
69    pragma auto_vacuum = 1;
70    pragma auto_vacuum;
71  }
72} {1}
73do_test incrvacuum-1.6 {
74  execsql {
75    pragma auto_vacuum = '2';
76    pragma auto_vacuum;
77  }
78} {2}
79do_test incrvacuum-1.7 {
80  # Invalid value. auto_vacuum setting remains unchanged.
81  execsql {
82    pragma auto_vacuum = 5;
83    pragma auto_vacuum;
84  }
85} {2}
86
87#---------------------------------------------------------------------
88# Test the pragma on a non-empty database. It is possible to toggle
89# the connection between "full" and "incremental" mode, but not to
90# change from either of these to "none", or from "none" to "full" or
91# "incremental".
92#
93do_test incrvacuum-2.1 {
94  execsql {
95    pragma auto_vacuum = 1;
96    CREATE TABLE abc(a, b, c);
97  }
98} {}
99do_test incrvacuum-2.2 {
100  execsql {
101    pragma auto_vacuum = 'none';
102    pragma auto_vacuum;
103  }
104} {1}
105do_test incrvacuum-2.2.1 {
106  db close
107  sqlite3 db test.db
108  execsql {
109    pragma auto_vacuum;
110  }
111} {1}
112do_test incrvacuum-2.3 {
113  execsql {
114    pragma auto_vacuum = 'incremental';
115    pragma auto_vacuum;
116  }
117} {2}
118do_test incrvacuum-2.4 {
119  execsql {
120    pragma auto_vacuum = 'full';
121    pragma auto_vacuum;
122  }
123} {1}
124
125#---------------------------------------------------------------------
126# Test that when the auto_vacuum mode is "incremental", the database
127# does not shrink when pages are removed from it. But it does if
128# the mode is set to "full".
129#
130do_test incrvacuum-3.1 {
131  execsql {
132    pragma auto_vacuum;
133  }
134} {1}
135do_test incrvacuum-3.2 {
136  set ::str [string repeat 1234567890 110]
137  execsql {
138    PRAGMA auto_vacuum = 2;
139    BEGIN;
140    CREATE TABLE tbl2(str);
141    INSERT INTO tbl2 VALUES($::str);
142    COMMIT;
143  }
144  # 5 pages:
145  #
146  #   1 -> database header
147  #   2 -> first back-pointer page
148  #   3 -> table abc
149  #   4 -> table tbl2
150  #   5 -> table tbl2 overflow page.
151  #
152  expr {[file size test.db] / 1024}
153} {5}
154do_test incrvacuum-3.3 {
155  execsql {
156    DROP TABLE abc;
157    DELETE FROM tbl2;
158  }
159  expr {[file size test.db] / 1024}
160} {5}
161do_test incrvacuum-3.4 {
162  execsql {
163    PRAGMA auto_vacuum = 1;
164    INSERT INTO tbl2 VALUES('hello world');
165  }
166  expr {[file size test.db] / 1024}
167} {3}
168
169#---------------------------------------------------------------------
170# Try to run a very simple incremental vacuum. Also verify that 
171# PRAGMA incremental_vacuum is a harmless no-op against a database that
172# does not support auto-vacuum.
173#
174do_test incrvacuum-4.1 {
175  set ::str [string repeat 1234567890 110]
176  execsql {
177    PRAGMA auto_vacuum = 2;
178    INSERT INTO tbl2 VALUES($::str);
179    CREATE TABLE tbl1(a, b, c);
180  }
181  expr {[file size test.db] / 1024}
182} {5}
183do_test incrvacuum-4.2 {
184  execsql {
185    DELETE FROM tbl2;
186    DROP TABLE tbl1;
187  }
188  expr {[file size test.db] / 1024}
189} {5}
190do_test incrvacuum-4.3 {
191  set ::nStep 0
192  db eval {pragma incremental_vacuum(10)} {
193    incr ::nStep
194  }
195  list [expr {[file size test.db] / 1024}] $::nStep
196} {3 2}
197
198#---------------------------------------------------------------------
199# The following tests - incrvacuum-5.* - test incremental vacuum
200# from within a transaction.
201#
202do_test incrvacuum-5.1.1 {
203  expr {[file size test.db] / 1024}
204} {3}
205do_test incrvacuum-5.1.2 {
206  execsql {
207    BEGIN;
208    DROP TABLE tbl2;
209    PRAGMA incremental_vacuum;
210    COMMIT;
211  }
212  expr {[file size test.db] / 1024}
213} {1}
214
215do_test incrvacuum-5.2.1 {
216  set ::str [string repeat abcdefghij 110]
217  execsql {
218    BEGIN;
219    CREATE TABLE tbl1(a);
220    INSERT INTO tbl1 VALUES($::str);
221    PRAGMA incremental_vacuum;                 -- this is a no-op.
222    COMMIT;
223  }
224  expr {[file size test.db] / 1024}
225} {4}
226do_test incrvacuum-5.2.2 {
227  set ::str [string repeat abcdefghij 110]
228  execsql {
229    BEGIN;
230    INSERT INTO tbl1 VALUES($::str);
231    INSERT INTO tbl1 SELECT * FROM tbl1;
232    DELETE FROM tbl1 WHERE oid%2;        -- Put 2 overflow pages on free-list.
233    COMMIT;
234  }
235  expr {[file size test.db] / 1024}
236} {7}
237do_test incrvacuum-5.2.3 {
238  execsql {
239    BEGIN;
240    PRAGMA incremental_vacuum;           -- Vacuum up the two pages.
241    CREATE TABLE tbl2(b);                -- Use one free page as a table root.
242    INSERT INTO tbl2 VALUES('a nice string');
243    COMMIT;
244  }
245  expr {[file size test.db] / 1024}
246} {6}
247do_test incrvacuum-5.2.4 {
248  execsql {
249    SELECT * FROM tbl2;
250  }
251} {{a nice string}}
252do_test incrvacuum-5.2.5 {
253  execsql {
254    DROP TABLE tbl1;
255    DROP TABLE tbl2;
256    PRAGMA incremental_vacuum;
257  }
258  expr {[file size test.db] / 1024}
259} {1}
260
261
262# Test cases incrvacuum-5.3.* use the following list as input data.
263# Two new databases are opened, one with incremental vacuum enabled,
264# the other with no auto-vacuum completely disabled. After executing
265# each element of the following list on both databases, test that
266# the integrity-check passes and the contents of each are identical.
267# 
268set TestScriptList [list {
269  BEGIN;
270  CREATE TABLE t1(a, b);
271  CREATE TABLE t2(a, b);
272  CREATE INDEX t1_i ON t1(a);
273  CREATE INDEX t2_i ON t2(a);
274} {
275  INSERT INTO t1 VALUES($::str1, $::str2);
276  INSERT INTO t1 VALUES($::str1||$::str2, $::str2||$::str1);
277  INSERT INTO t2 SELECT b, a FROM t1;
278  INSERT INTO t2 SELECT a, b FROM t1;
279  INSERT INTO t1 SELECT b, a FROM t2;
280  UPDATE t2 SET b = '';
281  PRAGMA incremental_vacuum;
282} {
283  UPDATE t2 SET b = (SELECT b FROM t1 WHERE t1.oid = t2.oid);
284  PRAGMA incremental_vacuum;
285} {
286  CREATE TABLE t3(a, b);
287  INSERT INTO t3 SELECT * FROM t2;
288  DROP TABLE t2;
289  PRAGMA incremental_vacuum;
290} {
291  CREATE INDEX t3_i ON t3(a);
292  COMMIT;
293} {
294  BEGIN;
295  DROP INDEX t3_i;
296  PRAGMA incremental_vacuum;
297  INSERT INTO t3 VALUES('hello', 'world');
298  ROLLBACK;
299} {
300  INSERT INTO t3 VALUES('hello', 'world');
301}
302]
303
304# If this build omits subqueries, step 2 in the above list will not
305# work. Replace it with "" in this case. 
306#
307ifcapable !subquery { lset TestScriptList 2 "" }
308
309# Compare the contents of databases $A and $B.
310#
311proc compare_dbs {A B tname} {
312  set tbl_list [execsql {
313    SELECT tbl_name FROM sqlite_master WHERE type = 'table'
314  } $A]
315
316  do_test ${tname}.1 [subst {
317    execsql {
318      SELECT tbl_name FROM sqlite_master WHERE type = 'table'
319    } $B
320  }] $tbl_list
321
322  set tn 1
323  foreach tbl $tbl_list {
324    set control [execsql "SELECT * FROM $tbl" $A]
325    do_test ${tname}.[incr tn] [subst {
326      execsql "SELECT * FROM $tbl" $B
327    }] $control
328  }
329}
330
331set ::str1 [string repeat abcdefghij 130]
332set ::str2 [string repeat 1234567890 105]
333
334file delete -force test1.db test1.db-journal test2.db test2.db-journal
335sqlite3 db1 test1.db
336sqlite3 db2 test2.db
337execsql { PRAGMA auto_vacuum = 'none' } db1
338execsql { PRAGMA auto_vacuum = 'incremental' } db2
339
340set tn 1
341foreach sql $::TestScriptList {
342  execsql $sql db1
343  execsql $sql db2
344
345  compare_dbs db1 db2 incrvacuum-5.3.${tn}
346  do_test incrvacuum-5.3.${tn}.integrity1 {
347    execsql { PRAGMA integrity_check; } db1
348  } {ok}
349  do_test incrvacuum-5.3.${tn}.integrity2 {
350    execsql { PRAGMA integrity_check; } db2
351  } {ok}
352  incr tn
353}
354db1 close
355db2 close
356#
357# End of test cases 5.3.*
358
359#---------------------------------------------------------------------
360# The following tests - incrvacuum-6.* - test running incremental 
361# vacuum while another statement (a read) is being executed.
362#
363for {set jj 0} {$jj < 10} {incr jj} {
364  # Build some test data. Two tables are created in an empty
365  # database. tbl1 data is a contiguous block starting at page 5 (pages
366  # 3 and 4 are the table roots). tbl2 is a contiguous block starting 
367  # right after tbl1.
368  #
369  # Then drop tbl1 so that when an incr vacuum is run the pages
370  # of tbl2 have to be moved to fill the gap.
371  #
372  do_test incrvacuum-6.${jj}.1 {
373    execsql {
374      DROP TABLE IF EXISTS tbl1;
375      DROP TABLE IF EXISTS tbl2;
376      PRAGMA incremental_vacuum;
377      CREATE TABLE tbl1(a, b);
378      CREATE TABLE tbl2(a, b);
379      BEGIN;
380    }
381    for {set ii 0} {$ii < 1000} {incr ii} {
382      db eval {INSERT INTO tbl1 VALUES($ii, $ii || $ii)}
383    }
384    execsql {
385      INSERT INTO tbl2 SELECT * FROM tbl1;
386      COMMIT;
387      DROP TABLE tbl1;
388    }
389    expr {[file size test.db] / 1024}
390  } {36}
391
392  # Run a linear scan query on tbl2. After reading ($jj*100) rows, 
393  # run the incremental vacuum to shrink the database.
394  #
395  do_test incrvacuum-6.${jj}.2 {
396    set ::nRow 0
397    db eval {SELECT a FROM tbl2} {} {
398      if {$a == [expr $jj*100]} {
399        db eval {PRAGMA incremental_vacuum}
400      }
401      incr ::nRow
402    }
403    list [expr {[file size test.db] / 1024}] $nRow
404  } {19 1000}
405}
406
407#---------------------------------------------------------------------
408# This test - incrvacuum-7.* - is to check that the database can be
409# written in the middle of an incremental vacuum.
410#
411set ::iWrite 1
412while 1 {
413  do_test incrvacuum-7.${::iWrite}.1 {
414    execsql {
415      DROP TABLE IF EXISTS tbl1;
416      DROP TABLE IF EXISTS tbl2;
417      PRAGMA incremental_vacuum;
418      CREATE TABLE tbl1(a, b);
419      CREATE TABLE tbl2(a, b);
420      BEGIN;
421    }
422    for {set ii 0} {$ii < 1000} {incr ii} {
423      db eval {INSERT INTO tbl1 VALUES($ii, $ii || $ii)}
424    }
425    execsql {
426      INSERT INTO tbl2 SELECT * FROM tbl1;
427      COMMIT;
428      DROP TABLE tbl1;
429    }
430    expr {[file size test.db] / 1024}
431  } {36}
432
433  do_test incrvacuum-7.${::iWrite}.2 {
434    set ::nRow 0
435    db eval {PRAGMA incremental_vacuum} {
436      incr ::nRow
437      if {$::nRow == $::iWrite} {
438        db eval {
439          CREATE TABLE tbl1(a, b);
440          INSERT INTO tbl1 VALUES('hello', 'world');
441        }
442      }
443    }
444    list [expr {[file size test.db] / 1024}]
445  } {20}
446
447  do_test incrvacuum-7.${::iWrite}.3 {
448    execsql {
449      SELECT * FROM tbl1;
450    }
451  } {hello world}
452
453  if {$::nRow == $::iWrite} break
454  incr ::iWrite
455}
456
457#---------------------------------------------------------------------
458# This test - incrvacuum-8.* - is to check that nothing goes wrong
459# with an incremental-vacuum if it is the first statement executed
460# after an existing database is opened.
461#
462# At one point, this would always return SQLITE_SCHEMA (which 
463# causes an infinite loop in tclsqlite.c if using the Tcl interface).
464#
465do_test incrvacuum-8.1 {
466  db close
467  sqlite3 db test.db
468  execsql {
469    PRAGMA incremental_vacuum(50);
470  }
471} {}
472
473#---------------------------------------------------------------------
474# At one point this test case was causing an assert() to fail.
475#
476do_test incrvacuum-9.1 {
477  db close
478  file delete -force test.db test.db-journal
479  sqlite3 db test.db
480
481  execsql {
482    PRAGMA auto_vacuum = 'incremental';
483    CREATE TABLE t1(a, b, c);
484    CREATE TABLE t2(a, b, c);
485    INSERT INTO t2 VALUES(randstr(500,500),randstr(500,500),randstr(500,500));
486    INSERT INTO t1 VALUES(1, 2, 3);
487    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
488    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
489    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
490    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
491    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
492    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
493    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
494    INSERT INTO t1 SELECT a||a, b||b, c||c FROM t1;
495  }
496} {}
497
498do_test incrvacuum-9.2 {
499  execsql {
500    PRAGMA synchronous = 'OFF';
501    BEGIN;
502    UPDATE t1 SET a = a, b = b, c = c;
503    DROP TABLE t2;
504    PRAGMA incremental_vacuum(10);
505    ROLLBACK;
506  }
507} {}
508
509do_test incrvacuum-9.3 {
510  execsql {
511    PRAGMA cache_size = 10;
512    BEGIN;
513    UPDATE t1 SET a = a, b = b, c = c;
514    DROP TABLE t2;
515    PRAGMA incremental_vacuum(10);
516    ROLLBACK;
517  }
518} {}
519
520#---------------------------------------------------------------------
521# Test that the parameter to the incremental_vacuum pragma works. That
522# is, if the user executes "PRAGMA incremental_vacuum(N)", at most
523# N pages are vacuumed.
524#
525do_test incrvacuum-10.1 {
526  execsql {
527    DROP TABLE t1;
528    DROP TABLE t2;
529  }
530  expr [file size test.db] / 1024
531} {29}
532
533do_test incrvacuum-10.2 {
534  execsql {
535    PRAGMA incremental_vacuum(1);
536  }
537  expr [file size test.db] / 1024
538} {28}
539
540do_test incrvacuum-10.3 {
541  execsql {
542    PRAGMA incremental_vacuum(5);
543  }
544  expr [file size test.db] / 1024
545} {23}
546
547do_test incrvacuum-10.4 {
548  execsql {
549    PRAGMA incremental_vacuum('1');
550  }
551  expr [file size test.db] / 1024
552} {22}
553
554do_test incrvacuum-10.5 {
555  execsql {
556    PRAGMA incremental_vacuum("+3");
557  }
558  expr [file size test.db] / 1024
559} {19}
560
561do_test incrvacuum-10.6 {
562  execsql {
563    PRAGMA incremental_vacuum = 1;
564  }
565  expr [file size test.db] / 1024
566} {18}
567
568do_test incrvacuum-10.7 {
569  # Use a really big number as an argument to incremetal_vacuum. Should
570  # be interpreted as "free all possible space".
571  execsql {
572    PRAGMA incremental_vacuum(2147483649);
573  }
574  expr [file size test.db] / 1024
575} {1}
576
577do_test incrvacuum-10.8 {
578  execsql {
579    CREATE TABLE t1(x);
580    INSERT INTO t1 VALUES(hex(randomblob(1000)));
581    DROP TABLE t1;
582  }
583  # A negative number means free all possible space.
584  execsql {
585    PRAGMA incremental_vacuum=-1;
586  }
587  expr [file size test.db] / 1024
588} {1}
589
590#----------------------------------------------------------------
591# Test that if we set the auto_vacuum mode to 'incremental', then
592# create a database, thereafter that database defaults to incremental 
593# vacuum mode.
594#
595db close
596file delete -force test.db test.db-journal
597sqlite3 db test.db
598
599ifcapable default_autovacuum {
600  do_test incrvacuum-11.1-av-dflt-on {
601    execsql {
602      PRAGMA auto_vacuum;
603    }
604  } $AUTOVACUUM
605} else {
606  do_test incrvacuum-11.1-av-dflt-off {
607    execsql {
608      PRAGMA auto_vacuum;
609    }
610  } {0}
611}
612do_test incrvacuum-11.2 {
613  execsql {
614    PRAGMA auto_vacuum = incremental;
615  }
616} {}
617do_test incrvacuum-11.3 {
618  execsql {
619    PRAGMA auto_vacuum;
620  }
621} {2}
622do_test incrvacuum-11.4 {
623  # The database has now been created.
624  expr {[file size test.db]>0}
625} {1}
626do_test incrvacuum-11.5 {
627  # Close and reopen the connection.
628  db close
629  sqlite3 db test.db
630
631  # Test we are still in incremental vacuum mode.
632  execsql { PRAGMA auto_vacuum; }
633} {2}
634do_test incrvacuum-11.6 {
635  execsql {
636    PRAGMA auto_vacuum = 'full';
637    PRAGMA auto_vacuum;
638  }
639} {1}
640do_test incrvacuum-11.7 {
641  # Close and reopen the connection.
642  db close
643  sqlite3 db test.db
644
645  # Test we are still in "full" auto-vacuum mode.
646  execsql { PRAGMA auto_vacuum; }
647} {1}
648
649#----------------------------------------------------------------------
650# Special case: What happens if the database is locked when a "PRAGMA
651# auto_vacuum = XXX" statement is executed.
652#
653db close
654file delete -force test.db test.db-journal
655sqlite3 db test.db
656
657do_test incrvacuum-12.1 {
658  execsql {
659    PRAGMA auto_vacuum = 1;
660  }
661  expr {[file size test.db]>0}
662} {1}
663
664# Try to change the auto-vacuum from "full" to "incremental" while the
665# database is locked. Nothing should change.
666#
667do_test incrvacuum-12.2 {
668  sqlite3 db2 test.db
669  execsql { BEGIN EXCLUSIVE; } db2
670  catchsql { PRAGMA auto_vacuum = 2; }
671} {1 {database is locked}}
672
673do_test incrvacuum-12.3 {
674  execsql { ROLLBACK; } db2
675  execsql { PRAGMA auto_vacuum }
676} {2}   ;# Still 2 because PRAGMA auto_vacuum setting held in case of vacuum
677do_test incrvacuum-12.4 {
678  db close
679  sqlite3 db test.db
680  execsql { PRAGMA auto_vacuum }
681} {1}   ;# Revert to 1 because the database file did not change
682
683do_test incrvacuum-12.5 {
684  execsql { SELECT * FROM sqlite_master }
685  execsql { PRAGMA auto_vacuum }
686} {1}
687
688#----------------------------------------------------------------------
689# Special case #2: What if one process prepares a "PRAGMA auto_vacuum = XXX"
690# statement when the database is empty, but doesn't execute it until
691# after some other process has created the database.
692#
693db2 close
694db close
695file delete -force test.db test.db-journal
696sqlite3 db test.db  ;  set ::DB [sqlite3_connection_pointer db]
697sqlite3 db2 test.db
698
699do_test incrvacuum-13.1 {
700  # File size is sometimes 1 instead of 0 due to the hack we put in
701  # to work around ticket #3260.  Search for comments on #3260 in
702  # os_unix.c.
703  expr {[file size test.db]>1}
704} {0}
705do_test incrvacuum-13.2 {
706  set ::STMT [sqlite3_prepare $::DB {PRAGMA auto_vacuum = 2} -1 DUMMY]
707  execsql {
708    PRAGMA auto_vacuum = none;
709    PRAGMA default_cache_size = 1024;
710    PRAGMA auto_vacuum;
711  } db2
712} {0}
713do_test incrvacuum-13.3 {
714  expr {[file size test.db]>0}
715} {1}
716do_test incrvacuum-13.4 {
717  set rc [sqlite3_step $::STMT]
718  list $rc [sqlite3_finalize $::STMT]
719} {SQLITE_DONE SQLITE_OK}
720do_test incrvacuum-13.5 {
721  execsql {
722    PRAGMA auto_vacuum;
723  }
724} {0}
725
726
727# Verify that the incremental_vacuum pragma fails gracefully if it
728# is used against an invalid database file.
729#
730if {[permutation] == ""} {
731  do_test incrvacuum-14.1 {
732    set out [open invalid.db w]
733    puts $out "This is not an SQLite database file"
734    close $out
735    sqlite3 db3 invalid.db
736    catchsql {
737      PRAGMA incremental_vacuum(10);
738    } db3
739  } {1 {file is encrypted or is not a database}}
740  db3 close
741}
742
743do_test incrvacuum-15.1 {
744  db close
745  db2 close
746  file delete -force test.db
747  sqlite3 db test.db
748
749  set str [string repeat "abcdefghij" 500]
750
751  execsql {
752    PRAGMA cache_size = 10;
753    PRAGMA auto_vacuum = incremental;
754    CREATE TABLE t1(x, y);
755    INSERT INTO t1 VALUES('a', $str);
756    INSERT INTO t1 VALUES('b', $str);
757    INSERT INTO t1 VALUES('c', $str);
758    INSERT INTO t1 VALUES('d', $str);
759    INSERT INTO t1 VALUES('e', $str);
760    INSERT INTO t1 VALUES('f', $str);
761    INSERT INTO t1 VALUES('g', $str);
762    INSERT INTO t1 VALUES('h', $str);
763    INSERT INTO t1 VALUES('i', $str);
764    INSERT INTO t1 VALUES('j', $str);
765    INSERT INTO t1 VALUES('j', $str);
766
767    CREATE TABLE t2(x PRIMARY KEY, y);
768    INSERT INTO t2 VALUES('a', $str);
769    INSERT INTO t2 VALUES('b', $str);
770    INSERT INTO t2 VALUES('c', $str);
771    INSERT INTO t2 VALUES('d', $str);
772
773    BEGIN;
774      DELETE FROM t2;
775      PRAGMA incremental_vacuum;
776  }
777
778  catchsql {INSERT INTO t2 SELECT * FROM t1}
779
780  execsql { 
781    COMMIT;
782    PRAGMA integrity_check;
783  }
784} {ok}
785
786finish_test
787