mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Do not flatten sub-queries that contain window functions.
FossilOrigin-Name: 236cb75bd1f0d5eb86aa5f52d8d548e7263c34633833dcea9dfc934f142113b8
This commit is contained in:
20
src/expr.c
20
src/expr.c
@@ -1182,24 +1182,6 @@ static int dupedExprSize(Expr *p, int flags){
|
||||
return nByte;
|
||||
}
|
||||
|
||||
static Window *winDup(sqlite3 *db, Window *p){
|
||||
Window *pNew = 0;
|
||||
if( p ){
|
||||
pNew = sqlite3DbMallocZero(db, sizeof(Window));
|
||||
if( pNew ){
|
||||
pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
|
||||
pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
|
||||
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
|
||||
pNew->eType = p->eType;
|
||||
pNew->eEnd = p->eEnd;
|
||||
pNew->eStart = p->eStart;
|
||||
pNew->pStart = sqlite3ExprDup(db, pNew->pStart, 0);
|
||||
pNew->pEnd = sqlite3ExprDup(db, pNew->pEnd, 0);
|
||||
}
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is similar to sqlite3ExprDup(), except that if pzBuffer
|
||||
** is not NULL then *pzBuffer is assumed to point to a buffer large enough
|
||||
@@ -1289,7 +1271,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
|
||||
pNew->pWin = 0;
|
||||
}else{
|
||||
pNew->pWin = winDup(db, p->pWin);
|
||||
pNew->pWin = sqlite3WindowDup(db, p->pWin);
|
||||
}
|
||||
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
|
||||
if( pNew->op==TK_SELECT_COLUMN ){
|
||||
|
||||
22
src/select.c
22
src/select.c
@@ -3712,7 +3712,7 @@ static int flattenSubquery(
|
||||
pSub = pSubitem->pSelect;
|
||||
assert( pSub!=0 );
|
||||
|
||||
if( p->pWin ) return 0;
|
||||
if( p->pWin || pSub->pWin ) return 0;
|
||||
|
||||
pSubSrc = pSub->pSrc;
|
||||
assert( pSubSrc );
|
||||
@@ -5898,26 +5898,18 @@ int sqlite3Select(
|
||||
assert( p->pEList==pEList );
|
||||
if( pWin ){
|
||||
int addrGosub = sqlite3VdbeMakeLabel(v);
|
||||
int iCont = sqlite3VdbeMakeLabel(v);
|
||||
int regGosub = ++pParse->nMem;
|
||||
int addr = 0;
|
||||
int bLoop = 0;
|
||||
|
||||
sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub, &bLoop);
|
||||
sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub);
|
||||
|
||||
sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
addr = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
sqlite3VdbeResolveLabel(v, addrGosub);
|
||||
if( bLoop ){
|
||||
addr = sqlite3VdbeAddOp1(v, OP_Rewind, pWin->iEphCsr);
|
||||
}else{
|
||||
addr = sqlite3VdbeCurrentAddr(v);
|
||||
}
|
||||
selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, addr+1, 0);
|
||||
if( bLoop ){
|
||||
sqlite3VdbeAddOp2(v, OP_Next, pWin->iEphCsr, addr+1);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, 0);
|
||||
sqlite3VdbeResolveLabel(v, iCont);
|
||||
sqlite3VdbeAddOp1(v, OP_Return, regGosub);
|
||||
sqlite3VdbeJumpHere(v, addr-1); /* OP_Goto jumps here */
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
|
||||
}else{
|
||||
/* Use the standard inner loop. */
|
||||
|
||||
@@ -3502,10 +3502,11 @@ Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*);
|
||||
void sqlite3WindowAttach(Parse*, Expr*, Window*);
|
||||
int sqlite3WindowCompare(Parse*, Window*, Window*);
|
||||
void sqlite3WindowCodeInit(Parse*, Window*);
|
||||
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int, int*);
|
||||
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
|
||||
int sqlite3WindowRewrite(Parse*, Select*);
|
||||
int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
|
||||
void sqlite3WindowUpdate(Parse*, Window*, FuncDef*);
|
||||
Window *sqlite3WindowDup(sqlite3 *db, Window *p);
|
||||
|
||||
/*
|
||||
** Assuming zIn points to the first byte of a UTF-8 character,
|
||||
|
||||
27
src/window.c
27
src/window.c
@@ -1560,7 +1560,10 @@ static void windowCodeDefaultStep(
|
||||
if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto);
|
||||
}
|
||||
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3);
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1);
|
||||
|
||||
sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
|
||||
sqlite3VdbeAddOp3(
|
||||
v, OP_Copy, reg+pMWin->nBufferCol, pMWin->regPart, nPart+nPeer-1
|
||||
@@ -1586,9 +1589,28 @@ static void windowCodeDefaultStep(
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
|
||||
windowAggFinal(pParse, pMWin, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3);
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1);
|
||||
}
|
||||
|
||||
Window *sqlite3WindowDup(sqlite3 *db, Window *p){
|
||||
Window *pNew = 0;
|
||||
if( p ){
|
||||
pNew = sqlite3DbMallocZero(db, sizeof(Window));
|
||||
if( pNew ){
|
||||
pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
|
||||
pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
|
||||
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
|
||||
pNew->eType = p->eType;
|
||||
pNew->eEnd = p->eEnd;
|
||||
pNew->eStart = p->eStart;
|
||||
pNew->pStart = sqlite3ExprDup(db, pNew->pStart, 0);
|
||||
pNew->pEnd = sqlite3ExprDup(db, pNew->pEnd, 0);
|
||||
}
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/*
|
||||
** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||
@@ -1649,13 +1671,11 @@ void sqlite3WindowCodeStep(
|
||||
Select *p,
|
||||
WhereInfo *pWInfo,
|
||||
int regGosub,
|
||||
int addrGosub,
|
||||
int *pbLoop
|
||||
int addrGosub
|
||||
){
|
||||
Window *pMWin = p->pWin;
|
||||
Window *pWin;
|
||||
|
||||
*pbLoop = 0;
|
||||
if( (pMWin->eType==TK_ROWS
|
||||
&& (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy))
|
||||
|| (pMWin->eStart==TK_CURRENT&&pMWin->eEnd==TK_UNBOUNDED&&pMWin->pOrderBy)
|
||||
@@ -1677,7 +1697,6 @@ void sqlite3WindowCodeStep(
|
||||
}
|
||||
}
|
||||
|
||||
*pbLoop = 1;
|
||||
windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user