SQLite

Check-in [af635cab8a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Back out changes allowing writes to tables that have open cursors. (CVS 2134)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: af635cab8a1d761c469e35208dda08a29f0964a1
User & Date: danielk1977 2004-11-22 10:02:22.000
Context
2004-11-22
10:02
Back out changes allowing writes to tables that have open cursors. (CVS 2135) (check-in: ec6b48f4b2 user: danielk1977 tags: trunk)
10:02
Back out changes allowing writes to tables that have open cursors. (CVS 2134) (check-in: af635cab8a user: danielk1977 tags: trunk)
10:02
Back out changes allowing writes to tables that have open cursors. (CVS 2133) (check-in: 91acd87e52 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Deleted test/btree8.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
# 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

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































































































































































































































































































































































































































































































































































































































































































































Changes to test/capi2.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2003 January 29
#
# 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 testing the callback-free C/C++ API.
#
# $Id: capi2.test,v 1.21 2004/11/16 15:50:21 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Return the text values from the current row pointed at by STMT as a list.
proc get_row_values {STMT} {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2003 January 29
#
# 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 testing the callback-free C/C++ API.
#
# $Id: capi2.test,v 1.22 2004/11/22 10:02:22 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Return the text values from the current row pointed at by STMT as a list.
proc get_row_values {STMT} {
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
do_test capi2-6.12 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [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 {}}
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}}
do_test capi2-6.15 {
  execsql {SELECT * FROM t1}
} {1 2 3}
do_test capi2-6.16 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 8 {x counter}}
do_test capi2-6.17 {
  catchsql {UPDATE t1 SET b=b+1}
} {0 {}}
do_test capi2-6.18 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 9 {x counter}}
do_test capi2-6.19 {
  execsql {SELECT * FROM t1}
} {1 3 3}
do_test capi2-6.20 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 10 {x counter}}
#do_test capi2-6.21 {
#  execsql {ROLLBACK; SELECT * FROM t1}
#} {1 2 3}
do_test capi2-6.22 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 11 {x counter}}
#do_test capi2-6.23 {
#  execsql {BEGIN TRANSACTION;}
#} {}
do_test capi2-6.24 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 12 {x counter}}
do_test capi2-6.25 {
  execsql {
    INSERT INTO t1 VALUES(2,3,4);
    SELECT * FROM t1;
  }
} {1 3 3 2 3 4}
do_test capi2-6.26 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 13 {x counter}}
do_test capi2-6.27 {
  catchsql {
    INSERT INTO t1 VALUES(2,4,5);
    SELECT * FROM t1;
  }
} {1 {column a is not unique}}
do_test capi2-6.28 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 14 {x counter}}
do_test capi2-6.99 {
  sqlite3_finalize $VM1
} {SQLITE_OK}
catchsql {ROLLBACK}

do_test capi2-7.1 {
  stepsql $DB {







<
<
<
<
<
<


|





|








|








|








|








|








|











|











|







447
448
449
450
451
452
453






454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
do_test capi2-6.12 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 5 {x counter}}







do_test capi2-6.13 {
  catchsql {UPDATE t3 SET x=x+1}
} {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 6 {x counter}}
do_test capi2-6.15 {
  execsql {SELECT * FROM t1}
} {1 2 3}
do_test capi2-6.16 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 7 {x counter}}
do_test capi2-6.17 {
  catchsql {UPDATE t1 SET b=b+1}
} {0 {}}
do_test capi2-6.18 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 8 {x counter}}
do_test capi2-6.19 {
  execsql {SELECT * FROM t1}
} {1 3 3}
do_test capi2-6.20 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 9 {x counter}}
#do_test capi2-6.21 {
#  execsql {ROLLBACK; SELECT * FROM t1}
#} {1 2 3}
do_test capi2-6.22 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 10 {x counter}}
#do_test capi2-6.23 {
#  execsql {BEGIN TRANSACTION;}
#} {}
do_test capi2-6.24 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 11 {x counter}}
do_test capi2-6.25 {
  execsql {
    INSERT INTO t1 VALUES(2,3,4);
    SELECT * FROM t1;
  }
} {1 3 3 2 3 4}
do_test capi2-6.26 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 12 {x counter}}
do_test capi2-6.27 {
  catchsql {
    INSERT INTO t1 VALUES(2,4,5);
    SELECT * FROM t1;
  }
} {1 {column a is not unique}}
do_test capi2-6.28 {
  list [sqlite3_step $VM1] \
       [sqlite3_column_count $VM1] \
       [get_row_values $VM1] \
       [get_column_names $VM1]
} {SQLITE_ROW 1 13 {x counter}}
do_test capi2-6.99 {
  sqlite3_finalize $VM1
} {SQLITE_OK}
catchsql {ROLLBACK}

do_test capi2-7.1 {
  stepsql $DB {
Changes to test/capi3.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2003 January 29
#
# 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 testing the callback-free C/C++ API.
#
# $Id: capi3.test,v 1.25 2004/11/20 20:18:55 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Return the UTF-16 representation of the supplied UTF-8 string $str.
# If $nt is true, append two 0x00 bytes as a nul terminator.













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2003 January 29
#
# 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 testing the callback-free C/C++ API.
#
# $Id: capi3.test,v 1.26 2004/11/22 10:02:22 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Return the UTF-16 representation of the supplied UTF-8 string $str.
# If $nt is true, append two 0x00 bytes as a nul terminator.
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
} {SQLITE_ROW}
do_test capi3-12.2 {
  catchsql {
    INSERT INTO t1 VALUES(3, NULL);
  }
} {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 {}}
do_test capi3-12.4 {
  catchsql {
    BEGIN;
    INSERT INTO t1 VALUES(4, NULL);
  }
} {0 {}}
do_test capi3-12.5 {
  sqlite3_step $STMT
} {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 {
  sqlite3_finalize $STMT
} {SQLITE_OK}
do_test capi3-12.9 {
  execsql {
    COMMIT;
    SELECT a FROM t1;
  }
} {1 2 3 4}

finish_test







<
<
<
<




|











<
<
<

|


|







756
757
758
759
760
761
762




763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778



779
780
781
782
783
784
785
786
787
788
789
790
} {SQLITE_ROW}
do_test capi3-12.2 {
  catchsql {
    INSERT INTO t1 VALUES(3, NULL);
  }
} {0 {}}





do_test capi3-12.3 {
  catchsql {
    INSERT INTO t2 VALUES(4);
  }
} {1 {database table is locked}}
do_test capi3-12.4 {
  catchsql {
    BEGIN;
    INSERT INTO t1 VALUES(4, NULL);
  }
} {0 {}}
do_test capi3-12.5 {
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-12.6 {
  sqlite3_step $STMT



} {SQLITE_DONE}
do_test capi3-12.7 {
  sqlite3_finalize $STMT
} {SQLITE_OK}
do_test capi3-12.8 {
  execsql {
    COMMIT;
    SELECT a FROM t1;
  }
} {1 2 3 4}

finish_test
Changes to test/delete2.test.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# index entry was deleted first, before the table entry.  And the index
# delete worked.  Thus an entry was deleted from the index but not from
# the table.
#
# 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 $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table that has an index.
#







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# index entry was deleted first, before the table entry.  And the index
# delete worked.  Thus an entry was deleted from the index but not from
# the table.
#
# The solution to the problem was to detect that the table is locked
# before the index entry is deleted.
#
# $Id: delete2.test,v 1.4 2004/11/22 10:02:23 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table that has an index.
#
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84



85
86
87
88
89
90
91
92
93
94
95
96
97
98
#
do_test delete2-1.4 {
  set STMT [sqlite3_prepare $DB {SELECT * FROM q} -1 TAIL]
  sqlite3_step $STMT
} 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.
#
do_test delete2-1.6 {
  catchsql {
    DELETE FROM q WHERE rowid=1
  }
} {0 {}}
integrity_check delete2-1.7
do_test delete2-1.8 {
  execsql {
    SELECT * FROM q;
  }
} {goodbye id.2 again id.3}




do_test delete2-1.9 {
  sqlite3_finalize $STMT
  catchsql {
    DELETE FROM q WHERE rowid=2
  }
} {0 {}}
integrity_check delete2-1.10
do_test delete2-1.11 {
  execsql {
    SELECT * FROM q;
  }
} {again id.3}

finish_test







|
<
<





|





|

>
>
>



|







|


62
63
64
65
66
67
68
69


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#
do_test delete2-1.4 {
  set STMT [sqlite3_prepare $DB {SELECT * FROM q} -1 TAIL]
  sqlite3_step $STMT
} SQLITE_ROW
integrity_check delete2-1.5

# Try to delete a row from the table. The delete should fail.


#
do_test delete2-1.6 {
  catchsql {
    DELETE FROM q WHERE rowid=1
  }
} {1 {database table is locked}}
integrity_check delete2-1.7
do_test delete2-1.8 {
  execsql {
    SELECT * FROM q;
  }
} {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=1
  }
} {0 {}}
integrity_check delete2-1.10
do_test delete2-1.11 {
  execsql {
    SELECT * FROM q;
  }
} {goodbye id.2 again id.3}

finish_test
Changes to test/lock.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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 script is database locks.
#
# $Id: lock.test,v 1.28 2004/11/16 15:50:21 danielk1977 Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create an alternative connection to the database
#













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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 script is database locks.
#
# $Id: lock.test,v 1.29 2004/11/22 10:02:23 danielk1977 Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create an alternative connection to the database
#
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
do_test lock-1.17 {
  db eval {SELECT * FROM t1} qv {
    set x [db eval {SELECT * FROM t2}]
  }
  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}}

# But you can UPDATE a different table from the one that is used in
# the SELECT.
#
do_test lock-1.19 {
  db eval {SELECT * FROM t1} qv {
    set r [catch {db eval {UPDATE t2 SET x=y, y=x}} msg]







|
|
<
<
|
|
|
|
<
>
|
|







94
95
96
97
98
99
100
101
102


103
104
105
106

107
108
109
110
111
112
113
114
115
116
do_test lock-1.17 {
  db eval {SELECT * FROM t1} qv {
    set x [db eval {SELECT * FROM t2}]
  }
  set x
} {8 9}

# 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.
#
do_test lock-1.19 {
  db eval {SELECT * FROM t1} qv {
    set r [catch {db eval {UPDATE t2 SET x=y, y=x}} msg]
Deleted test/lock4.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# 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

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































































































































Changes to test/misc2.test.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# 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 $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable {trigger} {
# Test for ticket #360
#







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for miscellanous features that were
# left out of other test files.
#
# $Id: misc2.test,v 1.16 2004/11/22 10:02:23 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable {trigger} {
# Test for ticket #360
#
130
131
132
133
134
135
136



















































137
138
139
140
141
142
143
  sqlite3 db {}
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
    SELECT * FROM t1;
  }
} {1 2}




















































# 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.
#
do_test misc2-8.1 {
  catchsql {-}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  sqlite3 db {}
  execsql {
    CREATE TABLE t1(a,b);
    INSERT INTO t1 VALUES(1,2);
    SELECT * FROM t1;
  }
} {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.
#
do_test misc2-8.1 {
  catchsql {-}