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