180231042Sdan# 2014 November 12 280231042Sdan# 380231042Sdan# The author disclaims copyright to this source code. In place of 480231042Sdan# a legal notice, here is a blessing: 580231042Sdan# 680231042Sdan# May you do good and not evil. 780231042Sdan# May you find forgiveness for yourself and forgive others. 880231042Sdan# May you share freely, never taking more than you give. 980231042Sdan# 1080231042Sdan#*********************************************************************** 1180231042Sdan# 12d7b06909Sdan# This file containst tests to verify that ROLLBACK or ROLLBACK TO 13d7b06909Sdan# operations interact correctly with ongoing SELECT statements. 14d7b06909Sdan# 1580231042Sdan 1680231042Sdanset testdir [file dirname $argv0] 1780231042Sdansource $testdir/tester.tcl 1880231042Sdanset ::testprefix rollback2 1980231042Sdan 2080231042Sdanproc int2hex {i} { format %.2X $i } 2180231042Sdandb func int2hex int2hex 2280231042Sdando_execsql_test 1.0 { 2380231042Sdan SELECT int2hex(0), int2hex(100), int2hex(255) 2480231042Sdan} {00 64 FF} 2580231042Sdando_execsql_test 1.1 { 2680231042Sdan CREATE TABLE t1(i, h); 2780231042Sdan CREATE INDEX i1 ON t1(h); 2880231042Sdan WITH data(a, b) AS ( 2980231042Sdan SELECT 1, int2hex(1) 3080231042Sdan UNION ALL 3180231042Sdan SELECT a+1, int2hex(a+1) FROM data WHERE a<40 3280231042Sdan ) 3380231042Sdan INSERT INTO t1 SELECT * FROM data; 3480231042Sdan} {} 3580231042Sdan 3680231042Sdan 37d7b06909Sdan# do_rollback_test ID SWITCHES 38d7b06909Sdan# 39d7b06909Sdan# where SWITCHES are: 40d7b06909Sdan# 41d7b06909Sdan# -setup SQL script to open transaction and begin writing. 42d7b06909Sdan# -select SELECT to execute after -setup script 43d7b06909Sdan# -result Expected result of -select statement 44d7b06909Sdan# -rollback Use this SQL command ("ROLLBACK" or "ROLLBACK TO ...") to 45d7b06909Sdan# rollback the transaction in the middle of the -select statment 46d7b06909Sdan# execution. 47d7b06909Sdan# 4880231042Sdanproc do_rollback_test {tn args} { 4980231042Sdan set A(-setup) "" 5080231042Sdan set A(-select) "" 5180231042Sdan set A(-result) "" 5280231042Sdan set A(-rollback) ROLLBACK 5380231042Sdan 5480231042Sdan array set O $args 5580231042Sdan foreach k [array names O] { 5680231042Sdan if {[info exists A($k)]==0} { error "unknown option: $k" } 5780231042Sdan set A($k) $O($k) 5880231042Sdan } 5980231042Sdan 6080231042Sdan for {set iRollback 0} 1 {incr iRollback} { 6180231042Sdan catch { db eval ROLLBACK } 6280231042Sdan set res [list] 6380231042Sdan db eval $A(-setup) 6480231042Sdan 6580231042Sdan set i 0 6680231042Sdan db eval $A(-select) x { 6780231042Sdan if {$i==$iRollback} { db eval $A(-rollback) } 6880231042Sdan foreach k $x(*) { lappend res $x($k) } 6980231042Sdan incr i 7080231042Sdan } 7180231042Sdan 7280231042Sdan do_test $tn.$iRollback [list set {} $res] [list {*}$A(-result)] 7380231042Sdan if {$i < $iRollback} break 7480231042Sdan } 7580231042Sdan} 7680231042Sdan 77d7b06909Sdando_rollback_test 2.1 -setup { 7880231042Sdan BEGIN; 7980231042Sdan DELETE FROM t1 WHERE (i%2)==1; 8080231042Sdan} -select { 8180231042Sdan SELECT i FROM t1 WHERE (i%2)==0 8280231042Sdan} -result { 8380231042Sdan 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 8480231042Sdan} 8580231042Sdan 86d7b06909Sdando_rollback_test 2.2 -setup { 87d7b06909Sdan BEGIN; 88d7b06909Sdan DELETE FROM t1 WHERE (i%4)==1; 89d7b06909Sdan SAVEPOINT one; 90d7b06909Sdan DELETE FROM t1 WHERE (i%2)==1; 91d7b06909Sdan} -rollback { 92d7b06909Sdan ROLLBACK TO one; 93d7b06909Sdan} -select { 94d7b06909Sdan SELECT i FROM t1 WHERE (i%2)==0 95d7b06909Sdan} -result { 96d7b06909Sdan 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 97d7b06909Sdan} 98d7b06909Sdan 99d7b06909Sdan#-------------------------------------------------------------------- 100d7b06909Sdan# Try with some index scans 101d7b06909Sdan# 102d7b06909Sdando_eqp_test 3.1 { 103d7b06909Sdan SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC; 104*8210233cSdrh} {SCAN t1 USING INDEX i1} 105d7b06909Sdando_rollback_test 3.2 -setup { 106d7b06909Sdan BEGIN; 107d7b06909Sdan DELETE FROM t1 WHERE (i%2)==1; 108d7b06909Sdan} -select { 109d7b06909Sdan SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC; 110d7b06909Sdan} -result { 111d7b06909Sdan 40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2 112d7b06909Sdan} 113d7b06909Sdando_rollback_test 3.3 -setup { 114d7b06909Sdan BEGIN; 115d7b06909Sdan DELETE FROM t1 WHERE (i%4)==1; 116d7b06909Sdan SAVEPOINT one; 117d7b06909Sdan DELETE FROM t1 WHERE (i%2)==1; 118d7b06909Sdan} -rollback { 119d7b06909Sdan ROLLBACK TO one; 120d7b06909Sdan} -select { 121d7b06909Sdan SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC; 122d7b06909Sdan} -result { 123d7b06909Sdan 40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2 124d7b06909Sdan} 125d7b06909Sdan 126d7b06909Sdan#-------------------------------------------------------------------- 127d7b06909Sdan# Now with some index scans that feature overflow keys. 128d7b06909Sdan# 129d7b06909Sdanset leader [string repeat "abcdefghij" 70] 130d7b06909Sdando_execsql_test 4.1 { UPDATE t1 SET h = $leader || h; } 131d7b06909Sdan 132d7b06909Sdando_eqp_test 4.2 { 133d7b06909Sdan SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC; 134*8210233cSdrh} {SCAN t1 USING INDEX i1} 135d7b06909Sdando_rollback_test 4.3 -setup { 136d7b06909Sdan BEGIN; 137d7b06909Sdan DELETE FROM t1 WHERE (i%2)==1; 138d7b06909Sdan} -select { 139d7b06909Sdan SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC; 140d7b06909Sdan} -result { 141d7b06909Sdan 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 142d7b06909Sdan} 143d7b06909Sdando_rollback_test 4.4 -setup { 144d7b06909Sdan BEGIN; 145d7b06909Sdan DELETE FROM t1 WHERE (i%4)==1; 146d7b06909Sdan SAVEPOINT one; 147d7b06909Sdan DELETE FROM t1 WHERE (i%2)==1; 148d7b06909Sdan} -rollback { 149d7b06909Sdan ROLLBACK TO one; 150d7b06909Sdan} -select { 151d7b06909Sdan SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC; 152d7b06909Sdan} -result { 153d7b06909Sdan 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 154d7b06909Sdan} 155d7b06909Sdan 15680231042Sdanfinish_test 157