xref: /sqlite-3.40.0/test/skipscan5.test (revision 8210233c)
14e42ba4aSdan# 2013-11-13
24e42ba4aSdan#
34e42ba4aSdan# The author disclaims copyright to this source code.  In place of
44e42ba4aSdan# a legal notice, here is a blessing:
54e42ba4aSdan#
64e42ba4aSdan#    May you do good and not evil.
74e42ba4aSdan#    May you find forgiveness for yourself and forgive others.
84e42ba4aSdan#    May you share freely, never taking more than you give.
94e42ba4aSdan#
104e42ba4aSdan#***********************************************************************
114e42ba4aSdan#
124e42ba4aSdan# This file implements tests of the "skip-scan" query strategy. In
134e42ba4aSdan# particular it tests that stat4 data can be used by a range query
144e42ba4aSdan# that uses the skip-scan approach.
154e42ba4aSdan#
164e42ba4aSdan
174e42ba4aSdanset testdir [file dirname $argv0]
184e42ba4aSdansource $testdir/tester.tcl
194e42ba4aSdanset testprefix skipscan5
204e42ba4aSdan
214e42ba4aSdanifcapable !stat4 {
224e42ba4aSdan  finish_test
234e42ba4aSdan  return
244e42ba4aSdan}
254e42ba4aSdan
264e42ba4aSdando_execsql_test 1.1 {
274e42ba4aSdan  CREATE TABLE t1(a INT, b INT, c INT);
284e42ba4aSdan  CREATE INDEX i1 ON t1(a, b);
294e42ba4aSdan} {}
304e42ba4aSdan
314e42ba4aSdanexpr srand(4)
324e42ba4aSdando_test 1.2 {
33461ff359Sdrh  for {set i 0} {$i < 1000} {incr i} {
344e42ba4aSdan    set a [expr int(rand()*4.0) + 1]
354e42ba4aSdan    set b [expr int(rand()*20.0) + 1]
364e42ba4aSdan    execsql { INSERT INTO t1 VALUES($a, $b, NULL) }
374e42ba4aSdan  }
384e42ba4aSdan  execsql ANALYZE
394e42ba4aSdan} {}
404e42ba4aSdan
418e9028d0Sdanforeach {tn q res} {
428e9028d0Sdan  1  "b = 5"                   {/*ANY(a) AND b=?*/}
438e9028d0Sdan  2  "b > 12 AND b < 16"       {/*ANY(a) AND b>? AND b<?*/}
44*8210233cSdrh  3  "b > 2 AND b < 16"        {/*SCAN t1*/}
458e9028d0Sdan  4  "b > 18 AND b < 25"       {/*ANY(a) AND b>? AND b<?*/}
46461ff359Sdrh  5  "b > 16"                  {/*ANY(a) AND b>?*/}
47*8210233cSdrh  6  "b > 5"                   {/*SCAN t1*/}
48*8210233cSdrh  7  "b < 15"                  {/*SCAN t1*/}
498e9028d0Sdan  8  "b < 5"                   {/*ANY(a) AND b<?*/}
508e9028d0Sdan  9  "5 > b"                   {/*ANY(a) AND b<?*/}
518e9028d0Sdan  10 "b = '5'"                 {/*ANY(a) AND b=?*/}
528e9028d0Sdan  11 "b > '12' AND b < '16'"   {/*ANY(a) AND b>? AND b<?*/}
53*8210233cSdrh  12 "b > '2' AND b < '16'"    {/*SCAN t1*/}
548e9028d0Sdan  13 "b > '18' AND b < '25'"   {/*ANY(a) AND b>? AND b<?*/}
55461ff359Sdrh  14 "b > '16'"                {/*ANY(a) AND b>?*/}
56*8210233cSdrh  15 "b > '5'"                 {/*SCAN t1*/}
57*8210233cSdrh  16 "b < '15'"                {/*SCAN t1*/}
588e9028d0Sdan  17 "b < '5'"                 {/*ANY(a) AND b<?*/}
598e9028d0Sdan  18 "'5' > b"                 {/*ANY(a) AND b<?*/}
604e42ba4aSdan} {
618e9028d0Sdan  set sql "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE $q"
628e9028d0Sdan  do_execsql_test 1.3.$tn $sql $res
634e42ba4aSdan}
644e42ba4aSdan
654e42ba4aSdan
66fa887454Sdan#-------------------------------------------------------------------------
67fa887454Sdan# Test that range-query/skip-scan estimation works with text values.
68fa887454Sdan# And on UTF-16 databases when there is no UTF-16 collation sequence
69fa887454Sdan# available.
708e9028d0Sdan#
71fa887454Sdan
72fa887454Sdanproc test_collate {enc lhs rhs} {
73fa887454Sdan  string compare $lhs $rhs
74fa887454Sdan}
75fa887454Sdan
76fa887454Sdanforeach {tn dbenc coll} {
77fa887454Sdan  1 UTF-8   { add_test_collate db 0 0 1 }
78fa887454Sdan  2 UTF-16  { add_test_collate db 1 0 0 }
79fa887454Sdan  3 UTF-8   { add_test_collate db 0 1 0 }
80fa887454Sdan} {
81fa887454Sdan  reset_db
82fa887454Sdan  eval $coll
83fa887454Sdan
84fa887454Sdan  do_execsql_test 2.$tn.1 " PRAGMA encoding = '$dbenc' "
85fa887454Sdan  do_execsql_test 2.$tn.2 {
86fa887454Sdan    CREATE TABLE t2(a TEXT, b TEXT, c TEXT COLLATE test_collate, d TEXT);
87fa887454Sdan    CREATE INDEX i2 ON t2(a, b, c);
88fa887454Sdan  }
89fa887454Sdan
90fa887454Sdan  set vocab(d) { :) }
91fa887454Sdan  set vocab(c) { a b c d e f g h i j k l m n o p q r s t }
92fa887454Sdan  set vocab(b) { one two three }
93fa887454Sdan  set vocab(a) { sql }
94fa887454Sdan
95fa887454Sdan  do_test 2.$tn.3 {
96fa887454Sdan    for {set i 0} {$i < 100} {incr i} {
97fa887454Sdan      foreach var {a b c d} {
98fa887454Sdan        set $var [lindex $vocab($var) [expr $i % [llength $vocab($var)]]]
99fa887454Sdan      }
100fa887454Sdan      execsql { INSERT INTO t2 VALUES($a, $b, $c, $d) }
101fa887454Sdan    }
102fa887454Sdan    execsql ANALYZE
103fa887454Sdan  } {}
104fa887454Sdan
105fa887454Sdan  foreach {tn2 q res} {
106fa887454Sdan    1 { c BETWEEN 'd' AND 'e' }       {/*ANY(a) AND ANY(b) AND c>? AND c<?*/}
107*8210233cSdrh    2 { c BETWEEN 'b' AND 'r' }       {/*SCAN t2*/}
108fa887454Sdan    3 { c > 'q' }                     {/*ANY(a) AND ANY(b) AND c>?*/}
109*8210233cSdrh    4 { c > 'e' }                     {/*SCAN t2*/}
110*8210233cSdrh    5 { c < 'q' }                     {/*SCAN t2*/}
111461ff359Sdrh    6 { c < 'b' }                     {/*ANY(a) AND ANY(b) AND c<?*/}
112fa887454Sdan  } {
113fa887454Sdan    set sql "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE $q"
114fa887454Sdan    do_execsql_test 2.$tn.$tn2 $sql $res
115fa887454Sdan  }
116fa887454Sdan
117fa887454Sdan}
118fa887454Sdan
1198e9028d0Sdan#-------------------------------------------------------------------------
1208e9028d0Sdan# Test that range-query/skip-scan estimation works on columns that contain
1218e9028d0Sdan# a variety of types.
1228e9028d0Sdan#
1238e9028d0Sdan
1248e9028d0Sdanreset_db
1258e9028d0Sdando_execsql_test 3.1 {
1268e9028d0Sdan  CREATE TABLE t3(a, b, c);
1278e9028d0Sdan  CREATE INDEX i3 ON t3(a, b);
1288e9028d0Sdan}
1298e9028d0Sdan
1308e9028d0Sdanset values {
1318e9028d0Sdan    NULL NULL NULL
1328e9028d0Sdan    NULL -9567 -9240
1338e9028d0Sdan    -8725 -8659 -8248.340244520614
1348e9028d0Sdan    -8208 -7939 -7746.985758536954
1358e9028d0Sdan    -7057 -6550 -5916
1368e9028d0Sdan    -5363 -4935.781822975623 -4935.063633571875
1378e9028d0Sdan    -3518.4554911770183 -2537 -2026
1388e9028d0Sdan    -1511.2603881914456 -1510.4195994839156 -1435
1398e9028d0Sdan    -1127.4210136045804 -1045 99
1408e9028d0Sdan    1353 1457 1563.2908193223611
1418e9028d0Sdan    2245 2286 2552
1428e9028d0Sdan    2745.18831295203 2866.279926554429 3075.0468527316334
1438e9028d0Sdan    3447 3867 4237.892420141907
1448e9028d0Sdan    4335 5052.9775000424015 5232.178240656935
1458e9028d0Sdan    5541.784919585003 5749.725576373621 5758
1468e9028d0Sdan    6005 6431 7263.477992854769
1478e9028d0Sdan    7441 7541 8667.279760663994
1488e9028d0Sdan    8857 9199.638673662972 'dl'
1498e9028d0Sdan    'dro' 'h' 'igprfq'
1508e9028d0Sdan    'jnbd' 'k' 'kordee'
1518e9028d0Sdan    'lhwcv' 'mzlb' 'nbjked'
1528e9028d0Sdan    'nufpo' 'nxqkdq' 'shelln'
1538e9028d0Sdan    'tvzn' 'wpnt' 'wylf'
1548e9028d0Sdan    'ydkgu' 'zdb' X''
1558e9028d0Sdan    X'0a' X'203f6429f1f33f' X'23858e324545e0362b'
1568e9028d0Sdan    X'3f9f8a' X'516f7ddd4b' X'68f1df0930ac6b'
1578e9028d0Sdan    X'9ea60d' X'a06f' X'aefd342a39ce36df'
1588e9028d0Sdan    X'afaa020fe2' X'be201c' X'c47d97b209601e45'
1598e9028d0Sdan}
1608e9028d0Sdan
1618e9028d0Sdando_test 3.2 {
1628e9028d0Sdan  set c 0
1638e9028d0Sdan  foreach v $values {
1648e9028d0Sdan    execsql "INSERT INTO t3 VALUES($c % 2, $v, $c)"
1658e9028d0Sdan    incr c
1668e9028d0Sdan  }
1678e9028d0Sdan  execsql ANALYZE
1688e9028d0Sdan} {}
1698e9028d0Sdan
1708e9028d0Sdanforeach {tn q res} {
1718e9028d0Sdan  1 "b BETWEEN -10000 AND -8000"       {/*ANY(a) AND b>? AND b<?*/}
172*8210233cSdrh  2 "b BETWEEN -10000 AND 'qqq'"       {/*SCAN t3*/}
173*8210233cSdrh  3 "b < X'5555'"                      {/*SCAN t3*/}
1748e9028d0Sdan  4 "b > X'5555'"                      {/*ANY(a) AND b>?*/}
1758e9028d0Sdan  5 "b > 'zzz'"                        {/*ANY(a) AND b>?*/}
176*8210233cSdrh  6 "b < 'zzz'"                        {/*SCAN t3*/}
1778e9028d0Sdan} {
1788e9028d0Sdan  set sql "EXPLAIN QUERY PLAN SELECT * FROM t3 WHERE $q"
1798e9028d0Sdan  do_execsql_test 3.3.$tn $sql $res
1808e9028d0Sdan}
1818e9028d0Sdan
1824e42ba4aSdanfinish_test
183