Help the parser run faster by avoiding the "explain ::= ." production.
[sqlite.git] / test / cursorhint.test
blobae86120fa8912ed18aaac704e709c45d7708ef98
1 # 2014 July 15
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
6 #    May you do good and not evil.
7 #    May you find forgiveness for yourself and forgive others.
8 #    May you share freely, never taking more than you give.
10 #***********************************************************************
11 # This file implements regression tests for SQLite library.
14 set testdir [file dirname $argv0]
15 source $testdir/tester.tcl
16 set testprefix cursorhint
18 ifcapable !cursorhints {
19   finish_test
20   return
23 do_execsql_test 1.0 {
24   CREATE TABLE t1(a,b,c,d);
25   CREATE TABLE t2(x,y,z);
26   INSERT INTO t1(a,b) VALUES(10, 15);
27   INSERT INTO t1(a,b) VALUES(20, 25);
28   INSERT INTO t2(x,y) VALUES('ten', 'fifteen');
29   INSERT INTO t2(x,y) VALUES('twenty', 'twentyfive');
30   CREATE TABLE t3(id TEXT PRIMARY KEY, a, b, c, d) WITHOUT ROWID;
31   INSERT INTO t3(id,a,b,c,d) SELECT rowid, a, b, c, d FROM t1;
32   PRAGMA automatic_index = 0;
35 # Run EXPLAIN on $sql.  Return a list of P4 values for all $opcode
36 # opcodes.
38 proc p4_of_opcode {db opcode sql} {
39   set res {}
40   $db eval "EXPLAIN $sql" x {
41     if {$x(opcode)==$opcode} {lappend res $x(p4)}
42   }
43   return $res
46 # Run EXPLAIN on $sql.  Return a list of P5 values for all $opcode
47 # opcodes that contain regexp $comment in their comment
49 proc p5_of_opcode {db opcode sql} {
50   set res {}
51   $db eval "EXPLAIN $sql" x {
52     if {$x(opcode)==$opcode} {
53       lappend res $x(p5)
54     }
55   }
56   return $res
59 # Verify that when t1 is in the outer loop and t2 is in the inner loop,
60 # no cursor hints occur for t1 (since it is a full table scan) but that
61 # each t2 access has a cursor hint based on the current t1.a value.
63 do_test 1.1 {
64   p4_of_opcode db CursorHint {
65      SELECT * FROM t1 CROSS JOIN t2 WHERE a=x
66   }
67 } {{EQ(r[1],c0)}}
68 do_test 1.2 {
69   p5_of_opcode db OpenRead {
70      SELECT * FROM t1 CROSS JOIN t2 WHERE a=x
71   }
72 } {00 00}
74 # Do the same test the other way around.
76 do_test 2.1 {
77   p4_of_opcode db CursorHint {
78      SELECT * FROM t2 CROSS JOIN t1 WHERE a=x
79   }
80 } {{EQ(c0,r[1])}}
81 do_test 2.2 {
82   p5_of_opcode db OpenRead {
83      SELECT * FROM t2 CROSS JOIN t1 WHERE a=x
84   }
85 } {00 00}
87 # Various expressions captured by CursorHint
89 do_test 3.1 {
90   p4_of_opcode db CursorHint {
91     SELECT * FROM t1 WHERE a=15 AND c=22 AND rowid!=98
92   }
93 } {AND(AND(EQ(c0,15),EQ(c2,22)),NE(rowid,98))}
94 do_test 3.2 {
95   p4_of_opcode db CursorHint {
96     SELECT * FROM t3 WHERE a<15 AND b>22 AND id!=98
97   }
98 } {AND(AND(LT(c1,15),GT(c2,22)),NE(c0,98))}
100 # Indexed queries
102 do_test 4.1asc {
103   db eval {
104     CREATE INDEX t1bc ON t1(b,c);
105     CREATE INDEX t2yz ON t2(y,z);
106   }
107   p4_of_opcode db CursorHint {
108     SELECT * FROM t1 WHERE b>11 ORDER BY b ASC;
109   }
110 } {}
111 do_test 4.1desc {
112   p4_of_opcode db CursorHint {
113     SELECT * FROM t1 WHERE b>11 ORDER BY b DESC;
114   }
115 } {GT(c0,11)}
116 do_test 4.2 {
117   p5_of_opcode db OpenRead {
118     SELECT * FROM t1 WHERE b>11;
119   }
120 } {02 00}
121 do_test 4.3asc {
122   p4_of_opcode db CursorHint {
123     SELECT c FROM t1 WHERE b<11 ORDER BY b ASC;
124   }
125 } {LT(c0,11)}
126 do_test 4.3desc {
127   p4_of_opcode db CursorHint {
128     SELECT c FROM t1 WHERE b<11 ORDER BY b DESC;
129   }
130 } {}
131 do_test 4.4 {
132   p5_of_opcode db OpenRead {
133     SELECT c FROM t1 WHERE b<11;
134   }
135 } {00}
137 do_test 4.5asc {
138   p4_of_opcode db CursorHint {
139     SELECT c FROM t1 WHERE b>=10 AND b<=20 ORDER BY b ASC;
140   }
141 } {LE(c0,20)}
142 do_test 4.5desc {
143   p4_of_opcode db CursorHint {
144     SELECT c FROM t1 WHERE b>=10 AND b<=20 ORDER BY b DESC;
145   }
146 } {GE(c0,10)}
148 # If there are any equality terms used in the constraint, then all terms
149 # should be hinted.
151 do_test 4.6asc {
152   p4_of_opcode db CursorHint {
153     SELECT rowid FROM t1 WHERE b=22 AND c>=10 AND c<=20 ORDER BY b,c ASC;
154   }
155 } {AND(AND(EQ(c0,22),GE(c1,10)),LE(c1,20))}
156 do_test 4.6desc {
157   p4_of_opcode db CursorHint {
158     SELECT rowid FROM t1 WHERE b=22 AND c>=10 AND c<=20 ORDER BY b,c DESC;
159   }
160 } {AND(AND(EQ(c0,22),GE(c1,10)),LE(c1,20))}
162 finish_test