]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix an obscure b-tree bug that applied to transient trees used for IN(...) expression...
authordanielk1977 <danielk1977@noemail.net>
Sat, 12 May 2007 09:30:47 +0000 (09:30 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Sat, 12 May 2007 09:30:47 +0000 (09:30 +0000)
FossilOrigin-Name: 96c7232f8b208cd1c50063f7946bb6dbc386abd6

manifest
manifest.uuid
src/btree.c
test/in2.test [new file with mode: 0644]
test/quick.test

index d0443333b6c914d23392ae1b5627cdb7d2914fd5..2815e02f61d67379e0131fe4d6274c77a58adafd 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Bugfixes\sfor\sassert()\sfailures\sfound\sby\sfuzz.test.\s(CVS\s3986)
-D 2007-05-12T06:11:12
+C Fix\san\sobscure\sb-tree\sbug\sthat\sapplied\sto\stransient\strees\sused\sfor\sIN(...)\sexpressions.\s(CVS\s3987)
+D 2007-05-12T09:30:47
 F Makefile.in 87b200ad9970907f76df734d29dff3d294c10935
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -61,7 +61,7 @@ F src/alter.c ca8fc4a3c7359379598dc12589b65c32eb88defd
 F src/analyze.c 4bbf5ddf9680587c6d4917e02e378b6037be3651
 F src/attach.c ba628db0c2b6a362f036d017bf1196cdfe4ebb37
 F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f
-F src/btree.c ec0943dd89a7209ea3326ff29df7708f98c5596f
+F src/btree.c f24b394e5f5b46fced3464c19ac623d0d92ccaa6
 F src/btree.h 1d527bf61ed176f980c34999d5793a0fd45dcf8c
 F src/btreeInt.h cb3c0e9eb842d06079a62cdf3492c90c5db7ba75
 F src/build.c 5789303291d40a1d37bfede83c1c769be22c88ab
@@ -253,6 +253,7 @@ F test/fuzz2.test fdbea571808441c12c91e9cd038eb77b4692d42b
 F test/hook.test 7e7645fd9a033f79cce8fdff151e32715e7ec50a
 F test/icu.test e6bfae7f625c88fd14df6f540fe835bdfc1e4329
 F test/in.test 369cb2aa1eab02296b4ec470732fe8c131260b1d
+F test/in2.test d76a13877d9c445308f48a26db9ea25a6d77032f
 F test/incrblob.test 7f82ae497364612aa17a37f77f12e01e2bee9f20
 F test/incrblob_err.test 9dae0762ba4d73b516d176d091c6b2b16f625953
 F test/incrvacuum.test f490c8ae86f2ecca622425d02e27d3119058cb21
@@ -318,7 +319,7 @@ F test/pragma.test fecb7085f58d9fb5172a5c0b63fd3b25c7bfb414
 F test/printf.test 69d8cb0771a1a5e4d9d5dece12fc2c16179ac5e5
 F test/progress.test 8b22b4974b0a95272566385f8cb8c341c7130df8 x
 F test/ptrchng.test 1c712dd6516e1377471744fa765e41c79a357da6
-F test/quick.test 9f5bb4e95460472dc379f5dd8932c743407501ef
+F test/quick.test 3d7f6ffd285e1589a58874dd483ccb6e058ea4a5
 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
 F test/rdonly.test b34db316525440d3b42c32e83942c02c37d28ef0
 F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b
@@ -488,7 +489,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 6f346a6be9803b84260509352315f8fa1e820490
-R 421ee1c5131718e89476168ba0bf8dd2
+P 2e80736d57fde55b112864d8b198a9a2fe0eaa38
+R c03758dd4b5f8ad6c12d156193f78eb7
 U danielk1977
-Z 5c7f7cde115ea23bf87a55ad3a52e94b
+Z d455335e1335c1a2040ee8b7528b51b1
index c50bb3486e07bd95523f3468569686cb81399a7c..a5702e213cb823401e852ccf06c67dc260414b37 100644 (file)
@@ -1 +1 @@
-2e80736d57fde55b112864d8b198a9a2fe0eaa38
\ No newline at end of file
+96c7232f8b208cd1c50063f7946bb6dbc386abd6
\ No newline at end of file
index 90ee29ca5eb63b322ed72462e69a1decece3432e..2c0f0dfc3c0311a5fe6e1725d13a16a84c98488d 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.379 2007/05/08 21:45:27 drh Exp $
+** $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.
@@ -4731,6 +4731,21 @@ static int balance_nonroot(MemPage *pPage){
         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;
diff --git a/test/in2.test b/test/in2.test
new file mode 100644 (file)
index 0000000..9fd7be6
--- /dev/null
@@ -0,0 +1,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
+
index 87e154ceb5d316f6ada5ff3989c20c4bfe8df6f1..a3d18a8ef05d89dcfd96811e1cdf1dcafdbf2b74 100644 (file)
@@ -6,7 +6,7 @@
 #***********************************************************************
 # This file runs all tests.
 #
-# $Id: quick.test,v 1.55 2007/05/10 15:37:53 danielk1977 Exp $
+# $Id: quick.test,v 1.56 2007/05/12 09:30:47 danielk1977 Exp $
 
 proc lshift {lvar} {
   upvar $lvar l
@@ -46,6 +46,7 @@ set EXCLUDE {
   crash2.test
   exclusive3.test
   fuzz.test
+  in2.test
   loadext.test
   malloc.test
   malloc2.test