diff options
author | drh <drh@noemail.net> | 2002-02-27 19:50:59 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2002-02-27 19:50:59 +0000 |
commit | dd5baa95e81b1aa25d5314c2452afc0560110c08 (patch) | |
tree | e2aeb578b67bd2a1b5d1d87191ba4de799807654 /src | |
parent | 1350b030c146486e58ab3bc0ca825650eaf0ab97 (diff) | |
download | sqlite-dd5baa95e81b1aa25d5314c2452afc0560110c08.tar.gz sqlite-dd5baa95e81b1aa25d5314c2452afc0560110c08.zip |
Try to reduce the number of malloc() for user-defined functions. Begin
transfering built-in functions over to the user-define function
mechanism. (CVS 399)
FossilOrigin-Name: c4f9e017b449d4036fa8d2bf77b931d4c31d74f7
Diffstat (limited to 'src')
-rw-r--r-- | src/func.c | 52 | ||||
-rw-r--r-- | src/sqlite.h.in | 14 | ||||
-rw-r--r-- | src/vdbe.c | 24 |
3 files changed, 69 insertions, 21 deletions
diff --git a/src/func.c b/src/func.c index 26c401e12..881b26ab3 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.4 2002/02/27 19:00:22 drh Exp $ +** $Id: func.c,v 1.5 2002/02/27 19:50:59 drh Exp $ */ #include <ctype.h> #include <math.h> @@ -49,13 +49,50 @@ static void lowerFunc(sqlite_func *context, int argc, const char **argv){ /* ** An instance of the following structure holds the context of a +** sum() or avg() aggregate computation. +*/ +typedef struct SumCtx SumCtx; +struct SumCtx { + double sum; /* Sum of terms */ +}; + +/* +** Routines used to compute the sum or average. +*/ +static void sumStep(sqlite_func *context, int argc, const char **argv){ + SumCtx *p; + double x; + if( argc<1 ) return; + p = sqlite_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + x = argv[0] ? atof(argv[0]) : 0.0; + p->sum += x; +} +static void sumFinalize(sqlite_func *context){ + SumCtx *p; + p = sqlite_aggregate_context(context, sizeof(*p)); + if( p ){ + sqlite_set_result_double(context, p->sum); + } +} +static void avgFinalize(sqlite_func *context){ + SumCtx *p; + double rN; + p = sqlite_aggregate_context(context, sizeof(*p)); + rN = sqlite_aggregate_count(context); + if( p && rN>0.0 ){ + sqlite_set_result_double(context, p->sum/rN); + } +} + +/* +** An instance of the following structure holds the context of a ** variance or standard deviation computation. */ typedef struct StdDevCtx StdDevCtx; struct StdDevCtx { double sum; /* Sum of terms */ double sum2; /* Sum of the squares of terms */ - int n; /* Number of terms seen so far */ }; /* @@ -67,20 +104,21 @@ static void stdDevStep(sqlite_func *context, int argc, const char **argv){ if( argc<1 ) return; p = sqlite_aggregate_context(context, sizeof(*p)); if( p==0 ) return; - x = atof(argv[0]); + x = argv[0] ? atof(argv[0]) : 0.0; p->sum += x; p->sum2 += x*x; - p->n++; } static void stdDevFinalize(sqlite_func *context){ + double rN = sqlite_aggregate_count(context); StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p)); - if( p && p->n>1 ){ - double rN = p->n; + if( p && rN>1.0 ){ sqlite_set_result_double(context, sqrt((p->sum2 - p->sum*p->sum/rN)/(rN-1.0))); } } + + /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with @@ -90,4 +128,6 @@ void sqliteRegisterBuildinFunctions(sqlite *db){ sqlite_create_function(db, "upper", 1, upperFunc, 0); sqlite_create_function(db, "lower", 1, lowerFunc, 0); sqlite_create_aggregate(db, "stddev", 1, stdDevStep, stdDevFinalize, 0); + sqlite_create_aggregate(db, "x_sum", 1, sumStep, sumFinalize, 0); + sqlite_create_aggregate(db, "x_avg", 1, sumStep, avgFinalize, 0); } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 251bd35d8..b460849fa 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.27 2002/02/27 19:00:22 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.28 2002/02/27 19:50:59 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -391,7 +391,7 @@ int sqlite_create_aggregate( /* ** The user function implementations call one of the following four routines ** in order to return their results. The first parameter to each of these -** routines is a copy of the first argument to xFunc() or xFinialize() +** routines is a copy of the first argument to xFunc() or xFinialize(). ** The second parameter to these routines is the result to be returned. ** A NULL can be passed as the second parameter to sqlite_set_result_string() ** in order to return a NULL result. @@ -419,8 +419,8 @@ void sqlite_set_result_error(sqlite_func*,const char*,int); void *sqlite_user_data(sqlite_func*); /* -** User aggregate functions use the following routine to allocate -** a structure for storing their context. The first time this routine +** Aggregate functions use the following routine to allocate +** a structure for storing their state. The first time this routine ** is called for a particular aggregate, a new structure of size nBytes ** is allocated, zeroed, and returned. On subsequent calls (for the ** same aggregate instance) the same buffer is returned. The implementation @@ -431,9 +431,9 @@ void *sqlite_user_data(sqlite_func*); void *sqlite_aggregate_context(sqlite_func*, int nBytes); /* -** The next return returns the number of calls to xStep for a particular -** aggregate function instance. The current call to xStep counts so the -** function always returns at least 1. +** The next routine returns the number of calls to xStep for a particular +** aggregate function instance. The current call to xStep counts so this +** routine always returns at least 1. */ int sqlite_aggregate_count(sqlite_func*); diff --git a/src/vdbe.c b/src/vdbe.c index c285eb6f4..0d134ae03 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,7 +30,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.124 2002/02/27 19:00:22 drh Exp $ +** $Id: vdbe.c,v 1.125 2002/02/27 19:50:59 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -618,7 +618,11 @@ void *sqlite_user_data(sqlite_func *p){ void *sqlite_aggregate_context(sqlite_func *p, int nByte){ assert( p && p->pFunc && p->pFunc->xStep ); if( p->pAgg==0 ){ - p->pAgg = sqliteMalloc( nByte ); + if( nByte<=NBFS ){ + p->pAgg = (void*)p->z; + }else{ + p->pAgg = sqliteMalloc( nByte ); + } } return p->pAgg; } @@ -652,18 +656,21 @@ static void AggReset(Agg *pAgg){ AggElem *pElem = sqliteHashData(p); assert( pAgg->apFunc!=0 ); for(i=0; i<pAgg->nMem; i++){ - if( pAgg->apFunc[i] && (pElem->aMem[i].s.flags & STK_AggCtx)!=0 ){ + Mem *pMem = &pElem->aMem[i]; + if( pAgg->apFunc[i] && (pMem->s.flags & STK_AggCtx)!=0 ){ sqlite_func ctx; ctx.s.flags = STK_Null; ctx.z = 0; - ctx.pAgg = pElem->aMem[i].z; - ctx.cnt = pElem->aMem[i].s.i; + ctx.pAgg = pMem->z; + ctx.cnt = pMem->s.i; ctx.isStep = 0; ctx.isError = 0; (*pAgg->apFunc[i]->xFinalize)(&ctx); - } - if( pElem->aMem[i].s.flags & (STK_Dyn | STK_AggCtx) ){ - sqliteFree(pElem->aMem[i].z); + if( pMem->z!=0 && pMem->z!=pMem->s.z ){ + sqliteFree(pMem->z); + } + }else if( pMem->s.flags & STK_Dyn ){ + sqliteFree(pMem->z); } } sqliteFree(pElem); @@ -4437,6 +4444,7 @@ case OP_AggFunc: { VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; ) ctx.pFunc = (UserFunc*)pOp->p3; pMem = &p->agg.pCurrent->aMem[i]; + ctx.z = pMem->s.z; ctx.pAgg = pMem->z; ctx.cnt = ++pMem->s.i; ctx.isError = 0; |