]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Try to reduce the number of malloc() for user-defined functions. Begin
authordrh <drh@noemail.net>
Wed, 27 Feb 2002 19:50:59 +0000 (19:50 +0000)
committerdrh <drh@noemail.net>
Wed, 27 Feb 2002 19:50:59 +0000 (19:50 +0000)
transfering built-in functions over to the user-define function
mechanism. (CVS 399)

FossilOrigin-Name: c4f9e017b449d4036fa8d2bf77b931d4c31d74f7

manifest
manifest.uuid
src/func.c
src/sqlite.h.in
src/vdbe.c

index b6fe23ef814a5f026e9603d60f4c2718785e6843..76b44c7facc212dc4fd1f577031a2dee22d67a92 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Revise\sthe\sAPI\sfor\suser-defined\sfunctions.\s(CVS\s398)
-D 2002-02-27T19:00:21
+C Try\sto\sreduce\sthe\snumber\sof\smalloc()\sfor\suser-defined\sfunctions.\s\sBegin\ntransfering\sbuilt-in\sfunctions\sover\sto\sthe\suser-define\sfunction\nmechanism.\s(CVS\s399)
+D 2002-02-27T19:50:59
 F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d
 F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296
 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
@@ -24,7 +24,7 @@ F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
 F src/build.c 7ada2426caba70cb1072ba268bedb694b5018065
 F src/delete.c 950d8f9097361419f1963875f9943344b469cf02
 F src/expr.c ea2209a6bdefea23db988b470fc16dbf9d5b3a5a
-F src/func.c f020b8c659c95ba1e46cab548ada582ebf8c6c3c
+F src/func.c 3aeff18b277d9fdece117497dfff8119113ea412
 F src/hash.c cc259475e358baaf299b00a2c7370f2b03dda892
 F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9
 F src/insert.c 164d2d5e943268a8ff0594e1947599e04df0ce11
@@ -40,7 +40,7 @@ F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
 F src/select.c a8e90e8f8366b72830010dd6a9bfbf121d2e9370
 F src/shell.c 9f8249ca5b8f8aad40becd778c151b58c0d6109e
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
-F src/sqlite.h.in 681dd71442788f900439b624ad1ea2b98f178904
+F src/sqlite.h.in a9b5772604265f98f3120573ef29e37b9d917216
 F src/sqliteInt.h 4e746aa13c5fa39a31a89b73afcd33fa164e8b4f
 F src/table.c 203a09d5d0009eeeb1f670370d52b4ce163a3b52
 F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
@@ -51,7 +51,7 @@ F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f
 F src/tokenize.c 4b5d30590a744b9bb5605a92d1f620ab2e7e75af
 F src/update.c 18971d265b0341574b7e3f73116e7947ddab0997
 F src/util.c 40a12067fa7b18c7e0461b3256b1353c755b59ac
-F src/vdbe.c 1a5378625687ced2acaa01e200cb63f07f780ad6
+F src/vdbe.c d1efbaf24a745cf895432baf7642846e34a60f40
 F src/vdbe.h 785b2f175f8be2af285d137125f30042ce8a53b5
 F src/where.c 664be01b0ce9ffaecbde609afbd4d8d3e5ed1585
 F test/all.test 7a8a8a7a579ed2bb4d8976d55402f21eacd58049
@@ -127,7 +127,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5
 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
 F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 085b0d671a1dac964693d69d866224de155dfe4c
-R 06586960572c0c651395cc4d56fdf6f3
+P 633951f0fa11c91f93aa2862df84691750c01e73
+R 1ad564fc9fb52e423ae79061556e1e37
 U drh
-Z 67f54dfeaa3612775fa7c5da9d11c294
+Z 9b3029f554c840c37489da7d32038cb8
index c77dfa24e5b0c67e364370c4733a94cfa568075b..1ea5eee158570dde4b5c319e4cd44bf7c647eed7 100644 (file)
@@ -1 +1 @@
-633951f0fa11c91f93aa2862df84691750c01e73
\ No newline at end of file
+c4f9e017b449d4036fa8d2bf77b931d4c31d74f7
\ No newline at end of file
index 26c401e124d9b863ae0252d0b878dcf22b2a044b..881b26ab3c51c2728770c72b38217adedf819765 100644 (file)
@@ -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>
@@ -47,6 +47,44 @@ 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.
@@ -55,7 +93,6 @@ 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);
 }
index 251bd35d8f08bb73941fe17367cb124461ec0546..b460849fae163989e2ea4d93838e4144eb3129c6 100644 (file)
@@ -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*);
 
index c285eb6f46ad0a2a0c8606cd40b83f8bebe9cd7b..0d134ae0397cd64b4c94a4f9fe5db2473f8c5f0f 100644 (file)
@@ -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;