-C Remove\sa\sfew\smore\slines\sof\scode\swhen\sSQLITE_OMIT_**\smacros\sare\sdefined.\s(CVS\s2244)
-D 2005-01-20T13:03:10
+C Added\sthe\sSQLITE_OMIT_SUBQUERY\scompile-time\soption\sand\sthe\sEXISTS\soperator.\nRegression\stests\sare\scurrently\sfailing\swith\san\sassertion\sfault.\s(CVS\s2245)
+D 2005-01-20T13:36:20
F Makefile.in ffd81f5e926d40b457071b4de8d7c1fa18f39b5a
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
F src/date.c f3d1f5cd1503dabf426a198f3ebef5afbc122a7f
F src/delete.c b3accca9c38d9a67dbd724f67b04151a13735ebd
F src/experimental.c 8cc66b2be6a011055d75ef19ed2584bcfbb585ad
-F src/expr.c 09022cbd4fbdff66fbab0f04d010d413cb06b493
+F src/expr.c 12b37893ab7e3a41d1d9e9a4931eeb3690951d1f
F src/func.c dc188d862d7276ea897655b248e2cb17022686e3
F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 05d23abbcfa3133f716a99589e53883c10551b1f
F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862
-F src/parse.y 276efb30de5d8582bda9b6a98b17aac6875ab3e9
+F src/parse.y 301d07db056f5125806e84994b5f41a8355d28ad
F src/pragma.c 8ab313986673aa4c45e8693d8aabb9b95ee7b14a
F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
-F src/select.c 1686f2503c9c7f9de4d564944584015b71c50ac3
+F src/select.c 8a4a38310c5168d1f6e1759494e57cf838d6d37c
F src/shell.c 591364a0e9ca4ce53873e21e0294476c0c2b4770
F src/sqlite.h.in 8249b697d71ef6d7f7f752ba4ca04058e9e8b5ff
-F src/sqliteInt.h c1acfbeb8b84444e5b86dfce19ff42b5854f6478
+F src/sqliteInt.h 9a582fcb8333b5a30706250282d9697654305dbc
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
F src/tclsqlite.c fd27457b228118be96524dae285146c76efe032b
F src/test1.c 59fc0f0c35cb3bccdf166f36a1a5f9ffb0b951e7
F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
F tool/memleak3.tcl b8eb053190e95a55dc188896afb972e8108822d6
-F tool/mkkeywordhash.c 408dccad57ed50dc67a9a1ee7fd258e0f0a07bd2
+F tool/mkkeywordhash.c db33613e94e9ed3fb0838e2c3ca4415c5fd7ec0e
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl c3b50d3ac31c54be2a1af9b488a89d22f1e6e746
-P 5b1a9bf6aa5a5c466b88f649e322e81b8466851f
-R db2528b7bd532f73e60abad289bd81fd
-U danielk1977
-Z b2590dd052208a3aa6c3782df4f94dd4
+P 417bbba93ad7ed5c03d9db6afc12e170155bd152
+R 0a5b2b3342f1338802ba7063dbaea636
+U drh
+Z 9bd559beb0f6f23bafe4d9cc37e5f07d
-417bbba93ad7ed5c03d9db6afc12e170155bd152
\ No newline at end of file
+d30fdf0f2c24cb74b48fab9b83fba4e4b2fe878a
\ No newline at end of file
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.184 2005/01/20 13:03:10 danielk1977 Exp $
+** $Id: expr.c,v 1.185 2005/01/20 13:36:20 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
** sqlite3ExprCodeSubquery(). See comments on those routines for
** additional information.
*/
+#ifndef SQLITE_OMIT_SUBQUERY
static int codeSubqueryStep(void *pArg, Expr *pExpr){
QueryCoder *pCoder = (QueryCoder*)pArg;
Parse *pParse = pCoder->pParse;
return 1;
}
+ case TK_EXISTS:
case TK_SELECT: {
/* This has to be a scalar SELECT. Generate code to put the
** value of this select in a memory cell and record the number
int nRef;
Vdbe *v;
int addr;
+ int sop;
+ Select *pSel;
pNC = pCoder->pNC;
if( pNC ) nRef = pNC->nRef;
v = sqlite3GetVdbe(pParse);
addr = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
pExpr->iColumn = pParse->nMem++;
- sqlite3Select(pParse, pExpr->pSelect, SRT_Mem,pExpr->iColumn,0,0,0,0,pNC);
+ pSel = pExpr->pSelect;
+ if( pExpr->op==TK_SELECT ){
+ sop = SRT_Mem;
+ }else{
+ static const Token one = { "1", 0, 1 };
+ sop = SRT_Exists;
+ sqlite3ExprListDelete(pSel->pEList);
+ pSel->pEList = sqlite3ExprListAppend(0,
+ sqlite3Expr(TK_INTEGER, 0, 0, &one), 0);
+ }
+ sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0, pNC);
if( pNC && pNC->nRef>nRef ){
/* Subquery value changes. Evaluate at each use */
pExpr->iTable = addr+1;
}
return 0;
}
+#endif /* SQLITE_OMIT_SUBQUERY */
/*
** Generate code to evaluate subqueries and IN operators contained
NameContext *pNC, /* First enclosing namespace. Often NULL */
Expr *pExpr /* Subquery to be coded */
){
+#ifndef SQLITE_OMIT_SUBQUERY
QueryCoder sCoder;
sCoder.pParse = pParse;
sCoder.pNC = pNC;
walkExprTree(pExpr, codeSubqueryStep, &sCoder);
+#endif
return 0;
}
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.160 2005/01/20 02:14:31 drh Exp $
+** @(#) $Id: parse.y,v 1.161 2005/01/20 13:36:20 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
else { sqlite3IdListDelete(U); }
}
}
-seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP
- as(Z) on_opt(N) using_opt(U). {
- A = sqlite3SrcListAppend(X,0,0);
- A->a[A->nSrc-1].pSelect = S;
- if( Z.n ) sqlite3SrcListAddAlias(A,&Z);
- if( N ){
- if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; }
- else { sqlite3ExprDelete(N); }
+%ifndef SQLITE_OMIT_SUBQUERY
+ seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP
+ as(Z) on_opt(N) using_opt(U). {
+ A = sqlite3SrcListAppend(X,0,0);
+ A->a[A->nSrc-1].pSelect = S;
+ if( Z.n ) sqlite3SrcListAddAlias(A,&Z);
+ if( N ){
+ if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pOn = N; }
+ else { sqlite3ExprDelete(N); }
+ }
+ if( U ){
+ if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; }
+ else { sqlite3IdListDelete(U); }
+ }
}
- if( U ){
- if( A && A->nSrc>1 ){ A->a[A->nSrc-2].pUsing = U; }
- else { sqlite3IdListDelete(U); }
+
+ // A seltablist_paren nonterminal represents anything in a FROM that
+ // is contained inside parentheses. This can be either a subquery or
+ // a grouping of table and subqueries.
+ //
+ %type seltablist_paren {Select*}
+ %destructor seltablist_paren {sqlite3SelectDelete($$);}
+ seltablist_paren(A) ::= select(S). {A = S;}
+ seltablist_paren(A) ::= seltablist(F). {
+ A = sqlite3SelectNew(0,F,0,0,0,0,0,-1,0);
}
-}
-
-// A seltablist_paren nonterminal represents anything in a FROM that
-// is contained inside parentheses. This can be either a subquery or
-// a grouping of table and subqueries.
-//
-%type seltablist_paren {Select*}
-%destructor seltablist_paren {sqlite3SelectDelete($$);}
-seltablist_paren(A) ::= select(S). {A = S;}
-seltablist_paren(A) ::= seltablist(F). {
- A = sqlite3SelectNew(0,F,0,0,0,0,0,-1,0);
-}
+%endif // SQLITE_OMIT_SUBQUERY
%type dbnm {Token}
dbnm(A) ::= . {A.z=0; A.n=0;}
A = sqlite3Expr(TK_UPLUS, X, 0, 0);
sqlite3ExprSpan(A,&B,&X->span);
}
-expr(A) ::= LP(B) select(X) RP(E). {
- A = sqlite3Expr(TK_SELECT, 0, 0, 0);
- if( A ) A->pSelect = X;
- sqlite3ExprSpan(A,&B,&E);
-}
%type between_op {int}
between_op(A) ::= BETWEEN. {A = 0;}
between_op(A) ::= NOT BETWEEN. {A = 1;}
if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
sqlite3ExprSpan(A,&X->span,&E);
}
-expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] {
- A = sqlite3Expr(TK_IN, X, 0, 0);
- if( A ) A->pSelect = Y;
- if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
- sqlite3ExprSpan(A,&X->span,&E);
-}
-expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
- SrcList *pSrc = sqlite3SrcListAppend(0,&Y,&Z);
- A = sqlite3Expr(TK_IN, X, 0, 0);
- if( A ) A->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,-1,0);
- if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
- sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y);
-}
-
+%ifndef SQLITE_OMIT_SUBQUERY
+ expr(A) ::= LP(B) select(X) RP(E). {
+ A = sqlite3Expr(TK_SELECT, 0, 0, 0);
+ if( A ) A->pSelect = X;
+ sqlite3ExprSpan(A,&B,&E);
+ }
+ expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] {
+ A = sqlite3Expr(TK_IN, X, 0, 0);
+ if( A ) A->pSelect = Y;
+ if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
+ sqlite3ExprSpan(A,&X->span,&E);
+ }
+ expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
+ SrcList *pSrc = sqlite3SrcListAppend(0,&Y,&Z);
+ A = sqlite3Expr(TK_IN, X, 0, 0);
+ if( A ) A->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,-1,0);
+ if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
+ sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y);
+ }
+ expr(A) ::= EXISTS(B) LP select(Y) RP(E). {
+ Expr *p = A = sqlite3Expr(TK_EXISTS, 0, 0, 0);
+ if( p ){
+ p->pSelect = Y;
+ sqlite3ExprSpan(p,&B,&E);
+ }
+ }
+%endif // SQLITE_OMIT_SUBQUERY
/* CASE expressions */
expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.230 2005/01/20 13:03:10 danielk1977 Exp $
+** $Id: select.c,v 1.231 2005/01/20 13:36:20 drh Exp $
*/
#include "sqliteInt.h"
** store the results in the appropriate memory cell and break out
** of the scan loop.
*/
+ case SRT_Exists:
case SRT_Mem: {
assert( nColumn==1 );
if( pOrderBy ){
sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
break;
}
+ case SRT_Exists:
case SRT_Mem: {
assert( nColumn==1 );
sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
/* If writing to memory or generating a set
** only a single column may be output.
*/
+ assert( eDest!=SRT_Exists || pEList->nExpr==1 );
if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){
sqlite3ErrorMsg(pParse, "only a single result allowed for "
"a SELECT that is part of an expression");
/* Generate code for all sub-queries in the FROM clause
*/
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; i<pTabList->nSrc; i++){
const char *zSavedAuthContext = 0;
int needRestoreContext;
pHaving = p->pHaving;
isDistinct = p->isDistinct;
}
+#endif
/* Check for the special case of a min() or max() function by itself
** in the result set.
}
}
- /* Initialize the memory cell to NULL
+ /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists
*/
- if( eDest==SRT_Mem ){
- sqlite3VdbeAddOp(v, OP_String8, 0, 0);
+ if( eDest==SRT_Mem || eDest==SRT_Exists ){
+ sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_String8 : OP_Integer, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
}
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.358 2005/01/20 02:14:31 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.359 2005/01/20 13:36:20 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
#define EP_Error 0x0008 /* Expression contains one or more errors */
+#define EP_Not 0x0010 /* Operator preceeded by NOT */
/*
** These macros can be used to test, set, or clear bits in the
#define SRT_Discard 9 /* Do not save the results anywhere */
#define SRT_Sorter 10 /* Store results in the sorter */
#define SRT_Subroutine 11 /* Call a subroutine to handle results */
+#define SRT_Exists 12 /* Put 0 or 1 in a memory cell */
/*
** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)")
#else
# define REINDEX 1024
#endif
+#ifdef SQLITE_OMIT_SUBQUERY
+# define SUBQUERY 0
+#else
+# define SUBQUERY 2048
+#endif
#ifdef SQLITE_OMIT_TRIGGER
# define TRIGGER 0
#else
-# define TRIGGER 2048
+# define TRIGGER 4096
#endif
#ifdef SQLITE_OMIT_VACUUM
# define VACUUM 0
#else
-# define VACUUM 4096
+# define VACUUM 8192
#endif
#ifdef SQLITE_OMIT_VIEW
# define VIEW 0
#else
-# define VIEW 8192
+# define VIEW 16384
#endif
{ "ESCAPE", "TK_ESCAPE", ALWAYS },
{ "EXCEPT", "TK_EXCEPT", COMPOUND },
{ "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS },
+ { "EXISTS", "TK_EXISTS", SUBQUERY },
{ "EXPLAIN", "TK_EXPLAIN", EXPLAIN },
{ "FAIL", "TK_FAIL", CONFLICT|TRIGGER },
{ "FETCH", "TK_FETCH", CURSOR },