summaryrefslogtreecommitdiffstats
path: root/test/cursorhint.test
diff options
context:
space:
mode:
Diffstat (limited to 'test/cursorhint.test')
-rw-r--r--test/cursorhint.test162
1 files changed, 162 insertions, 0 deletions
diff --git a/test/cursorhint.test b/test/cursorhint.test
new file mode 100644
index 0000000..a3397b8
--- /dev/null
+++ b/test/cursorhint.test
@@ -0,0 +1,162 @@
+# 2014 July 15
+#
+# 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 regression tests for SQLite library.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix cursorhint
+
+ifcapable !cursorhints {
+ finish_test
+ return
+}
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a,b,c,d);
+ CREATE TABLE t2(x,y,z);
+ INSERT INTO t1(a,b) VALUES(10, 15);
+ INSERT INTO t1(a,b) VALUES(20, 25);
+ INSERT INTO t2(x,y) VALUES('ten', 'fifteen');
+ INSERT INTO t2(x,y) VALUES('twenty', 'twentyfive');
+ CREATE TABLE t3(id TEXT PRIMARY KEY, a, b, c, d) WITHOUT ROWID;
+ INSERT INTO t3(id,a,b,c,d) SELECT rowid, a, b, c, d FROM t1;
+ PRAGMA automatic_index = 0;
+}
+
+# Run EXPLAIN on $sql. Return a list of P4 values for all $opcode
+# opcodes.
+#
+proc p4_of_opcode {db opcode sql} {
+ set res {}
+ $db eval "EXPLAIN $sql" x {
+ if {$x(opcode)==$opcode} {lappend res $x(p4)}
+ }
+ return $res
+}
+
+# Run EXPLAIN on $sql. Return a list of P5 values for all $opcode
+# opcodes that contain regexp $comment in their comment
+#
+proc p5_of_opcode {db opcode sql} {
+ set res {}
+ $db eval "EXPLAIN $sql" x {
+ if {$x(opcode)==$opcode} {
+ lappend res $x(p5)
+ }
+ }
+ return $res
+}
+
+# Verify that when t1 is in the outer loop and t2 is in the inner loop,
+# no cursor hints occur for t1 (since it is a full table scan) but that
+# each t2 access has a cursor hint based on the current t1.a value.
+#
+do_test 1.1 {
+ p4_of_opcode db CursorHint {
+ SELECT * FROM t1 CROSS JOIN t2 WHERE a=x
+ }
+} {{EQ(r[1],c0)}}
+do_test 1.2 {
+ p5_of_opcode db OpenRead {
+ SELECT * FROM t1 CROSS JOIN t2 WHERE a=x
+ }
+} {0 0}
+
+# Do the same test the other way around.
+#
+do_test 2.1 {
+ p4_of_opcode db CursorHint {
+ SELECT * FROM t2 CROSS JOIN t1 WHERE a=x
+ }
+} {{EQ(c0,r[1])}}
+do_test 2.2 {
+ p5_of_opcode db OpenRead {
+ SELECT * FROM t2 CROSS JOIN t1 WHERE a=x
+ }
+} {0 0}
+
+# Various expressions captured by CursorHint
+#
+do_test 3.1 {
+ p4_of_opcode db CursorHint {
+ SELECT * FROM t1 WHERE a=15 AND c=22 AND rowid!=98
+ }
+} {AND(AND(EQ(c0,15),EQ(c2,22)),NE(rowid,98))}
+do_test 3.2 {
+ p4_of_opcode db CursorHint {
+ SELECT * FROM t3 WHERE a<15 AND b>22 AND id!=98
+ }
+} {AND(AND(LT(c1,15),GT(c2,22)),NE(c0,98))}
+
+# Indexed queries
+#
+do_test 4.1asc {
+ db eval {
+ CREATE INDEX t1bc ON t1(b,c);
+ CREATE INDEX t2yz ON t2(y,z);
+ }
+ p4_of_opcode db CursorHint {
+ SELECT * FROM t1 WHERE b>11 ORDER BY b ASC;
+ }
+} {}
+do_test 4.1desc {
+ p4_of_opcode db CursorHint {
+ SELECT * FROM t1 WHERE b>11 ORDER BY b DESC;
+ }
+} {GT(c0,11)}
+do_test 4.2 {
+ p5_of_opcode db OpenRead {
+ SELECT * FROM t1 WHERE b>11;
+ }
+} {2 0}
+do_test 4.3asc {
+ p4_of_opcode db CursorHint {
+ SELECT c FROM t1 WHERE b<11 ORDER BY b ASC;
+ }
+} {LT(c0,11)}
+do_test 4.3desc {
+ p4_of_opcode db CursorHint {
+ SELECT c FROM t1 WHERE b<11 ORDER BY b DESC;
+ }
+} {}
+do_test 4.4 {
+ p5_of_opcode db OpenRead {
+ SELECT c FROM t1 WHERE b<11;
+ }
+} {0}
+
+do_test 4.5asc {
+ p4_of_opcode db CursorHint {
+ SELECT c FROM t1 WHERE b>=10 AND b<=20 ORDER BY b ASC;
+ }
+} {LE(c0,20)}
+do_test 4.5desc {
+ p4_of_opcode db CursorHint {
+ SELECT c FROM t1 WHERE b>=10 AND b<=20 ORDER BY b DESC;
+ }
+} {GE(c0,10)}
+
+# If there are any equality terms used in the constraint, then all terms
+# should be hinted.
+#
+do_test 4.6asc {
+ p4_of_opcode db CursorHint {
+ SELECT rowid FROM t1 WHERE b=22 AND c>=10 AND c<=20 ORDER BY b,c ASC;
+ }
+} {AND(AND(EQ(c0,22),GE(c1,10)),LE(c1,20))}
+do_test 4.6desc {
+ p4_of_opcode db CursorHint {
+ SELECT rowid FROM t1 WHERE b=22 AND c>=10 AND c<=20 ORDER BY b,c DESC;
+ }
+} {AND(AND(EQ(c0,22),GE(c1,10)),LE(c1,20))}
+
+finish_test