/ Check-in [c4f9e017]
Login

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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:c4f9e017b449d4036fa8d2bf77b931d4c31d74f7
User & Date: drh 2002-02-27 19:50:59
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: 50797fee 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: c4f9e017 user: drh tags: trunk
19:00
Revise the API for user-defined functions. (CVS 398) check-in: 633951f0 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/func.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
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
** 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.4 2002/02/27 19:00:22 drh Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include "sqlite.h"

/*
................................................................................
  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 */
  int n;          /* Number of terms seen so far */
};

/*
** 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 = atof(argv[0]);
  p->sum += x;
  p->sum2 += x*x;
  p->n++;
}
static void stdDevFinalize(sqlite_func *context){

  StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p));
  if( p && p->n>1 ){
    double rN = p->n;
    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);


}







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









<











|


<


>

|
<




>
>










>
>

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
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
** 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"

/*
................................................................................
  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
15
16
17
18
19
20
21
22
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
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
**    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.27 2002/02/27 19:00:22 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** The version of the SQLite library.
................................................................................
  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.
................................................................................
** 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*);

/*
** User aggregate functions use the following routine to allocate
** a structure for storing their context.  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 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.
*/
int sqlite_aggregate_count(sqlite_func*);

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif

#endif /* _SQLITE_H_ */







|







 







|







 







|
|










|
|
|








8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
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
**    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.
................................................................................
  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.
................................................................................
** 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
33
34
35
36
37
38
39
40
...
614
615
616
617
618
619
620



621

622
623
624
625
626
627
628
...
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662
663


664
665

666
667
668
669
670
671
672
673
....
4433
4434
4435
4436
4437
4438
4439

4440
4441
4442
4443
4444
4445
4446
** 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.124 2002/02/27 19:00:22 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
................................................................................
** 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 ){



    p->pAgg = sqliteMalloc( nByte );

  }
  return p->pAgg;
}

/*
** Return the number of times the Step function of a user-defined 
** aggregate has been called.
................................................................................
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++){

      if( pAgg->apFunc[i] && (pElem->aMem[i].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.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);
      }
    }
    sqliteFree(pElem);
  }
  sqliteHashClear(&pAgg->hash);
  sqliteFree(pAgg->apFunc);
  pAgg->apFunc = 0;
................................................................................
      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;







|







 







>
>
>
|
>







 







>
|



|
|



>
>
|
<
>
|







 







>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
...
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
....
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
** 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
................................................................................
** 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.
................................................................................
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;
................................................................................
      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;