Imported Upstream version 5.3.21
[platform/upstream/libdb.git] / lang / sql / sqlite / test / analyze2.test
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 the extra functionality provided by the ANALYZE 
14 # command when the library is compiled with SQLITE_ENABLE_STAT2 defined.
15 #
16
17 set testdir [file dirname $argv0]
18 source $testdir/tester.tcl
19
20 ifcapable !stat2 {
21   finish_test
22   return
23 }
24
25 set testprefix analyze2
26
27 # Do not use a codec for tests in this file, as the database file is
28 # manipulated directly using tcl scripts (using the [hexio_write] command).
29 #
30 do_not_use_codec
31
32 #--------------------------------------------------------------------
33 # Test organization:
34 #
35 # analyze2-1.*: Tests to verify that ANALYZE creates and populates the
36 #               sqlite_stat2 table as expected.
37 #
38 # analyze2-2.*: Test that when a table has two indexes on it and either
39 #               index may be used for the scan, the index suggested by
40 #               the contents of sqlite_stat2 table is prefered.
41
42 # analyze2-3.*: Similar to the previous block of tests, but using tables
43 #               that contain a mixture of NULL, numeric, text and blob
44 #               values.
45 #
46 # analyze2-4.*: Check that when an indexed column uses a collation other
47 #               than BINARY, the collation is taken into account when
48 #               using the contents of sqlite_stat2 to estimate the cost
49 #               of a range scan.
50 #
51 # analyze2-5.*: Check that collation sequences are used as described above
52 #               even when the only available version of the collation 
53 #               function require UTF-16 encoded arguments.
54 #
55 # analyze2-6.*: Check that the library behaves correctly when one of the
56 #               sqlite_stat2 or sqlite_stat1 tables are missing.
57 #
58 # analyze2-7.*: Check that in a shared-schema situation, nothing goes
59 #               wrong if sqlite_stat2 data is read by one connection,
60 #               and freed by another.
61
62
63 proc eqp {sql {db db}} {
64   uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db
65 }
66
67 do_test analyze2-1.1 {
68   execsql { CREATE TABLE t1(x PRIMARY KEY) }
69   for {set i 0} {$i < 1000} {incr i} {
70     execsql { INSERT INTO t1 VALUES($i) }
71   }
72   execsql { 
73     ANALYZE;
74     SELECT * FROM sqlite_stat2;
75   }
76 } [list t1 sqlite_autoindex_t1_1 0 50  \
77         t1 sqlite_autoindex_t1_1 1 149 \
78         t1 sqlite_autoindex_t1_1 2 249 \
79         t1 sqlite_autoindex_t1_1 3 349 \
80         t1 sqlite_autoindex_t1_1 4 449 \
81         t1 sqlite_autoindex_t1_1 5 549 \
82         t1 sqlite_autoindex_t1_1 6 649 \
83         t1 sqlite_autoindex_t1_1 7 749 \
84         t1 sqlite_autoindex_t1_1 8 849 \
85         t1 sqlite_autoindex_t1_1 9 949 \
86 ]
87
88 do_test analyze2-1.2 {
89   execsql {
90     DELETE FROM t1 WHERe x>9;
91     ANALYZE;
92     SELECT tbl, idx, group_concat(sample, ' ') FROM sqlite_stat2;
93   }
94 } {t1 sqlite_autoindex_t1_1 {0 1 2 3 4 5 6 7 8 9}}
95 do_test analyze2-1.3 {
96   execsql {
97     DELETE FROM t1 WHERE x>8;
98     ANALYZE;
99     SELECT * FROM sqlite_stat2;
100   }
101 } {}
102 do_test analyze2-1.4 {
103   execsql {
104     DELETE FROM t1;
105     ANALYZE;
106     SELECT * FROM sqlite_stat2;
107   }
108 } {}
109
110 do_test analyze2-2.1 {
111   execsql { 
112     BEGIN;
113     DROP TABLE t1;
114     CREATE TABLE t1(x, y);
115     CREATE INDEX t1_x ON t1(x);
116     CREATE INDEX t1_y ON t1(y);
117   }
118   for {set i 0} {$i < 1000} {incr i} {
119     execsql { INSERT INTO t1 VALUES($i, $i) }
120   }
121   execsql COMMIT
122   execsql ANALYZE
123 } {}
124 do_eqp_test 2.2 {
125   SELECT * FROM t1 WHERE x>500 AND y>700
126 } {
127   0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~100 rows)}
128 }
129 do_eqp_test 2.3 {
130   SELECT * FROM t1 WHERE x>700 AND y>500
131 } {
132   0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>?) (~100 rows)}
133 }
134 do_eqp_test 2.3 {
135   SELECT * FROM t1 WHERE y>700 AND x>500
136 } {
137   0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~100 rows)}
138 }
139 do_eqp_test 2.4 {
140   SELECT * FROM t1 WHERE y>500 AND x>700
141 } {
142   0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>?) (~100 rows)}
143 }
144 do_eqp_test 2.5 {
145   SELECT * FROM t1 WHERE x BETWEEN 100 AND 200 AND y BETWEEN 400 AND 700
146 } {
147   0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x<?) (~25 rows)}
148 }
149 do_eqp_test 2.6 {
150   SELECT * FROM t1 WHERE x BETWEEN 100 AND 500 AND y BETWEEN 400 AND 700
151 } {
152   0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y<?) (~75 rows)}
153 }
154 do_eqp_test 2.7 {
155   SELECT * FROM t1 WHERE x BETWEEN -400 AND -300 AND y BETWEEN 100 AND 300
156 } {
157   0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x<?) (~12 rows)}
158 }
159 do_eqp_test 2.8 {
160   SELECT * FROM t1 WHERE x BETWEEN 100 AND 300 AND y BETWEEN -400 AND -300
161 } {
162   0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y<?) (~12 rows)}
163 }
164 do_eqp_test 2.9 {
165   SELECT * FROM t1 WHERE x BETWEEN 500 AND 100 AND y BETWEEN 100 AND 300
166 } {
167   0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x<?) (~12 rows)}
168 }
169 do_eqp_test 2.10 {
170   SELECT * FROM t1 WHERE x BETWEEN 100 AND 300 AND y BETWEEN 500 AND 100
171 } {
172   0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y<?) (~12 rows)}
173 }
174
175 do_test analyze2-3.1 {
176   set alphabet [list a b c d e f g h i j]
177   execsql BEGIN
178   for {set i 0} {$i < 1000} {incr i} {
179     set str    [lindex $alphabet [expr ($i/100)%10]] 
180     append str [lindex $alphabet [expr ($i/ 10)%10]]
181     append str [lindex $alphabet [expr ($i/  1)%10]]
182     execsql { INSERT INTO t1 VALUES($str, $str) }
183   }
184   execsql COMMIT
185   execsql ANALYZE
186   execsql { 
187     SELECT tbl,idx,group_concat(sample,' ') 
188     FROM sqlite_stat2 
189     WHERE idx = 't1_x' 
190     GROUP BY tbl,idx
191   }
192 } {t1 t1_x {100 299 499 699 899 ajj cjj ejj gjj ijj}}
193 do_test analyze2-3.2 {
194   execsql { 
195     SELECT tbl,idx,group_concat(sample,' ') 
196     FROM sqlite_stat2 
197     WHERE idx = 't1_y' 
198     GROUP BY tbl,idx
199   }
200 } {t1 t1_y {100 299 499 699 899 ajj cjj ejj gjj ijj}}
201
202 do_eqp_test 3.3 {
203   SELECT * FROM t1 WHERE x BETWEEN 100 AND 500 AND y BETWEEN 'a' AND 'b'
204 } {
205   0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>? AND y<?) (~50 rows)}
206 }
207 do_eqp_test 3.4 {
208   SELECT * FROM t1 WHERE x BETWEEN 100 AND 400 AND y BETWEEN 'a' AND 'h'
209 } {
210   0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x>? AND x<?) (~100 rows)}
211 }
212 do_eqp_test 3.5 {
213   SELECT * FROM t1 WHERE x<'a' AND y>'h'
214 } {
215   0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~66 rows)}
216 }
217 do_eqp_test 3.6 {
218   SELECT * FROM t1 WHERE x<444 AND y>'h'
219 } {
220   0 0 0 {SEARCH TABLE t1 USING INDEX t1_y (y>?) (~66 rows)}
221 }
222 do_eqp_test 3.7 {
223   SELECT * FROM t1 WHERE x<221 AND y>'g'
224 } {
225   0 0 0 {SEARCH TABLE t1 USING INDEX t1_x (x<?) (~66 rows)}
226 }
227
228 do_test analyze2-4.1 {
229   execsql { CREATE TABLE t3(a COLLATE nocase, b) }
230   execsql { CREATE INDEX t3a ON t3(a) }
231   execsql { CREATE INDEX t3b ON t3(b) }
232   set alphabet [list A b C d E f G h I j]
233   execsql BEGIN
234   for {set i 0} {$i < 1000} {incr i} {
235     set str    [lindex $alphabet [expr ($i/100)%10]] 
236     append str [lindex $alphabet [expr ($i/ 10)%10]]
237     append str [lindex $alphabet [expr ($i/  1)%10]]
238     execsql { INSERT INTO t3 VALUES($str, $str) }
239   }
240   execsql COMMIT
241   execsql ANALYZE
242 } {}
243 do_test analyze2-4.2 {
244   execsql { 
245     PRAGMA automatic_index=OFF;
246     SELECT tbl,idx,group_concat(sample,' ') 
247     FROM sqlite_stat2 
248     WHERE idx = 't3a' 
249     GROUP BY tbl,idx;
250     PRAGMA automatic_index=ON;
251   }
252 } {t3 t3a {AfA bEj CEj dEj EEj fEj GEj hEj IEj jEj}}
253 do_test analyze2-4.3 {
254   execsql { 
255     SELECT tbl,idx,group_concat(sample,' ') 
256     FROM sqlite_stat2 
257     WHERE idx = 't3b' 
258     GROUP BY tbl,idx
259   }
260 } {t3 t3b {AbA CIj EIj GIj IIj bIj dIj fIj hIj jIj}}
261
262 do_eqp_test 4.4 {
263   SELECT * FROM t3 WHERE a > 'A' AND a < 'C' AND b > 'A' AND b < 'C'
264 } {
265   0 0 0 {SEARCH TABLE t3 USING INDEX t3b (b>? AND b<?) (~11 rows)}
266 }
267 do_eqp_test 4.5 {
268   SELECT * FROM t3 WHERE a > 'A' AND a < 'c' AND b > 'A' AND b < 'c'
269 } {
270   0 0 0 {SEARCH TABLE t3 USING INDEX t3a (a>? AND a<?) (~22 rows)}
271 }
272
273 ifcapable utf16 {
274   proc test_collate {enc lhs rhs} {
275     # puts $enc
276     return [string compare $lhs $rhs]
277   }
278   do_test analyze2-5.1 {
279     add_test_collate db 0 0 1
280     execsql { CREATE TABLE t4(x COLLATE test_collate) }
281     execsql { CREATE INDEX t4x ON t4(x) }
282     set alphabet [list a b c d e f g h i j]
283     execsql BEGIN
284     for {set i 0} {$i < 1000} {incr i} {
285       set str    [lindex $alphabet [expr ($i/100)%10]] 
286       append str [lindex $alphabet [expr ($i/ 10)%10]]
287       append str [lindex $alphabet [expr ($i/  1)%10]]
288       execsql { INSERT INTO t4 VALUES($str) }
289     }
290     execsql COMMIT
291     execsql ANALYZE
292   } {}
293   do_test analyze2-5.2 {
294     execsql { 
295       SELECT tbl,idx,group_concat(sample,' ') 
296       FROM sqlite_stat2 
297       WHERE tbl = 't4' 
298       GROUP BY tbl,idx
299     }
300   } {t4 t4x {afa bej cej dej eej fej gej hej iej jej}}
301   do_eqp_test 5.3 {
302     SELECT * FROM t4 WHERE x>'ccc'
303   } {0 0 0 {SEARCH TABLE t4 USING COVERING INDEX t4x (x>?) (~800 rows)}}
304   do_eqp_test 5.4 {
305     SELECT * FROM t4 AS t41, t4 AS t42 WHERE t41.x>'ccc' AND t42.x>'ggg'
306   } {
307     0 0 1 {SEARCH TABLE t4 AS t42 USING COVERING INDEX t4x (x>?) (~300 rows)} 
308     0 1 0 {SEARCH TABLE t4 AS t41 USING COVERING INDEX t4x (x>?) (~800 rows)}
309   }
310   do_eqp_test 5.5 {
311     SELECT * FROM t4 AS t41, t4 AS t42 WHERE t41.x>'ddd' AND t42.x>'ccc'
312   } {
313     0 0 0 {SEARCH TABLE t4 AS t41 USING COVERING INDEX t4x (x>?) (~700 rows)} 
314     0 1 1 {SEARCH TABLE t4 AS t42 USING COVERING INDEX t4x (x>?) (~800 rows)}
315   }
316 }
317
318 #--------------------------------------------------------------------
319 # These tests, analyze2-6.*, verify that the library behaves correctly
320 # when one of the sqlite_stat1 and sqlite_stat2 tables is missing.
321 #
322 # If the sqlite_stat1 table is not present, then the sqlite_stat2
323 # table is not read. However, if it is the sqlite_stat2 table that
324 # is missing, the data in the sqlite_stat1 table is still used.
325 #
326 # Tests analyze2-6.1.* test the libary when the sqlite_stat2 table
327 # is missing. Tests analyze2-6.2.* test the library when sqlite_stat1
328 # is not present.
329 #
330 do_test analyze2-6.0 {
331   execsql {
332     DROP TABLE IF EXISTS t4;
333     CREATE TABLE t5(a, b); CREATE INDEX t5i ON t5(a, b);
334     CREATE TABLE t6(a, b); CREATE INDEX t6i ON t6(a, b);
335   }
336   for {set ii 0} {$ii < 20} {incr ii} {
337     execsql {
338       INSERT INTO t5 VALUES($ii, $ii);
339       INSERT INTO t6 VALUES($ii/10, $ii/10);
340     }
341   }
342   execsql { 
343     CREATE TABLE master AS 
344     SELECT * FROM sqlite_master WHERE name LIKE 'sqlite_stat%' 
345   }
346 } {}
347
348 do_test analyze2-6.1.1 {
349   eqp {SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
350        t5.a = 1 AND
351        t6.a = 1 AND t6.b = 1
352   }
353 } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a=? AND b=?) (~9 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
354 do_test analyze2-6.1.2 {
355   db cache flush
356   execsql ANALYZE
357   eqp {SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
358        t5.a = 1 AND
359        t6.a = 1 AND t6.b = 1
360   }
361 } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
362 do_test analyze2-6.1.3 {
363   sqlite3 db test.db
364   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
365        t5.a = 1 AND
366        t6.a = 1 AND t6.b = 1
367   }
368 } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
369 do_test analyze2-6.1.4 {
370   execsql { 
371     PRAGMA writable_schema = 1;
372     DELETE FROM sqlite_master WHERE tbl_name = 'sqlite_stat2';
373   }
374   sqlite3 db test.db
375   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
376        t5.a = 1 AND
377        t6.a = 1 AND t6.b = 1
378   }
379 } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
380 do_test analyze2-6.1.5 {
381   execsql { 
382     PRAGMA writable_schema = 1;
383     DELETE FROM sqlite_master WHERE tbl_name = 'sqlite_stat1';
384   }
385   sqlite3 db test.db
386   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
387        t5.a = 1 AND
388        t6.a = 1 AND t6.b = 1
389   }
390 } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a=? AND b=?) (~9 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
391 do_test analyze2-6.1.6 {
392   execsql { 
393     PRAGMA writable_schema = 1;
394     INSERT INTO sqlite_master SELECT * FROM master;
395   }
396   sqlite3 db test.db
397   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
398        t5.a = 1 AND
399        t6.a = 1 AND t6.b = 1
400   }
401 } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a=?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
402
403 do_test analyze2-6.2.1 {
404   execsql { 
405     DELETE FROM sqlite_stat1;
406     DELETE FROM sqlite_stat2;
407   }
408   sqlite3 db test.db
409   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
410         t5.a>1 AND t5.a<15 AND
411         t6.a>1
412   }
413 } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a<?) (~60000 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
414 do_test analyze2-6.2.2 {
415   db cache flush
416   execsql ANALYZE
417   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
418         t5.a>1 AND t5.a<15 AND
419         t6.a>1
420   }
421 } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
422 do_test analyze2-6.2.3 {
423   sqlite3 db test.db
424   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
425         t5.a>1 AND t5.a<15 AND
426         t6.a>1
427   }
428 } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
429 do_test analyze2-6.2.4 {
430   execsql { 
431     PRAGMA writable_schema = 1;
432     DELETE FROM sqlite_master WHERE tbl_name = 'sqlite_stat1';
433   }
434   sqlite3 db test.db
435   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
436         t5.a>1 AND t5.a<15 AND
437         t6.a>1
438   }
439 } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a<?) (~60000 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
440 do_test analyze2-6.2.5 {
441   execsql { 
442     PRAGMA writable_schema = 1;
443     DELETE FROM sqlite_master WHERE tbl_name = 'sqlite_stat2';
444   }
445   sqlite3 db test.db
446   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
447         t5.a>1 AND t5.a<15 AND
448         t6.a>1
449   }
450 } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a<?) (~60000 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
451 do_test analyze2-6.2.6 {
452   execsql { 
453     PRAGMA writable_schema = 1;
454     INSERT INTO sqlite_master SELECT * FROM master;
455   }
456   sqlite3 db test.db
457   execsql ANALYZE
458   eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
459         t5.a>1 AND t5.a<15 AND
460         t6.a>1
461   }
462 } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
463
464 #--------------------------------------------------------------------
465 # These tests, analyze2-7.*, test that the sqlite_stat2 functionality
466 # works in shared-cache mode. Note that these tests reuse the database
467 # created for the analyze2-6.* tests.
468 #
469 ifcapable shared_cache {
470   db close
471   set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
472
473   proc incr_schema_cookie {zDb} {
474     foreach iOffset {24 40} {
475       set cookie [hexio_get_int [hexio_read $zDb $iOffset 4]]
476       incr cookie
477       hexio_write $zDb $iOffset [hexio_render_int32 $cookie]
478     }
479   }
480
481   do_test analyze2-7.1 {
482     sqlite3 db1 test.db
483     sqlite3 db2 test.db
484     db1 cache size 0
485     db2 cache size 0
486     execsql { SELECT count(*) FROM t5 } db1
487   } {20}
488   do_test analyze2-7.2 {
489     incr_schema_cookie test.db
490     execsql { SELECT count(*) FROM t5 } db2
491   } {20}
492   do_test analyze2-7.3 {
493     incr_schema_cookie test.db
494     execsql { SELECT count(*) FROM t5 } db1
495   } {20}
496   do_test analyze2-7.4 {
497     incr_schema_cookie test.db
498     execsql { SELECT count(*) FROM t5 } db2
499   } {20}
500
501   do_test analyze2-7.5 {
502     eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
503           t5.a>1 AND t5.a<15 AND
504           t6.a>1
505     } db1
506   } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
507   do_test analyze2-7.6 {
508     incr_schema_cookie test.db
509     execsql { SELECT * FROM sqlite_master } db2
510     eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
511           t5.a>1 AND t5.a<15 AND
512           t6.a>1
513     } db2
514   } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
515   do_test analyze2-7.7 {
516     incr_schema_cookie test.db
517     execsql { SELECT * FROM sqlite_master } db1
518     eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
519           t5.a>1 AND t5.a<15 AND
520           t6.a>1
521     } db1
522   } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
523
524   do_test analyze2-7.8 {
525     execsql { DELETE FROM sqlite_stat2 } db2
526     execsql { SELECT * FROM sqlite_master } db1
527     eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
528           t5.a>1 AND t5.a<15 AND
529           t6.a>1
530     } db1
531   } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
532   do_test analyze2-7.9 {
533     execsql { SELECT * FROM sqlite_master } db2
534     eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
535           t5.a>1 AND t5.a<15 AND
536           t6.a>1
537     } db2
538   } {0 0 1 {SEARCH TABLE t6 USING COVERING INDEX t6i (a>?) (~1 rows)} 0 1 0 {SEARCH TABLE t5 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
539
540   do_test analyze2-7.10 {
541     incr_schema_cookie test.db
542     execsql { SELECT * FROM sqlite_master } db1
543     eqp { SELECT * FROM t5,t6 WHERE t5.rowid=t6.rowid AND 
544           t5.a>1 AND t5.a<15 AND
545           t6.a>1
546     } db1
547   } {0 0 0 {SEARCH TABLE t5 USING COVERING INDEX t5i (a>? AND a<?) (~1 rows)} 0 1 1 {SEARCH TABLE t6 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)}}
548
549   db1 close
550   db2 close
551   sqlite3_enable_shared_cache $::enable_shared_cache
552 }
553
554 finish_test