SQLite

Check-in [de000280c6]
Login

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

Overview
Comment:Detect nested aggregate functions even if the inner aggregate function is aliased using an AS clause. Ticket #2526. (CVS 4179)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: de000280c6d0b13440d2450eb6ba42073ad46c56
User & Date: drh 2007-07-23 22:51:15.000
Context
2007-07-24
10:22
Remove the comment in the documentation that says that incremental vacuum mode is not persistent because as of 3.4.1 it is persistent. Ticket #2528. (CVS 4180) (check-in: 6c4040941e user: drh tags: trunk)
2007-07-23
22:51
Detect nested aggregate functions even if the inner aggregate function is aliased using an AS clause. Ticket #2526. (CVS 4179) (check-in: de000280c6 user: drh tags: trunk)
19:39
The REPLACE conflict resolution falls back to FAIL when on a CHECK constraint violation. Ticket #2525. (CVS 4178) (check-in: b213614abf user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/expr.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.300 2007/06/25 16:29:34 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.301 2007/07/23 22:51:15 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146






1147
1148
1149
1150
1151
1152
1153
1154
    ** Note that the expression in the result set should have already been
    ** resolved by the time the WHERE clause is resolved.
    */
    if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
      for(j=0; j<pEList->nExpr; j++){
        char *zAs = pEList->a[j].zName;
        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
          Expr *pDup;
          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
          assert( pExpr->pList==0 );
          assert( pExpr->pSelect==0 );






          pDup = sqlite3ExprDup(pEList->a[j].pExpr);
          if( pExpr->flags & EP_ExpCollate ){
            pDup->pColl = pExpr->pColl;
            pDup->flags |= EP_ExpCollate;
          }
          if( pExpr->span.dyn ) sqliteFree((char*)pExpr->span.z);
          if( pExpr->token.dyn ) sqliteFree((char*)pExpr->token.z);
          memcpy(pExpr, pDup, sizeof(*pExpr));







|



>
>
>
>
>
>
|







1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
    ** Note that the expression in the result set should have already been
    ** resolved by the time the WHERE clause is resolved.
    */
    if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
      for(j=0; j<pEList->nExpr; j++){
        char *zAs = pEList->a[j].zName;
        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
          Expr *pDup, *pOrig;
          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
          assert( pExpr->pList==0 );
          assert( pExpr->pSelect==0 );
          pOrig = pEList->a[j].pExpr;
          if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
            sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
            sqliteFree(zCol);
            return 2;
          }
          pDup = sqlite3ExprDup(pOrig);
          if( pExpr->flags & EP_ExpCollate ){
            pDup->pColl = pExpr->pColl;
            pDup->flags |= EP_ExpCollate;
          }
          if( pExpr->span.dyn ) sqliteFree((char*)pExpr->span.z);
          if( pExpr->token.dyn ) sqliteFree((char*)pExpr->token.z);
          memcpy(pExpr, pDup, sizeof(*pExpr));
Changes to test/select1.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.53 2007/04/13 16:06:34 drh Exp $

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

# Try to select on a non-existant table.
#
do_test select1-1.1 {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.54 2007/07/23 22:51:15 drh Exp $

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

# Try to select on a non-existant table.
#
do_test select1-1.1 {
221
222
223
224
225
226
227

























228
229
230
231
232
233
234
  lappend v $msg
} {0 44}
do_test select1-2.20 {
  set v [catch {execsql {SELECT SUM(min(f1)) FROM test1}} msg]
  lappend v $msg
} {1 {misuse of aggregate function min()}}


























# WHERE clause expressions
#
do_test select1-3.1 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<11}} msg]
  lappend v $msg
} {0 {}}
do_test select1-3.2 {







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







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  lappend v $msg
} {0 44}
do_test select1-2.20 {
  set v [catch {execsql {SELECT SUM(min(f1)) FROM test1}} msg]
  lappend v $msg
} {1 {misuse of aggregate function min()}}

# Ticket #2526
#
do_test select1-2.21 {
  catchsql {
     SELECT min(f1) AS m FROM test1 GROUP BY f1 HAVING max(m+5)<10
  }
} {1 {misuse of aliased aggregate m}}
do_test select1-2.22 {
  catchsql {
     SELECT coalesce(min(f1)+5,11) AS m FROM test1
      GROUP BY f1
     HAVING max(m+5)<10
  }
} {1 {misuse of aliased aggregate m}}
do_test select1-2.23 {
  execsql {
    CREATE TABLE tkt2526(a,b,c PRIMARY KEY);
    INSERT INTO tkt2526 VALUES('x','y',NULL);
    INSERT INTO tkt2526 VALUES('x','z',NULL);
  }
  catchsql {
    SELECT count(a) AS cn FROM tkt2526 GROUP BY a HAVING cn<max(cn)
  }
} {1 {misuse of aliased aggregate cn}}

# WHERE clause expressions
#
do_test select1-3.1 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<11}} msg]
  lappend v $msg
} {0 {}}
do_test select1-3.2 {