Home | History | Annotate | Download | only in test
      1 # 2005 July 28
      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 # based on recent changes to the optimizer.
     14 #
     15 # $Id: where2.test,v 1.15 2009/02/02 01:50:40 drh Exp $
     16 
     17 set testdir [file dirname $argv0]
     18 source $testdir/tester.tcl
     19 
     20 # Build some test data
     21 #
     22 do_test where2-1.0 {
     23   execsql {
     24     BEGIN;
     25     CREATE TABLE t1(w int, x int, y int, z int);
     26   }
     27   for {set i 1} {$i<=100} {incr i} {
     28     set w $i
     29     set x [expr {int(log($i)/log(2))}]
     30     set y [expr {$i*$i + 2*$i + 1}]
     31     set z [expr {$x+$y}]
     32     ifcapable tclvar {
     33       execsql {INSERT INTO t1 VALUES($::w,$::x,$::y,$::z)}
     34     } else {
     35       execsql {INSERT INTO t1 VALUES(:w,:x,:y,:z)}
     36     }
     37   }
     38   execsql {
     39     CREATE UNIQUE INDEX i1w ON t1(w);
     40     CREATE INDEX i1xy ON t1(x,y);
     41     CREATE INDEX i1zyx ON t1(z,y,x);
     42     COMMIT;
     43   }
     44 } {}
     45 
     46 # Do an SQL statement.  Append the search count to the end of the result.
     47 #
     48 proc count sql {
     49   set ::sqlite_search_count 0
     50   return [concat [execsql $sql] $::sqlite_search_count]
     51 }
     52 
     53 # This procedure executes the SQL.  Then it checks to see if the OP_Sort
     54 # opcode was executed.  If an OP_Sort did occur, then "sort" is appended
     55 # to the result.  If no OP_Sort happened, then "nosort" is appended.
     56 #
     57 # This procedure is used to check to make sure sorting is or is not
     58 # occurring as expected.
     59 #
     60 proc cksort {sql} {
     61   set data [execsql $sql]
     62   if {[db status sort]} {set x sort} {set x nosort}
     63   lappend data $x
     64   return $data
     65 }
     66 
     67 # This procedure executes the SQL.  Then it appends to the result the
     68 # "sort" or "nosort" keyword (as in the cksort procedure above) then
     69 # it appends the ::sqlite_query_plan variable.
     70 #
     71 proc queryplan {sql} {
     72   set ::sqlite_sort_count 0
     73   set data [execsql $sql]
     74   if {$::sqlite_sort_count} {set x sort} {set x nosort}
     75   lappend data $x
     76   return [concat $data $::sqlite_query_plan]
     77 }
     78 
     79 
     80 # Prefer a UNIQUE index over another index.
     81 #
     82 do_test where2-1.1 {
     83   queryplan {
     84     SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396
     85   }
     86 } {85 6 7396 7402 nosort t1 i1w}
     87 
     88 # Always prefer a rowid== constraint over any other index.
     89 #
     90 do_test where2-1.3 {
     91   queryplan {
     92     SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396 AND rowid=85
     93   }
     94 } {85 6 7396 7402 nosort t1 *}
     95 
     96 # When constrained by a UNIQUE index, the ORDER BY clause is always ignored.
     97 #
     98 do_test where2-2.1 {
     99   queryplan {
    100     SELECT * FROM t1 WHERE w=85 ORDER BY random();
    101   }
    102 } {85 6 7396 7402 nosort t1 i1w}
    103 do_test where2-2.2 {
    104   queryplan {
    105     SELECT * FROM t1 WHERE x=6 AND y=7396 ORDER BY random();
    106   }
    107 } {85 6 7396 7402 sort t1 i1xy}
    108 do_test where2-2.3 {
    109   queryplan {
    110     SELECT * FROM t1 WHERE rowid=85 AND x=6 AND y=7396 ORDER BY random();
    111   }
    112 } {85 6 7396 7402 nosort t1 *}
    113 
    114 
    115 # Efficient handling of forward and reverse table scans.
    116 #
    117 do_test where2-3.1 {
    118   queryplan {
    119     SELECT * FROM t1 ORDER BY rowid LIMIT 2
    120   }
    121 } {1 0 4 4 2 1 9 10 nosort t1 *}
    122 do_test where2-3.2 {
    123   queryplan {
    124     SELECT * FROM t1 ORDER BY rowid DESC LIMIT 2
    125   }
    126 } {100 6 10201 10207 99 6 10000 10006 nosort t1 *}
    127 
    128 # The IN operator can be used by indices at multiple layers
    129 #
    130 ifcapable subquery {
    131   do_test where2-4.1 {
    132     queryplan {
    133       SELECT * FROM t1 WHERE z IN (10207,10006) AND y IN (10000,10201)
    134                        AND x>0 AND x<10
    135       ORDER BY w
    136     }
    137   } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
    138   do_test where2-4.2 {
    139     queryplan {
    140       SELECT * FROM t1 WHERE z IN (10207,10006) AND y=10000
    141                        AND x>0 AND x<10
    142       ORDER BY w
    143     }
    144   } {99 6 10000 10006 sort t1 i1zyx}
    145   do_test where2-4.3 {
    146     queryplan {
    147       SELECT * FROM t1 WHERE z=10006 AND y IN (10000,10201)
    148                        AND x>0 AND x<10
    149       ORDER BY w
    150     }
    151   } {99 6 10000 10006 sort t1 i1zyx}
    152   ifcapable compound {
    153     do_test where2-4.4 {
    154       queryplan {
    155         SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
    156                          AND y IN (10000,10201)
    157                          AND x>0 AND x<10
    158         ORDER BY w
    159       }
    160     } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
    161     do_test where2-4.5 {
    162       queryplan {
    163         SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
    164                          AND y IN (SELECT 10000 UNION SELECT 10201)
    165                          AND x>0 AND x<10
    166         ORDER BY w
    167       }
    168     } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
    169   }
    170   do_test where2-4.6 {
    171     queryplan {
    172       SELECT * FROM t1
    173        WHERE x IN (1,2,3,4,5,6,7,8)
    174          AND y IN (10000,10001,10002,10003,10004,10005)
    175        ORDER BY 2
    176     }
    177   } {99 6 10000 10006 sort t1 i1xy}
    178 
    179   # Duplicate entires on the RHS of an IN operator do not cause duplicate
    180   # output rows.
    181   #
    182   do_test where2-4.6 {
    183     queryplan {
    184       SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207)
    185       ORDER BY w
    186     }
    187   } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
    188   ifcapable compound {
    189     do_test where2-4.7 {
    190       queryplan {
    191         SELECT * FROM t1 WHERE z IN (
    192            SELECT 10207 UNION ALL SELECT 10006
    193            UNION ALL SELECT 10006 UNION ALL SELECT 10207)
    194         ORDER BY w
    195       }
    196     } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
    197   }
    198 
    199 } ;# ifcapable subquery
    200 
    201 # The use of an IN operator disables the index as a sorter.
    202 #
    203 do_test where2-5.1 {
    204   queryplan {
    205     SELECT * FROM t1 WHERE w=99 ORDER BY w
    206   }
    207 } {99 6 10000 10006 nosort t1 i1w}
    208 
    209 ifcapable subquery {
    210   do_test where2-5.2 {
    211     queryplan {
    212       SELECT * FROM t1 WHERE w IN (99) ORDER BY w
    213     }
    214   } {99 6 10000 10006 sort t1 i1w}
    215 }
    216 
    217 # Verify that OR clauses get translated into IN operators.
    218 #
    219 set ::idx {}
    220 ifcapable subquery {set ::idx i1w}
    221 do_test where2-6.1.1 {
    222   queryplan {
    223     SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w
    224   }
    225 } [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
    226 do_test where2-6.1.2 {
    227   queryplan {
    228     SELECT * FROM t1 WHERE 99=w OR 100=w ORDER BY +w
    229   }
    230 } [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
    231 do_test where2-6.2 {
    232   queryplan {
    233     SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=w ORDER BY +w
    234   }
    235 } [list 6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
    236 
    237 do_test where2-6.3 {
    238   queryplan {
    239     SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w
    240   }
    241 } {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}
    242 do_test where2-6.4 {
    243   queryplan {
    244     SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w
    245   }
    246 } {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}
    247 
    248 set ::idx {}
    249 ifcapable subquery {set ::idx i1zyx}
    250 do_test where2-6.5 {
    251   queryplan {
    252     SELECT b.* FROM t1 a, t1 b
    253      WHERE a.w=1 AND (a.y=b.z OR b.z=10)
    254      ORDER BY +b.w
    255   }
    256 } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]
    257 do_test where2-6.6 {
    258   queryplan {
    259     SELECT b.* FROM t1 a, t1 b
    260      WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10)
    261      ORDER BY +b.w
    262   }
    263 } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]
    264 
    265 # Ticket #2249.  Make sure the OR optimization is not attempted if
    266 # comparisons between columns of different affinities are needed.
    267 #
    268 do_test where2-6.7 {
    269   execsql {
    270     CREATE TABLE t2249a(a TEXT UNIQUE);
    271     CREATE TABLE t2249b(b INTEGER);
    272     INSERT INTO t2249a VALUES('0123');
    273     INSERT INTO t2249b VALUES(123);
    274   }
    275   queryplan {
    276     -- Because a is type TEXT and b is type INTEGER, both a and b
    277     -- will attempt to convert to NUMERIC before the comparison.
    278     -- They will thus compare equal.
    279     --
    280     SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=b;
    281   }
    282 } {123 0123 nosort t2249b {} t2249a {}}
    283 do_test where2-6.9 {
    284   queryplan {
    285     -- The + operator removes affinity from the rhs.  No conversions
    286     -- occur and the comparison is false.  The result is an empty set.
    287     --
    288     SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b;
    289   }
    290 } {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
    291 do_test where2-6.9.2 {
    292   # The same thing but with the expression flipped around.
    293   queryplan {
    294     SELECT * FROM t2249b CROSS JOIN t2249a WHERE +b=a
    295   }
    296 } {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
    297 do_test where2-6.10 {
    298   queryplan {
    299     -- Use + on both sides of the comparison to disable indices
    300     -- completely.  Make sure we get the same result.
    301     --
    302     SELECT * FROM t2249b CROSS JOIN t2249a WHERE +a=+b;
    303   }
    304 } {nosort t2249b {} t2249a {}}
    305 do_test where2-6.11 {
    306   # This will not attempt the OR optimization because of the a=b
    307   # comparison.
    308   queryplan {
    309     SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello';
    310   }
    311 } {123 0123 nosort t2249b {} t2249a {}}
    312 do_test where2-6.11.2 {
    313   # Permutations of the expression terms.
    314   queryplan {
    315     SELECT * FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello';
    316   }
    317 } {123 0123 nosort t2249b {} t2249a {}}
    318 do_test where2-6.11.3 {
    319   # Permutations of the expression terms.
    320   queryplan {
    321     SELECT * FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a;
    322   }
    323 } {123 0123 nosort t2249b {} t2249a {}}
    324 do_test where2-6.11.4 {
    325   # Permutations of the expression terms.
    326   queryplan {
    327     SELECT * FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a;
    328   }
    329 } {123 0123 nosort t2249b {} t2249a {}}
    330 ifcapable explain&&subquery {
    331   # These tests are not run if subquery support is not included in the
    332   # build. This is because these tests test the "a = 1 OR a = 2" to
    333   # "a IN (1, 2)" optimisation transformation, which is not enabled if
    334   # subqueries and the IN operator is not available.
    335   #
    336   do_test where2-6.12 {
    337     # In this case, the +b disables the affinity conflict and allows
    338     # the OR optimization to be used again.  The result is now an empty
    339     # set, the same as in where2-6.9.
    340     queryplan {
    341       SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello';
    342     }
    343   } {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
    344   do_test where2-6.12.2 {
    345     # In this case, the +b disables the affinity conflict and allows
    346     # the OR optimization to be used again.  The result is now an empty
    347     # set, the same as in where2-6.9.
    348     queryplan {
    349       SELECT * FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a;
    350     }
    351   } {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
    352   do_test where2-6.12.3 {
    353     # In this case, the +b disables the affinity conflict and allows
    354     # the OR optimization to be used again.  The result is now an empty
    355     # set, the same as in where2-6.9.
    356     queryplan {
    357       SELECT * FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello';
    358     }
    359   } {nosort t2249b {} {} sqlite_autoindex_t2249a_1}
    360   do_test where2-6.13 {
    361     # The addition of +a on the second term disabled the OR optimization.
    362     # But we should still get the same empty-set result as in where2-6.9.
    363     queryplan {
    364       SELECT * FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello';
    365     }
    366   } {nosort t2249b {} t2249a {}}
    367 }
    368 
    369 # Variations on the order of terms in a WHERE clause in order
    370 # to make sure the OR optimizer can recognize them all.
    371 do_test where2-6.20 {
    372   queryplan {
    373     SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a
    374   }
    375 } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1}
    376 ifcapable explain&&subquery {
    377   # These tests are not run if subquery support is not included in the
    378   # build. This is because these tests test the "a = 1 OR a = 2" to
    379   # "a IN (1, 2)" optimisation transformation, which is not enabled if
    380   # subqueries and the IN operator is not available.
    381   #
    382   do_test where2-6.21 {
    383     queryplan {
    384       SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a OR y.a='hello'
    385     }
    386   } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1}
    387   do_test where2-6.22 {
    388     queryplan {
    389       SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE y.a=x.a OR y.a='hello'
    390     }
    391   } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1}
    392   do_test where2-6.23 {
    393     queryplan {
    394       SELECT * FROM t2249a x CROSS JOIN t2249a y WHERE y.a='hello' OR x.a=y.a
    395     }
    396   } {0123 0123 nosort x {} {} sqlite_autoindex_t2249a_1}
    397 }
    398 
    399 # Unique queries (queries that are guaranteed to return only a single
    400 # row of result) do not call the sorter.  But all tables must give
    401 # a unique result.  If any one table in the join does not give a unique
    402 # result then sorting is necessary.
    403 #
    404 do_test where2-7.1 {
    405   cksort {
    406     create table t8(a unique, b, c);
    407     insert into t8 values(1,2,3);
    408     insert into t8 values(2,3,4);
    409     create table t9(x,y);
    410     insert into t9 values(2,4);
    411     insert into t9 values(2,3);
    412     select y from t8, t9 where a=1 order by a, y;
    413   }
    414 } {3 4 sort}
    415 do_test where2-7.2 {
    416   cksort {
    417     select * from t8 where a=1 order by b, c
    418   }
    419 } {1 2 3 nosort}
    420 do_test where2-7.3 {
    421   cksort {
    422     select * from t8, t9 where a=1 and y=3 order by b, x
    423   }
    424 } {1 2 3 2 3 sort}
    425 do_test where2-7.4 {
    426   cksort {
    427     create unique index i9y on t9(y);
    428     select * from t8, t9 where a=1 and y=3 order by b, x
    429   }
    430 } {1 2 3 2 3 nosort}
    431 
    432 # Ticket #1807.  Using IN constrains on multiple columns of
    433 # a multi-column index.
    434 #
    435 ifcapable subquery {
    436   do_test where2-8.1 {
    437     execsql {
    438       SELECT * FROM t1 WHERE x IN (20,21) AND y IN (1,2)
    439     }
    440   } {}
    441   do_test where2-8.2 {
    442     execsql {
    443       SELECT * FROM t1 WHERE x IN (1,2) AND y IN (-5,-6)
    444     }
    445   } {}
    446   execsql {CREATE TABLE tx AS SELECT * FROM t1}
    447   do_test where2-8.3 {
    448     execsql {
    449       SELECT w FROM t1
    450        WHERE x IN (SELECT x FROM tx WHERE rowid<0)
    451          AND +y IN (SELECT y FROM tx WHERE rowid=1)
    452     }
    453   } {}
    454   do_test where2-8.4 {
    455     execsql {
    456       SELECT w FROM t1
    457        WHERE x IN (SELECT x FROM tx WHERE rowid=1)
    458          AND y IN (SELECT y FROM tx WHERE rowid<0)
    459     }
    460   } {}
    461   #set sqlite_where_trace 1
    462   do_test where2-8.5 {
    463     execsql {
    464       CREATE INDEX tx_xyz ON tx(x, y, z, w);
    465       SELECT w FROM tx
    466        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
    467          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
    468          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 12 AND 14)
    469     }
    470   } {12 13 14}
    471   do_test where2-8.6 {
    472     execsql {
    473       SELECT w FROM tx
    474        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
    475          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 12 AND 14)
    476          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
    477     }
    478   } {12 13 14}
    479   do_test where2-8.7 {
    480     execsql {
    481       SELECT w FROM tx
    482        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 12 AND 14)
    483          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
    484          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
    485     }
    486   } {10 11 12 13 14 15}
    487   do_test where2-8.8 {
    488     execsql {
    489       SELECT w FROM tx
    490        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
    491          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
    492          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
    493     }
    494   } {10 11 12 13 14 15 16 17 18 19 20}
    495   do_test where2-8.9 {
    496     execsql {
    497       SELECT w FROM tx
    498        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
    499          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
    500          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 2 AND 4)
    501     }
    502   } {}
    503   do_test where2-8.10 {
    504     execsql {
    505       SELECT w FROM tx
    506        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
    507          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 2 AND 4)
    508          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
    509     }
    510   } {}
    511   do_test where2-8.11 {
    512     execsql {
    513       SELECT w FROM tx
    514        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 2 AND 4)
    515          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
    516          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
    517     }
    518   } {}
    519   do_test where2-8.12 {
    520     execsql {
    521       SELECT w FROM tx
    522        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
    523          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
    524          AND z IN (SELECT z FROM t1 WHERE w BETWEEN -4 AND -2)
    525     }
    526   } {}
    527   do_test where2-8.13 {
    528     execsql {
    529       SELECT w FROM tx
    530        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
    531          AND y IN (SELECT y FROM t1 WHERE w BETWEEN -4 AND -2)
    532          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
    533     }
    534   } {}
    535   do_test where2-8.14 {
    536     execsql {
    537       SELECT w FROM tx
    538        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN -4 AND -2)
    539          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
    540          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
    541     }
    542   } {}
    543   do_test where2-8.15 {
    544     execsql {
    545       SELECT w FROM tx
    546        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
    547          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
    548          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 200 AND 300)
    549     }
    550   } {}
    551   do_test where2-8.16 {
    552     execsql {
    553       SELECT w FROM tx
    554        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
    555          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 200 AND 300)
    556          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
    557     }
    558   } {}
    559   do_test where2-8.17 {
    560     execsql {
    561       SELECT w FROM tx
    562        WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 200 AND 300)
    563          AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
    564          AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
    565     }
    566   } {}
    567   do_test where2-8.18 {
    568     execsql {
    569       SELECT w FROM tx
    570        WHERE x IN (SELECT x FROM t1 WHERE +w BETWEEN 10 AND 20)
    571          AND y IN (SELECT y FROM t1 WHERE +w BETWEEN 10 AND 20)
    572          AND z IN (SELECT z FROM t1 WHERE +w BETWEEN 200 AND 300)
    573     }
    574   } {}
    575   do_test where2-8.19 {
    576     execsql {
    577       SELECT w FROM tx
    578        WHERE x IN (SELECT x FROM t1 WHERE +w BETWEEN 10 AND 20)
    579          AND y IN (SELECT y FROM t1 WHERE +w BETWEEN 200 AND 300)
    580          AND z IN (SELECT z FROM t1 WHERE +w BETWEEN 10 AND 20)
    581     }
    582   } {}
    583   do_test where2-8.20 {
    584     execsql {
    585       SELECT w FROM tx
    586        WHERE x IN (SELECT x FROM t1 WHERE +w BETWEEN 200 AND 300)
    587          AND y IN (SELECT y FROM t1 WHERE +w BETWEEN 10 AND 20)
    588          AND z IN (SELECT z FROM t1 WHERE +w BETWEEN 10 AND 20)
    589     }
    590   } {}
    591 }  
    592 
    593 # Make sure WHERE clauses of the form A=1 AND (B=2 OR B=3) are optimized
    594 # when we have an index on A and B.
    595 #
    596 ifcapable or_opt&&tclvar {
    597   do_test where2-9.1 {
    598     execsql {
    599       BEGIN;
    600       CREATE TABLE t10(a,b,c);
    601       INSERT INTO t10 VALUES(1,1,1);
    602       INSERT INTO t10 VALUES(1,2,2);
    603       INSERT INTO t10 VALUES(1,3,3);
    604     }
    605     for {set i 4} {$i<=1000} {incr i} {
    606       execsql {INSERT INTO t10 VALUES(1,$i,$i)}
    607     }
    608     execsql {
    609       CREATE INDEX i10 ON t10(a,b);
    610       COMMIT;
    611       SELECT count(*) FROM t10;
    612     }
    613   } 1000
    614   ifcapable subquery {
    615     do_test where2-9.2 {
    616       count {
    617         SELECT * FROM t10 WHERE a=1 AND (b=2 OR b=3)
    618       }
    619     } {1 2 2 1 3 3 7}
    620   }
    621 }
    622 
    623 # Indices with redundant columns
    624 #
    625 do_test where2-11.1 {
    626   execsql {
    627     CREATE TABLE t11(a,b,c,d);
    628     CREATE INDEX i11aba ON t11(a,b,a,c); -- column A occurs twice.
    629     INSERT INTO t11 VALUES(1,2,3,4);
    630     INSERT INTO t11 VALUES(5,6,7,8);
    631     INSERT INTO t11 VALUES(1,2,9,10);
    632     INSERT INTO t11 VALUES(5,11,12,13);
    633     SELECT c FROM t11 WHERE a=1 AND b=2 ORDER BY c;
    634   }
    635 } {3 9}
    636 do_test where2-11.2 {
    637   execsql {
    638     CREATE INDEX i11cccccccc ON t11(c,c,c,c,c,c,c,c); -- repeated column
    639     SELECT d FROM t11 WHERE c=9;
    640   }
    641 } {10}
    642 do_test where2-11.3 {
    643   execsql {
    644     SELECT d FROM t11 WHERE c IN (1,2,3,4,5);
    645   }
    646 } {4}
    647 do_test where2-11.4 {
    648   execsql {
    649     SELECT d FROM t11 WHERE c=7 OR (a=1 AND b=2) ORDER BY d;
    650   }
    651 } {4 8 10}
    652 
    653 
    654 finish_test
    655