/ Check-in [db5ed226]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix the sqlite3ExprDup() function so that it correctly duplicates the Window object list on a Select that contains window functions. Fix for ticket [f09fcd17810f65f717].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:db5ed2268eda2e6c1df15cd8df4176463d89103b8fda33ba9a0604f0d92bd4da
User & Date: drh 2018-12-07 01:56:26
Context
2018-12-07
03:01
Fix dbfuzz2.c so that it works with -DSQLITE_OMIT_INIT check-in: 9ad796a8 user: drh tags: trunk
02:01
Fix the sqlite3ExprDup() function so that it correctly duplicates the Window object list on a Select that contains window functions. Fix for ticket [f09fcd17810f65f717]. check-in: 65aafb55 user: drh tags: branch-3.26
01:56
Fix the sqlite3ExprDup() function so that it correctly duplicates the Window object list on a Select that contains window functions. Fix for ticket [f09fcd17810f65f717]. check-in: db5ed226 user: drh tags: trunk
2018-12-06
22:12
Performance improvement: Avoid using sqlite3WalkerSelectExpr() and sqlite3WalkerSelectFrom() twice, so that the compiler will in-line their implementation. Closed-Leaf check-in: 2b9258b8 user: drh tags: ticket-f09fcd17810f
17:06
When masking bits off of sqlite3.flags, make sure the mask is 64 bits in size so as not to accidentally mask of high-order bits. check-in: 53d3b169 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  1325   1325       }
  1326   1326     }
  1327   1327     return pRet;
  1328   1328   }
  1329   1329   #else
  1330   1330   # define withDup(x,y) 0
  1331   1331   #endif
         1332  +
         1333  +#ifndef SQLITE_OMIT_WINDOWFUNC
         1334  +/*
         1335  +** The gatherSelectWindows() procedure and its helper routine
         1336  +** gatherSelectWindowsCallback() are used to scan all the expressions
         1337  +** an a newly duplicated SELECT statement and gather all of the Window
         1338  +** objects found there, assembling them onto the linked list at Select->pWin.
         1339  +*/
         1340  +static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){
         1341  +  if( pExpr->op==TK_FUNCTION && pExpr->y.pWin!=0 ){
         1342  +    assert( ExprHasProperty(pExpr, EP_WinFunc) );
         1343  +    pExpr->y.pWin->pNextWin = pWalker->u.pSelect->pWin;
         1344  +    pWalker->u.pSelect->pWin = pExpr->y.pWin;
         1345  +  }
         1346  +  return WRC_Continue;
         1347  +}
         1348  +static int gatherSelectWindowsSelectCallback(Walker *pWalker, Select *p){
         1349  +  return p==pWalker->u.pSelect ? WRC_Continue : WRC_Prune;
         1350  +}
         1351  +static void gatherSelectWindows(Select *p){
         1352  +  Walker w;
         1353  +  w.xExprCallback = gatherSelectWindowsCallback;
         1354  +  w.xSelectCallback = gatherSelectWindowsSelectCallback;
         1355  +  w.xSelectCallback2 = 0;
         1356  +  w.u.pSelect = p;
         1357  +  sqlite3WalkSelect(&w, p);
         1358  +}
         1359  +#endif
         1360  +
  1332   1361   
  1333   1362   /*
  1334   1363   ** The following group of routines make deep copies of expressions,
  1335   1364   ** expression lists, ID lists, and select statements.  The copies can
  1336   1365   ** be deleted (by being passed to their respective ...Delete() routines)
  1337   1366   ** without effecting the originals.
  1338   1367   **
................................................................................
  1493   1522       pNew->addrOpenEphm[0] = -1;
  1494   1523       pNew->addrOpenEphm[1] = -1;
  1495   1524       pNew->nSelectRow = p->nSelectRow;
  1496   1525       pNew->pWith = withDup(db, p->pWith);
  1497   1526   #ifndef SQLITE_OMIT_WINDOWFUNC
  1498   1527       pNew->pWin = 0;
  1499   1528       pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
         1529  +    if( p->pWin ) gatherSelectWindows(pNew);
  1500   1530   #endif
  1501   1531       pNew->selId = p->selId;
  1502   1532       *pp = pNew;
  1503   1533       pp = &pNew->pPrior;
  1504   1534       pNext = pNew;
  1505   1535     }
  1506   1536   

Changes to src/select.c.

  3457   3457           if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
  3458   3458             memset(&ifNullRow, 0, sizeof(ifNullRow));
  3459   3459             ifNullRow.op = TK_IF_NULL_ROW;
  3460   3460             ifNullRow.pLeft = pCopy;
  3461   3461             ifNullRow.iTable = pSubst->iNewTable;
  3462   3462             pCopy = &ifNullRow;
  3463   3463           }
         3464  +        testcase( ExprHasProperty(pCopy, EP_Subquery) );
  3464   3465           pNew = sqlite3ExprDup(db, pCopy, 0);
  3465   3466           if( pNew && pSubst->isLeftJoin ){
  3466   3467             ExprSetProperty(pNew, EP_CanBeNull);
  3467   3468           }
  3468   3469           if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
  3469   3470             pNew->iRightJoinTable = pExpr->iRightJoinTable;
  3470   3471             ExprSetProperty(pNew, EP_FromJoin);
................................................................................
  4021   4022         for(i=0; i<pOrderBy->nExpr; i++){
  4022   4023           pOrderBy->a[i].u.x.iOrderByCol = 0;
  4023   4024         }
  4024   4025         assert( pParent->pOrderBy==0 );
  4025   4026         pParent->pOrderBy = pOrderBy;
  4026   4027         pSub->pOrderBy = 0;
  4027   4028       }
  4028         -    pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
         4029  +    pWhere = pSub->pWhere;
         4030  +    pSub->pWhere = 0;
  4029   4031       if( isLeftJoin>0 ){
  4030   4032         setJoinExpr(pWhere, iNewParent);
  4031   4033       }
  4032   4034       pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
  4033   4035       if( db->mallocFailed==0 ){
  4034   4036         SubstContext x;
  4035   4037         x.pParse = pParse;

Changes to src/window.c.

  2129   2129   Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
  2130   2130     Window *pNew = 0;
  2131   2131     if( ALWAYS(p) ){
  2132   2132       pNew = sqlite3DbMallocZero(db, sizeof(Window));
  2133   2133       if( pNew ){
  2134   2134         pNew->zName = sqlite3DbStrDup(db, p->zName);
  2135   2135         pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
         2136  +      pNew->pFunc = p->pFunc;
  2136   2137         pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
  2137   2138         pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
  2138   2139         pNew->eType = p->eType;
  2139   2140         pNew->eEnd = p->eEnd;
  2140   2141         pNew->eStart = p->eStart;
  2141   2142         pNew->pStart = sqlite3ExprDup(db, p->pStart, 0);
  2142   2143         pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0);

Changes to test/window1.test.

   589    589   
   590    590   do_execsql_test 13.5 {
   591    591     SELECT a, rank() OVER(ORDER BY b) FROM t1
   592    592       INTERSECT 
   593    593     SELECT a, rank() OVER(ORDER BY b DESC) FROM t1;
   594    594   } {
   595    595   }
          596  +
          597  +# 2018-12-06
          598  +# https://www.sqlite.org/src/info/f09fcd17810f65f7
          599  +# Assertion fault when window functions are used.
          600  +#
          601  +# Root cause is the query flattener invoking sqlite3ExprDup() on
          602  +# expressions that contain subqueries with window functions.  The
          603  +# sqlite3ExprDup() routine is not making correctly initializing
          604  +# Select.pWin field of the subqueries.
          605  +#
          606  +sqlite3 db :memory:
          607  +do_execsql_test 14.0 {
          608  +  SELECT * FROM(
          609  +    SELECT * FROM (SELECT 1 AS c) WHERE c IN (
          610  +        SELECT (row_number() OVER()) FROM (VALUES (0))
          611  +    )
          612  +  );
          613  +} {1}
          614  +do_execsql_test 14.1 {
          615  +  CREATE TABLE t1(x); INSERT INTO t1(x) VALUES(12345);
          616  +  CREATE TABLE t2(c); INSERT INTO t2(c) VALUES(1);
          617  +  SELECT y, y+1, y+2 FROM (
          618  +    SELECT c IN (
          619  +      SELECT (row_number() OVER()) FROM t1
          620  +    ) AS y FROM t2
          621  +  );
          622  +} {1 2 3}
   596    623   
   597    624   finish_test