/ Check-in [0f9fc6b6]
Login

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

Overview
Comment:Ensure that the window function rewrite does not leave the parse tree in an invalid state that might cause problems downstream before the error is recognized and unwinds the stack. Also take steps such that an invalid parse tree does not cause problems even if it goes unrecognized. Forum post 398e9d5aa9.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0f9fc6b6073365d5159cd71e7fe08f8dadbc7b42abd324361e809502f4359155
User & Date: drh 2021-11-07 23:33:01
Context
2021-11-08
16:38
Add assert()s that verify that cursor numbers on subqueries are always greater than outer cursor numbers. Except, this is not always true in the presence of query flattening. We might need to relax that constraint. This branch will probably become a dead-end. For now it is saved for reference. (Closed-Leaf check-in: 6f436966 user: drh tags: well-ordered-cursors)
15:46
Fix an assert() in memdbTruncate() that could fail when processing a corrupt database. (check-in: b1e29298 user: dan tags: trunk)
2021-11-07
23:33
Ensure that the window function rewrite does not leave the parse tree in an invalid state that might cause problems downstream before the error is recognized and unwinds the stack. Also take steps such that an invalid parse tree does not cause problems even if it goes unrecognized. Forum post 398e9d5aa9. (check-in: 0f9fc6b6 user: drh tags: trunk)
2021-11-06
20:25
Add ALWAYS() to a branch made unreachable by the previous check-in. (check-in: 0dc963f6 user: drh tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
static void exprCodeBetween(Parse*,Expr*,int,void(*)(Parse*,Expr*,int,int),int);
static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree);

/*
** Return the affinity character for a single column of a table.
*/
char sqlite3TableColumnAffinity(const Table *pTab, int iCol){
  assert( iCol<pTab->nCol );
  return iCol>=0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
}

/*
** Return the 'affinity' of the expression pExpr if any.
**
** If pExpr is a column, a reference to a column via an 'AS' alias,
** or a sub-select with a column as the return value, then the 







|
|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
static void exprCodeBetween(Parse*,Expr*,int,void(*)(Parse*,Expr*,int,int),int);
static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree);

/*
** Return the affinity character for a single column of a table.
*/
char sqlite3TableColumnAffinity(const Table *pTab, int iCol){
  if( iCol<0 || NEVER(iCol>=pTab->nCol) ) return SQLITE_AFF_INTEGER;
  return pTab->aCol[iCol].affinity;
}

/*
** Return the 'affinity' of the expression pExpr if any.
**
** If pExpr is a column, a reference to a column via an 'AS' alias,
** or a sub-select with a column as the return value, then the 

Changes to src/where.c.

5361
5362
5363
5364
5365
5366
5367

5368
5369
5370
5371
5372
5373
5374
  /* Generate the code to do the search.  Each iteration of the for
  ** loop below generates code for a single nested loop of the VM
  ** program.
  */
  for(ii=0; ii<nTabList; ii++){
    int addrExplain;
    int wsFlags;

    pLevel = &pWInfo->a[ii];
    wsFlags = pLevel->pWLoop->wsFlags;
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
    if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
      constructAutomaticIndex(pParse, &pWInfo->sWC,
                &pTabList->a[pLevel->iFrom], notReady, pLevel);
      if( db->mallocFailed ) goto whereBeginError;







>







5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
  /* Generate the code to do the search.  Each iteration of the for
  ** loop below generates code for a single nested loop of the VM
  ** program.
  */
  for(ii=0; ii<nTabList; ii++){
    int addrExplain;
    int wsFlags;
    if( pParse->nErr ) goto whereBeginError;
    pLevel = &pWInfo->a[ii];
    wsFlags = pLevel->pWLoop->wsFlags;
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
    if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
      constructAutomaticIndex(pParse, &pWInfo->sWC,
                &pTabList->a[pLevel->iFrom], notReady, pLevel);
      if( db->mallocFailed ) goto whereBeginError;

Changes to src/window.c.

1095
1096
1097
1098
1099
1100
1101
1102




1103
1104
1105
1106
1107
1108
1109
        w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
        sqlite3WalkSelect(&w, pSub);
      }
    }else{
      sqlite3SelectDelete(db, pSub);
    }
    if( db->mallocFailed ) rc = SQLITE_NOMEM;
    sqlite3DbFree(db, pTab);




  }

  if( rc ){
    if( pParse->nErr==0 ){
      assert( pParse->db->mallocFailed );
      sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
    }







|
>
>
>
>







1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
        w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
        sqlite3WalkSelect(&w, pSub);
      }
    }else{
      sqlite3SelectDelete(db, pSub);
    }
    if( db->mallocFailed ) rc = SQLITE_NOMEM;

    /* Defer deleting the temporary table pTab because if an error occurred,
    ** there could still be references to that table embedded in the
    ** result-set or ORDER BY clause of the SELECT statement p.  */
    sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab);
  }

  if( rc ){
    if( pParse->nErr==0 ){
      assert( pParse->db->mallocFailed );
      sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
    }

Changes to test/window1.test.

2186
2187
2188
2189
2190
2191
2192












2193
2194
2195
}
do_execsql_test 70.1 {
  SELECT substr(a,4,lag(a,7) OVER(PARTITION BY 'cf23' ORDER BY 2)) AS ca0 FROM t1 ORDER BY ca0;
}
do_execsql_test 70.2 {
  SELECT substr(a,4,lag(a,7) OVER(PARTITION BY 'cf23' ORDER BY likely(2))) AS ca0 FROM t1 ORDER BY ca0;
}














finish_test







>
>
>
>
>
>
>
>
>
>
>
>



2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
}
do_execsql_test 70.1 {
  SELECT substr(a,4,lag(a,7) OVER(PARTITION BY 'cf23' ORDER BY 2)) AS ca0 FROM t1 ORDER BY ca0;
}
do_execsql_test 70.2 {
  SELECT substr(a,4,lag(a,7) OVER(PARTITION BY 'cf23' ORDER BY likely(2))) AS ca0 FROM t1 ORDER BY ca0;
}

# 2021-11-07
# Bug report from Wang Ke
# https://sqlite.org/forum/forumpost/9ba4f60ff8
reset_db
do_catchsql_test 71.0 {
  CREATE TABLE t0(a);
  SELECT a FROM t0, (SELECT a AS b FROM t0)
   WHERE (a,1)=(SELECT 2,2 UNION SELECT sum(b),max(b) OVER(ORDER BY b) ORDER BY 2)
     AND b=4
   ORDER BY b;
} {/1 {.*}/}


finish_test