461ff3594b
FossilOrigin-Name: 27c681c9c6672ad7098d8ff2c41e76d3e9e55866b6327ed85e73f63bd623ceed
183 lines
5.4 KiB
Plaintext
183 lines
5.4 KiB
Plaintext
# 2013-11-13
|
|
#
|
|
# 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 of the "skip-scan" query strategy. In
|
|
# particular it tests that stat4 data can be used by a range query
|
|
# that uses the skip-scan approach.
|
|
#
|
|
|
|
set testdir [file dirname $argv0]
|
|
source $testdir/tester.tcl
|
|
set testprefix skipscan5
|
|
|
|
ifcapable !stat4 {
|
|
finish_test
|
|
return
|
|
}
|
|
|
|
do_execsql_test 1.1 {
|
|
CREATE TABLE t1(a INT, b INT, c INT);
|
|
CREATE INDEX i1 ON t1(a, b);
|
|
} {}
|
|
|
|
expr srand(4)
|
|
do_test 1.2 {
|
|
for {set i 0} {$i < 1000} {incr i} {
|
|
set a [expr int(rand()*4.0) + 1]
|
|
set b [expr int(rand()*20.0) + 1]
|
|
execsql { INSERT INTO t1 VALUES($a, $b, NULL) }
|
|
}
|
|
execsql ANALYZE
|
|
} {}
|
|
|
|
foreach {tn q res} {
|
|
1 "b = 5" {/*ANY(a) AND b=?*/}
|
|
2 "b > 12 AND b < 16" {/*ANY(a) AND b>? AND b<?*/}
|
|
3 "b > 2 AND b < 16" {/*SCAN TABLE t1*/}
|
|
4 "b > 18 AND b < 25" {/*ANY(a) AND b>? AND b<?*/}
|
|
5 "b > 16" {/*ANY(a) AND b>?*/}
|
|
6 "b > 5" {/*SCAN TABLE t1*/}
|
|
7 "b < 15" {/*SCAN TABLE t1*/}
|
|
8 "b < 5" {/*ANY(a) AND b<?*/}
|
|
9 "5 > b" {/*ANY(a) AND b<?*/}
|
|
10 "b = '5'" {/*ANY(a) AND b=?*/}
|
|
11 "b > '12' AND b < '16'" {/*ANY(a) AND b>? AND b<?*/}
|
|
12 "b > '2' AND b < '16'" {/*SCAN TABLE t1*/}
|
|
13 "b > '18' AND b < '25'" {/*ANY(a) AND b>? AND b<?*/}
|
|
14 "b > '16'" {/*ANY(a) AND b>?*/}
|
|
15 "b > '5'" {/*SCAN TABLE t1*/}
|
|
16 "b < '15'" {/*SCAN TABLE t1*/}
|
|
17 "b < '5'" {/*ANY(a) AND b<?*/}
|
|
18 "'5' > b" {/*ANY(a) AND b<?*/}
|
|
} {
|
|
set sql "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE $q"
|
|
do_execsql_test 1.3.$tn $sql $res
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
# Test that range-query/skip-scan estimation works with text values.
|
|
# And on UTF-16 databases when there is no UTF-16 collation sequence
|
|
# available.
|
|
#
|
|
|
|
proc test_collate {enc lhs rhs} {
|
|
string compare $lhs $rhs
|
|
}
|
|
|
|
foreach {tn dbenc coll} {
|
|
1 UTF-8 { add_test_collate db 0 0 1 }
|
|
2 UTF-16 { add_test_collate db 1 0 0 }
|
|
3 UTF-8 { add_test_collate db 0 1 0 }
|
|
} {
|
|
reset_db
|
|
eval $coll
|
|
|
|
do_execsql_test 2.$tn.1 " PRAGMA encoding = '$dbenc' "
|
|
do_execsql_test 2.$tn.2 {
|
|
CREATE TABLE t2(a TEXT, b TEXT, c TEXT COLLATE test_collate, d TEXT);
|
|
CREATE INDEX i2 ON t2(a, b, c);
|
|
}
|
|
|
|
set vocab(d) { :) }
|
|
set vocab(c) { a b c d e f g h i j k l m n o p q r s t }
|
|
set vocab(b) { one two three }
|
|
set vocab(a) { sql }
|
|
|
|
do_test 2.$tn.3 {
|
|
for {set i 0} {$i < 100} {incr i} {
|
|
foreach var {a b c d} {
|
|
set $var [lindex $vocab($var) [expr $i % [llength $vocab($var)]]]
|
|
}
|
|
execsql { INSERT INTO t2 VALUES($a, $b, $c, $d) }
|
|
}
|
|
execsql ANALYZE
|
|
} {}
|
|
|
|
foreach {tn2 q res} {
|
|
1 { c BETWEEN 'd' AND 'e' } {/*ANY(a) AND ANY(b) AND c>? AND c<?*/}
|
|
2 { c BETWEEN 'b' AND 'r' } {/*SCAN TABLE t2*/}
|
|
3 { c > 'q' } {/*ANY(a) AND ANY(b) AND c>?*/}
|
|
4 { c > 'e' } {/*SCAN TABLE t2*/}
|
|
5 { c < 'q' } {/*SCAN TABLE t2*/}
|
|
6 { c < 'b' } {/*ANY(a) AND ANY(b) AND c<?*/}
|
|
} {
|
|
set sql "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE $q"
|
|
do_execsql_test 2.$tn.$tn2 $sql $res
|
|
}
|
|
|
|
}
|
|
|
|
#-------------------------------------------------------------------------
|
|
# Test that range-query/skip-scan estimation works on columns that contain
|
|
# a variety of types.
|
|
#
|
|
|
|
reset_db
|
|
do_execsql_test 3.1 {
|
|
CREATE TABLE t3(a, b, c);
|
|
CREATE INDEX i3 ON t3(a, b);
|
|
}
|
|
|
|
set values {
|
|
NULL NULL NULL
|
|
NULL -9567 -9240
|
|
-8725 -8659 -8248.340244520614
|
|
-8208 -7939 -7746.985758536954
|
|
-7057 -6550 -5916
|
|
-5363 -4935.781822975623 -4935.063633571875
|
|
-3518.4554911770183 -2537 -2026
|
|
-1511.2603881914456 -1510.4195994839156 -1435
|
|
-1127.4210136045804 -1045 99
|
|
1353 1457 1563.2908193223611
|
|
2245 2286 2552
|
|
2745.18831295203 2866.279926554429 3075.0468527316334
|
|
3447 3867 4237.892420141907
|
|
4335 5052.9775000424015 5232.178240656935
|
|
5541.784919585003 5749.725576373621 5758
|
|
6005 6431 7263.477992854769
|
|
7441 7541 8667.279760663994
|
|
8857 9199.638673662972 'dl'
|
|
'dro' 'h' 'igprfq'
|
|
'jnbd' 'k' 'kordee'
|
|
'lhwcv' 'mzlb' 'nbjked'
|
|
'nufpo' 'nxqkdq' 'shelln'
|
|
'tvzn' 'wpnt' 'wylf'
|
|
'ydkgu' 'zdb' X''
|
|
X'0a' X'203f6429f1f33f' X'23858e324545e0362b'
|
|
X'3f9f8a' X'516f7ddd4b' X'68f1df0930ac6b'
|
|
X'9ea60d' X'a06f' X'aefd342a39ce36df'
|
|
X'afaa020fe2' X'be201c' X'c47d97b209601e45'
|
|
}
|
|
|
|
do_test 3.2 {
|
|
set c 0
|
|
foreach v $values {
|
|
execsql "INSERT INTO t3 VALUES($c % 2, $v, $c)"
|
|
incr c
|
|
}
|
|
execsql ANALYZE
|
|
} {}
|
|
|
|
foreach {tn q res} {
|
|
1 "b BETWEEN -10000 AND -8000" {/*ANY(a) AND b>? AND b<?*/}
|
|
2 "b BETWEEN -10000 AND 'qqq'" {/*SCAN TABLE t3*/}
|
|
3 "b < X'5555'" {/*SCAN TABLE t3*/}
|
|
4 "b > X'5555'" {/*ANY(a) AND b>?*/}
|
|
5 "b > 'zzz'" {/*ANY(a) AND b>?*/}
|
|
6 "b < 'zzz'" {/*SCAN TABLE t3*/}
|
|
} {
|
|
set sql "EXPLAIN QUERY PLAN SELECT * FROM t3 WHERE $q"
|
|
do_execsql_test 3.3.$tn $sql $res
|
|
}
|
|
|
|
finish_test
|