Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1608,11 +1608,11 @@ UNUSED_PARAMETER(NotUsed); pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); if( !pBest ) return; - if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ + if( sqlite3_value_type(pArg)==SQLITE_NULL ){ if( pBest->flags ) sqlite3SkipAccumulatorLoad(context); }else if( pBest->flags ){ int max; int cmp; CollSeq *pColl = sqlite3GetFuncCollSeq(context); @@ -1634,19 +1634,25 @@ }else{ pBest->db = sqlite3_context_db_handle(context); sqlite3VdbeMemCopy(pBest, pArg); } } -static void minMaxFinalize(sqlite3_context *context){ +static void minMaxValueFinalize(sqlite3_context *context, int bValue){ sqlite3_value *pRes; pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); if( pRes ){ if( pRes->flags ){ sqlite3_result_value(context, pRes); } - sqlite3VdbeMemRelease(pRes); + if( bValue==0 ) sqlite3VdbeMemRelease(pRes); } +} +static void minMaxValue(sqlite3_context *context){ + return minMaxValueFinalize(context, 1); +} +static void minMaxFinalize(sqlite3_context *context){ + return minMaxValueFinalize(context, 0); } /* ** group_concat(EXPR, ?SEPARATOR?) */ @@ -1881,15 +1887,15 @@ FUNCTION(rtrim, 2, 2, 0, trimFunc ), FUNCTION(trim, 1, 3, 0, trimFunc ), FUNCTION(trim, 2, 3, 0, trimFunc ), FUNCTION(min, -1, 0, 1, minmaxFunc ), FUNCTION(min, 0, 0, 1, 0 ), - AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize, + WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, SQLITE_FUNC_MINMAX ), FUNCTION(max, -1, 1, 1, minmaxFunc ), FUNCTION(max, 0, 1, 1, 0 ), - AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize, + WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, SQLITE_FUNC_MINMAX ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ), @@ -1916,19 +1922,19 @@ VFUNCTION(total_changes, 0, 0, 0, total_changes ), FUNCTION(replace, 3, 0, 0, replaceFunc ), FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), - WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse), - WAGGREGATE(total, 1,0,0, sumStep, totalFinalize, totalFinalize, sumInverse), - WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse), + WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0), + WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0), + WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0), AGGREGATE2(count, 0,0,0, countStep, countFinalize, SQLITE_FUNC_COUNT ), - WAGGREGATE(count, 1,0,0, countStep, countFinalize, 0, 0 ), + WAGGREGATE(count, 1,0,0, countStep, countFinalize, 0, 0, 0 ), WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep, - groupConcatFinalize, groupConcatValue, groupConcatInverse), + groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep, - groupConcatFinalize, groupConcatValue, groupConcatInverse), + groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), #ifdef SQLITE_CASE_SENSITIVE_LIKE LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -1760,12 +1760,12 @@ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}} #define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}} -#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse) \ - {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ +#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}} /* ** All current savepoints are stored in a linked list starting at ** sqlite3.pSavepoint. The first element in the list is the most recently Index: test/window1.test ================================================================== --- test/window1.test +++ test/window1.test @@ -267,11 +267,10 @@ do_execsql_test 7.3 { SELECT row_number() OVER (ORDER BY x) FROM t1 } {1 2 3 4 5} -breakpoint do_execsql_test 7.4 { SELECT row_number() OVER win, lead(x) OVER win FROM t1 @@ -315,9 +314,43 @@ } {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6} do_execsql_test 8.2.2 { SELECT * FROM v2 } {1 1 1 3 1 2 6 1 3 10 1 4 15 1 5 21 1 6} +#------------------------------------------------------------------------- +# Attempt to use a window function in a trigger. +# +do_execsql_test 9.0 { + CREATE TABLE t4(x, y); + INSERT INTO t4 VALUES(1, 'g'); + INSERT INTO t4 VALUES(2, 'i'); + INSERT INTO t4 VALUES(3, 'l'); + INSERT INTO t4 VALUES(4, 'g'); + INSERT INTO t4 VALUES(5, 'a'); + + CREATE TABLE t5(x, y, m); + CREATE TRIGGER t4i AFTER INSERT ON t4 BEGIN + DELETE FROM t5; + INSERT INTO t5 + SELECT x, y, max(y) OVER xyz FROM t4 + WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x); + END; +} + +do_execsql_test 9.1.1 { + SELECT x, y, max(y) OVER xyz FROM t4 + WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x) ORDER BY 1 +} {1 g g 2 i i 3 l l 4 g i 5 a l} + +do_execsql_test 9.1.2 { + INSERT INTO t4 VALUES(6, 'm'); + SELECT x, y, max(y) OVER xyz FROM t4 + WINDOW xyz AS (PARTITION BY (x%2) ORDER BY x) ORDER BY 1 +} {1 g g 2 i i 3 l l 4 g i 5 a l 6 m m} + +do_execsql_test 9.1.3 { + SELECT * FROM t5 ORDER BY 1 +} {1 g g 2 i i 3 l l 4 g i 5 a l 6 m m} finish_test