aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <dan@noemail.net>2020-01-01 20:17:15 +0000
committerdan <dan@noemail.net>2020-01-01 20:17:15 +0000
commit4ea562ee7007f184b53faa4a2bbdbfa70d0dbe9c (patch)
treed39b2c23cbcc1db8377a124eae6cbb1efa73362f /src
parentaef81674211ab2f0f93852e3e9ca3bebb7e77c0b (diff)
downloadsqlite-4ea562ee7007f184b53faa4a2bbdbfa70d0dbe9c.tar.gz
sqlite-4ea562ee7007f184b53faa4a2bbdbfa70d0dbe9c.zip
Ensure that when code for a scalar SELECT featuring window functions is generated more than once by the planner, separate ephemeral tables are opened for each instance.
FossilOrigin-Name: ce1417325273aba866767349b55d9bbfb61a08e716bebda2122918a9657ee38c
Diffstat (limited to 'src')
-rw-r--r--src/select.c2
-rw-r--r--src/sqliteInt.h2
-rw-r--r--src/window.c13
3 files changed, 10 insertions, 7 deletions
diff --git a/src/select.c b/src/select.c
index 247ccfbaa..1a23b2b26 100644
--- a/src/select.c
+++ b/src/select.c
@@ -6177,7 +6177,7 @@ int sqlite3Select(
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin = p->pWin; /* Master window object (or NULL) */
if( pWin ){
- sqlite3WindowCodeInit(pParse, pWin);
+ sqlite3WindowCodeInit(pParse, p);
}
#endif
assert( WHERE_USE_LIMIT==SF_FixedLimit );
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 8090f77cc..6eb07b7c6 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3727,7 +3727,7 @@ Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
void sqlite3WindowAttach(Parse*, Expr*, Window*);
void sqlite3WindowLink(Select *pSel, Window *pWin);
int sqlite3WindowCompare(Parse*, Window*, Window*, int);
-void sqlite3WindowCodeInit(Parse*, Window*);
+void sqlite3WindowCodeInit(Parse*, Select*);
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
int sqlite3WindowRewrite(Parse*, Select*);
int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
diff --git a/src/window.c b/src/window.c
index 15a49f442..5fb78ce35 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1033,10 +1033,6 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
p->pSrc->a[0].pTab = pTab;
pTab = pTab2;
}
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr);
- sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
- sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr);
- sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr);
}else{
sqlite3SelectDelete(db, pSub);
}
@@ -1308,10 +1304,17 @@ int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2, int bFilter){
** to begin iterating through the sub-query results. It is used to allocate
** and initialize registers and cursors used by sqlite3WindowCodeStep().
*/
-void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
+void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){
+ int nEphExpr = pSelect->pSrc->a[0].pSelect->pEList->nExpr;
+ Window *pMWin = pSelect->pWin;
Window *pWin;
Vdbe *v = sqlite3GetVdbe(pParse);
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, nEphExpr);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr);
+
/* Allocate registers to use for PARTITION BY values, if any. Initialize
** said registers to NULL. */
if( pMWin->pPartition ){