Merge the nested aggregate query fix (ticket [c2ad16f997ee9c8ed]) unto trunk.
FossilOrigin-Name: e459c3360ba2543e52b5736d7a84f1ce67388d5c
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
C Make\ssure\slookaside\smemory\sallocations\sare\sunusable\safter\sthey\sare\sfreed.
|
||||
D 2012-05-21T16:59:16.604
|
||||
C Merge\sthe\snested\saggregate\squery\sfix\s(ticket\s[c2ad16f997ee9c8ed])\sunto\strunk.
|
||||
D 2012-05-21T21:26:17.383
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -121,13 +121,13 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c df800f10896bc2ddaa1125c532d6e7a7b9efc532
|
||||
F src/btree.h 48a013f8964f12d944d90e4700df47b72dd6d923
|
||||
F src/btreeInt.h 38a639c0542c29fe8331a221c4aed0cb8686249e
|
||||
F src/build.c 95fd8aa1bf81acf15e9ef46b07d1f70111ea88d0
|
||||
F src/build.c 2bb2163bb1e69f59e9f36a9413079ead42fa1d2c
|
||||
F src/callback.c 0cb4228cdcd827dcc5def98fb099edcc9142dbcd
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33
|
||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/delete.c 4c20ea4f6213b3bc1c6a510586864b679946e05e
|
||||
F src/expr.c eefabaa4a3dc67309a754eb0eab1a163ff4c2bf3
|
||||
F src/expr.c 06a7733d19dc725dc46ba51afd9feadb4b85d991
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
|
||||
F src/func.c c6b3c94320253a35bda43fb69cc292618e3285d6
|
||||
@@ -171,13 +171,13 @@ F src/pragma.c e708b3bb5704605816f617e0b1d63a5488060715
|
||||
F src/prepare.c 9a00a9612ebf80203fbb41f8a29ab8cb27a05f40
|
||||
F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c 748e75299faff345f34f0e5bd02a2bac8aa69fcd
|
||||
F src/resolve.c b3c70ab28cac60de33684c9aa9e5138dcf71d6dd
|
||||
F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1
|
||||
F src/select.c d7b9018b7dd2e821183d69477ab55c39b8272335
|
||||
F src/select.c f6c4833c4d8e94714761d99013d74f381e084f1d
|
||||
F src/shell.c c16f72e34f611f060546709564c121a67cb2b31b
|
||||
F src/sqlite.h.in 4f4d4792f6fb00387c877af013cb09d955643f12
|
||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||
F src/sqliteInt.h c5e917c4f1453f3972b1fd0c81105dfe4f09cc32
|
||||
F src/sqliteInt.h 97ccae71ae0a4e924dcb9fab14eb4fc4839790da
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@@ -499,6 +499,7 @@ F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/func.test 9809b7622d721904a8cc33c1ffb87f46d506ed01
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
|
||||
F test/fuzz-oss1.test b108e46744d80e0574c69fc5774eab0c0b61950d
|
||||
F test/fuzz.test 77fd50afc12847af50fcf1941679d90adebadde6
|
||||
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
|
||||
F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
|
||||
@@ -712,7 +713,7 @@ F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
|
||||
F test/stat.test 08e8185b3fd5b010c90d7ad82b9dd4ea1cbf14b0
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
F test/subquery.test c5e0d183f1ae6251453338a465b32ae11326e0fa
|
||||
F test/subquery.test d4aea23ac267463d4aa604bf937c3992347b20f7
|
||||
F test/subquery2.test edcad5c118f0531c2e21bf16a09bbb105252d4cd
|
||||
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
|
||||
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||
@@ -997,7 +998,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
P fda1ea0bee0fe283e0ed5710058fdfc403519bac
|
||||
R 6e4bfedf4c57499c35337d815d50cfb9
|
||||
P 3869aef6348018f584137f36f6924193a790e52f bdc01fd0fa0c15efbb32bf18527c71e3e4dc48ed
|
||||
R 15d4dbbc25fb6a4a0d7e19b673fed210
|
||||
U drh
|
||||
Z bde27247c00eb88661bdbd820aaab779
|
||||
Z 861d1d99d6fb7da6ba53d2868b8d367e
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3869aef6348018f584137f36f6924193a790e52f
|
||||
e459c3360ba2543e52b5736d7a84f1ce67388d5c
|
||||
+1
-1
@@ -1507,7 +1507,7 @@ void sqlite3EndTable(
|
||||
sSrc.a[0].iCursor = -1;
|
||||
sNC.pParse = pParse;
|
||||
sNC.pSrcList = &sSrc;
|
||||
sNC.isCheck = 1;
|
||||
sNC.ncFlags = NC_IsCheck;
|
||||
pList = p->pCheck;
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
|
||||
|
||||
+5
-3
@@ -3778,7 +3778,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
|
||||
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
|
||||
return 2;
|
||||
}
|
||||
}else if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
|
||||
}else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
|
||||
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
|
||||
if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
|
||||
return 2;
|
||||
@@ -3965,7 +3965,9 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
return WRC_Prune;
|
||||
}
|
||||
case TK_AGG_FUNCTION: {
|
||||
if( !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList) ){
|
||||
if( (pNC->ncFlags & NC_InAggFunc)==0
|
||||
&& !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList)
|
||||
){
|
||||
/* Check to see if pExpr is a duplicate of another aggregate
|
||||
** function that is already in the pAggInfo structure
|
||||
*/
|
||||
@@ -4002,8 +4004,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
ExprSetIrreducible(pExpr);
|
||||
pExpr->iAgg = (i16)i;
|
||||
pExpr->pAggInfo = pAggInfo;
|
||||
return WRC_Prune;
|
||||
}
|
||||
return WRC_Prune;
|
||||
}
|
||||
}
|
||||
return WRC_Continue;
|
||||
|
||||
+18
-18
@@ -311,7 +311,7 @@ static int lookupName(
|
||||
assert( pExpr->x.pList==0 );
|
||||
assert( pExpr->x.pSelect==0 );
|
||||
pOrig = pEList->a[j].pExpr;
|
||||
if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
|
||||
if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
|
||||
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
|
||||
return WRC_Abort;
|
||||
}
|
||||
@@ -556,7 +556,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( is_agg && !pNC->allowAgg ){
|
||||
if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
|
||||
pNC->nErr++;
|
||||
is_agg = 0;
|
||||
@@ -570,11 +570,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
if( is_agg ){
|
||||
pExpr->op = TK_AGG_FUNCTION;
|
||||
pNC->hasAgg = 1;
|
||||
pNC->ncFlags |= NC_HasAgg;
|
||||
}
|
||||
if( is_agg ) pNC->allowAgg = 0;
|
||||
if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
|
||||
sqlite3WalkExprList(pWalker, pList);
|
||||
if( is_agg ) pNC->allowAgg = 1;
|
||||
if( is_agg ) pNC->ncFlags |= NC_AllowAgg;
|
||||
/* FIX ME: Compute pExpr->affinity based on the expected return
|
||||
** type of the function
|
||||
*/
|
||||
@@ -589,7 +589,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
int nRef = pNC->nRef;
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
if( pNC->isCheck ){
|
||||
if( (pNC->ncFlags & NC_IsCheck)!=0 ){
|
||||
sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
|
||||
}
|
||||
#endif
|
||||
@@ -603,7 +603,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
#ifndef SQLITE_OMIT_CHECK
|
||||
case TK_VARIABLE: {
|
||||
if( pNC->isCheck ){
|
||||
if( (pNC->ncFlags & NC_IsCheck)!=0 ){
|
||||
sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
|
||||
}
|
||||
break;
|
||||
@@ -685,7 +685,7 @@ static int resolveOrderByTermToExprList(
|
||||
nc.pParse = pParse;
|
||||
nc.pSrcList = pSelect->pSrc;
|
||||
nc.pEList = pEList;
|
||||
nc.allowAgg = 1;
|
||||
nc.ncFlags = NC_AllowAgg;
|
||||
nc.nErr = 0;
|
||||
db = pParse->db;
|
||||
savedSuppErr = db->suppressErr;
|
||||
@@ -987,7 +987,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
|
||||
** resolve the result-set expression list.
|
||||
*/
|
||||
sNC.allowAgg = 1;
|
||||
sNC.ncFlags = NC_AllowAgg;
|
||||
sNC.pSrcList = p->pSrc;
|
||||
sNC.pNext = pOuterNC;
|
||||
|
||||
@@ -1033,10 +1033,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
*/
|
||||
assert( (p->selFlags & SF_Aggregate)==0 );
|
||||
pGroupBy = p->pGroupBy;
|
||||
if( pGroupBy || sNC.hasAgg ){
|
||||
if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
|
||||
p->selFlags |= SF_Aggregate;
|
||||
}else{
|
||||
sNC.allowAgg = 0;
|
||||
sNC.ncFlags &= ~NC_AllowAgg;
|
||||
}
|
||||
|
||||
/* If a HAVING clause is present, then there must be a GROUP BY clause.
|
||||
@@ -1065,7 +1065,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
** outer queries
|
||||
*/
|
||||
sNC.pNext = 0;
|
||||
sNC.allowAgg = 1;
|
||||
sNC.ncFlags |= NC_AllowAgg;
|
||||
|
||||
/* Process the ORDER BY clause for singleton SELECT statements.
|
||||
** The ORDER BY clause for compounds SELECT statements is handled
|
||||
@@ -1153,7 +1153,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
**
|
||||
** Function calls are checked to make sure that the function is
|
||||
** defined and that the correct number of arguments are specified.
|
||||
** If the function is an aggregate function, then the pNC->hasAgg is
|
||||
** If the function is an aggregate function, then the NC_HasAgg flag is
|
||||
** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
|
||||
** If an expression contains aggregate functions then the EP_Agg
|
||||
** property on the expression is set.
|
||||
@@ -1165,7 +1165,7 @@ int sqlite3ResolveExprNames(
|
||||
NameContext *pNC, /* Namespace to resolve expressions in. */
|
||||
Expr *pExpr /* The expression to be analyzed. */
|
||||
){
|
||||
int savedHasAgg;
|
||||
u8 savedHasAgg;
|
||||
Walker w;
|
||||
|
||||
if( pExpr==0 ) return 0;
|
||||
@@ -1178,8 +1178,8 @@ int sqlite3ResolveExprNames(
|
||||
pParse->nHeight += pExpr->nHeight;
|
||||
}
|
||||
#endif
|
||||
savedHasAgg = pNC->hasAgg;
|
||||
pNC->hasAgg = 0;
|
||||
savedHasAgg = pNC->ncFlags & NC_HasAgg;
|
||||
pNC->ncFlags &= ~NC_HasAgg;
|
||||
w.xExprCallback = resolveExprStep;
|
||||
w.xSelectCallback = resolveSelectStep;
|
||||
w.pParse = pNC->pParse;
|
||||
@@ -1191,10 +1191,10 @@ int sqlite3ResolveExprNames(
|
||||
if( pNC->nErr>0 || w.pParse->nErr>0 ){
|
||||
ExprSetProperty(pExpr, EP_Error);
|
||||
}
|
||||
if( pNC->hasAgg ){
|
||||
if( pNC->ncFlags & NC_HasAgg ){
|
||||
ExprSetProperty(pExpr, EP_Agg);
|
||||
}else if( savedHasAgg ){
|
||||
pNC->hasAgg = 1;
|
||||
pNC->ncFlags |= NC_HasAgg;
|
||||
}
|
||||
return ExprHasProperty(pExpr, EP_Error);
|
||||
}
|
||||
|
||||
@@ -3149,6 +3149,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
|
||||
|
||||
if( IsVirtual(pTab) ) return 0;
|
||||
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
|
||||
if( pAggInfo->nFunc==0 ) return 0;
|
||||
if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0;
|
||||
if( pExpr->flags&EP_Distinct ) return 0;
|
||||
|
||||
@@ -4139,7 +4140,9 @@ int sqlite3Select(
|
||||
sAggInfo.nAccumulator = sAggInfo.nColumn;
|
||||
for(i=0; i<sAggInfo.nFunc; i++){
|
||||
assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
|
||||
sNC.ncFlags |= NC_InAggFunc;
|
||||
sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
|
||||
sNC.ncFlags &= ~NC_InAggFunc;
|
||||
}
|
||||
if( db->mallocFailed ) goto select_end;
|
||||
|
||||
|
||||
+11
-5
@@ -2006,15 +2006,21 @@ struct NameContext {
|
||||
Parse *pParse; /* The parser */
|
||||
SrcList *pSrcList; /* One or more tables used to resolve names */
|
||||
ExprList *pEList; /* Optional list of named expressions */
|
||||
int nRef; /* Number of names resolved by this context */
|
||||
int nErr; /* Number of errors encountered while resolving names */
|
||||
u8 allowAgg; /* Aggregate functions allowed here */
|
||||
u8 hasAgg; /* True if aggregates are seen */
|
||||
u8 isCheck; /* True if resolving names in a CHECK constraint */
|
||||
AggInfo *pAggInfo; /* Information about aggregates at this level */
|
||||
NameContext *pNext; /* Next outer name context. NULL for outermost */
|
||||
int nRef; /* Number of names resolved by this context */
|
||||
int nErr; /* Number of errors encountered while resolving names */
|
||||
u8 ncFlags; /* Zero or more NC_* flags defined below */
|
||||
};
|
||||
|
||||
/*
|
||||
** Allowed values for the NameContext, ncFlags field.
|
||||
*/
|
||||
#define NC_AllowAgg 0x01 /* Aggregate functions are allowed here */
|
||||
#define NC_HasAgg 0x02 /* One or more aggregate functions seen */
|
||||
#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */
|
||||
#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */
|
||||
|
||||
/*
|
||||
** An instance of the following structure contains all information
|
||||
** needed to generate code for a single SELECT statement.
|
||||
|
||||
+1993
File diff suppressed because it is too large
Load Diff
@@ -377,6 +377,44 @@ do_test subquery-3.4.3 {
|
||||
}
|
||||
} {106 4.5 0 1 107 4.0 1 0}
|
||||
|
||||
do_test subquery-3.5.1 {
|
||||
execsql {
|
||||
CREATE TABLE t35a(x); INSERT INTO t35a VALUES(1),(2),(3);
|
||||
CREATE TABLE t35b(y); INSERT INTO t35b VALUES(98), (99);
|
||||
SELECT max((SELECT avg(y) FROM t35b)) FROM t35a;
|
||||
}
|
||||
} {98.5}
|
||||
do_test subquery-3.5.2 {
|
||||
execsql {
|
||||
SELECT max((SELECT count(y) FROM t35b)) FROM t35a;
|
||||
}
|
||||
} {2}
|
||||
do_test subquery-3.5.3 {
|
||||
execsql {
|
||||
SELECT max((SELECT count() FROM t35b)) FROM t35a;
|
||||
}
|
||||
} {2}
|
||||
do_test subquery-3.5.4 {
|
||||
catchsql {
|
||||
SELECT max((SELECT count(x) FROM t35b)) FROM t35a;
|
||||
}
|
||||
} {1 {misuse of aggregate: count()}}
|
||||
do_test subquery-3.5.5 {
|
||||
catchsql {
|
||||
SELECT max((SELECT count(x) FROM t35b)) FROM t35a;
|
||||
}
|
||||
} {1 {misuse of aggregate: count()}}
|
||||
do_test subquery-3.5.6 {
|
||||
catchsql {
|
||||
SELECT max((SELECT a FROM (SELECT count(x) AS a FROM t35b))) FROM t35a;
|
||||
}
|
||||
} {1 {misuse of aggregate: count()}}
|
||||
do_test subquery-3.5.7 {
|
||||
execsql {
|
||||
SELECT max((SELECT a FROM (SELECT count(y) AS a FROM t35b))) FROM t35a;
|
||||
}
|
||||
} {2}
|
||||
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# These tests - subquery-4.* - use the TCL statement cache to try
|
||||
|
||||
Reference in New Issue
Block a user