]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
The ANALYZE command now counts at all rows of an index, even those containing
authordrh <drh@noemail.net>
Tue, 4 Jan 2011 17:57:53 +0000 (17:57 +0000)
committerdrh <drh@noemail.net>
Tue, 4 Jan 2011 17:57:53 +0000 (17:57 +0000)
NULL values.  A valid sqlite_stat1 entry is created even if the index contains
nothing but NULLs.

FossilOrigin-Name: 824c8dd3015bbd5c8a1dd661cfe09fe5bf7a80d3

manifest
manifest.uuid
src/analyze.c
test/analyze4.test [new file with mode: 0644]

index 287040a5de9823786f1afad6840dc5984116b58c..05d30be4a93d07d7b4b5cc12df37ace39823522a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,8 @@
-C Have\stestfixture\sinvoke\sC\sroutine\sZipvfs_Init()\swhen\screating\sa\snew\sinterpreter\sif\sSQLITE_ENABLE_ZIPVFS\sis\sdefined.
-D 2010-12-29T18:24:39
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+C The\sANALYZE\scommand\snow\scounts\sat\sall\srows\sof\san\sindex,\seven\sthose\scontaining\nNULL\svalues.\s\sA\svalid\ssqlite_stat1\sentry\sis\screated\seven\sif\sthe\sindex\scontains\nnothing\sbut\sNULLs.
+D 2011-01-04T17:57:54
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in de6498556d536ae60bb8bb10e8c1ba011448658c
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -113,7 +116,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
 F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
 F src/alter.c 6a0c176e64a34929a4436048066a84ef4f1445b3
-F src/analyze.c 1ea594a912a14138e20a05db09d9065e46f29a2a
+F src/analyze.c 62ccd3a44e5c303bfa27987c596bfd1136741d81
 F src/attach.c 252c4f7e36cc219349451ed63e278c60e80b26f3
 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
 F src/backup.c d5b0137bc20327af08c14772227cc35134839c30
@@ -252,6 +255,7 @@ F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
 F test/analyze.test c1eb87067fc16ece7c07e823d6395fd831b270c5
 F test/analyze2.test 3bde8f0879d9c1f2df3af21fcf42e706d8ee1e43
 F test/analyze3.test 820ddfb7591b49607fbaf77240c7955ac3cabb04
+F test/analyze4.test ce844952931beea75dcd3bd416f3d10444fbcfde
 F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
 F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
 F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
@@ -894,7 +898,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 7ded90baeb75db5af83345cd2c31211cbee1e91b
-R d42c36fbd6ce68590e6e0dd8ec4c5c18
-U dan
-Z 8593c64ef1af55c2ba01b9032057e1e5
+P 430635dacfa818e8266a88214aaf60c77862de1c
+R ec45ba633f0c4f96e6a484b9eb344d5c
+U drh
+Z cde307ce45c85e17f986af467042bf4f
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.6 (GNU/Linux)
+
+iD8DBQFNI1+moxKgR168RlERAjnJAJ4o8v4Qvkj2Lt5p/tc7Gw/iz0iScACeJQd8
+a939JIEB/46ZOm5/OzfvI/M=
+=dmuf
+-----END PGP SIGNATURE-----
index 23c1ab40b8be666eeafe5d49d3f33231777f1797..ec7d8b96b40264ff5b3ba38b122b4458290821c8 100644 (file)
@@ -1 +1 @@
-430635dacfa818e8266a88214aaf60c77862de1c
\ No newline at end of file
+824c8dd3015bbd5c8a1dd661cfe09fe5bf7a80d3
\ No newline at end of file
index 159e323612bde750e5f843baa5957d6fb57bcdbe..96fd4e4703d7f0edc7083eaafa9d4a6cd70690e6 100644 (file)
@@ -234,8 +234,8 @@ static void analyzeOneTable(
 
     for(i=0; i<nCol; i++){
       sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol);
-#ifdef SQLITE_ENABLE_STAT2
       if( i==0 ){
+#ifdef SQLITE_ENABLE_STAT2
         /* Check if the record that cursor iIdxCur points to contains a
         ** value that should be stored in the sqlite_stat2 table. If so,
         ** store it.  */
@@ -264,12 +264,14 @@ static void analyzeOneTable(
 
         sqlite3VdbeJumpHere(v, ne);
         sqlite3VdbeAddOp2(v, OP_AddImm, regRecno, 1);
-      }
 #endif
 
+        /* Always record the very first row */
+        sqlite3VdbeAddOp1(v, OP_IfNot, iMem+1);
+      }
       sqlite3VdbeAddOp3(v, OP_Ne, regCol, 0, iMem+nCol+i+1);
       /**** TODO:  add collating sequence *****/
-      sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
+      sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
     }
     if( db->mallocFailed ){
       /* If a malloc failure has occurred, then the result of the expression 
@@ -280,7 +282,11 @@ static void analyzeOneTable(
     }
     sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
     for(i=0; i<nCol; i++){
-      sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-(nCol*2));
+      int addr = sqlite3VdbeCurrentAddr(v) - (nCol*2);
+      if( i==0 ){
+        sqlite3VdbeJumpHere(v, addr-1);  /* Set jump dest for the OP_IfNot */
+      }
+      sqlite3VdbeJumpHere(v, addr);      /* Set jump dest for the OP_Ne */
       sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
       sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
     }
diff --git a/test/analyze4.test b/test/analyze4.test
new file mode 100644 (file)
index 0000000..3919bad
--- /dev/null
@@ -0,0 +1,80 @@
+# 2011 January 04
+#
+# 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 implements regression tests for SQLite library. This file 
+# implements tests for ANALYZE to verify that multiple rows containing
+# a NULL value count as distinct rows for the purposes of analyze 
+# statistics.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test analyze4-1.0 {
+  db eval {
+    CREATE TABLE t1(a,b);
+    CREATE INDEX t1a ON t1(a);
+    CREATE INDEX t1b ON t1(b);
+    INSERT INTO t1 VALUES(1,NULL);
+    INSERT INTO t1 SELECT a+1, b FROM t1;
+    INSERT INTO t1 SELECT a+2, b FROM t1;
+    INSERT INTO t1 SELECT a+4, b FROM t1;
+    INSERT INTO t1 SELECT a+8, b FROM t1;
+    INSERT INTO t1 SELECT a+16, b FROM t1;
+    INSERT INTO t1 SELECT a+32, b FROM t1;
+    INSERT INTO t1 SELECT a+64, b FROM t1;
+    ANALYZE;
+  }
+
+  # Should choose the t1a index since it is more specific than t1b.
+  db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+
+# Verify that the t1b index shows that it does not narrow down the
+# search any at all.
+#
+do_test analyze4-1.1 {
+  db eval {
+    SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx;
+  }
+} {t1a {128 1} t1b {128 128}}
+
+# Change half of the b values from NULL to a constant.  Verify
+# that the number of rows selected in stat1 is half the total 
+# number of rows.
+#
+do_test analyze4-1.2 {
+  db eval {
+    UPDATE t1 SET b='x' WHERE a%2;
+    ANALYZE;
+    SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx;
+  }
+} {t1a {128 1} t1b {128 64}}
+
+# Change the t1.b values all back to NULL.  Add columns t1.c and t1.d.
+# Create a multi-column indices using t1.b and verify that ANALYZE 
+# processes them correctly.
+#
+do_test analyze4-1.3 {
+  db eval {
+    UPDATE t1 SET b=NULL;
+    ALTER TABLE t1 ADD COLUMN c;
+    ALTER TABLE t1 ADD COLUMN d;
+    UPDATE t1 SET c=a/4, d=a/2;
+    CREATE INDEX t1bcd ON t1(b,c,d);
+    CREATE INDEX t1cdb ON t1(c,d,b);
+    CREATE INDEX t1cbd ON t1(c,b,d);
+    ANALYZE;
+    SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx;
+  }
+} {t1a {128 1} t1b {128 128} t1bcd {128 128 4 2} t1cbd {128 4 4 2} t1cdb {128 4 2 2}}
+
+finish_test