-C Change\sthe\sname\sof\sthe\sOpenTemp\sopcode\sto\sOpenVirtual\swhich\sis\smore\ndescriptive\sof\swhat\sit\sdoes.\s(CVS\s2541)
-D 2005-07-08T17:13:47
+C Allow\sthe\sIN\soperator\sto\stake\sa\slist\sof\sarbitrary\sexpressions\son\sits\nright-hand\sside.\s\sThe\sexpressions\sno\slonger\sneed\sto\sbe\sconstant.\s\sThe\ncurrent\simplementation\sseems\sto\swork\sbut\sneeds\smore\stesting\sand\soptimization.\s(CVS\s2542)
+D 2005-07-08T18:25:26
F Makefile.in 3c10cd7bc3ecbd60fe4d5a5c0f59bfa7fb217a66
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F src/date.c 7444b0900a28da77e57e3337a636873cff0ae940
F src/delete.c 250d436a68fe371b4ab403d1c0f6fdc9a6860c39
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
-F src/expr.c daf3515d33467090741d98227577356c108ea33f
+F src/expr.c 94dce12d5228af02fdafc23e56abfeae25f3b694
F src/func.c e6637354fe3a66dfac063a49109f277cde9ce87d
F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F test/fkey1.test 81bb13caaa78f58d7d191d7f535529f7c91d821a
F test/func.test b062105b45cf8fb5b386ba137180c0f439eea0c9
F test/hook.test f8605cde4c77b2c6a4a73723bf6c507796a64dda
-F test/in.test ed134f8d477a6280297ced1646de83cccf8f196d
+F test/in.test cead6165aebbe0d451bb2263a307173acfeb6240
F test/index.test 51e01a0928b4b61228917ddd8c6c0e2466547f6f
F test/index2.test 9ad98243fd7fe833795a9cc662f371f0eed4ff4f
F test/index3.test 72bd07b508022db688ec536c460345d24a3912e3
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
-P f4a66ed04dfd8714746b766b4859682ea18e328f
-R 7dbd5cf11e082700c07694668805a635
+P 3bb9ce5f20d0a6bc19df31df9b8e82044c3e6004
+R 1efa9cdd449acebde300ce2385775e19
U drh
-Z 2074933014582e5567aec0bab96430cb
+Z 5c326e79427e109a129a76bef3edf05e
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.210 2005/07/08 17:13:47 drh Exp $
+** $Id: expr.c,v 1.211 2005/07/08 18:25:26 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
*/
#ifndef SQLITE_OMIT_SUBQUERY
void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
- int label = 0; /* Address after sub-select code */
+ int testAddr = 0; /* One-time test address */
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
- /* If this is not a variable (correlated) select, then execute
- ** it only once. Unless this is part of a trigger program. In
- ** that case re-execute every time (this could be optimized).
+ /* This code must be run in its entirety every time it is encountered
+ ** if any of the following is true:
+ **
+ ** * The right-hand side is a correlated subquery
+ ** * The right-hand side is an expression list containing variables
+ ** * We are inside a trigger
+ **
+ ** If all of the above are false, then we can run this code just once
+ ** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
int mem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);
- label = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp(v, OP_If, 0, label);
+ testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0);
+ assert( testAddr>0 );
sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
sqlite3VdbeAddOp(v, OP_MemStore, mem, 1);
}
affinity = sqlite3ExprAffinity(pExpr->pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
- ** expression it is handled the same way. A temporary table is
+ ** expression it is handled the same way. A virtual table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
** a column, use numeric affinity.
*/
int i;
+ ExprList *pList = pExpr->pList;
+ struct ExprList_item *pItem;
+
if( !affinity ){
affinity = SQLITE_AFF_NUMERIC;
}
keyInfo.aColl[0] = pExpr->pLeft->pColl;
/* Loop through each expression in <exprlist>. */
- for(i=0; i<pExpr->pList->nExpr; i++){
- Expr *pE2 = pExpr->pList->a[i].pExpr;
-
- /* Check that the expression is constant and valid. */
- if( !sqlite3ExprIsConstant(pE2) ){
- sqlite3ErrorMsg(pParse,
- "right-hand side of IN operator must be constant");
- return;
+ for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
+ Expr *pE2 = pItem->pExpr;
+
+ /* If the expression is not constant then we will need to
+ ** disable the test that was generated above that makes sure
+ ** this code only executes once. Because for a non-constant
+ ** expression we need to rerun this code each time.
+ */
+ if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
+ VdbeOp *aOp = sqlite3VdbeGetOp(v, testAddr-1);
+ int i;
+ for(i=0; i<4; i++){
+ aOp[i].opcode = OP_Noop;
+ }
+ testAddr = 0;
}
/* Evaluate the expression and insert it into the temp table */
if( pExpr->pSelect ){
sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0);
}
- if( label<0 ){
- sqlite3VdbeResolveLabel(v, label);
+ if( testAddr ){
+ sqlite3VdbeChangeP2(v, testAddr, sqlite3VdbeCurrentAddr(v));
}
return;
}
# This file implements regression tests for SQLite library. The
# focus of this file is testing the IN and BETWEEN operator.
#
-# $Id: in.test,v 1.13 2005/01/21 03:12:16 danielk1977 Exp $
+# $Id: in.test,v 1.14 2005/07/08 18:25:26 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
} {1 2 103 104 5 6 7 8 9 10}
do_test in-2.6 {
- set v [catch {execsql {SELECT a FROM t1 WHERE b IN (b+10,20)}} msg]
- lappend v $msg
-} {1 {right-hand side of IN operator must be constant}}
+ execsql {SELECT a FROM t1 WHERE b IN (b+8,64)}
+} {6}
do_test in-2.7 {
- set v [catch {execsql {SELECT a FROM t1 WHERE b IN (max(5,10,b),20)}} msg]
- lappend v $msg
-} {1 {right-hand side of IN operator must be constant}}
+ execsql {SELECT a FROM t1 WHERE b IN (max(5,10,b),20)}
+} {4 5 6 7 8 9 10}
do_test in-2.8 {
execsql {SELECT a FROM t1 WHERE b IN (8*2,64/2) ORDER BY b}
} {4 5}
do_test in-2.9 {
- set v [catch {execsql {SELECT a FROM t1 WHERE b IN (max(5,10),20)}} msg]
- lappend v $msg
-} {1 {right-hand side of IN operator must be constant}}
+ execsql {SELECT a FROM t1 WHERE b IN (max(5,10),20)}
+} {}
do_test in-2.10 {
- set v [catch {execsql {SELECT a FROM t1 WHERE min(0,b IN (a,30))}} msg]
- lappend v $msg
-} {1 {right-hand side of IN operator must be constant}}
+ execsql {SELECT a FROM t1 WHERE min(0,b IN (a,30))}
+} {}
do_test in-2.11 {
set v [catch {execsql {SELECT a FROM t1 WHERE c IN (10,20)}} msg]
lappend v $msg