Further improvements to the processing of nested aggregate queries.
FossilOrigin-Name: 3c3ffa901f5ce8a523028ff15563ce3e0f55a641
This commit is contained in:
parent
2f7d5d8394
commit
030796df8d
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
||||
C Modify\sthe\sMSVC\smakefile\sto\smake\sit\seasier\sto\sselect\sthe\sheap\ssubsystem\sto\suse.
|
||||
D 2012-08-22T00:39:34.681
|
||||
C Further\simprovements\sto\sthe\sprocessing\sof\snested\saggregate\squeries.
|
||||
D 2012-08-23T16:18:10.544
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in abd5c10d21d1395f140d9e50ea999df8fa4d6376
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -132,7 +132,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 500d019da966631ad957c37705642be87524463b
|
||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/delete.c 4c20ea4f6213b3bc1c6a510586864b679946e05e
|
||||
F src/expr.c e2927abf9c69ce4ff9a931bd201946961c34819a
|
||||
F src/expr.c e03a5509b5c8f0d0b5e8210ea43addabc4a17f47
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
|
||||
F src/func.c 18dfedfb857e100b05755a1b12e88b389f957879
|
||||
@ -174,13 +174,13 @@ F src/pragma.c 97f9357f0e7e5fb46a2519f14539550aa07db49f
|
||||
F src/prepare.c 33291b83cca285718048d219c67b8298501fa3a5
|
||||
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c b3c70ab28cac60de33684c9aa9e5138dcf71d6dd
|
||||
F src/resolve.c e60d1f7ce1f1d1ae13acf1c39b4e8bfd9e243847
|
||||
F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1
|
||||
F src/select.c a365da6d7a6d7d8a10ad60ca71837ab5e9369466
|
||||
F src/select.c cd051b460e7d0c3ac42e7727eef075fb29c23769
|
||||
F src/shell.c 076e1c90d594644f36027c8ecff9a392cf2d3a06
|
||||
F src/sqlite.h.in f664797c68ced43c2ea2c541d4ec8e1e04ec68ac
|
||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||
F src/sqliteInt.h c8169801f8bbfdf5873cc6fa45cb5df720c04db4
|
||||
F src/sqliteInt.h f4748d18114510f61e6de8bac0d513dc76e8f21c
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -253,6 +253,7 @@ F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c 24c7494d8875ead994b4dfe5461340c27fd424ca
|
||||
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 6c1efa2ed9f5dd0f80035b4fe794c6a278cd1ead
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 52fc8dee494092031a556911d404ca30a749a30b
|
||||
F test/alter.test 57d96ec9b320bd07af77567034488dcb6642c748
|
||||
@ -1011,7 +1012,10 @@ F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9
|
||||
P 573770f5a66fa4d708931b30350149eb739da607
|
||||
R 37de98f91b94867b24c6cd4084658a36
|
||||
U mistachkin
|
||||
Z 9fc3bc40456dded5ffdcfb8030fc95c3
|
||||
P b1dbf490869d7fc55ce797cf80cf3bf7141d2d15
|
||||
R 6f0858104ecac7c70bd80af9dbc9e718
|
||||
T *branch * nested-agg
|
||||
T *sym-nested-agg *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z fbb7622480ad2005f08fba3df589ccf6
|
||||
|
@ -1 +1 @@
|
||||
b1dbf490869d7fc55ce797cf80cf3bf7141d2d15
|
||||
3c3ffa901f5ce8a523028ff15563ce3e0f55a641
|
65
src/expr.c
65
src/expr.c
@ -3816,22 +3816,35 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the expression callback for sqlite3FunctionUsesOtherSrc().
|
||||
**
|
||||
** Determine if an expression references any table other than one of the
|
||||
** tables in pWalker->u.pSrcList and abort if it does.
|
||||
** An instance of the following structure is used by the tree walker
|
||||
** to count references to table columns in the arguments of an
|
||||
** aggregate function, in order to implement the sqlite3FunctionUsesOtherSrc()
|
||||
** and sqlite3FunctionThisSrc() routines.
|
||||
*/
|
||||
static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){
|
||||
struct SrcCount {
|
||||
SrcList *pSrc; /* One particular FROM clause in a nested query */
|
||||
int nThis; /* Number of references to columns in pSrcList */
|
||||
int nOther; /* Number of references to columns in other FROM clauses */
|
||||
};
|
||||
|
||||
/*
|
||||
** Count the number of references to columns.
|
||||
*/
|
||||
static int exprSrcCount(Walker *pWalker, Expr *pExpr){
|
||||
if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){
|
||||
int i;
|
||||
SrcList *pSrc = pWalker->u.pSrcList;
|
||||
struct SrcCount *p = pWalker->u.pSrcCount;
|
||||
SrcList *pSrc = p->pSrc;
|
||||
for(i=0; i<pSrc->nSrc; i++){
|
||||
if( pExpr->iTable==pSrc->a[i].iCursor ) return WRC_Continue;
|
||||
if( pExpr->iTable==pSrc->a[i].iCursor ) break;
|
||||
}
|
||||
if( i<pSrc->nSrc ){
|
||||
p->nThis++;
|
||||
}else{
|
||||
p->nOther++;
|
||||
}
|
||||
return WRC_Abort;
|
||||
}else{
|
||||
return WRC_Continue;
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3842,12 +3855,36 @@ static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){
|
||||
*/
|
||||
static int sqlite3FunctionUsesOtherSrc(Expr *pExpr, SrcList *pSrcList){
|
||||
Walker w;
|
||||
struct SrcCount cnt;
|
||||
assert( pExpr->op==TK_AGG_FUNCTION );
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = exprUsesOtherSrc;
|
||||
w.u.pSrcList = pSrcList;
|
||||
if( sqlite3WalkExprList(&w, pExpr->x.pList)!=WRC_Continue ) return 1;
|
||||
return 0;
|
||||
w.xExprCallback = exprSrcCount;
|
||||
w.u.pSrcCount = &cnt;
|
||||
cnt.pSrc = pSrcList;
|
||||
cnt.nThis = 0;
|
||||
cnt.nOther = 0;
|
||||
sqlite3WalkExprList(&w, pExpr->x.pList);
|
||||
return cnt.nOther>0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Determine if any of the arguments to the pExpr Function reference
|
||||
** pSrcList. Return true if they do. Also return true if the function
|
||||
** has no arguments or has only constant arguments. Return false if pExpr
|
||||
** references columns but not columns of tables found in pSrcList.
|
||||
*/
|
||||
int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
|
||||
Walker w;
|
||||
struct SrcCount cnt;
|
||||
assert( pExpr->op==TK_AGG_FUNCTION );
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = exprSrcCount;
|
||||
w.u.pSrcCount = &cnt;
|
||||
cnt.pSrc = pSrcList;
|
||||
cnt.nThis = 0;
|
||||
cnt.nOther = 0;
|
||||
sqlite3WalkExprList(&w, pExpr->x.pList);
|
||||
return cnt.nThis>0 || cnt.nOther==0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -568,13 +568,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
nId, zId);
|
||||
pNC->nErr++;
|
||||
}
|
||||
if( is_agg ){
|
||||
pExpr->op = TK_AGG_FUNCTION;
|
||||
pNC->ncFlags |= NC_HasAgg;
|
||||
}
|
||||
if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
|
||||
sqlite3WalkExprList(pWalker, pList);
|
||||
if( is_agg ) pNC->ncFlags |= NC_AllowAgg;
|
||||
if( is_agg ){
|
||||
NameContext *pNC2 = pNC;
|
||||
pExpr->op = TK_AGG_FUNCTION;
|
||||
pExpr->op2 = 0;
|
||||
while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
|
||||
pExpr->op2++;
|
||||
pNC2 = pNC2->pNext;
|
||||
}
|
||||
if( pNC2 ) pNC2->ncFlags |= NC_HasAgg;
|
||||
pNC->ncFlags |= NC_AllowAgg;
|
||||
}
|
||||
/* FIX ME: Compute pExpr->affinity based on the expected return
|
||||
** type of the function
|
||||
*/
|
||||
|
@ -3521,7 +3521,7 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
|
||||
|
||||
|
||||
/*
|
||||
** This routine sets of a SELECT statement for processing. The
|
||||
** This routine sets up a SELECT statement for processing. The
|
||||
** following is accomplished:
|
||||
**
|
||||
** * VDBE Cursor numbers are assigned to all FROM-clause terms.
|
||||
@ -3553,7 +3553,8 @@ void sqlite3SelectPrep(
|
||||
**
|
||||
** The aggregate accumulator is a set of memory cells that hold
|
||||
** intermediate results while calculating an aggregate. This
|
||||
** routine simply stores NULLs in all of those memory cells.
|
||||
** routine generates code that stores NULLs in all of those memory
|
||||
** cells.
|
||||
*/
|
||||
static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
|
@ -1690,8 +1690,9 @@ struct Expr {
|
||||
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
||||
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
||||
u8 flags2; /* Second set of flags. EP2_... */
|
||||
u8 op2; /* If a TK_REGISTER, the original value of Expr.op */
|
||||
/* If TK_COLUMN, the value of p5 for OP_Column */
|
||||
u8 op2; /* TK_REGISTER: original value of Expr.op
|
||||
** TK_COLUMN: the value of p5 for OP_Column
|
||||
** TK_AGG_FUNCTION: nesting depth */
|
||||
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
||||
Table *pTab; /* Table for TK_COLUMN expressions. */
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
@ -2498,10 +2499,12 @@ struct Walker {
|
||||
int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
|
||||
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
|
||||
Parse *pParse; /* Parser context. */
|
||||
int walkerDepth; /* Number of subqueries */
|
||||
union { /* Extra data for callback */
|
||||
NameContext *pNC; /* Naming context */
|
||||
int i; /* Integer value */
|
||||
SrcList *pSrcList; /* FROM clause */
|
||||
struct SrcCount *pSrcCount; /* Counting column references */
|
||||
} u;
|
||||
};
|
||||
|
||||
@ -2835,6 +2838,7 @@ int sqlite3ExprCompare(Expr*, Expr*);
|
||||
int sqlite3ExprListCompare(ExprList*, ExprList*);
|
||||
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
|
||||
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
|
||||
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
|
||||
Vdbe *sqlite3GetVdbe(Parse*);
|
||||
void sqlite3PrngSaveState(void);
|
||||
void sqlite3PrngRestoreState(void);
|
||||
|
38
test/aggnested.test
Normal file
38
test/aggnested.test
Normal file
@ -0,0 +1,38 @@
|
||||
# 2012 August 23
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# This file implements tests for processing aggregate queries with
|
||||
# subqueries in which the subqueries hold the aggregate functions
|
||||
# or in which the subqueries are themselves aggregate queries
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_test aggnested-1.1 {
|
||||
db eval {
|
||||
CREATE TABLE t1(a1 INTEGER);
|
||||
INSERT INTO t1 VALUES(1), (2), (3);
|
||||
CREATE TABLE t2(b1 INTEGER);
|
||||
INSERT INTO t2 VALUES(4), (5);
|
||||
SELECT (SELECT group_concat(a1,'x') FROM t2) FROM t1;
|
||||
}
|
||||
} {1x2x3}
|
||||
do_test aggnested-1.2 {
|
||||
db eval {
|
||||
SELECT
|
||||
(SELECT group_concat(a1,'x') || '-' || group_concat(b1,'y') FROM t2)
|
||||
FROM t1;
|
||||
}
|
||||
} {1x2x3-4y5}
|
||||
|
||||
finish_test
|
Loading…
Reference in New Issue
Block a user