danielk1977 | 4aeff62 | 2007-05-12 09:30:47 +0000 | [diff] [blame] | 1 | # 2007 May 12 |
| 2 | # |
| 3 | # The author disclaims copyright to this source code. In place of |
| 4 | # a legal notice, here is a blessing: |
| 5 | # |
| 6 | # May you do good and not evil. |
| 7 | # May you find forgiveness for yourself and forgive others. |
| 8 | # May you share freely, never taking more than you give. |
| 9 | # |
| 10 | #*********************************************************************** |
| 11 | # This file tests a special case in the b-tree code that can be |
| 12 | # hit by the "IN" operator (or EXISTS, NOT IN, etc.). |
| 13 | # |
drh | e8f52c5 | 2008-07-12 14:52:20 +0000 | [diff] [blame] | 14 | # $Id: in2.test,v 1.3 2008/07/12 14:52:20 drh Exp $ |
danielk1977 | 4aeff62 | 2007-05-12 09:30:47 +0000 | [diff] [blame] | 15 | |
| 16 | set testdir [file dirname $argv0] |
| 17 | source $testdir/tester.tcl |
| 18 | |
| 19 | do_test in2-1 { |
| 20 | execsql { |
| 21 | CREATE TABLE a(i INTEGER PRIMARY KEY, a); |
| 22 | } |
| 23 | } {} |
| 24 | |
danielk1977 | 39c9604 | 2007-05-12 10:41:47 +0000 | [diff] [blame] | 25 | set ::N 2000 |
| 26 | |
danielk1977 | 4aeff62 | 2007-05-12 09:30:47 +0000 | [diff] [blame] | 27 | do_test in2-2 { |
| 28 | db transaction { |
danielk1977 | 39c9604 | 2007-05-12 10:41:47 +0000 | [diff] [blame] | 29 | for {set ::ii 0} {$::ii < $::N} {incr ::ii} { |
danielk1977 | 4aeff62 | 2007-05-12 09:30:47 +0000 | [diff] [blame] | 30 | execsql {INSERT INTO a VALUES($::ii, $::ii)} |
| 31 | } |
danielk1977 | 39c9604 | 2007-05-12 10:41:47 +0000 | [diff] [blame] | 32 | execsql {INSERT INTO a VALUES(4000, '')} |
danielk1977 | 4aeff62 | 2007-05-12 09:30:47 +0000 | [diff] [blame] | 33 | |
danielk1977 | 39c9604 | 2007-05-12 10:41:47 +0000 | [diff] [blame] | 34 | for {set ::ii 0} {$::ii < $::N} {incr ::ii} { |
| 35 | set ::t [format "x%04d" $ii] |
| 36 | execsql {INSERT INTO a VALUES(NULL, $::t)} |
danielk1977 | 4aeff62 | 2007-05-12 09:30:47 +0000 | [diff] [blame] | 37 | } |
| 38 | } |
| 39 | } {} |
| 40 | |
| 41 | # Each iteration of this loop builds a slightly different b-tree to |
| 42 | # evaluate the "IN (...)" operator in the SQL statement. The contents |
| 43 | # of the b-tree are (in sorted order): |
| 44 | # |
| 45 | # $::ii integers. |
| 46 | # a string of zero length. |
danielk1977 | 39c9604 | 2007-05-12 10:41:47 +0000 | [diff] [blame] | 47 | # $::N short strings. |
danielk1977 | 4aeff62 | 2007-05-12 09:30:47 +0000 | [diff] [blame] | 48 | # |
| 49 | # Records are inserted in sorted order. |
| 50 | # |
| 51 | # The string of zero-length is stored in a b-tree cell with 3 bytes |
| 52 | # of payload. Moving this cell from a leaf node to a internal node |
| 53 | # during b-tree balancing was causing an assertion failure. |
| 54 | # |
| 55 | # This bug only applied to b-trees generated to evaluate IN (..) |
| 56 | # clauses, as it is impossible for persistent b-trees (SQL tables + |
| 57 | # indices) to contain cells smaller than 4 bytes. |
| 58 | # |
danielk1977 | 39c9604 | 2007-05-12 10:41:47 +0000 | [diff] [blame] | 59 | for {set ::ii 3} {$::ii < $::N} {incr ::ii} { |
danielk1977 | 4aeff62 | 2007-05-12 09:30:47 +0000 | [diff] [blame] | 60 | do_test in2-$::ii { |
| 61 | execsql { |
danielk1977 | 39c9604 | 2007-05-12 10:41:47 +0000 | [diff] [blame] | 62 | SELECT 1 IN (SELECT a FROM a WHERE (i < $::ii) OR (i >= $::N)) |
danielk1977 | 4aeff62 | 2007-05-12 09:30:47 +0000 | [diff] [blame] | 63 | } |
| 64 | } {1} |
| 65 | } |
| 66 | |
| 67 | finish_test |