Improved comments, including a typo fix, on the whereLoopCheaperProperSubset()
[sqlite.git] / test / autoindex1.test
blobbf9eca84c27633786b46e41d1f5c812b99b8feb8
1 # 2010 April 07
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #*************************************************************************
11 # This file implements regression tests for SQLite library.  The
12 # focus of this script is testing automatic index creation logic.
14 # EVIDENCE-OF: R-34271-33106 PRAGMA automatic_index; PRAGMA
15 # automatic_index = boolean; Query, set, or clear the automatic indexing
16 # capability.
18 set testdir [file dirname $argv0]
19 source $testdir/tester.tcl
21 # If the library is not compiled with automatic index support then
22 # skip all tests in this file.
24 ifcapable {!autoindex} {
25   finish_test
26   return
29 # Setup for logging 
30 db close
31 sqlite3_shutdown
32 test_sqlite3_log [list lappend ::log]
33 set ::log [list]
34 sqlite3 db test.db
37 # With automatic index turned off, we do a full scan of the T2 table
38 do_test autoindex1-100 {
39   db eval {
40     CREATE TABLE t1(a,b);
41     INSERT INTO t1 VALUES(1,11);
42     INSERT INTO t1 VALUES(2,22);
43     INSERT INTO t1 SELECT a+2, b+22 FROM t1;
44     INSERT INTO t1 SELECT a+4, b+44 FROM t1;
45     CREATE TABLE t2(c,d);
46     INSERT INTO t2 SELECT a, 900+b FROM t1;
47   }
48   db eval {
49     PRAGMA automatic_index=OFF;
50     SELECT b, d FROM t1 JOIN t2 ON a=c ORDER BY b;
51   }
52 } {11 911 22 922 33 933 44 944 55 955 66 966 77 977 88 988}
53 do_test autoindex1-101 {
54   db status step
55 } {63}
56 do_test autoindex1-102 {
57   db status autoindex
58 } {0}
60 # With autoindex turned on, we build an index once and then use that index
61 # to find T2 values.
62 do_test autoindex1-110 {
63   db eval {
64     PRAGMA automatic_index=ON;
65     SELECT b, d FROM t1 JOIN t2 ON a=c ORDER BY b;
66   }
67 } {11 911 22 922 33 933 44 944 55 955 66 966 77 977 88 988}
68 do_test autoindex1-111 {
69   db status step
70 } {7}
71 do_test autoindex1-112 {
72   db status autoindex
73 } {7}
74 do_test autoindex1-113 {
75   set ::log
76 } {SQLITE_WARNING_AUTOINDEX {automatic index on t2(c)}}
78 db close
79 sqlite3_shutdown
80 test_sqlite3_log
81 sqlite3_initialize
82 sqlite3 db test.db
84 # The same test as above, but this time the T2 query is a subquery rather
85 # than a join.
86 do_test autoindex1-200 {
87   db eval {
88     PRAGMA automatic_index=OFF;
89     SELECT b, (SELECT d FROM t2 WHERE c=a) FROM t1;
90   }
91 } {11 911 22 922 33 933 44 944 55 955 66 966 77 977 88 988}
92 do_test autoindex1-201 {
93   db status step
94 } {35}
95 do_test autoindex1-202 {
96   db status autoindex
97 } {0}
98 do_test autoindex1-210 {
99   db eval {
100     PRAGMA automatic_index=ON;
101     ANALYZE;
102     UPDATE sqlite_stat1 SET stat='10000' WHERE tbl='t1';
103     -- Table t2 actually contains 8 rows.
104     UPDATE sqlite_stat1 SET stat='16' WHERE tbl='t2';
105     ANALYZE sqlite_master;
106     SELECT b, (SELECT d FROM t2 WHERE c=a) FROM t1;
107   }
108 } {11 911 22 922 33 933 44 944 55 955 66 966 77 977 88 988}
109 do_test autoindex1-211 {
110   db status step
111 } {7}
112 do_test autoindex1-212 {
113   db status autoindex
114 } {7}
117 # Modify the second table of the join while the join is in progress
119 do_execsql_test autoindex1-299 {
120   UPDATE sqlite_stat1 SET stat='10000' WHERE tbl='t2';
121   ANALYZE sqlite_master;
122   EXPLAIN QUERY PLAN
123   SELECT b, d FROM t1 CROSS JOIN t2 ON (c=a);
124 } {/AUTOMATIC COVERING INDEX/}
125 do_test autoindex1-300 {
126   set r {}
127   db eval {SELECT b, d FROM t1 CROSS JOIN t2 ON (c=a)} {
128     lappend r $b $d
129     db eval {UPDATE t2 SET d=d+1}
130   }
131   set r
132 } {11 911 22 922 33 933 44 944 55 955 66 966 77 977 88 988}
133 do_test autoindex1-310 {
134   db eval {SELECT d FROM t2 ORDER BY d}
135 } {919 930 941 952 963 974 985 996}
137 # The next test does a 10-way join on unindexed tables.  Without
138 # automatic indices, the join will take a long time to complete.
139 # With automatic indices, it should only take about a second.
141 do_test autoindex1-400 {
142   db eval {
143     CREATE TABLE t4(a, b);
144     INSERT INTO t4 VALUES(1,2);
145     INSERT INTO t4 VALUES(2,3);
146   }
147   for {set n 2} {$n<4096} {set n [expr {$n+$n}]} {
148     db eval {INSERT INTO t4 SELECT a+$n, b+$n FROM t4}
149   }
150   db eval {
151     SELECT count(*) FROM t4;
152   }
153 } {4096}
154 do_test autoindex1-401 {
155   db eval {
156     SELECT count(*)
157       FROM t4 AS x1
158       JOIN t4 AS x2 ON x2.a=x1.b
159       JOIN t4 AS x3 ON x3.a=x2.b
160       JOIN t4 AS x4 ON x4.a=x3.b
161       JOIN t4 AS x5 ON x5.a=x4.b
162       JOIN t4 AS x6 ON x6.a=x5.b
163       JOIN t4 AS x7 ON x7.a=x6.b
164       JOIN t4 AS x8 ON x8.a=x7.b
165       JOIN t4 AS x9 ON x9.a=x8.b
166       JOIN t4 AS x10 ON x10.a=x9.b;
167   }
168 } {4087}
170 # Ticket [8011086c85c6c404014c947fcf3eb9f42b184a0d] from 2010-07-08
171 # Make sure automatic indices are not created for the RHS of an IN expression
172 # that is not a correlated subquery.
174 do_execsql_test autoindex1-500 {
175   CREATE TABLE t501(a INTEGER PRIMARY KEY, b);
176   CREATE TABLE t502(x INTEGER PRIMARY KEY, y);
177   INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t501',null,'1000000');
178   INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t502',null,'1000');
179   ANALYZE sqlite_master;
180   EXPLAIN QUERY PLAN
181   SELECT b FROM t501
182    WHERE t501.a IN (SELECT x FROM t502 WHERE y=?);
183 } {
184   0 0 0 {SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)} 
185   0 0 0 {EXECUTE LIST SUBQUERY 1} 
186   1 0 0 {SCAN TABLE t502}
188 do_execsql_test autoindex1-501 {
189   EXPLAIN QUERY PLAN
190   SELECT b FROM t501
191    WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
192 } {
193   0 0 0 {SCAN TABLE t501} 
194   0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1} 
195   1 0 0 {SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)}
197 do_execsql_test autoindex1-502 {
198   EXPLAIN QUERY PLAN
199   SELECT b FROM t501
200    WHERE t501.a=123
201      AND t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
202 } {
203   0 0 0 {SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)} 
204   0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1} 
205   1 0 0 {SCAN TABLE t502}
209 # The following code checks a performance regression reported on the
210 # mailing list on 2010-10-19.  The problem is that the nRowEst field
211 # of ephermeral tables was not being initialized correctly and so no
212 # automatic index was being created for the emphemeral table when it was
213 # used as part of a join.
215 do_execsql_test autoindex1-600 {
216   CREATE TABLE flock_owner(
217     owner_rec_id INTEGER CONSTRAINT flock_owner_key PRIMARY KEY,
218     flock_no VARCHAR(6) NOT NULL REFERENCES flock (flock_no),
219     owner_person_id INTEGER NOT NULL REFERENCES person (person_id),
220     owner_change_date TEXT, last_changed TEXT NOT NULL,
221     CONSTRAINT fo_owner_date UNIQUE (flock_no, owner_change_date)
222   );
223   CREATE TABLE sheep (
224     Sheep_No char(7) NOT NULL,
225     Date_of_Birth char(8),
226     Sort_DoB text,
227     Flock_Book_Vol char(2),
228     Breeder_No char(6),
229     Breeder_Person integer,
230     Originating_Flock char(6),
231     Registering_Flock char(6),
232     Tag_Prefix char(9),
233     Tag_No char(15),
234     Sort_Tag_No integer,
235     Breeders_Temp_Tag char(15),
236     Sex char(1),
237     Sheep_Name char(32),
238     Sire_No char(7),
239     Dam_No char(7),
240     Register_Code char(1),
241     Colour char(48),
242     Colour_Code char(2),
243     Pattern_Code char(8),
244     Horns char(1),
245     Litter_Size char(1),
246     Coeff_of_Inbreeding real,
247     Date_of_Registration text,
248     Date_Last_Changed text,
249     UNIQUE(Sheep_No));
250   CREATE INDEX fo_flock_no_index  
251               ON flock_owner (flock_no);
252   CREATE INDEX fo_owner_change_date_index  
253               ON flock_owner (owner_change_date);
254   CREATE INDEX fo_owner_person_id_index  
255               ON flock_owner (owner_person_id);
256   CREATE INDEX sheep_org_flock_index  
257            ON sheep (originating_flock);
258   CREATE INDEX sheep_reg_flock_index  
259            ON sheep (registering_flock);
260   EXPLAIN QUERY PLAN
261   SELECT x.sheep_no, x.registering_flock, x.date_of_registration
262    FROM sheep x LEFT JOIN
263        (SELECT s.sheep_no, prev.flock_no, prev.owner_person_id,
264        s.date_of_registration, prev.owner_change_date
265        FROM sheep s JOIN flock_owner prev ON s.registering_flock =
266    prev.flock_no
267        AND (prev.owner_change_date <= s.date_of_registration || ' 00:00:00')
268        WHERE NOT EXISTS
269            (SELECT 'x' FROM flock_owner later
270            WHERE prev.flock_no = later.flock_no
271            AND later.owner_change_date > prev.owner_change_date
272            AND later.owner_change_date <= s.date_of_registration||' 00:00:00')
273        ) y ON x.sheep_no = y.sheep_no
274    WHERE y.sheep_no IS NULL
275    ORDER BY x.registering_flock;
276 } {
277   1 0 0 {SCAN TABLE sheep AS s} 
278   1 1 1 {SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)} 
279   1 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2} 
280   2 0 0 {SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)} 
281   0 0 0 {SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index} 
282   0 1 1 {SEARCH SUBQUERY 1 AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)}
286 do_execsql_test autoindex1-700 {
287   CREATE TABLE t5(a, b, c);
288   EXPLAIN QUERY PLAN SELECT a FROM t5 WHERE b=10 ORDER BY c;
289 } {
290   0 0 0 {SCAN TABLE t5} 
291   0 0 0 {USE TEMP B-TREE FOR ORDER BY}
294 # The following checks a performance issue reported on the sqlite-dev
295 # mailing list on 2013-01-10
297 do_execsql_test autoindex1-800 {
298   CREATE TABLE accounts(
299     _id INTEGER PRIMARY KEY AUTOINCREMENT,
300     account_name TEXT,
301     account_type TEXT,
302     data_set TEXT
303   );
304   CREATE TABLE data(
305     _id INTEGER PRIMARY KEY AUTOINCREMENT,
306     package_id INTEGER REFERENCES package(_id),
307     mimetype_id INTEGER REFERENCES mimetype(_id) NOT NULL,
308     raw_contact_id INTEGER REFERENCES raw_contacts(_id) NOT NULL,
309     is_read_only INTEGER NOT NULL DEFAULT 0,
310     is_primary INTEGER NOT NULL DEFAULT 0,
311     is_super_primary INTEGER NOT NULL DEFAULT 0,
312     data_version INTEGER NOT NULL DEFAULT 0,
313     data1 TEXT,
314     data2 TEXT,
315     data3 TEXT,
316     data4 TEXT,
317     data5 TEXT,
318     data6 TEXT,
319     data7 TEXT,
320     data8 TEXT,
321     data9 TEXT,
322     data10 TEXT,
323     data11 TEXT,
324     data12 TEXT,
325     data13 TEXT,
326     data14 TEXT,
327     data15 TEXT,
328     data_sync1 TEXT,
329     data_sync2 TEXT,
330     data_sync3 TEXT,
331     data_sync4 TEXT 
332   );
333   CREATE TABLE mimetypes(
334     _id INTEGER PRIMARY KEY AUTOINCREMENT,
335     mimetype TEXT NOT NULL
336   );
337   CREATE TABLE raw_contacts(
338     _id INTEGER PRIMARY KEY AUTOINCREMENT,
339     account_id INTEGER REFERENCES accounts(_id),
340     sourceid TEXT,
341     raw_contact_is_read_only INTEGER NOT NULL DEFAULT 0,
342     version INTEGER NOT NULL DEFAULT 1,
343     dirty INTEGER NOT NULL DEFAULT 0,
344     deleted INTEGER NOT NULL DEFAULT 0,
345     contact_id INTEGER REFERENCES contacts(_id),
346     aggregation_mode INTEGER NOT NULL DEFAULT 0,
347     aggregation_needed INTEGER NOT NULL DEFAULT 1,
348     custom_ringtone TEXT,
349     send_to_voicemail INTEGER NOT NULL DEFAULT 0,
350     times_contacted INTEGER NOT NULL DEFAULT 0,
351     last_time_contacted INTEGER,
352     starred INTEGER NOT NULL DEFAULT 0,
353     display_name TEXT,
354     display_name_alt TEXT,
355     display_name_source INTEGER NOT NULL DEFAULT 0,
356     phonetic_name TEXT,
357     phonetic_name_style TEXT,
358     sort_key TEXT,
359     sort_key_alt TEXT,
360     name_verified INTEGER NOT NULL DEFAULT 0,
361     sync1 TEXT,
362     sync2 TEXT,
363     sync3 TEXT,
364     sync4 TEXT,
365     sync_uid TEXT,
366     sync_version INTEGER NOT NULL DEFAULT 1,
367     has_calendar_event INTEGER NOT NULL DEFAULT 0,
368     modified_time INTEGER,
369     is_restricted INTEGER DEFAULT 0,
370     yp_source TEXT,
371     method_selected INTEGER DEFAULT 0,
372     custom_vibration_type INTEGER DEFAULT 0,
373     custom_ringtone_path TEXT,
374     message_notification TEXT,
375     message_notification_path TEXT
376   );
377   CREATE INDEX data_mimetype_data1_index ON data (mimetype_id,data1);
378   CREATE INDEX data_raw_contact_id ON data (raw_contact_id);
379   CREATE UNIQUE INDEX mime_type ON mimetypes (mimetype);
380   CREATE INDEX raw_contact_sort_key1_index ON raw_contacts (sort_key);
381   CREATE INDEX raw_contact_sort_key2_index ON raw_contacts (sort_key_alt);
382   CREATE INDEX raw_contacts_contact_id_index ON raw_contacts (contact_id);
383   CREATE INDEX raw_contacts_source_id_account_id_index
384       ON raw_contacts (sourceid, account_id);
385   ANALYZE sqlite_master;
386   INSERT INTO sqlite_stat1
387      VALUES('raw_contacts','raw_contact_sort_key2_index','1600 4');
388   INSERT INTO sqlite_stat1
389      VALUES('raw_contacts','raw_contact_sort_key1_index','1600 4');
390   INSERT INTO sqlite_stat1
391      VALUES('raw_contacts','raw_contacts_source_id_account_id_index',
392             '1600 1600 1600');
393   INSERT INTO sqlite_stat1
394      VALUES('raw_contacts','raw_contacts_contact_id_index','1600 1');
395   INSERT INTO sqlite_stat1 VALUES('mimetypes','mime_type','12 1');
396   INSERT INTO sqlite_stat1
397      VALUES('data','data_mimetype_data1_index','9819 2455 3');
398   INSERT INTO sqlite_stat1 VALUES('data','data_raw_contact_id','9819 7');
399   INSERT INTO sqlite_stat1 VALUES('accounts',NULL,'1');
400   DROP TABLE IF EXISTS sqlite_stat3;
401   ANALYZE sqlite_master;
402   
403   EXPLAIN QUERY PLAN
404   SELECT * FROM 
405         data JOIN mimetypes ON (data.mimetype_id=mimetypes._id) 
406              JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id) 
407              JOIN accounts ON (raw_contacts.account_id=accounts._id)
408    WHERE mimetype_id=10 AND data14 IS NOT NULL;
409 } {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
410 do_execsql_test autoindex1-801 {
411   EXPLAIN QUERY PLAN
412   SELECT * FROM 
413         data JOIN mimetypes ON (data.mimetype_id=mimetypes._id) 
414              JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id) 
415              JOIN accounts ON (raw_contacts.account_id=accounts._id)
416    WHERE mimetypes._id=10 AND data14 IS NOT NULL;
417 } {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
419 # Another test case from an important user of SQLite.  The key feature of
420 # this test is that the "aggindex" subquery should make use of an
421 # automatic index.  If it does, the query is fast.  If it does not, the
422 # query is deathly slow.  It worked OK in 3.7.17 but started going slow
423 # with version 3.8.0.  The problem was fixed for 3.8.7 by reducing the
424 # cost estimate for automatic indexes on views and subqueries.
426 db close
427 forcedelete test.db
428 sqlite3 db test.db
429 do_execsql_test autoindex1-900 {
430   CREATE TABLE messages (ROWID INTEGER PRIMARY KEY AUTOINCREMENT, message_id, document_id BLOB, in_reply_to, remote_id INTEGER, sender INTEGER, subject_prefix, subject INTEGER, date_sent INTEGER, date_received INTEGER, date_created INTEGER, date_last_viewed INTEGER, mailbox INTEGER, remote_mailbox INTEGER, original_mailbox INTEGER, flags INTEGER, read, flagged, size INTEGER, color, encoding, type INTEGER, pad, conversation_id INTEGER DEFAULT -1, snippet TEXT DEFAULT NULL, fuzzy_ancestor INTEGER DEFAULT NULL, automated_conversation INTEGER DEFAULT 0, root_status INTEGER DEFAULT -1, conversation_position INTEGER DEFAULT -1);
431   CREATE INDEX date_index ON messages(date_received);
432   CREATE INDEX date_last_viewed_index ON messages(date_last_viewed);
433   CREATE INDEX date_created_index ON messages(date_created);
434   CREATE INDEX message_message_id_mailbox_index ON messages(message_id, mailbox);
435   CREATE INDEX message_document_id_index ON messages(document_id);
436   CREATE INDEX message_read_index ON messages(read);
437   CREATE INDEX message_flagged_index ON messages(flagged);
438   CREATE INDEX message_mailbox_index ON messages(mailbox, date_received);
439   CREATE INDEX message_remote_mailbox_index ON messages(remote_mailbox, remote_id);
440   CREATE INDEX message_type_index ON messages(type);
441   CREATE INDEX message_conversation_id_conversation_position_index ON messages(conversation_id, conversation_position);
442   CREATE INDEX message_fuzzy_ancestor_index ON messages(fuzzy_ancestor);
443   CREATE INDEX message_subject_fuzzy_ancestor_index ON messages(subject, fuzzy_ancestor);
444   CREATE INDEX message_sender_subject_automated_conversation_index ON messages(sender, subject, automated_conversation);
445   CREATE INDEX message_sender_index ON messages(sender);
446   CREATE INDEX message_root_status ON messages(root_status);
447   CREATE TABLE subjects (ROWID INTEGER PRIMARY KEY, subject COLLATE RTRIM, normalized_subject COLLATE RTRIM);
448   CREATE INDEX subject_subject_index ON subjects(subject);
449   CREATE INDEX subject_normalized_subject_index ON subjects(normalized_subject);
450   CREATE TABLE addresses (ROWID INTEGER PRIMARY KEY, address COLLATE NOCASE, comment, UNIQUE(address, comment));
451   CREATE INDEX addresses_address_index ON addresses(address);
452   CREATE TABLE mailboxes (ROWID INTEGER PRIMARY KEY, url UNIQUE, total_count INTEGER DEFAULT 0, unread_count INTEGER DEFAULT 0, unseen_count INTEGER DEFAULT 0, deleted_count INTEGER DEFAULT 0, unread_count_adjusted_for_duplicates INTEGER DEFAULT 0, change_identifier, source INTEGER, alleged_change_identifier);
453   CREATE INDEX mailboxes_source_index ON mailboxes(source);
454   CREATE TABLE labels (ROWID INTEGER PRIMARY KEY, message_id INTEGER NOT NULL, mailbox_id INTEGER NOT NULL, UNIQUE(message_id, mailbox_id));
455   CREATE INDEX labels_message_id_mailbox_id_index ON labels(message_id, mailbox_id);
456   CREATE INDEX labels_mailbox_id_index ON labels(mailbox_id);
457   
458   explain query plan
459   SELECT messages.ROWID,
460          messages.message_id,
461          messages.remote_id,
462          messages.date_received,
463          messages.date_sent,
464          messages.flags,
465          messages.size,
466          messages.color,
467          messages.date_last_viewed,
468          messages.subject_prefix,
469          subjects.subject,
470          sender.comment,
471          sender.address,
472          NULL,
473          messages.mailbox,
474          messages.original_mailbox,
475          NULL,
476          NULL,
477          messages.type,
478          messages.document_id,
479          sender,
480          NULL,
481          messages.conversation_id,
482          messages.conversation_position,
483          agglabels.labels
484    FROM mailboxes AS mailbox
485         JOIN messages ON mailbox.ROWID = messages.mailbox
486         LEFT OUTER JOIN subjects ON messages.subject = subjects.ROWID
487         LEFT OUTER JOIN addresses AS sender ON messages.sender = sender.ROWID
488         LEFT OUTER JOIN (
489                SELECT message_id, group_concat(mailbox_id) as labels
490                FROM labels GROUP BY message_id
491              ) AS agglabels ON messages.ROWID = agglabels.message_id
492   WHERE (mailbox.url = 'imap://email.app@imap.gmail.com/%5BGmail%5D/All%20Mail')
493     AND (messages.ROWID IN (
494             SELECT labels.message_id
495               FROM labels JOIN mailboxes ON labels.mailbox_id = mailboxes.ROWID
496              WHERE mailboxes.url = 'imap://email.app@imap.gmail.com/INBOX'))
497     AND messages.mailbox in (6,12,18,24,30,36,42,1,7,13,19,25,31,37,43,2,8,
498                              14,20,26,32,38,3,9,15,21,27,33,39,4,10,16,22,28,
499                              34,40,5,11,17,23,35,41)
500    ORDER BY date_received DESC;
501 } {/agglabels USING AUTOMATIC COVERING INDEX/}
503 # A test case for VIEWs
505 do_execsql_test autoindex1-901 {
506   CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z);
507   CREATE TABLE t2(a, b);
508   CREATE VIEW agg2 AS SELECT a, sum(b) AS m FROM t2 GROUP BY a;
509   EXPLAIN QUERY PLAN
510   SELECT t1.z, agg2.m
511     FROM t1 JOIN agg2 ON t1.y=agg2.m
512    WHERE t1.x IN (1,2,3);
513 } {/USING AUTOMATIC COVERING INDEX/}
515 # 2015-04-15:  A NULL CollSeq pointer in automatic index creation.
517 do_execsql_test autoindex1-920 {
518   CREATE TABLE t920(x);
519   INSERT INTO t920 VALUES(3),(4),(5);
520   SELECT * FROM t920,(SELECT 0 FROM t920),(VALUES(9)) WHERE 5 IN (x);
521 } {5 0 9 5 0 9 5 0 9}
523 #-------------------------------------------------------------------------
524 # An IS term from the WHERE clause of a LEFT JOIN cannot be used as an
525 # index driver for the RHS of a LEFT JOIN. Prior to this being fixed,
526 # the following SELECT count(*) would incorrectly return 1.
528 do_execsql_test autoindex1-1010 {
529   CREATE TABLE t11(w);
530   CREATE TABLE t12(y);
531   INSERT INTO t11 VALUES(NULL);
532   INSERT INTO t12 VALUES('notnull');
534 do_execsql_test autoindex1-1020 {
535   SELECT count(*) FROM t11 LEFT JOIN t12 WHERE t12.y IS t11.w;
536 } 0
541 finish_test