Annotation of embedaddon/sqlite3/test/where2.test, revision 1.1

1.1     ! misho       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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>