blob: 3e721a087713e0c0223e61e5ea97d2dbc57f73b1 [file] [log] [blame]
dan937d0de2009-10-15 18:35:38 +00001# 2009 August 06
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#
12# This file implements regression tests for SQLite library. This file
dan1d2ce4f2009-10-19 18:11:09 +000013# implements tests for range and LIKE constraints that use bound variables
14# instead of literal constant arguments.
dan937d0de2009-10-15 18:35:38 +000015#
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
dan4eed0532015-04-20 15:13:08 +000019set testprefix analyze3
dan937d0de2009-10-15 18:35:38 +000020
dan8ad169a2013-08-12 20:14:04 +000021ifcapable !stat4&&!stat3 {
dan937d0de2009-10-15 18:35:38 +000022 finish_test
23 return
24}
25
26#----------------------------------------------------------------------
27# Test Organization:
28#
29# analyze3-1.*: Test that the values of bound parameters are considered
30# in the same way as constants when planning queries that
31# use range constraints.
32#
33# analyze3-2.*: Test that the values of bound parameters are considered
34# in the same way as constants when planning queries that
35# use LIKE expressions in the WHERE clause.
36#
dan1d2ce4f2009-10-19 18:11:09 +000037# analyze3-3.*: Test that binding to a variable does not invalidate the
38# query plan when there is no way in which replanning the
39# query may produce a superior outcome.
dan937d0de2009-10-15 18:35:38 +000040#
41# analyze3-4.*: Test that SQL or authorization callback errors occuring
dan1d2ce4f2009-10-19 18:11:09 +000042# within sqlite3Reprepare() are handled correctly.
dan937d0de2009-10-15 18:35:38 +000043#
danc94b8592009-10-20 07:01:24 +000044# analyze3-5.*: Check that the query plans of applicable statements are
45# invalidated if the values of SQL parameter are modified
46# using the clear_bindings() or transfer_bindings() APIs.
dan2acbc0d2013-08-01 17:43:35 +000047#
48# analyze3-6.*: Test that the problem fixed by commit [127a5b776d] is fixed.
danc94b8592009-10-20 07:01:24 +000049#
dan4eed0532015-04-20 15:13:08 +000050# analyze3-7.*: Test that some memory leaks discovered by fuzz testing
51# have been fixed.
52#
dan937d0de2009-10-15 18:35:38 +000053
54proc getvar {varname} { uplevel #0 set $varname }
55db function var getvar
56
57proc eqp {sql {db db}} {
58 uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
59}
60
61proc sf_execsql {sql {db db}} {
62 set ::sqlite_search_count 0
63 set r [uplevel [list execsql $sql $db]]
64
65 concat $::sqlite_search_count [$db status step] $r
66}
67
68#-------------------------------------------------------------------------
69#
70# analyze3-1.1.1:
71# Create a table with two columns. Populate the first column (affinity
72# INTEGER) with integer values from 100 to 1100. Create an index on this
73# column. ANALYZE the table.
74#
75# analyze3-1.1.2 - 3.1.3
76# Show that there are two possible plans for querying the table with
77# a range constraint on the indexed column - "full table scan" or "use
78# the index". When the range is specified using literal values, SQLite
drh74e7c8f2011-10-21 19:06:32 +000079# is able to pick the best plan based on the samples in sqlite_stat3.
dan937d0de2009-10-15 18:35:38 +000080#
81# analyze3-1.1.4 - 3.1.9
82# Show that using SQL variables produces the same results as using
dan1d2ce4f2009-10-19 18:11:09 +000083# literal values to constrain the range scan.
dan937d0de2009-10-15 18:35:38 +000084#
85# These tests also check that the compiler code considers column
86# affinities when estimating the number of rows scanned by the "use
87# index strategy".
88#
89do_test analyze3-1.1.1 {
90 execsql {
91 BEGIN;
92 CREATE TABLE t1(x INTEGER, y);
93 CREATE INDEX i1 ON t1(x);
94 }
95 for {set i 0} {$i < 1000} {incr i} {
96 execsql { INSERT INTO t1 VALUES($i+100, $i) }
97 }
98 execsql {
99 COMMIT;
100 ANALYZE;
101 }
dan8ad169a2013-08-12 20:14:04 +0000102
103 ifcapable stat4 {
104 execsql { SELECT count(*)>0 FROM sqlite_stat4; }
105 } else {
106 execsql { SELECT count(*)>0 FROM sqlite_stat3; }
dandd6e1f12013-08-10 19:08:30 +0000107 }
108} {1}
dan937d0de2009-10-15 18:35:38 +0000109
danb51926e2014-04-28 10:00:59 +0000110do_execsql_test analyze3-1.1.x {
111 SELECT count(*) FROM t1 WHERE x>200 AND x<300;
112 SELECT count(*) FROM t1 WHERE x>0 AND x<1100;
113} {99 1000}
114
115# The first of the following two SELECT statements visits 99 rows. So
116# it is better to use the index. But the second visits every row in
117# the table (1000 in total) so it is better to do a full-table scan.
118#
dan39854792010-11-15 16:12:58 +0000119do_eqp_test analyze3-1.1.2 {
120 SELECT sum(y) FROM t1 WHERE x>200 AND x<300
drh5822d6f2013-06-10 23:30:09 +0000121} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
dan39854792010-11-15 16:12:58 +0000122do_eqp_test analyze3-1.1.3 {
123 SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
danb51926e2014-04-28 10:00:59 +0000124} {0 0 0 {SCAN TABLE t1}}
dan937d0de2009-10-15 18:35:38 +0000125
drh169dd922017-06-26 13:57:49 +0000126# 2017-06-26: Verify that the SQLITE_DBCONFIG_ENABLE_QPSG setting disables
127# the use of bound parameters by STAT4
128#
129db cache flush
130unset -nocomplain l
131unset -nocomplain u
132do_eqp_test analyze3-1.1.3.100 {
133 SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
134} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
135set l 200
136set u 300
137do_eqp_test analyze3-1.1.3.101 {
138 SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
139} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
140set l 0
141set u 1100
142do_eqp_test analyze3-1.1.3.102 {
143 SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
144} {0 0 0 {SCAN TABLE t1}}
145db cache flush
146sqlite3_db_config db ENABLE_QPSG 1
147do_eqp_test analyze3-1.1.3.103 {
148 SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
149} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
150db cache flush
151sqlite3_db_config db ENABLE_QPSG 0
152do_eqp_test analyze3-1.1.3.104 {
153 SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
154} {0 0 0 {SCAN TABLE t1}}
155
dan937d0de2009-10-15 18:35:38 +0000156do_test analyze3-1.1.4 {
157 sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
158} {199 0 14850}
159do_test analyze3-1.1.5 {
160 set l [string range "200" 0 end]
161 set u [string range "300" 0 end]
162 sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
163} {199 0 14850}
164do_test analyze3-1.1.6 {
165 set l [expr int(200)]
166 set u [expr int(300)]
167 sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
168} {199 0 14850}
169do_test analyze3-1.1.7 {
170 sf_execsql { SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 }
danb51926e2014-04-28 10:00:59 +0000171} {999 999 499500}
dan937d0de2009-10-15 18:35:38 +0000172do_test analyze3-1.1.8 {
173 set l [string range "0" 0 end]
174 set u [string range "1100" 0 end]
175 sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
danb51926e2014-04-28 10:00:59 +0000176} {999 999 499500}
dan937d0de2009-10-15 18:35:38 +0000177do_test analyze3-1.1.9 {
178 set l [expr int(0)]
179 set u [expr int(1100)]
180 sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
danb51926e2014-04-28 10:00:59 +0000181} {999 999 499500}
dan937d0de2009-10-15 18:35:38 +0000182
183
184# The following tests are similar to the block above. The difference is
185# that the indexed column has TEXT affinity in this case. In the tests
186# above the affinity is INTEGER.
187#
188do_test analyze3-1.2.1 {
189 execsql {
190 BEGIN;
191 CREATE TABLE t2(x TEXT, y);
192 INSERT INTO t2 SELECT * FROM t1;
193 CREATE INDEX i2 ON t2(x);
194 COMMIT;
195 ANALYZE;
196 }
197} {}
danb51926e2014-04-28 10:00:59 +0000198do_execsql_test analyze3-2.1.x {
199 SELECT count(*) FROM t2 WHERE x>1 AND x<2;
200 SELECT count(*) FROM t2 WHERE x>0 AND x<99;
201} {200 990}
dan39854792010-11-15 16:12:58 +0000202do_eqp_test analyze3-1.2.2 {
203 SELECT sum(y) FROM t2 WHERE x>1 AND x<2
drh5822d6f2013-06-10 23:30:09 +0000204} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}}
dan39854792010-11-15 16:12:58 +0000205do_eqp_test analyze3-1.2.3 {
206 SELECT sum(y) FROM t2 WHERE x>0 AND x<99
danb51926e2014-04-28 10:00:59 +0000207} {0 0 0 {SCAN TABLE t2}}
208
dan937d0de2009-10-15 18:35:38 +0000209do_test analyze3-1.2.4 {
210 sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
211} {161 0 4760}
212do_test analyze3-1.2.5 {
213 set l [string range "12" 0 end]
214 set u [string range "20" 0 end]
215 sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
216} {161 0 text text 4760}
217do_test analyze3-1.2.6 {
218 set l [expr int(12)]
219 set u [expr int(20)]
220 sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
221} {161 0 integer integer 4760}
222do_test analyze3-1.2.7 {
223 sf_execsql { SELECT sum(y) FROM t2 WHERE x>0 AND x<99 }
danb51926e2014-04-28 10:00:59 +0000224} {999 999 490555}
dan937d0de2009-10-15 18:35:38 +0000225do_test analyze3-1.2.8 {
226 set l [string range "0" 0 end]
227 set u [string range "99" 0 end]
228 sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
danb51926e2014-04-28 10:00:59 +0000229} {999 999 text text 490555}
dan937d0de2009-10-15 18:35:38 +0000230do_test analyze3-1.2.9 {
231 set l [expr int(0)]
232 set u [expr int(99)]
233 sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
danb51926e2014-04-28 10:00:59 +0000234} {999 999 integer integer 490555}
dan937d0de2009-10-15 18:35:38 +0000235
236# Same tests a third time. This time, column x has INTEGER affinity and
237# is not the leftmost column of the table. This triggered a bug causing
238# SQLite to use sub-optimal query plans in 3.6.18 and earlier.
239#
240do_test analyze3-1.3.1 {
241 execsql {
242 BEGIN;
243 CREATE TABLE t3(y TEXT, x INTEGER);
244 INSERT INTO t3 SELECT y, x FROM t1;
245 CREATE INDEX i3 ON t3(x);
246 COMMIT;
247 ANALYZE;
248 }
249} {}
danb51926e2014-04-28 10:00:59 +0000250do_execsql_test analyze3-1.3.x {
251 SELECT count(*) FROM t3 WHERE x>200 AND x<300;
252 SELECT count(*) FROM t3 WHERE x>0 AND x<1100
253} {99 1000}
dan39854792010-11-15 16:12:58 +0000254do_eqp_test analyze3-1.3.2 {
255 SELECT sum(y) FROM t3 WHERE x>200 AND x<300
drh5822d6f2013-06-10 23:30:09 +0000256} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}}
dan39854792010-11-15 16:12:58 +0000257do_eqp_test analyze3-1.3.3 {
258 SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
danb51926e2014-04-28 10:00:59 +0000259} {0 0 0 {SCAN TABLE t3}}
dan937d0de2009-10-15 18:35:38 +0000260
261do_test analyze3-1.3.4 {
262 sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
263} {199 0 14850}
264do_test analyze3-1.3.5 {
265 set l [string range "200" 0 end]
266 set u [string range "300" 0 end]
267 sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
268} {199 0 14850}
269do_test analyze3-1.3.6 {
270 set l [expr int(200)]
271 set u [expr int(300)]
272 sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
273} {199 0 14850}
274do_test analyze3-1.3.7 {
275 sf_execsql { SELECT sum(y) FROM t3 WHERE x>0 AND x<1100 }
danb51926e2014-04-28 10:00:59 +0000276} {999 999 499500}
dan937d0de2009-10-15 18:35:38 +0000277do_test analyze3-1.3.8 {
278 set l [string range "0" 0 end]
279 set u [string range "1100" 0 end]
280 sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
danb51926e2014-04-28 10:00:59 +0000281} {999 999 499500}
dan937d0de2009-10-15 18:35:38 +0000282do_test analyze3-1.3.9 {
283 set l [expr int(0)]
284 set u [expr int(1100)]
285 sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
danb51926e2014-04-28 10:00:59 +0000286} {999 999 499500}
dan937d0de2009-10-15 18:35:38 +0000287
288#-------------------------------------------------------------------------
289# Test that the values of bound SQL variables may be used for the LIKE
290# optimization.
291#
292drop_all_tables
293do_test analyze3-2.1 {
294 execsql {
295 PRAGMA case_sensitive_like=off;
296 BEGIN;
297 CREATE TABLE t1(a, b TEXT COLLATE nocase);
298 CREATE INDEX i1 ON t1(b);
299 }
300 for {set i 0} {$i < 1000} {incr i} {
301 set t ""
302 append t [lindex {a b c d e f g h i j} [expr $i/100]]
303 append t [lindex {a b c d e f g h i j} [expr ($i/10)%10]]
304 append t [lindex {a b c d e f g h i j} [expr ($i%10)]]
305 execsql { INSERT INTO t1 VALUES($i, $t) }
306 }
307 execsql COMMIT
308} {}
dan39854792010-11-15 16:12:58 +0000309do_eqp_test analyze3-2.2 {
310 SELECT count(a) FROM t1 WHERE b LIKE 'a%'
drh5822d6f2013-06-10 23:30:09 +0000311} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?)}}
dan39854792010-11-15 16:12:58 +0000312do_eqp_test analyze3-2.3 {
313 SELECT count(a) FROM t1 WHERE b LIKE '%a'
drh5822d6f2013-06-10 23:30:09 +0000314} {0 0 0 {SCAN TABLE t1}}
dan937d0de2009-10-15 18:35:38 +0000315
drh41d2e662015-12-01 21:23:07 +0000316# Return the first argument if like_match_blobs is true (the default)
317# or the second argument if not
318#
319proc ilmb {a b} {
320 ifcapable like_match_blobs {return $a}
321 return $b
322}
323
dan937d0de2009-10-15 18:35:38 +0000324do_test analyze3-2.4 {
325 sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE 'a%' }
drh41d2e662015-12-01 21:23:07 +0000326} [list [ilmb 102 101] 0 100]
dan937d0de2009-10-15 18:35:38 +0000327do_test analyze3-2.5 {
328 sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE '%a' }
329} {999 999 100}
330
drha9c18a92015-03-06 20:49:52 +0000331do_test analyze3-2.6 {
dan937d0de2009-10-15 18:35:38 +0000332 set like "a%"
333 sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
drh41d2e662015-12-01 21:23:07 +0000334} [list [ilmb 102 101] 0 100]
drha9c18a92015-03-06 20:49:52 +0000335do_test analyze3-2.7 {
dan937d0de2009-10-15 18:35:38 +0000336 set like "%a"
337 sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
338} {999 999 100}
drha9c18a92015-03-06 20:49:52 +0000339do_test analyze3-2.8 {
drh93ee23c2010-07-22 12:33:57 +0000340 set like "a"
341 sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
drh41d2e662015-12-01 21:23:07 +0000342} [list [ilmb 102 101] 0 0]
drha9c18a92015-03-06 20:49:52 +0000343do_test analyze3-2.9 {
drh93ee23c2010-07-22 12:33:57 +0000344 set like "ab"
345 sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
drh41d2e662015-12-01 21:23:07 +0000346} [list [ilmb 12 11] 0 0]
drha9c18a92015-03-06 20:49:52 +0000347do_test analyze3-2.10 {
drh93ee23c2010-07-22 12:33:57 +0000348 set like "abc"
349 sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
drh41d2e662015-12-01 21:23:07 +0000350} [list [ilmb 3 2] 0 1]
drha9c18a92015-03-06 20:49:52 +0000351do_test analyze3-2.11 {
drh93ee23c2010-07-22 12:33:57 +0000352 set like "a_c"
353 sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
drh41d2e662015-12-01 21:23:07 +0000354} [list [ilmb 102 101] 0 10]
dan937d0de2009-10-15 18:35:38 +0000355
356
357#-------------------------------------------------------------------------
dan1d2ce4f2009-10-19 18:11:09 +0000358# This block of tests checks that statements are correctly marked as
359# expired when the values bound to any parameters that may affect the
360# query plan are modified.
dan937d0de2009-10-15 18:35:38 +0000361#
362drop_all_tables
363db auth auth
364proc auth {args} {
365 set ::auth 1
366 return SQLITE_OK
367}
368
dan937d0de2009-10-15 18:35:38 +0000369do_test analyze3-3.1 {
370 execsql {
371 BEGIN;
372 CREATE TABLE t1(a, b, c);
373 CREATE INDEX i1 ON t1(b);
374 }
375 for {set i 0} {$i < 100} {incr i} {
376 execsql { INSERT INTO t1 VALUES($i, $i, $i) }
377 }
378 execsql COMMIT
379 execsql ANALYZE
380} {}
dan937d0de2009-10-15 18:35:38 +0000381do_test analyze3-3.2.1 {
382 set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE b>?" -1 dummy]
dan1d2ce4f2009-10-19 18:11:09 +0000383 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000384} {0}
385do_test analyze3-3.2.2 {
dand893ed82009-10-16 15:59:35 +0000386 sqlite3_bind_text $S 1 "abc" 3
dan1d2ce4f2009-10-19 18:11:09 +0000387 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000388} {1}
dan937d0de2009-10-15 18:35:38 +0000389do_test analyze3-3.2.4 {
390 sqlite3_finalize $S
391} {SQLITE_OK}
392
dan1d2ce4f2009-10-19 18:11:09 +0000393do_test analyze3-3.2.5 {
dan937d0de2009-10-15 18:35:38 +0000394 set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE b=?" -1 dummy]
dan1d2ce4f2009-10-19 18:11:09 +0000395 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000396} {0}
dan1d2ce4f2009-10-19 18:11:09 +0000397do_test analyze3-3.2.6 {
dand893ed82009-10-16 15:59:35 +0000398 sqlite3_bind_text $S 1 "abc" 3
dan1d2ce4f2009-10-19 18:11:09 +0000399 sqlite3_expired $S
drh5822d6f2013-06-10 23:30:09 +0000400} {1}
dan1d2ce4f2009-10-19 18:11:09 +0000401do_test analyze3-3.2.7 {
dan937d0de2009-10-15 18:35:38 +0000402 sqlite3_finalize $S
403} {SQLITE_OK}
404
405do_test analyze3-3.4.1 {
406 set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
dan1d2ce4f2009-10-19 18:11:09 +0000407 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000408} {0}
409do_test analyze3-3.4.2 {
dand893ed82009-10-16 15:59:35 +0000410 sqlite3_bind_text $S 1 "abc" 3
dan1d2ce4f2009-10-19 18:11:09 +0000411 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000412} {0}
413do_test analyze3-3.4.3 {
dand893ed82009-10-16 15:59:35 +0000414 sqlite3_bind_text $S 2 "def" 3
dan1d2ce4f2009-10-19 18:11:09 +0000415 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000416} {1}
417do_test analyze3-3.4.4 {
dand893ed82009-10-16 15:59:35 +0000418 sqlite3_bind_text $S 2 "ghi" 3
dan1d2ce4f2009-10-19 18:11:09 +0000419 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000420} {1}
421do_test analyze3-3.4.5 {
dan1d2ce4f2009-10-19 18:11:09 +0000422 sqlite3_expired $S
423} {1}
dan937d0de2009-10-15 18:35:38 +0000424do_test analyze3-3.4.6 {
425 sqlite3_finalize $S
426} {SQLITE_OK}
427
428do_test analyze3-3.5.1 {
429 set S [sqlite3_prepare_v2 db {
430 SELECT * FROM t1 WHERE a IN (
431 ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10,
432 ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
433 ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30, ?31
434 ) AND b>?32;
435 } -1 dummy]
dan1d2ce4f2009-10-19 18:11:09 +0000436 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000437} {0}
438do_test analyze3-3.5.2 {
dand893ed82009-10-16 15:59:35 +0000439 sqlite3_bind_text $S 31 "abc" 3
dan1d2ce4f2009-10-19 18:11:09 +0000440 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000441} {0}
442do_test analyze3-3.5.3 {
dand893ed82009-10-16 15:59:35 +0000443 sqlite3_bind_text $S 32 "def" 3
dan1d2ce4f2009-10-19 18:11:09 +0000444 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000445} {1}
dan937d0de2009-10-15 18:35:38 +0000446do_test analyze3-3.5.5 {
447 sqlite3_finalize $S
448} {SQLITE_OK}
449
450do_test analyze3-3.6.1 {
451 set S [sqlite3_prepare_v2 db {
452 SELECT * FROM t1 WHERE a IN (
453 ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10,
454 ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
455 ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30, ?31, ?32
456 ) AND b>?33;
457 } -1 dummy]
dan1d2ce4f2009-10-19 18:11:09 +0000458 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000459} {0}
460do_test analyze3-3.6.2 {
dand893ed82009-10-16 15:59:35 +0000461 sqlite3_bind_text $S 32 "abc" 3
dan1d2ce4f2009-10-19 18:11:09 +0000462 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000463} {1}
464do_test analyze3-3.6.3 {
dand893ed82009-10-16 15:59:35 +0000465 sqlite3_bind_text $S 33 "def" 3
dan1d2ce4f2009-10-19 18:11:09 +0000466 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000467} {1}
dan937d0de2009-10-15 18:35:38 +0000468do_test analyze3-3.6.5 {
469 sqlite3_finalize $S
470} {SQLITE_OK}
471
472do_test analyze3-3.7.1 {
dan937d0de2009-10-15 18:35:38 +0000473 set S [sqlite3_prepare_v2 db {
474 SELECT * FROM t1 WHERE a IN (
475 ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?33,
476 ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
477 ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30, ?31, ?32
478 ) AND b>?10;
479 } -1 dummy]
dan1d2ce4f2009-10-19 18:11:09 +0000480 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000481} {0}
482do_test analyze3-3.7.2 {
dand893ed82009-10-16 15:59:35 +0000483 sqlite3_bind_text $S 32 "abc" 3
dan1d2ce4f2009-10-19 18:11:09 +0000484 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000485} {0}
486do_test analyze3-3.7.3 {
dand893ed82009-10-16 15:59:35 +0000487 sqlite3_bind_text $S 33 "def" 3
dan1d2ce4f2009-10-19 18:11:09 +0000488 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000489} {0}
490do_test analyze3-3.7.4 {
dand893ed82009-10-16 15:59:35 +0000491 sqlite3_bind_text $S 10 "def" 3
dan1d2ce4f2009-10-19 18:11:09 +0000492 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000493} {1}
dan937d0de2009-10-15 18:35:38 +0000494do_test analyze3-3.7.6 {
495 sqlite3_finalize $S
496} {SQLITE_OK}
497
498do_test analyze3-3.8.1 {
499 execsql {
500 CREATE TABLE t4(x, y TEXT COLLATE NOCASE);
501 CREATE INDEX i4 ON t4(y);
502 }
503} {}
504do_test analyze3-3.8.2 {
505 set S [sqlite3_prepare_v2 db {
506 SELECT * FROM t4 WHERE x != ? AND y LIKE ?
507 } -1 dummy]
dan1d2ce4f2009-10-19 18:11:09 +0000508 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000509} {0}
510do_test analyze3-3.8.3 {
dand893ed82009-10-16 15:59:35 +0000511 sqlite3_bind_text $S 1 "abc" 3
dan1d2ce4f2009-10-19 18:11:09 +0000512 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000513} {0}
514do_test analyze3-3.8.4 {
dand893ed82009-10-16 15:59:35 +0000515 sqlite3_bind_text $S 2 "def" 3
dan937d0de2009-10-15 18:35:38 +0000516 sqlite3_expired $S
dan1d2ce4f2009-10-19 18:11:09 +0000517} {1}
dan937d0de2009-10-15 18:35:38 +0000518do_test analyze3-3.8.7 {
dand893ed82009-10-16 15:59:35 +0000519 sqlite3_bind_text $S 2 "ghi%" 4
dan937d0de2009-10-15 18:35:38 +0000520 sqlite3_expired $S
dan1d2ce4f2009-10-19 18:11:09 +0000521} {1}
dan937d0de2009-10-15 18:35:38 +0000522do_test analyze3-3.8.8 {
dan1d2ce4f2009-10-19 18:11:09 +0000523 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000524} {1}
525do_test analyze3-3.8.9 {
dand893ed82009-10-16 15:59:35 +0000526 sqlite3_bind_text $S 2 "ghi%def" 7
dan937d0de2009-10-15 18:35:38 +0000527 sqlite3_expired $S
528} {1}
529do_test analyze3-3.8.10 {
dan1d2ce4f2009-10-19 18:11:09 +0000530 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000531} {1}
532do_test analyze3-3.8.11 {
dand893ed82009-10-16 15:59:35 +0000533 sqlite3_bind_text $S 2 "%ab" 3
dan937d0de2009-10-15 18:35:38 +0000534 sqlite3_expired $S
535} {1}
536do_test analyze3-3.8.12 {
dan1d2ce4f2009-10-19 18:11:09 +0000537 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000538} {1}
539do_test analyze3-3.8.12 {
dand893ed82009-10-16 15:59:35 +0000540 sqlite3_bind_text $S 2 "%de" 3
dan937d0de2009-10-15 18:35:38 +0000541 sqlite3_expired $S
dan1d2ce4f2009-10-19 18:11:09 +0000542} {1}
dan937d0de2009-10-15 18:35:38 +0000543do_test analyze3-3.8.13 {
dan1d2ce4f2009-10-19 18:11:09 +0000544 sqlite3_expired $S
dan937d0de2009-10-15 18:35:38 +0000545} {1}
546do_test analyze3-3.8.14 {
547 sqlite3_finalize $S
548} {SQLITE_OK}
549
550#-------------------------------------------------------------------------
551# These tests check that errors encountered while repreparing an SQL
dan1d2ce4f2009-10-19 18:11:09 +0000552# statement within sqlite3Reprepare() are handled correctly.
dan937d0de2009-10-15 18:35:38 +0000553#
554
dan1d2ce4f2009-10-19 18:11:09 +0000555# Check a schema error.
dan937d0de2009-10-15 18:35:38 +0000556#
557do_test analyze3-4.1.1 {
558 set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
dan1d2ce4f2009-10-19 18:11:09 +0000559 sqlite3_step $S
560} {SQLITE_DONE}
dan937d0de2009-10-15 18:35:38 +0000561do_test analyze3-4.1.2 {
dan1d2ce4f2009-10-19 18:11:09 +0000562 sqlite3_reset $S
dand893ed82009-10-16 15:59:35 +0000563 sqlite3_bind_text $S 2 "abc" 3
dan937d0de2009-10-15 18:35:38 +0000564 execsql { DROP TABLE t1 }
dan937d0de2009-10-15 18:35:38 +0000565 sqlite3_step $S
drhcda455b2010-02-24 19:23:56 +0000566} {SQLITE_ERROR}
dan1d2ce4f2009-10-19 18:11:09 +0000567do_test analyze3-4.1.3 {
dan937d0de2009-10-15 18:35:38 +0000568 sqlite3_finalize $S
drhcda455b2010-02-24 19:23:56 +0000569} {SQLITE_ERROR}
dan937d0de2009-10-15 18:35:38 +0000570
571# Check an authorization error.
572#
573do_test analyze3-4.2.1 {
574 execsql {
575 BEGIN;
576 CREATE TABLE t1(a, b, c);
577 CREATE INDEX i1 ON t1(b);
578 }
579 for {set i 0} {$i < 100} {incr i} {
580 execsql { INSERT INTO t1 VALUES($i, $i, $i) }
581 }
582 execsql COMMIT
583 execsql ANALYZE
584 set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
dan1d2ce4f2009-10-19 18:11:09 +0000585 sqlite3_step $S
586} {SQLITE_DONE}
dan937d0de2009-10-15 18:35:38 +0000587db auth auth
588proc auth {args} {
589 if {[lindex $args 0] == "SQLITE_READ"} {return SQLITE_DENY}
590 return SQLITE_OK
591}
592do_test analyze3-4.2.2 {
dan1d2ce4f2009-10-19 18:11:09 +0000593 sqlite3_reset $S
dand893ed82009-10-16 15:59:35 +0000594 sqlite3_bind_text $S 2 "abc" 3
dan937d0de2009-10-15 18:35:38 +0000595 sqlite3_step $S
drhcda455b2010-02-24 19:23:56 +0000596} {SQLITE_AUTH}
dan937d0de2009-10-15 18:35:38 +0000597do_test analyze3-4.2.4 {
598 sqlite3_finalize $S
drhcda455b2010-02-24 19:23:56 +0000599} {SQLITE_AUTH}
dan937d0de2009-10-15 18:35:38 +0000600
601# Check the effect of an authorization error that occurs in a re-prepare
602# performed by sqlite3_step() is the same as one that occurs within
dan1d2ce4f2009-10-19 18:11:09 +0000603# sqlite3Reprepare().
dan937d0de2009-10-15 18:35:38 +0000604#
605do_test analyze3-4.3.1 {
606 db auth {}
607 set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
608 execsql { CREATE TABLE t2(d, e, f) }
609 db auth auth
610 sqlite3_step $S
drhcda455b2010-02-24 19:23:56 +0000611} {SQLITE_AUTH}
dan937d0de2009-10-15 18:35:38 +0000612do_test analyze3-4.3.2 {
613 sqlite3_finalize $S
drhcda455b2010-02-24 19:23:56 +0000614} {SQLITE_AUTH}
danc94b8592009-10-20 07:01:24 +0000615db auth {}
616
617#-------------------------------------------------------------------------
618# Test that modifying bound variables using the clear_bindings() or
619# transfer_bindings() APIs works.
620#
621# analyze3-5.1.*: sqlite3_clear_bindings()
622# analyze3-5.2.*: sqlite3_transfer_bindings()
623#
624do_test analyze3-5.1.1 {
625 drop_all_tables
626 execsql {
627 CREATE TABLE t1(x TEXT COLLATE NOCASE);
628 CREATE INDEX i1 ON t1(x);
629 INSERT INTO t1 VALUES('aaa');
630 INSERT INTO t1 VALUES('abb');
631 INSERT INTO t1 VALUES('acc');
632 INSERT INTO t1 VALUES('baa');
633 INSERT INTO t1 VALUES('bbb');
634 INSERT INTO t1 VALUES('bcc');
635 }
636
637 set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x LIKE ?" -1 dummy]
638 sqlite3_bind_text $S 1 "a%" 2
639 set R [list]
640 while { "SQLITE_ROW" == [sqlite3_step $S] } {
641 lappend R [sqlite3_column_text $S 0]
642 }
643 concat [sqlite3_reset $S] $R
644} {SQLITE_OK aaa abb acc}
645do_test analyze3-5.1.2 {
646 sqlite3_clear_bindings $S
647 set R [list]
648 while { "SQLITE_ROW" == [sqlite3_step $S] } {
649 lappend R [sqlite3_column_text $S 0]
650 }
651 concat [sqlite3_reset $S] $R
652} {SQLITE_OK}
653do_test analyze3-5.1.3 {
654 sqlite3_finalize $S
655} {SQLITE_OK}
656
657do_test analyze3-5.1.1 {
658 set S1 [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x LIKE ?" -1 dummy]
659 sqlite3_bind_text $S1 1 "b%" 2
660 set R [list]
661 while { "SQLITE_ROW" == [sqlite3_step $S1] } {
662 lappend R [sqlite3_column_text $S1 0]
663 }
664 concat [sqlite3_reset $S1] $R
665} {SQLITE_OK baa bbb bcc}
666
667do_test analyze3-5.1.2 {
668 set S2 [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x = ?" -1 dummy]
669 sqlite3_bind_text $S2 1 "a%" 2
670 sqlite3_transfer_bindings $S2 $S1
671 set R [list]
672 while { "SQLITE_ROW" == [sqlite3_step $S1] } {
673 lappend R [sqlite3_column_text $S1 0]
674 }
675 concat [sqlite3_reset $S1] $R
676} {SQLITE_OK aaa abb acc}
677do_test analyze3-5.1.3 {
678 sqlite3_finalize $S2
679 sqlite3_finalize $S1
680} {SQLITE_OK}
dan937d0de2009-10-15 18:35:38 +0000681
dan2acbc0d2013-08-01 17:43:35 +0000682#-------------------------------------------------------------------------
683
684do_test analyze3-6.1 {
685 execsql { DROP TABLE IF EXISTS t1 }
686 execsql BEGIN
687 execsql { CREATE TABLE t1(a, b, c) }
688 for {set i 0} {$i < 1000} {incr i} {
689 execsql "INSERT INTO t1 VALUES([expr $i/100], 'x', [expr $i/10])"
690 }
691 execsql {
692 CREATE INDEX i1 ON t1(a, b);
693 CREATE INDEX i2 ON t1(c);
694 }
695 execsql COMMIT
696 execsql ANALYZE
697} {}
698
699do_eqp_test analyze3-6-3 {
700 SELECT * FROM t1 WHERE a = 5 AND c = 13;
701} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
702
703do_eqp_test analyze3-6-2 {
704 SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
705} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
706
drhcef25842015-04-20 13:59:18 +0000707#-----------------------------------------------------------------------------
708# 2015-04-20.
709# Memory leak in sqlite3Stat4ProbeFree(). (Discovered while fuzzing.)
710#
711do_execsql_test analyze-7.1 {
712 DROP TABLE IF EXISTS t1;
713 CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
714 INSERT INTO t1 VALUES(1,1,'0000');
715 CREATE INDEX t0b ON t1(b);
716 ANALYZE;
717 SELECT c FROM t1 WHERE b=3 AND a BETWEEN 30 AND hex(1);
718} {}
719
dan4eed0532015-04-20 15:13:08 +0000720# At one point duplicate stat1 entries were causing a memory leak.
721#
722reset_db
723do_execsql_test 7.2 {
724 CREATE TABLE t1(a,b,c);
725 CREATE INDEX t1a ON t1(a);
726 ANALYZE;
727 SELECT * FROM sqlite_stat1;
728 INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
729 INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
730 ANALYZE sqlite_master;
731}
732
dan937d0de2009-10-15 18:35:38 +0000733finish_test