1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TclScript/interrupt.test Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,183 @@
1.4 +# 2004 Feb 8
1.5 +#
1.6 +# The author disclaims copyright to this source code. In place of
1.7 +# a legal notice, here is a blessing:
1.8 +#
1.9 +# May you do good and not evil.
1.10 +# May you find forgiveness for yourself and forgive others.
1.11 +# May you share freely, never taking more than you give.
1.12 +#
1.13 +#***********************************************************************
1.14 +# This file implements regression tests for SQLite library. The
1.15 +# focus of this script is the sqlite_interrupt() API.
1.16 +#
1.17 +# $Id: interrupt.test,v 1.16 2008/01/16 17:46:38 drh Exp $
1.18 +
1.19 +
1.20 +set testdir [file dirname $argv0]
1.21 +source $testdir/tester.tcl
1.22 +set DB [sqlite3_connection_pointer db]
1.23 +
1.24 +# This routine attempts to execute the sql in $sql. It triggers an
1.25 +# interrupt at progressively later and later points during the processing
1.26 +# and checks to make sure SQLITE_INTERRUPT is returned. Eventually,
1.27 +# the routine completes successfully.
1.28 +#
1.29 +proc interrupt_test {testid sql result {initcnt 0}} {
1.30 + set orig_sum [cksum]
1.31 + set i $initcnt
1.32 + while 1 {
1.33 + incr i
1.34 + set ::sqlite_interrupt_count $i
1.35 + do_test $testid.$i.1 [format {
1.36 + set ::r [catchsql %s]
1.37 + set ::code [db errorcode]
1.38 + expr {$::code==0 || $::code==9}
1.39 + } [list $sql]] 1
1.40 + if {$::code==9} {
1.41 + do_test $testid.$i.2 {
1.42 + cksum
1.43 + } $orig_sum
1.44 + } else {
1.45 + do_test $testid.$i.99 {
1.46 + set ::r
1.47 + } [list 0 $result]
1.48 + break
1.49 + }
1.50 + }
1.51 + set ::sqlite_interrupt_count 0
1.52 +}
1.53 +
1.54 +do_test interrupt-1.1 {
1.55 + execsql {
1.56 + CREATE TABLE t1(a,b);
1.57 + SELECT name FROM sqlite_master;
1.58 + }
1.59 +} {t1}
1.60 +interrupt_test interrupt-1.2 {DROP TABLE t1} {}
1.61 +do_test interrupt-1.3 {
1.62 + execsql {
1.63 + SELECT name FROM sqlite_master;
1.64 + }
1.65 +} {}
1.66 +integrity_check interrupt-1.4
1.67 +
1.68 +do_test interrrupt-2.1 {
1.69 + execsql {
1.70 + BEGIN;
1.71 + CREATE TABLE t1(a,b);
1.72 + INSERT INTO t1 VALUES(1,randstr(300,400));
1.73 + INSERT INTO t1 SELECT a+1, randstr(300,400) FROM t1;
1.74 + INSERT INTO t1 SELECT a+2, a || '-' || b FROM t1;
1.75 + INSERT INTO t1 SELECT a+4, a || '-' || b FROM t1;
1.76 + INSERT INTO t1 SELECT a+8, a || '-' || b FROM t1;
1.77 + INSERT INTO t1 SELECT a+16, a || '-' || b FROM t1;
1.78 + INSERT INTO t1 SELECT a+32, a || '-' || b FROM t1;
1.79 + COMMIT;
1.80 + UPDATE t1 SET b=substr(b,-5,5);
1.81 + SELECT count(*) from t1;
1.82 + }
1.83 +} 64
1.84 +set origsize [file size test.db]
1.85 +set cksum [db eval {SELECT md5sum(a || b) FROM t1}]
1.86 +ifcapable {vacuum} {
1.87 + interrupt_test interrupt-2.2 {VACUUM} {} 100
1.88 +}
1.89 +do_test interrupt-2.3 {
1.90 + execsql {
1.91 + SELECT md5sum(a || b) FROM t1;
1.92 + }
1.93 +} $cksum
1.94 +ifcapable {vacuum && !default_autovacuum} {
1.95 + do_test interrupt-2.4 {
1.96 + expr {$::origsize>[file size test.db]}
1.97 + } 1
1.98 +}
1.99 +ifcapable {explain} {
1.100 + do_test interrupt-2.5 {
1.101 + set sql {EXPLAIN SELECT max(a,b), a, b FROM t1}
1.102 + execsql $sql
1.103 + set rc [catch {db eval $sql {sqlite3_interrupt $DB}} msg]
1.104 + lappend rc $msg
1.105 + } {1 interrupted}
1.106 +}
1.107 +integrity_check interrupt-2.6
1.108 +
1.109 +# Ticket #594. If an interrupt occurs in the middle of a transaction
1.110 +# and that transaction is later rolled back, the internal schema tables do
1.111 +# not reset.
1.112 +#
1.113 +# UPDATE: Interrupting a DML statement in the middle of a transaction now
1.114 +# causes the transaction to roll back. Leaving the transaction open after
1.115 +# an SQL statement was interrupted halfway through risks database corruption.
1.116 +#
1.117 +ifcapable tempdb {
1.118 + for {set i 1} {$i<50} {incr i 5} {
1.119 + do_test interrupt-3.$i.1 {
1.120 + execsql {
1.121 + BEGIN;
1.122 + CREATE TEMP TABLE t2(x,y);
1.123 + SELECT name FROM sqlite_temp_master;
1.124 + }
1.125 + } {t2}
1.126 + do_test interrupt-3.$i.2 {
1.127 + set ::sqlite_interrupt_count $::i
1.128 + catchsql {
1.129 + INSERT INTO t2 SELECT * FROM t1;
1.130 + }
1.131 + } {1 interrupted}
1.132 + do_test interrupt-3.$i.3 {
1.133 + execsql {
1.134 + SELECT name FROM sqlite_temp_master;
1.135 + }
1.136 + } {}
1.137 + do_test interrupt-3.$i.4 {
1.138 + catchsql {
1.139 + ROLLBACK
1.140 + }
1.141 + } {1 {cannot rollback - no transaction is active}}
1.142 + do_test interrupt-3.$i.5 {
1.143 + catchsql {SELECT name FROM sqlite_temp_master};
1.144 + execsql {
1.145 + SELECT name FROM sqlite_temp_master;
1.146 + }
1.147 + } {}
1.148 + }
1.149 +}
1.150 +
1.151 +# There are reports of a memory leak if an interrupt occurs during
1.152 +# the beginning of a complex query - before the first callback. We
1.153 +# will try to reproduce it here:
1.154 +#
1.155 +execsql {
1.156 + CREATE TABLE t2(a,b,c);
1.157 + INSERT INTO t2 SELECT round(a/10), randstr(50,80), randstr(50,60) FROM t1;
1.158 +}
1.159 +set sql {
1.160 + SELECT max(min(b,c)), min(max(b,c)), a FROM t2 GROUP BY a ORDER BY a;
1.161 +}
1.162 +set sqlite_interrupt_count 1000000
1.163 +execsql $sql
1.164 +set max_count [expr {1000000-$sqlite_interrupt_count}]
1.165 +for {set i 1} {$i<$max_count-5} {incr i 1} {
1.166 + do_test interrupt-4.$i.1 {
1.167 + set ::sqlite_interrupt_count $::i
1.168 + catchsql $sql
1.169 + } {1 interrupted}
1.170 +}
1.171 +
1.172 +# Interrupt during parsing
1.173 +#
1.174 +do_test interrupt-5.1 {
1.175 + proc fake_interrupt {args} {
1.176 + db collate fake_collation no-op
1.177 + sqlite3_interrupt db
1.178 + return SQLITE_OK
1.179 + }
1.180 + db collation_needed fake_interrupt
1.181 + catchsql {
1.182 + CREATE INDEX fake ON fake1(a COLLATE fake_collation, b, c DESC);
1.183 + }
1.184 +} {1 interrupt}
1.185 +
1.186 +finish_test