1
0

analyze5.test 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. # 2011 January 19
  2. #
  3. # The author disclaims copyright to this source code. In place of
  4. # a legal notice, here is a blessing:
  5. #
  6. # May you do good and not evil.
  7. # May you find forgiveness for yourself and forgive others.
  8. # May you share freely, never taking more than you give.
  9. #
  10. #***********************************************************************
  11. #
  12. # This file implements tests for SQLite library. The focus of the tests
  13. # in this file is the use of the sqlite_stat4 histogram data on tables
  14. # with many repeated values and only a few distinct values.
  15. #
  16. set testdir [file dirname $argv0]
  17. source $testdir/tester.tcl
  18. ifcapable !stat4&&!stat3 {
  19. finish_test
  20. return
  21. }
  22. set testprefix analyze5
  23. proc eqp {sql {db db}} {
  24. uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
  25. }
  26. proc alpha {blob} {
  27. set ret ""
  28. foreach c [split $blob {}] {
  29. if {[string is alpha $c]} {append ret $c}
  30. }
  31. return $ret
  32. }
  33. db func alpha alpha
  34. db func lindex lindex
  35. unset -nocomplain i t u v w x y z
  36. do_test analyze5-1.0 {
  37. db eval {CREATE TABLE t1(t,u,v TEXT COLLATE nocase,w,x,y,z)}
  38. for {set i 0} {$i < 1000} {incr i} {
  39. set y [expr {$i>=25 && $i<=50}]
  40. set z [expr {($i>=400) + ($i>=700) + ($i>=875)}]
  41. set x $z
  42. set w $z
  43. set t [expr {$z+0.5}]
  44. switch $z {
  45. 0 {set u "alpha"; unset x}
  46. 1 {set u "bravo"}
  47. 2 {set u "charlie"}
  48. 3 {set u "delta"; unset w}
  49. }
  50. if {$i%2} {set v $u} {set v [string toupper $u]}
  51. db eval {INSERT INTO t1 VALUES($t,$u,$v,$w,$x,$y,$z)}
  52. }
  53. db eval {
  54. CREATE INDEX t1t ON t1(t); -- 0.5, 1.5, 2.5, and 3.5
  55. CREATE INDEX t1u ON t1(u); -- text
  56. CREATE INDEX t1v ON t1(v); -- mixed case text
  57. CREATE INDEX t1w ON t1(w); -- integers 0, 1, 2 and a few NULLs
  58. CREATE INDEX t1x ON t1(x); -- integers 1, 2, 3 and many NULLs
  59. CREATE INDEX t1y ON t1(y); -- integers 0 and very few 1s
  60. CREATE INDEX t1z ON t1(z); -- integers 0, 1, 2, and 3
  61. ANALYZE;
  62. }
  63. ifcapable stat4 {
  64. db eval {
  65. SELECT DISTINCT lindex(test_decode(sample),0)
  66. FROM sqlite_stat4 WHERE idx='t1u' ORDER BY nlt;
  67. }
  68. } else {
  69. db eval {
  70. SELECT sample FROM sqlite_stat3 WHERE idx='t1u' ORDER BY nlt;
  71. }
  72. }
  73. } {alpha bravo charlie delta}
  74. do_test analyze5-1.1 {
  75. ifcapable stat4 {
  76. db eval {
  77. SELECT DISTINCT lower(lindex(test_decode(sample), 0))
  78. FROM sqlite_stat4 WHERE idx='t1v' ORDER BY 1
  79. }
  80. } else {
  81. db eval {
  82. SELECT lower(sample) FROM sqlite_stat3 WHERE idx='t1v' ORDER BY 1
  83. }
  84. }
  85. } {alpha bravo charlie delta}
  86. ifcapable stat4 {
  87. do_test analyze5-1.2 {
  88. db eval {SELECT idx, count(*) FROM sqlite_stat4 GROUP BY 1 ORDER BY 1}
  89. } {t1t 8 t1u 8 t1v 8 t1w 8 t1x 8 t1y 9 t1z 8}
  90. } else {
  91. do_test analyze5-1.2 {
  92. db eval {SELECT idx, count(*) FROM sqlite_stat3 GROUP BY 1 ORDER BY 1}
  93. } {t1t 4 t1u 4 t1v 4 t1w 4 t1x 4 t1y 2 t1z 4}
  94. }
  95. # Verify that range queries generate the correct row count estimates
  96. #
  97. foreach {testid where index rows} {
  98. 1 {z>=0 AND z<=0} t1z 400
  99. 2 {z>=1 AND z<=1} t1z 300
  100. 3 {z>=2 AND z<=2} t1z 175
  101. 4 {z>=3 AND z<=3} t1z 125
  102. 5 {z>=4 AND z<=4} t1z 1
  103. 6 {z>=-1 AND z<=-1} t1z 1
  104. 7 {z>1 AND z<3} t1z 175
  105. 8 {z>0 AND z<100} t1z 600
  106. 9 {z>=1 AND z<100} t1z 600
  107. 10 {z>1 AND z<100} t1z 300
  108. 11 {z>=2 AND z<100} t1z 300
  109. 12 {z>2 AND z<100} t1z 125
  110. 13 {z>=3 AND z<100} t1z 125
  111. 14 {z>3 AND z<100} t1z 1
  112. 15 {z>=4 AND z<100} t1z 1
  113. 16 {z>=-100 AND z<=-1} t1z 1
  114. 17 {z>=-100 AND z<=0} t1z 400
  115. 18 {z>=-100 AND z<0} t1z 1
  116. 19 {z>=-100 AND z<=1} t1z 700
  117. 20 {z>=-100 AND z<2} t1z 700
  118. 21 {z>=-100 AND z<=2} t1z 875
  119. 22 {z>=-100 AND z<3} t1z 875
  120. 31 {z>=0.0 AND z<=0.0} t1z 400
  121. 32 {z>=1.0 AND z<=1.0} t1z 300
  122. 33 {z>=2.0 AND z<=2.0} t1z 175
  123. 34 {z>=3.0 AND z<=3.0} t1z 125
  124. 35 {z>=4.0 AND z<=4.0} t1z 1
  125. 36 {z>=-1.0 AND z<=-1.0} t1z 1
  126. 37 {z>1.5 AND z<3.0} t1z 174
  127. 38 {z>0.5 AND z<100} t1z 599
  128. 39 {z>=1.0 AND z<100} t1z 600
  129. 40 {z>1.5 AND z<100} t1z 299
  130. 41 {z>=2.0 AND z<100} t1z 300
  131. 42 {z>2.1 AND z<100} t1z 124
  132. 43 {z>=3.0 AND z<100} t1z 125
  133. 44 {z>3.2 AND z<100} t1z 1
  134. 45 {z>=4.0 AND z<100} t1z 1
  135. 46 {z>=-100 AND z<=-1.0} t1z 1
  136. 47 {z>=-100 AND z<=0.0} t1z 400
  137. 48 {z>=-100 AND z<0.0} t1z 1
  138. 49 {z>=-100 AND z<=1.0} t1z 700
  139. 50 {z>=-100 AND z<2.0} t1z 700
  140. 51 {z>=-100 AND z<=2.0} t1z 875
  141. 52 {z>=-100 AND z<3.0} t1z 875
  142. 101 {z=-1} t1z 1
  143. 102 {z=0} t1z 400
  144. 103 {z=1} t1z 300
  145. 104 {z=2} t1z 175
  146. 105 {z=3} t1z 125
  147. 106 {z=4} t1z 1
  148. 107 {z=-10.0} t1z 1
  149. 108 {z=0.0} t1z 400
  150. 109 {z=1.0} t1z 300
  151. 110 {z=2.0} t1z 175
  152. 111 {z=3.0} t1z 125
  153. 112 {z=4.0} t1z 1
  154. 113 {z=1.5} t1z 1
  155. 114 {z=2.5} t1z 1
  156. 201 {z IN (-1)} t1z 1
  157. 202 {z IN (0)} t1z 400
  158. 203 {z IN (1)} t1z 300
  159. 204 {z IN (2)} t1z 175
  160. 205 {z IN (3)} t1z 125
  161. 206 {z IN (4)} t1z 1
  162. 207 {z IN (0.5)} t1z 1
  163. 208 {z IN (0,1)} t1z 700
  164. 209 {z IN (0,1,2)} t1z 875
  165. 210 {z IN (0,1,2,3)} {} 100
  166. 211 {z IN (0,1,2,3,4,5)} {} 100
  167. 212 {z IN (1,2)} t1z 475
  168. 213 {z IN (2,3)} t1z 300
  169. 214 {z=3 OR z=2} t1z 300
  170. 215 {z IN (-1,3)} t1z 126
  171. 216 {z=-1 OR z=3} t1z 126
  172. 300 {y=0} t1y 974
  173. 301 {y=1} t1y 26
  174. 302 {y=0.1} t1y 1
  175. 400 {x IS NULL} t1x 400
  176. } {
  177. # Verify that the expected index is used with the expected row count
  178. # No longer valid due to an EXPLAIN QUERY PLAN output format change
  179. # do_test analyze5-1.${testid}a {
  180. # set x [lindex [eqp "SELECT * FROM t1 WHERE $where"] 3]
  181. # set idx {}
  182. # regexp {INDEX (t1.) } $x all idx
  183. # regexp {~([0-9]+) rows} $x all nrow
  184. # list $idx $nrow
  185. # } [list $index $rows]
  186. # Verify that the same result is achieved regardless of whether or not
  187. # the index is used
  188. do_test analyze5-1.${testid}b {
  189. set w2 [string map {y +y z +z} $where]
  190. set a1 [db eval "SELECT rowid FROM t1 NOT INDEXED WHERE $w2\
  191. ORDER BY +rowid"]
  192. set a2 [db eval "SELECT rowid FROM t1 WHERE $where ORDER BY +rowid"]
  193. if {$a1==$a2} {
  194. set res ok
  195. } else {
  196. set res "a1=\[$a1\] a2=\[$a2\]"
  197. }
  198. set res
  199. } {ok}
  200. }
  201. # Increase the number of NULLs in column x
  202. #
  203. db eval {
  204. UPDATE t1 SET x=NULL;
  205. UPDATE t1 SET x=rowid
  206. WHERE rowid IN (SELECT rowid FROM t1 ORDER BY random() LIMIT 5);
  207. ANALYZE;
  208. }
  209. # Verify that range queries generate the correct row count estimates
  210. #
  211. foreach {testid where index rows} {
  212. 500 {x IS NULL AND u='charlie'} t1u 17
  213. 501 {x=1 AND u='charlie'} t1x 1
  214. 502 {x IS NULL} t1x 995
  215. 503 {x=1} t1x 1
  216. 504 {x IS NOT NULL} t1x 2
  217. 505 {+x IS NOT NULL} {} 500
  218. 506 {upper(x) IS NOT NULL} {} 500
  219. } {
  220. # Verify that the expected index is used with the expected row count
  221. # No longer valid due to an EXPLAIN QUERY PLAN format change
  222. # do_test analyze5-1.${testid}a {
  223. # set x [lindex [eqp "SELECT * FROM t1 WHERE $where"] 3]
  224. # set idx {}
  225. # regexp {INDEX (t1.) } $x all idx
  226. # regexp {~([0-9]+) rows} $x all nrow
  227. # list $idx $nrow
  228. # } [list $index $rows]
  229. # Verify that the same result is achieved regardless of whether or not
  230. # the index is used
  231. do_test analyze5-1.${testid}b {
  232. set w2 [string map {y +y z +z} $where]
  233. set a1 [db eval "SELECT rowid FROM t1 NOT INDEXED WHERE $w2\
  234. ORDER BY +rowid"]
  235. set a2 [db eval "SELECT rowid FROM t1 WHERE $where ORDER BY +rowid"]
  236. if {$a1==$a2} {
  237. set res ok
  238. } else {
  239. set res "a1=\[$a1\] a2=\[$a2\]"
  240. }
  241. set res
  242. } {ok}
  243. }
  244. finish_test