Back out changes allowing writes to tables that have open cursors. (CVS 2134)

FossilOrigin-Name: af635cab8a1d761c469e35208dda08a29f0964a1
This commit is contained in:
danielk1977 2004-11-22 10:02:21 +00:00
parent 299b187d76
commit 12b13002ce
9 changed files with 96 additions and 591 deletions

View File

@ -1,5 +1,5 @@
C Back\sout\schanges\sallowing\swrites\sto\stables\sthat\shave\sopen\scursors.\s(CVS\s2133)
D 2004-11-22T10:02:10
C Back\sout\schanges\sallowing\swrites\sto\stables\sthat\shave\sopen\scursors.\s(CVS\s2134)
D 2004-11-22T10:02:22
F Makefile.in 8291610f5839939a5fbff4dbbf85adb0fe1ac37f
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@ -101,9 +101,8 @@ F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4
F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2
F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027
F test/btree7.test a6d3b842db22af97dd14b989e90a2fd96066b72f
F test/btree8.test d4e5932e54ae10f934d92ebaff94b594923d9ebc
F test/capi2.test cd5e149564094bda9a587e70ec5949863222cd23
F test/capi3.test c53e4eea686dacad8a1239c0d584fe63e6e601dc
F test/capi2.test 8279d1d5ca1f9b518d78fefd01fd58958c7240d6
F test/capi3.test 3b33bf7c8836028835354c055989314e9c969c5c
F test/capi3b.test 5b6a66f9f295f79f443b5d3f33187fa5ef6cf336
F test/collate1.test f79736d2ebf5492167ee4d1f4ab4c09dda776b03
F test/collate2.test 12fd658d8f5106a8a5c8a77d66919d8c89394036
@ -117,7 +116,7 @@ F test/crash.test 48b481769dd0ead25b0dfc0150853bfa39a3b65c
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/date.test dda578ec1857837156bd8b32f8e09d81d7d7881c
F test/delete.test fc29491f6a7ac899ce29f4549a104809e245d9a6
F test/delete2.test 04a19e248d88156324ae964676bb4584b65b46f4
F test/delete2.test e382b6a97787197eb8b93dd4ccd37797c3725ea3
F test/diskfull.test e2f6cfd868713ead06dc82b84a4938e868128fc0
F test/enc.test 7a03417a1051fe8bc6c7641cf4c8c3f7e0066d52
F test/enc2.test 6d1a2650e9da43eab499d18ca694a0cb6ec69dee
@ -140,17 +139,16 @@ F test/join4.test 8dec387d06b3a4685e1104048065cf5236b99b93
F test/lastinsert.test b6a1db3e1ce2d3f0d6afe99d445084f543b6feaa
F test/laststmtchanges.test 07cbdabc52407c29e40abc25050f2434f044a6b1
F test/limit.test 4798e0196186e4c9b0f3ce90c1efd196877a1d17
F test/lock.test ba72c211499b0874c56643b9ede1df4018bb20de
F test/lock.test 32fe28e5030f25f23bcf6beef440675b0d848413
F test/lock2.test 59c3dd7d9b24d1bf7ec91b2d1541c37e97939d5f
F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9
F test/lock4.test 07768b4d4e942693d6036f1e6502199a3fa22a4f
F test/main.test 5f9deae11b93336da1ccc5f91cf8be075c91ddf1
F test/malloc.test b4674cbb5a72b113eedaaf64fcd5c062e9957ded
F test/memdb.test c9ccd02cd9ce9d2cdcd5a712efecf24e7b93b7fa
F test/memleak.test f1fa233f8295dd1d955a00d5e5ee857850f27f29
F test/minmax.test c0f92d3f7b11656221735385f2c8b1878bbbdaf6
F test/misc1.test 744f60d1025fa978708b96cb222a07a1feb1524a
F test/misc2.test 851e63fcc849b0c155cb02eb06537ea93b7f24b2
F test/misc2.test d3bea4b809efaa4319299e55c50ee987b4f6470c
F test/misc3.test 928a2f1e1189924ed14e1ae074e34f40688bdf94
F test/misc4.test d005a75f095bb04db09a5d096144405ae566b622
F test/misuse.test 2d7c46160f7c214f761fc5d030684a37ae8832a6
@ -261,7 +259,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
P 711e8d7695dfc74b3f1ee00591dcdda2cd7fc7d5
R 435be4c4df18ad02a5220daa06c920af
P 91acd87e52509a8f78894d0f4b625b54376cac21
R 3f35736f01d9cae236fc378ee100c137
U danielk1977
Z 690d6154f35eb3573c00acd3211a6213
Z 78e9f3a6a9971c738e9a8b2edd14f6b6

View File

@ -1 +1 @@
91acd87e52509a8f78894d0f4b625b54376cac21
af635cab8a1d761c469e35208dda08a29f0964a1

View File

@ -1,413 +0,0 @@
# 2004 Jun 4
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is btree database backend. Specifically,
# this file tests that existing cursors are correctly repositioned
# when entries are inserted into or deleted from btrees.
#
# $Id: btree8.test,v 1.4 2004/11/17 10:22:04 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Test organization:
#
# btree-8.1.*: Test cursor persistence when inserting records into tables.
# btree-8.2.*: Test cursor persistence when deleting records from tables.
# btree-8.3.*: Test cursor persistence when inserting records into indices.
# btree-8.4.*: Test cursor persistence when deleting records from indices.
#
# Transform the number $num into a string of length $len by repeating the
# string representation of the number as many times as necessary. Repeats
# are seperated by a '.' character. Eg:
#
# [num_to_string 456 10] -> "456.456.45"
#
proc num_to_string {num len} {
set num [format %.4d $num]
return [string range [string repeat "$num." $len] 0 [expr $len-1]]
}
# Proc lshuffle takes a list as an argument and returns a copy of that
# list in randomized order. It uses the K-combinator for speed.
#
proc K {x y} {set x}
proc lshuffle { list } {
set n [llength $list]
while {$n>0} {
set j [expr {int(rand()*$n)}]
lappend slist [lindex $list $j]
set list [lreplace [K $list [set list {}]] $j $j]
incr n -1
}
return $slist
}
# Proc lremove takes two arguments, a list (the first argument) and a key
# (the second argument). A copy of the list is returned with all elements
# equal to $key removed.
#
proc lremove {list key} {
while { [set i [lsearch $list $key]] != -1 } {
set list [concat \
[lrange $list 0 [expr $i-1]] \
[lrange $list [expr $i+1] end]
]
}
return $list
}
# Use the SQL interface to create a couple of btree tables, one using
# the flags for an SQL table, the other an SQL index.
#
do_test btree8-0.0 {
execsql {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE INDEX i1 ON t1(b);
}
} {}
set tnum [execsql {SELECT rootpage FROM sqlite_master where type = 'table'}]
set inum [execsql {SELECT rootpage FROM sqlite_master where type = 'index'}]
db close
#-------------------------------------------------------------------------
# Tests btree8-1.* insert a handful of records (~10) into the type of
# b-tree created for an SQL table. The records have integer keys in the
# range 1..5000. A cursor is left pointing to each of these records.
# Then, a record is inserted for each key value between 1 and 5000,
# including the values for which a record already exists (overwriting
# the original). After each record is inserted, the existing cursors
# are checked to ensure they still point at the same key-value.
#
# Open the database at the btree level and begin a transaction
do_test btree8-1.0 {
set ::bt [btree_open test.db 100 0]
expr 0
} {0}
do_test btree8-1.1 {
btree_begin_transaction $::bt
expr 0
} {0}
# For each element in the list $keys, insert an entry into the SQL table
# with the corresponding key value. Check that the cursor used to insert
# the key is left pointing to it after the insert. Then save this cursor
# in the list $csr_list.
#
set keys [list 3178 4886 719 1690 443 4113 1618 310 1320 2028]
set csr_list [list]
set testnum 2
foreach key $keys {
do_test btree-8-1.$testnum {
set csr [btree_cursor $::bt $::tnum 1]
btree_insert $csr $key [string repeat a 10]
lappend csr_list $csr
btree_key $csr
} $key
incr testnum
}
btree_commit $::bt
# Now write more entries to the table (and overwriting the ones that exist).
# After each write, check that the cursors created above still point to the
# same entries.
btree_begin_transaction $::bt
set ::write_csr [btree_cursor $::bt $::tnum 1]
set first_entry $testnum
for {set i $testnum} {$i < 5000 && $nErr==0 } {incr i} {
set datalen [expr int(rand()*20.0)]
do_test btree8-1.$i.1 {
btree_insert $::write_csr $i [string repeat x $datalen]
} {}
set testnum 1
foreach csr $csr_list key $keys {
incr testnum
do_test btree8-1.$i.$testnum {
btree_key $::csr
} $key
}
}
#-------------------------------------------------------------------------
# Tests btree8-2.* loop through the tree created by tests btree8-1.*,
# deleting records in sequential order. After each record is deleted,
# each of the open cursors is checked to ensure that it still points
# to the same key-value or, if that key value has been deleted, returns
# 0 as the integer key value.
#
# Now delete entries from the table.
btree_first $::write_csr
for {set i $first_entry} {$i < 5000 && $nErr==0 } {incr i} {
do_test btree8-2.$i.1 {
btree_key $::write_csr
} $i
do_test btree8-2.$i.2 {
btree_delete $::write_csr
btree_next $::write_csr
expr 0
} {0}
set testnum 2
foreach csr $csr_list key $keys {
incr testnum
if {$key <= $i } {
set key 0
}
do_test btree8-2.$i.$testnum {
btree_key $::csr
} $key
}
}
# Close all existing cursors and conclude the open transaction.
btree_close_cursor $::write_csr
btree_commit $::bt
if {$::nErr>0} { puts $::csr_list ; exit }
foreach csr $csr_list {
btree_close_cursor $csr
}
set csr_list [list]
#-------------------------------------------------------------------------
# Tests btree8-3.* are analogous to btree8-1.*, but use the type of btree
# created for an SQL index, not an SQL table. Instead of integers, key
# values are strings 20 bytes long created by transforming integers
# into string using the [num_to_string] proc (see above).
#
foreach key $keys {
lappend skeys [num_to_string $key 20]
}
# For each element in the list $skeys, insert an entry into the SQL index
# with the corresponding key value. Check that the cursor used to insert
# the key is left pointing to it after the insert. Then save this cursor
# in the list $csr_list.
#
btree_begin_transaction $::bt
set testnum 0
foreach key $skeys {
incr testnum
do_test btree-8-3.$testnum {
set csr [btree_cursor $::bt $::inum 1]
btree_insert $csr $key ""
lappend csr_list $csr
btree_key $csr
} $key
}
btree_commit $::bt
# Now write more entries to the index (and overwrite the ones that exist).
# After each write, check that the cursors created above still point to the
# same entries.
btree_begin_transaction $::bt
set ::write_csr [btree_cursor $::bt $::inum 1]
set first_entry $testnum
for {set i $testnum} {$i < 5000 && $nErr==0 } {incr i} {
set skey [num_to_string $i 20]
do_test btree-8-3.$i.1 {
btree_insert $::write_csr $skey ""
} {}
set testnum 1
foreach csr $csr_list key $skeys {
incr testnum
do_test btree-8-3.$i.$testnum {
btree_key $::csr
} $key
}
}
btree_commit $::bt
btree_begin_transaction $::bt
#-------------------------------------------------------------------------
# Tests btree8-4.* are analogous to btree8-2.*, but use the type of btree
# created for an SQL index, not an SQL table. Instead of integers, key
# values are strings 20 bytes long created by transforming integers
# into string using the [num_to_string] proc (see above). Also, keys
# are deleted in random order, calculated by the [lshuffle] proc (see above).
#
# Now delete entries from the index. Do this in a random order, to try to
# ensure that internal and external nodes are deleted.
for {set i $first_entry} {$i < 5000} {incr i} {
lappend delete_order $i
}
set delete_order [lshuffle $delete_order]
btree_first $::write_csr
foreach i $delete_order {
do_test btree8-4.$i.1 {
btree_move_to $::write_csr [num_to_string $i 20]
btree_key $::write_csr
} [num_to_string $i 20]
do_test btree8-4.$i.2 {
btree_delete $::write_csr
} {}
set delete_order [lremove $delete_order $i]
set testnum 2
foreach csr $csr_list key $keys {
incr testnum
if { [lsearch $delete_order $key]==-1 } {
set skey ""
} else {
set skey [num_to_string $key 20]
}
do_test btree8-4.$i.$testnum {
btree_key $::csr
} $skey
}
}
btree_close_cursor $::write_csr
btree_commit $::bt
if {$::nErr>0} { puts $::csr_list }
foreach csr $csr_list {
btree_close_cursor $csr
}
set csr_list [list]
#------------------------------------------------------------------------
# Tests btree8.5.* also test the types of trees used for SQL indices.
# This time, 300 entries of 150 bytes each are inserted into the btree (this
# produces a tree of height 3 - root page is the grandparent of the leaves).
# A cursor points at each entry. We check that all cursors retain there
# validity when:
#
# * Each entry is deleted (test cases btree-8.5.1.*)
# * An entry is inserted just after/before each existing key (test
# cases btree-8.5.2.*).
#
# Open a cursor on each entry in the tree in B-tree $bt, root-page $tnum.
# Return a list of the cursors.
#
proc open_cursors {bt tnum} {
set c [btree_cursor $bt $tnum 0]
set csr_list [list]
for {btree_first $c} {![btree_eof $c]} {btree_next $c} {
set c2 [btree_cursor $bt $tnum 0]
btree_move_to $c2 [btree_key $c]
lappend csr_list $c2
}
btree_close_cursor $c
return $csr_list
}
# Close all cursors in the list $csr_list.
#
proc close_cursors {csr_list} {
foreach c $csr_list {
btree_close_cursor $c
}
}
# Check that the key for each cursor in csr_list matches the corresponding
# entry in key_list. If not, raise an exception.
#
proc check_cursors {key_list csr_list} {
foreach k $key_list c $csr_list {
if {[string compare $k [btree_key $c]]} {
error "Csr key '[btree_key $c]' - should be '$k'"
}
}
}
# Set up the table used for the btree-8.5.* tests
do_test btree-8.5.0 {
btree_begin_transaction $::bt
set c [btree_cursor $::bt $::inum 1]
for {set i 2} {$i<=600} {incr i 2} {
set key [num_to_string $i 150]
lappend key_list $key
btree_insert $c $key ""
}
btree_close_cursor $c
btree_commit $::bt
} {}
# Test cases btree-8.5.1.* - Check that cursors survive DELETE operations.
set testnum 0
foreach key [lrange $::key_list 0 0] {
incr testnum
btree_begin_transaction $::bt
# Open the 300 cursors.
do_test btree-8.5.1.$testnum.1 {
set ::csr_list [open_cursors $::bt $::inum]
llength $::csr_list
} {300}
# Delete an entry.
do_test btree-8.5.1.$testnum.2 {
set c [btree_cursor $::bt $::inum 1]
btree_move_to $c $::key
btree_delete $c
btree_close_cursor $c
} {}
# Check that all 300 cursors are Ok.
do_test btree-8.5.1.$testnum.3 {
catch {
set e [lsearch $::key_list $::key]
check_cursors [lreplace $::key_list $e $e ""] $::csr_list
} msg
set msg
} {}
close_cursors $::csr_list
btree_rollback $::bt
}
# Test cases btree-8.5.2.* - Check that cursors survive INSERT operations.
set testnum 0
foreach key $::key_list {
incr testnum
btree_begin_transaction $::bt
# Open the 300 cursors.
do_test btree-8.5.2.$testnum.1 {
set ::csr_list [open_cursors $::bt $::inum]
llength $::csr_list
} {300}
# Insert new entries, one before the key, and one after.
do_test btree-8.5.2.$testnum.2 {
set c [btree_cursor $::bt $::inum 1]
btree_insert $c "$::key$::key" ""
btree_insert $c [string range $::key 0 end-1] ""
btree_close_cursor $c
} {}
# Check that all 300 cursors are Ok.
do_test btree-8.5.2.$testnum.3 {
catch {
check_cursors $::key_list $::csr_list
} msg
set msg
} {}
close_cursors $::csr_list
btree_rollback $::bt
}
finish_test

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script testing the callback-free C/C++ API.
#
# $Id: capi2.test,v 1.21 2004/11/16 15:50:21 danielk1977 Exp $
# $Id: capi2.test,v 1.22 2004/11/22 10:02:22 danielk1977 Exp $
#
set testdir [file dirname $argv0]
@ -451,21 +451,15 @@ do_test capi2-6.12 {
[get_column_names $VM1]
} {SQLITE_ROW 1 5 {x counter}}
# The next test used to report that the database was locked.
# As of 3.1 this is no longer the case, the UPDATE works
# even though there is a SELECT active on the table. Rows
# scanned by subsequent calls to sqlite3_step report the
# updated values.
#
do_test capi2-6.13 {
catchsql {UPDATE t3 SET x=x+1}
} {0 {}}
} {1 {database table is locked}}
do_test capi2-6.14 {
list [sqlite3_step $VM1] \
[sqlite3_column_count $VM1] \
[get_row_values $VM1] \
[get_column_names $VM1]
} {SQLITE_ROW 1 7 {x counter}}
} {SQLITE_ROW 1 6 {x counter}}
do_test capi2-6.15 {
execsql {SELECT * FROM t1}
} {1 2 3}
@ -474,7 +468,7 @@ do_test capi2-6.16 {
[sqlite3_column_count $VM1] \
[get_row_values $VM1] \
[get_column_names $VM1]
} {SQLITE_ROW 1 8 {x counter}}
} {SQLITE_ROW 1 7 {x counter}}
do_test capi2-6.17 {
catchsql {UPDATE t1 SET b=b+1}
} {0 {}}
@ -483,7 +477,7 @@ do_test capi2-6.18 {
[sqlite3_column_count $VM1] \
[get_row_values $VM1] \
[get_column_names $VM1]
} {SQLITE_ROW 1 9 {x counter}}
} {SQLITE_ROW 1 8 {x counter}}
do_test capi2-6.19 {
execsql {SELECT * FROM t1}
} {1 3 3}
@ -492,7 +486,7 @@ do_test capi2-6.20 {
[sqlite3_column_count $VM1] \
[get_row_values $VM1] \
[get_column_names $VM1]
} {SQLITE_ROW 1 10 {x counter}}
} {SQLITE_ROW 1 9 {x counter}}
#do_test capi2-6.21 {
# execsql {ROLLBACK; SELECT * FROM t1}
#} {1 2 3}
@ -501,7 +495,7 @@ do_test capi2-6.22 {
[sqlite3_column_count $VM1] \
[get_row_values $VM1] \
[get_column_names $VM1]
} {SQLITE_ROW 1 11 {x counter}}
} {SQLITE_ROW 1 10 {x counter}}
#do_test capi2-6.23 {
# execsql {BEGIN TRANSACTION;}
#} {}
@ -510,7 +504,7 @@ do_test capi2-6.24 {
[sqlite3_column_count $VM1] \
[get_row_values $VM1] \
[get_column_names $VM1]
} {SQLITE_ROW 1 12 {x counter}}
} {SQLITE_ROW 1 11 {x counter}}
do_test capi2-6.25 {
execsql {
INSERT INTO t1 VALUES(2,3,4);
@ -522,7 +516,7 @@ do_test capi2-6.26 {
[sqlite3_column_count $VM1] \
[get_row_values $VM1] \
[get_column_names $VM1]
} {SQLITE_ROW 1 13 {x counter}}
} {SQLITE_ROW 1 12 {x counter}}
do_test capi2-6.27 {
catchsql {
INSERT INTO t1 VALUES(2,4,5);
@ -534,7 +528,7 @@ do_test capi2-6.28 {
[sqlite3_column_count $VM1] \
[get_row_values $VM1] \
[get_column_names $VM1]
} {SQLITE_ROW 1 14 {x counter}}
} {SQLITE_ROW 1 13 {x counter}}
do_test capi2-6.99 {
sqlite3_finalize $VM1
} {SQLITE_OK}

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script testing the callback-free C/C++ API.
#
# $Id: capi3.test,v 1.25 2004/11/20 20:18:55 drh Exp $
# $Id: capi3.test,v 1.26 2004/11/22 10:02:22 danielk1977 Exp $
#
set testdir [file dirname $argv0]
@ -760,15 +760,11 @@ do_test capi3-12.2 {
}
} {0 {}}
# The following test used to report "database is locked". As of 3.10
# this is no longer the case, the INSERT is legal. The inserted row
# will be returned after all others (because the scan is being done
# in rowid order).
do_test capi3-12.3 {
catchsql {
INSERT INTO t2 VALUES(4);
}
} {0 {}}
} {1 {database table is locked}}
do_test capi3-12.4 {
catchsql {
BEGIN;
@ -780,14 +776,11 @@ do_test capi3-12.5 {
} {SQLITE_ROW}
do_test capi3-12.6 {
sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-12.7 {
sqlite3_step $STMT
} {SQLITE_DONE}
do_test capi3-12.8 {
do_test capi3-12.7 {
sqlite3_finalize $STMT
} {SQLITE_OK}
do_test capi3-12.9 {
do_test capi3-12.8 {
execsql {
COMMIT;
SELECT a FROM t1;

View File

@ -29,7 +29,7 @@
# The solution to the problem was to detect that the table is locked
# before the index entry is deleted.
#
# $Id: delete2.test,v 1.3 2004/11/16 15:50:21 danielk1977 Exp $
# $Id: delete2.test,v 1.4 2004/11/22 10:02:23 danielk1977 Exp $
#
set testdir [file dirname $argv0]
@ -66,26 +66,27 @@ do_test delete2-1.4 {
} SQLITE_ROW
integrity_check delete2-1.5
# Try to delete a row from the table. Before version 3.10 the DELETE
# would fail because of the SELECT active on the table. In 3.10 the
# DELETE is legal.
# Try to delete a row from the table. The delete should fail.
#
do_test delete2-1.6 {
catchsql {
DELETE FROM q WHERE rowid=1
}
} {0 {}}
} {1 {database table is locked}}
integrity_check delete2-1.7
do_test delete2-1.8 {
execsql {
SELECT * FROM q;
}
} {goodbye id.2 again id.3}
} {hello id.1 goodbye id.2 again id.3}
# Finalize the query, thus clearing the lock on the table. Then
# retry the delete. The delete should work this time.
#
do_test delete2-1.9 {
sqlite3_finalize $STMT
catchsql {
DELETE FROM q WHERE rowid=2
DELETE FROM q WHERE rowid=1
}
} {0 {}}
integrity_check delete2-1.10
@ -93,6 +94,6 @@ do_test delete2-1.11 {
execsql {
SELECT * FROM q;
}
} {again id.3}
} {goodbye id.2 again id.3}
finish_test

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script is database locks.
#
# $Id: lock.test,v 1.28 2004/11/16 15:50:21 danielk1977 Exp $
# $Id: lock.test,v 1.29 2004/11/22 10:02:23 danielk1977 Exp $
set testdir [file dirname $argv0]
@ -98,17 +98,15 @@ do_test lock-1.17 {
set x
} {8 9}
# Previously, this test ensured that you cannot UPDATE a table from within the
# callback of a SELECT on that same table because the SELECT has the table
# locked. But as of 3.10 you can do this, so the test is removed.
#
#do_test lock-1.18 {
# db eval {SELECT * FROM t1} qv {
# set r [catch {db eval {UPDATE t1 SET a=b, b=a}} msg]
# lappend r $msg
# }
# set r
#} {1 {database table is locked}}
# You cannot UPDATE a table from within the callback of a SELECT
# on that same table because the SELECT has the table locked.
do_test lock-1.18 {
db eval {SELECT * FROM t1} qv {
set r [catch {db eval {UPDATE t1 SET a=b, b=a}} msg]
lappend r $msg
}
set r
} {1 {database table is locked}}
# But you can UPDATE a different table from the one that is used in
# the SELECT.

View File

@ -1,117 +0,0 @@
# 2001 September 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The focus
# of this file is modifications made to tables while SELECT queries are
# active on the tables. Using this capability in a program is tricky
# because results can be difficult to predict, but can be useful.
#
# $Id: lock4.test,v 1.1 2004/11/17 16:41:29 danielk1977 Exp $
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test lock4-1.0 {
execsql {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
}
} {}
# Check that we can INSERT into a table while doing a SELECT on it.
do_test lock4-1.1 {
db eval {SELECT * FROM t1} {
if {$a<5} {
execsql "INSERT INTO t1 VALUES($a+1, ($a+1)*2)"
}
}
} {}
do_test lock4-1.2 {
execsql {
SELECT * FROM t1
}
} {1 2 2 4 3 6 4 8 5 10}
# Check that we can UPDATE a table while doing a SELECT on it.
do_test lock4-1.3 {
db eval {SELECT * FROM t1 WHERE (a%2)=0} {
execsql "UPDATE t1 SET b = b/2 WHERE a = $a"
}
} {}
do_test lock4-1.4 {
execsql {
SELECT * FROM t1
}
} {1 2 2 2 3 6 4 4 5 10}
# Check that we can DELETE from a table while doing a SELECT on it.
do_test lock4-1.5 {
db eval {SELECT * FROM t1 WHERE (a%2)=0} {
execsql "DELETE FROM t1 WHERE a = $a"
}
} {}
do_test lock4-1.6 {
execsql {
SELECT * FROM t1
}
} {1 2 3 6 5 10}
# Check what happens when a row is deleted while a cursor is still using
# the row (because of a SELECT that does a join).
do_test lock4-2.0 {
execsql {
CREATE TABLE t2(c);
INSERT INTO t2 VALUES('one');
INSERT INTO t2 VALUES('two');
}
} {}
do_test lock4-2.1 {
set res [list]
db eval {SELECT a, b, c FROM t1, t2} {
lappend res $a $b $c
if {0==[string compare $c one]} {
execsql "DELETE FROM t1 WHERE a = $a"
}
}
set res
} {1 2 one 1 2 two 3 6 one 3 6 two 5 10 one 5 10 two}
do_test lock4-2.2 {
execsql {
SELECT * FROM t1;
}
} {}
# do_test lock4-2.3 {
# execsql "
# INSERT INTO t1 VALUES('[string repeat 1 750]', '[string repeat 2 750]')
# "
# } {}
# do_test lock4-2.4 {
# set res [list]
# db eval {SELECT a, b, c FROM t1, t2} {
# lappend res $a $b $c
# if {0==[string compare $c one]} {
# execsql "DELETE FROM t1 WHERE a = '$a'"
# }
# }
# set res
# } [list \
# [string repeat 1 750] [string repeat 2 750] one \
# [string repeat 1 750] [string repeat 2 750] two
# ]
# do_test lock4-2.5 {
# execsql {
# SELECT * FROM t1;
# }
# } {}
finish_test

View File

@ -13,7 +13,7 @@
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc2.test,v 1.15 2004/11/22 08:43:32 danielk1977 Exp $
# $Id: misc2.test,v 1.16 2004/11/22 10:02:23 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -135,6 +135,57 @@ do_test misc2-6.1 {
}
} {1 2}
# Make sure we get an error message (not a segfault) on an attempt to
# update a table from within the callback of a select on that same
# table.
#
do_test misc2-7.1 {
db close
file delete -force test.db
sqlite3 db test.db
execsql {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1);
}
set rc [catch {
db eval {SELECT rowid FROM t1} {} {
db eval "DELETE FROM t1 WHERE rowid=$rowid"
}
} msg]
lappend rc $msg
} {1 {database table is locked}}
do_test misc2-7.2 {
set rc [catch {
db eval {SELECT rowid FROM t1} {} {
db eval "INSERT INTO t1 VALUES(3)"
}
} msg]
lappend rc $msg
} {1 {database table is locked}}
do_test misc2-7.3 {
db close
file delete -force test.db
sqlite3 db :memory:
execsql {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1);
}
set rc [catch {
db eval {SELECT rowid FROM t1} {} {
db eval "DELETE FROM t1 WHERE rowid=$rowid"
}
} msg]
lappend rc $msg
} {1 {database table is locked}}
do_test misc2-7.4 {
set rc [catch {
db eval {SELECT rowid FROM t1} {} {
db eval "INSERT INTO t1 VALUES(3)"
}
} msg]
lappend rc $msg
} {1 {database table is locked}}
# Ticket #453. If the SQL ended with "-", the tokenizer was calling that
# an incomplete token, which caused problem. The solution was to just call
# it a minus sign.