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