aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expr.c53
-rw-r--r--src/select.c32
-rw-r--r--src/sqliteInt.h4
3 files changed, 51 insertions, 38 deletions
diff --git a/src/expr.c b/src/expr.c
index 10283ef2e..3d3655d7e 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -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.221 2005/08/25 12:45:04 drh Exp $
+** $Id: expr.c,v 1.222 2005/08/30 00:54:02 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -2071,28 +2071,30 @@ static int appendAggInfo(Parse *pParse){
*/
static int analyzeAggregate(void *pArg, Expr *pExpr){
int i;
- AggExpr *aAgg;
+ AggExpr *pAgg;
NameContext *pNC = (NameContext *)pArg;
Parse *pParse = pNC->pParse;
SrcList *pSrcList = pNC->pSrcList;
+ Expr *pAggExpr;
switch( pExpr->op ){
case TK_COLUMN: {
for(i=0; pSrcList && i<pSrcList->nSrc; i++){
if( pExpr->iTable==pSrcList->a[i].iCursor ){
- aAgg = pParse->aAgg;
- for(i=0; i<pParse->nAgg; i++){
- if( aAgg[i].isAgg ) continue;
- if( aAgg[i].pExpr->iTable==pExpr->iTable
- && aAgg[i].pExpr->iColumn==pExpr->iColumn ){
+ pAgg = pParse->aAgg;
+ for(i=0; i<pParse->nAgg; i++, pAgg++){
+ if( pAgg->isAgg ) continue;
+ if( (pAggExpr = pAgg->pExpr)->iTable==pExpr->iTable
+ && pAggExpr->iColumn==pExpr->iColumn ){
break;
}
}
if( i>=pParse->nAgg ){
i = appendAggInfo(pParse);
if( i<0 ) return 1;
- pParse->aAgg[i].isAgg = 0;
- pParse->aAgg[i].pExpr = pExpr;
+ pAgg = &pParse->aAgg[i];
+ pAgg->isAgg = 0;
+ pAgg->pExpr = pExpr;
}
pExpr->iAgg = i;
pExpr->iAggCtx = pNC->nDepth;
@@ -2103,10 +2105,10 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
}
case TK_AGG_FUNCTION: {
if( pNC->nDepth==0 ){
- aAgg = pParse->aAgg;
- for(i=0; i<pParse->nAgg; i++){
- if( !aAgg[i].isAgg ) continue;
- if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){
+ pAgg = pParse->aAgg;
+ for(i=0; i<pParse->nAgg; i++, pAgg++){
+ if( !pAgg->isAgg ) continue;
+ if( sqlite3ExprCompare(pAgg->pExpr, pExpr) ){
break;
}
}
@@ -2114,9 +2116,10 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
u8 enc = pParse->db->enc;
i = appendAggInfo(pParse);
if( i<0 ) return 1;
- pParse->aAgg[i].isAgg = 1;
- pParse->aAgg[i].pExpr = pExpr;
- pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db,
+ pAgg = &pParse->aAgg[i];
+ pAgg->isAgg = 1;
+ pAgg->pExpr = pExpr;
+ pAgg->pFunc = sqlite3FindFunction(pParse->db,
pExpr->token.z, pExpr->token.n,
pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);
}
@@ -2149,3 +2152,21 @@ int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
walkExprTree(pExpr, analyzeAggregate, pNC);
return pNC->pParse->nErr - nErr;
}
+
+/*
+** Call sqlite3ExprAnalyzeAggregates() for every expression in an
+** expression list. Return the number of errors.
+**
+** If an error is found, the analysis is cut short.
+*/
+int sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
+ struct ExprList_item *pItem;
+ int i;
+ int nErr = 0;
+ if( pList ){
+ for(pItem=pList->a, i=0; nErr==0 && i<pList->nExpr; i++, pItem++){
+ nErr += sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr);
+ }
+ }
+ return nErr;
+}
diff --git a/src/select.c b/src/select.c
index 33c5f2449..bb8c06e86 100644
--- a/src/select.c
+++ b/src/select.c
@@ -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.255 2005/08/28 01:34:22 drh Exp $
+** $Id: select.c,v 1.256 2005/08/30 00:54:03 drh Exp $
*/
#include "sqliteInt.h"
@@ -2632,10 +2632,10 @@ int sqlite3Select(
** names that have been explicitly specified.
*/
if( pOrderBy ){
- for(i=0; i<pOrderBy->nExpr; i++){
- if( pOrderBy->a[i].zName ){
- pOrderBy->a[i].pExpr->pColl =
- sqlite3LocateCollSeq(pParse, pOrderBy->a[i].zName, -1);
+ struct ExprList_item *pTerm;
+ for(i=0, pTerm=pOrderBy->a; i<pOrderBy->nExpr; i++, pTerm++){
+ if( pTerm->zName ){
+ pTerm->pExpr->pColl = sqlite3LocateCollSeq(pParse, pTerm->zName, -1);
}
}
if( pParse->nErr ){
@@ -2664,27 +2664,17 @@ int sqlite3Select(
assert( pParse->nAgg==0 );
isAgg = 1;
- for(i=0; i<pEList->nExpr; i++){
- if( sqlite3ExprAnalyzeAggregates(&sNC, pEList->a[i].pExpr) ){
- goto select_end;
- }
+ if( sqlite3ExprAnalyzeAggList(&sNC, pEList) ){
+ goto select_end;
}
- if( pGroupBy ){
- for(i=0; i<pGroupBy->nExpr; i++){
- if( sqlite3ExprAnalyzeAggregates(&sNC, pGroupBy->a[i].pExpr) ){
- goto select_end;
- }
- }
+ if( sqlite3ExprAnalyzeAggList(&sNC, pGroupBy) ){
+ goto select_end;
}
if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){
goto select_end;
}
- if( pOrderBy ){
- for(i=0; i<pOrderBy->nExpr; i++){
- if( sqlite3ExprAnalyzeAggregates(&sNC, pOrderBy->a[i].pExpr) ){
- goto select_end;
- }
- }
+ if( sqlite3ExprAnalyzeAggList(&sNC, pOrderBy) ){
+ goto select_end;
}
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 8042ae047..b391eb3bf 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.405 2005/08/29 23:00:04 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.406 2005/08/30 00:54:03 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -892,6 +892,7 @@ struct ExprList {
u8 sortOrder; /* 1 for DESC or 0 for ASC */
u8 isAgg; /* True if this is an aggregate like count(*) */
u8 done; /* A flag to indicate when processing is finished */
+ u8 orderByDup[2]; /* Corresponding term in OrderBy/GroupBy clause */
} *a; /* One entry for each expression */
};
@@ -1452,6 +1453,7 @@ int sqlite3ExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
int sqlite3ExprResolveNames(NameContext *, Expr *);
int sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
+int sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
Vdbe *sqlite3GetVdbe(Parse*);
void sqlite3Randomness(int, void*);
void sqlite3RollbackAll(sqlite3*);