Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c4f9e017b449d4036fa8d2bf77b931d4 |
User & Date: | drh 2002-02-27 19:50:59.000 |
Context
2002-02-28
| ||
00:41 | Completely remove the old SQL function system and replace it with the new user functions. The code currently compiles but it coredumps on the test suite. Do not use in its present state. (CVS 400) (check-in: 50797fee50 user: drh tags: trunk) | |
2002-02-27
| ||
19:50 | 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) (check-in: c4f9e017b4 user: drh tags: trunk) | |
19:00 | Revise the API for user-defined functions. (CVS 398) (check-in: 633951f0fa user: drh tags: trunk) | |
Changes
Changes to src/func.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.5 2002/02/27 19:50:59 drh Exp $ */ #include <ctype.h> #include <math.h> #include <stdlib.h> #include "sqlite.h" /* |
︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | if( argc<1 || argv[0]==0 ) return; z = sqlite_set_result_string(context, argv[0], -1); if( z==0 ) return; for(i=0; z[i]; i++){ if( isupper(z[i]) ) z[i] = tolower(z[i]); } } /* ** 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 */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | < > | < > > > > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | if( argc<1 || argv[0]==0 ) return; z = sqlite_set_result_string(context, argv[0], -1); if( z==0 ) return; for(i=0; z[i]; i++){ if( isupper(z[i]) ) z[i] = tolower(z[i]); } } /* ** 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 */ }; /* ** Routines used to compute the standard deviation as an aggregate. */ static void stdDevStep(sqlite_func *context, int argc, const char **argv){ StdDevCtx *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; p->sum2 += x*x; } static void stdDevFinalize(sqlite_func *context){ double rN = sqlite_aggregate_count(context); StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p)); 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 ** external linkage. */ 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); } |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite.h.in,v 1.28 2002/02/27 19:50:59 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** The version of the SQLite library. |
︙ | ︙ | |||
387 388 389 390 391 392 393 | void (*xFinalize)(sqlite_func*), /* Called once to get final result */ void *pUserData /* Available via the sqlite_user_data() call */ ); /* ** The user function implementations call one of the following four routines ** in order to return their results. The first parameter to each of these | | | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 | void (*xFinalize)(sqlite_func*), /* Called once to get final result */ void *pUserData /* Available via the sqlite_user_data() call */ ); /* ** 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(). ** 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. ** ** The 3rd argument to _string and _error is the number of characters to ** take from the string. If this argument is negative, then all characters ** up to and including the first '\000' are used. |
︙ | ︙ | |||
415 416 417 418 419 420 421 | ** sqlite_create_aggregate() routines used to register user functions ** is available to the implementation of the function using this ** call. */ void *sqlite_user_data(sqlite_func*); /* | | | | | | | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 | ** sqlite_create_aggregate() routines used to register user functions ** is available to the implementation of the function using this ** call. */ void *sqlite_user_data(sqlite_func*); /* ** 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 ** of the aggregate can use the returned buffer to accumulate data. ** ** The buffer allocated is freed automatically be SQLite. */ void *sqlite_aggregate_context(sqlite_func*, int nBytes); /* ** 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*); #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif /* _SQLITE_H_ */ |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.125 2002/02/27 19:50:59 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
614 615 616 617 618 619 620 | ** This routine is defined here in vdbe.c because it depends on knowing ** the internals of the sqlite_func structure which is only defined in that ** one source file. */ void *sqlite_aggregate_context(sqlite_func *p, int nByte){ assert( p && p->pFunc && p->pFunc->xStep ); if( p->pAgg==0 ){ | > > > | > | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 | ** This routine is defined here in vdbe.c because it depends on knowing ** the internals of the sqlite_func structure which is only defined in that ** one source file. */ void *sqlite_aggregate_context(sqlite_func *p, int nByte){ assert( p && p->pFunc && p->pFunc->xStep ); if( p->pAgg==0 ){ if( nByte<=NBFS ){ p->pAgg = (void*)p->z; }else{ p->pAgg = sqliteMalloc( nByte ); } } return p->pAgg; } /* ** Return the number of times the Step function of a user-defined ** aggregate has been called. |
︙ | ︙ | |||
648 649 650 651 652 653 654 | static void AggReset(Agg *pAgg){ int i; HashElem *p; for(p = sqliteHashFirst(&pAgg->hash); p; p = sqliteHashNext(p)){ AggElem *pElem = sqliteHashData(p); assert( pAgg->apFunc!=0 ); for(i=0; i<pAgg->nMem; i++){ | > | | | > > | | | | 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | static void AggReset(Agg *pAgg){ int i; HashElem *p; for(p = sqliteHashFirst(&pAgg->hash); p; p = sqliteHashNext(p)){ AggElem *pElem = sqliteHashData(p); assert( pAgg->apFunc!=0 ); for(i=0; i<pAgg->nMem; i++){ 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 = pMem->z; ctx.cnt = pMem->s.i; ctx.isStep = 0; ctx.isError = 0; (*pAgg->apFunc[i]->xFinalize)(&ctx); if( pMem->z!=0 && pMem->z!=pMem->s.z ){ sqliteFree(pMem->z); } }else if( pMem->s.flags & STK_Dyn ){ sqliteFree(pMem->z); } } sqliteFree(pElem); } sqliteHashClear(&pAgg->hash); sqliteFree(pAgg->apFunc); pAgg->apFunc = 0; |
︙ | ︙ | |||
4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 | if( Stringify(p, i) ) goto no_mem; } } i = aStack[p->tos].i; VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; ) ctx.pFunc = (UserFunc*)pOp->p3; pMem = &p->agg.pCurrent->aMem[i]; ctx.pAgg = pMem->z; ctx.cnt = ++pMem->s.i; ctx.isError = 0; ctx.isStep = 1; (ctx.pFunc->xStep)(&ctx, n, (const char**)&zStack[p->tos-n]); pMem->z = ctx.pAgg; pMem->s.flags = STK_AggCtx; | > | 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 | if( Stringify(p, i) ) goto no_mem; } } i = aStack[p->tos].i; 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; ctx.isStep = 1; (ctx.pFunc->xStep)(&ctx, n, (const char**)&zStack[p->tos-n]); pMem->z = ctx.pAgg; pMem->s.flags = STK_AggCtx; |
︙ | ︙ |