xref: /sqlite-3.40.0/test/analyze3.test (revision e8f2c9dc)
1# 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
13# implements tests for range and LIKE constraints that use bound variables
14# instead of literal constant arguments.
15#
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20ifcapable !stat4&&!stat3 {
21  finish_test
22  return
23}
24
25#----------------------------------------------------------------------
26# Test Organization:
27#
28# analyze3-1.*: Test that the values of bound parameters are considered
29#               in the same way as constants when planning queries that
30#               use range constraints.
31#
32# analyze3-2.*: Test that the values of bound parameters are considered
33#               in the same way as constants when planning queries that
34#               use LIKE expressions in the WHERE clause.
35#
36# analyze3-3.*: Test that binding to a variable does not invalidate the
37#               query plan when there is no way in which replanning the
38#               query may produce a superior outcome.
39#
40# analyze3-4.*: Test that SQL or authorization callback errors occuring
41#               within sqlite3Reprepare() are handled correctly.
42#
43# analyze3-5.*: Check that the query plans of applicable statements are
44#               invalidated if the values of SQL parameter are modified
45#               using the clear_bindings() or transfer_bindings() APIs.
46#
47# analyze3-6.*: Test that the problem fixed by commit [127a5b776d] is fixed.
48#
49
50proc getvar {varname} { uplevel #0 set $varname }
51db function var getvar
52
53proc eqp {sql {db db}} {
54  uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
55}
56
57proc sf_execsql {sql {db db}} {
58  set ::sqlite_search_count 0
59  set r [uplevel [list execsql $sql $db]]
60
61  concat $::sqlite_search_count [$db status step] $r
62}
63
64#-------------------------------------------------------------------------
65#
66# analyze3-1.1.1:
67#   Create a table with two columns. Populate the first column (affinity
68#   INTEGER) with integer values from 100 to 1100. Create an index on this
69#   column. ANALYZE the table.
70#
71# analyze3-1.1.2 - 3.1.3
72#   Show that there are two possible plans for querying the table with
73#   a range constraint on the indexed column - "full table scan" or "use
74#   the index". When the range is specified using literal values, SQLite
75#   is able to pick the best plan based on the samples in sqlite_stat3.
76#
77# analyze3-1.1.4 - 3.1.9
78#   Show that using SQL variables produces the same results as using
79#   literal values to constrain the range scan.
80#
81#   These tests also check that the compiler code considers column
82#   affinities when estimating the number of rows scanned by the "use
83#   index strategy".
84#
85do_test analyze3-1.1.1 {
86  execsql {
87    BEGIN;
88    CREATE TABLE t1(x INTEGER, y);
89    CREATE INDEX i1 ON t1(x);
90  }
91  for {set i 0} {$i < 1000} {incr i} {
92    execsql { INSERT INTO t1 VALUES($i+100, $i) }
93  }
94  execsql {
95    COMMIT;
96    ANALYZE;
97  }
98
99  ifcapable stat4 {
100    execsql { SELECT count(*)>0 FROM sqlite_stat4; }
101  } else {
102    execsql { SELECT count(*)>0 FROM sqlite_stat3; }
103  }
104} {1}
105
106do_execsql_test analyze3-1.1.x {
107  SELECT count(*) FROM t1 WHERE x>200 AND x<300;
108  SELECT count(*) FROM t1 WHERE x>0 AND x<1100;
109} {99 1000}
110
111# The first of the following two SELECT statements visits 99 rows. So
112# it is better to use the index. But the second visits every row in
113# the table (1000 in total) so it is better to do a full-table scan.
114#
115do_eqp_test analyze3-1.1.2 {
116  SELECT sum(y) FROM t1 WHERE x>200 AND x<300
117} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
118do_eqp_test analyze3-1.1.3 {
119  SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
120} {0 0 0 {SCAN TABLE t1}}
121
122do_test analyze3-1.1.4 {
123  sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
124} {199 0 14850}
125do_test analyze3-1.1.5 {
126  set l [string range "200" 0 end]
127  set u [string range "300" 0 end]
128  sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
129} {199 0 14850}
130do_test analyze3-1.1.6 {
131  set l [expr int(200)]
132  set u [expr int(300)]
133  sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
134} {199 0 14850}
135do_test analyze3-1.1.7 {
136  sf_execsql { SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 }
137} {999 999 499500}
138do_test analyze3-1.1.8 {
139  set l [string range "0" 0 end]
140  set u [string range "1100" 0 end]
141  sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
142} {999 999 499500}
143do_test analyze3-1.1.9 {
144  set l [expr int(0)]
145  set u [expr int(1100)]
146  sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
147} {999 999 499500}
148
149
150# The following tests are similar to the block above. The difference is
151# that the indexed column has TEXT affinity in this case. In the tests
152# above the affinity is INTEGER.
153#
154do_test analyze3-1.2.1 {
155  execsql {
156    BEGIN;
157      CREATE TABLE t2(x TEXT, y);
158      INSERT INTO t2 SELECT * FROM t1;
159      CREATE INDEX i2 ON t2(x);
160    COMMIT;
161    ANALYZE;
162  }
163} {}
164do_execsql_test analyze3-2.1.x {
165  SELECT count(*) FROM t2 WHERE x>1 AND x<2;
166  SELECT count(*) FROM t2 WHERE x>0 AND x<99;
167} {200 990}
168do_eqp_test analyze3-1.2.2 {
169  SELECT sum(y) FROM t2 WHERE x>1 AND x<2
170} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}}
171do_eqp_test analyze3-1.2.3 {
172  SELECT sum(y) FROM t2 WHERE x>0 AND x<99
173} {0 0 0 {SCAN TABLE t2}}
174
175do_test analyze3-1.2.4 {
176  sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
177} {161 0 4760}
178do_test analyze3-1.2.5 {
179  set l [string range "12" 0 end]
180  set u [string range "20" 0 end]
181  sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
182} {161 0 text text 4760}
183do_test analyze3-1.2.6 {
184  set l [expr int(12)]
185  set u [expr int(20)]
186  sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
187} {161 0 integer integer 4760}
188do_test analyze3-1.2.7 {
189  sf_execsql { SELECT sum(y) FROM t2 WHERE x>0 AND x<99 }
190} {999 999 490555}
191do_test analyze3-1.2.8 {
192  set l [string range "0" 0 end]
193  set u [string range "99" 0 end]
194  sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
195} {999 999 text text 490555}
196do_test analyze3-1.2.9 {
197  set l [expr int(0)]
198  set u [expr int(99)]
199  sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
200} {999 999 integer integer 490555}
201
202# Same tests a third time. This time, column x has INTEGER affinity and
203# is not the leftmost column of the table. This triggered a bug causing
204# SQLite to use sub-optimal query plans in 3.6.18 and earlier.
205#
206do_test analyze3-1.3.1 {
207  execsql {
208    BEGIN;
209      CREATE TABLE t3(y TEXT, x INTEGER);
210      INSERT INTO t3 SELECT y, x FROM t1;
211      CREATE INDEX i3 ON t3(x);
212    COMMIT;
213    ANALYZE;
214  }
215} {}
216do_execsql_test analyze3-1.3.x {
217  SELECT count(*) FROM t3 WHERE x>200 AND x<300;
218  SELECT count(*) FROM t3 WHERE x>0 AND x<1100
219} {99 1000}
220do_eqp_test analyze3-1.3.2 {
221  SELECT sum(y) FROM t3 WHERE x>200 AND x<300
222} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}}
223do_eqp_test analyze3-1.3.3 {
224  SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
225} {0 0 0 {SCAN TABLE t3}}
226
227do_test analyze3-1.3.4 {
228  sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
229} {199 0 14850}
230do_test analyze3-1.3.5 {
231  set l [string range "200" 0 end]
232  set u [string range "300" 0 end]
233  sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
234} {199 0 14850}
235do_test analyze3-1.3.6 {
236  set l [expr int(200)]
237  set u [expr int(300)]
238  sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
239} {199 0 14850}
240do_test analyze3-1.3.7 {
241  sf_execsql { SELECT sum(y) FROM t3 WHERE x>0 AND x<1100 }
242} {999 999 499500}
243do_test analyze3-1.3.8 {
244  set l [string range "0" 0 end]
245  set u [string range "1100" 0 end]
246  sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
247} {999 999 499500}
248do_test analyze3-1.3.9 {
249  set l [expr int(0)]
250  set u [expr int(1100)]
251  sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
252} {999 999 499500}
253
254#-------------------------------------------------------------------------
255# Test that the values of bound SQL variables may be used for the LIKE
256# optimization.
257#
258drop_all_tables
259do_test analyze3-2.1 {
260  execsql {
261    PRAGMA case_sensitive_like=off;
262    BEGIN;
263    CREATE TABLE t1(a, b TEXT COLLATE nocase);
264    CREATE INDEX i1 ON t1(b);
265  }
266  for {set i 0} {$i < 1000} {incr i} {
267    set t ""
268    append t [lindex {a b c d e f g h i j} [expr $i/100]]
269    append t [lindex {a b c d e f g h i j} [expr ($i/10)%10]]
270    append t [lindex {a b c d e f g h i j} [expr ($i%10)]]
271    execsql { INSERT INTO t1 VALUES($i, $t) }
272  }
273  execsql COMMIT
274} {}
275do_eqp_test analyze3-2.2 {
276  SELECT count(a) FROM t1 WHERE b LIKE 'a%'
277} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?)}}
278do_eqp_test analyze3-2.3 {
279  SELECT count(a) FROM t1 WHERE b LIKE '%a'
280} {0 0 0 {SCAN TABLE t1}}
281
282do_test analyze3-2.4 {
283  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE 'a%' }
284} {101 0 100}
285do_test analyze3-2.5 {
286  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE '%a' }
287} {999 999 100}
288
289do_test analyze3-2.4 {
290  set like "a%"
291  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
292} {101 0 100}
293do_test analyze3-2.5 {
294  set like "%a"
295  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
296} {999 999 100}
297do_test analyze3-2.6 {
298  set like "a"
299  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
300} {101 0 0}
301do_test analyze3-2.7 {
302  set like "ab"
303  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
304} {11 0 0}
305do_test analyze3-2.8 {
306  set like "abc"
307  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
308} {2 0 1}
309do_test analyze3-2.9 {
310  set like "a_c"
311  sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
312} {101 0 10}
313
314
315#-------------------------------------------------------------------------
316# This block of tests checks that statements are correctly marked as
317# expired when the values bound to any parameters that may affect the
318# query plan are modified.
319#
320drop_all_tables
321db auth auth
322proc auth {args} {
323  set ::auth 1
324  return SQLITE_OK
325}
326
327do_test analyze3-3.1 {
328  execsql {
329    BEGIN;
330    CREATE TABLE t1(a, b, c);
331    CREATE INDEX i1 ON t1(b);
332  }
333  for {set i 0} {$i < 100} {incr i} {
334    execsql { INSERT INTO t1 VALUES($i, $i, $i) }
335  }
336  execsql COMMIT
337  execsql ANALYZE
338} {}
339do_test analyze3-3.2.1 {
340  set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE b>?" -1 dummy]
341  sqlite3_expired $S
342} {0}
343do_test analyze3-3.2.2 {
344  sqlite3_bind_text $S 1 "abc" 3
345  sqlite3_expired $S
346} {1}
347do_test analyze3-3.2.4 {
348  sqlite3_finalize $S
349} {SQLITE_OK}
350
351do_test analyze3-3.2.5 {
352  set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE b=?" -1 dummy]
353  sqlite3_expired $S
354} {0}
355do_test analyze3-3.2.6 {
356  sqlite3_bind_text $S 1 "abc" 3
357  sqlite3_expired $S
358} {1}
359do_test analyze3-3.2.7 {
360  sqlite3_finalize $S
361} {SQLITE_OK}
362
363do_test analyze3-3.4.1 {
364  set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
365  sqlite3_expired $S
366} {0}
367do_test analyze3-3.4.2 {
368  sqlite3_bind_text $S 1 "abc" 3
369  sqlite3_expired $S
370} {0}
371do_test analyze3-3.4.3 {
372  sqlite3_bind_text $S 2 "def" 3
373  sqlite3_expired $S
374} {1}
375do_test analyze3-3.4.4 {
376  sqlite3_bind_text $S 2 "ghi" 3
377  sqlite3_expired $S
378} {1}
379do_test analyze3-3.4.5 {
380  sqlite3_expired $S
381} {1}
382do_test analyze3-3.4.6 {
383  sqlite3_finalize $S
384} {SQLITE_OK}
385
386do_test analyze3-3.5.1 {
387  set S [sqlite3_prepare_v2 db {
388    SELECT * FROM t1 WHERE a IN (
389      ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10,
390      ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
391      ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30, ?31
392    ) AND b>?32;
393  } -1 dummy]
394  sqlite3_expired $S
395} {0}
396do_test analyze3-3.5.2 {
397  sqlite3_bind_text $S 31 "abc" 3
398  sqlite3_expired $S
399} {0}
400do_test analyze3-3.5.3 {
401  sqlite3_bind_text $S 32 "def" 3
402  sqlite3_expired $S
403} {1}
404do_test analyze3-3.5.5 {
405  sqlite3_finalize $S
406} {SQLITE_OK}
407
408do_test analyze3-3.6.1 {
409  set S [sqlite3_prepare_v2 db {
410    SELECT * FROM t1 WHERE a IN (
411      ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10,
412      ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
413      ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30, ?31, ?32
414    ) AND b>?33;
415  } -1 dummy]
416  sqlite3_expired $S
417} {0}
418do_test analyze3-3.6.2 {
419  sqlite3_bind_text $S 32 "abc" 3
420  sqlite3_expired $S
421} {1}
422do_test analyze3-3.6.3 {
423  sqlite3_bind_text $S 33 "def" 3
424  sqlite3_expired $S
425} {1}
426do_test analyze3-3.6.5 {
427  sqlite3_finalize $S
428} {SQLITE_OK}
429
430do_test analyze3-3.7.1 {
431  set S [sqlite3_prepare_v2 db {
432    SELECT * FROM t1 WHERE a IN (
433      ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?33,
434      ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
435      ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30, ?31, ?32
436    ) AND b>?10;
437  } -1 dummy]
438  sqlite3_expired $S
439} {0}
440do_test analyze3-3.7.2 {
441  sqlite3_bind_text $S 32 "abc" 3
442  sqlite3_expired $S
443} {0}
444do_test analyze3-3.7.3 {
445  sqlite3_bind_text $S 33 "def" 3
446  sqlite3_expired $S
447} {0}
448do_test analyze3-3.7.4 {
449  sqlite3_bind_text $S 10 "def" 3
450  sqlite3_expired $S
451} {1}
452do_test analyze3-3.7.6 {
453  sqlite3_finalize $S
454} {SQLITE_OK}
455
456do_test analyze3-3.8.1 {
457  execsql {
458    CREATE TABLE t4(x, y TEXT COLLATE NOCASE);
459    CREATE INDEX i4 ON t4(y);
460  }
461} {}
462do_test analyze3-3.8.2 {
463  set S [sqlite3_prepare_v2 db {
464    SELECT * FROM t4 WHERE x != ? AND y LIKE ?
465  } -1 dummy]
466  sqlite3_expired $S
467} {0}
468do_test analyze3-3.8.3 {
469  sqlite3_bind_text $S 1 "abc" 3
470  sqlite3_expired $S
471} {0}
472do_test analyze3-3.8.4 {
473  sqlite3_bind_text $S 2 "def" 3
474  sqlite3_expired $S
475} {1}
476do_test analyze3-3.8.7 {
477  sqlite3_bind_text $S 2 "ghi%" 4
478  sqlite3_expired $S
479} {1}
480do_test analyze3-3.8.8 {
481  sqlite3_expired $S
482} {1}
483do_test analyze3-3.8.9 {
484  sqlite3_bind_text $S 2 "ghi%def" 7
485  sqlite3_expired $S
486} {1}
487do_test analyze3-3.8.10 {
488  sqlite3_expired $S
489} {1}
490do_test analyze3-3.8.11 {
491  sqlite3_bind_text $S 2 "%ab" 3
492  sqlite3_expired $S
493} {1}
494do_test analyze3-3.8.12 {
495  sqlite3_expired $S
496} {1}
497do_test analyze3-3.8.12 {
498  sqlite3_bind_text $S 2 "%de" 3
499  sqlite3_expired $S
500} {1}
501do_test analyze3-3.8.13 {
502  sqlite3_expired $S
503} {1}
504do_test analyze3-3.8.14 {
505  sqlite3_finalize $S
506} {SQLITE_OK}
507
508#-------------------------------------------------------------------------
509# These tests check that errors encountered while repreparing an SQL
510# statement within sqlite3Reprepare() are handled correctly.
511#
512
513# Check a schema error.
514#
515do_test analyze3-4.1.1 {
516  set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
517  sqlite3_step $S
518} {SQLITE_DONE}
519do_test analyze3-4.1.2 {
520  sqlite3_reset $S
521  sqlite3_bind_text $S 2 "abc" 3
522  execsql { DROP TABLE t1 }
523  sqlite3_step $S
524} {SQLITE_ERROR}
525do_test analyze3-4.1.3 {
526  sqlite3_finalize $S
527} {SQLITE_ERROR}
528
529# Check an authorization error.
530#
531do_test analyze3-4.2.1 {
532  execsql {
533    BEGIN;
534    CREATE TABLE t1(a, b, c);
535    CREATE INDEX i1 ON t1(b);
536  }
537  for {set i 0} {$i < 100} {incr i} {
538    execsql { INSERT INTO t1 VALUES($i, $i, $i) }
539  }
540  execsql COMMIT
541  execsql ANALYZE
542  set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
543  sqlite3_step $S
544} {SQLITE_DONE}
545db auth auth
546proc auth {args} {
547  if {[lindex $args 0] == "SQLITE_READ"} {return SQLITE_DENY}
548  return SQLITE_OK
549}
550do_test analyze3-4.2.2 {
551  sqlite3_reset $S
552  sqlite3_bind_text $S 2 "abc" 3
553  sqlite3_step $S
554} {SQLITE_AUTH}
555do_test analyze3-4.2.4 {
556  sqlite3_finalize $S
557} {SQLITE_AUTH}
558
559# Check the effect of an authorization error that occurs in a re-prepare
560# performed by sqlite3_step() is the same as one that occurs within
561# sqlite3Reprepare().
562#
563do_test analyze3-4.3.1 {
564  db auth {}
565  set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE a=? AND b>?" -1 dummy]
566  execsql { CREATE TABLE t2(d, e, f) }
567  db auth auth
568  sqlite3_step $S
569} {SQLITE_AUTH}
570do_test analyze3-4.3.2 {
571  sqlite3_finalize $S
572} {SQLITE_AUTH}
573db auth {}
574
575#-------------------------------------------------------------------------
576# Test that modifying bound variables using the clear_bindings() or
577# transfer_bindings() APIs works.
578#
579#   analyze3-5.1.*: sqlite3_clear_bindings()
580#   analyze3-5.2.*: sqlite3_transfer_bindings()
581#
582do_test analyze3-5.1.1 {
583  drop_all_tables
584  execsql {
585    CREATE TABLE t1(x TEXT COLLATE NOCASE);
586    CREATE INDEX i1 ON t1(x);
587    INSERT INTO t1 VALUES('aaa');
588    INSERT INTO t1 VALUES('abb');
589    INSERT INTO t1 VALUES('acc');
590    INSERT INTO t1 VALUES('baa');
591    INSERT INTO t1 VALUES('bbb');
592    INSERT INTO t1 VALUES('bcc');
593  }
594
595  set S [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x LIKE ?" -1 dummy]
596  sqlite3_bind_text $S 1 "a%" 2
597  set R [list]
598  while { "SQLITE_ROW" == [sqlite3_step $S] } {
599    lappend R [sqlite3_column_text $S 0]
600  }
601  concat [sqlite3_reset $S] $R
602} {SQLITE_OK aaa abb acc}
603do_test analyze3-5.1.2 {
604  sqlite3_clear_bindings $S
605  set R [list]
606  while { "SQLITE_ROW" == [sqlite3_step $S] } {
607    lappend R [sqlite3_column_text $S 0]
608  }
609  concat [sqlite3_reset $S] $R
610} {SQLITE_OK}
611do_test analyze3-5.1.3 {
612  sqlite3_finalize $S
613} {SQLITE_OK}
614
615do_test analyze3-5.1.1 {
616  set S1 [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x LIKE ?" -1 dummy]
617  sqlite3_bind_text $S1 1 "b%" 2
618  set R [list]
619  while { "SQLITE_ROW" == [sqlite3_step $S1] } {
620    lappend R [sqlite3_column_text $S1 0]
621  }
622  concat [sqlite3_reset $S1] $R
623} {SQLITE_OK baa bbb bcc}
624
625do_test analyze3-5.1.2 {
626  set S2 [sqlite3_prepare_v2 db "SELECT * FROM t1 WHERE x = ?" -1 dummy]
627  sqlite3_bind_text $S2 1 "a%" 2
628  sqlite3_transfer_bindings $S2 $S1
629  set R [list]
630  while { "SQLITE_ROW" == [sqlite3_step $S1] } {
631    lappend R [sqlite3_column_text $S1 0]
632  }
633  concat [sqlite3_reset $S1] $R
634} {SQLITE_OK aaa abb acc}
635do_test analyze3-5.1.3 {
636  sqlite3_finalize $S2
637  sqlite3_finalize $S1
638} {SQLITE_OK}
639
640#-------------------------------------------------------------------------
641
642do_test analyze3-6.1 {
643  execsql { DROP TABLE IF EXISTS t1 }
644  execsql BEGIN
645  execsql { CREATE TABLE t1(a, b, c) }
646  for {set i 0} {$i < 1000} {incr i} {
647    execsql "INSERT INTO t1 VALUES([expr $i/100], 'x', [expr $i/10])"
648  }
649  execsql {
650    CREATE INDEX i1 ON t1(a, b);
651    CREATE INDEX i2 ON t1(c);
652  }
653  execsql COMMIT
654  execsql ANALYZE
655} {}
656
657do_eqp_test analyze3-6-3 {
658  SELECT * FROM t1 WHERE a = 5 AND c = 13;
659} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
660
661do_eqp_test analyze3-6-2 {
662  SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
663} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
664
665finish_test
666