-C Fix\san\sunnecessarily\sobtuse\suse\sof\sa\sbitmask\sflag.
-D 2014-03-20T12:17:35.051
+C Convert\sexpressions\sof\sthe\sform\s"X\sIN\s(?)"\swith\sexactly\sone\svalue\son\sthe\nRHS\sof\sthe\sIN\sinto\sequality\stests:\s\s"X=?".\s\sAdd\stest\scases\sto\sverify\sthat\nstatements\swork\scorrectly\son\sthis\scorner\scase.\nFix\sfor\sticket\s[e39d032577df6942].
+D 2014-03-20T13:26:47.152
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/os_win.c e71678ac927d0a0fb11d993db20a9748eabf808e
F src/pager.c 97a8908bf4e6e7c3adea09d3597cfa48ae33ab4e
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
-F src/parse.y 2613ca5d609c2f3d71dd297351f010bcec16e1e0
+F src/parse.y 52d749e7fd1289d9a576fe88782d9637a2f7bb6d
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
-F src/where.c e433accd201ca482c761e679f4a2ce2f6a7348e6
+F src/where.c a2f20bdc6565a3add38ac5e4d9e71523ed5b2f2b
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
-F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617
+F test/in4.test ed42587bed8c8e2219a09a6a6e3675edffc011da
F test/in5.test 99f9a40af01711b06d2d614ecfe96129f334fba3
F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 707ea170b3e26965b7e3982f7554d122d130b9a6
-R 829b1d227d22721b3fefbad8e2ead1b7
+P ca3140813198ab7ce470cf86334e55207f3461f9
+R abb091fc1f04a82c7540caf08b56e8dd
U drh
-Z fcfbdaafabd38e7e728b08b0509fc847
+Z 8ed34cb3369a2d9b188815f2f4b333aa
-ca3140813198ab7ce470cf86334e55207f3461f9
\ No newline at end of file
+e68b427afbc82e201c64474117851aa4c9eb0c92
\ No newline at end of file
*/
A.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[N]);
sqlite3ExprDelete(pParse->db, X.pExpr);
+ }else if( Y->nExpr==1 ){
+ /* Expressions of the form:
+ **
+ ** expr1 IN (?1)
+ ** expr1 NOT IN (?2)
+ **
+ ** with exactly one value on the RHS can be simplified to:
+ **
+ ** expr1 == ?1
+ ** expr1 <> ?2
+ */
+ Expr *pRHS = Y->a[0].pExpr;
+ Y->a[0].pExpr = 0;
+ sqlite3ExprListDelete(pParse->db, Y);
+ A.pExpr = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, X.pExpr, pRHS, 0);
}else{
A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
if( A.pExpr ){
/* "x IN (value, value, ...)" */
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
+ assert( nIn>0 ); /* RHS always has 2 or more terms... The parser
+ ** changes "x IN (?)" into "x=?". */
pNew->rRun += nIn;
pNew->u.btree.nEq++;
pNew->nOut = nRowEst + nInMul + nIn;
execsql { SELECT * FROM t3 WHERE x IN (1, 2) AND y IN ()}
} {}
+# Tests for "... IN (?)" and "... NOT IN (?)". In other words, tests
+# for when the RHS of IN is a single expression. This should work the
+# same as the == and <> operators.
+#
+do_execsql_test in4-3.21 {
+ SELECT * FROM t3 WHERE x=10 AND y IN (10);
+} {10 10 10}
+do_execsql_test in4-3.22 {
+ SELECT * FROM t3 WHERE x IN (10) AND y=10;
+} {10 10 10}
+do_execsql_test in4-3.23 {
+ SELECT * FROM t3 WHERE x IN (10) AND y IN (10);
+} {10 10 10}
+do_execsql_test in4-3.24 {
+ SELECT * FROM t3 WHERE x=1 AND y NOT IN (10);
+} {1 1 1}
+do_execsql_test in4-3.25 {
+ SELECT * FROM t3 WHERE x NOT IN (10) AND y=1;
+} {1 1 1}
+do_execsql_test in4-3.26 {
+ SELECT * FROM t3 WHERE x NOT IN (10) AND y NOT IN (10);
+} {1 1 1}
+
+# The query planner recognizes that "x IN (?)" only generates a
+# single match and can use this information to optimize-out ORDER BY
+# clauses.
+#
+do_execsql_test in4-3.31 {
+ DROP INDEX t3i1;
+ CREATE UNIQUE INDEX t3xy ON t3(x,y);
+
+ SELECT *, '|' FROM t3 A, t3 B
+ WHERE A.x=10 AND A.y IN (10)
+ AND B.x=1 AND B.y IN (1);
+} {10 10 10 1 1 1 |}
+do_execsql_test in4-3.32 {
+ EXPLAIN QUERY PLAN
+ SELECT *, '|' FROM t3 A, t3 B
+ WHERE A.x=10 AND A.y IN (10)
+ AND B.x=1 AND B.y IN (1);
+} {~/B-TREE/} ;# No separate sorting pass
+do_execsql_test in4-3.33 {
+ SELECT *, '|' FROM t3 A, t3 B
+ WHERE A.x IN (10) AND A.y=10
+ AND B.x IN (1) AND B.y=1;
+} {10 10 10 1 1 1 |}
+do_execsql_test in4-3.34 {
+ EXPLAIN QUERY PLAN
+ SELECT *, '|' FROM t3 A, t3 B
+ WHERE A.x IN (10) AND A.y=10
+ AND B.x IN (1) AND B.y=1;
+} {~/B-TREE/} ;# No separate sorting pass
+
+# An expression of the form "x IN (?,?)" creates an ephemeral table to
+# hold the list of values on the RHS. But "x IN (?)" does not create
+# an ephemeral table.
+#
+do_execsql_test in4-3.41 {
+ SELECT * FROM t3 WHERE x IN (10,11);
+} {10 10 10}
+do_execsql_test in4-3.42 {
+ EXPLAIN
+ SELECT * FROM t3 WHERE x IN (10,11);
+} {/OpenEphemeral/}
+do_execsql_test in4-3.43 {
+ SELECT * FROM t3 WHERE x IN (10);
+} {10 10 10}
+do_execsql_test in4-3.44 {
+ EXPLAIN
+ SELECT * FROM t3 WHERE x IN (10);
+} {~/OpenEphemeral/}
+do_execsql_test in4-3.45 {
+ SELECT * FROM t3 WHERE x NOT IN (10,11);
+} {1 1 1}
+do_execsql_test in4-3.46 {
+ EXPLAIN
+ SELECT * FROM t3 WHERE x NOT IN (10,11);
+} {/OpenEphemeral/}
+do_execsql_test in4-3.47 {
+ SELECT * FROM t3 WHERE x NOT IN (10);
+} {1 1 1}
+do_execsql_test in4-3.48 {
+ EXPLAIN
+ SELECT * FROM t3 WHERE x NOT IN (10);
+} {~/OpenEphemeral/}
+
+
+
finish_test