Fix handling of window frames containing negative number of rows. e.g. "ROWS x
PRECEDING AND y PRECEDING" where (x<y). FossilOrigin-Name: b6d9c7eda853420ae46a05bd432711e8bf9ebaa448c7d90ccfc0bcc338a87706
This commit is contained in:
parent
72a9f0233b
commit
26522d1c45
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\stypon\sin\smain.mk.
|
||||
D 2018-06-11T11:19:35.512
|
||||
C Fix\shandling\sof\swindow\sframes\scontaining\snegative\snumber\sof\srows.\se.g.\s"ROWS\sx\nPRECEDING\sAND\sy\sPRECEDING"\swhere\s(x<y).
|
||||
D 2018-06-11T18:16:51.622
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 498b77b89a8cb42f2ee20fcd6317f279a45c0d6ff40d27825f94b69884c09bbe
|
||||
@ -493,7 +493,7 @@ F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
|
||||
F src/prepare.c e966ecc97c3671ff0e96227c8c877b83f2d33ea371ee190bbf1698b36b5605c0
|
||||
F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c da9b85ec0e1a05384134cece5747a90b8da1fc5750f4705c7812d2294ca20cec
|
||||
F src/resolve.c 03791a761ede3a2cd71dffb92aa760d728122dbbdbf26010813da3edd01cb431
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c 0b0ce29bd7b8a7232e6f7602ddb447caa954a1fc476ff5e23ce1e5aaa6a0e0ed
|
||||
F src/shell.c.in 4d0ddf10c403710d241bf920163dcf032c21119aebb61e70840942c0eafecdf9
|
||||
@ -583,7 +583,7 @@ F src/where.c fe1a6f97c12cc9472ccce86166ba3f827cf61d6ae770c036a6396b63863baac4
|
||||
F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
|
||||
F src/wherecode.c 3317f2b083a66d3e65a03edf316ade4ccb0a99c9956273282ebb579b95d4ba96
|
||||
F src/whereexpr.c 6f022d6cc9daf56495f191b199352f783aff5cf268ba136b4d8cea3fb62d8c7d
|
||||
F src/window.c 72c08229b59a447db5ffb8e87680105549465df502092e0e24f9451e6b082031
|
||||
F src/window.c 0519e5a03ebbcf22ab692410d4b25f28cc2d0e4e37e6288ca1eb0820276d67ba
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@ -1617,13 +1617,13 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/window1.test 6c648f3fa79b29ef114c4e73ae8adefae70e4d3aae4cc36a3318ab237b64e9c5
|
||||
F test/window1.test 94c626fe8d9eced3e3d5ef0a2106209904daba77d549aafde09eba1db8e98c3e
|
||||
F test/window2.tcl 0983de5eade5eeda49469244799d5331bfe3199fca3f6c6d2a836aa08f4fba1b
|
||||
F test/window2.test 79747b2edde4ad424e0752b27529aedc86e91f3d8d88846fa17ff0cb67f65086
|
||||
F test/window3.tcl 654d61d73e10db089b22514d498bb23ec310f720c0f4b5f69f67fda83d672048
|
||||
F test/window3.test 41727668ee31d2ba50f78efcb5bf1bda2c5cffd889aa65243511004669d1ac25
|
||||
F test/window4.tcl e459eb2fe561d7731008a80d071e2d995c3554706de764c9f456f54357e70316
|
||||
F test/window4.test 207ab5e54ba0fec5e1157d136489b615a0e88dc8f9fb81cd77e11f20d2ddd72e
|
||||
F test/window4.tcl bfea0c4f65dff22568032ae3a0cf3be0910c4160314e5ac3f895eca11b068cb1
|
||||
F test/window4.test ca7c63f27604a0eb432cab1673da75498c69d66b9093ef80a5d4c7287b95906b
|
||||
F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
|
||||
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
|
||||
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
|
||||
@ -1740,7 +1740,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 16db73842ade5eb0fe02f257b91d1c7b41d830d3f17f8638b8fbaed309d9a852
|
||||
R 96748b81a5c5c17387af91f1f0c0dfa1
|
||||
P e74f86f271d6ab1ecd17c1ee63ab2aa0885ca56624be7382872f04d46c48ed86
|
||||
R a123bfa3a94ae6460114239fab9e1170
|
||||
U dan
|
||||
Z 83b8eb197a3e3709547b1acd87361cc8
|
||||
Z 6b49a0a9a9265834682b1c9c02ee1753
|
||||
|
@ -1 +1 @@
|
||||
e74f86f271d6ab1ecd17c1ee63ab2aa0885ca56624be7382872f04d46c48ed86
|
||||
b6d9c7eda853420ae46a05bd432711e8bf9ebaa448c7d90ccfc0bcc338a87706
|
@ -756,11 +756,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
NC_IdxExpr|NC_PartIdx);
|
||||
}
|
||||
}
|
||||
if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|
||||
|| (pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
|
||||
|
||||
if( is_agg==0 && pExpr->pWin ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"%.*s() may not be used as a window function", nId, zId
|
||||
);
|
||||
pNC->nErr++;
|
||||
}else if(
|
||||
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|
||||
|| (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin)
|
||||
|| (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
|
||||
){
|
||||
const char *zType = pExpr->pWin ? "window" : "aggregate";
|
||||
sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
|
||||
const char *zType;
|
||||
if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){
|
||||
zType = "window";
|
||||
}else{
|
||||
zType = "aggregate";
|
||||
}
|
||||
sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()", zType, nId,zId);
|
||||
pNC->nErr++;
|
||||
is_agg = 0;
|
||||
}else if( no_such_func && pParse->db->init.busy==0
|
||||
|
27
src/window.c
27
src/window.c
@ -1,4 +1,5 @@
|
||||
/*
|
||||
** 2018 May 08
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
@ -1258,13 +1259,26 @@ static void windowCodeRowExprStep(
|
||||
|
||||
/* If this is "ROWS <expr1> FOLLOWING AND ROWS <expr2> FOLLOWING", do:
|
||||
**
|
||||
** if( regEnd<regStart ){
|
||||
** // The frame always consists of 0 rows
|
||||
** regStart = regSize;
|
||||
** }
|
||||
** regEnd = regEnd - regStart;
|
||||
*/
|
||||
if( pMWin->pEnd && pMWin->pStart && pMWin->eStart==TK_FOLLOWING ){
|
||||
assert( pMWin->eEnd==TK_FOLLOWING );
|
||||
sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd);
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart);
|
||||
sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd);
|
||||
}
|
||||
|
||||
if( pMWin->pEnd && pMWin->pStart && pMWin->eEnd==TK_PRECEDING ){
|
||||
assert( pMWin->eStart==TK_PRECEDING );
|
||||
sqlite3VdbeAddOp3(v, OP_Le, regStart, sqlite3VdbeCurrentAddr(v)+3, regEnd);
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart);
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, regSize, regEnd);
|
||||
}
|
||||
|
||||
/* Initialize the accumulator register for each window function to NULL */
|
||||
regArg = windowInitAccum(pParse, pMWin);
|
||||
|
||||
@ -1731,6 +1745,14 @@ void sqlite3WindowCodeStep(
|
||||
Window *pMWin = p->pWin;
|
||||
Window *pWin;
|
||||
|
||||
/*
|
||||
** Call windowCodeRowExprStep() for all window modes *except*:
|
||||
**
|
||||
** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
|
||||
** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
|
||||
** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
|
||||
** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
|
||||
*/
|
||||
if( (pMWin->eType==TK_ROWS
|
||||
&& (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy))
|
||||
|| (pMWin->eStart==TK_CURRENT&&pMWin->eEnd==TK_UNBOUNDED&&pMWin->pOrderBy)
|
||||
@ -1739,6 +1761,11 @@ void sqlite3WindowCodeStep(
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Call windowCodeCacheStep() if there is a window function that requires
|
||||
** that the entire partition be cached in a temp table before any rows
|
||||
** are returned.
|
||||
*/
|
||||
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
||||
FuncDef *pFunc = pWin->pFunc;
|
||||
if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE)
|
||||
|
@ -214,9 +214,43 @@ do_execsql_test 6.2 {
|
||||
a 1 1 a 2 2 a 3 3 a 4 4 a 5 5 a 6 6 a 7 7
|
||||
}
|
||||
|
||||
do_catchsql_test 3.5 {
|
||||
do_catchsql_test 6.3 {
|
||||
SELECT x, lag(x) FILTER (WHERE (x%2)=0) OVER w FROM t1
|
||||
WINDOW w AS (ORDER BY x)
|
||||
} {1 {FILTER clause may only be used with aggregate window functions}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Attempt to use a window function as an aggregate. And other errors.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
CREATE TABLE t1(x, y);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
INSERT INTO t1 VALUES(9, 10);
|
||||
}
|
||||
|
||||
do_catchsql_test 7.1.1 {
|
||||
SELECT nth_value(x, 1) FROM t1;
|
||||
} {1 {misuse of window function nth_value()}}
|
||||
do_catchsql_test 7.1.2 {
|
||||
SELECT * FROM t1 WHERE nth_value(x, 1) OVER (ORDER BY y);
|
||||
} {1 {misuse of window function nth_value()}}
|
||||
do_catchsql_test 7.1.3 {
|
||||
SELECT count(*) FROM t1 GROUP BY y HAVING nth_value(x, 1) OVER (ORDER BY y);
|
||||
} {1 {misuse of window function nth_value()}}
|
||||
do_catchsql_test 7.1.4 {
|
||||
SELECT count(*) FROM t1 GROUP BY nth_value(x, 1) OVER (ORDER BY y);
|
||||
} {1 {misuse of window function nth_value()}}
|
||||
do_catchsql_test 7.1.5 {
|
||||
SELECT count(*) FROM t1 LIMIT nth_value(x, 1) OVER (ORDER BY y);
|
||||
} {1 {no such column: x}}
|
||||
do_catchsql_test 7.1.6 {
|
||||
SELECT trim(x) OVER (ORDER BY y) FROM t1;
|
||||
} {1 {trim() may not be used as a window function}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -102,6 +102,32 @@ execsql_test 3.4 {
|
||||
WINDOW w AS (ORDER BY a)
|
||||
}
|
||||
|
||||
execsql_test 3.5.1 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 2 PRECEDING)
|
||||
FROM t5
|
||||
}
|
||||
execsql_test 3.5.2 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
|
||||
FROM t5
|
||||
}
|
||||
execsql_test 3.5.3 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 0 PRECEDING AND 0 PRECEDING)
|
||||
FROM t5
|
||||
}
|
||||
|
||||
execsql_test 3.6.1 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 2 FOLLOWING AND 1 FOLLOWING)
|
||||
FROM t5
|
||||
}
|
||||
execsql_test 3.6.2 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING)
|
||||
FROM t5
|
||||
}
|
||||
execsql_test 3.6.3 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 0 FOLLOWING AND 0 FOLLOWING)
|
||||
FROM t5
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -176,14 +176,39 @@ do_execsql_test 3.3 {
|
||||
ORDER BY a;
|
||||
} {1 1 5 2 2 4 3 3 3 4 4 2 5 5 1}
|
||||
|
||||
explain_i {
|
||||
SELECT a, max(a) FILTER (WHERE (a%2)=0) OVER w FROM t5
|
||||
WINDOW w AS (ORDER BY a)
|
||||
}
|
||||
breakpoint
|
||||
do_execsql_test 3.4 {
|
||||
SELECT a, max(a) FILTER (WHERE (a%2)=0) OVER w FROM t5
|
||||
WINDOW w AS (ORDER BY a)
|
||||
} {1 {} 2 2 3 2 4 4 5 4}
|
||||
|
||||
do_execsql_test 3.5.1 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 2 PRECEDING)
|
||||
FROM t5
|
||||
} {1 {} 2 {} 3 {} 4 {} 5 {}}
|
||||
|
||||
do_execsql_test 3.5.2 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
|
||||
FROM t5
|
||||
} {1 {} 2 one 3 two 4 three 5 four}
|
||||
|
||||
do_execsql_test 3.5.3 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 0 PRECEDING AND 0 PRECEDING)
|
||||
FROM t5
|
||||
} {1 one 2 two 3 three 4 four 5 five}
|
||||
|
||||
do_execsql_test 3.6.1 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 2 FOLLOWING AND 1 FOLLOWING)
|
||||
FROM t5
|
||||
} {1 {} 2 {} 3 {} 4 {} 5 {}}
|
||||
|
||||
do_execsql_test 3.6.2 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING)
|
||||
FROM t5
|
||||
} {1 two 2 three 3 four 4 five 5 {}}
|
||||
|
||||
do_execsql_test 3.6.3 {
|
||||
SELECT a, max(c) OVER (ORDER BY a ROWS BETWEEN 0 FOLLOWING AND 0 FOLLOWING)
|
||||
FROM t5
|
||||
} {1 one 2 two 3 three 4 four 5 five}
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user