mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
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
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Revise\sthe\sAPI\sfor\suser-defined\sfunctions.\s(CVS\s398)
|
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:00:21
|
D 2002-02-27T19:50:59
|
||||||
F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d
|
F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d
|
||||||
F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296
|
F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296
|
||||||
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
|
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
|
||||||
@@ -24,7 +24,7 @@ F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
|
|||||||
F src/build.c 7ada2426caba70cb1072ba268bedb694b5018065
|
F src/build.c 7ada2426caba70cb1072ba268bedb694b5018065
|
||||||
F src/delete.c 950d8f9097361419f1963875f9943344b469cf02
|
F src/delete.c 950d8f9097361419f1963875f9943344b469cf02
|
||||||
F src/expr.c ea2209a6bdefea23db988b470fc16dbf9d5b3a5a
|
F src/expr.c ea2209a6bdefea23db988b470fc16dbf9d5b3a5a
|
||||||
F src/func.c f020b8c659c95ba1e46cab548ada582ebf8c6c3c
|
F src/func.c 3aeff18b277d9fdece117497dfff8119113ea412
|
||||||
F src/hash.c cc259475e358baaf299b00a2c7370f2b03dda892
|
F src/hash.c cc259475e358baaf299b00a2c7370f2b03dda892
|
||||||
F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9
|
F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9
|
||||||
F src/insert.c 164d2d5e943268a8ff0594e1947599e04df0ce11
|
F src/insert.c 164d2d5e943268a8ff0594e1947599e04df0ce11
|
||||||
@@ -40,7 +40,7 @@ F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
|
|||||||
F src/select.c a8e90e8f8366b72830010dd6a9bfbf121d2e9370
|
F src/select.c a8e90e8f8366b72830010dd6a9bfbf121d2e9370
|
||||||
F src/shell.c 9f8249ca5b8f8aad40becd778c151b58c0d6109e
|
F src/shell.c 9f8249ca5b8f8aad40becd778c151b58c0d6109e
|
||||||
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
|
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
|
||||||
F src/sqlite.h.in 681dd71442788f900439b624ad1ea2b98f178904
|
F src/sqlite.h.in a9b5772604265f98f3120573ef29e37b9d917216
|
||||||
F src/sqliteInt.h 4e746aa13c5fa39a31a89b73afcd33fa164e8b4f
|
F src/sqliteInt.h 4e746aa13c5fa39a31a89b73afcd33fa164e8b4f
|
||||||
F src/table.c 203a09d5d0009eeeb1f670370d52b4ce163a3b52
|
F src/table.c 203a09d5d0009eeeb1f670370d52b4ce163a3b52
|
||||||
F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
|
F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
|
||||||
@@ -51,7 +51,7 @@ F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f
|
|||||||
F src/tokenize.c 4b5d30590a744b9bb5605a92d1f620ab2e7e75af
|
F src/tokenize.c 4b5d30590a744b9bb5605a92d1f620ab2e7e75af
|
||||||
F src/update.c 18971d265b0341574b7e3f73116e7947ddab0997
|
F src/update.c 18971d265b0341574b7e3f73116e7947ddab0997
|
||||||
F src/util.c 40a12067fa7b18c7e0461b3256b1353c755b59ac
|
F src/util.c 40a12067fa7b18c7e0461b3256b1353c755b59ac
|
||||||
F src/vdbe.c 1a5378625687ced2acaa01e200cb63f07f780ad6
|
F src/vdbe.c d1efbaf24a745cf895432baf7642846e34a60f40
|
||||||
F src/vdbe.h 785b2f175f8be2af285d137125f30042ce8a53b5
|
F src/vdbe.h 785b2f175f8be2af285d137125f30042ce8a53b5
|
||||||
F src/where.c 664be01b0ce9ffaecbde609afbd4d8d3e5ed1585
|
F src/where.c 664be01b0ce9ffaecbde609afbd4d8d3e5ed1585
|
||||||
F test/all.test 7a8a8a7a579ed2bb4d8976d55402f21eacd58049
|
F test/all.test 7a8a8a7a579ed2bb4d8976d55402f21eacd58049
|
||||||
@@ -127,7 +127,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5
|
|||||||
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
|
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
|
||||||
F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
|
F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
|
||||||
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
||||||
P 085b0d671a1dac964693d69d866224de155dfe4c
|
P 633951f0fa11c91f93aa2862df84691750c01e73
|
||||||
R 06586960572c0c651395cc4d56fdf6f3
|
R 1ad564fc9fb52e423ae79061556e1e37
|
||||||
U drh
|
U drh
|
||||||
Z 67f54dfeaa3612775fa7c5da9d11c294
|
Z 9b3029f554c840c37489da7d32038cb8
|
||||||
|
@@ -1 +1 @@
|
|||||||
633951f0fa11c91f93aa2862df84691750c01e73
|
c4f9e017b449d4036fa8d2bf77b931d4c31d74f7
|
52
src/func.c
52
src/func.c
@@ -16,7 +16,7 @@
|
|||||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||||
** All other code has file scope.
|
** 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 <ctype.h>
|
||||||
#include <math.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
|
** An instance of the following structure holds the context of a
|
||||||
** variance or standard deviation computation.
|
** variance or standard deviation computation.
|
||||||
@@ -55,7 +93,6 @@ typedef struct StdDevCtx StdDevCtx;
|
|||||||
struct StdDevCtx {
|
struct StdDevCtx {
|
||||||
double sum; /* Sum of terms */
|
double sum; /* Sum of terms */
|
||||||
double sum2; /* Sum of the squares 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;
|
if( argc<1 ) return;
|
||||||
p = sqlite_aggregate_context(context, sizeof(*p));
|
p = sqlite_aggregate_context(context, sizeof(*p));
|
||||||
if( p==0 ) return;
|
if( p==0 ) return;
|
||||||
x = atof(argv[0]);
|
x = argv[0] ? atof(argv[0]) : 0.0;
|
||||||
p->sum += x;
|
p->sum += x;
|
||||||
p->sum2 += x*x;
|
p->sum2 += x*x;
|
||||||
p->n++;
|
|
||||||
}
|
}
|
||||||
static void stdDevFinalize(sqlite_func *context){
|
static void stdDevFinalize(sqlite_func *context){
|
||||||
|
double rN = sqlite_aggregate_count(context);
|
||||||
StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p));
|
StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p));
|
||||||
if( p && p->n>1 ){
|
if( p && rN>1.0 ){
|
||||||
double rN = p->n;
|
|
||||||
sqlite_set_result_double(context,
|
sqlite_set_result_double(context,
|
||||||
sqrt((p->sum2 - p->sum*p->sum/rN)/(rN-1.0)));
|
sqrt((p->sum2 - p->sum*p->sum/rN)/(rN-1.0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function registered all of the above C functions as SQL
|
** This function registered all of the above C functions as SQL
|
||||||
** functions. This should be the only routine in this file with
|
** 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, "upper", 1, upperFunc, 0);
|
||||||
sqlite_create_function(db, "lower", 1, lowerFunc, 0);
|
sqlite_create_function(db, "lower", 1, lowerFunc, 0);
|
||||||
sqlite_create_aggregate(db, "stddev", 1, stdDevStep, stdDevFinalize, 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);
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
** This header file defines the interface that the SQLite library
|
** This header file defines the interface that the SQLite library
|
||||||
** presents to client programs.
|
** 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_
|
#ifndef _SQLITE_H_
|
||||||
#define _SQLITE_H_
|
#define _SQLITE_H_
|
||||||
@@ -391,7 +391,7 @@ int sqlite_create_aggregate(
|
|||||||
/*
|
/*
|
||||||
** The user function implementations call one of the following four routines
|
** The user function implementations call one of the following four routines
|
||||||
** in order to return their results. The first parameter to each of these
|
** 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.
|
** 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()
|
** A NULL can be passed as the second parameter to sqlite_set_result_string()
|
||||||
** in order to return a NULL result.
|
** 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*);
|
void *sqlite_user_data(sqlite_func*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** User aggregate functions use the following routine to allocate
|
** Aggregate functions use the following routine to allocate
|
||||||
** a structure for storing their context. The first time this routine
|
** a structure for storing their state. The first time this routine
|
||||||
** is called for a particular aggregate, a new structure of size nBytes
|
** is called for a particular aggregate, a new structure of size nBytes
|
||||||
** is allocated, zeroed, and returned. On subsequent calls (for the
|
** is allocated, zeroed, and returned. On subsequent calls (for the
|
||||||
** same aggregate instance) the same buffer is returned. The implementation
|
** 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);
|
void *sqlite_aggregate_context(sqlite_func*, int nBytes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The next return returns the number of calls to xStep for a particular
|
** The next routine returns the number of calls to xStep for a particular
|
||||||
** aggregate function instance. The current call to xStep counts so the
|
** aggregate function instance. The current call to xStep counts so this
|
||||||
** function always returns at least 1.
|
** routine always returns at least 1.
|
||||||
*/
|
*/
|
||||||
int sqlite_aggregate_count(sqlite_func*);
|
int sqlite_aggregate_count(sqlite_func*);
|
||||||
|
|
||||||
|
24
src/vdbe.c
24
src/vdbe.c
@@ -30,7 +30,7 @@
|
|||||||
** But other routines are also provided to help in building up
|
** But other routines are also provided to help in building up
|
||||||
** a program instruction by instruction.
|
** 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 "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -618,7 +618,11 @@ void *sqlite_user_data(sqlite_func *p){
|
|||||||
void *sqlite_aggregate_context(sqlite_func *p, int nByte){
|
void *sqlite_aggregate_context(sqlite_func *p, int nByte){
|
||||||
assert( p && p->pFunc && p->pFunc->xStep );
|
assert( p && p->pFunc && p->pFunc->xStep );
|
||||||
if( p->pAgg==0 ){
|
if( p->pAgg==0 ){
|
||||||
p->pAgg = sqliteMalloc( nByte );
|
if( nByte<=NBFS ){
|
||||||
|
p->pAgg = (void*)p->z;
|
||||||
|
}else{
|
||||||
|
p->pAgg = sqliteMalloc( nByte );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return p->pAgg;
|
return p->pAgg;
|
||||||
}
|
}
|
||||||
@@ -652,18 +656,21 @@ static void AggReset(Agg *pAgg){
|
|||||||
AggElem *pElem = sqliteHashData(p);
|
AggElem *pElem = sqliteHashData(p);
|
||||||
assert( pAgg->apFunc!=0 );
|
assert( pAgg->apFunc!=0 );
|
||||||
for(i=0; i<pAgg->nMem; i++){
|
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;
|
sqlite_func ctx;
|
||||||
ctx.s.flags = STK_Null;
|
ctx.s.flags = STK_Null;
|
||||||
ctx.z = 0;
|
ctx.z = 0;
|
||||||
ctx.pAgg = pElem->aMem[i].z;
|
ctx.pAgg = pMem->z;
|
||||||
ctx.cnt = pElem->aMem[i].s.i;
|
ctx.cnt = pMem->s.i;
|
||||||
ctx.isStep = 0;
|
ctx.isStep = 0;
|
||||||
ctx.isError = 0;
|
ctx.isError = 0;
|
||||||
(*pAgg->apFunc[i]->xFinalize)(&ctx);
|
(*pAgg->apFunc[i]->xFinalize)(&ctx);
|
||||||
}
|
if( pMem->z!=0 && pMem->z!=pMem->s.z ){
|
||||||
if( pElem->aMem[i].s.flags & (STK_Dyn | STK_AggCtx) ){
|
sqliteFree(pMem->z);
|
||||||
sqliteFree(pElem->aMem[i].z);
|
}
|
||||||
|
}else if( pMem->s.flags & STK_Dyn ){
|
||||||
|
sqliteFree(pMem->z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqliteFree(pElem);
|
sqliteFree(pElem);
|
||||||
@@ -4437,6 +4444,7 @@ case OP_AggFunc: {
|
|||||||
VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; )
|
VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; )
|
||||||
ctx.pFunc = (UserFunc*)pOp->p3;
|
ctx.pFunc = (UserFunc*)pOp->p3;
|
||||||
pMem = &p->agg.pCurrent->aMem[i];
|
pMem = &p->agg.pCurrent->aMem[i];
|
||||||
|
ctx.z = pMem->s.z;
|
||||||
ctx.pAgg = pMem->z;
|
ctx.pAgg = pMem->z;
|
||||||
ctx.cnt = ++pMem->s.i;
|
ctx.cnt = ++pMem->s.i;
|
||||||
ctx.isError = 0;
|
ctx.isError = 0;
|
||||||
|
Reference in New Issue
Block a user