]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
separate Select structure (CVS 51)
authordrh <drh@noemail.net>
Mon, 5 Jun 2000 16:01:39 +0000 (16:01 +0000)
committerdrh <drh@noemail.net>
Mon, 5 Jun 2000 16:01:39 +0000 (16:01 +0000)
FossilOrigin-Name: ce45dea902f9010a1c2c9ba3550dd789e7c15fcd

manifest
manifest.uuid
src/main.c
src/parse.y
src/select.c
src/sqliteInt.h
src/util.c
src/vdbe.c

index 28bcf84ebafe50e1af6facffd143d7662c9f1fd6..1d1c1fcb902d0b6487cd26371fd44dbd74cd079b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C :-)\s(CVS\s50)
-D 2000-06-05T02:07:04
+C separate\sSelect\sstructure\s(CVS\s51)
+D 2000-06-05T16:01:39
 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
 F Makefile.in 17ba1ccf8d2d40c627796bba8f72952365d6d644
 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
@@ -12,17 +12,17 @@ F src/dbbe.h a8a46f71238e0f09f3ec08fd9d1c8c7f4cdc49bf
 F src/delete.c e11433c14ed5cc8553cba14296b3baa3c23054bc
 F src/expr.c 793c15de4ce2911fa1a74999750bd3c0c9ca513f
 F src/insert.c ddae33b3dea1b4e743092d04240a20def9f88b72
-F src/main.c 06ee1dd1929b0a90e22a977c033e53c31cc012dd
-F src/parse.y 9ec486608b7b4daaccf4ad9f05eef1a26a008fb8
-F src/select.c 2dff3d237db6588ad657bb13f19dedebc046a4eb
+F src/main.c 93a7ad14bb5a82ad13ad59da23ef674a94b0c3d6
+F src/parse.y 020e5da71e14b63860c97589700eb11bf4699981
+F src/select.c 98f417b72e2edd277602cc14eb5c23743e616e60
 F src/shell.c 5fa24c0bb678782ffe9070128e3e160674f297eb
 F src/sqlite.h 58da0a8590133777b741f9836beaef3d58f40268
-F src/sqliteInt.h 7c269d229848045995782b10688acd59cbf08079
+F src/sqliteInt.h da8e0abf204438b812e315279acce05122166440
 F src/tclsqlite.c 9f358618ae803bedf4fb96da5154fd45023bc1f7
 F src/tokenize.c 15c229fee77325334c6814652e429b0930eba6c1
 F src/update.c 3f05d5082fd2c34f15d1e4a4db17355ad8807a78
-F src/util.c a06e8379665b18539cd9400641f3581d925f337e
-F src/vdbe.c c101c98de98cb4f946bb003ca2e6347cdd218ebc
+F src/util.c 33f9baa01e45394ef0cf85361a0e872987884315
+F src/vdbe.c 108f0e58beee1361bcb8dc2a59c7d54e5f4360bc
 F src/vdbe.h f20a3140905c385237e0891122beccde779c78c7
 F src/where.c bed9a8360cbfbf712bdc397c8e22216a5e5f9800
 F test/all.test 0950c135cab7e60c07bd745ccfad1476211e5bd7
@@ -47,7 +47,7 @@ F www/c_interface.tcl 8867d76ddd416d2fbd41e4cb3de8efa9cef105a5
 F www/changes.tcl 567cc6066d87460bdedff8e5bbc20f41ddaadf77
 F www/index.tcl f8189a7898f6d06307c34047b9d7e00860026e44
 F www/sqlite.tcl 2f933ce18cffd34a0a020a82435ab937137970fd
-P 6ea5cebf05562de00d2cf0b9e2aac5f3857638ee
-R 6949f362a1592f0e27ca1ae669f63813
+P 1cf2873d55b471bb3e397f90dc0868dd88c440a0
+R dfbce0b035783f6473b57dede04bcdd9
 U drh
-Z aae59671b659273e5022be83deddccc9
+Z 4195201472d7632b2259e7fe18f40c66
index d97df18fa6ea37ccc98ca1b47665517aacaaf1d2..b3958a948e16d6d95e2c9d9325985cae438e81bc 100644 (file)
@@ -1 +1 @@
-1cf2873d55b471bb3e397f90dc0868dd88c440a0
\ No newline at end of file
+ce45dea902f9010a1c2c9ba3550dd789e7c15fcd
\ No newline at end of file
index aeb75e3cff58295b4d7814f5300e53ef99d373a9..317c08ce61d8a8c3f1266227898768bacfbc7d9b 100644 (file)
@@ -26,7 +26,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.8 2000/06/05 02:07:04 drh Exp $
+** $Id: main.c,v 1.9 2000/06/05 16:01:39 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -40,7 +40,6 @@ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){
   sqlite *db = (sqlite*)pDb;
   Parse sParse;
   int nErr;
-  char *zErrMsg = 0;
 
   if( argc!=1 ) return 0;
   memset(&sParse, 0, sizeof(sParse));
index 69be1485dc9f3f19acf338b198549d86491c143e..001b03d0bc7dbe42564ce9af0076a16e480baee0 100644 (file)
@@ -26,7 +26,7 @@
 ** the parser.  Lemon will also generate a header file containing
 ** numeric codes for all of the tokens.
 **
-** @(#) $Id: parse.y,v 1.8 2000/06/03 19:19:41 drh Exp $
+** @(#) $Id: parse.y,v 1.9 2000/06/05 16:01:39 drh Exp $
 */
 %token_prefix TK_
 %token_type {Token}
@@ -132,28 +132,44 @@ cmd ::= DROP TABLE id(X).          {sqliteDropTable(pParse,&X);}
 
 // The select statement
 //
-cmd ::= select.
-select ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) orderby_opt(Z).
-     {sqliteSelect(pParse, W, X, Y, Z, D);}
-select ::= SELECT distinct(D) STAR from(X) where_opt(Y) orderby_opt(Z).
-     {sqliteSelect(pParse, 0, X, Y, Z, D);}
+cmd ::= select(X).  {
+  sqliteSelect(pParse, X, 0, 0);
+  sqliteSelectDelete(X);
+}
 
-%type distinct {int}
+%type select {Select*}
+%destructor select {sqliteSelectDelete($$);}
+
+select(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
+              orderby_opt(Z). {
+  A = sqliteSelectNew(W,X,Y,0,0,Z,D);
+}
 
+// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
+// present and false (0) if it is not.
+//
+%type distinct {int}
 distinct(A) ::= DISTINCT.   {A = 1;}
 distinct(A) ::= .           {A = 0;}
 
+// selcollist is a list of expressions that are to become the return
+// values of the SELECT statement.  In the case of "SELECT * FROM ..."
+// the selcollist value is NULL.  
+//
 %type selcollist {ExprList*}
 %destructor selcollist {sqliteExprListDelete($$);}
 %type sclp {ExprList*}
 %destructor sclp {sqliteExprListDelete($$);}
-
 sclp(A) ::= selcollist(X) COMMA.             {A = X;}
 sclp(A) ::= .                                {A = 0;}
+selcollist(A) ::= STAR.                      {A = 0;}
 selcollist(A) ::= sclp(P) expr(X).           {A = sqliteExprListAppend(P,X,0);}
-selcollist(A) ::= sclp(P) expr(X) AS ID(Y).  {A = sqliteExprListAppend(P,X,&Y);}
-selcollist(A) ::= sclp(P) expr(X) AS STRING(Y).
+selcollist(A) ::= sclp(P) expr(X) as ID(Y).  {A = sqliteExprListAppend(P,X,&Y);}
+selcollist(A) ::= sclp(P) expr(X) as STRING(Y).
   {A = sqliteExprListAppend(P,X,&Y);}
+as ::= .
+as ::= AS.
+
 
 %type seltablist {IdList*}
 %destructor seltablist {sqliteIdListDelete($$);}
@@ -179,16 +195,14 @@ seltablist(A) ::= stl_prefix(X) id(Y) AS id(Z).
 
 orderby_opt(A) ::= .                          {A = 0;}
 orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
-sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z).  
-  {
-    A = sqliteExprListAppend(X,Y,0);
-    A->a[A->nExpr-1].idx = Z;
-  }
-sortlist(A) ::= sortitem(Y) sortorder(Z).
-  {
-    A = sqliteExprListAppend(0,Y,0);
-    A->a[0].idx = Z;
-  }
+sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). {
+  A = sqliteExprListAppend(X,Y,0);
+  A->a[A->nExpr-1].idx = Z;       /* 0 for ascending order, 1 for decending */
+}
+sortlist(A) ::= sortitem(Y) sortorder(Z). {
+  A = sqliteExprListAppend(0,Y,0);
+  A->a[0].idx = Z;
+}
 sortitem(A) ::= expr(X).   {A = X;}
 
 %type sortorder {int}
index 82001ea18fd6b9fabca9b3bf1c5de8c26f85ffa3..e1f94891ece39b5dc576f9461c915e5e6b18f87d 100644 (file)
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements.
 **
-** $Id: select.c,v 1.6 2000/06/04 12:58:38 drh Exp $
+** $Id: select.c,v 1.7 2000/06/05 16:01:39 drh Exp $
 */
 #include "sqliteInt.h"
 
 
 /*
-** Process a SELECT statement.
+** Allocate a new Select structure and return a pointer to that
+** structure.
 */
-void sqliteSelect(
+Select *sqliteSelectNew(
+  ExprList *pEList,
+  IdList *pSrc,
+  Expr *pWhere,
+  ExprList *pGroupBy,
+  Expr *pHaving,
+  ExprList *pOrderBy,
+  int isDistinct
+){
+  Select *pNew;
+  pNew = sqliteMalloc( sizeof(*pNew) );
+  if( pNew==0 ) return 0;
+  pNew->pEList = pEList;
+  pNew->pSrc = pSrc;
+  pNew->pWhere = pWhere;
+  pNew->pGroupBy = pGroupBy;
+  pNew->pHaving = pHaving;
+  pNew->pOrderBy = pOrderBy;
+  pNew->isDistinct = isDistinct;
+  return pNew;
+}
+
+/*
+** Delete the given Select structure and all of its substructures.
+*/
+void sqliteSelectDelete(Select *p){
+  sqliteExprListDelete(p->pEList);
+  sqliteIdListDelete(p->pSrc);
+  sqliteExprDelete(p->pWhere);
+  sqliteExprListDelete(p->pGroupBy);
+  sqliteExprDelete(p->pHaving);
+  sqliteExprListDelete(p->pOrderBy);
+  sqliteFree(p);
+}
+
+/*
+** Generate code for the given SELECT statement.
+**
+** If pDest==0 and iMem<0, then the results of the query are sent to
+** the callback function.  If pDest!=0 then the results are written to
+** the single table specified.  If pDest==0 and iMem>=0 then the result
+** should be a single value which is then stored in memory location iMem
+** of the virtual machine.
+**
+** This routine returns the number of errors.  If any errors are
+** encountered, then an appropriate error message is left in
+** pParse->zErrMsg.
+**
+** This routine does NOT free the Select structure passed in.  The
+** calling function needs to do that.
+*/
+int sqliteSelect(
   Parse *pParse,         /* The parser context */
-  ExprList *pEList,      /* List of fields to extract.  NULL means "*" */
-  IdList *pTabList,      /* List of tables to select from */
-  Expr *pWhere,          /* The WHERE clause.  May be NULL */
-  ExprList *pOrderBy,    /* The ORDER BY clause.  May be NULL */
-  int distinct           /* If true, only output distinct results */
+  Select *p,             /* The SELECT statement being coded. */
+  Table *pDest,          /* Write results here, if not NULL */
+  int iMem               /* Save result in this memory location, if >=0 */
 ){
   int i, j;
   WhereInfo *pWInfo;
   Vdbe *v;
   int isAgg = 0;         /* True for select lists like "count(*)" */
+  ExprList *pEList;      /* List of fields to extract.  NULL means "*" */
+  IdList *pTabList;      /* List of tables to select from */
+  Expr *pWhere;          /* The WHERE clause.  May be NULL */
+  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
+  int distinct;          /* If true, only output distinct results */
+
 
-  if( pParse->nErr>0 ) goto select_cleanup;
+  pEList = p->pEList;
+  pTabList = p->pSrc;
+  pWhere = p->pWhere;
+  pOrderBy = p->pOrderBy;
+  distinct = p->isDistinct;
+
+  /* 
+  ** Do not even attempt to generate any code if we have already seen
+  ** errors before this routine starts.
+  */
+  if( pParse->nErr>0 ) return 0;
 
   /* Look up every table in the table list.
   */
@@ -55,7 +121,7 @@ void sqliteSelect(
       sqliteSetString(&pParse->zErrMsg, "no such table: ", 
          pTabList->a[i].zName, 0);
       pParse->nErr++;
-      goto select_cleanup;
+      return 1;
     }
   }
 
@@ -78,10 +144,10 @@ void sqliteSelect(
   */
   for(i=0; i<pEList->nExpr; i++){
     if( sqliteExprResolveIds(pParse, pTabList, pEList->a[i].pExpr) ){
-      goto select_cleanup;
+      return 1;
     }
     if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &pEList->a[i].isAgg) ){
-      goto select_cleanup;
+      return 1;
     }
   }
   if( pEList->nExpr>0 ){
@@ -91,25 +157,25 @@ void sqliteSelect(
         sqliteSetString(&pParse->zErrMsg, "some selected items are aggregates "
           "and others are not", 0);
         pParse->nErr++;
-        goto select_cleanup;
+        return 1;
       }
     }
   }
   if( pWhere ){
     if( sqliteExprResolveIds(pParse, pTabList, pWhere) ){
-      goto select_cleanup;
+      return 1;
     }
     if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
-      goto select_cleanup;
+      return 1;
     }
   }
   if( pOrderBy ){
     for(i=0; i<pOrderBy->nExpr; i++){
       if( sqliteExprResolveIds(pParse, pTabList, pOrderBy->a[i].pExpr) ){
-        goto select_cleanup;
+        return 1;
       }
       if( sqliteExprCheck(pParse, pOrderBy->a[i].pExpr, 0, 0) ){
-        goto select_cleanup;
+        return 1;
       }
     }
   }
@@ -118,7 +184,6 @@ void sqliteSelect(
   ** since only one row will be returned.
   */
   if( isAgg && pOrderBy ){
-    sqliteExprListDelete(pOrderBy);
     pOrderBy = 0;
   }
 
@@ -134,7 +199,11 @@ void sqliteSelect(
   if( v==0 ){
     v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
   }
-  if( v==0 ) goto select_cleanup;
+  if( v==0 ){
+    sqliteSetString(&pParse->zErrMsg, "out of memory", 0);
+    pParse->nErr++;
+    return 1;
+  }
   if( pOrderBy ){
     sqliteVdbeAddOp(v, OP_SortOpen, 0, 0, 0, 0);
   }
@@ -201,7 +270,7 @@ void sqliteSelect(
     sqliteVdbeAddOp(v, OP_Open, distinct, 1, 0, 0);
   }
   pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0);
-  if( pWInfo==0 ) goto select_cleanup;
+  if( pWInfo==0 ) return 1;
 
   /* Pull the requested fields.
   */
@@ -232,7 +301,7 @@ void sqliteSelect(
     char *zSortOrder;
     sqliteVdbeAddOp(v, OP_SortMakeRec, pEList->nExpr, 0, 0, 0);
     zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 );
-    if( zSortOrder==0 ) goto select_cleanup;
+    if( zSortOrder==0 ) return 1;
     for(i=0; i<pOrderBy->nExpr; i++){
       zSortOrder[i] = pOrderBy->a[i].idx ? '-' : '+';
       sqliteExprCode(pParse, pOrderBy->a[i].pExpr);
@@ -288,14 +357,5 @@ void sqliteSelect(
   if( isAgg ){
     sqliteVdbeAddOp(v, OP_Callback, pEList->nExpr, 0, 0, 0);
   }
-
-  /* Always execute the following code before exiting, in order to
-  ** release resources.
-  */
-select_cleanup:
-  sqliteExprListDelete(pEList);
-  sqliteIdListDelete(pTabList);
-  sqliteExprDelete(pWhere);
-  sqliteExprListDelete(pOrderBy);
-  return;
+  return 0;
 }
index 48f3895f3ad2150dd9ea758529bee7fcced00a69..a0a6f319d08fa7c0b983646f260d86a360355a84 100644 (file)
@@ -23,7 +23,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.13 2000/06/05 02:07:04 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.14 2000/06/05 16:01:39 drh Exp $
 */
 #include "sqlite.h"
 #include "dbbe.h"
@@ -35,7 +35,7 @@
 #include <string.h>
 #include <assert.h>
 
-/* #define MEMORY_DEBUG 1 */
+#define MEMORY_DEBUG 1
 #ifdef MEMORY_DEBUG
 # define sqliteMalloc(X)    sqliteMalloc_(X,__FILE__,__LINE__)
 # define sqliteFree(X)      sqliteFree_(X,__FILE__,__LINE__)
@@ -87,6 +87,7 @@ typedef struct Parse Parse;
 typedef struct Token Token;
 typedef struct IdList IdList;
 typedef struct WhereInfo WhereInfo;
+typedef struct Select Select;
 
 /*
 ** Each database is an instance of the following structure
@@ -208,6 +209,20 @@ struct WhereInfo {
   int iBreak;
 };
 
+/*
+** An instance of the following structure contains all information
+** needed to generate code for a single SELECT statement.
+*/
+struct Select {
+  int isDistinct;        /* True if the DISTINCT keyword is present */
+  ExprList *pEList;      /* The fields of the result */
+  IdList *pSrc;          /* The FROM clause */
+  Expr *pWhere;          /* The WHERE clause */
+  ExprList *pGroupBy;    /* The GROUP BY clause */
+  Expr *pHaving;         /* The HAVING clause */
+  ExprList *pOrderBy;    /* The ORDER BY clause */
+};
+
 /*
 ** An SQL parser context
 */
@@ -266,7 +281,9 @@ void sqliteIdListAddAlias(IdList*, Token*);
 void sqliteIdListDelete(IdList*);
 void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, Token*, Token*);
 void sqliteDropIndex(Parse*, Token*);
-void sqliteSelect(Parse*, ExprList*, IdList*, Expr*, ExprList*, int);
+int sqliteSelect(Parse*, Select*, Table*, int);
+Select *sqliteSelectNew(ExprList*,IdList*,Expr*,ExprList*,Expr*,ExprList*,int);
+void sqliteSelectDelete(Select*);
 void sqliteDeleteFrom(Parse*, Token*, Expr*);
 void sqliteUpdate(Parse*, Token*, ExprList*, Expr*);
 WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int);
index 1142a60e9af19ba5f4cd7404f33c48967f683192..b3e0d7760cefd8a056e3d910282f582422181335 100644 (file)
@@ -26,7 +26,7 @@
 ** This file contains functions for allocating memory, comparing
 ** strings, and stuff like that.
 **
-** $Id: util.c,v 1.10 2000/06/04 12:58:38 drh Exp $
+** $Id: util.c,v 1.11 2000/06/05 16:01:39 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -102,13 +102,13 @@ void *sqliteRealloc_(void *oldP, int n, char *zFile, int line){
   oldPi -= 2;
   if( oldPi[0]!=0xdead1122 ){
     fprintf(stderr,"Low-end memory corruption in realloc at 0x%x\n", (int)p);
-    return;
+    return 0;
   }
   oldN = oldPi[1];
   oldK = (oldN+sizeof(int)-1)/sizeof(int);
   if( oldPi[oldK+2]!=0xdead3344 ){
     fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n", (int)p);
-    return;
+    return 0;
   }
   k = (n + sizeof(int) - 1)/sizeof(int);
   pi = malloc( (k+3)*sizeof(int) );
index 53a4e01921ef92bba8b92df1789319b757c3ac0b..d302a031b62003f92e9d5e21eaf61cb18a371566 100644 (file)
 ** But other routines are also provided to help in building up
 ** a program instruction by instruction.
 **
-** $Id: vdbe.c,v 1.14 2000/06/05 02:07:04 drh Exp $
+** $Id: vdbe.c,v 1.15 2000/06/05 16:01:39 drh Exp $
 */
 #include "sqliteInt.h"
+#include <unistd.h>
 
 /*
 ** SQL is translated into a sequence of instructions to be
@@ -741,7 +742,6 @@ int sqliteVdbeExec(
       */
       case OP_Null: {
         int i = ++p->tos;
-        char *z;
         if( NeedStack(p, p->tos) ) goto no_mem;
         p->zStack[i] = 0;
         p->aStack[i].flags = STK_Null;