1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

separate Select structure (CVS 51)

FossilOrigin-Name: ce45dea902f9010a1c2c9ba3550dd789e7c15fcd
This commit is contained in:
drh
2000-06-05 16:01:39 +00:00
parent d1dedb86bf
commit 9bb61fe751
8 changed files with 163 additions and 73 deletions

View File

@@ -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

View File

@@ -1 +1 @@
1cf2873d55b471bb3e397f90dc0868dd88c440a0
ce45dea902f9010a1c2c9ba3550dd789e7c15fcd

View 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));

View 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 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).
{
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->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}

View File

@@ -24,28 +24,94 @@
** 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;
}

View 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);

View 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) );

View File

@@ -41,9 +41,10 @@
** 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;