drh | dc04c58 | 2002-02-24 01:55:15 +0000 | [diff] [blame] | 1 | /* |
| 2 | ** 2002 February 23 |
| 3 | ** |
| 4 | ** The author disclaims copyright to this source code. In place of |
| 5 | ** a legal notice, here is a blessing: |
| 6 | ** |
| 7 | ** May you do good and not evil. |
| 8 | ** May you find forgiveness for yourself and forgive others. |
| 9 | ** May you share freely, never taking more than you give. |
| 10 | ** |
| 11 | ************************************************************************* |
| 12 | ** This file contains the C functions that implement various SQL |
| 13 | ** functions of SQLite. |
| 14 | ** |
| 15 | ** There is only one exported symbol in this file - the function |
| 16 | ** sqliteRegisterBuildinFunctions() found at the bottom of the file. |
| 17 | ** All other code has file scope. |
| 18 | ** |
drh | a2ed560 | 2002-02-26 23:55:31 +0000 | [diff] [blame^] | 19 | ** $Id: func.c,v 1.3 2002/02/26 23:55:31 drh Exp $ |
drh | dc04c58 | 2002-02-24 01:55:15 +0000 | [diff] [blame] | 20 | */ |
| 21 | #include <ctype.h> |
drh | d3a149e | 2002-02-24 17:12:53 +0000 | [diff] [blame] | 22 | #include <math.h> |
| 23 | #include <stdlib.h> |
drh | dc04c58 | 2002-02-24 01:55:15 +0000 | [diff] [blame] | 24 | #include "sqlite.h" |
| 25 | |
| 26 | /* |
| 27 | ** Implementation of the upper() and lower() SQL functions. |
| 28 | */ |
| 29 | static void upperFunc(void *context, int argc, const char **argv){ |
| 30 | char *z; |
| 31 | int i; |
| 32 | if( argc<1 || argv[0]==0 ) return; |
| 33 | z = sqlite_set_result_string(context, argv[0], -1); |
| 34 | if( z==0 ) return; |
| 35 | for(i=0; z[i]; i++){ |
| 36 | if( islower(z[i]) ) z[i] = toupper(z[i]); |
| 37 | } |
| 38 | } |
| 39 | static void lowerFunc(void *context, int argc, const char **argv){ |
| 40 | char *z; |
| 41 | int i; |
| 42 | if( argc<1 || argv[0]==0 ) return; |
| 43 | z = sqlite_set_result_string(context, argv[0], -1); |
| 44 | if( z==0 ) return; |
| 45 | for(i=0; z[i]; i++){ |
| 46 | if( isupper(z[i]) ) z[i] = tolower(z[i]); |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | /* |
drh | d3a149e | 2002-02-24 17:12:53 +0000 | [diff] [blame] | 51 | ** An instance of the following structure holds the context of a |
drh | a2ed560 | 2002-02-26 23:55:31 +0000 | [diff] [blame^] | 52 | ** variance or standard deviation computation. |
drh | d3a149e | 2002-02-24 17:12:53 +0000 | [diff] [blame] | 53 | */ |
| 54 | typedef struct StdDevCtx StdDevCtx; |
| 55 | struct StdDevCtx { |
| 56 | double sum; /* Sum of terms */ |
| 57 | double sum2; /* Sum of the squares of terms */ |
| 58 | int n; /* Number of terms seen so far */ |
| 59 | }; |
| 60 | |
| 61 | /* |
| 62 | ** Routines used to compute the standard deviation as an aggregate. |
| 63 | */ |
| 64 | static void *stdDevStep(void *stddev, int argc, char **argv){ |
| 65 | StdDevCtx *p; |
| 66 | double x; |
| 67 | if( argc<1 ) return 0; |
| 68 | if( stddev==0 ){ |
| 69 | p = malloc( sizeof(*p) ); |
| 70 | p->n = 0; |
| 71 | p->sum = 0.0; |
| 72 | p->sum2 = 0.0; |
| 73 | }else{ |
| 74 | p = (StdDevCtx*)stddev; |
| 75 | } |
| 76 | x = atof(argv[0]); |
| 77 | p->sum += x; |
| 78 | p->sum2 += x*x; |
| 79 | p->n++; |
| 80 | return p; |
| 81 | } |
| 82 | static void stdDevFinalize(void *stddev, void *context){ |
| 83 | StdDevCtx *p = (StdDevCtx*)stddev; |
| 84 | if( context && p && p->n>1 ){ |
| 85 | double rN = p->n; |
| 86 | sqlite_set_result_double(context, |
| 87 | sqrt((p->sum2 - p->sum*p->sum/rN)/(rN-1.0))); |
| 88 | } |
| 89 | if( stddev ) free(stddev); |
| 90 | } |
| 91 | |
| 92 | /* |
drh | a2ed560 | 2002-02-26 23:55:31 +0000 | [diff] [blame^] | 93 | ** This function registered all of the above C functions as SQL |
| 94 | ** functions. This should be the only routine in this file with |
| 95 | ** external linkage. |
drh | dc04c58 | 2002-02-24 01:55:15 +0000 | [diff] [blame] | 96 | */ |
| 97 | void sqliteRegisterBuildinFunctions(sqlite *db){ |
| 98 | sqlite_create_function(db, "upper", 1, upperFunc); |
| 99 | sqlite_create_function(db, "lower", 1, lowerFunc); |
drh | d3a149e | 2002-02-24 17:12:53 +0000 | [diff] [blame] | 100 | sqlite_create_aggregate(db, "stddev", 1, stdDevStep, stdDevFinalize); |
drh | dc04c58 | 2002-02-24 01:55:15 +0000 | [diff] [blame] | 101 | } |