SQLite

Check-in [96c7232f8b]
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
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 96c7232f8b208cd1c50063f7946bb6dbc386abd6
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
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
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.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"












|







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








|







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