From: drh Date: Thu, 12 Jan 2006 22:17:50 +0000 (+0000) Subject: Add support for the TOTAL() aggregate function - works like SUM() except X-Git-Tag: version-3.6.10~3237 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a97fdd3bfc16604e48a505a875f7f8601e810e2c;p=thirdparty%2Fsqlite.git Add support for the TOTAL() aggregate function - works like SUM() except that it returns 0 instead of NULL when presented with an empty list. (CVS 2930) FossilOrigin-Name: a7f528ff3446d50b280fb0b85063879e3ac5751a --- diff --git a/manifest b/manifest index f79e868ab6..af3e0ac7bb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\sboost\sin\ssqlite3VdbeRecordCompare.\s(CVS\s2929) -D 2006-01-12T20:28:35 +C Add\ssupport\sfor\sthe\sTOTAL()\saggregate\sfunction\s-\sworks\slike\sSUM()\sexcept\nthat\sit\sreturns\s0\sinstead\sof\sNULL\swhen\spresented\swith\san\sempty\slist.\s(CVS\s2930) +D 2006-01-12T22:17:50 F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -43,7 +43,7 @@ F src/date.c a927bdbb51296ac398d2f667086a7072c099e5ab F src/delete.c c7bd5708a629585e073ce34cf3b1fcb52c2fef38 F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d F src/expr.c 3b6acdb4e254027fe72ce70054ea6b71c7d423a3 -F src/func.c e013c3b6c607c6a1654f5260eab59f5609a5ce4a +F src/func.c be4c026c1d2401f14c3186611e1131a895a3ca6e F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 F src/insert.c a5595cf8d1d8ba087b676a63f1f7277ea44b5ac1 @@ -202,7 +202,7 @@ F test/misc4.test b043a05dea037cca5989f3ae09552fa16119bc80 F test/misc5.test a27520a0033f2837cda94bfdfb096a25fc4b128d F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33 F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0 -F test/null.test 012fe5455f4fc3102490b4bad373a674e5741fdd +F test/null.test db52272f9628ae9e77ab451cf0fb3871a98c5f00 F test/pager.test 1579e8f07291ae8e24db62ffade5c101c3e76597 F test/pager2.test 49c0f57c7da0b060f0486b85fdd074025caa694e F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4 @@ -319,7 +319,7 @@ F www/fullscanb.gif f7c94cb227f060511f8909e10f570157263e9a25 F www/index-ex1-x-b.gif f9b1d85c3fa2435cf38b15970c7e3aa1edae23a3 F www/index.tcl f84bf390bd272035934639748c89730f3d60dc44 F www/indirect1b1.gif adfca361d2df59e34f9c5cac52a670c2bfc303a1 -F www/lang.tcl 6f81b2726dc350ba5dc0dd6dcddb9e7a307b9976 +F www/lang.tcl b3561af8d85d2d712d43b3604e4aadce9257e4d9 F www/lockingv3.tcl f59b19d6c8920a931f096699d6faaf61c05db55f F www/mingw.tcl d96b451568c5d28545fefe0c80bee3431c73f69c F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf @@ -340,7 +340,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 730ddb0b74ed23c916dabd7ce893bd6bc55f3549 -R 36b85235284a365ef7c4f8a7c8bf02e6 +P 14c423075bcebf42a3f4e24838bc865cfb90afda +R 96aa9577c2fe78f0881f3a139cc6dc0c U drh -Z 308f9bd267f3ff57a7f1fa05f779432c +Z 680a9cdd5661322ac6544d3998d3b8d1 diff --git a/manifest.uuid b/manifest.uuid index 99f52e187d..4034ef219e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -14c423075bcebf42a3f4e24838bc865cfb90afda \ No newline at end of file +a7f528ff3446d50b280fb0b85063879e3ac5751a \ No newline at end of file diff --git a/src/func.c b/src/func.c index 7c16f70beb..4198d61005 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.115 2006/01/09 16:12:05 danielk1977 Exp $ +** $Id: func.c,v 1.116 2006/01/12 22:17:50 drh Exp $ */ #include "sqliteInt.h" #include @@ -823,7 +823,13 @@ struct SumCtx { }; /* -** Routines used to compute the sum or average. +** Routines used to compute the sum, average, and total. +** +** The SUM() function follows the (broken) SQL standard which means +** that it returns NULL if it sums over no inputs. TOTAL returns +** 0.0 in that case. In addition, TOTAL always returns a float where +** SUM might return an integer if it never encounters a floating point +** value. */ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ SumCtx *p; @@ -857,6 +863,11 @@ static void avgFinalize(sqlite3_context *context){ sqlite3_result_double(context, p->sum/(double)p->cnt); } } +static void totalFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_double(context, p ? p->sum : 0.0); +} /* ** An instance of the following structure holds the context of a @@ -1000,6 +1011,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, { "max", 1, 2, 1, minmaxStep, minMaxFinalize }, { "sum", 1, 0, 0, sumStep, sumFinalize }, + { "total", 1, 0, 0, sumStep, totalFinalize }, { "avg", 1, 0, 0, sumStep, avgFinalize }, { "count", 0, 0, 0, countStep, countFinalize }, { "count", 1, 0, 0, countStep, countFinalize }, diff --git a/test/null.test b/test/null.test index ba9c6f88e0..8d401f6519 100644 --- a/test/null.test +++ b/test/null.test @@ -102,6 +102,14 @@ do_test null-3.1 { } } {7 4 6 2 3 0.5 0.5 0 1} +# The sum of zero entries is a NULL, but the total of zero entries is 0. +# +do_test null-3.2 { + execsql { + SELECT sum(b), total(b) FROM t1 WHERE b<0 + } +} {{} 0.0} + # Check to see how WHERE clauses handle NULL values. A NULL value # is the same as UNKNOWN. The WHERE clause should only select those # rows that are TRUE. FALSE and UNKNOWN rows are rejected. diff --git a/www/lang.tcl b/www/lang.tcl index 0fe77cd558..b937cbd277 100644 --- a/www/lang.tcl +++ b/www/lang.tcl @@ -1,7 +1,7 @@ # # Run this Tcl script to generate the lang-*.html files. # -set rcsid {$Id: lang.tcl,v 1.104 2006/01/04 15:58:29 drh Exp $} +set rcsid {$Id: lang.tcl,v 1.105 2006/01/12 22:17:50 drh Exp $} source common.tcl if {[llength $argv]>0} { @@ -1395,15 +1395,15 @@ if all values in the group are NULL. -sum(X) +sum(X)
total(X) Return the numeric sum of all numeric values in the group. - If there are no input rows or all values are NULL, then NULL is returned. + If there are no input rows or all values are NULL, then sum() returns + NULL but total() returns zero. NULL is not a helpful result in that case (the correct answer should be - zero) but it is what the SQL standard requires and how - most other SQL database engines operate so SQLite does it that way - in order to be compatible. - You will probably want to use - "coalesce(sum(X),0)" instead of just "sum(X)" + zero) but the SQL standard requires that behavior from sum() and that is how + most other SQL database engines implement sum() so SQLite does it that way + in order to be compatible. The non-standard total() function is provided + as a convenient way to work around this design problem in the SQL language.