Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix an obscure b-tree bug that applied to transient trees used for IN(...) expressions. (CVS 3987) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
96c7232f8b208cd1c50063f7946bb6db |
User & Date: | danielk1977 2007-05-12 09:30:47.000 |
Context
2007-05-12
| ||
10:41 | Fix another variant of the "IN (...)" b-tree problem. (CVS 3988) (check-in: 260338c4b2 user: danielk1977 tags: trunk) | |
09:30 | Fix an obscure b-tree bug that applied to transient trees used for IN(...) expressions. (CVS 3987) (check-in: 96c7232f8b user: danielk1977 tags: trunk) | |
06:11 | Bugfixes for assert() failures found by fuzz.test. (CVS 3986) (check-in: 2e80736d57 user: danielk1977 tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* ** $Id: btree.c,v 1.380 2007/05/12 09:30:47 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" |
︙ | ︙ | |||
4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 | assert( iSpace<=pBt->pageSize*5 ); pTemp = 0; }else{ pCell -= 4; pTemp = &aSpace[iSpace]; iSpace += sz; assert( iSpace<=pBt->pageSize*5 ); } rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4); if( rc!=SQLITE_OK ) goto balance_cleanup; put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno); #ifndef SQLITE_OMIT_AUTOVACUUM /* If this is an auto-vacuum database, and not a leaf-data tree, ** then update the pointer map with an entry for the overflow page | > > > > > > > > > > > > > > > | 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 | assert( iSpace<=pBt->pageSize*5 ); pTemp = 0; }else{ pCell -= 4; pTemp = &aSpace[iSpace]; iSpace += sz; assert( iSpace<=pBt->pageSize*5 ); /* Obscure case for non-leaf-data trees: If the cell at pCell was ** previously stored on a leaf node, and it's reported size was 4 ** bytes, then it may actually be smaller than this ** (see sqlite3BtreeParseCellPtr(), 4 bytes is the minimum size of ** any cell). But it's important to pass the correct size to ** insertCell(), so reparse the cell now. ** ** Note that this can never happen in an SQLite data file, as all ** cells are at least 4 bytes. It only happens in b-trees used ** to evaluate "IN (SELECT ...)" and similar clauses. */ if( szCell[j]==4 ){ assert(leafCorrection==4); sz = cellSizePtr(pParent, pCell); } } rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4); if( rc!=SQLITE_OK ) goto balance_cleanup; put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno); #ifndef SQLITE_OMIT_AUTOVACUUM /* If this is an auto-vacuum database, and not a leaf-data tree, ** then update the pointer map with an entry for the overflow page |
︙ | ︙ |
Added test/in2.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 | # 2007 May 12 # # 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 tests a special case in the b-tree code that can be # hit by the "IN" operator (or EXISTS, NOT IN, etc.). # # $Id: in2.test,v 1.1 2007/05/12 09:30:47 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test in2-1 { execsql { CREATE TABLE a(i INTEGER PRIMARY KEY, a); } } {} do_test in2-2 { db transaction { for {set ::ii 0} {$::ii < 1000} {incr ::ii} { execsql {INSERT INTO a VALUES($::ii, $::ii)} } execsql {INSERT INTO a VALUES(1000, '')} for {set ::ii 0} {$::ii < 1000} {incr ::ii} { execsql {INSERT INTO a VALUES(NULL, 'x' || $::ii)} } } } {} # Each iteration of this loop builds a slightly different b-tree to # evaluate the "IN (...)" operator in the SQL statement. The contents # of the b-tree are (in sorted order): # # $::ii integers. # a string of zero length. # 1000 short strings. # # Records are inserted in sorted order. # # The string of zero-length is stored in a b-tree cell with 3 bytes # of payload. Moving this cell from a leaf node to a internal node # during b-tree balancing was causing an assertion failure. # # This bug only applied to b-trees generated to evaluate IN (..) # clauses, as it is impossible for persistent b-trees (SQL tables + # indices) to contain cells smaller than 4 bytes. # for {set ::ii 3} {$::ii < 1000} {incr ::ii} { do_test in2-$::ii { execsql { SELECT 1 IN (SELECT a FROM a WHERE (i < $::ii) OR (i >= 1000)) } } {1} } finish_test |
Changes to test/quick.test.
1 2 3 4 5 6 7 8 | # # 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 runs all tests. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # # 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 runs all tests. # # $Id: quick.test,v 1.56 2007/05/12 09:30:47 danielk1977 Exp $ proc lshift {lvar} { upvar $lvar l set ret [lindex $l 0] set l [lrange $l 1 end] return $ret } |
︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 51 52 53 54 55 | btree5.test btree6.test corrupt.test crash.test crash2.test exclusive3.test fuzz.test loadext.test malloc.test malloc2.test malloc3.test memleak.test misc7.test misuse.test | > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | btree5.test btree6.test corrupt.test crash.test crash2.test exclusive3.test fuzz.test in2.test loadext.test malloc.test malloc2.test malloc3.test memleak.test misc7.test misuse.test |
︙ | ︙ |