/ Check-in [96c7232f]
Login

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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 96c7232f8b208cd1c50063f7946bb6dbc386abd6
User & Date: danielk1977 2007-05-12 09:30:47
Context
2007-05-12
10:41
Fix another variant of the "IN (...)" b-tree problem. (CVS 3988) check-in: 260338c4 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: 96c7232f user: danielk1977 tags: trunk
06:11
Bugfixes for assert() failures found by fuzz.test. (CVS 3986) check-in: 2e80736d user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
4727
4728
4729
4730
4731
4732
4733















4734
4735
4736
4737
4738
4739
4740
** 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.379 2007/05/08 21:45:27 drh 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"

................................................................................
        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







|







 







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







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
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
** 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"

................................................................................
        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.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
42
43
44
45
46
47
48

49
50
51
52
53
54
55
#    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.55 2007/05/10 15:37:53 danielk1977 Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}
................................................................................
  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







|







 







>







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#    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
}
................................................................................
  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