persistentstorage/sqlite3api/TEST/TclScript/where4.test
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 # 2006 October 27
       
     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 # This file implements regression tests for SQLite library.  The
       
    12 # focus of this file is testing the use of indices in WHERE clauses.
       
    13 # This file was created when support for optimizing IS NULL phrases
       
    14 # was added.  And so the principle purpose of this file is to test
       
    15 # that IS NULL phrases are correctly optimized.  But you can never
       
    16 # have too many tests, so some other tests are thrown in as well.
       
    17 #
       
    18 # $Id: where4.test,v 1.6 2007/12/10 05:03:48 danielk1977 Exp $
       
    19 
       
    20 set testdir [file dirname $argv0]
       
    21 source $testdir/tester.tcl
       
    22 
       
    23 ifcapable !tclvar||!bloblit {
       
    24   finish_test
       
    25   return
       
    26 }
       
    27 
       
    28 # Build some test data
       
    29 #
       
    30 do_test where4-1.0 {
       
    31   execsql {
       
    32     CREATE TABLE t1(w, x, y);
       
    33     CREATE INDEX i1wxy ON t1(w,x,y);
       
    34     INSERT INTO t1 VALUES(1,2,3);
       
    35     INSERT INTO t1 VALUES(1,NULL,3);
       
    36     INSERT INTO t1 VALUES('a','b','c');
       
    37     INSERT INTO t1 VALUES('a',NULL,'c');
       
    38     INSERT INTO t1 VALUES(X'78',x'79',x'7a');
       
    39     INSERT INTO t1 VALUES(X'78',NULL,X'7A');
       
    40     INSERT INTO t1 VALUES(NULL,NULL,NULL);
       
    41     SELECT count(*) FROM t1;
       
    42   }
       
    43 } {7}
       
    44 
       
    45 # Do an SQL statement.  Append the search count to the end of the result.
       
    46 #
       
    47 proc count sql {
       
    48   set ::sqlite_search_count 0
       
    49   return [concat [execsql $sql] $::sqlite_search_count]
       
    50 }
       
    51 
       
    52 # Verify that queries use an index.  We are using the special variable
       
    53 # "sqlite_search_count" which tallys the number of executions of MoveTo
       
    54 # and Next operators in the VDBE.  By verifing that the search count is
       
    55 # small we can be assured that indices are being used properly.
       
    56 #
       
    57 do_test where4-1.1 {
       
    58   count {SELECT rowid FROM t1 WHERE w IS NULL}
       
    59 } {7 2}
       
    60 do_test where4-1.2 {
       
    61   count {SELECT rowid FROM t1 WHERE +w IS NULL}
       
    62 } {7 6}
       
    63 do_test where4-1.3 {
       
    64   count {SELECT rowid FROM t1 WHERE w=1 AND x IS NULL}
       
    65 } {2 2}
       
    66 do_test where4-1.4 {
       
    67   count {SELECT rowid FROM t1 WHERE w=1 AND +x IS NULL}
       
    68 } {2 3}
       
    69 do_test where4-1.5 {
       
    70   count {SELECT rowid FROM t1 WHERE w=1 AND x>0}
       
    71 } {1 2}
       
    72 do_test where4-1.6 {
       
    73   count {SELECT rowid FROM t1 WHERE w=1 AND x<9}
       
    74 } {1 3}
       
    75 do_test where4-1.7 {
       
    76   count {SELECT rowid FROM t1 WHERE w=1 AND x IS NULL AND y=3}
       
    77 } {2 2}
       
    78 do_test where4-1.8 {
       
    79   count {SELECT rowid FROM t1 WHERE w=1 AND x IS NULL AND y>2}
       
    80 } {2 2}
       
    81 do_test where4-1.9 {
       
    82   count {SELECT rowid FROM t1 WHERE w='a' AND x IS NULL AND y='c'}
       
    83 } {4 2}
       
    84 do_test where4-1.10 {
       
    85   count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL}
       
    86 } {6 2}
       
    87 do_test where4-1.11 {
       
    88   count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL AND y=123}
       
    89 } {1}
       
    90 do_test where4-1.12 {
       
    91   count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL AND y=x'7A'}
       
    92 } {6 2}
       
    93 do_test where4-1.13 {
       
    94   count {SELECT rowid FROM t1 WHERE w IS NULL AND x IS NULL}
       
    95 } {7 2}
       
    96 do_test where4-1.14 {
       
    97   count {SELECT rowid FROM t1 WHERE w IS NULL AND x IS NULL AND y IS NULL}
       
    98 } {7 2}
       
    99 do_test where4-1.15 {
       
   100   count {SELECT rowid FROM t1 WHERE w IS NULL AND x IS NULL AND y<0}
       
   101 } {2}
       
   102 do_test where4-1.16 {
       
   103   count {SELECT rowid FROM t1 WHERE w IS NULL AND x IS NULL AND y>=0}
       
   104 } {1}
       
   105 
       
   106 do_test where4-2.1 {
       
   107   execsql {SELECT rowid FROM t1 ORDER BY w, x, y}
       
   108 } {7 2 1 4 3 6 5}
       
   109 do_test where4-2.2 {
       
   110   execsql {SELECT rowid FROM t1 ORDER BY w DESC, x, y}
       
   111 } {6 5 4 3 2 1 7}
       
   112 do_test where4-2.3 {
       
   113   execsql {SELECT rowid FROM t1 ORDER BY w, x DESC, y}
       
   114 } {7 1 2 3 4 5 6}
       
   115 
       
   116 
       
   117 # Ticket #2177
       
   118 #
       
   119 # Suppose you have a left join where the right table of the left
       
   120 # join (the one that can be NULL) has an index on two columns.
       
   121 # The first indexed column is used in the ON clause of the join.
       
   122 # The second indexed column is used in the WHERE clause with an IS NULL
       
   123 # constraint.  It is not allowed to use the IS NULL optimization to
       
   124 # optimize the query because the second column might be NULL because
       
   125 # the right table did not match - something the index does not know
       
   126 # about.
       
   127 #
       
   128 do_test where4-3.1 {
       
   129   execsql {
       
   130     CREATE TABLE t2(a);
       
   131     INSERT INTO t2 VALUES(1);
       
   132     INSERT INTO t2 VALUES(2);
       
   133     INSERT INTO t2 VALUES(3);
       
   134     CREATE TABLE t3(x,y,UNIQUE(x,y));
       
   135     INSERT INTO t3 VALUES(1,11);
       
   136     INSERT INTO t3 VALUES(2,NULL);
       
   137  
       
   138     SELECT * FROM t2 LEFT JOIN t3 ON a=x WHERE +y IS NULL;
       
   139   }
       
   140 } {2 2 {} 3 {} {}}
       
   141 do_test where4-3.2 {
       
   142   execsql {
       
   143     SELECT * FROM t2 LEFT JOIN t3 ON a=x WHERE y IS NULL;
       
   144   }
       
   145 } {2 2 {} 3 {} {}}
       
   146 
       
   147 # Ticket #2189.  Probably the same bug as #2177.
       
   148 #
       
   149 do_test where4-4.1 {
       
   150   execsql {
       
   151     CREATE TABLE test(col1 TEXT PRIMARY KEY);
       
   152     INSERT INTO test(col1) values('a');
       
   153     INSERT INTO test(col1) values('b');
       
   154     INSERT INTO test(col1) values('c');
       
   155     CREATE TABLE test2(col1 TEXT PRIMARY KEY);
       
   156     INSERT INTO test2(col1) values('a');
       
   157     INSERT INTO test2(col1) values('b');
       
   158     INSERT INTO test2(col1) values('c');
       
   159     SELECT * FROM test t1 LEFT OUTER JOIN test2 t2 ON t1.col1 = t2.col1
       
   160       WHERE +t2.col1 IS NULL;
       
   161   }
       
   162 } {}
       
   163 do_test where4-4.2 {
       
   164   execsql {
       
   165     SELECT * FROM test t1 LEFT OUTER JOIN test2 t2 ON t1.col1 = t2.col1
       
   166       WHERE t2.col1 IS NULL;
       
   167   }
       
   168 } {}
       
   169 do_test where4-4.3 {
       
   170   execsql {
       
   171     SELECT * FROM test t1 LEFT OUTER JOIN test2 t2 ON t1.col1 = t2.col1
       
   172       WHERE +t1.col1 IS NULL;
       
   173   }
       
   174 } {}
       
   175 do_test where4-4.4 {
       
   176   execsql {
       
   177     SELECT * FROM test t1 LEFT OUTER JOIN test2 t2 ON t1.col1 = t2.col1
       
   178       WHERE t1.col1 IS NULL;
       
   179   }
       
   180 } {}
       
   181 
       
   182 # Ticket #2273.  Problems with IN operators and NULLs.
       
   183 #
       
   184 ifcapable subquery {
       
   185 do_test where4-5.1 {
       
   186   execsql {
       
   187     CREATE TABLE t4(x,y,z,PRIMARY KEY(x,y));
       
   188   }
       
   189   execsql {
       
   190     SELECT *
       
   191       FROM t2 LEFT JOIN t4 b1
       
   192               LEFT JOIN t4 b2 ON b2.x=b1.x AND b2.y IN (b1.y);
       
   193   }
       
   194 } {1 {} {} {} {} {} {} 2 {} {} {} {} {} {} 3 {} {} {} {} {} {}}
       
   195 do_test where4-5.2 {
       
   196   execsql {
       
   197     INSERT INTO t4 VALUES(1,1,11);
       
   198     INSERT INTO t4 VALUES(1,2,12);
       
   199     INSERT INTO t4 VALUES(1,3,13);
       
   200     INSERT INTO t4 VALUES(2,2,22);
       
   201     SELECT rowid FROM t4 WHERE x IN (1,9,2,5) AND y IN (1,3,NULL,2) AND z!=13;
       
   202   }
       
   203 } {1 2 4}
       
   204 do_test where4-5.3 {
       
   205   execsql {
       
   206     SELECT rowid FROM t4 WHERE x IN (1,9,NULL,2) AND y IN (1,3,2) AND z!=13;
       
   207   }
       
   208 } {1 2 4}
       
   209 do_test where4-6.1 {
       
   210   execsql {
       
   211     CREATE TABLE t5(a,b,c,d,e,f,UNIQUE(a,b,c,d,e,f));
       
   212     INSERT INTO t5 VALUES(1,1,1,1,1,11111);
       
   213     INSERT INTO t5 VALUES(2,2,2,2,2,22222);
       
   214     INSERT INTO t5 VALUES(1,2,3,4,5,12345);
       
   215     INSERT INTO t5 VALUES(2,3,4,5,6,23456);
       
   216   }
       
   217   execsql {
       
   218     SELECT rowid FROM t5
       
   219      WHERE a IN (1,9,2) AND b=2 AND c IN (1,2,3,4) AND d>0
       
   220   }
       
   221 } {3 2}
       
   222 do_test where4-6.2 {
       
   223   execsql {
       
   224     SELECT rowid FROM t5
       
   225      WHERE a IN (1,NULL,2) AND b=2 AND c IN (1,2,3,4) AND d>0
       
   226   }
       
   227 } {3 2}
       
   228 do_test where4-7.1 {
       
   229   execsql {
       
   230     CREATE TABLE t6(y,z,PRIMARY KEY(y,z));
       
   231   }
       
   232   execsql {
       
   233     SELECT * FROM t6 WHERE y=NULL AND z IN ('hello');
       
   234   }
       
   235 } {}
       
   236 
       
   237 integrity_check {where4-99.0}
       
   238 
       
   239 do_test where4-7.1 {
       
   240   execsql {
       
   241     BEGIN;
       
   242     CREATE TABLE t8(a, b, c, d);
       
   243     CREATE INDEX t8_i ON t8(a, b, c);
       
   244     CREATE TABLE t7(i);
       
   245 
       
   246     INSERT INTO t7 VALUES(1);
       
   247     INSERT INTO t7 SELECT i*2 FROM t7;
       
   248     INSERT INTO t7 SELECT i*2 FROM t7;
       
   249     INSERT INTO t7 SELECT i*2 FROM t7;
       
   250     INSERT INTO t7 SELECT i*2 FROM t7;
       
   251     INSERT INTO t7 SELECT i*2 FROM t7;
       
   252     INSERT INTO t7 SELECT i*2 FROM t7;
       
   253 
       
   254     COMMIT;
       
   255   }
       
   256 } {}
       
   257 
       
   258 # At one point the sub-select inside the aggregate sum() function in the
       
   259 # following query was leaking a couple of stack entries. This query 
       
   260 # runs the SELECT in a loop enough times that an assert() fails. Or rather,
       
   261 # did fail before the bug was fixed.
       
   262 #
       
   263 do_test where4-7.2 {
       
   264   execsql {
       
   265     SELECT sum((
       
   266       SELECT d FROM t8 WHERE a = i AND b = i AND c < NULL
       
   267     )) FROM t7;
       
   268   }
       
   269 } {{}}
       
   270 
       
   271 }; #ifcapable subquery
       
   272 
       
   273 finish_test