mirror of https://github.com/sqlite/sqlite
Add test cases for skip-scan. Enhance "do_test" so that if the expected result
is of the form "/*..*/" or "~/*..*/" it treats the expected result as a glob pattern rather than as a regular expression. Fix a bug in ANALYZE result loading associated with WITHOUT ROWID tables. FossilOrigin-Name: d3e6e9b2a74074c05429d3c341c23525504351ab
This commit is contained in:
parent
cd8629e4bb
commit
c2b23e7a98
18
manifest
18
manifest
|
@ -1,5 +1,5 @@
|
|||
C Add\sthe\sability\sto\suse\san\sindex\seven\sif\sthe\sleft-most\scolumns\sof\sthe\sindex\nare\sunconstrainted,\sprovided\sthat\sthe\sleft-most\scolumns\shave\sfew\sdistinct\nvalues.
|
||||
D 2013-11-13T12:27:25.442
|
||||
C Add\stest\scases\sfor\sskip-scan.\s\sEnhance\s"do_test"\sso\sthat\sif\sthe\sexpected\sresult\nis\sof\sthe\sform\s"/*..*/"\sor\s"~/*..*/"\sit\streats\sthe\sexpected\sresult\sas\sa\sglob\npattern\srather\sthan\sas\sa\sregular\sexpression.\s\sFix\sa\sbug\sin\sANALYZE\sresult\nloading\sassociated\swith\sWITHOUT\sROWID\stables.
|
||||
D 2013-11-13T15:32:15.331
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 8a07bebafbfda0eb67728f4bd15a36201662d1a1
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
|
@ -160,7 +160,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
|||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
|
||||
F src/analyze.c 27f0c132aa0679189837e0addf8762e7fd6831b6
|
||||
F src/analyze.c 581d5c18ce89c6f45d4dca65914d0de5b4dad41f
|
||||
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
|
||||
|
@ -805,6 +805,7 @@ F test/shell5.test 46c8c18d62732415c4fe084816c13d559831705e
|
|||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test 63af32c300be545417410ea2ce44e78c5b2e34b1
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
|
||||
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
|
||||
|
@ -835,7 +836,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
|||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptrigger.test 0a48d94222d50e6e50d72ac103606c4f8e7cbb81
|
||||
F test/tester.tcl 3f675f00d22de3595be25dc2d2cba7ff623ef058
|
||||
F test/tester.tcl bce6b929932498383ce92431da6a96432c690bf7
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
|
@ -1138,10 +1139,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P 5196000930600d0cd931b87e864507791b9dab08
|
||||
R d1d503c972952b4e29bfacf424d1532a
|
||||
T *branch * skip-scan
|
||||
T *sym-skip-scan *
|
||||
T -sym-trunk *
|
||||
P 27dd5993d1ae5625eb94bf406421eb390d001be9
|
||||
R 56958c69a5559324c31384471b37b6dc
|
||||
U drh
|
||||
Z c64da1e6d225931e6198f9f21b69efb9
|
||||
Z 2ff45f7229fb8bf180b3b10c0362f0e0
|
||||
|
|
|
@ -1 +1 @@
|
|||
27dd5993d1ae5625eb94bf406421eb390d001be9
|
||||
d3e6e9b2a74074c05429d3c341c23525504351ab
|
|
@ -1428,10 +1428,12 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
|
|||
if( pTable==0 ){
|
||||
return 0;
|
||||
}
|
||||
if( argv[1] ){
|
||||
pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
|
||||
}else{
|
||||
if( argv[1]==0 ){
|
||||
pIndex = 0;
|
||||
}else if( sqlite3_stricmp(argv[0],argv[1])==0 ){
|
||||
pIndex = sqlite3PrimaryKeyIndex(pTable);
|
||||
}else{
|
||||
pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
|
||||
}
|
||||
z = argv[2];
|
||||
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
# 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.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test skipscan1-1.1 {
|
||||
CREATE TABLE t1(a TEXT, b INT, c INT, d INT);
|
||||
CREATE INDEX t1abc ON t1(a,b,c);
|
||||
INSERT INTO t1 VALUES('abc',123,4,5);
|
||||
INSERT INTO t1 VALUES('abc',234,5,6);
|
||||
INSERT INTO t1 VALUES('abc',234,6,7);
|
||||
INSERT INTO t1 VALUES('abc',345,7,8);
|
||||
INSERT INTO t1 VALUES('def',567,8,9);
|
||||
INSERT INTO t1 VALUES('def',345,9,10);
|
||||
INSERT INTO t1 VALUES('bcd',100,6,11);
|
||||
|
||||
/* Fake the sqlite_stat1 table so that the query planner believes
|
||||
** the table contains thousands of rows and that the first few
|
||||
** columns are not selective. */
|
||||
ANALYZE;
|
||||
DELETE FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1 VALUES('t1','t1abc','10000 5000 2000 10');
|
||||
ANALYZE sqlite_master;
|
||||
} {}
|
||||
|
||||
# Simple queries that leave the first one or two columns of the
|
||||
# index unconstrainted.
|
||||
#
|
||||
do_execsql_test skipscan1-1.2 {
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE b=345 ORDER BY a;
|
||||
} {abc 345 7 8 | def 345 9 10 |}
|
||||
do_execsql_test skipscan1-1.2eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE b=345 ORDER BY a;
|
||||
} {/* USING INDEX t1abc (ANY(a) AND b=?)*/}
|
||||
do_execsql_test skipscan1-1.2sort {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE b=345 ORDER BY a;
|
||||
} {~/*ORDER BY*/}
|
||||
|
||||
do_execsql_test skipscan1-1.3 {
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE b=345 ORDER BY a DESC;
|
||||
} {def 345 9 10 | abc 345 7 8 |}
|
||||
do_execsql_test skipscan1-1.3eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE b=345 ORDER BY a;
|
||||
} {/* USING INDEX t1abc (ANY(a) AND b=?)*/}
|
||||
do_execsql_test skipscan1-1.3sort {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE b=345 ORDER BY a;
|
||||
} {~/*ORDER BY*/}
|
||||
|
||||
do_execsql_test skipscan1-1.4 {
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE c=6 ORDER BY a, b, c;
|
||||
} {abc 234 6 7 | bcd 100 6 11 |}
|
||||
do_execsql_test skipscan1-1.4eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE c=6 ORDER BY a, b, c;
|
||||
} {/* USING INDEX t1abc (ANY(a) AND ANY(b) AND c=?)*/}
|
||||
do_execsql_test skipscan1-1.4sort {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t1 WHERE c=6 ORDER BY a, b, c;
|
||||
} {~/*ORDER BY*/}
|
||||
|
||||
# Joins
|
||||
#
|
||||
do_execsql_test skipscan1-1.5 {
|
||||
CREATE TABLE t1j(x TEXT, y INTEGER);
|
||||
INSERT INTO t1j VALUES('one',1),('six',6),('ninty-nine',99);
|
||||
SELECT x, a, b, c, d, '|' FROM t1j, t1 WHERE c=y ORDER BY +a;
|
||||
} {six abc 234 6 7 | six bcd 100 6 11 |}
|
||||
do_execsql_test skipscan1-1.5eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT x, a, b, c, d, '|' FROM t1j, t1 WHERE c=y ORDER BY +a;
|
||||
} {/* INDEX t1abc (ANY(a) AND ANY(b) AND c=?)*/}
|
||||
|
||||
do_execsql_test skipscan1-1.6 {
|
||||
SELECT x, a, b, c, d, '|' FROM t1j LEFT JOIN t1 ON c=y ORDER BY +y, +a;
|
||||
} {one {} {} {} {} | six abc 234 6 7 | six bcd 100 6 11 | ninty-nine {} {} {} {} |}
|
||||
do_execsql_test skipscan1-1.6eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT x, a, b, c, d, '|' FROM t1j LEFT JOIN t1 ON c=y ORDER BY +y, +a;
|
||||
} {/* INDEX t1abc (ANY(a) AND ANY(b) AND c=?)*/}
|
||||
|
||||
do_execsql_test skipscan1-2.1 {
|
||||
CREATE TABLE t2(a TEXT, b INT, c INT, d INT,
|
||||
PRIMARY KEY(a,b,c));
|
||||
INSERT INTO t2 SELECT * FROM t1;
|
||||
|
||||
/* Fake the sqlite_stat1 table so that the query planner believes
|
||||
** the table contains thousands of rows and that the first few
|
||||
** columns are not selective. */
|
||||
ANALYZE;
|
||||
UPDATE sqlite_stat1 SET stat='10000 5000 2000 10' WHERE idx NOT NULL;
|
||||
ANALYZE sqlite_master;
|
||||
} {}
|
||||
|
||||
do_execsql_test skipscan1-2.2 {
|
||||
SELECT a,b,c,d,'|' FROM t2 WHERE b=345 ORDER BY a;
|
||||
} {abc 345 7 8 | def 345 9 10 |}
|
||||
do_execsql_test skipscan1-2.2eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t2 WHERE b=345 ORDER BY a;
|
||||
} {/* USING INDEX sqlite_autoindex_t2_1 (ANY(a) AND b=?)*/}
|
||||
do_execsql_test skipscan1-2.2sort {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t2 WHERE b=345 ORDER BY a;
|
||||
} {~/*ORDER BY*/}
|
||||
|
||||
|
||||
do_execsql_test skipscan1-3.1 {
|
||||
CREATE TABLE t3(a TEXT, b INT, c INT, d INT,
|
||||
PRIMARY KEY(a,b,c)) WITHOUT ROWID;
|
||||
INSERT INTO t3 SELECT * FROM t1;
|
||||
|
||||
/* Fake the sqlite_stat1 table so that the query planner believes
|
||||
** the table contains thousands of rows and that the first few
|
||||
** columns are not selective. */
|
||||
ANALYZE;
|
||||
UPDATE sqlite_stat1 SET stat='10000 5000 2000 10' WHERE idx NOT NULL;
|
||||
ANALYZE sqlite_master;
|
||||
} {}
|
||||
|
||||
do_execsql_test skipscan1-3.2 {
|
||||
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
|
||||
} {abc 345 7 8 | def 345 9 10 |}
|
||||
do_execsql_test skipscan1-3.2eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
|
||||
} {/* INDEX sqlite_autoindex_t3_1 (ANY(a) AND b=?)*/}
|
||||
do_execsql_test skipscan1-3.2sort {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
|
||||
} {~/*ORDER BY*/}
|
||||
|
||||
finish_test
|
|
@ -616,11 +616,24 @@ proc do_test {name cmd expected} {
|
|||
# regular expression PATTERN matches the result. "~/PATTERN/" means
|
||||
# the regular expression must not match.
|
||||
if {[string index $expected 0]=="~"} {
|
||||
set re [string map {# {[-0-9.]+}} [string range $expected 2 end-1]]
|
||||
set ok [expr {![regexp $re $result]}]
|
||||
set re [string range $expected 2 end-1]
|
||||
if {[string index $re 0]=="*"} {
|
||||
# If the regular expression begins with * then treat it as a glob instead
|
||||
set ok [string match $re $result]
|
||||
} else {
|
||||
set re [string map {# {[-0-9.]+}} $re]
|
||||
set ok [regexp $re $result]
|
||||
}
|
||||
set ok [expr {!$ok}]
|
||||
} else {
|
||||
set re [string map {# {[-0-9.]+}} [string range $expected 1 end-1]]
|
||||
set ok [regexp $re $result]
|
||||
set re [string range $expected 1 end-1]
|
||||
if {[string index $re 0]=="*"} {
|
||||
# If the regular expression begins with * then treat it as a glob instead
|
||||
set ok [string match $re $result]
|
||||
} else {
|
||||
set re [string map {# {[-0-9.]+}} $re]
|
||||
set ok [regexp $re $result]
|
||||
}
|
||||
}
|
||||
} elseif {[regexp {^~?\*.*\*$} $expected]} {
|
||||
# "expected" is of the form "*GLOB*" then the result if correct if
|
||||
|
|
Loading…
Reference in New Issue