Fix a problem with window functions min() and max() when used with a FILTER clause. Forum post [forum:/forumpost/e9126d554a | e9126d554a].
FossilOrigin-Name: d15fb0f75e64bbfdb8df0c0d0358aafbbd7d5e2048df676dafe1abd5e9917f2a
This commit is contained in:
parent
f154cef8f2
commit
c87d7bede0
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Document\sthe\sif\sblock\sat\sthe\send\sof\ssqlite-check-tcl.
|
||||
D 2024-11-14T12:23:05.149
|
||||
C Fix\sa\sproblem\swith\swindow\sfunctions\smin()\sand\smax()\swhen\sused\swith\sa\sFILTER\sclause.\sForum\spost\s[forum:/forumpost/e9126d554a\s|\se9126d554a].
|
||||
D 2024-11-14T14:38:16.785
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
|
||||
@ -863,7 +863,7 @@ F src/where.c 4de9e7ca5f49e4a21c1d733e2b2fbbc8b62b1a157a58a562c569da84cfcb005b
|
||||
F src/whereInt.h 1e36ec50392f7cc3d93d1152d4338064cd522b87156a0739388b7e273735f0ca
|
||||
F src/wherecode.c 81b9af89f4f85c8097d0da6a31499f015eabc4d3584963d30ba7b7b782e26514
|
||||
F src/whereexpr.c 0f93a29cabd3a338d09a1f5c6770620a1ac51ec1157f3229502a7e7767c60b6f
|
||||
F src/window.c 499d48f315a09242dc68f2fac635ed27dcf6bbb0d9ab9084857898c64489e975
|
||||
F src/window.c 6c386af5972a58f9a9847bba9d7ca70c4c682391ab8478d94a6e046b22a0dbb3
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
|
||||
F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
|
||||
@ -2067,9 +2067,9 @@ F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652
|
||||
F test/window6.test 311de885bd7e453134fa6747680bfb4a1be87c91720bf58703db945891e7d30b
|
||||
F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f
|
||||
F test/window7.test 1d31276961ae7801edc72173edaf7593e3cbc79c06d1f1f09e20d8418af403cd
|
||||
F test/window8.tcl 5e02e41d9d9a80f597063aed1a381eb19d1d0ef677a4f0df352c5365cf23f79c
|
||||
F test/window8.test 4ab16817414af0c904abe2ebdf88eb6c2b00058b84f9748c6174ff11fc45f1ed
|
||||
F test/window9.test 349c71eab4288a1ffc19e2f65872ec2c37e6cf8a1dda2ad300364b7450ae4836
|
||||
F test/window8.tcl c57364e64d816f6e26df60437e1202e2c1031c7b818a1a67535d1006862a026a
|
||||
F test/window8.test 3d931e58802b8ab8063da00f0cf30aa3351640238a952c0efb5a129e2349a4bb
|
||||
F test/window9.test 7b98a7916dd87763ea35f56ea023e3b29e99744582204ccf2937a3bac411cd4d
|
||||
F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be
|
||||
F test/windowB.test aad7c31739999f68a98a813cfd78390918fc70f56d2d925317a1523cab548ecf
|
||||
F test/windowC.test 6fd75f5bb2f1343d34e470e36e68f0ff638d8a42f6aa7d99471261b31a0d42f2
|
||||
@ -2199,8 +2199,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 6940caa192fa0cc84dbd24191a940aec96c304c68e60ead8f239e85d093e01e0
|
||||
R a630c6439d1fbf64015d5e1115d0f02b
|
||||
U stephan
|
||||
Z 28b305c9589a667cd87e3823cca8351c
|
||||
P 6bfd09408b9a51c0cbdb28f901a79c9774da755294d7eb67d88e4c42c5652830
|
||||
R 4dbd1e8b72bd923323c250178cad8662
|
||||
U dan
|
||||
Z 283ba5d1ed32af60aeb437d70b951d46
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
6bfd09408b9a51c0cbdb28f901a79c9774da755294d7eb67d88e4c42c5652830
|
||||
d15fb0f75e64bbfdb8df0c0d0358aafbbd7d5e2048df676dafe1abd5e9917f2a
|
||||
|
30
src/window.c
30
src/window.c
@ -1670,6 +1670,7 @@ static void windowAggStep(
|
||||
int regArg;
|
||||
int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin);
|
||||
int i;
|
||||
int addrIf = 0;
|
||||
|
||||
assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED );
|
||||
|
||||
@ -1686,6 +1687,18 @@ static void windowAggStep(
|
||||
}
|
||||
regArg = reg;
|
||||
|
||||
if( pWin->pFilter ){
|
||||
int regTmp;
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
|
||||
assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
|
||||
regTmp = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
|
||||
addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
|
||||
VdbeCoverage(v);
|
||||
sqlite3ReleaseTempReg(pParse, regTmp);
|
||||
}
|
||||
|
||||
if( pMWin->regStartRowid==0
|
||||
&& (pFunc->funcFlags & SQLITE_FUNC_MINMAX)
|
||||
&& (pWin->eStart!=TK_UNBOUNDED)
|
||||
@ -1705,25 +1718,13 @@ static void windowAggStep(
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, addrIsNull);
|
||||
}else if( pWin->regApp ){
|
||||
assert( pWin->pFilter==0 );
|
||||
assert( pFunc->zName==nth_valueName
|
||||
|| pFunc->zName==first_valueName
|
||||
);
|
||||
assert( bInverse==0 || bInverse==1 );
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1);
|
||||
}else if( pFunc->xSFunc!=noopStepFunc ){
|
||||
int addrIf = 0;
|
||||
if( pWin->pFilter ){
|
||||
int regTmp;
|
||||
assert( ExprUseXList(pWin->pOwner) );
|
||||
assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
|
||||
assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
|
||||
regTmp = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
|
||||
addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
|
||||
VdbeCoverage(v);
|
||||
sqlite3ReleaseTempReg(pParse, regTmp);
|
||||
}
|
||||
|
||||
if( pWin->bExprArgs ){
|
||||
int iOp = sqlite3VdbeCurrentAddr(v);
|
||||
int iEnd;
|
||||
@ -1754,8 +1755,9 @@ static void windowAggStep(
|
||||
if( pWin->bExprArgs ){
|
||||
sqlite3ReleaseTempRange(pParse, regArg, nArg);
|
||||
}
|
||||
if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
|
||||
}
|
||||
|
||||
if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -489,6 +489,68 @@ execsql_test 9.2 {
|
||||
FROM t1
|
||||
}
|
||||
|
||||
==========
|
||||
|
||||
execsql_test 10.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER, b INTEGER);
|
||||
INSERT INTO t1 VALUES (10, 1),
|
||||
(20, -1),
|
||||
(5, 2),
|
||||
(15, 0),
|
||||
(25, 3);
|
||||
}
|
||||
|
||||
execsql_test 10.1 {
|
||||
SELECT
|
||||
a, b, MIN(a) FILTER(WHERE b > 0) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING);
|
||||
}
|
||||
|
||||
execsql_test 10.2 {
|
||||
SELECT
|
||||
a, b, MIN(a) FILTER(WHERE b > 0) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS ();
|
||||
}
|
||||
|
||||
execsql_test 10.3 {
|
||||
SELECT
|
||||
a, b, MIN(a) FILTER(WHERE b > 0) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a);
|
||||
}
|
||||
|
||||
execsql_test 10.4 {
|
||||
SELECT
|
||||
a, b, MIN(a) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING);
|
||||
}
|
||||
|
||||
==========
|
||||
|
||||
execsql_test 11.0 {
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(a INTEGER, b INTEGER);
|
||||
INSERT INTO t2 VALUES(1, 12);
|
||||
INSERT INTO t2 VALUES(2, 10);
|
||||
INSERT INTO t2 VALUES(3, 15);
|
||||
INSERT INTO t2 VALUES(4, 22);
|
||||
INSERT INTO t2 VALUES(5, 1);
|
||||
INSERT INTO t2 VALUES(6, 4);
|
||||
INSERT INTO t2 VALUES(7, 7);
|
||||
INSERT INTO t2 VALUES(8, 6);
|
||||
INSERT INTO t2 VALUES(9, 22);
|
||||
INSERT INTO t2 VALUES(10, 2);
|
||||
}
|
||||
|
||||
execsql_test 11.1 {
|
||||
SELECT a, min(b) FILTER (WHERE a%2 != 0) OVER win
|
||||
FROM t2
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING);
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -6540,4 +6540,67 @@ do_execsql_test 9.2 {
|
||||
FROM t1
|
||||
} {}
|
||||
|
||||
#==========================================================================
|
||||
|
||||
do_execsql_test 10.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER, b INTEGER);
|
||||
INSERT INTO t1 VALUES (10, 1),
|
||||
(20, -1),
|
||||
(5, 2),
|
||||
(15, 0),
|
||||
(25, 3);
|
||||
} {}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
SELECT
|
||||
a, b, MIN(a) FILTER(WHERE b > 0) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING);
|
||||
} {5 2 5 10 1 5 15 0 10 20 -1 25 25 3 25}
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
SELECT
|
||||
a, b, MIN(a) FILTER(WHERE b > 0) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS ();
|
||||
} {10 1 5 20 -1 5 5 2 5 15 0 5 25 3 5}
|
||||
|
||||
do_execsql_test 10.3 {
|
||||
SELECT
|
||||
a, b, MIN(a) FILTER(WHERE b > 0) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a);
|
||||
} {5 2 5 10 1 5 15 0 5 20 -1 5 25 3 5}
|
||||
|
||||
do_execsql_test 10.4 {
|
||||
SELECT
|
||||
a, b, MIN(a) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING);
|
||||
} {5 2 5 10 1 5 15 0 10 20 -1 15 25 3 20}
|
||||
|
||||
#==========================================================================
|
||||
|
||||
do_execsql_test 11.0 {
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(a INTEGER, b INTEGER);
|
||||
INSERT INTO t2 VALUES(1, 12);
|
||||
INSERT INTO t2 VALUES(2, 10);
|
||||
INSERT INTO t2 VALUES(3, 15);
|
||||
INSERT INTO t2 VALUES(4, 22);
|
||||
INSERT INTO t2 VALUES(5, 1);
|
||||
INSERT INTO t2 VALUES(6, 4);
|
||||
INSERT INTO t2 VALUES(7, 7);
|
||||
INSERT INTO t2 VALUES(8, 6);
|
||||
INSERT INTO t2 VALUES(9, 22);
|
||||
INSERT INTO t2 VALUES(10, 2);
|
||||
} {}
|
||||
|
||||
do_execsql_test 11.1 {
|
||||
SELECT a, min(b) FILTER (WHERE a%2 != 0) OVER win
|
||||
FROM t2
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING);
|
||||
} {1 12 2 12 3 1 4 1 5 1 6 1 7 1 8 7 9 7 10 22}
|
||||
|
||||
finish_test
|
||||
|
@ -282,4 +282,62 @@ do_catchsql_test 9.1 {
|
||||
FROM t1
|
||||
} {1 {frame ending offset must be a non-negative number}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 10.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 'a');
|
||||
INSERT INTO t1 VALUES(2, 'b');
|
||||
INSERT INTO t1 VALUES(3, 'c');
|
||||
INSERT INTO t1 VALUES(4, 'd');
|
||||
INSERT INTO t1 VALUES(5, 'e');
|
||||
INSERT INTO t1 VALUES(6, 'f');
|
||||
}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
SELECT a, min(b) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 2 PRECEDING AND 1 FOLLOWING)
|
||||
} {
|
||||
1 a
|
||||
2 a
|
||||
3 a
|
||||
4 b
|
||||
5 c
|
||||
6 d
|
||||
}
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
SELECT a, min(b) FILTER (WHERE a%2) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 2 PRECEDING AND 1 FOLLOWING)
|
||||
} {
|
||||
1 a
|
||||
2 a
|
||||
3 a
|
||||
4 c
|
||||
5 c
|
||||
6 e
|
||||
}
|
||||
|
||||
do_execsql_test 10.3 {
|
||||
SELECT a, min(b) FILTER (WHERE (a%2)=0) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 2 PRECEDING AND 1 FOLLOWING)
|
||||
} {
|
||||
1 b
|
||||
2 b
|
||||
3 b
|
||||
4 b
|
||||
5 d
|
||||
6 d
|
||||
}
|
||||
|
||||
do_catchsql_test 10.4 {
|
||||
SELECT a, nth_value(b, 1) FILTER (WHERE (a%2)=0) OVER win
|
||||
FROM t1
|
||||
WINDOW win AS (ORDER BY a ROWS BETWEEN 2 PRECEDING AND 1 FOLLOWING)
|
||||
} {1 {FILTER clause may only be used with aggregate window functions}}
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user