github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/where2.test (about)

     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 name of the table and index used.
    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    set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
    77    # puts eqp=$eqp
    78    foreach {a b c x} $eqp {
    79      if {[regexp {SCAN CONSTANT} $x]} {
    80        # noop
    81      } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
    82          $x all ss as tab idx]} {
    83        lappend data $tab $idx
    84      } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
    85        lappend data $tab *
    86      }
    87    }
    88    return $data   
    89  }
    90  
    91  
    92  # Prefer a UNIQUE index over another index.
    93  #
    94  do_test where2-1.1 {
    95    queryplan {
    96      SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396
    97    }
    98  } {85 6 7396 7402 nosort t1 i1w}
    99  
   100  # Always prefer a rowid== constraint over any other index.
   101  #
   102  do_test where2-1.3 {
   103    queryplan {
   104      SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396 AND rowid=85
   105    }
   106  } {85 6 7396 7402 nosort t1 *}
   107  
   108  # When constrained by a UNIQUE index, the ORDER BY clause is always ignored.
   109  #
   110  do_test where2-2.1 {
   111    queryplan {
   112      SELECT * FROM t1 WHERE w=85 ORDER BY random();
   113    }
   114  } {85 6 7396 7402 nosort t1 i1w}
   115  do_test where2-2.2 {
   116    queryplan {
   117      SELECT * FROM t1 WHERE x=6 AND y=7396 ORDER BY random();
   118    }
   119  } {85 6 7396 7402 sort t1 i1xy}
   120  do_test where2-2.3 {
   121    queryplan {
   122      SELECT * FROM t1 WHERE rowid=85 AND x=6 AND y=7396 ORDER BY random();
   123    }
   124  } {85 6 7396 7402 nosort t1 *}
   125  
   126  # Ticket [65bdeb9739605cc22966f49208452996ff29a640] 2014-02-26
   127  # Make sure "ORDER BY random" does not gets optimized out.
   128  #
   129  do_test where2-2.4 {
   130    db eval {
   131      CREATE TABLE x1(a INTEGER PRIMARY KEY, b DEFAULT 1);
   132      WITH RECURSIVE
   133         cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<50)
   134      INSERT INTO x1 SELECT x, 1 FROM cnt;
   135      CREATE TABLE x2(x INTEGER PRIMARY KEY);
   136      INSERT INTO x2 VALUES(1);
   137    }
   138    set sql {SELECT * FROM x1, x2 WHERE x=1 ORDER BY random()}
   139    set out1 [db eval $sql]
   140    set out2 [db eval $sql]
   141    set out3 [db eval $sql]
   142    expr {$out1!=$out2 && $out2!=$out3}
   143  } {1}
   144  do_execsql_test where2-2.5 {
   145    -- random() is not optimized out
   146    EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random();
   147  } {/ random/}
   148  do_execsql_test where2-2.5b {
   149    -- random() is not optimized out
   150    EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY random();
   151  } {/ SorterOpen /}
   152  do_execsql_test where2-2.6 {
   153    -- other constant functions are optimized out
   154    EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5);
   155  } {~/ abs/}
   156  do_execsql_test where2-2.6b {
   157    -- other constant functions are optimized out
   158    EXPLAIN SELECT * FROM x1, x2 WHERE x=1 ORDER BY abs(5);
   159  } {~/ SorterOpen /}
   160  
   161  
   162  
   163  # Efficient handling of forward and reverse table scans.
   164  #
   165  do_test where2-3.1 {
   166    queryplan {
   167      SELECT * FROM t1 ORDER BY rowid LIMIT 2
   168    }
   169  } {1 0 4 4 2 1 9 10 nosort t1 *}
   170  do_test where2-3.2 {
   171    queryplan {
   172      SELECT * FROM t1 ORDER BY rowid DESC LIMIT 2
   173    }
   174  } {100 6 10201 10207 99 6 10000 10006 nosort t1 *}
   175  
   176  # The IN operator can be used by indices at multiple layers
   177  #
   178  ifcapable subquery {
   179    do_test where2-4.1 {
   180      queryplan {
   181        SELECT * FROM t1 WHERE z IN (10207,10006) AND y IN (10000,10201)
   182                         AND x>0 AND x<10
   183        ORDER BY w
   184      }
   185    } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
   186    do_test where2-4.2 {
   187      queryplan {
   188        SELECT * FROM t1 WHERE z IN (10207,10006) AND y=10000
   189                         AND x>0 AND x<10
   190        ORDER BY w
   191      }
   192    } {99 6 10000 10006 sort t1 i1zyx}
   193    do_test where2-4.3 {
   194      queryplan {
   195        SELECT * FROM t1 WHERE z=10006 AND y IN (10000,10201)
   196                         AND x>0 AND x<10
   197        ORDER BY w
   198      }
   199    } {99 6 10000 10006 sort t1 i1zyx}
   200    ifcapable compound {
   201      do_test where2-4.4 {
   202        queryplan {
   203          SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
   204                           AND y IN (10000,10201)
   205                           AND x>0 AND x<10
   206          ORDER BY w
   207        }
   208      } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
   209      do_test where2-4.5 {
   210        queryplan {
   211          SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
   212                           AND y IN (SELECT 10000 UNION SELECT 10201)
   213                           AND x>0 AND x<10
   214          ORDER BY w
   215        }
   216      } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
   217    }
   218    do_test where2-4.6a {
   219      queryplan {
   220        SELECT * FROM t1
   221         WHERE x IN (1,2,3,4,5,6,7,8)
   222           AND y IN (10000,10001,10002,10003,10004,10005)
   223         ORDER BY x
   224      }
   225    } {99 6 10000 10006 nosort t1 i1xy}
   226    do_test where2-4.6b {
   227      queryplan {
   228        SELECT * FROM t1
   229         WHERE x IN (1,2,3,4,5,6,7,8)
   230           AND y IN (10000,10001,10002,10003,10004,10005)
   231         ORDER BY x DESC
   232      }
   233    } {99 6 10000 10006 nosort t1 i1xy}
   234    do_test where2-4.6c {
   235      queryplan {
   236        SELECT * FROM t1
   237         WHERE x IN (1,2,3,4,5,6,7,8)
   238           AND y IN (10000,10001,10002,10003,10004,10005)
   239         ORDER BY x, y
   240      }
   241    } {99 6 10000 10006 nosort t1 i1xy}
   242    do_test where2-4.6d {
   243      queryplan {
   244        SELECT * FROM t1
   245         WHERE x IN (1,2,3,4,5,6,7,8)
   246           AND y IN (10000,10001,10002,10003,10004,10005)
   247         ORDER BY x, y DESC
   248      }
   249    } {99 6 10000 10006 sort t1 i1xy}
   250  
   251    # Duplicate entires on the RHS of an IN operator do not cause duplicate
   252    # output rows.
   253    #
   254    do_test where2-4.6x {
   255      queryplan {
   256        SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207)
   257        ORDER BY w
   258      }
   259    } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
   260    do_test where2-4.6y {
   261      queryplan {
   262        SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207)
   263        ORDER BY w DESC
   264      }
   265    } {100 6 10201 10207 99 6 10000 10006 sort t1 i1zyx}
   266    ifcapable compound {
   267      do_test where2-4.7 {
   268        queryplan {
   269          SELECT * FROM t1 WHERE z IN (
   270             SELECT 10207 UNION ALL SELECT 10006
   271             UNION ALL SELECT 10006 UNION ALL SELECT 10207)
   272          ORDER BY w
   273        }
   274      } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
   275    }
   276  
   277  } ;# ifcapable subquery
   278  
   279  # The use of an IN operator disables the index as a sorter.
   280  #
   281  do_test where2-5.1 {
   282    queryplan {
   283      SELECT * FROM t1 WHERE w=99 ORDER BY w
   284    }
   285  } {99 6 10000 10006 nosort t1 i1w}
   286  
   287  ifcapable subquery {
   288    do_test where2-5.2a {
   289      queryplan {
   290        SELECT * FROM t1 WHERE w IN (99) ORDER BY w
   291      }
   292    } {99 6 10000 10006 nosort t1 i1w}
   293    do_test where2-5.2b {
   294      queryplan {
   295        SELECT * FROM t1 WHERE w IN (99) ORDER BY w DESC
   296      }
   297    } {99 6 10000 10006 nosort t1 i1w}
   298  }
   299  
   300  # Verify that OR clauses get translated into IN operators.
   301  #
   302  set ::idx {}
   303  ifcapable subquery {set ::idx i1w}
   304  do_test where2-6.1.1 {
   305    queryplan {
   306      SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w
   307    }
   308  } [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
   309  do_test where2-6.1.2 {
   310    queryplan {
   311      SELECT * FROM t1 WHERE 99=w OR 100=w ORDER BY +w
   312    }
   313  } [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
   314  do_test where2-6.2 {
   315    queryplan {
   316      SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=w ORDER BY +w
   317    }
   318  } [list 6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
   319  
   320  do_test where2-6.3 {
   321    queryplan {
   322      SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w
   323    }
   324  } {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 *}
   325  do_test where2-6.4 {
   326    queryplan {
   327      SELECT *, '|' FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w
   328    }
   329  } {6 2 49 51 | 99 6 10000 10006 | 100 6 10201 10207 | sort t1 *}
   330  do_test where2-6.5 {
   331    queryplan {
   332      SELECT *, '|' FROM t1 WHERE w=99 OR y=10201 OR 6=w ORDER BY +w
   333    }
   334  } {6 2 49 51 | 99 6 10000 10006 | 100 6 10201 10207 | sort t1 *}
   335  
   336  set ::idx {}
   337  ifcapable subquery {set ::idx i1zyx}
   338  do_test where2-6.5 {
   339    queryplan {
   340      SELECT b.* FROM t1 a, t1 b
   341       WHERE a.w=1 AND (a.y=b.z OR b.z=10)
   342       ORDER BY +b.w
   343    }
   344  } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]
   345  do_test where2-6.6 {
   346    queryplan {
   347      SELECT b.* FROM t1 a, t1 b
   348       WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10)
   349       ORDER BY +b.w
   350    }
   351  } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]
   352  
   353  if {[permutation] != "no_optimization"} {
   354  
   355  # Ticket #2249.  Make sure the OR optimization is not attempted if
   356  # comparisons between columns of different affinities are needed.
   357  #
   358  do_test where2-6.7 {
   359    execsql {
   360      CREATE TABLE t2249a(a TEXT UNIQUE, x CHAR(100));
   361      CREATE TABLE t2249b(b INTEGER);
   362      INSERT INTO t2249a(a) VALUES('0123');
   363      INSERT INTO t2249b VALUES(123);
   364    }
   365    queryplan {
   366      -- Because a is type TEXT and b is type INTEGER, both a and b
   367      -- will attempt to convert to NUMERIC before the comparison.
   368      -- They will thus compare equal.
   369      --
   370      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b;
   371    }
   372  } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   373  do_test where2-6.9 {
   374    queryplan {
   375      -- The + operator removes affinity from the rhs.  No conversions
   376      -- occur and the comparison is false.  The result is an empty set.
   377      --
   378      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b;
   379    }
   380  } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   381  do_test where2-6.9.2 {
   382    # The same thing but with the expression flipped around.
   383    queryplan {
   384      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a
   385    }
   386  } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   387  do_test where2-6.10 {
   388    queryplan {
   389      -- Use + on both sides of the comparison to disable indices
   390      -- completely.  Make sure we get the same result.
   391      --
   392      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +a=+b;
   393    }
   394  } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   395  do_test where2-6.11 {
   396    # This will not attempt the OR optimization because of the a=b
   397    # comparison.
   398    queryplan {
   399      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=b OR a='hello';
   400    }
   401  } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   402  do_test where2-6.11.2 {
   403    # Permutations of the expression terms.
   404    queryplan {
   405      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE b=a OR a='hello';
   406    }
   407  } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   408  do_test where2-6.11.3 {
   409    # Permutations of the expression terms.
   410    queryplan {
   411      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE 'hello'=a OR b=a;
   412    }
   413  } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   414  do_test where2-6.11.4 {
   415    # Permutations of the expression terms.
   416    queryplan {
   417      SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR b=a;
   418    }
   419  } {123 0123 nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   420  ifcapable explain&&subquery {
   421    # These tests are not run if subquery support is not included in the
   422    # build. This is because these tests test the "a = 1 OR a = 2" to
   423    # "a IN (1, 2)" optimisation transformation, which is not enabled if
   424    # subqueries and the IN operator is not available.
   425    #
   426    do_test where2-6.12 {
   427      # In this case, the +b disables the affinity conflict and allows
   428      # the OR optimization to be used again.  The result is now an empty
   429      # set, the same as in where2-6.9.
   430      queryplan {
   431        SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR a='hello';
   432      }
   433    } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   434    do_test where2-6.12.2 {
   435      # In this case, the +b disables the affinity conflict and allows
   436      # the OR optimization to be used again.  The result is now an empty
   437      # set, the same as in where2-6.9.
   438      queryplan {
   439        SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a='hello' OR +b=a;
   440      }
   441    } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   442    do_test where2-6.12.3 {
   443      # In this case, the +b disables the affinity conflict and allows
   444      # the OR optimization to be used again.  The result is now an empty
   445      # set, the same as in where2-6.9.
   446      queryplan {
   447        SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE +b=a OR a='hello';
   448      }
   449    } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   450    do_test where2-6.13 {
   451      # The addition of +a on the second term disabled the OR optimization.
   452      # But we should still get the same empty-set result as in where2-6.9.
   453      queryplan {
   454        SELECT b,a FROM t2249b CROSS JOIN t2249a WHERE a=+b OR +a='hello';
   455      }
   456    } {nosort t2249b * t2249a sqlite_autoindex_t2249a_1}
   457  }
   458  
   459  # Variations on the order of terms in a WHERE clause in order
   460  # to make sure the OR optimizer can recognize them all.
   461  do_test where2-6.20 {
   462    queryplan {
   463      SELECT x.a, y.a FROM t2249a x CROSS JOIN t2249a y WHERE x.a=y.a
   464    }
   465  } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
   466  ifcapable explain&&subquery {
   467    # These tests are not run if subquery support is not included in the
   468    # build. This is because these tests test the "a = 1 OR a = 2" to
   469    # "a IN (1, 2)" optimisation transformation, which is not enabled if
   470    # subqueries and the IN operator is not available.
   471    #
   472    do_test where2-6.21 {
   473      queryplan {
   474        SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y
   475         WHERE x.a=y.a OR y.a='hello'
   476      }
   477    } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
   478    do_test where2-6.22 {
   479      queryplan {
   480        SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y
   481         WHERE y.a=x.a OR y.a='hello'
   482      }
   483    } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
   484    do_test where2-6.23 {
   485      queryplan {
   486        SELECT x.a,y.a FROM t2249a x CROSS JOIN t2249a y
   487         WHERE y.a='hello' OR x.a=y.a
   488      }
   489    } {0123 0123 nosort x sqlite_autoindex_t2249a_1 y sqlite_autoindex_t2249a_1}
   490  }
   491  
   492  # Unique queries (queries that are guaranteed to return only a single
   493  # row of result) do not call the sorter.  But all tables must give
   494  # a unique result.  If any one table in the join does not give a unique
   495  # result then sorting is necessary.
   496  #
   497  do_test where2-7.1 {
   498    cksort {
   499      create table t8(a unique, b, c);
   500      insert into t8 values(1,2,3);
   501      insert into t8 values(2,3,4);
   502      create table t9(x,y);
   503      insert into t9 values(2,4);
   504      insert into t9 values(2,3);
   505      select y from t8, t9 where a=1 order by a, y;
   506    }
   507  } {3 4 sort}
   508  do_test where2-7.2 {
   509    cksort {
   510      select * from t8 where a=1 order by b, c
   511    }
   512  } {1 2 3 nosort}
   513  do_test where2-7.3 {
   514    cksort {
   515      select * from t8, t9 where a=1 and y=3 order by b, x
   516    }
   517  } {1 2 3 2 3 sort}
   518  do_test where2-7.4 {
   519    cksort {
   520      create unique index i9y on t9(y);
   521      select * from t8, t9 where a=1 and y=3 order by b, x
   522    }
   523  } {1 2 3 2 3 nosort}
   524  
   525  } ;# if {[permutation] != "no_optimization"}
   526  
   527  # Ticket #1807.  Using IN constrains on multiple columns of
   528  # a multi-column index.
   529  #
   530  ifcapable subquery {
   531    do_test where2-8.1 {
   532      execsql {
   533        SELECT * FROM t1 WHERE x IN (20,21) AND y IN (1,2)
   534      }
   535    } {}
   536    do_test where2-8.2 {
   537      execsql {
   538        SELECT * FROM t1 WHERE x IN (1,2) AND y IN (-5,-6)
   539      }
   540    } {}
   541    execsql {CREATE TABLE tx AS SELECT * FROM t1}
   542    do_test where2-8.3 {
   543      execsql {
   544        SELECT w FROM t1
   545         WHERE x IN (SELECT x FROM tx WHERE rowid<0)
   546           AND +y IN (SELECT y FROM tx WHERE rowid=1)
   547      }
   548    } {}
   549    do_test where2-8.4 {
   550      execsql {
   551        SELECT w FROM t1
   552         WHERE x IN (SELECT x FROM tx WHERE rowid=1)
   553           AND y IN (SELECT y FROM tx WHERE rowid<0)
   554      }
   555    } {}
   556    #set sqlite_where_trace 1
   557    do_test where2-8.5 {
   558      execsql {
   559        CREATE INDEX tx_xyz ON tx(x, y, z, w);
   560        SELECT w FROM tx
   561         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
   562           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
   563           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 12 AND 14)
   564      }
   565    } {12 13 14}
   566    do_test where2-8.6 {
   567      execsql {
   568        SELECT w FROM tx
   569         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
   570           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 12 AND 14)
   571           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
   572      }
   573    } {12 13 14}
   574    do_test where2-8.7 {
   575      execsql {
   576        SELECT w FROM tx
   577         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 12 AND 14)
   578           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
   579           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
   580      }
   581    } {10 11 12 13 14 15}
   582    do_test where2-8.8 {
   583      execsql {
   584        SELECT w FROM tx
   585         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
   586           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
   587           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
   588      }
   589    } {10 11 12 13 14 15 16 17 18 19 20}
   590    do_test where2-8.9 {
   591      execsql {
   592        SELECT w FROM tx
   593         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
   594           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
   595           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 2 AND 4)
   596      }
   597    } {}
   598    do_test where2-8.10 {
   599      execsql {
   600        SELECT w FROM tx
   601         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
   602           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 2 AND 4)
   603           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
   604      }
   605    } {}
   606    do_test where2-8.11 {
   607      execsql {
   608        SELECT w FROM tx
   609         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 2 AND 4)
   610           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
   611           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
   612      }
   613    } {}
   614    do_test where2-8.12 {
   615      execsql {
   616        SELECT w FROM tx
   617         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
   618           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
   619           AND z IN (SELECT z FROM t1 WHERE w BETWEEN -4 AND -2)
   620      }
   621    } {}
   622    do_test where2-8.13 {
   623      execsql {
   624        SELECT w FROM tx
   625         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
   626           AND y IN (SELECT y FROM t1 WHERE w BETWEEN -4 AND -2)
   627           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
   628      }
   629    } {}
   630    do_test where2-8.14 {
   631      execsql {
   632        SELECT w FROM tx
   633         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN -4 AND -2)
   634           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
   635           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
   636      }
   637    } {}
   638    do_test where2-8.15 {
   639      execsql {
   640        SELECT w FROM tx
   641         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
   642           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
   643           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 200 AND 300)
   644      }
   645    } {}
   646    do_test where2-8.16 {
   647      execsql {
   648        SELECT w FROM tx
   649         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
   650           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 200 AND 300)
   651           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
   652      }
   653    } {}
   654    do_test where2-8.17 {
   655      execsql {
   656        SELECT w FROM tx
   657         WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 200 AND 300)
   658           AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
   659           AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
   660      }
   661    } {}
   662    do_test where2-8.18 {
   663      execsql {
   664        SELECT w FROM tx
   665         WHERE x IN (SELECT x FROM t1 WHERE +w BETWEEN 10 AND 20)
   666           AND y IN (SELECT y FROM t1 WHERE +w BETWEEN 10 AND 20)
   667           AND z IN (SELECT z FROM t1 WHERE +w BETWEEN 200 AND 300)
   668      }
   669    } {}
   670    do_test where2-8.19 {
   671      execsql {
   672        SELECT w FROM tx
   673         WHERE x IN (SELECT x FROM t1 WHERE +w BETWEEN 10 AND 20)
   674           AND y IN (SELECT y FROM t1 WHERE +w BETWEEN 200 AND 300)
   675           AND z IN (SELECT z FROM t1 WHERE +w BETWEEN 10 AND 20)
   676      }
   677    } {}
   678    do_test where2-8.20 {
   679      execsql {
   680        SELECT w FROM tx
   681         WHERE x IN (SELECT x FROM t1 WHERE +w BETWEEN 200 AND 300)
   682           AND y IN (SELECT y FROM t1 WHERE +w BETWEEN 10 AND 20)
   683           AND z IN (SELECT z FROM t1 WHERE +w BETWEEN 10 AND 20)
   684      }
   685    } {}
   686  }  
   687  
   688  # Make sure WHERE clauses of the form A=1 AND (B=2 OR B=3) are optimized
   689  # when we have an index on A and B.
   690  #
   691  ifcapable or_opt&&tclvar {
   692    do_test where2-9.1 {
   693      execsql {
   694        BEGIN;
   695        CREATE TABLE t10(a,b,c);
   696        INSERT INTO t10 VALUES(1,1,1);
   697        INSERT INTO t10 VALUES(1,2,2);
   698        INSERT INTO t10 VALUES(1,3,3);
   699      }
   700      for {set i 4} {$i<=1000} {incr i} {
   701        execsql {INSERT INTO t10 VALUES(1,$i,$i)}
   702      }
   703      execsql {
   704        CREATE INDEX i10 ON t10(a,b);
   705        COMMIT;
   706        SELECT count(*) FROM t10;
   707      }
   708    } 1000
   709    ifcapable subquery {
   710      do_test where2-9.2 {
   711        count {
   712          SELECT * FROM t10 WHERE a=1 AND (b=2 OR b=3)
   713        }
   714      } {1 2 2 1 3 3 7}
   715    }
   716  }
   717  
   718  # Indices with redundant columns
   719  #
   720  do_test where2-11.1 {
   721    execsql {
   722      CREATE TABLE t11(a,b,c,d);
   723      CREATE INDEX i11aba ON t11(a,b,a,c); -- column A occurs twice.
   724      INSERT INTO t11 VALUES(1,2,3,4);
   725      INSERT INTO t11 VALUES(5,6,7,8);
   726      INSERT INTO t11 VALUES(1,2,9,10);
   727      INSERT INTO t11 VALUES(5,11,12,13);
   728      SELECT c FROM t11 WHERE a=1 AND b=2 ORDER BY c;
   729    }
   730  } {3 9}
   731  do_test where2-11.2 {
   732    execsql {
   733      CREATE INDEX i11cccccccc ON t11(c,c,c,c,c,c,c,c); -- repeated column
   734      SELECT d FROM t11 WHERE c=9;
   735    }
   736  } {10}
   737  do_test where2-11.3 {
   738    execsql {
   739      SELECT d FROM t11 WHERE c IN (1,2,3,4,5);
   740    }
   741  } {4}
   742  do_test where2-11.4 {
   743    execsql {
   744      SELECT d FROM t11 WHERE c=7 OR (a=1 AND b=2) ORDER BY d;
   745    }
   746  } {4 8 10}
   747  
   748  # Verify that the OR clause is used in an outer loop even when
   749  # the OR clause scores slightly better on an inner loop.
   750  if {[permutation] != "no_optimization"} {
   751  do_execsql_test where2-12.1 {
   752    CREATE TABLE t12(x INTEGER PRIMARY KEY, y INT, z CHAR(100));
   753    CREATE INDEX t12y ON t12(y);
   754    EXPLAIN QUERY PLAN
   755      SELECT a.x, b.x
   756        FROM t12 AS a JOIN t12 AS b ON a.y=b.x
   757       WHERE (b.x=$abc OR b.y=$abc);
   758  } {/SEARCH b .*SEARCH b /}
   759  }
   760  
   761  # Verify that all necessary OP_OpenRead opcodes occur in the OR optimization.
   762  #
   763  do_execsql_test where2-13.1 {
   764    CREATE TABLE t13(a,b);
   765    CREATE INDEX t13a ON t13(a);
   766    INSERT INTO t13 VALUES(4,5);
   767    SELECT * FROM t13 WHERE (1=2 AND a=3) OR a=4;
   768  } {4 5}
   769  
   770  # https://www.sqlite.org/src/info/5e3c886796e5512e  (2016-03-09)
   771  # Correlated subquery on the RHS of an IN operator 
   772  #
   773  do_execsql_test where2-14.1 {
   774    CREATE TABLE t14a(x INTEGER PRIMARY KEY);
   775    INSERT INTO t14a(x) VALUES(1),(2),(3),(4);
   776    CREATE TABLE t14b(y INTEGER PRIMARY KEY);
   777    INSERT INTO t14b(y) VALUES(1);
   778    SELECT x FROM t14a WHERE x NOT IN (SELECT x FROM t14b);
   779  } {}
   780  
   781  finish_test