]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Backport test cases from trunk that seek to prove that the IS NOT NULL
authordrh <drh@noemail.net>
Fri, 8 Apr 2011 23:36:09 +0000 (23:36 +0000)
committerdrh <drh@noemail.net>
Fri, 8 Apr 2011 23:36:09 +0000 (23:36 +0000)
query optimization is working.

FossilOrigin-Name: 9eff470226c6f879bb1b24fb00b6786a816d8cfd

manifest
manifest.uuid
test/analyze5.test [new file with mode: 0644]

index 7cc612f4ffa4b69ced0af0638b84928cc5b4fd53..32ee8c3e739bda5ddc2699938ad22d8d2f4dc2fb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Make\ssure\sthe\squery\splanner\sis\sable\sto\scorrectly\sanalyze\sNULL\svalue\nsamples\sin\sthe\ssqlite_stat2\stable.\s\sThis\sis\sa\sbackport\sof\schanges\nfrom\scheck-in\s[f73a167b434f]
-D 2011-04-08T23:05:50.899
+C Backport\stest\scases\sfrom\strunk\sthat\sseek\sto\sprove\sthat\sthe\sIS\sNOT\sNULL\nquery\soptimization\sis\sworking.
+D 2011-04-08T23:36:09.017
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 543f91f24cd7fee774ecc0a61c19704c0c3e78fd
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -242,6 +242,7 @@ F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
 F test/analyze.test d21f2143664912a20d04b67baf4bed935e7b1b48
 F test/analyze2.test ea3df826879dd672031b27c6a845afc3a39f27d9
 F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b
+F test/analyze5.test 1de8d66b11aae5a1453aa042d62e834a476bac9c
 F test/analyze6.test 1ba1aea8fad25a77ffd71f24522d1bb9ecc949fc
 F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
 F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
@@ -847,7 +848,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P e8177e0149280ea775e9aac18307ce2528f72298
-R 0453ff8f07b741701e560aed8706c2ec
+P 1d6378898aab5208e1fbaf2683a63650b4987c16
+R b045c370be1787d7b141ea78738ab71f
 U drh
-Z 69d0a371db70c7015ac745d683a50d31
+Z 0143ec47aac262d7a15c469ecf440697
index 38d45350f1de5fc24730be7168c832d451eb9751..93a856e18ba255d306c5bcafc4a0a2892393bd42 100644 (file)
@@ -1 +1 @@
-1d6378898aab5208e1fbaf2683a63650b4987c16
\ No newline at end of file
+9eff470226c6f879bb1b24fb00b6786a816d8cfd
\ No newline at end of file
diff --git a/test/analyze5.test b/test/analyze5.test
new file mode 100644 (file)
index 0000000..a0469da
--- /dev/null
@@ -0,0 +1,241 @@
+# 2011 January 19
+#
+# 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 tests for SQLite library.  The focus of the tests
+# in this file is the use of the sqlite_stat2 histogram data on tables
+# with many repeated values and only a few distinct values.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+ifcapable !stat2 {
+  finish_test
+  return
+}
+
+set testprefix analyze5
+
+proc eqp {sql {db db}} {
+  uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
+}
+
+unset -nocomplain i t u v w x y z
+do_test analyze5-1.0 {
+  db eval {CREATE TABLE t1(t,u,v TEXT COLLATE nocase,w,x,y,z)}
+  for {set i 0} {$i < 1000} {incr i} {
+    set y [expr {$i>=25 && $i<=50}]
+    set z [expr {($i>=400) + ($i>=700) + ($i>=875)}]
+    set x $z
+    set w $z
+    set t [expr {$z+0.5}]
+    switch $z {
+      0 {set u "alpha"; unset x}
+      1 {set u "bravo"}
+      2 {set u "charlie"}
+      3 {set u "delta"; unset w}
+    }
+    if {$i%2} {set v $u} {set v [string toupper $u]}
+    db eval {INSERT INTO t1 VALUES($t,$u,$v,$w,$x,$y,$z)}
+  }
+  db eval { 
+    CREATE INDEX t1t ON t1(t);  -- 0.5, 1.5, 2.5, and 3.5
+    CREATE INDEX t1u ON t1(u);  -- text
+    CREATE INDEX t1v ON t1(v);  -- mixed case text
+    CREATE INDEX t1w ON t1(w);  -- integers 0, 1, 2 and a few NULLs
+    CREATE INDEX t1x ON t1(x);  -- integers 1, 2, 3 and many NULLs
+    CREATE INDEX t1y ON t1(y);  -- integers 0 and very few 1s
+    CREATE INDEX t1z ON t1(z);  -- integers 0, 1, 2, and 3
+    ANALYZE;
+    SELECT sample FROM sqlite_stat2 WHERE idx='t1u' ORDER BY sampleno;
+  }
+} {alpha alpha alpha alpha bravo bravo bravo charlie charlie delta}
+do_test analyze5-1.1 {
+  string tolower \
+   [db eval {SELECT sample from sqlite_stat2 WHERE idx='t1v' ORDER BY sampleno}]
+} {alpha alpha alpha alpha bravo bravo bravo charlie charlie delta}
+do_test analyze5-1.2 {
+  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1w' ORDER BY sampleno}
+} {{} 0 0 0 0 1 1 1 2 2}
+do_test analyze5-1.3 {
+  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1x' ORDER BY sampleno}
+} {{} {} {} {} 1 1 1 2 2 3}
+do_test analyze5-1.4 {
+  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1y' ORDER BY sampleno}
+} {0 0 0 0 0 0 0 0 0 0}
+do_test analyze5-1.5 {
+  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1z' ORDER BY sampleno}
+} {0 0 0 0 1 1 1 2 2 3}
+do_test analyze5-1.6 {
+  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1t' ORDER BY sampleno}
+} {0.5 0.5 0.5 0.5 1.5 1.5 1.5 2.5 2.5 3.5}
+
+
+# Verify that range queries generate the correct row count estimates
+#
+foreach {testid where index rows} {
+    1  {z>=0 AND z<=0}       t1z  400
+    2  {z>=1 AND z<=1}       t1z  300
+    3  {z>=2 AND z<=2}       t1z  200
+    4  {z>=3 AND z<=3}       t1z  100
+    5  {z>=4 AND z<=4}       t1z   50
+    6  {z>=-1 AND z<=-1}     t1z   50
+    7  {z>1 AND z<3}         t1z  200
+    8  {z>0 AND z<100}       t1z  600
+    9  {z>=1 AND z<100}      t1z  600
+   10  {z>1 AND z<100}       t1z  300
+   11  {z>=2 AND z<100}      t1z  300
+   12  {z>2 AND z<100}       t1z  100
+   13  {z>=3 AND z<100}      t1z  100
+   14  {z>3 AND z<100}       t1z   50
+   15  {z>=4 AND z<100}      t1z   50
+   16  {z>=-100 AND z<=-1}   t1z   50
+   17  {z>=-100 AND z<=0}    t1z  400
+   18  {z>=-100 AND z<0}     t1z   50
+   19  {z>=-100 AND z<=1}    t1z  700
+   20  {z>=-100 AND z<2}     t1z  700
+   21  {z>=-100 AND z<=2}    t1z  900
+   22  {z>=-100 AND z<3}     t1z  900
+  
+   31  {z>=0.0 AND z<=0.0}   t1z  400
+   32  {z>=1.0 AND z<=1.0}   t1z  300
+   33  {z>=2.0 AND z<=2.0}   t1z  200
+   34  {z>=3.0 AND z<=3.0}   t1z  100
+   35  {z>=4.0 AND z<=4.0}   t1z   50
+   36  {z>=-1.0 AND z<=-1.0} t1z   50
+   37  {z>1.5 AND z<3.0}     t1z  200
+   38  {z>0.5 AND z<100}     t1z  600
+   39  {z>=1.0 AND z<100}    t1z  600
+   40  {z>1.5 AND z<100}     t1z  300
+   41  {z>=2.0 AND z<100}    t1z  300
+   42  {z>2.1 AND z<100}     t1z  100
+   43  {z>=3.0 AND z<100}    t1z  100
+   44  {z>3.2 AND z<100}     t1z   50
+   45  {z>=4.0 AND z<100}    t1z   50
+   46  {z>=-100 AND z<=-1.0} t1z   50
+   47  {z>=-100 AND z<=0.0}  t1z  400
+   48  {z>=-100 AND z<0.0}   t1z   50
+   49  {z>=-100 AND z<=1.0}  t1z  700
+   50  {z>=-100 AND z<2.0}   t1z  700
+   51  {z>=-100 AND z<=2.0}  t1z  900
+   52  {z>=-100 AND z<3.0}   t1z  900
+  
+  101  {z=-1}                t1z   50
+  102  {z=0}                 t1z  400
+  103  {z=1}                 t1z  300
+  104  {z=2}                 t1z  200
+  105  {z=3}                 t1z  100
+  106  {z=4}                 t1z   50
+  107  {z=-10.0}             t1z   50
+  108  {z=0.0}               t1z  400
+  109  {z=1.0}               t1z  300
+  110  {z=2.0}               t1z  200
+  111  {z=3.0}               t1z  100
+  112  {z=4.0}               t1z   50
+  113  {z=1.5}               t1z   50
+  114  {z=2.5}               t1z   50
+  
+  201  {z IN (-1)}           t1z   50
+  202  {z IN (0)}            t1z  400
+  203  {z IN (1)}            t1z  300
+  204  {z IN (2)}            t1z  200
+  205  {z IN (3)}            t1z  100
+  206  {z IN (4)}            t1z   50
+  207  {z IN (0.5)}          t1z   50
+  208  {z IN (0,1)}          t1z  700
+  209  {z IN (0,1,2)}        t1z  900
+  210  {z IN (0,1,2,3)}      {}   100
+  211  {z IN (0,1,2,3,4,5)}  {}   100
+  212  {z IN (1,2)}          t1z  500
+  213  {z IN (2,3)}          t1z  300
+  214  {z=3 OR z=2}          t1z  300
+  215  {z IN (-1,3)}         t1z  150
+  216  {z=-1 OR z=3}         t1z  150
+
+  300  {y=0}                 {}   100
+  301  {y=1}                 t1y   50
+  302  {y=0.1}               t1y   50
+
+  400  {x IS NULL}           t1x  400
+
+} {
+  # Verify that the expected index is used with the expected row count
+  do_test analyze5-1.${testid}a {
+    set x [lindex [eqp "SELECT * FROM t1 WHERE $where"] 3]
+    set idx {}
+    regexp {INDEX (t1.) } $x all idx
+    regexp {~([0-9]+) rows} $x all nrow
+    list $idx $nrow
+  } [list $index $rows]
+
+  # Verify that the same result is achieved regardless of whether or not
+  # the index is used
+  do_test analyze5-1.${testid}b {
+    set w2 [string map {y +y z +z} $where]
+    set a1 [db eval "SELECT rowid FROM t1 NOT INDEXED WHERE $w2\
+                     ORDER BY +rowid"]
+    set a2 [db eval "SELECT rowid FROM t1 WHERE $where ORDER BY +rowid"]
+    if {$a1==$a2} {
+      set res ok
+    } else {
+      set res "a1=\[$a1\] a2=\[$a2\]"
+    }
+    set res
+  } {ok}
+}
+
+# Increase the number of NULLs in column x
+#
+db eval {
+   UPDATE t1 SET x=NULL;
+   UPDATE t1 SET x=rowid
+    WHERE rowid IN (SELECT rowid FROM t1 ORDER BY random() LIMIT 5);
+   ANALYZE;
+}
+
+# Verify that range queries generate the correct row count estimates
+#
+foreach {testid where index rows} {
+  500  {x IS NULL AND u='charlie'}         t1u  20
+  501  {x=1 AND u='charlie'}               t1x   5
+  502  {x IS NULL}                          {} 100
+  503  {x=1}                               t1x  50
+  504  {x IS NOT NULL}                     t1x  25
+  505  {+x IS NOT NULL}                     {} 500
+  506  {upper(x) IS NOT NULL}               {} 500
+
+} {
+  # Verify that the expected index is used with the expected row count
+  do_test analyze5-1.${testid}a {
+    set x [lindex [eqp "SELECT * FROM t1 WHERE $where"] 3]
+    set idx {}
+    regexp {INDEX (t1.) } $x all idx
+    regexp {~([0-9]+) rows} $x all nrow
+    list $idx $nrow
+  } [list $index $rows]
+
+  # Verify that the same result is achieved regardless of whether or not
+  # the index is used
+  do_test analyze5-1.${testid}b {
+    set w2 [string map {y +y z +z} $where]
+    set a1 [db eval "SELECT rowid FROM t1 NOT INDEXED WHERE $w2\
+                     ORDER BY +rowid"]
+    set a2 [db eval "SELECT rowid FROM t1 WHERE $where ORDER BY +rowid"]
+    if {$a1==$a2} {
+      set res ok
+    } else {
+      set res "a1=\[$a1\] a2=\[$a2\]"
+    }
+    set res
+  } {ok}
+}
+
+finish_test