107cb560bSdanielk1977# 2005 December 30 207cb560bSdanielk1977# 307cb560bSdanielk1977# The author disclaims copyright to this source code. In place of 407cb560bSdanielk1977# a legal notice, here is a blessing: 507cb560bSdanielk1977# 607cb560bSdanielk1977# May you do good and not evil. 707cb560bSdanielk1977# May you find forgiveness for yourself and forgive others. 807cb560bSdanielk1977# May you share freely, never taking more than you give. 907cb560bSdanielk1977# 1007cb560bSdanielk1977#*********************************************************************** 1107cb560bSdanielk1977# 1207cb560bSdanielk1977# The focus of the tests in this file are IO errors that occur in a shared 1307cb560bSdanielk1977# cache context. What happens to connection B if one connection A encounters 1407cb560bSdanielk1977# an IO-error whilst reading or writing the file-system? 1507cb560bSdanielk1977# 16*8d34dfd6Sdanielk1977# $Id: shared_err.test,v 1.9 2006/01/24 16:37:59 danielk1977 Exp $ 1707cb560bSdanielk1977 1807cb560bSdanielk1977proc skip {args} {} 1907cb560bSdanielk1977 2007cb560bSdanielk1977 2107cb560bSdanielk1977set testdir [file dirname $argv0] 2207cb560bSdanielk1977source $testdir/tester.tcl 2307cb560bSdanielk1977db close 2407cb560bSdanielk1977 2507cb560bSdanielk1977ifcapable !shared_cache||!subquery { 2607cb560bSdanielk1977 finish_test 2707cb560bSdanielk1977 return 2807cb560bSdanielk1977} 2907cb560bSdanielk1977set ::enable_shared_cache [sqlite3_enable_shared_cache 1] 3007cb560bSdanielk1977 31c4da5b9fSdanielk1977 32c4da5b9fSdanielk1977# Todo: This is a copy of the [do_malloc_test] proc in malloc.test 33c4da5b9fSdanielk1977# It would be better if these were consolidated. 34c4da5b9fSdanielk1977 35c4da5b9fSdanielk1977# Usage: do_malloc_test <test number> <options...> 36c4da5b9fSdanielk1977# 37c4da5b9fSdanielk1977# The first argument, <test number>, is an integer used to name the 38c4da5b9fSdanielk1977# tests executed by this proc. Options are as follows: 39c4da5b9fSdanielk1977# 40c4da5b9fSdanielk1977# -tclprep TCL script to run to prepare test. 41c4da5b9fSdanielk1977# -sqlprep SQL script to run to prepare test. 42c4da5b9fSdanielk1977# -tclbody TCL script to run with malloc failure simulation. 43c4da5b9fSdanielk1977# -sqlbody TCL script to run with malloc failure simulation. 44c4da5b9fSdanielk1977# -cleanup TCL script to run after the test. 45c4da5b9fSdanielk1977# 46c4da5b9fSdanielk1977# This command runs a series of tests to verify SQLite's ability 47c4da5b9fSdanielk1977# to handle an out-of-memory condition gracefully. It is assumed 48c4da5b9fSdanielk1977# that if this condition occurs a malloc() call will return a 49c4da5b9fSdanielk1977# NULL pointer. Linux, for example, doesn't do that by default. See 50c4da5b9fSdanielk1977# the "BUGS" section of malloc(3). 51c4da5b9fSdanielk1977# 52c4da5b9fSdanielk1977# Each iteration of a loop, the TCL commands in any argument passed 53c4da5b9fSdanielk1977# to the -tclbody switch, followed by the SQL commands in any argument 54c4da5b9fSdanielk1977# passed to the -sqlbody switch are executed. Each iteration the 55c4da5b9fSdanielk1977# Nth call to sqliteMalloc() is made to fail, where N is increased 56c4da5b9fSdanielk1977# each time the loop runs starting from 1. When all commands execute 57c4da5b9fSdanielk1977# successfully, the loop ends. 58c4da5b9fSdanielk1977# 59c4da5b9fSdanielk1977proc do_malloc_test {tn args} { 60c4da5b9fSdanielk1977 array unset ::mallocopts 61c4da5b9fSdanielk1977 array set ::mallocopts $args 62c4da5b9fSdanielk1977 63c4da5b9fSdanielk1977 set ::go 1 64c4da5b9fSdanielk1977 for {set ::n 1} {$::go && $::n < 50000} {incr ::n} { 65c4da5b9fSdanielk1977 do_test shared_malloc-$tn.$::n { 66c4da5b9fSdanielk1977 67c4da5b9fSdanielk1977 # Remove all traces of database files test.db and test2.db from the files 68c4da5b9fSdanielk1977 # system. Then open (empty database) "test.db" with the handle [db]. 69c4da5b9fSdanielk1977 # 70c4da5b9fSdanielk1977 sqlite_malloc_fail 0 71c4da5b9fSdanielk1977 catch {db close} 72c4da5b9fSdanielk1977 catch {file delete -force test.db} 73c4da5b9fSdanielk1977 catch {file delete -force test.db-journal} 74c4da5b9fSdanielk1977 catch {file delete -force test2.db} 75c4da5b9fSdanielk1977 catch {file delete -force test2.db-journal} 76c4da5b9fSdanielk1977 catch {sqlite3 db test.db} 77c4da5b9fSdanielk1977 set ::DB [sqlite3_connection_pointer db] 78c4da5b9fSdanielk1977 79c4da5b9fSdanielk1977 # Execute any -tclprep and -sqlprep scripts. 80c4da5b9fSdanielk1977 # 81c4da5b9fSdanielk1977 if {[info exists ::mallocopts(-tclprep)]} { 82c4da5b9fSdanielk1977 eval $::mallocopts(-tclprep) 83c4da5b9fSdanielk1977 } 84c4da5b9fSdanielk1977 if {[info exists ::mallocopts(-sqlprep)]} { 85c4da5b9fSdanielk1977 execsql $::mallocopts(-sqlprep) 86c4da5b9fSdanielk1977 } 87c4da5b9fSdanielk1977 88c4da5b9fSdanielk1977 # Now set the ${::n}th malloc() to fail and execute the -tclbody and 89c4da5b9fSdanielk1977 # -sqlbody scripts. 90c4da5b9fSdanielk1977 # 91c4da5b9fSdanielk1977 sqlite_malloc_fail $::n 92c4da5b9fSdanielk1977 set ::mallocbody {} 93c4da5b9fSdanielk1977 if {[info exists ::mallocopts(-tclbody)]} { 94c4da5b9fSdanielk1977 append ::mallocbody "$::mallocopts(-tclbody)\n" 95c4da5b9fSdanielk1977 } 96c4da5b9fSdanielk1977 if {[info exists ::mallocopts(-sqlbody)]} { 97c4da5b9fSdanielk1977 append ::mallocbody "db eval {$::mallocopts(-sqlbody)}" 98c4da5b9fSdanielk1977 } 99c4da5b9fSdanielk1977 set v [catch $::mallocbody msg] 100c4da5b9fSdanielk1977 101c4da5b9fSdanielk1977 set leftover [lindex [sqlite_malloc_stat] 2] 102c4da5b9fSdanielk1977 if {$leftover>0} { 103c4da5b9fSdanielk1977 if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} 104c4da5b9fSdanielk1977 set ::go 0 105c4da5b9fSdanielk1977 if {$v} { 106c4da5b9fSdanielk1977 puts "\nError message returned: $msg" 107c4da5b9fSdanielk1977 } else { 108c4da5b9fSdanielk1977 set v {1 1} 109c4da5b9fSdanielk1977 } 110c4da5b9fSdanielk1977 } else { 111c4da5b9fSdanielk1977 set v2 [expr {$msg=="" || $msg=="out of memory"}] 112c4da5b9fSdanielk1977 if {!$v2} {puts "\nError message returned: $msg"} 113c4da5b9fSdanielk1977 lappend v $v2 114c4da5b9fSdanielk1977 } 115c4da5b9fSdanielk1977 } {1 1} 116c4da5b9fSdanielk1977 117c4da5b9fSdanielk1977 sqlite_malloc_fail 0 118c4da5b9fSdanielk1977 if {[info exists ::mallocopts(-cleanup)]} { 119c4da5b9fSdanielk1977 catch [list uplevel #0 $::mallocopts(-cleanup)] msg 120c4da5b9fSdanielk1977 } 121c4da5b9fSdanielk1977 } 122c4da5b9fSdanielk1977 unset ::mallocopts 123c4da5b9fSdanielk1977} 124c4da5b9fSdanielk1977 125c4da5b9fSdanielk1977 12607cb560bSdanielk1977do_ioerr_test shared_ioerr-1 -tclprep { 12707cb560bSdanielk1977 sqlite3 db2 test.db 12807cb560bSdanielk1977 execsql { 12907cb560bSdanielk1977 PRAGMA read_uncommitted = 1; 13007cb560bSdanielk1977 CREATE TABLE t1(a,b,c); 13107cb560bSdanielk1977 BEGIN; 13207cb560bSdanielk1977 SELECT * FROM sqlite_master; 13307cb560bSdanielk1977 } db2 13407cb560bSdanielk1977} -sqlbody { 13507cb560bSdanielk1977 SELECT * FROM sqlite_master; 13607cb560bSdanielk1977 INSERT INTO t1 VALUES(1,2,3); 13707cb560bSdanielk1977 BEGIN TRANSACTION; 13807cb560bSdanielk1977 INSERT INTO t1 VALUES(1,2,3); 13907cb560bSdanielk1977 INSERT INTO t1 VALUES(4,5,6); 14007cb560bSdanielk1977 ROLLBACK; 14107cb560bSdanielk1977 SELECT * FROM t1; 14207cb560bSdanielk1977 BEGIN TRANSACTION; 14307cb560bSdanielk1977 INSERT INTO t1 VALUES(1,2,3); 14407cb560bSdanielk1977 INSERT INTO t1 VALUES(4,5,6); 14507cb560bSdanielk1977 COMMIT; 14607cb560bSdanielk1977 SELECT * FROM t1; 14707cb560bSdanielk1977 DELETE FROM t1 WHERE a<100; 14807cb560bSdanielk1977} -cleanup { 14997a227c9Sdanielk1977 do_test shared_ioerr-1.$n.cleanup.1 { 15007cb560bSdanielk1977 set res [catchsql { 15107cb560bSdanielk1977 SELECT * FROM t1; 15207cb560bSdanielk1977 } db2] 15307cb560bSdanielk1977 set possible_results [list \ 15407cb560bSdanielk1977 "1 {disk I/O error}" \ 15507cb560bSdanielk1977 "0 {1 2 3}" \ 15607cb560bSdanielk1977 "0 {1 2 3 1 2 3 4 5 6}" \ 15707cb560bSdanielk1977 "0 {1 2 3 1 2 3 4 5 6 1 2 3 4 5 6}" \ 15807cb560bSdanielk1977 "0 {}" \ 15907cb560bSdanielk1977 ] 16007cb560bSdanielk1977 set rc [expr [lsearch -exact $possible_results $res] >= 0] 16107cb560bSdanielk1977 if {$rc != 1} { 16207cb560bSdanielk1977 puts "" 16307cb560bSdanielk1977 puts "Result: $res" 16407cb560bSdanielk1977 } 16507cb560bSdanielk1977 set rc 16607cb560bSdanielk1977 } {1} 16707cb560bSdanielk1977 db2 close 16807cb560bSdanielk1977} 16907cb560bSdanielk1977 17007cb560bSdanielk1977do_ioerr_test shared_ioerr-2 -tclprep { 17107cb560bSdanielk1977 sqlite3 db2 test.db 17207cb560bSdanielk1977 execsql { 17307cb560bSdanielk1977 PRAGMA read_uncommitted = 1; 17407cb560bSdanielk1977 BEGIN; 17507cb560bSdanielk1977 CREATE TABLE t1(a, b); 17607cb560bSdanielk1977 INSERT INTO t1(oid) VALUES(NULL); 17707cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 17807cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 17907cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 18007cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 18107cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 18207cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 18307cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 18407cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 18507cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 18607cb560bSdanielk1977 INSERT INTO t1(oid) SELECT NULL FROM t1; 18707cb560bSdanielk1977 UPDATE t1 set a = oid, b = 'abcdefghijklmnopqrstuvwxyz0123456789'; 18807cb560bSdanielk1977 CREATE INDEX i1 ON t1(a); 18907cb560bSdanielk1977 COMMIT; 19007cb560bSdanielk1977 BEGIN; 19107cb560bSdanielk1977 SELECT * FROM sqlite_master; 19207cb560bSdanielk1977 } db2 19307cb560bSdanielk1977} -tclbody { 19407cb560bSdanielk1977 set ::residx 0 19507cb560bSdanielk1977 execsql {DELETE FROM t1 WHERE 0 = (a % 2);} 19607cb560bSdanielk1977 incr ::residx 19707cb560bSdanielk1977 19807cb560bSdanielk1977 # When this transaction begins the table contains 512 entries. The 19907cb560bSdanielk1977 # two statements together add 512+146 more if it succeeds. 20007cb560bSdanielk1977 # (1024/7==146) 20107cb560bSdanielk1977 execsql {BEGIN;} 20207cb560bSdanielk1977 execsql {INSERT INTO t1 SELECT a+1, b FROM t1;} 20307cb560bSdanielk1977 execsql {INSERT INTO t1 SELECT 'string' || a, b FROM t1 WHERE 0 = (a%7);} 20407cb560bSdanielk1977 execsql {COMMIT;} 20507cb560bSdanielk1977 20607cb560bSdanielk1977 incr ::residx 20707cb560bSdanielk1977} -cleanup { 20807cb560bSdanielk1977 do_test shared_ioerr-2.$n.cleanup.1 { 20907cb560bSdanielk1977 set res [catchsql { 21007cb560bSdanielk1977 SELECT max(a), min(a), count(*) FROM (SELECT a FROM t1 order by a); 21107cb560bSdanielk1977 } db2] 21207cb560bSdanielk1977 set possible_results [list \ 21307cb560bSdanielk1977 {0 {1024 1 1024}} \ 21407cb560bSdanielk1977 {0 {1023 1 512}} \ 21507cb560bSdanielk1977 {0 {string994 1 1170}} \ 21607cb560bSdanielk1977 ] 21707cb560bSdanielk1977 set idx [lsearch -exact $possible_results $res] 21807cb560bSdanielk1977 set success [expr {$idx==$::residx || $res=="1 {disk I/O error}"}] 21907cb560bSdanielk1977 if {!$success} { 22007cb560bSdanielk1977 puts "" 22107cb560bSdanielk1977 puts "Result: \"$res\" ($::residx)" 22207cb560bSdanielk1977 } 22307cb560bSdanielk1977 set success 22407cb560bSdanielk1977 } {1} 22507cb560bSdanielk1977 db2 close 22607cb560bSdanielk1977} 22707cb560bSdanielk1977 22897a227c9Sdanielk1977# This test is designed to provoke an IO error when a cursor position is 22997a227c9Sdanielk1977# "saved" (because another cursor is going to modify the underlying table). 23097a227c9Sdanielk1977# 23197a227c9Sdanielk1977do_ioerr_test shared_ioerr-3 -tclprep { 23297a227c9Sdanielk1977 sqlite3 db2 test.db 23397a227c9Sdanielk1977 execsql { 23497a227c9Sdanielk1977 PRAGMA read_uncommitted = 1; 235c4da5b9fSdanielk1977 PRAGMA cache_size = 10; 236c4da5b9fSdanielk1977 BEGIN; 237c4da5b9fSdanielk1977 CREATE TABLE t1(a, b, UNIQUE(a, b)); 238c4da5b9fSdanielk1977 } db2 239c4da5b9fSdanielk1977 for {set i 0} {$i < 200} {incr i} { 240c4da5b9fSdanielk1977 set a [string range [string repeat "[format %03d $i]." 5] 0 end-1] 241c4da5b9fSdanielk1977 242c4da5b9fSdanielk1977 set b [string repeat $i 2000] 243c4da5b9fSdanielk1977 execsql {INSERT INTO t1 VALUES($a, $b)} db2 244c4da5b9fSdanielk1977 } 245c4da5b9fSdanielk1977 execsql {COMMIT} db2 246c4da5b9fSdanielk1977 set ::DB2 [sqlite3_connection_pointer db2] 247c4da5b9fSdanielk1977 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] 248c4da5b9fSdanielk1977 sqlite3_step $::STMT ;# Cursor points at 000.000.000.000 249c4da5b9fSdanielk1977 sqlite3_step $::STMT ;# Cursor points at 001.001.001.001 250c4da5b9fSdanielk1977 251c4da5b9fSdanielk1977} -tclbody { 252c4da5b9fSdanielk1977 execsql { 25375bab7d6Sdanielk1977 BEGIN; 254c4da5b9fSdanielk1977 INSERT INTO t1 VALUES('201.201.201.201.201', NULL); 25575bab7d6Sdanielk1977 UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%'; 25675bab7d6Sdanielk1977 COMMIT; 257c4da5b9fSdanielk1977 } 258c4da5b9fSdanielk1977} -cleanup { 259c4da5b9fSdanielk1977 do_test shared_ioerr-3.$n.cleanup.1 { 260c4da5b9fSdanielk1977 sqlite3_step $::STMT 261c4da5b9fSdanielk1977 } {SQLITE_ROW} 262c4da5b9fSdanielk1977 do_test shared_ioerr-3.$n.cleanup.2 { 263c4da5b9fSdanielk1977 sqlite3_column_text $::STMT 0 264c4da5b9fSdanielk1977 } {002.002.002.002.002} 265c4da5b9fSdanielk1977 do_test shared_ioerr-3.$n.cleanup.3 { 266c4da5b9fSdanielk1977 sqlite3_finalize $::STMT 267c4da5b9fSdanielk1977 } {SQLITE_OK} 268c4da5b9fSdanielk1977# db2 eval {select * from sqlite_master} 269c4da5b9fSdanielk1977 db2 close 270c4da5b9fSdanielk1977} 271c4da5b9fSdanielk1977 2727b3822b3Sdrh# Only run these tests if memory debugging is turned on. 2737b3822b3Sdrh# 2747b3822b3Sdrhif {[info command sqlite_malloc_stat]==""} { 2757b3822b3Sdrh puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." 27680d56827Sdrh db close 27780d56827Sdrh sqlite3_enable_shared_cache $::enable_shared_cache 2787b3822b3Sdrh finish_test 2797b3822b3Sdrh return 2807b3822b3Sdrh} 2817b3822b3Sdrh 282c4da5b9fSdanielk1977# Provoke a malloc() failure when a cursor position is being saved. This 283c4da5b9fSdanielk1977# only happens with index cursors (because they malloc() space to save the 284c4da5b9fSdanielk1977# current key value). It does not happen with tables, because an integer 285c4da5b9fSdanielk1977# key does not require a malloc() to store. 286c4da5b9fSdanielk1977# 287c4da5b9fSdanielk1977# The library should return an SQLITE_NOMEM to the caller. The query that 288c4da5b9fSdanielk1977# owns the cursor (the one for which the position is not saved) should 289c4da5b9fSdanielk1977# continue unaffected. 290c4da5b9fSdanielk1977# 291c4da5b9fSdanielk1977do_malloc_test 4 -tclprep { 292c4da5b9fSdanielk1977 sqlite3 db2 test.db 293c4da5b9fSdanielk1977 execsql { 294c4da5b9fSdanielk1977 PRAGMA read_uncommitted = 1; 29597a227c9Sdanielk1977 BEGIN; 29697a227c9Sdanielk1977 CREATE TABLE t1(a, b, UNIQUE(a, b)); 29797a227c9Sdanielk1977 } db2 29897a227c9Sdanielk1977 for {set i 0} {$i < 5} {incr i} { 29997a227c9Sdanielk1977 set a [string repeat $i 10] 30097a227c9Sdanielk1977 set b [string repeat $i 2000] 30197a227c9Sdanielk1977 execsql {INSERT INTO t1 VALUES($a, $b)} db2 30297a227c9Sdanielk1977 } 30397a227c9Sdanielk1977 execsql {COMMIT} db2 30497a227c9Sdanielk1977 set ::DB2 [sqlite3_connection_pointer db2] 30597a227c9Sdanielk1977 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] 30697a227c9Sdanielk1977 sqlite3_step $::STMT ;# Cursor points at 0000000000 30797a227c9Sdanielk1977 sqlite3_step $::STMT ;# Cursor points at 1111111111 30897a227c9Sdanielk1977} -tclbody { 30997a227c9Sdanielk1977 execsql { 31097a227c9Sdanielk1977 INSERT INTO t1 VALUES(6, NULL); 31197a227c9Sdanielk1977 } 31297a227c9Sdanielk1977} -cleanup { 313c4da5b9fSdanielk1977 do_test shared_malloc-4.$::n.cleanup.1 { 314*8d34dfd6Sdanielk1977 set ::rc [sqlite3_step $::STMT] 315*8d34dfd6Sdanielk1977 expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ABORT"} 316*8d34dfd6Sdanielk1977 } {1} 317*8d34dfd6Sdanielk1977 if {$::rc=="SQLITE_ROW"} { 318c4da5b9fSdanielk1977 do_test shared_malloc-4.$::n.cleanup.2 { 31997a227c9Sdanielk1977 sqlite3_column_text $::STMT 0 32097a227c9Sdanielk1977 } {2222222222} 321*8d34dfd6Sdanielk1977 } 322c4da5b9fSdanielk1977 do_test shared_malloc-4.$::n.cleanup.3 { 32397a227c9Sdanielk1977 sqlite3_finalize $::STMT 32497a227c9Sdanielk1977 } {SQLITE_OK} 32597a227c9Sdanielk1977# db2 eval {select * from sqlite_master} 32697a227c9Sdanielk1977 db2 close 32797a227c9Sdanielk1977} 32897a227c9Sdanielk1977 3294b202ae2Sdanielk1977do_malloc_test 5 -tclbody { 3304b202ae2Sdanielk1977 sqlite3 dbX test.db 3314b202ae2Sdanielk1977 sqlite3 dbY test.db 3324b202ae2Sdanielk1977 dbX close 3334b202ae2Sdanielk1977 dbY close 3344b202ae2Sdanielk1977} -cleanup { 3354b202ae2Sdanielk1977 catch {dbX close} 3364b202ae2Sdanielk1977 catch {dbY close} 3374b202ae2Sdanielk1977} 3384b202ae2Sdanielk1977 3397246f5b9Sdanielk1977do_malloc_test 6 -tclbody { 3407246f5b9Sdanielk1977 catch {db close} 3417246f5b9Sdanielk1977 sqlite3_thread_cleanup 3427246f5b9Sdanielk1977 sqlite3_enable_shared_cache 0 3437246f5b9Sdanielk1977} -cleanup { 3447246f5b9Sdanielk1977 sqlite3_enable_shared_cache 1 3457246f5b9Sdanielk1977} 3467246f5b9Sdanielk1977 3477246f5b9Sdanielk1977do_test shared_misuse-7.1 { 3487246f5b9Sdanielk1977 sqlite3 db test.db 3497246f5b9Sdanielk1977 catch { 3507246f5b9Sdanielk1977 sqlite3_enable_shared_cache 0 3517246f5b9Sdanielk1977 } msg 3527246f5b9Sdanielk1977 set msg 3537246f5b9Sdanielk1977} {library routine called out of sequence} 3547246f5b9Sdanielk1977 355*8d34dfd6Sdanielk1977# Again provoke a malloc() failure when a cursor position is being saved, 356*8d34dfd6Sdanielk1977# this time during a ROLLBACK operation by some other handle. 357*8d34dfd6Sdanielk1977# 358*8d34dfd6Sdanielk1977# The library should return an SQLITE_NOMEM to the caller. The query that 359*8d34dfd6Sdanielk1977# owns the cursor (the one for which the position is not saved) should 360*8d34dfd6Sdanielk1977# be aborted. 361*8d34dfd6Sdanielk1977# 362*8d34dfd6Sdanielk1977set ::aborted 0 363*8d34dfd6Sdanielk1977do_malloc_test 8 -tclprep { 364*8d34dfd6Sdanielk1977 sqlite3 db2 test.db 365*8d34dfd6Sdanielk1977 execsql { 366*8d34dfd6Sdanielk1977 PRAGMA read_uncommitted = 1; 367*8d34dfd6Sdanielk1977 BEGIN; 368*8d34dfd6Sdanielk1977 CREATE TABLE t1(a, b, UNIQUE(a, b)); 369*8d34dfd6Sdanielk1977 } db2 370*8d34dfd6Sdanielk1977 for {set i 0} {$i < 2} {incr i} { 371*8d34dfd6Sdanielk1977 set a [string repeat $i 10] 372*8d34dfd6Sdanielk1977 set b [string repeat $i 2000] 373*8d34dfd6Sdanielk1977 execsql {INSERT INTO t1 VALUES($a, $b)} db2 374*8d34dfd6Sdanielk1977 } 375*8d34dfd6Sdanielk1977 execsql {COMMIT} db2 376*8d34dfd6Sdanielk1977 set ::DB2 [sqlite3_connection_pointer db2] 377*8d34dfd6Sdanielk1977 set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] 378*8d34dfd6Sdanielk1977 sqlite3_step $::STMT ;# Cursor points at 0000000000 379*8d34dfd6Sdanielk1977 sqlite3_step $::STMT ;# Cursor points at 1111111111 380*8d34dfd6Sdanielk1977} -tclbody { 381*8d34dfd6Sdanielk1977 execsql { 382*8d34dfd6Sdanielk1977 BEGIN; 383*8d34dfd6Sdanielk1977 INSERT INTO t1 VALUES(6, NULL); 384*8d34dfd6Sdanielk1977 ROLLBACK; 385*8d34dfd6Sdanielk1977 } 386*8d34dfd6Sdanielk1977} -cleanup { 387*8d34dfd6Sdanielk1977 do_test shared_malloc-8.$::n.cleanup.1 { 388*8d34dfd6Sdanielk1977 lrange [execsql { 389*8d34dfd6Sdanielk1977 SELECT a FROM t1; 390*8d34dfd6Sdanielk1977 } db2] 0 1 391*8d34dfd6Sdanielk1977 } {0000000000 1111111111} 392*8d34dfd6Sdanielk1977 do_test shared_malloc-8.$::n.cleanup.2 { 393*8d34dfd6Sdanielk1977 set rc1 [sqlite3_step $::STMT] 394*8d34dfd6Sdanielk1977 set rc2 [sqlite3_finalize $::STMT] 395*8d34dfd6Sdanielk1977 if {$rc1=="SQLITE_ABORT"} { 396*8d34dfd6Sdanielk1977 incr ::aborted 397*8d34dfd6Sdanielk1977 } 398*8d34dfd6Sdanielk1977 expr { 399*8d34dfd6Sdanielk1977 ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") || 400*8d34dfd6Sdanielk1977 ($rc1=="SQLITE_ABORT" && $rc2=="SQLITE_OK") 401*8d34dfd6Sdanielk1977 } 402*8d34dfd6Sdanielk1977 } {1} 403*8d34dfd6Sdanielk1977 db2 close 404*8d34dfd6Sdanielk1977} 405*8d34dfd6Sdanielk1977do_test shared_malloc-8.X { 406*8d34dfd6Sdanielk1977 # Test that one or more queries were aborted due to the malloc() failure. 407*8d34dfd6Sdanielk1977 expr $::aborted>=1 408*8d34dfd6Sdanielk1977} {1} 409*8d34dfd6Sdanielk1977 41007cb560bSdanielk1977catch {db close} 41107cb560bSdanielk1977sqlite3_enable_shared_cache $::enable_shared_cache 41207cb560bSdanielk1977finish_test 413