Min() and max() ignore NULL values. Ticket #800. (CVS 1803)
FossilOrigin-Name: 223521c04e8ad39e06fee455f7dbb31ace2d3800
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
C Fix\sfor\sticket\s#812\sin\sthe\s2.8\sbranch.\s(CVS\s1801)
|
||||
D 2004-07-17T21:59:18
|
||||
C Min()\sand\smax()\signore\sNULL\svalues.\s\sTicket\s#800.\s(CVS\s1803)
|
||||
D 2004-07-18T21:14:05
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@@ -32,7 +32,7 @@ F src/date.c f055419d602bde622c70f831350b6b52f2235de0
|
||||
F src/delete.c 82001c74882319f94dab5f6b92a27311b31092ae
|
||||
F src/encode.c fc8c51f0b61bc803ccdec092e130bebe762b0a2f
|
||||
F src/expr.c 8c3f5603c3e98b1c146d18076ba3e82cdbb59c11
|
||||
F src/func.c 522d58abf2ec9f93fe3aa08b12611aede570d125
|
||||
F src/func.c 5bd2ce383d29dd6db0e8102847ac2cf02f157fd1
|
||||
F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e
|
||||
F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7
|
||||
F src/insert.c c0485ee2d1b99322894e2d1e0b576fd05ed75616
|
||||
@@ -46,7 +46,7 @@ F src/parse.y 023720cb8c3bef74e51738bca78335d0dc6d2cfd
|
||||
F src/pragma.c f9c157b0591419d2d3407dac90222020d2a6d822
|
||||
F src/printf.c 378ec63d9303993eef24814a56a9fc7260aacbea
|
||||
F src/random.c 775913e0b7fbd6295d21f12a7bd35b46387c44b2
|
||||
F src/select.c 3833e2b64cc6d249385ee44e13bf49c9ae5b903d
|
||||
F src/select.c b8fe5c69d414af1a831593e41439f93e793874dc
|
||||
F src/shell.c 920af040d3a33ea8919c82cee45b424ad841cee0
|
||||
F src/sqlite.h.in 35bec264dfb4965bbfeb7e75221f8658f210c30d
|
||||
F src/sqliteInt.h 3e9203f16d12baf3a364fae9d64903d813651abd
|
||||
@@ -88,7 +88,7 @@ F test/delete.test 92256384f1801760180ded129f7427884cf28886
|
||||
F test/expr.test ad985242e140f87eeef329d98257b8369a2066dc
|
||||
F test/fkey1.test d65c824459916249bee501532d6154ddab0b5db7
|
||||
F test/format3.test 149cc166c97923fa60def047e90dd3fb32bba916
|
||||
F test/func.test cf6434042bf14dcfa124ce2835b049018248e9f6
|
||||
F test/func.test 56b12001d4d8239c6af2864e3d64916cf5dad711
|
||||
F test/hook.test 1a67ce0cd64a6455d016962542f2822458dccc49
|
||||
F test/in.test 0de39b02ceeca90993b096822fb5a884661c5b47
|
||||
F test/index.test 9295deefbdb6dedbe01be8905f0c448fe5bd4079
|
||||
@@ -107,13 +107,13 @@ F test/main.test 6a851b5992c4881a725a3d9647e629199df8de9d
|
||||
F test/malloc.test 2cfcffb7c858640e01e6520ee1cd54ca57d98e80
|
||||
F test/memdb.test 6ece25c7c0e6500199d3662607a3edca081abb2a
|
||||
F test/memleak.test 4d5d374c8ea1fc5ac634aed58cac1047848ce65e
|
||||
F test/minmax.test db8cd0e865682143dca77447d944fb25685e1cd3
|
||||
F test/minmax.test 9dc011a23b897718004b38f4f99e0171f9d5a3fe
|
||||
F test/misc1.test 0b98d493b0cf55cb5f53e1f3df8107c166eecb5a
|
||||
F test/misc2.test 10c2ce26407d37411b96273e552d5095393732be
|
||||
F test/misc3.test 3b5e369514a3ba3f919fb7eafa7d027440b5079e
|
||||
F test/misuse.test 1095f26d1aed406c65e1d2eba651c4bb7c38cbff
|
||||
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
|
||||
F test/null.test b5c066aad5f6a948b9bf372b289c28faffe174dc
|
||||
F test/null.test 675e6823d72d4866d2aca6bf5b7259c9cd713703
|
||||
F test/pager.test 331519008889d45f6df6697395e5bce6ee602fd9
|
||||
F test/pragma.test 24a3f7a697b45cb90d664ebce5566bec7ac41571
|
||||
F test/printf.test 46b3d07d59d871d0831b4a657f6dfcafe0574850
|
||||
@@ -121,7 +121,7 @@ F test/progress.test 701b6115c2613128ececdfe1398a1bd0e1a4cfb3 x
|
||||
F test/quick.test 5a6bccf5c02f16841a79fbac7409a02138880c10
|
||||
F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d
|
||||
F test/rowid.test 77f7e8c7ca626a15ff91a536595b695cfce7c845
|
||||
F test/select1.test e40a88c85f98fb87f60db1abefae0bab7264c9a3
|
||||
F test/select1.test ccace97d8f63d3827ec0e2f8fd33328d0d72bf23
|
||||
F test/select2.test aceea74fd895b9d007512f72499db589735bd8e4
|
||||
F test/select3.test 445a1a3dde4e2fd32541b311f55da5e2f8079d76
|
||||
F test/select4.test e7e9a32fa745246cb99fadbeb63af4843a17925b
|
||||
@@ -189,7 +189,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P 41526d098dcae6def4940cd464d0e1e673c6abb5
|
||||
R dc7d58b1f667e10493476b8cb056afde
|
||||
P ea364dffc7dfe7533d6916d63db0a79181440e64
|
||||
R 8bd46754e3600088dd9144cc11814695
|
||||
U drh
|
||||
Z 05e8ac77c8d502f50a18d54914bc52cb
|
||||
Z 90af30adbb2fcd99b6ec0617557df19e
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
ea364dffc7dfe7533d6916d63db0a79181440e64
|
||||
223521c04e8ad39e06fee455f7dbb31ace2d3800
|
||||
+4
-11
@@ -16,7 +16,7 @@
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: func.c,v 1.43.2.1 2004/06/23 21:16:52 drh Exp $
|
||||
** $Id: func.c,v 1.43.2.2 2004/07/18 21:14:05 drh Exp $
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
@@ -517,6 +517,7 @@ static void minmaxStep(sqlite_func *context, int argc, const char **argv){
|
||||
int mask; /* 0 for min() or 0xffffffff for max() */
|
||||
|
||||
assert( argc==2 );
|
||||
if( argv[0]==0 ) return; /* Ignore NULL values */
|
||||
if( argv[1][0]=='n' ){
|
||||
xCompare = sqliteCompare;
|
||||
}else{
|
||||
@@ -526,17 +527,9 @@ static void minmaxStep(sqlite_func *context, int argc, const char **argv){
|
||||
assert( mask==0 || mask==-1 );
|
||||
p = sqlite_aggregate_context(context, sizeof(*p));
|
||||
if( p==0 || argc<1 ) return;
|
||||
if( mask==0 && p->zBuf[0]>=2 ) return;
|
||||
if( argv[0]==0 ){
|
||||
if( mask==0 ){
|
||||
p->zBuf[0] |= 2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
assert( p->zBuf[0]<2 );
|
||||
if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){
|
||||
int len;
|
||||
if( p->zBuf[0]!=0 ){
|
||||
if( p->zBuf[0] ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
len = strlen(argv[0]);
|
||||
@@ -557,7 +550,7 @@ static void minMaxFinalize(sqlite_func *context){
|
||||
if( p && p->z && p->zBuf[0]<2 ){
|
||||
sqlite_set_result_string(context, p->z, strlen(p->z));
|
||||
}
|
||||
if( p && (p->zBuf[0]&1)!=0 ){
|
||||
if( p && p->zBuf[0] ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.161 2004/03/13 14:00:36 drh Exp $
|
||||
** $Id: select.c,v 1.161.2.1 2004/07/18 21:14:05 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -1916,6 +1916,12 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
}else{
|
||||
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
|
||||
sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
|
||||
if( seekOp==OP_Rewind ){
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_MakeKey, 1, 0);
|
||||
sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
|
||||
seekOp = OP_MoveTo;
|
||||
}
|
||||
sqliteVdbeAddOp(v, seekOp, base+1, 0);
|
||||
sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
|
||||
sqliteVdbeAddOp(v, OP_Close, base+1, 0);
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing built-in functions.
|
||||
#
|
||||
# $Id: func.test,v 1.16.2.1 2004/06/23 21:16:52 drh Exp $
|
||||
# $Id: func.test,v 1.16.2.2 2004/07/18 21:14:05 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -252,7 +252,7 @@ do_test func-8.1 {
|
||||
execsql {
|
||||
SELECT sum(a), count(a), round(avg(a),2), min(a), max(a), count(*) FROM t2;
|
||||
}
|
||||
} {68236 3 22745.33 {} 67890 5}
|
||||
} {68236 3 22745.33 1 67890 5}
|
||||
do_test func-8.2 {
|
||||
execsql {
|
||||
SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t2;
|
||||
@@ -263,7 +263,7 @@ do_test func-8.3 {
|
||||
CREATE TEMP TABLE t3 AS SELECT a FROM t2 ORDER BY a DESC;
|
||||
SELECT min('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
|
||||
}
|
||||
} {{}}
|
||||
} {z+1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP}
|
||||
do_test func-8.4 {
|
||||
execsql {
|
||||
SELECT max('z+'||a||'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP') FROM t3;
|
||||
|
||||
+58
-8
@@ -13,7 +13,7 @@
|
||||
# aggregate min() and max() functions and which are handled as
|
||||
# as a special case.
|
||||
#
|
||||
# $Id: minmax.test,v 1.9.2.1 2004/06/23 21:16:52 drh Exp $
|
||||
# $Id: minmax.test,v 1.9.2.2 2004/07/18 21:14:05 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -68,7 +68,7 @@ do_test minmax-1.5 {
|
||||
} {1}
|
||||
do_test minmax-1.6 {
|
||||
set sqlite_search_count
|
||||
} {1}
|
||||
} {2}
|
||||
do_test minmax-1.7 {
|
||||
set sqlite_search_count 0
|
||||
execsql {SELECT max(x) FROM t1}
|
||||
@@ -127,7 +127,7 @@ do_test minmax-4.1 {
|
||||
SELECT coalesce(min(x+0),-1), coalesce(max(x+0),-1) FROM
|
||||
(SELECT * FROM t1 UNION SELECT NULL as 'x', NULL as 'y')
|
||||
}
|
||||
} {-1 20}
|
||||
} {1 20}
|
||||
do_test minmax-4.2 {
|
||||
execsql {
|
||||
SELECT y, sum(x) FROM
|
||||
@@ -276,9 +276,8 @@ do_test minmax-9.2 {
|
||||
}
|
||||
} {{}}
|
||||
|
||||
# If there is a NULL in an aggregate max(), ignore it. If a NULL
|
||||
# occurs in an aggregate min(), then the result will be NULL because
|
||||
# NULL compares less than all other values.
|
||||
# If there is a NULL in an aggregate max() or min(), ignore it. An
|
||||
# aggregate min() or max() will only return NULL if all values are NULL.
|
||||
#
|
||||
do_test minmax-10.1 {
|
||||
execsql {
|
||||
@@ -288,7 +287,7 @@ do_test minmax-10.1 {
|
||||
INSERT INTO t6 VALUES(NULL);
|
||||
SELECT coalesce(min(x),-1) FROM t6;
|
||||
}
|
||||
} {-1}
|
||||
} {1}
|
||||
do_test minmax-10.2 {
|
||||
execsql {
|
||||
SELECT max(x) FROM t6;
|
||||
@@ -299,11 +298,62 @@ do_test minmax-10.3 {
|
||||
CREATE INDEX i6 ON t6(x);
|
||||
SELECT coalesce(min(x),-1) FROM t6;
|
||||
}
|
||||
} {-1}
|
||||
} {1}
|
||||
do_test minmax-10.4 {
|
||||
execsql {
|
||||
SELECT max(x) FROM t6;
|
||||
}
|
||||
} {2}
|
||||
do_test minmax-10.5 {
|
||||
execsql {
|
||||
DELETE FROM t6 WHERE x NOT NULL;
|
||||
SELECT count(*) FROM t6;
|
||||
}
|
||||
} 1
|
||||
do_test minmax-10.6 {
|
||||
execsql {
|
||||
SELECT count(x) FROM t6;
|
||||
}
|
||||
} 0
|
||||
do_test minmax-10.7 {
|
||||
execsql {
|
||||
SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
|
||||
}
|
||||
} {{} {}}
|
||||
do_test minmax-10.8 {
|
||||
execsql {
|
||||
SELECT min(x), max(x) FROM t6;
|
||||
}
|
||||
} {{} {}}
|
||||
do_test minmax-10.9 {
|
||||
execsql {
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
INSERT INTO t6 SELECT * FROM t6;
|
||||
SELECT count(*) FROM t6;
|
||||
}
|
||||
} 1024
|
||||
do_test minmax-10.10 {
|
||||
execsql {
|
||||
SELECT count(x) FROM t6;
|
||||
}
|
||||
} 0
|
||||
do_test minmax-10.11 {
|
||||
execsql {
|
||||
SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6);
|
||||
}
|
||||
} {{} {}}
|
||||
do_test minmax-10.12 {
|
||||
execsql {
|
||||
SELECT min(x), max(x) FROM t6;
|
||||
}
|
||||
} {{} {}}
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ do_test null-3.1 {
|
||||
select count(*), count(b), count(c), sum(b), sum(c),
|
||||
avg(b), avg(c), min(b), max(b) from t1;
|
||||
}
|
||||
} {7 4 6 2 3 0.5 0.5 {} 1}
|
||||
} {7 4 6 2 3 0.5 0.5 0 1}
|
||||
|
||||
# Check to see how WHERE clauses handle NULL values. A NULL value
|
||||
# is the same as UNKNOWN. The WHERE clause should only select those
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the SELECT statement.
|
||||
#
|
||||
# $Id: select1.test,v 1.30.2.1 2004/06/23 21:16:52 drh Exp $
|
||||
# $Id: select1.test,v 1.30.2.2 2004/07/18 21:14:05 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -159,7 +159,7 @@ do_test select1-2.8 {
|
||||
} {0 {11 33}}
|
||||
do_test select1-2.8.1 {
|
||||
execsql {SELECT coalesce(min(a),'xyzzy') FROM t3}
|
||||
} {xyzzy}
|
||||
} {11}
|
||||
do_test select1-2.8.2 {
|
||||
execsql {SELECT min(coalesce(a,'xyzzy')) FROM t3}
|
||||
} {11}
|
||||
|
||||
Reference in New Issue
Block a user