1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-10-31 18:11:01 +03:00

Added the SQLITE_OMIT_SUBQUERY compile-time option and the EXISTS operator.

Regression tests are currently failing with an assertion fault. (CVS 2245)

FossilOrigin-Name: d30fdf0f2c24cb74b48fab9b83fba4e4b2fe878a
This commit is contained in:
drh
2005-01-20 13:36:19 +00:00
parent 5338a5f74d
commit 51522cd34a
7 changed files with 105 additions and 65 deletions

View File

@@ -1,5 +1,5 @@
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
@@ -36,7 +36,7 @@ F src/cursor.c de73c00aefc4747ad59b5105cf38bbff0667922e
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
@@ -54,14 +54,14 @@ F src/os_win.c 3c0b0a3bc33318cf555a1cd130232ad1b9a5a711
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
@@ -214,7 +214,7 @@ F tool/lempar.c 1e61d2b6cb9d8affa264a13336bc0c088498caa4
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
@@ -270,7 +270,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
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

View File

@@ -1 +1 @@
417bbba93ad7ed5c03d9db6afc12e170155bd152
d30fdf0f2c24cb74b48fab9b83fba4e4b2fe878a

View File

@@ -12,7 +12,7 @@
** 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>
@@ -1176,6 +1176,7 @@ struct QueryCoder {
** 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;
@@ -1263,6 +1264,7 @@ static int codeSubqueryStep(void *pArg, Expr *pExpr){
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
@@ -1272,6 +1274,8 @@ static int codeSubqueryStep(void *pArg, Expr *pExpr){
int nRef;
Vdbe *v;
int addr;
int sop;
Select *pSel;
pNC = pCoder->pNC;
if( pNC ) nRef = pNC->nRef;
@@ -1279,7 +1283,17 @@ static int codeSubqueryStep(void *pArg, Expr *pExpr){
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;
@@ -1295,6 +1309,7 @@ static int codeSubqueryStep(void *pArg, Expr *pExpr){
}
return 0;
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** Generate code to evaluate subqueries and IN operators contained
@@ -1305,10 +1320,12 @@ static int sqlite3ExprCodeSubquery(
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;
}

View File

@@ -14,7 +14,7 @@
** 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}
@@ -418,6 +418,7 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). {
else { sqlite3IdListDelete(U); }
}
}
%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);
@@ -443,6 +444,7 @@ 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;}
@@ -692,11 +694,6 @@ expr(A) ::= PLUS(B) expr(X). [UPLUS] {
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;}
@@ -717,6 +714,12 @@ expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
if( N ) A = sqlite3Expr(TK_NOT, A, 0, 0);
sqlite3ExprSpan(A,&X->span,&E);
}
%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;
@@ -730,7 +733,14 @@ expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
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). {

View File

@@ -12,7 +12,7 @@
** 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"
@@ -504,6 +504,7 @@ static int selectInnerLoop(
** 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 ){
@@ -617,6 +618,7 @@ static void generateSortTail(
sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
break;
}
case SRT_Exists:
case SRT_Mem: {
assert( nColumn==1 );
sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
@@ -2373,6 +2375,7 @@ int sqlite3Select(
/* 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");
@@ -2460,6 +2463,7 @@ int sqlite3Select(
/* 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;
@@ -2486,6 +2490,7 @@ int sqlite3Select(
pHaving = p->pHaving;
isDistinct = p->isDistinct;
}
#endif
/* Check for the special case of a min() or max() function by itself
** in the result set.
@@ -2590,10 +2595,10 @@ int sqlite3Select(
}
}
/* 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);
}

View File

@@ -11,7 +11,7 @@
*************************************************************************
** 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_
@@ -832,6 +832,7 @@ struct Expr {
#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
@@ -1016,6 +1017,7 @@ struct Select {
#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)")

View File

@@ -80,20 +80,25 @@ struct Keyword {
#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
@@ -146,6 +151,7 @@ static Keyword aKeywordTable[] = {
{ "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 },