/ Check-in [4f5b2d93]
Login

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

Overview
Comment:Ensure that SQLite does not attempt to process incompatible window functions in a single scan. Fix for [256741a1].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 4f5b2d938194fab7627486e2ced633def2c90d9d3328e3700612feb9dbfa3d9a
User & Date: dan 2019-08-15 13:53:22
Context
2019-08-15
14:35
Ensure that the optional "sz=N" parameter that can be manually added to the end of an sqlite_stat1 entry does not have an N value that is too small. Ticket [e4598ecbdd18bd82] check-in: 98357d8c user: drh tags: trunk
13:53
Ensure that SQLite does not attempt to process incompatible window functions in a single scan. Fix for [256741a1]. check-in: 4f5b2d93 user: dan tags: trunk
13:46
Avoid downgrading SQLITE_CORRUPT errors detected by the schema parser into SQLITE_NOMEM or SQLITE_ERROR errors. check-in: b2e79f8f user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  1321   1321   static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){
  1322   1322     if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_WinFunc) ){
  1323   1323       Select *pSelect = pWalker->u.pSelect;
  1324   1324       Window *pWin = pExpr->y.pWin;
  1325   1325       assert( pWin );
  1326   1326       assert( IsWindowFunc(pExpr) );
  1327   1327       assert( pWin->ppThis==0 );
  1328         -    if( pSelect->pWin ){
  1329         -      pSelect->pWin->ppThis = &pWin->pNextWin;
  1330         -    }
  1331         -    pWin->pNextWin = pSelect->pWin;
  1332         -    pWin->ppThis = &pSelect->pWin;
  1333         -    pSelect->pWin = pWin;
         1328  +    sqlite3WindowLink(pSelect, pWin);
  1334   1329     }
  1335   1330     return WRC_Continue;
  1336   1331   }
  1337   1332   static int gatherSelectWindowsSelectCallback(Walker *pWalker, Select *p){
  1338   1333     return p==pWalker->u.pSelect ? WRC_Continue : WRC_Prune;
  1339   1334   }
  1340   1335   static void gatherSelectWindows(Select *p){

Changes to src/resolve.c.

   904    904             assert( pWin==pExpr->y.pWin );
   905    905             if( IN_RENAME_OBJECT==0 ){
   906    906               sqlite3WindowUpdate(pParse, pSel->pWinDefn, pWin, pDef);
   907    907             }
   908    908             sqlite3WalkExprList(pWalker, pWin->pPartition);
   909    909             sqlite3WalkExprList(pWalker, pWin->pOrderBy);
   910    910             sqlite3WalkExpr(pWalker, pWin->pFilter);
   911         -          if( 0==pSel->pWin 
   912         -           || 0==sqlite3WindowCompare(pParse, pSel->pWin, pWin, 0)
   913         -          ){
   914         -            pWin->pNextWin = pSel->pWin;
   915         -            if( pSel->pWin ){
   916         -              pSel->pWin->ppThis = &pWin->pNextWin;
   917         -            }
   918         -            pSel->pWin = pWin;
   919         -            pWin->ppThis = &pSel->pWin;
   920         -          }
          911  +          sqlite3WindowLink(pSel, pWin);
   921    912             pNC->ncFlags |= NC_HasWin;
   922    913           }else
   923    914   #endif /* SQLITE_OMIT_WINDOWFUNC */
   924    915           {
   925    916             NameContext *pNC2 = pNC;
   926    917             pExpr->op = TK_AGG_FUNCTION;
   927    918             pExpr->op2 = 0;

Changes to src/sqliteInt.h.

  3605   3605   
  3606   3606   #ifndef SQLITE_OMIT_WINDOWFUNC
  3607   3607   void sqlite3WindowDelete(sqlite3*, Window*);
  3608   3608   void sqlite3WindowUnlinkFromSelect(Window*);
  3609   3609   void sqlite3WindowListDelete(sqlite3 *db, Window *p);
  3610   3610   Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
  3611   3611   void sqlite3WindowAttach(Parse*, Expr*, Window*);
         3612  +void sqlite3WindowLink(Select *pSel, Window *pWin);
  3612   3613   int sqlite3WindowCompare(Parse*, Window*, Window*, int);
  3613   3614   void sqlite3WindowCodeInit(Parse*, Window*);
  3614   3615   void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
  3615   3616   int sqlite3WindowRewrite(Parse*, Select*);
  3616   3617   int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
  3617   3618   void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
  3618   3619   Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);

Changes to src/window.c.

  1224   1224             "DISTINCT is not supported for window functions"
  1225   1225         );
  1226   1226       }
  1227   1227     }else{
  1228   1228       sqlite3WindowDelete(pParse->db, pWin);
  1229   1229     }
  1230   1230   }
         1231  +
         1232  +/*
         1233  +** Possibly link window pWin into the list at pSel->pWin (window functions
         1234  +** to be processed as part of SELECT statement pSel). The window is linked
         1235  +** in if either (a) there are no other windows already linked to this
         1236  +** SELECT, or (b) the windows already linked use a compatible window frame.
         1237  +*/
         1238  +void sqlite3WindowLink(Select *pSel, Window *pWin){
         1239  +  if( 0==pSel->pWin 
         1240  +   || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0)
         1241  +  ){
         1242  +    pWin->pNextWin = pSel->pWin;
         1243  +    if( pSel->pWin ){
         1244  +      pSel->pWin->ppThis = &pWin->pNextWin;
         1245  +    }
         1246  +    pSel->pWin = pWin;
         1247  +    pWin->ppThis = &pSel->pWin;
         1248  +  }
         1249  +}
  1231   1250   
  1232   1251   /*
  1233   1252   ** Return 0 if the two window objects are identical, or non-zero otherwise.
  1234   1253   ** Identical window objects can be processed in a single scan.
  1235   1254   */
  1236   1255   int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2, int bFilter){
  1237   1256     if( p1->eFrmType!=p2->eFrmType ) return 1;
................................................................................
  1411   1430     Vdbe *v = sqlite3GetVdbe(pParse);
  1412   1431     Window *pWin;
  1413   1432     for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
  1414   1433       FuncDef *pFunc = pWin->pFunc;
  1415   1434       int regArg;
  1416   1435       int nArg = windowArgCount(pWin);
  1417   1436       int i;
         1437  +
         1438  +    assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED );
  1418   1439   
  1419   1440       for(i=0; i<nArg; i++){
  1420   1441         if( i!=1 || pFunc->zName!=nth_valueName ){
  1421   1442           sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);
  1422   1443         }else{
  1423   1444           sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+i, reg+i);
  1424   1445         }

Changes to test/window9.test.

   167    167     }
   168    168   } {
   169    169     do_test 5.1.$tn {
   170    170       execsql "EXPLAIN QUERY PLAN $sql"
   171    171     } {~/ORDER/}
   172    172   }
   173    173   
          174  +#-------------------------------------------------------------------------
          175  +reset_db
          176  +do_execsql_test 6.0 {
          177  +  CREATE TABLE t0(c0);
          178  +  INSERT INTO t0(c0) VALUES (0);
          179  +}
          180  +
          181  +do_execsql_test 6.1 {
          182  +  SELECT * FROM t0 WHERE 
          183  +  EXISTS (
          184  +    SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0
          185  +  ) >=1 AND 
          186  +  EXISTS (
          187  +    SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0
          188  +  ) <=1;
          189  +} {0}
          190  +
          191  +do_execsql_test 6.2 {
          192  +  SELECT * FROM t0 WHERE EXISTS (
          193  +    SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0
          194  +  ) 
          195  +  BETWEEN 1 AND 1;
          196  +} {0}
   174    197   
   175    198   
   176    199   finish_test