summaryrefslogtreecommitdiffstats
path: root/test/cursorhint.test
blob: a3397b867328a1eb1e77408eb56272f09d6405ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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