Merge trunk into jni-post-3.44 branch.
[sqlite.git] / test / indexexpr1.test
blob51ef73bbf5acba6b5d104cd9279249a0440b6d1a
1 # 2015-08-31
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 file is testing indexes on expressions.
15 set testdir [file dirname $argv0]
16 source $testdir/tester.tcl
18 do_execsql_test indexexpr1-100 {
19   CREATE TABLE t1(a,b,c);
20   INSERT INTO t1(a,b,c)
21       /*  123456789 123456789 123456789 123456789 123456789 123456789 */ 
22   VALUES('In_the_beginning_was_the_Word',1,1),
23         ('and_the_Word_was_with_God',1,2),
24         ('and_the_Word_was_God',1,3),
25         ('The_same_was_in_the_beginning_with_God',2,1),
26         ('All_things_were_made_by_him',3,1),
27         ('and_without_him_was_not_any_thing_made_that_was_made',3,2);
28   CREATE INDEX t1a1 ON t1(substr(a,1,12));
29 } {}
30 do_execsql_test indexexpr1-110 {
31   SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and_the_Word' ORDER BY b, c;
32 } {1 2 | 1 3 |}
33 do_execsql_test indexexpr1-110eqp {
34   EXPLAIN QUERY PLAN
35   SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and_the_Word' ORDER BY b, c;
36 } {/USING INDEX t1a1/}
37 do_execsql_test indexexpr1-120 {
38   SELECT b, c, '|' FROM t1 WHERE 'and_the_Word'==substr(a,1,12) ORDER BY b, c;
39 } {1 2 | 1 3 |}
40 do_execsql_test indexexpr1-120eqp {
41   EXPLAIN QUERY PLAN
42   SELECT b, c, '|' FROM t1 WHERE 'and_the_Word'==substr(a,1,12) ORDER BY b, c;
43 } {/USING INDEX t1a1/}
45 do_execsql_test indexexpr1-130 {
46   CREATE INDEX t1ba ON t1(b,substr(a,2,3),c);
47   SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
48 } {2 3}
49 do_execsql_test indexexpr1-130eqp {
50   EXPLAIN QUERY PLAN
51   SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
52 } {/USING INDEX t1ba/}
54 do_execsql_test indexexpr1-140 {
55   SELECT rowid, substr(a,b,3), '|' FROM t1 ORDER BY 2;
56 } {1 In_ | 2 and | 3 and | 6 d_w | 4 he_ | 5 l_t |}
57 do_execsql_test indexexpr1-141 {
58   CREATE INDEX t1abx ON t1(substr(a,b,3));
59   SELECT rowid FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +rowid;
60 } {1 2 3}
61 do_execsql_test indexexpr1-141eqp {
62   EXPLAIN QUERY PLAN
63   SELECT rowid FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +rowid;
64 } {/USING INDEX t1abx/}
65 do_execsql_test indexexpr1-142 {
66   SELECT rowid FROM t1 WHERE +substr(a,b,3)<='and' ORDER BY +rowid;
67 } {1 2 3}
68 do_execsql_test indexexpr1-150 {
69   SELECT rowid FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
70    ORDER BY +rowid;
71 } {2 3 5}
72 do_execsql_test indexexpr1-150eqp {
73   EXPLAIN QUERY PLAN
74   SELECT rowid FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
75    ORDER BY +rowid;
76 } {/USING INDEX t1abx/}
78 ifcapable altertable {
79   do_execsql_test indexexpr1-160 {
80     ALTER TABLE t1 ADD COLUMN d;
81     UPDATE t1 SET d=length(a);
82     CREATE INDEX t1a2 ON t1(SUBSTR(a, 27, 3)) WHERE d>=29;
83     SELECT rowid, b, c FROM t1
84       WHERE substr(a,27,3)=='ord' AND d>=29;
85   } {1 1 1}
86   do_execsql_test indexexpr1-160eqp {
87     EXPLAIN QUERY PLAN
88       SELECT rowid, b, c FROM t1
89       WHERE substr(a,27,3)=='ord' AND d>=29;
90   } {/USING INDEX t1a2/}
93 # ORDER BY using an indexed expression
95 do_execsql_test indexexpr1-170 {
96   CREATE INDEX t1alen ON t1(length(a));
97   SELECT length(a) FROM t1 ORDER BY length(a);
98 } {20 25 27 29 38 52}
99 do_execsql_test indexexpr1-170eqp {
100   EXPLAIN QUERY PLAN
101   SELECT length(a) FROM t1 ORDER BY length(a);
102 } {/SCAN t1 USING INDEX t1alen/}
103 do_execsql_test indexexpr1-171 {
104   SELECT length(a) FROM t1 ORDER BY length(a) DESC;
105 } {52 38 29 27 25 20}
106 do_execsql_test indexexpr1-171eqp {
107   EXPLAIN QUERY PLAN
108   SELECT length(a) FROM t1 ORDER BY length(a) DESC;
109 } {/SCAN t1 USING INDEX t1alen/}
111 do_execsql_test indexexpr1-200 {
112   DROP TABLE t1;
113   CREATE TABLE t1(id ANY PRIMARY KEY, a,b,c) WITHOUT ROWID;
114   INSERT INTO t1(id,a,b,c)
115   VALUES(1,'In_the_beginning_was_the_Word',1,1),
116         (2,'and_the_Word_was_with_God',1,2),
117         (3,'and_the_Word_was_God',1,3),
118         (4,'The_same_was_in_the_beginning_with_God',2,1),
119         (5,'All_things_were_made_by_him',3,1),
120         (6,'and_without_him_was_not_any_thing_made_that_was_made',3,2);
121   CREATE INDEX t1a1 ON t1(substr(a,1,12));
122 } {}
123 do_execsql_test indexexpr1-210 {
124   SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and_the_Word' ORDER BY b, c;
125 } {1 2 | 1 3 |}
126 do_execsql_test indexexpr1-210eqp {
127   EXPLAIN QUERY PLAN
128   SELECT b, c, '|' FROM t1 WHERE substr(a,1,12)=='and_the_Word' ORDER BY b, c;
129 } {/USING INDEX t1a1/}
130 do_execsql_test indexexpr1-220 {
131   SELECT b, c, '|' FROM t1 WHERE 'and_the_Word'==substr(a,1,12) ORDER BY b, c;
132 } {1 2 | 1 3 |}
133 do_execsql_test indexexpr1-220eqp {
134   EXPLAIN QUERY PLAN
135   SELECT b, c, '|' FROM t1 WHERE 'and_the_Word'==substr(a,1,12) ORDER BY b, c;
136 } {/USING INDEX t1a1/}
138 do_execsql_test indexexpr1-230 {
139   CREATE INDEX t1ba ON t1(b,substr(a,2,3),c);
140   SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
141 } {2 3}
142 do_execsql_test indexexpr1-230eqp {
143   EXPLAIN QUERY PLAN
144   SELECT c FROM t1 WHERE b=1 AND substr(a,2,3)='nd_' ORDER BY c;
145 } {/USING INDEX t1ba/}
147 do_execsql_test indexexpr1-240 {
148   SELECT id, substr(a,b,3), '|' FROM t1 ORDER BY 2;
149 } {1 In_ | 2 and | 3 and | 6 d_w | 4 he_ | 5 l_t |}
150 do_execsql_test indexexpr1-241 {
151   CREATE INDEX t1abx ON t1(substr(a,b,3));
152   SELECT id FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +id;
153 } {1 2 3}
154 do_execsql_test indexexpr1-241eqp {
155   EXPLAIN QUERY PLAN
156   SELECT id FROM t1 WHERE substr(a,b,3)<='and' ORDER BY +id;
157 } {/USING INDEX t1abx/}
158 do_execsql_test indexexpr1-242 {
159   SELECT id FROM t1 WHERE +substr(a,b,3)<='and' ORDER BY +id;
160 } {1 2 3}
161 do_execsql_test indexexpr1-250 {
162   SELECT id FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
163    ORDER BY +id;
164 } {2 3 5}
165 do_execsql_test indexexpr1-250eqp {
166   EXPLAIN QUERY PLAN
167   SELECT id FROM t1 WHERE substr(a,b,3) IN ('and','l_t','xyz')
168    ORDER BY +id;
169 } {/USING INDEX t1abx/}
171 ifcapable altertable {
172   do_execsql_test indexexpr1-260 {
173     ALTER TABLE t1 ADD COLUMN d;
174     UPDATE t1 SET d=length(a);
175     CREATE INDEX t1a2 ON t1(SUBSTR(a, 27, 3)) WHERE d>=29;
176     SELECT id, b, c FROM t1
177       WHERE substr(a,27,3)=='ord' AND d>=29;
178   } {1 1 1}
179   do_execsql_test indexexpr1-260eqp {
180     EXPLAIN QUERY PLAN
181       SELECT id, b, c FROM t1
182       WHERE substr(a,27,3)=='ord' AND d>=29;
183   } {/USING INDEX t1a2/}
187 do_catchsql_test indexexpr1-300 {
188   CREATE TABLE t2(a,b,c); INSERT INTO t2 VALUES(1,2,3);
189   CREATE INDEX t2x1 ON t2(a,b+random());
190 } {1 {non-deterministic functions prohibited in index expressions}}
191 do_catchsql_test indexexpr1-301 {
192   CREATE INDEX t2x1 ON t2(julianday('now',a));
193 } {1 {non-deterministic use of julianday() in an index}}
194 do_catchsql_test indexexpr1-310 {
195   CREATE INDEX t2x2 ON t2(a,b+(SELECT 15));
196 } {1 {subqueries prohibited in index expressions}}
197 do_catchsql_test indexexpr1-320 {
198   CREATE TABLE e1(x,y,UNIQUE(y,substr(x,1,5)));
199 } {1 {expressions prohibited in PRIMARY KEY and UNIQUE constraints}}
200 do_catchsql_test indexexpr1-330 {
201   CREATE TABLE e1(x,y,PRIMARY KEY(y,substr(x,1,5)));
202 } {1 {expressions prohibited in PRIMARY KEY and UNIQUE constraints}}
203 do_catchsql_test indexexpr1-331 {
204   CREATE TABLE e1(x,y,PRIMARY KEY(y,substr(x,1,5))) WITHOUT ROWID;
205 } {1 {expressions prohibited in PRIMARY KEY and UNIQUE constraints}}
206 do_catchsql_test indexexpr1-340 {
207   CREATE TABLE e1(x,y,FOREIGN KEY(substr(y,1,5)) REFERENCES t1);
208 } {1 {near "(": syntax error}}
210 do_execsql_test indexexpr1-400 {
211   CREATE TABLE t3(a,b,c);
212   WITH RECURSIVE c(x) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<30)
213   INSERT INTO t3(a,b,c)
214     SELECT x, printf('ab%04xyz',x), random() FROM c;
215   CREATE UNIQUE INDEX t3abc ON t3(CAST(a AS text), b, substr(c,1,3));
216   SELECT a FROM t3 WHERE CAST(a AS text)<='10' ORDER BY +a;
217   PRAGMA integrity_check;
218 } {1 10 ok}
219 do_catchsql_test indexexpr1-410 {
220   INSERT INTO t3 SELECT * FROM t3 WHERE rowid=10;
221 } {1 {UNIQUE constraint failed: index 't3abc'}}
223 do_execsql_test indexexpr1-500 {
224   CREATE TABLE t5(a);
225   CREATE TABLE cnt(x);
226   WITH RECURSIVE
227     c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
228   INSERT INTO cnt(x) SELECT x FROM c;
229   INSERT INTO t5(a) SELECT printf('abc%03dxyz',x) FROM cnt;
230   CREATE INDEX t5ax ON t5( substr(a,4,3) );
231 } {}
232 do_execsql_test indexexpr1-510 {
233   -- The use of the "k" alias in the WHERE clause is technically
234   -- illegal, but SQLite allows it for historical reasons.  In this
235   -- test and the next, verify that "k" can be used by the t5ax index
236   SELECT substr(a,4,3) AS k FROM cnt, t5 WHERE k=printf('%03d',x);
237 } {001 002 003 004 005}
238 do_execsql_test indexexpr1-510eqp {
239   EXPLAIN QUERY PLAN
240   SELECT substr(a,4,3) AS k FROM cnt, t5 WHERE k=printf('%03d',x);
241 } {/USING INDEX t5ax/}
243 # Skip-scan on an indexed expression
245 do_execsql_test indexexpr1-600 {
246   DROP TABLE IF EXISTS t4;
247   CREATE TABLE t4(a,b,c,d,e,f,g,h,i);
248   CREATE INDEX t4all ON t4(a,b,c<d,e,f,i,h);
249   INSERT INTO t4 VALUES(1,2,3,4,5,6,7,8,9);
250   ANALYZE;
251   DELETE FROM sqlite_stat1;
252   INSERT INTO sqlite_stat1
253     VALUES('t4','t4all','600000 160000 40000 10000 2000 600 100 40 10');
254   ANALYZE sqlite_master;
255   SELECT i FROM t4 WHERE e=5;
256 } {9}
258 # Indexed expressions on both sides of an == in a WHERE clause.
260 do_execsql_test indexexpr1-700 {
261   DROP TABLE IF EXISTS t7;
262   CREATE TABLE t7(a,b,c);
263   INSERT INTO t7(a,b,c) VALUES(1,2,2),('abc','def','def'),(4,5,6);
264   CREATE INDEX t7b ON t7(+b);
265   CREATE INDEX t7c ON t7(+c);
266   SELECT *, '|' FROM t7 WHERE +b=+c ORDER BY +a;
267 } {1 2 2 | abc def def |}
268 do_execsql_test indexexpr1-710 {
269   CREATE TABLE t71(a,b,c);
270   CREATE INDEX t71bc ON t71(b+c);
271   CREATE TABLE t72(x,y,z);
272   CREATE INDEX t72yz ON t72(y+z);
273   INSERT INTO t71(a,b,c) VALUES(1,11,2),(2,7,15),(3,5,4);
274   INSERT INTO t72(x,y,z) VALUES(1,10,3),(2,8,14),(3,9,9);
275   SELECT a, x, '|' FROM t71, t72
276    WHERE b+c=y+z
277   ORDER BY +a, +x;
278 } {1 1 | 2 2 |}
280 # Collating sequences on indexes of expressions
282 do_execsql_test indexexpr1-800 {
283   DROP TABLE IF EXISTS t8;
284   CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT);
285   CREATE UNIQUE INDEX t8bx ON t8(substr(b,2,4) COLLATE nocase);
286   INSERT INTO t8(a,b) VALUES(1,'Alice'),(2,'Bartholemew'),(3,'Cynthia');
287   SELECT * FROM t8 WHERE substr(b,2,4)='ARTH' COLLATE nocase;
288 } {2 Bartholemew}
289 do_catchsql_test indexexpr1-810 {
290   INSERT INTO t8(a,b) VALUES(4,'BARTHMERE');
291 } {1 {UNIQUE constraint failed: index 't8bx'}}
292 do_catchsql_test indexexpr1-820 {
293   DROP INDEX t8bx;
294   CREATE UNIQUE INDEX t8bx ON t8(substr(b,2,4) COLLATE rtrim);
295   INSERT INTO t8(a,b) VALUES(4,'BARTHMERE');
296 } {0 {}}
298 # Check that PRAGMA integrity_check works correctly on a
299 # UNIQUE index that includes rowid and expression terms.
301 do_execsql_test indexexpr1-900 {
302   CREATE TABLE t9(a,b,c,d);
303   CREATE UNIQUE INDEX t9x1 ON t9(c,abs(d),b);
304   INSERT INTO t9(rowid,a,b,c,d) VALUES(1,2,3,4,5);
305   INSERT INTO t9(rowid,a,b,c,d) VALUES(2,NULL,NULL,NULL,NULL);
306   INSERT INTO t9(rowid,a,b,c,d) VALUES(3,NULL,NULL,NULL,NULL);
307   INSERT INTO t9(rowid,a,b,c,d) VALUES(4,5,6,7,8);
308   PRAGMA integrity_check;
309 } {ok}
310 do_catchsql_test indexexpr1-910 {
311   INSERT INTO t9(a,b,c,d) VALUES(5,6,7,-8);
312 } {1 {UNIQUE constraint failed: index 't9x1'}}
314 # Test cases derived from a NEVER() maro failure discovered by
315 # Jonathan Metzman using AFL
317 do_execsql_test indexexpr1-1000 {
318   DROP TABLE IF EXISTS t0;
319   CREATE TABLE t0(a,b,t);
320   CREATE INDEX i ON t0(a in(0,1));
321   INSERT INTO t0 VALUES(0,1,2),(2,3,4),(5,6,7);
322   UPDATE t0 SET b=99 WHERE (a in(0,1))=0;
323   SELECT *, '|' FROM t0 ORDER BY +a;
324 } {0 1 2 | 2 99 4 | 5 99 7 |}
325 do_execsql_test indexexpr1-1010 {
326   UPDATE t0 SET b=88 WHERE (a in(0,1))=1;
327   SELECT *, '|' FROM t0 ORDER BY +a;
328 } {0 88 2 | 2 99 4 | 5 99 7 |}
330 # 2016-10-10
331 # Make sure indexes on expressions skip over initial NULL values in the
332 # index as they are suppose to do.
333 # Ticket https://www.sqlite.org/src/tktview/4baa46491212947
335 do_execsql_test indexexpr1-1100 {
336   DROP TABLE IF EXISTS t1;
337   CREATE TABLE t1(a);
338   INSERT INTO t1 VALUES(NULL),(1);
339   SELECT '1:', typeof(a), a FROM t1 WHERE a<10;
340   SELECT '2:', typeof(a), a FROM t1 WHERE a+0<10;
341   CREATE INDEX t1x1 ON t1(a);
342   CREATE INDEX t1x2 ON t1(a+0);
343   SELECT '3:', typeof(a), a FROM t1 WHERE a<10;
344   SELECT '4:', typeof(a), a FROM t1 WHERE a+0<10;
345 } {1: integer 1 2: integer 1 3: integer 1 4: integer 1}
347 do_execsql_test indexexpr1-1200 {
348   CREATE TABLE t10(a int, b int, c int, d int);
349   INSERT INTO t10(a, b, c, d) VALUES(0, 0, 2, 2);
350   INSERT INTO t10(a, b, c, d) VALUES(0, 0, 0, 0);
351   INSERT INTO t10(a, b, c, d) VALUES(0, 0, 1, 1);
352   INSERT INTO t10(a, b, c, d) VALUES(1, 1, 1, 1);
353   INSERT INTO t10(a, b, c, d) VALUES(1, 1, 0, 0);
354   INSERT INTO t10(a, b, c, d) VALUES(2, 2, 0, 0);
356   SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d;
357 } {
358   0 0 0 2 0 4 2 0 2 2 4 0
360 do_execsql_test indexexpr1-1200.1 {
361   CREATE INDEX t10_ab ON t10(a+b);
363 do_execsql_test indexexpr1-1200.2 {
364   SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d;
365 } {
366   0 0 0 2 0 4 2 0 2 2 4 0
368 do_execsql_test indexexpr1-1200.3 {
369   CREATE INDEX t10_abcd ON t10(a+b,c+d);
371 do_execsql_test indexexpr1-1200.4 {
372   SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d;
373 } {
374   0 0 0 2 0 4 2 0 2 2 4 0
377 # Ticket https://www.sqlite.org/src/tktview/eb703ba7b50c1a
378 # Incorrect result using an index on an expression with a collating function
380 do_execsql_test indexexpr1-1300.1 {
381   CREATE TABLE t1300(a INTEGER PRIMARY KEY, b);
382   INSERT INTO t1300 VALUES(1,'coffee'),(2,'COFFEE'),(3,'stress'),(4,'STRESS');
383   CREATE INDEX t1300bexpr ON t1300( substr(b,4) );
384   SELECT a FROM t1300 WHERE substr(b,4)='ess' COLLATE nocase ORDER BY +a;
385 } {3 4}
387 # Ticket https://sqlite.org/src/tktview/aa98619a
388 # Assertion fault using an index on a constant
390 do_execsql_test indexexpr1-1400 {
391   CREATE TABLE t1400(x TEXT);
392   CREATE INDEX t1400x ON t1400(1);  -- Index on a constant
393   SELECT 1 IN (SELECT 2) FROM t1400;
394 } {}
395 do_execsql_test indexexpr1-1410 {
396   INSERT INTO t1400 VALUES('a'),('b');
397   SELECT 1 IN (SELECT 2) FROM t1400;
398 } {0 0}
399 do_execsql_test indexexpr1-1420 {
400   SELECT 1 IN (SELECT 2 UNION ALL SELECT 1) FROM t1400;
401 } {1 1}
402 do_execsql_test indexexpr1-1430 {
403   DROP INDEX t1400x;
404   CREATE INDEX t1400x ON t1400(abs(15+3));
405   SELECT abs(15+3) IN (SELECT 17 UNION ALL SELECT 18) FROM t1;
406 } {1 1}
408 # 2018-01-02 ticket https://sqlite.org/src/info/dc3f932f5a147771
409 # A REPLACE into a table that uses an index on an expression causes
410 # an assertion fault.  Problem discovered by OSSFuzz.
412 do_execsql_test indexexpr1-1500 {
413   CREATE TABLE t1500(a INT PRIMARY KEY, b INT UNIQUE);
414   CREATE INDEX t1500ab ON t1500(a*b);
415   INSERT INTO t1500(a,b) VALUES(1,2);
416   REPLACE INTO t1500(a,b) VALUES(1,3);  -- formerly caused assertion fault
417   SELECT * FROM t1500;
418 } {1 3}
420 # 2018-01-03 OSSFuzz discovers another test case for the same problem
421 # above.
423 do_execsql_test indexexpr1-1510 {
424   DROP TABLE IF EXISTS t1;
425   CREATE TABLE t1(a PRIMARY KEY,b UNIQUE);
426   REPLACE INTO t1 VALUES(2, 1);
427   REPLACE INTO t1 SELECT 6,1;
428   CREATE INDEX t1aa ON t1(a-a);
429   REPLACE INTO t1 SELECT a, randomblob(a) FROM t1
430 } {}
432 # 2018-01-31 https://www.sqlite.org/src/tktview/343634942dd54ab57b702411
433 # When an index on an expression depends on the string representation of
434 # a numeric table column, trouble can arise since there are multiple
435 # string that can map to the same numeric value.  (Ex: 123, 0123, 000123).
437 do_execsql_test indexexpr1-1600 {
438   DROP TABLE IF EXISTS t1;
439   CREATE TABLE t1 (a INTEGER, b);
440   CREATE INDEX idx1 ON t1 (lower(a));
441   INSERT INTO t1 VALUES('0001234',3);
442   PRAGMA integrity_check;
443 } {ok}
444 do_execsql_test indexexpr1-1610 {
445   INSERT INTO t1 VALUES('1234',0),('001234',2),('01234',1);
446   SELECT b FROM t1 WHERE lower(a)='1234' ORDER BY +b;
447 } {0 1 2 3}
448 do_execsql_test indexexpr1-1620 {
449   SELECT b FROM t1 WHERE lower(a)='01234' ORDER BY +b;
450 } {}
452 # 2019-08-09 https://www.sqlite.org/src/info/9080b6227fabb466
453 # ExprImpliesExpr theorem prover bug:
454 # "(NULL IS FALSE) IS FALSE" does not imply "NULL IS NULL"
456 do_execsql_test indexexpr1-1700 {
457   DROP TABLE IF EXISTS t0;
458   CREATE TABLE t0(c0);
459   INSERT INTO t0(c0) VALUES (0);
460   CREATE INDEX i0 ON t0(NULL > c0) WHERE (NULL NOT NULL);
461   SELECT * FROM t0 WHERE ((NULL IS FALSE) IS FALSE);
462 } {0}
464 # 2019-09-02 https://www.sqlite.org/src/tktview/57af00b6642ecd6848
465 # When the expression of an an index-on-expression references a
466 # table column of type REAL that is actually holding an MEM_IntReal
467 # value, be sure to use the REAL value and not the INT value when
468 # computing the expression.
470 ifcapable like_match_blobs {
471   do_execsql_test indexexpr1-1800 {
472     DROP TABLE IF EXISTS t0;
473     CREATE TABLE t0(c0 REAL, c1 TEXT);
474     CREATE INDEX i0 ON t0(+c0, c0);
475     INSERT INTO t0(c0) VALUES(0);
476     SELECT CAST(+ t0.c0 AS BLOB) LIKE 0 FROM t0; 
477   } {0}
478   do_execsql_test indexexpr1-1810 {
479     SELECT CAST(+ t0.c0 AS BLOB) LIKE '0.0' FROM t0; 
480   } {1}
481   do_execsql_test indexexpr1-1820 {
482     DROP TABLE IF EXISTS t1;
483     CREATE TABLE t1(x REAL);
484     CREATE INDEX t1x ON t1(x, +x);
485     INSERT INTO t1(x) VALUES(2);
486     SELECT +x FROM t1 WHERE x=2;
487   } {2.0}
490 # 2022-04-30 https://sqlite.org/forum/info/7efabf4b03328e57
491 # Assertion fault during a DELETE INDEXED BY.
493 reset_db
494 do_execsql_test indexexpr1-1900 {
495   CREATE TABLE t1(x TEXT PRIMARY KEY, y TEXT, z INT);
496   INSERT INTO t1(x,y,z) VALUES('alpha','ALPHA',1),('bravo','charlie',1);
497   CREATE INDEX i1 ON t1(+y COLLATE NOCASE);
498   SELECT * FROM t1;
499 } {alpha ALPHA 1 bravo charlie 1}
500 do_execsql_test indexexpr1-1910 {
501   DELETE FROM t1 INDEXED BY i1 
502    WHERE x IS +y COLLATE NOCASE IN (SELECT z FROM t1)
503   RETURNING *;
504 } {alpha ALPHA 1}
505 do_execsql_test indexexpr1-1920 {
506   SELECT * FROM t1;
507 } {bravo charlie 1}
509 # 2022-11-28 Ticket 695a1a53de
510 # Improved ability to recognize that an index on an expression is a
511 # covering index.
513 reset_db
514 do_execsql_test indexexpr1-2000 {
515   CREATE TABLE t1(a INT, b TEXT);
516   INSERT INTO t1(a,b) VALUES
517     (10, '{"one":5,"two":6}'),
518     (10, '{"one":50,"two":60}'),
519     (10, '{"three":99}'),
520     (11, '{"one":100,"two":200}');
521   CREATE INDEX t1_one ON t1(a, b->>'one');
522   CREATE INDEX t1_two ON t1(a, b->>'two');
524 do_execsql_test indexexpr1-2010 {
525   EXPLAIN QUERY PLAN
526   SELECT sum(b->>'one') FROM t1 WHERE a=10; /* Query AA */
527 } {/.* t1_one .*/}
528 do_execsql_test indexexpr1-2011 {
529   SELECT sum(b->>'one') FROM t1 WHERE a=10; /* Query AA */
530 } {55}
531 do_execsql_test indexexpr1-2020 {
532   EXPLAIN QUERY PLAN
533   SELECT sum(b->>'two') FROM t1 WHERE a=10; /* Query BB */
534 } {/.* t1_two .*/}
535 do_execsql_test indexexpr1-2021 {
536   SELECT sum(b->>'two') FROM t1 WHERE a=10; /* Query BB */
537 } {66}
538 do_execsql_test indexexpr1-2030 {
539   DROP TABLE t1;
540   CREATE TABLE t1(a INT, b TEXT, c INT, d INT);
541   INSERT INTO t1(a,b,c,d) VALUES
542     (1, '{"x":1}', 12,  3),
543     (1, '{"x":2}',  4,  5),
544     (1, '{"x":1}',  6, 11),
545     (2, '{"x":1}', 22,  3),
546     (2, '{"x":2}',  4,  5),
547     (3, '{"x":1}',  6,  7);
548   CREATE INDEX t1x ON t1(d, a, b->>'x', c);
550 do_execsql_test indexexpr1-2030 {
551   SELECT a,
552        SUM(1)                              AS t1,
553        SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
554        SUM(c)                              AS t3,
555        SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
556     FROM t1;
557 } {1 6 4 54 46}
558 do_execsql_test indexexpr1-2030 {
559   explain query plan
560   SELECT a,
561        SUM(1)                              AS t1,
562        SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2,
563        SUM(c)                              AS t3,
564        SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4
565     FROM t1;
566 } {/.*SCAN t1 USING INDEX t1x.*/}
568 reset_db
569 do_execsql_test indexexpr1-2100 {
570   CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
571   INSERT INTO t1(a,b) VALUES(1,0);
572   CREATE INDEX x1 ON t1( "y" );
573   CREATE INDEX x2 ON t1( +"y" );
574   CREATE INDEX x3 ON t1( +'y' );
575   CREATE INDEX x4 ON t1( "y*" );
577 do_execsql_test indexexpr1-2110 {
578   UPDATE t1 SET b=100 WHERE (SELECT 'y') GLOB "y";
579   SELECT b FROM t1;
580 } 100
581 do_execsql_test indexexpr1-2120 {
582   UPDATE t1 SET b=200 WHERE (SELECT 'y') GLOB +"y";
583   SELECT b FROM t1;
584 } 200
585 do_execsql_test indexexpr1-2130 {
586   UPDATE t1 SET b=300 WHERE (SELECT 'y') GLOB +'y';
587   SELECT b FROM t1;
588 } 300
589 do_execsql_test indexexpr1-2140 {
590   UPDATE t1 SET b=400 WHERE (SELECT 'y') GLOB "y*";
591   SELECT b FROM t1;
592 } 400
594 # 2023-04-18 Forum post https://sqlite.org/forum/forumpost/f34e32d120 from
595 # Alexis King.
597 # This problem originates at check-in b9190d3da70c4171 (2022-11-25).
598 # A similar problem arose on 2023-03-04 at
599 # https://sqlite.org/forum/forumpost/a68313d054 and was fixed at
600 # check-in e06973876993926f.  See the test case tkt-99378-400.
602 reset_db
603 do_execsql_test indexexpr1-2200 {
604   CREATE TABLE t1(id INTEGER PRIMARY KEY, tag INT);
605   INSERT INTO t1 VALUES (0, 7), (1, 8);
606   CREATE TABLE t2(type INT, t1_id  INT, value  INT);
607   INSERT INTO t2 VALUES (0, 0, 100), (0, 1, 101);
608   CREATE INDEX t1x ON t1(-tag);
609   SELECT u.tag, v.max_value
610     FROM (SELECT tag FROM t1 GROUP BY -tag) u
611     JOIN (SELECT t1.tag AS "tag", t2.type AS "type",
612                  MAX(t2.value) AS "max_value"
613             FROM t1
614                  JOIN t2 ON t2.t1_id = t1.id
615            GROUP BY t2.type, t1.tag
616          ) v ON v.type = 0 AND v.tag = u.tag;
617 } {7 100 8 101}
619 finish_test