diff --git a/manifest b/manifest index 8a1bf2f3ae..80d06c90ce 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s(highly\sexperimental)\somit_readlock\spragma\sthat\sdisables\sthe\suse\r\nof\sreadlocks\son\sread-only\sdatabases\sthat\sare\sconnected\susing\sATTACH.\s(CVS\s2317) -D 2005-02-06T02:45:42 +C Fix\sfor\scorrelated\ssubqueries\swhere\sthe\sparent\sis\san\saggregate.\sTicket\s#1105.\s(CVS\s2318) +D 2005-02-08T07:50:41 F Makefile.in d928187101fa3d78426cf48ca30e39d0fb714e57 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -35,7 +35,7 @@ F src/build.c fcb437bcda09a57b3fe898dff5ff558e7536621b F src/date.c f3d1f5cd1503dabf426a198f3ebef5afbc122a7f F src/delete.c 4b94395b52a8f7785acd71135c2ce54f3f5550b3 F src/experimental.c 8cc66b2be6a011055d75ef19ed2584bcfbb585ad -F src/expr.c 1b6b6b16bcb6a6dcc4a5df451d9e652f84b269ae +F src/expr.c b9ffd249cef8cd0f2d3681da8daf9a4292dcd005 F src/func.c f096b6771cc0aaa11790aca95773a50a8f74ba73 F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 @@ -57,10 +57,10 @@ F src/parse.y ee046c1ea30425a817285e52fb1993c2f955e766 F src/pragma.c 809b95acd9af67297a5f923a1a57d82179e0ad3a F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 -F src/select.c 6217e1f72cee7e173b21b252fd42a052f3b4decc +F src/select.c 37dd84fd228db14e9006e3eafb389f08d823502f F src/shell.c 3cb0ef124ed9cd582ce89aec59ff7c659bc6e61b F src/sqlite.h.in c85f6bad9ca7de29f505fe886646cfff7df4c55e -F src/sqliteInt.h 5fa59fd8369ec403bbdf35a9b6fbf7f60bd77cdb +F src/sqliteInt.h 9a53c5b5c591526e22b89deed38467cb8875b121 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/tclsqlite.c 101994a2c4c0eaa69f1de9bfe4a02167f6049e7d F src/test1.c feac8a742aca920c8ab18a43b3208ae3a834fe9d @@ -74,7 +74,7 @@ F src/update.c b6f4668c11059f86b71581187d09197fa28ec4be F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c F src/util.c 1b7b9a127b66743ab6cba8d44597aeb570723c99 F src/vacuum.c 4dbe45a5c41674a04ac45a7586031583386ab119 -F src/vdbe.c 5acf43749f44b0813d47f4b1801538f4aaa7ddbb +F src/vdbe.c d9ec62c9f63768b4d4f8513b25aded8faf2de17b F src/vdbe.h bb9186484f749a839c6c43953e79a6530253f7cd F src/vdbeInt.h e80721cd8ff611789e20743eec43363a9fb5a48e F src/vdbeapi.c 467caa6e6fb9247528b1c7ab9132ae1b4748e8ac @@ -181,7 +181,7 @@ F test/select5.test 2d414f712bff8e590091e08f9b7287600731be00 F test/select6.test 6e5a1a70a788cdbe515d1252dd0917d7e9d1d71e F test/select7.test 8f3362336c10d828ab6fe9c1b8897b484da8b592 F test/sort.test 312eade533cb3c7667110ccfa6e818db1078fd6c -F test/subquery.test e607b55276d2536e17e75896cd245ec1c8838f1d +F test/subquery.test 958bf1752c6b1c5c0b45b243fc74899f2037821e F test/subselect.test 3f3f7a940dc3195c3139f4d530385cb54665d614 F test/table.test a2a58cae70ef2511cbf27d40fb8f570106a2677e F test/tableapi.test 6a66d58b37d46dc0f2b3c7d4bd2617d209399bd1 @@ -270,7 +270,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl 3e522a06ad41992023c80ca29a048ae2331ca5bd -P 515e5033a5482f55e7edb66d69ff3da7e234ff2e -R 46e8e0ae6e4ce5a599c5b024b5c2e241 -U drh -Z dd83c9ab3e3ce7d0c16a2d058d1f0afb +P 2155448d2128119f74241da0ea07d6713b71765c +R 606c27806bb193ef40535820164d7cb2 +U danielk1977 +Z ab8a5b2917edd9042037cd2b7cc41ebd diff --git a/manifest.uuid b/manifest.uuid index 909087ae42..1a449e3950 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2155448d2128119f74241da0ea07d6713b71765c \ No newline at end of file +f0d3ca10c5bccf8fca7143028ebb3e604c0e3f20 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index e282833281..487c5395f5 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.192 2005/02/05 12:48:48 danielk1977 Exp $ +** $Id: expr.c,v 1.193 2005/02/08 07:50:41 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -189,6 +189,7 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){ pNew->op = op; pNew->pLeft = pLeft; pNew->pRight = pRight; + pNew->iAgg = -1; if( pToken ){ assert( pToken->dyn==0 ); pNew->span = pNew->token = *pToken; @@ -589,26 +590,47 @@ void sqlite3ExprListDelete(ExprList *pList){ ** The return value from this routine is 1 to abandon the tree walk ** and 0 to continue. */ +static int walkExprList(ExprList *, int (*)(void *, Expr*), void *); static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){ - ExprList *pList; int rc; if( pExpr==0 ) return 0; rc = (*xFunc)(pArg, pExpr); if( rc==0 ){ if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1; if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1; - pList = pExpr->pList; - if( pList ){ - int i; - struct ExprList_item *pItem; - for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ - if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1; - } - } + if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1; } return rc>1; } +/* +** Call walkExprTree() for every expression in list p. +*/ +static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){ + int i; + struct ExprList_item *pItem; + if( !p ) return 0; + for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){ + if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1; + } + return 0; +} + +/* +** Call walkExprTree() for every expression in Select p, not including +** expressions that are part of sub-selects in any FROM clause or the LIMIT +** or OFFSET expressions.. +*/ +static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){ + walkExprList(p->pEList, xFunc, pArg); + walkExprTree(p->pWhere, xFunc, pArg); + walkExprList(p->pGroupBy, xFunc, pArg); + walkExprTree(p->pHaving, xFunc, pArg); + walkExprList(p->pOrderBy, xFunc, pArg); + return 0; +} + + /* ** This routine is designed as an xFunc for walkExprTree(). ** @@ -1356,8 +1378,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ op = pExpr->op; switch( op ){ case TK_COLUMN: { - if( pParse->useAgg ){ - sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); + if( !pParse->fillAgg && pExpr->iAgg>=0 ){ + sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg); }else if( pExpr->iColumn>=0 ){ sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); #ifndef NDEBUG @@ -1968,49 +1990,64 @@ static int appendAggInfo(Parse *pParse){ static int analyzeAggregate(void *pArg, Expr *pExpr){ int i; AggExpr *aAgg; - Parse *pParse = (Parse*)pArg; + NameContext *pNC = (NameContext *)pArg; + Parse *pParse = pNC->pParse; + SrcList *pSrcList = pNC->pSrcList; switch( pExpr->op ){ case TK_COLUMN: { - aAgg = pParse->aAgg; - for(i=0; inAgg; i++){ - if( aAgg[i].isAgg ) continue; - if( aAgg[i].pExpr->iTable==pExpr->iTable - && aAgg[i].pExpr->iColumn==pExpr->iColumn ){ - break; + for(i=0; pSrcList && inSrc; i++){ + if( pExpr->iTable==pSrcList->a[i].iCursor ){ + aAgg = pParse->aAgg; + for(i=0; inAgg; i++){ + if( aAgg[i].isAgg ) continue; + if( aAgg[i].pExpr->iTable==pExpr->iTable + && aAgg[i].pExpr->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; + } + pExpr->iAgg = i; + pExpr->iAggCtx = pNC->nDepth; + return 1; } } - if( i>=pParse->nAgg ){ - i = appendAggInfo(pParse); - if( i<0 ) return 1; - pParse->aAgg[i].isAgg = 0; - pParse->aAgg[i].pExpr = pExpr; - } - pExpr->iAgg = i; return 1; } case TK_AGG_FUNCTION: { - aAgg = pParse->aAgg; - for(i=0; inAgg; i++){ - if( !aAgg[i].isAgg ) continue; - if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){ - break; + if( pNC->nDepth==0 ){ + aAgg = pParse->aAgg; + for(i=0; inAgg; i++){ + if( !aAgg[i].isAgg ) continue; + if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){ + break; + } } + if( i>=pParse->nAgg ){ + 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, + pExpr->token.z, pExpr->token.n, + pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); + } + pExpr->iAgg = i; + return 1; } - if( i>=pParse->nAgg ){ - 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, - pExpr->token.z, pExpr->token.n, - pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); - } - pExpr->iAgg = i; - return 1; } } + if( pExpr->pSelect ){ + pNC->nDepth++; + walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC); + pNC->nDepth--; + } return 0; } @@ -2025,10 +2062,10 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){ ** If errors are seen, leave an error message in zErrMsg and return ** the number of errors. */ -int sqlite3ExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){ - int nErr = pParse->nErr; - walkExprTree(pExpr, analyzeAggregate, pParse); - return pParse->nErr - nErr; +int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ + int nErr = pNC->pParse->nErr; + walkExprTree(pExpr, analyzeAggregate, pNC); + return pNC->pParse->nErr - nErr; } /* diff --git a/src/select.c b/src/select.c index 8bf0f1b95f..d9c79df48a 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.239 2005/02/05 12:48:48 danielk1977 Exp $ +** $Id: select.c,v 1.240 2005/02/08 07:50:41 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -1241,6 +1241,7 @@ static int matchOrderbyToColumn( pE->op = TK_COLUMN; pE->iColumn = iCol; pE->iTable = iTable; + pE->iAgg = -1; pOrderBy->a[i].done = 1; } if( iCol<0 && mustComplete ){ @@ -2095,6 +2096,9 @@ static int flattenSubquery( */ p->isDistinct = p->isDistinct || pSub->isDistinct; + /* + ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; + */ if( pSub->pLimit ){ p->pLimit = pSub->pLimit; pSub->pLimit = 0; @@ -2412,7 +2416,6 @@ int sqlite3SelectResolve( ** saveAggregateInfo() and restoreAggregateInfo(). */ struct AggregateInfo { - u8 useAgg; int nAgg; AggExpr *aAgg; }; @@ -2426,10 +2429,8 @@ typedef struct AggregateInfo AggregateInfo; static void saveAggregateInfo(Parse *pParse, AggregateInfo *pInfo){ pInfo->aAgg = pParse->aAgg; pInfo->nAgg = pParse->nAgg; - pInfo->useAgg = pParse->useAgg; pParse->aAgg = 0; pParse->nAgg = 0; - pParse->useAgg = 0; } /* @@ -2441,7 +2442,6 @@ static void restoreAggregateInfo(Parse *pParse, AggregateInfo *pInfo){ sqliteFree(pParse->aAgg); pParse->aAgg = pInfo->aAgg; pParse->nAgg = pInfo->nAgg; - pParse->useAgg = pInfo->useAgg; } /* @@ -2674,26 +2674,31 @@ int sqlite3Select( /* Do an analysis of aggregate expressions. */ if( isAgg || pGroupBy ){ + NameContext sNC; + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; + assert( pParse->nAgg==0 ); isAgg = 1; for(i=0; inExpr; i++){ - if( sqlite3ExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){ + if( sqlite3ExprAnalyzeAggregates(&sNC, pEList->a[i].pExpr) ){ goto select_end; } } if( pGroupBy ){ for(i=0; inExpr; i++){ - if( sqlite3ExprAnalyzeAggregates(pParse, pGroupBy->a[i].pExpr) ){ + if( sqlite3ExprAnalyzeAggregates(&sNC, pGroupBy->a[i].pExpr) ){ goto select_end; } } } - if( pHaving && sqlite3ExprAnalyzeAggregates(pParse, pHaving) ){ + if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){ goto select_end; } if( pOrderBy ){ for(i=0; inExpr; i++){ - if( sqlite3ExprAnalyzeAggregates(pParse, pOrderBy->a[i].pExpr) ){ + if( sqlite3ExprAnalyzeAggregates(&sNC, pOrderBy->a[i].pExpr) ){ goto select_end; } } @@ -2765,8 +2770,9 @@ int sqlite3Select( */ else{ AggExpr *pAgg; + int lbl1 = 0; + pParse->fillAgg = 1; if( pGroupBy ){ - int lbl1; for(i=0; inExpr; i++){ sqlite3ExprCode(pParse, pGroupBy->a[i].pExpr); } @@ -2775,11 +2781,14 @@ int sqlite3Select( sqlite3VdbeAddOp(v, OP_MakeRecord, pGroupBy->nExpr, 0); lbl1 = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_AggFocus, 0, lbl1); - for(i=0, pAgg=pParse->aAgg; inAgg; i++, pAgg++){ - if( pAgg->isAgg ) continue; - sqlite3ExprCode(pParse, pAgg->pExpr); - sqlite3VdbeAddOp(v, OP_AggSet, 0, i); - } + } + for(i=0, pAgg=pParse->aAgg; inAgg; i++, pAgg++){ + if( pAgg->isAgg ) continue; + sqlite3ExprCode(pParse, pAgg->pExpr); + sqlite3VdbeAddOp(v, OP_AggSet, 0, i); + } + pParse->fillAgg = 0; + if( lbl1<0 ){ sqlite3VdbeResolveLabel(v, lbl1); } for(i=0, pAgg=pParse->aAgg; inAgg; i++, pAgg++){ @@ -2819,7 +2828,6 @@ int sqlite3Select( int endagg = sqlite3VdbeMakeLabel(v); int startagg; startagg = sqlite3VdbeAddOp(v, OP_AggNext, 0, endagg); - pParse->useAgg = 1; if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, startagg, 1); } @@ -2830,7 +2838,6 @@ int sqlite3Select( sqlite3VdbeAddOp(v, OP_Goto, 0, startagg); sqlite3VdbeResolveLabel(v, endagg); sqlite3VdbeAddOp(v, OP_Noop, 0, 0); - pParse->useAgg = 0; } /* If there is an ORDER BY clause, then we need to sort the results diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 627aeae65d..786a16e4b5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.368 2005/02/06 02:45:43 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.369 2005/02/08 07:50:42 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -812,8 +812,9 @@ struct Expr { Token span; /* Complete text of the expression */ int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the ** iColumn-th field of the iTable-th table. */ - int iAgg; /* When op==TK_COLUMN and pParse->useAgg==TRUE, pull + int iAgg; /* When op==TK_COLUMN and pParse->fillAgg==FALSE, pull ** result from the iAgg-th element of the aggregator */ + int iAggCtx; /* The value to pass as P1 of OP_AggGet. */ Select *pSelect; /* When the expression is a sub-select. Also the ** right side of " IN (