]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add test cases for skip-scan. Enhance "do_test" so that if the expected result
authordrh <drh@noemail.net>
Wed, 13 Nov 2013 15:32:15 +0000 (15:32 +0000)
committerdrh <drh@noemail.net>
Wed, 13 Nov 2013 15:32:15 +0000 (15:32 +0000)
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

manifest
manifest.uuid
src/analyze.c
test/skipscan1.test [new file with mode: 0644]
test/tester.tcl

index 5d4c908bea5819ed355247101bafad03f53df2e2..7158caf1b6f85c625f56c4d27b28d8a3e8198b47 100644 (file)
--- a/manifest
+++ b/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
index 309dd4f350a77dc51809a02b16fc458329b743b7..1dae9064379879fd8280a16eab3746f6e5cc424f 100644 (file)
@@ -1 +1 @@
-27dd5993d1ae5625eb94bf406421eb390d001be9
\ No newline at end of file
+d3e6e9b2a74074c05429d3c341c23525504351ab
\ No newline at end of file
index f1094f79f9a1406440d77f26ec983b5e006fb120..3d5c4f6becaa4d63bbe5618342b7240006964172 100644 (file)
@@ -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];
 
diff --git a/test/skipscan1.test b/test/skipscan1.test
new file mode 100644 (file)
index 0000000..0931592
--- /dev/null
@@ -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
index 2d047be5f4e2496b0bb642988d4f20c2989c8b10..c1272210d0b42c9518bac17bb1779b3cfedbae8e 100644 (file)
@@ -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