]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Added the SQLITE_OMIT_SUBQUERY compile-time option and the EXISTS operator.
authordrh <drh@noemail.net>
Thu, 20 Jan 2005 13:36:19 +0000 (13:36 +0000)
committerdrh <drh@noemail.net>
Thu, 20 Jan 2005 13:36:19 +0000 (13:36 +0000)
Regression tests are currently failing with an assertion fault. (CVS 2245)

FossilOrigin-Name: d30fdf0f2c24cb74b48fab9b83fba4e4b2fe878a

manifest
manifest.uuid
src/expr.c
src/parse.y
src/select.c
src/sqliteInt.h
tool/mkkeywordhash.c

index a52e6f6c62ead403992d7a3d9de2a6c1e514d76e..e7853ffe1f3e7599a87c29c1afe2635378d82860 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index d1c6a0719bc4b12f614a2fd850a3a9e334c82190..12ebe43388c461dbf2b4d3c7401117bccf71f0f4 100644 (file)
@@ -1 +1 @@
-417bbba93ad7ed5c03d9db6afc12e170155bd152
\ No newline at end of file
+d30fdf0f2c24cb74b48fab9b83fba4e4b2fe878a
\ No newline at end of file
index 8d9d9f47eae9953e17ea7d856532e99d0ae4a822..514566aaa1f678d4c553b76d7808f4cfdd6a9907 100644 (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;
 }
 
index 197fce69a862471582a590e7488f6c80ec3ceab9..f5acf880e9214d518eb3fd7cb39fce14ce4c6bd0 100644 (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,31 +418,33 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). {
     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;}
@@ -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,20 +714,33 @@ 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);
 }
-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). {
index f26ebe1a0721549403c8bbc0c0b2e89d13d10b25..a91abbef27d95607ffe461dd8f9c6fad1590d19f 100644 (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);
   }
 
index 963e13bebafbc8102db70891311d6b816a69d9ad..745dd48737aadd88a857f1835d3fca9d42461ef5 100644 (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)")
index b1005c41caa6f5c73a47e81b1daf30082c22576c..952d5d34a67ef9ccc6d2d4dcd05eeb2eed829b32 100644 (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                 },