From fc15f4c52830c9152e4fdaebb4cfb8487bc86977 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 28 Mar 2019 13:03:41 +0000 Subject: [PATCH] Improved TreeView display of Window objects. Change the Window.eType field to Window.eFrmType to avoid confusion with other "eType" values. FossilOrigin-Name: ec2f207dedb223077bbd3e4584499250eb12219712c917e930acccfa2c46e23b --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/sqliteInt.h | 8 ++++---- src/treeview.c | 44 ++++++++++++++++++++++++++++++++++++++++---- src/window.c | 44 ++++++++++++++++++++++++-------------------- 5 files changed, 77 insertions(+), 37 deletions(-) diff --git a/manifest b/manifest index af3eaf8f26..2fc7b60fb8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sthe\sstring\sformatter\sin\ssqlite3NestedParse()\sfails\sdue\sto\san\sover-length\nstring,\smake\ssure\sthis\serror\sis\srecorded\sby\sthe\sparser\sso\sthat\sit\sknows\sto\nfail. -D 2019-03-28T04:03:17.931 +C Improved\sTreeView\sdisplay\sof\sWindow\sobjects.\nChange\sthe\sWindow.eType\sfield\sto\sWindow.eFrmType\sto\savoid\sconfusion\swith\nother\s"eType"\svalues. +D 2019-03-28T13:03:41.454 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -521,7 +521,7 @@ F src/shell.c.in c1986496062f9dba4ed5b70db06b5e0f32e1954cdcfab0b30372c6c18679681 F src/sqlite.h.in f765fce74038607388d3a96cd7fad892f363bdcde24911565edf610ecf69534c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683 -F src/sqliteInt.h 19641f2402ef4e45fd2e222f5a45bb24e3f89a519059d35ce2819f46ce5e1a1e +F src/sqliteInt.h 773a43d21001311853e2e213f693ed5ac64c5ec2cf4c7fc492715421f244454f F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -580,7 +580,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e -F src/treeview.c c6ff90da4cc1813ff2d9bb11f17d4d927db62c47e552faa1835edc47269d753d +F src/treeview.c f41d6a62ff054277e068829859b0f6259fb6a9ebda2e87aa3a83b01f4cb3cc0b F src/trigger.c bb034c08eca111e66a19cda045903a12547c1be2294b5570d794b869d9c44a73 F src/update.c 0b973357d88092140531e07ff641139c26fb4380b0b9f5ed98c5f7691b4604d1 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 @@ -605,7 +605,7 @@ F src/where.c 8a207cb2ca6b99e1edb1e4bbff9b0504385a759cbf66180d1deb34d80ca4b799 F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88 F src/wherecode.c 6fa4056c5ce019e4a8af33795906340176813cb3c1236f4b7b08df76a1b6287b F src/whereexpr.c 90859652920f153d2c03f075488744be2926625ebd36911bcbcb17d0d29c891c -F src/window.c 2e3fdb046dfe32a0a30855b952152ea8f1cb5cffdccb2b9d6845ca1f3a4d3bdc +F src/window.c 92b6d593a63f27b29360176f71eb5839562bdb7dae6effd35f4c69168ea5455d F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1813,7 +1813,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bbdbaf84a52937ccf877072a8b01b07f7b9c037c59ba54df72ca888d5404cbad -R a8b4e886cb7335563acdda9aaece2736 +P 85e53ff13300132250221de769a2aa7d92d81bb48d60f6e99000bc69a5b1e6fb +R 955959731aaddc58f4bc71017ffeeb76 U drh -Z 5908e55b684ef19b846738ab0396e51d +Z fae16977b4563395e6e67b312131bb19 diff --git a/manifest.uuid b/manifest.uuid index 5a275b656f..70aa3fbe7e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85e53ff13300132250221de769a2aa7d92d81bb48d60f6e99000bc69a5b1e6fb \ No newline at end of file +ec2f207dedb223077bbd3e4584499250eb12219712c917e930acccfa2c46e23b \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2fa1d1aa3d..13f2339dad 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3535,7 +3535,7 @@ struct TreeView { #endif /* SQLITE_DEBUG */ /* -** This object is used in varioius ways, all related to window functions +** This object is used in various ways, all related to window functions ** ** (1) A single instance of this structure is attached to the ** the Expr.pWin field for each window function in an expression tree. @@ -3550,18 +3550,18 @@ struct TreeView { ** object on a linked list attached to Select.pWinDefn. ** ** The uses (1) and (2) are really the same Window object that just happens -** to be accessible in two different ways. Use (3) is are separate objects. +** to be accessible in two different ways. Use case (3) are separate objects. */ struct Window { char *zName; /* Name of window (may be NULL) */ char *zBase; /* Name of base window for chaining (may be NULL) */ ExprList *pPartition; /* PARTITION BY clause */ ExprList *pOrderBy; /* ORDER BY clause */ - u8 eType; /* TK_RANGE or TK_ROWS */ + u8 eFrmType; /* TK_RANGE, TK_GROUPS, TK_ROWS, or 0 */ u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ u8 bImplicitFrame; /* True if frame was implicitly specified */ - u8 eExclude; + u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */ Expr *pStart; /* Expression for " PRECEDING" */ Expr *pEnd; /* Expression for " FOLLOWING" */ Window *pNextWin; /* Next window function belonging to this SELECT */ diff --git a/src/treeview.c b/src/treeview.c index 743c3b1298..490c2c3cb0 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -309,24 +309,60 @@ void sqlite3TreeViewBound( ** Generate a human-readable explanation for a Window object */ void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){ + int nElement = 0; pView = sqlite3TreeViewPush(pView, more); if( pWin->zName ){ sqlite3TreeViewLine(pView, "OVER %s", pWin->zName); }else{ sqlite3TreeViewLine(pView, "OVER"); } + if( pWin->pFilter ) nElement++; + if( pWin->zBase ) nElement++; + if( pWin->pOrderBy ) nElement++; + if( pWin->eFrmType ) nElement++; + if( pWin->eExclude ) nElement++; + if( pWin->pFilter ){ + sqlite3TreeViewItem(pView, "FILTER", (--nElement)>0); + sqlite3TreeViewExpr(pView, pWin->pFilter, 0); + sqlite3TreeViewPop(pView); + } + if( pWin->zBase ){ + sqlite3TreeViewPush(pView, (--nElement)>0); + sqlite3TreeViewLine(pView, "window: %s", pWin->zBase); + sqlite3TreeViewPop(pView); + } if( pWin->pPartition ){ - sqlite3TreeViewExprList(pView, pWin->pPartition, 1, "PARTITION-BY"); + sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY"); } if( pWin->pOrderBy ){ - sqlite3TreeViewExprList(pView, pWin->pOrderBy, 1, "ORDER-BY"); + sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY"); } - if( pWin->eType ){ - sqlite3TreeViewItem(pView, pWin->eType==TK_RANGE ? "RANGE" : "ROWS", 0); + if( pWin->eFrmType ){ + const char *zFrmType = "ROWS"; + if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE"; + if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS"; + sqlite3TreeViewItem(pView, zFrmType, (--nElement)>0); sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1); sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0); sqlite3TreeViewPop(pView); } + if( pWin->eExclude ){ + char zBuf[30]; + const char *zExclude; + switch( pWin->eExclude ){ + case TK_NO: zExclude = "NO OTHERS"; break; + case TK_CURRENT: zExclude = "CURRENT ROW"; break; + case TK_GROUP: zExclude = "GROUP"; break; + case TK_TIES: zExclude = "TIES"; break; + default: + sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude); + zExclude = zBuf; + break; + } + sqlite3TreeViewPush(pView, 0); + sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude); + sqlite3TreeViewPop(pView); + } sqlite3TreeViewPop(pView); } #endif /* SQLITE_OMIT_WINDOWFUNC */ diff --git a/src/window.c b/src/window.c index 38ae5792ab..000a179c83 100644 --- a/src/window.c +++ b/src/window.c @@ -662,7 +662,7 @@ void sqlite3WindowUpdate( Window *pWin, /* Window frame to update */ FuncDef *pFunc /* Window function definition */ ){ - if( pWin->zName && pWin->eType==0 ){ + if( pWin->zName && pWin->eFrmType==0 ){ Window *p = windowFind(pParse, pList, pWin->zName); if( p==0 ) return; pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0); @@ -671,12 +671,12 @@ void sqlite3WindowUpdate( pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0); pWin->eStart = p->eStart; pWin->eEnd = p->eEnd; - pWin->eType = p->eType; + pWin->eFrmType = p->eFrmType; pWin->eExclude = p->eExclude; }else{ sqlite3WindowChain(pParse, pWin, pList); } - if( (pWin->eType==TK_RANGE) + if( (pWin->eFrmType==TK_RANGE) && (pWin->pStart || pWin->pEnd) && (pWin->pOrderBy==0 || pWin->pOrderBy->nExpr!=1) ){ @@ -693,7 +693,7 @@ void sqlite3WindowUpdate( }else{ struct WindowUpdate { const char *zFunc; - int eType; + int eFrmType; int eStart; int eEnd; } aUp[] = { @@ -712,7 +712,7 @@ void sqlite3WindowUpdate( sqlite3ExprDelete(db, pWin->pStart); sqlite3ExprDelete(db, pWin->pEnd); pWin->pEnd = pWin->pStart = 0; - pWin->eType = aUp[i].eType; + pWin->eFrmType = aUp[i].eFrmType; pWin->eStart = aUp[i].eStart; pWin->eEnd = aUp[i].eEnd; pWin->eExclude = 0; @@ -1042,7 +1042,7 @@ static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ */ Window *sqlite3WindowAlloc( Parse *pParse, /* Parsing context */ - int eType, /* Frame type. TK_RANGE or TK_ROWS */ + int eType, /* Frame type. TK_RANGE, TK_ROWS, TK_GROUPS, or 0 */ int eStart, /* Start type: CURRENT, PRECEDING, FOLLOWING, UNBOUNDED */ Expr *pStart, /* Start window size if TK_PRECEDING or FOLLOWING */ int eEnd, /* End type: CURRENT, FOLLOWING, TK_UNBOUNDED, PRECEDING */ @@ -1089,7 +1089,7 @@ Window *sqlite3WindowAlloc( pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); if( pWin==0 ) goto windowAllocErr; - pWin->eType = eType; + pWin->eFrmType = eType; pWin->eStart = eStart; pWin->eEnd = eEnd; if( eExclude==0 && OptimizationDisabled(pParse->db, SQLITE_QueryFlattener) ){ @@ -1198,7 +1198,7 @@ void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ ** Identical window objects can be processed in a single scan. */ int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){ - if( p1->eType!=p2->eType ) return 1; + if( p1->eFrmType!=p2->eFrmType ) return 1; if( p1->eStart!=p2->eStart ) return 1; if( p1->eEnd!=p2->eEnd ) return 1; if( p1->eExclude!=p2->eExclude ) return 1; @@ -1861,7 +1861,7 @@ static int windowCodeOp( int addrIf = 0; int addrContinue = 0; int addrGoto = 0; - int bPeer = (pMWin->eType!=TK_ROWS); + int bPeer = (pMWin->eFrmType!=TK_ROWS); int lblDone = sqlite3VdbeMakeLabel(pParse); int addrNextRange = 0; @@ -1874,7 +1874,7 @@ static int windowCodeOp( } if( regCountdown>0 ){ - if( pMWin->eType==TK_RANGE ){ + if( pMWin->eFrmType==TK_RANGE ){ addrNextRange = sqlite3VdbeCurrentAddr(v); assert( op==WINDOW_AGGINVERSE || op==WINDOW_AGGSTEP ); if( op==WINDOW_AGGINVERSE ){ @@ -1983,7 +1983,7 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ pNew->pFunc = p->pFunc; pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0); - pNew->eType = p->eType; + pNew->eFrmType = p->eFrmType; pNew->eEnd = p->eEnd; pNew->eStart = p->eStart; pNew->eExclude = p->eExclude; @@ -2427,14 +2427,18 @@ void sqlite3WindowCodeStep( ** be deleted after they enter the frame (WINDOW_AGGSTEP). */ switch( pMWin->eStart ){ case TK_FOLLOWING: - if( pMWin->eType!=TK_RANGE && windowExprGtZero(pParse, pMWin->pStart) ){ + if( pMWin->eFrmType!=TK_RANGE + && windowExprGtZero(pParse, pMWin->pStart) + ){ s.eDelete = WINDOW_RETURN_ROW; } break; case TK_UNBOUNDED: if( windowCacheFrame(pMWin)==0 ){ if( pMWin->eEnd==TK_PRECEDING ){ - if( pMWin->eType!=TK_RANGE && windowExprGtZero(pParse, pMWin->pEnd) ){ + if( pMWin->eFrmType!=TK_RANGE + && windowExprGtZero(pParse, pMWin->pEnd) + ){ s.eDelete = WINDOW_AGGSTEP; } }else{ @@ -2468,7 +2472,7 @@ void sqlite3WindowCodeStep( /* If this is not a "ROWS BETWEEN ..." frame, then allocate arrays of ** registers to store copies of the ORDER BY expressions (peer values) ** for the main loop, and for each cursor (start, current and end). */ - if( pMWin->eType!=TK_ROWS ){ + if( pMWin->eFrmType!=TK_ROWS ){ int nPeer = (pOrderBy ? pOrderBy->nExpr : 0); regNewPeer = regNew + pMWin->nBufferCol; if( pMWin->pPartition ) regNewPeer += pMWin->pPartition->nExpr; @@ -2519,11 +2523,11 @@ void sqlite3WindowCodeStep( if( regStart ){ sqlite3ExprCode(pParse, pMWin->pStart, regStart); - windowCheckValue(pParse, regStart, 0 + (pMWin->eType==TK_RANGE ? 3 : 0)); + windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE ? 3 : 0)); } if( regEnd ){ sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); - windowCheckValue(pParse, regEnd, 1 + (pMWin->eType==TK_RANGE ? 3 : 0)); + windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE ? 3 : 0)); } if( pMWin->eStart==pMWin->eEnd && regStart ){ @@ -2538,7 +2542,7 @@ void sqlite3WindowCodeStep( sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd); sqlite3VdbeJumpHere(v, addrGe); } - if( pMWin->eStart==TK_FOLLOWING && pMWin->eType!=TK_RANGE && regEnd ){ + if( pMWin->eStart==TK_FOLLOWING && pMWin->eFrmType!=TK_RANGE && regEnd ){ assert( pMWin->eEnd==TK_FOLLOWING ); sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regStart); } @@ -2567,7 +2571,7 @@ void sqlite3WindowCodeStep( if( pMWin->eStart==TK_FOLLOWING ){ windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); if( pMWin->eEnd!=TK_UNBOUNDED ){ - if( pMWin->eType==TK_RANGE ){ + if( pMWin->eFrmType==TK_RANGE ){ int lbl = sqlite3VdbeMakeLabel(pParse); int addrNext = sqlite3VdbeCurrentAddr(v); windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl); @@ -2589,7 +2593,7 @@ void sqlite3WindowCodeStep( int addr = 0; windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); if( pMWin->eEnd!=TK_UNBOUNDED ){ - if( pMWin->eType==TK_RANGE ){ + if( pMWin->eFrmType==TK_RANGE ){ int lbl = 0; addr = sqlite3VdbeCurrentAddr(v); if( regEnd ){ @@ -2635,7 +2639,7 @@ void sqlite3WindowCodeStep( int addrBreak2; int addrBreak3; windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); - if( pMWin->eType==TK_RANGE ){ + if( pMWin->eFrmType==TK_RANGE ){ addrStart = sqlite3VdbeCurrentAddr(v); addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); -- 2.47.2