-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
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
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
-1cf2873d55b471bb3e397f90dc0868dd88c440a0
\ No newline at end of file
+ce45dea902f9010a1c2c9ba3550dd789e7c15fcd
\ No newline at end of file
** 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"
sqlite *db = (sqlite*)pDb;
Parse sParse;
int nErr;
- char *zErrMsg = 0;
if( argc!=1 ) return 0;
memset(&sParse, 0, sizeof(sParse));
** 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}
// 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($$);}
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}
** 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.
*/
sqliteSetString(&pParse->zErrMsg, "no such table: ",
pTabList->a[i].zName, 0);
pParse->nErr++;
- goto select_cleanup;
+ return 1;
}
}
*/
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 ){
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;
}
}
}
** since only one row will be returned.
*/
if( isAgg && pOrderBy ){
- sqliteExprListDelete(pOrderBy);
pOrderBy = 0;
}
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);
}
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.
*/
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);
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;
}
*************************************************************************
** 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"
#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__)
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
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
*/
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);
** 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>
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) );
** 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
*/
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;