SUM never gives an error. An integer result is returned for exact results
and a floating point result is returned for approximate results. Tickets #1664, #1669, and #1670. (CVS 3066) FossilOrigin-Name: 9e04f8fdf1ec0dc36effb55c05d075b3b4777fef
This commit is contained in:
+23
-11
@@ -16,7 +16,7 @@
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: func.c,v 1.120 2006/02/09 18:35:30 drh Exp $
|
||||
** $Id: func.c,v 1.121 2006/02/09 22:13:42 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -819,7 +819,7 @@ typedef struct SumCtx SumCtx;
|
||||
struct SumCtx {
|
||||
LONGDOUBLE_TYPE sum; /* Sum of terms */
|
||||
i64 cnt; /* Number of elements summed */
|
||||
u8 seenFloat; /* True if there has been any floating point value */
|
||||
u8 approx; /* True if sum is approximate */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -830,18 +830,33 @@ struct SumCtx {
|
||||
** 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.
|
||||
**
|
||||
** I am told that SUM() should raise an exception if it encounters
|
||||
** a integer overflow. But after pondering this, I decided that
|
||||
** behavior leads to brittle programs. So instead, I have coded
|
||||
** SUM() to revert to using floating point if it encounters an
|
||||
** integer overflow. The answer may not be exact, but it will be
|
||||
** close. If the SUM() function returns an integer, the value is
|
||||
** exact. If SUM() returns a floating point value, it means the
|
||||
** value might be approximated.
|
||||
*/
|
||||
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
SumCtx *p;
|
||||
int type;
|
||||
assert( argc==1 );
|
||||
p = sqlite3_aggregate_context(context, sizeof(*p));
|
||||
type = sqlite3_value_type(argv[0]);
|
||||
type = sqlite3_value_numeric_type(argv[0]);
|
||||
if( p && type!=SQLITE_NULL ){
|
||||
p->sum += sqlite3_value_double(argv[0]);
|
||||
p->cnt++;
|
||||
if( type==SQLITE_FLOAT ){
|
||||
p->seenFloat = 1;
|
||||
if( type==SQLITE_INTEGER ){
|
||||
p->sum += sqlite3_value_int64(argv[0]);
|
||||
if( !p->approx ){
|
||||
i64 iVal;
|
||||
p->approx = p->sum!=(LONGDOUBLE_TYPE)(iVal = (i64)p->sum);
|
||||
}
|
||||
}else{
|
||||
p->sum += sqlite3_value_double(argv[0]);
|
||||
p->approx = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -849,13 +864,10 @@ static void sumFinalize(sqlite3_context *context){
|
||||
SumCtx *p;
|
||||
p = sqlite3_aggregate_context(context, 0);
|
||||
if( p && p->cnt>0 ){
|
||||
i64 iVal = (i64)p->sum;
|
||||
if( p->seenFloat ){
|
||||
if( p->approx ){
|
||||
sqlite3_result_double(context, p->sum);
|
||||
}else if( p->sum==(LONGDOUBLE_TYPE)iVal ){
|
||||
sqlite3_result_int64(context, iVal);
|
||||
}else{
|
||||
sqlite3_result_error(context, "integer overflow", -1);
|
||||
sqlite3_result_int64(context, (i64)p->sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user