SQLite

Check-in [0387cb3add]
Login

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

Overview
Comment:Fix problems with sub-selects in WINDOW definitions. Also rename-column operations when the column being renamed appears in a WINDOW definition that is part of a VIEW or TRIGGER.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0387cb3add992b2028efe4f2100188d8f9fdfdcb233329857aa4b46a293cfc97
User & Date: dan 2019-01-23 16:59:24.350
Context
2019-01-23
19:17
Fix another fts5 crash that can occur if the database is corrupted. (check-in: 44ce8baa47 user: dan tags: trunk)
16:59
Fix problems with sub-selects in WINDOW definitions. Also rename-column operations when the column being renamed appears in a WINDOW definition that is part of a VIEW or TRIGGER. (check-in: 0387cb3add user: dan tags: trunk)
12:19
Fix a buffer overwrite triggered by a prefix query on a corrupt fts5 table. (check-in: 1d8172a94b user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/expr.c.
5362
5363
5364
5365
5366
5367
5368

5369
5370
5371
5372
5373
5374
5375
void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
  Walker w;
  w.xExprCallback = analyzeAggregate;
  w.xSelectCallback = analyzeAggregatesInSelect;
  w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
  w.walkerDepth = 0;
  w.u.pNC = pNC;

  assert( pNC->pSrcList!=0 );
  sqlite3WalkExpr(&w, pExpr);
}

/*
** Call sqlite3ExprAnalyzeAggregates() for every expression in an
** expression list.  Return the number of errors.







>







5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
  Walker w;
  w.xExprCallback = analyzeAggregate;
  w.xSelectCallback = analyzeAggregatesInSelect;
  w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
  w.walkerDepth = 0;
  w.u.pNC = pNC;
  w.pParse = 0;
  assert( pNC->pSrcList!=0 );
  sqlite3WalkExpr(&w, pExpr);
}

/*
** Call sqlite3ExprAnalyzeAggregates() for every expression in an
** expression list.  Return the number of errors.
Changes to src/resolve.c.
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868
869
870
871
        }
      }
      sqlite3WalkExprList(pWalker, pList);
      if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
        if( pExpr->y.pWin ){
          Select *pSel = pNC->pWinSelect;

          sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
          sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
          sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
          sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
          if( 0==pSel->pWin 
           || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin) 
          ){
            pExpr->y.pWin->pNextWin = pSel->pWin;
            pSel->pWin = pExpr->y.pWin;
          }
          pNC->ncFlags |= NC_AllowWin;







>



<







854
855
856
857
858
859
860
861
862
863
864

865
866
867
868
869
870
871
        }
      }
      sqlite3WalkExprList(pWalker, pList);
      if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
        if( pExpr->y.pWin ){
          Select *pSel = pNC->pWinSelect;
          sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
          sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
          sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
          sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);

          if( 0==pSel->pWin 
           || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin) 
          ){
            pExpr->y.pWin->pNextWin = pSel->pWin;
            pSel->pWin = pExpr->y.pWin;
          }
          pNC->ncFlags |= NC_AllowWin;
1531
1532
1533
1534
1535
1536
1537











1538
1539
1540
1541
1542
1543
1544
        if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
          sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
              "the GROUP BY clause");
          return WRC_Abort;
        }
      }
    }












    /* If this is part of a compound SELECT, check that it has the right
    ** number of expressions in the select list. */
    if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
      sqlite3SelectWrongNumTermsError(pParse, p->pNext);
      return WRC_Abort;
    }







>
>
>
>
>
>
>
>
>
>
>







1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
        if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
          sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
              "the GROUP BY clause");
          return WRC_Abort;
        }
      }
    }

    if( IN_RENAME_OBJECT ){
      Window *pWin;
      for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
        if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
         || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
        ){
          return WRC_Abort;
        }
      }
    }

    /* If this is part of a compound SELECT, check that it has the right
    ** number of expressions in the select list. */
    if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
      sqlite3SelectWrongNumTermsError(pParse, p->pNext);
      return WRC_Abort;
    }
Changes to src/walker.c.
13
14
15
16
17
18
19
















20
21
22
23
24
25
26
** an SQL statement.
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>


















/*
** Walk an expression tree.  Invoke the callback once for each node
** of the expression, while descending.  (In other words, the callback
** is invoked before visiting children.)
**
** The return value from the callback should be one of the WRC_*
** constants to specify how to proceed with the walk.







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







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
** an SQL statement.
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>


#if !defined(SQLITE_OMIT_WINDOWFUNC)
/*
** Walk all expressions linked into the list of Window objects passed
** as the second argument.
*/
static int walkWindowList(Walker *pWalker, Window *pList){
  Window *pWin;
  for(pWin=pList; pWin; pWin=pWin->pNextWin){
    if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
    if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
    if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
  }
  return WRC_Continue;
}
#endif

/*
** Walk an expression tree.  Invoke the callback once for each node
** of the expression, while descending.  (In other words, the callback
** is invoked before visiting children.)
**
** The return value from the callback should be one of the WRC_*
** constants to specify how to proceed with the walk.
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
      }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
      }else if( pExpr->x.pList ){
        if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
      }
#ifndef SQLITE_OMIT_WINDOWFUNC
      if( ExprHasProperty(pExpr, EP_WinFunc) ){
        Window *pWin = pExpr->y.pWin;
        if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
        if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
        if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
      }
#endif
    }
    break;
  }
  return WRC_Continue;
}







<
<
<
|







68
69
70
71
72
73
74



75
76
77
78
79
80
81
82
      }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
      }else if( pExpr->x.pList ){
        if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
      }
#ifndef SQLITE_OMIT_WINDOWFUNC
      if( ExprHasProperty(pExpr, EP_WinFunc) ){



        if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
      }
#endif
    }
    break;
  }
  return WRC_Continue;
}
95
96
97
98
99
100
101








102
103
104
105
106
107
108
int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
  if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
  if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
  if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
  if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
  if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
  if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;








  return WRC_Continue;
}

/*
** Walk the parse trees associated with all subqueries in the
** FROM clause of SELECT statement p.  Do not invoke the select
** callback on p, but do invoke it on each FROM clause subquery







>
>
>
>
>
>
>
>







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
  if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
  if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
  if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
  if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
  if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
  if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
#if !defined(SQLITE_OMIT_WINDOWFUNC) && !defined(SQLITE_OMIT_ALTERTABLE)
  {
    Parse *pParse = pWalker->pParse;
    if( pParse && IN_RENAME_OBJECT ){
      if( walkWindowList(pWalker, p->pWinDefn) ) return WRC_Abort;
    }
  }
#endif
  return WRC_Continue;
}

/*
** Walk the parse trees associated with all subqueries in the
** FROM clause of SELECT statement p.  Do not invoke the select
** callback on p, but do invoke it on each FROM clause subquery
Changes to test/altertab2.test.
178
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  END}
}

#-------------------------------------------------------------------------
do_execsql_test 5.0 {
  CREATE TABLE t2(a);
  CREATE TRIGGER r2 AFTER INSERT ON t2 WHEN new.a NOT NULL BEGIN
    SELECT a, rank() OVER w1 FROM t2
      WINDOW w1 AS (

        PARTITION BY b ORDER BY d ROWS BETWEEN 2 PRECEDING AND a FOLLOWING
      ),
      w2 AS (
        PARTITION BY b 
        ORDER BY d ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      );
  END;
} {}

do_catchsql_test 5.0.1 {
  INSERT INTO t2 VALUES(1);
} {1 {no such column: b}}

do_execsql_test 5.1 {
  ALTER TABLE t2 RENAME TO t2x;
  SELECT sql FROM sqlite_master WHERE name = 'r2';
} {
  {CREATE TRIGGER r2 AFTER INSERT ON "t2x" WHEN new.a NOT NULL BEGIN
    SELECT a, rank() OVER w1 FROM "t2x"
      WINDOW w1 AS (

        PARTITION BY b ORDER BY d ROWS BETWEEN 2 PRECEDING AND a FOLLOWING
      ),
      w2 AS (
        PARTITION BY b 
        ORDER BY d ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      );
  END}
}

do_execsql_test 5.2 {
  ALTER TABLE t2x RENAME a TO aaaa;
  SELECT sql FROM sqlite_master WHERE name = 'r2';
} {
  {CREATE TRIGGER r2 AFTER INSERT ON "t2x" WHEN new.aaaa NOT NULL BEGIN
    SELECT aaaa, rank() OVER w1 FROM "t2x"
      WINDOW w1 AS (

        PARTITION BY b ORDER BY d ROWS BETWEEN 2 PRECEDING AND a FOLLOWING
      ),
      w2 AS (
        PARTITION BY b 
        ORDER BY d ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      );
  END}
}

do_catchsql_test 5.3 {
  INSERT INTO t2x VALUES(1);
} {1 {no such column: b}}

#-------------------------------------------------------------------------

do_execsql_test 6.0 {
  CREATE TABLE t3(a,b,c,d);
  CREATE TRIGGER r3 AFTER INSERT ON t3 WHEN new.a NOT NULL BEGIN
    SELECT a,b,c FROM t3 EXCEPT SELECT a,b,c FROM t3 ORDER BY a;







|

>
|


|
|




|

|






|

>
|


|
|









|

>
|


|
|




|

|







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  END}
}

#-------------------------------------------------------------------------
do_execsql_test 5.0 {
  CREATE TABLE t2(a);
  CREATE TRIGGER r2 AFTER INSERT ON t2 WHEN new.a NOT NULL BEGIN
    SELECT a, sum(a) OVER w1 FROM t2
      WINDOW w1 AS (
        PARTITION BY a ORDER BY a 
        ROWS BETWEEN 2 PRECEDING AND 3 FOLLOWING
      ),
      w2 AS (
        PARTITION BY a
        ORDER BY rowid ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      );
  END;
} {}

do_execsql_test 5.0.1 {
  INSERT INTO t2 VALUES(1);
} {}

do_execsql_test 5.1 {
  ALTER TABLE t2 RENAME TO t2x;
  SELECT sql FROM sqlite_master WHERE name = 'r2';
} {
  {CREATE TRIGGER r2 AFTER INSERT ON "t2x" WHEN new.a NOT NULL BEGIN
    SELECT a, sum(a) OVER w1 FROM "t2x"
      WINDOW w1 AS (
        PARTITION BY a ORDER BY a 
        ROWS BETWEEN 2 PRECEDING AND 3 FOLLOWING
      ),
      w2 AS (
        PARTITION BY a
        ORDER BY rowid ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      );
  END}
}

do_execsql_test 5.2 {
  ALTER TABLE t2x RENAME a TO aaaa;
  SELECT sql FROM sqlite_master WHERE name = 'r2';
} {
  {CREATE TRIGGER r2 AFTER INSERT ON "t2x" WHEN new.aaaa NOT NULL BEGIN
    SELECT aaaa, sum(aaaa) OVER w1 FROM "t2x"
      WINDOW w1 AS (
        PARTITION BY aaaa ORDER BY aaaa 
        ROWS BETWEEN 2 PRECEDING AND 3 FOLLOWING
      ),
      w2 AS (
        PARTITION BY aaaa
        ORDER BY rowid ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      );
  END}
}

do_execsql_test 5.3 {
  INSERT INTO t2x VALUES(1);
} {}

#-------------------------------------------------------------------------

do_execsql_test 6.0 {
  CREATE TABLE t3(a,b,c,d);
  CREATE TRIGGER r3 AFTER INSERT ON t3 WHEN new.a NOT NULL BEGIN
    SELECT a,b,c FROM t3 EXCEPT SELECT a,b,c FROM t3 ORDER BY a;
Added test/altertab3.test.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 2019 January 23
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix altertab3

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b);
  CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    SELECT sum(b) OVER w FROM t1 WINDOW w AS (ORDER BY a);
  END;
}

do_execsql_test 1.1 {
  ALTER TABLE t1 RENAME a TO aaa;
}

do_execsql_test 1.2 {
  SELECT sql FROM sqlite_master WHERE name='tr1'
} {{CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
    SELECT sum(b) OVER w FROM t1 WINDOW w AS (ORDER BY aaa);
  END}}

do_execsql_test 1.3 {
  INSERT INTO t1 VALUES(1, 2);
}


finish_test


Changes to test/window1.test.
668
669
670
671
672
673
674




























675
676
do_execsql_test 15.2 {
  SELECT(
    WITH c AS(
      VALUES(1)
    ) SELECT '' FROM c,c
  ) x WHERE x+x;
} {}





























finish_test







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


668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
do_execsql_test 15.2 {
  SELECT(
    WITH c AS(
      VALUES(1)
    ) SELECT '' FROM c,c
  ) x WHERE x+x;
} {}

#-------------------------------------------------------------------------

do_execsql_test 16.0 {
  CREATE TABLE t7(a,b); 
  INSERT INTO t7(rowid, a, b) VALUES
      (1, 1, 3),
      (2, 10, 4),
      (3, 100, 2);
}

do_execsql_test 16.1 {
  SELECT rowid, sum(a) OVER (PARTITION BY b IN (SELECT rowid FROM t7)) FROM t7;
} {
  2 10
  1 101
  3 101
}

do_execsql_test 16.2 {
  SELECT rowid, sum(a) OVER w1 FROM t7 
  WINDOW w1 AS (PARTITION BY b IN (SELECT rowid FROM t7));
} {
  2 10
  1 101
  3 101
}


finish_test