1348bb5d6Sdanielk1977# 2001 September 15 2348bb5d6Sdanielk1977# 3348bb5d6Sdanielk1977# The author disclaims copyright to this source code. In place of 4348bb5d6Sdanielk1977# a legal notice, here is a blessing: 5348bb5d6Sdanielk1977# 6348bb5d6Sdanielk1977# May you do good and not evil. 7348bb5d6Sdanielk1977# May you find forgiveness for yourself and forgive others. 8348bb5d6Sdanielk1977# May you share freely, never taking more than you give. 9348bb5d6Sdanielk1977# 10348bb5d6Sdanielk1977#*********************************************************************** 11348bb5d6Sdanielk1977# This file implements regression tests for SQLite library. The 12348bb5d6Sdanielk1977# focus of this file is testing the 'progress callback'. 13348bb5d6Sdanielk1977# 14de523accSdanielk1977# $Id: progress.test,v 1.8 2007/06/15 14:53:53 danielk1977 Exp $ 15348bb5d6Sdanielk1977 16348bb5d6Sdanielk1977set testdir [file dirname $argv0] 17348bb5d6Sdanielk1977source $testdir/tester.tcl 18348bb5d6Sdanielk1977 194489f9bdSdanielk1977# If the progress callback is not available in this build, skip this 204489f9bdSdanielk1977# whole file. 214489f9bdSdanielk1977ifcapable !progress { 224489f9bdSdanielk1977 finish_test 234489f9bdSdanielk1977 return 244489f9bdSdanielk1977} 254489f9bdSdanielk1977 26348bb5d6Sdanielk1977# Build some test data 27348bb5d6Sdanielk1977# 28348bb5d6Sdanielk1977execsql { 29348bb5d6Sdanielk1977 BEGIN; 30348bb5d6Sdanielk1977 CREATE TABLE t1(a); 31348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(1); 32348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(2); 33348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(3); 34348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(4); 35348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(5); 36348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(6); 37348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(7); 38348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(8); 39348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(9); 40348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(10); 41348bb5d6Sdanielk1977 COMMIT; 42348bb5d6Sdanielk1977} 43348bb5d6Sdanielk1977 44348bb5d6Sdanielk1977 45348bb5d6Sdanielk1977# Test that the progress callback is invoked. 46348bb5d6Sdanielk1977do_test progress-1.0 { 47348bb5d6Sdanielk1977 set counter 0 48348bb5d6Sdanielk1977 db progress 1 "[namespace code {incr counter}] ; expr 0" 49348bb5d6Sdanielk1977 execsql { 50348bb5d6Sdanielk1977 SELECT * FROM t1 51348bb5d6Sdanielk1977 } 52348bb5d6Sdanielk1977 expr $counter > 1 53348bb5d6Sdanielk1977} 1 540f14e2ebSdrhdo_test progress-1.0.1 { 550f14e2ebSdrh db progress 560f14e2ebSdrh} {::namespace inscope :: {incr counter} ; expr 0} 570f14e2ebSdrhdo_test progress-1.0.2 { 580f14e2ebSdrh set v [catch {db progress xyz bogus} msg] 590f14e2ebSdrh lappend v $msg 600f14e2ebSdrh} {1 {expected integer but got "xyz"}} 61348bb5d6Sdanielk1977 62348bb5d6Sdanielk1977# Test that the query is abandoned when the progress callback returns non-zero 63b45bb9f1Sdrhdo_test progress-1.1 { 64348bb5d6Sdanielk1977 set counter 0 65348bb5d6Sdanielk1977 db progress 1 "[namespace code {incr counter}] ; expr 1" 661d850a72Sdanielk1977 set rc [catch {execsql { 67348bb5d6Sdanielk1977 SELECT * FROM t1 681d850a72Sdanielk1977 }}] 691d850a72Sdanielk1977 list $counter $rc 701d850a72Sdanielk1977} {1 1} 71348bb5d6Sdanielk1977 72348bb5d6Sdanielk1977# Test that the query is rolled back when the progress callback returns 73348bb5d6Sdanielk1977# non-zero. 74b45bb9f1Sdrhdo_test progress-1.2 { 75348bb5d6Sdanielk1977 76348bb5d6Sdanielk1977 # This figures out how many opcodes it takes to copy 5 extra rows into t1. 77348bb5d6Sdanielk1977 db progress 1 "[namespace code {incr five_rows}] ; expr 0" 78348bb5d6Sdanielk1977 set five_rows 0 79348bb5d6Sdanielk1977 execsql { 80348bb5d6Sdanielk1977 INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 6 81348bb5d6Sdanielk1977 } 82348bb5d6Sdanielk1977 db progress 0 "" 83348bb5d6Sdanielk1977 execsql { 84348bb5d6Sdanielk1977 DELETE FROM t1 WHERE a > 10 85348bb5d6Sdanielk1977 } 86348bb5d6Sdanielk1977 87348bb5d6Sdanielk1977 # Now set up the progress callback to abandon the query after the number of 88348bb5d6Sdanielk1977 # opcodes to copy 5 rows. That way, when we try to copy 6 rows, we know 89348bb5d6Sdanielk1977 # some data will have been inserted into the table by the time the progress 90348bb5d6Sdanielk1977 # callback abandons the query. 91348bb5d6Sdanielk1977 db progress $five_rows "expr 1" 921d850a72Sdanielk1977 catchsql { 931d850a72Sdanielk1977 INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 9 94348bb5d6Sdanielk1977 } 95348bb5d6Sdanielk1977 execsql { 96348bb5d6Sdanielk1977 SELECT count(*) FROM t1 97348bb5d6Sdanielk1977 } 98348bb5d6Sdanielk1977} 10 99348bb5d6Sdanielk1977 1003fe11f30Sdanielk1977# Test that an active transaction remains active and not rolled back 1013fe11f30Sdanielk1977# after the progress query abandons a query. 1023fe11f30Sdanielk1977# 1033fe11f30Sdanielk1977# UPDATE: It is now recognised that this is a sure route to database 1043fe11f30Sdanielk1977# corruption. So the transaction is rolled back. 105b45bb9f1Sdrhdo_test progress-1.3 { 106348bb5d6Sdanielk1977 107348bb5d6Sdanielk1977 db progress 0 "" 108348bb5d6Sdanielk1977 execsql BEGIN 109348bb5d6Sdanielk1977 execsql { 110348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(11) 111348bb5d6Sdanielk1977 } 112348bb5d6Sdanielk1977 db progress 1 "expr 1" 1131d850a72Sdanielk1977 catchsql { 114348bb5d6Sdanielk1977 INSERT INTO t1 VALUES(12) 115348bb5d6Sdanielk1977 } 116348bb5d6Sdanielk1977 db progress 0 "" 1173fe11f30Sdanielk1977 catchsql COMMIT 1183fe11f30Sdanielk1977} {1 {cannot commit - no transaction is active}} 1193fe11f30Sdanielk1977do_test progress-1.3.1 { 120348bb5d6Sdanielk1977 execsql { 121348bb5d6Sdanielk1977 SELECT count(*) FROM t1 122348bb5d6Sdanielk1977 } 1233fe11f30Sdanielk1977} 10 124348bb5d6Sdanielk1977 125348bb5d6Sdanielk1977# Check that a value of 0 for N means no progress callback 126b45bb9f1Sdrhdo_test progress-1.4 { 127348bb5d6Sdanielk1977 set counter 0 128348bb5d6Sdanielk1977 db progress 0 "[namespace code {incr counter}] ; expr 0" 129348bb5d6Sdanielk1977 execsql { 130348bb5d6Sdanielk1977 SELECT * FROM t1; 131348bb5d6Sdanielk1977 } 132348bb5d6Sdanielk1977 set counter 133348bb5d6Sdanielk1977} 0 134348bb5d6Sdanielk1977 135348bb5d6Sdanielk1977db progress 0 "" 136348bb5d6Sdanielk1977 137f8888bb2Sdrh# Make sure other queries can be run from within the progress 138f8888bb2Sdrh# handler. Ticket #1827 139f8888bb2Sdrh# 140f8888bb2Sdrhdo_test progress-1.5 { 141f8888bb2Sdrh set rx 0 142f8888bb2Sdrh proc set_rx {args} { 143f8888bb2Sdrh db progress 0 {} 144f8888bb2Sdrh set ::rx [db eval {SELECT count(*) FROM t1}] 145f8888bb2Sdrh return [expr 0] 146f8888bb2Sdrh } 147f8888bb2Sdrh db progress 10 set_rx 148f8888bb2Sdrh db eval { 149f8888bb2Sdrh SELECT sum(a) FROM t1 150f8888bb2Sdrh } 1513fe11f30Sdanielk1977} {55} 152f8888bb2Sdrhdo_test progress-1.6 { 153f8888bb2Sdrh set ::rx 1543fe11f30Sdanielk1977} {10} 155f8888bb2Sdrh 156de523accSdanielk1977# Check that abandoning a query using the progress handler does 157de523accSdanielk1977# not cause other queries to abort. Ticket #2415. 158de523accSdanielk1977do_test progress-1.7 { 159de523accSdanielk1977 execsql { 160de523accSdanielk1977 CREATE TABLE abc(a, b, c); 161de523accSdanielk1977 INSERT INTO abc VALUES(1, 2, 3); 162de523accSdanielk1977 INSERT INTO abc VALUES(4, 5, 6); 163de523accSdanielk1977 INSERT INTO abc VALUES(7, 8, 9); 164de523accSdanielk1977 } 165de523accSdanielk1977 166de523accSdanielk1977 set ::res [list] 167de523accSdanielk1977 db eval {SELECT a, b, c FROM abc} { 168de523accSdanielk1977 lappend ::res $a $b $c 16949afe3aaSdrh db progress 5 "expr 1" 170de523accSdanielk1977 catch {db eval {SELECT a, b, c FROM abc} { }} msg 171*22c745a9Sdan db progress 5 "expr 0" 172de523accSdanielk1977 lappend ::res $msg 173de523accSdanielk1977 } 174de523accSdanielk1977 175de523accSdanielk1977 set ::res 176de523accSdanielk1977} {1 2 3 interrupted 4 5 6 interrupted 7 8 9 interrupted} 177de523accSdanielk1977 178348bb5d6Sdanielk1977finish_test 179