blob: 3ca42ca4b803efbc1659ddf68a3942c3474927ed [file] [log] [blame]
drhdc04c582002-02-24 01:55:15 +00001/*
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**
drh193a6b42002-07-07 16:52:46 +000019** $Id: func.c,v 1.22 2002/07/07 16:52:47 drh Exp $
drhdc04c582002-02-24 01:55:15 +000020*/
21#include <ctype.h>
drhd3a149e2002-02-24 17:12:53 +000022#include <math.h>
23#include <stdlib.h>
drh0bce8352002-02-28 00:41:10 +000024#include <assert.h>
25#include "sqliteInt.h"
26
27/*
28** Implementation of the non-aggregate min() and max() functions
29*/
30static void minFunc(sqlite_func *context, int argc, const char **argv){
31 const char *zBest;
32 int i;
33
drh89425d52002-02-28 03:04:48 +000034 if( argc==0 ) return;
drh0bce8352002-02-28 00:41:10 +000035 zBest = argv[0];
drh8912d102002-05-26 21:34:58 +000036 if( zBest==0 ) return;
drh0bce8352002-02-28 00:41:10 +000037 for(i=1; i<argc; i++){
drh8912d102002-05-26 21:34:58 +000038 if( argv[i]==0 ) return;
drh0bce8352002-02-28 00:41:10 +000039 if( sqliteCompare(argv[i], zBest)<0 ){
40 zBest = argv[i];
41 }
42 }
43 sqlite_set_result_string(context, zBest, -1);
44}
45static void maxFunc(sqlite_func *context, int argc, const char **argv){
46 const char *zBest;
47 int i;
48
drh89425d52002-02-28 03:04:48 +000049 if( argc==0 ) return;
drh0bce8352002-02-28 00:41:10 +000050 zBest = argv[0];
drh8912d102002-05-26 21:34:58 +000051 if( zBest==0 ) return;
drh0bce8352002-02-28 00:41:10 +000052 for(i=1; i<argc; i++){
drh8912d102002-05-26 21:34:58 +000053 if( argv[i]==0 ) return;
drh0bce8352002-02-28 00:41:10 +000054 if( sqliteCompare(argv[i], zBest)>0 ){
55 zBest = argv[i];
56 }
57 }
58 sqlite_set_result_string(context, zBest, -1);
59}
60
61/*
62** Implementation of the length() function
63*/
64static void lengthFunc(sqlite_func *context, int argc, const char **argv){
65 const char *z;
66 int len;
67
68 assert( argc==1 );
69 z = argv[0];
drh8912d102002-05-26 21:34:58 +000070 if( z==0 ) return;
drh0bce8352002-02-28 00:41:10 +000071#ifdef SQLITE_UTF8
drh8912d102002-05-26 21:34:58 +000072 for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; }
drh0bce8352002-02-28 00:41:10 +000073#else
drh8912d102002-05-26 21:34:58 +000074 len = strlen(z);
drh0bce8352002-02-28 00:41:10 +000075#endif
drh0bce8352002-02-28 00:41:10 +000076 sqlite_set_result_int(context, len);
77}
78
79/*
80** Implementation of the abs() function
81*/
82static void absFunc(sqlite_func *context, int argc, const char **argv){
83 const char *z;
84 assert( argc==1 );
85 z = argv[0];
drh8912d102002-05-26 21:34:58 +000086 if( z==0 ) return;
87 if( z[0]=='-' && isdigit(z[1]) ) z++;
drh0bce8352002-02-28 00:41:10 +000088 sqlite_set_result_string(context, z, -1);
89}
90
91/*
92** Implementation of the substr() function
93*/
94static void substrFunc(sqlite_func *context, int argc, const char **argv){
95 const char *z;
96#ifdef SQLITE_UTF8
97 const char *z2;
98 int i;
99#endif
100 int p1, p2, len;
101 assert( argc==3 );
102 z = argv[0];
103 if( z==0 ) return;
104 p1 = atoi(argv[1]?argv[1]:0);
105 p2 = atoi(argv[2]?argv[2]:0);
106#ifdef SQLITE_UTF8
drh47c8a672002-02-28 04:00:12 +0000107 for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z2)!=0x80 ) len++; }
drh0bce8352002-02-28 00:41:10 +0000108#else
109 len = strlen(z);
110#endif
111 if( p1<0 ){
drh89425d52002-02-28 03:04:48 +0000112 p1 += len;
drh653bc752002-02-28 03:31:10 +0000113 if( p1<0 ){
114 p2 += p1;
115 p1 = 0;
116 }
drh0bce8352002-02-28 00:41:10 +0000117 }else if( p1>0 ){
118 p1--;
119 }
120 if( p1+p2>len ){
121 p2 = len-p1;
122 }
123#ifdef SQLITE_UTF8
124 for(i=0; i<p1; i++){
125 assert( z[i] );
drh47c8a672002-02-28 04:00:12 +0000126 if( (z[i]&0xc0)==0x80 ) p1++;
drh0bce8352002-02-28 00:41:10 +0000127 }
drh47c8a672002-02-28 04:00:12 +0000128 while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p1++; }
drh0bce8352002-02-28 00:41:10 +0000129 for(; i<p1+p2; i++){
130 assert( z[i] );
drh47c8a672002-02-28 04:00:12 +0000131 if( (z[i]&0xc0)==0x80 ) p2++;
drh0bce8352002-02-28 00:41:10 +0000132 }
drh47c8a672002-02-28 04:00:12 +0000133 while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; }
drh0bce8352002-02-28 00:41:10 +0000134#endif
drh653bc752002-02-28 03:31:10 +0000135 if( p2<0 ) p2 = 0;
drh0bce8352002-02-28 00:41:10 +0000136 sqlite_set_result_string(context, &z[p1], p2);
137}
138
139/*
140** Implementation of the round() function
141*/
142static void roundFunc(sqlite_func *context, int argc, const char **argv){
143 int n;
144 double r;
145 char zBuf[100];
146 assert( argc==1 || argc==2 );
drh8912d102002-05-26 21:34:58 +0000147 if( argv[0]==0 || (argc==2 && argv[1]==0) ) return;
148 n = argc==2 ? atoi(argv[1]) : 0;
drh0bce8352002-02-28 00:41:10 +0000149 if( n>30 ) n = 30;
150 if( n<0 ) n = 0;
drh8912d102002-05-26 21:34:58 +0000151 r = atof(argv[0]);
drh0bce8352002-02-28 00:41:10 +0000152 sprintf(zBuf,"%.*f",n,r);
153 sqlite_set_result_string(context, zBuf, -1);
154}
drhdc04c582002-02-24 01:55:15 +0000155
156/*
157** Implementation of the upper() and lower() SQL functions.
158*/
drh1350b032002-02-27 19:00:20 +0000159static void upperFunc(sqlite_func *context, int argc, const char **argv){
drhdc04c582002-02-24 01:55:15 +0000160 char *z;
161 int i;
162 if( argc<1 || argv[0]==0 ) return;
163 z = sqlite_set_result_string(context, argv[0], -1);
164 if( z==0 ) return;
165 for(i=0; z[i]; i++){
166 if( islower(z[i]) ) z[i] = toupper(z[i]);
167 }
168}
drh1350b032002-02-27 19:00:20 +0000169static void lowerFunc(sqlite_func *context, int argc, const char **argv){
drhdc04c582002-02-24 01:55:15 +0000170 char *z;
171 int i;
172 if( argc<1 || argv[0]==0 ) return;
173 z = sqlite_set_result_string(context, argv[0], -1);
174 if( z==0 ) return;
175 for(i=0; z[i]; i++){
176 if( isupper(z[i]) ) z[i] = tolower(z[i]);
177 }
178}
179
180/*
drhfbc99082002-02-28 03:14:18 +0000181** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
182** All three do the same thing. They return the first argument
183** non-NULL argument.
drh3212e182002-02-28 00:46:26 +0000184*/
185static void ifnullFunc(sqlite_func *context, int argc, const char **argv){
drhfbc99082002-02-28 03:14:18 +0000186 int i;
187 for(i=0; i<argc; i++){
188 if( argv[i] ){
189 sqlite_set_result_string(context, argv[i], -1);
190 break;
191 }
192 }
drh3212e182002-02-28 00:46:26 +0000193}
194
195/*
drhf9ffac92002-03-02 19:00:31 +0000196** Implementation of random(). Return a random integer.
197*/
198static void randomFunc(sqlite_func *context, int argc, const char **argv){
199 sqlite_set_result_int(context, sqliteRandomInteger());
200}
201
202/*
drh6ed41ad2002-04-06 14:10:47 +0000203** Implementation of the last_insert_rowid() SQL function. The return
204** value is the same as the sqlite_last_insert_rowid() API function.
205*/
drh0ac65892002-04-20 14:24:41 +0000206static void last_insert_rowid(sqlite_func *context, int arg, const char **argv){
drh6ed41ad2002-04-06 14:10:47 +0000207 sqlite *db = sqlite_user_data(context);
208 sqlite_set_result_int(context, sqlite_last_insert_rowid(db));
209}
210
211/*
drh0ac65892002-04-20 14:24:41 +0000212** Implementation of the like() SQL function. This function implements
213** the build-in LIKE operator. The first argument to the function is the
214** string and the second argument is the pattern. So, the SQL statements:
215**
216** A LIKE B
217**
218** is implemented as like(A,B).
219*/
220static void likeFunc(sqlite_func *context, int arg, const char **argv){
drh8912d102002-05-26 21:34:58 +0000221 if( argv[0]==0 || argv[1]==0 ) return;
222 sqlite_set_result_int(context, sqliteLikeCompare(argv[0], argv[1]));
drh0ac65892002-04-20 14:24:41 +0000223}
224
225/*
226** Implementation of the glob() SQL function. This function implements
227** the build-in GLOB operator. The first argument to the function is the
228** string and the second argument is the pattern. So, the SQL statements:
229**
230** A GLOB B
231**
232** is implemented as glob(A,B).
233*/
234static void globFunc(sqlite_func *context, int arg, const char **argv){
drh8912d102002-05-26 21:34:58 +0000235 if( argv[0]==0 || argv[1]==0 ) return;
236 sqlite_set_result_int(context, sqliteGlobCompare(argv[0], argv[1]));
237}
238
239/*
240** Implementation of the NULLIF(x,y) function. The result is the first
241** argument if the arguments are different. The result is NULL if the
242** arguments are equal to each other.
243*/
244static void nullifFunc(sqlite_func *context, int argc, const char **argv){
245 if( argv[0]!=0 && sqliteCompare(argv[0],argv[1])!=0 ){
246 sqlite_set_result_string(context, argv[0], -1);
247 }
drh0ac65892002-04-20 14:24:41 +0000248}
249
drh193a6b42002-07-07 16:52:46 +0000250#ifdef SQLITE_TEST
251/*
252** This function generates a string of random characters. Used for
253** generating test data.
254*/
255static void randStr(sqlite_func *context, int argc, const char **argv){
256 static const char zSrc[] =
257 "abcdefghijklmnopqrstuvwxyz"
258 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
259 "0123456789"
260 ".-!,:*^+=_|?/<> ";
261 int iMin, iMax, n, r, i;
262 char zBuf[1000];
263 if( argc>=1 ){
264 iMin = atoi(argv[0]);
265 if( iMin<0 ) iMin = 0;
266 if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1;
267 }else{
268 iMin = 1;
269 }
270 if( argc>=2 ){
271 iMax = atoi(argv[1]);
272 if( iMax<iMin ) iMax = iMin;
273 if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf);
274 }else{
275 iMax = 50;
276 }
277 n = iMin;
278 if( iMax>iMin ){
279 r = sqliteRandomInteger();
280 if( r<0 ) r = -r;
281 n += r%(iMax + 1 - iMin);
282 }
283 r = 0;
284 for(i=0; i<n; i++){
285 r = (r + sqliteRandomByte())% (sizeof(zSrc)-1);
286 zBuf[i] = zSrc[r];
287 }
288 zBuf[n] = 0;
289 sqlite_set_result_string(context, zBuf, n);
290}
291#endif
292
drh0ac65892002-04-20 14:24:41 +0000293/*
drhd3a149e2002-02-24 17:12:53 +0000294** An instance of the following structure holds the context of a
drhdd5baa92002-02-27 19:50:59 +0000295** sum() or avg() aggregate computation.
296*/
297typedef struct SumCtx SumCtx;
298struct SumCtx {
299 double sum; /* Sum of terms */
drh739105c2002-05-29 23:22:23 +0000300 int cnt; /* Number of elements summed */
drhdd5baa92002-02-27 19:50:59 +0000301};
302
303/*
304** Routines used to compute the sum or average.
305*/
306static void sumStep(sqlite_func *context, int argc, const char **argv){
307 SumCtx *p;
drhdd5baa92002-02-27 19:50:59 +0000308 if( argc<1 ) return;
309 p = sqlite_aggregate_context(context, sizeof(*p));
drh739105c2002-05-29 23:22:23 +0000310 if( p && argv[0] ){
311 p->sum += atof(argv[0]);
312 p->cnt++;
313 }
drhdd5baa92002-02-27 19:50:59 +0000314}
315static void sumFinalize(sqlite_func *context){
316 SumCtx *p;
317 p = sqlite_aggregate_context(context, sizeof(*p));
drh89425d52002-02-28 03:04:48 +0000318 sqlite_set_result_double(context, p ? p->sum : 0.0);
drhdd5baa92002-02-27 19:50:59 +0000319}
320static void avgFinalize(sqlite_func *context){
321 SumCtx *p;
drhdd5baa92002-02-27 19:50:59 +0000322 p = sqlite_aggregate_context(context, sizeof(*p));
drh739105c2002-05-29 23:22:23 +0000323 if( p && p->cnt>0 ){
324 sqlite_set_result_double(context, p->sum/(double)p->cnt);
drhdd5baa92002-02-27 19:50:59 +0000325 }
326}
327
328/*
329** An instance of the following structure holds the context of a
drha2ed5602002-02-26 23:55:31 +0000330** variance or standard deviation computation.
drhd3a149e2002-02-24 17:12:53 +0000331*/
332typedef struct StdDevCtx StdDevCtx;
333struct StdDevCtx {
334 double sum; /* Sum of terms */
335 double sum2; /* Sum of the squares of terms */
drh739105c2002-05-29 23:22:23 +0000336 int cnt; /* Number of terms counted */
drhd3a149e2002-02-24 17:12:53 +0000337};
338
drhef2daf52002-03-04 02:26:15 +0000339#if 0 /* Omit because math library is required */
drhd3a149e2002-02-24 17:12:53 +0000340/*
341** Routines used to compute the standard deviation as an aggregate.
342*/
drh1350b032002-02-27 19:00:20 +0000343static void stdDevStep(sqlite_func *context, int argc, const char **argv){
drhd3a149e2002-02-24 17:12:53 +0000344 StdDevCtx *p;
345 double x;
drh1350b032002-02-27 19:00:20 +0000346 if( argc<1 ) return;
347 p = sqlite_aggregate_context(context, sizeof(*p));
drh739105c2002-05-29 23:22:23 +0000348 if( p && argv[0] ){
349 x = atof(argv[0]);
350 p->sum += x;
351 p->sum2 += x*x;
352 p->cnt++;
353 }
drhd3a149e2002-02-24 17:12:53 +0000354}
drh1350b032002-02-27 19:00:20 +0000355static void stdDevFinalize(sqlite_func *context){
drhdd5baa92002-02-27 19:50:59 +0000356 double rN = sqlite_aggregate_count(context);
drh1350b032002-02-27 19:00:20 +0000357 StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p));
drh739105c2002-05-29 23:22:23 +0000358 if( p && p->cnt>1 ){
359 double rCnt = cnt;
drhd3a149e2002-02-24 17:12:53 +0000360 sqlite_set_result_double(context,
drh739105c2002-05-29 23:22:23 +0000361 sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0)));
drhd3a149e2002-02-24 17:12:53 +0000362 }
drhd3a149e2002-02-24 17:12:53 +0000363}
drhef2daf52002-03-04 02:26:15 +0000364#endif
drhd3a149e2002-02-24 17:12:53 +0000365
drh0bce8352002-02-28 00:41:10 +0000366/*
367** The following structure keeps track of state information for the
368** count() aggregate function.
369*/
370typedef struct CountCtx CountCtx;
371struct CountCtx {
372 int n;
373};
drhdd5baa92002-02-27 19:50:59 +0000374
drh0bce8352002-02-28 00:41:10 +0000375/*
376** Routines to implement the count() aggregate function.
377*/
378static void countStep(sqlite_func *context, int argc, const char **argv){
379 CountCtx *p;
380 p = sqlite_aggregate_context(context, sizeof(*p));
381 if( (argc==0 || argv[0]) && p ){
382 p->n++;
383 }
384}
385static void countFinalize(sqlite_func *context){
386 CountCtx *p;
387 p = sqlite_aggregate_context(context, sizeof(*p));
drhf55f25f2002-02-28 01:46:11 +0000388 sqlite_set_result_int(context, p ? p->n : 0);
drh0bce8352002-02-28 00:41:10 +0000389}
390
391/*
392** This function tracks state information for the min() and max()
393** aggregate functions.
394*/
395typedef struct MinMaxCtx MinMaxCtx;
396struct MinMaxCtx {
397 char *z; /* The best so far */
398 char zBuf[28]; /* Space that can be used for storage */
399};
400
401/*
402** Routines to implement min() and max() aggregate functions.
403*/
404static void minStep(sqlite_func *context, int argc, const char **argv){
405 MinMaxCtx *p;
406 p = sqlite_aggregate_context(context, sizeof(*p));
drh739105c2002-05-29 23:22:23 +0000407 if( p==0 || argc<1 || argv[0]==0 ) return;
drhf570f012002-05-31 15:51:25 +0000408 if( p->z==0 || sqliteCompare(argv[0],p->z)<0 ){
drh8912d102002-05-26 21:34:58 +0000409 int len;
drh0bce8352002-02-28 00:41:10 +0000410 if( p->z && p->z!=p->zBuf ){
411 sqliteFree(p->z);
412 }
drh8912d102002-05-26 21:34:58 +0000413 len = strlen(argv[0]);
414 if( len < sizeof(p->zBuf) ){
415 p->z = p->zBuf;
drh0bce8352002-02-28 00:41:10 +0000416 }else{
drh8912d102002-05-26 21:34:58 +0000417 p->z = sqliteMalloc( len+1 );
418 if( p->z==0 ) return;
drh0bce8352002-02-28 00:41:10 +0000419 }
drh8912d102002-05-26 21:34:58 +0000420 strcpy(p->z, argv[0]);
drh0bce8352002-02-28 00:41:10 +0000421 }
422}
423static void maxStep(sqlite_func *context, int argc, const char **argv){
424 MinMaxCtx *p;
425 p = sqlite_aggregate_context(context, sizeof(*p));
drh739105c2002-05-29 23:22:23 +0000426 if( p==0 || argc<1 || argv[0]==0 ) return;
drhf570f012002-05-31 15:51:25 +0000427 if( p->z==0 || sqliteCompare(argv[0],p->z)>0 ){
drh8912d102002-05-26 21:34:58 +0000428 int len;
drh0bce8352002-02-28 00:41:10 +0000429 if( p->z && p->z!=p->zBuf ){
430 sqliteFree(p->z);
431 }
drh8912d102002-05-26 21:34:58 +0000432 len = strlen(argv[0]);
433 if( len < sizeof(p->zBuf) ){
434 p->z = p->zBuf;
drh0bce8352002-02-28 00:41:10 +0000435 }else{
drh8912d102002-05-26 21:34:58 +0000436 p->z = sqliteMalloc( len+1 );
437 if( p->z==0 ) return;
drh0bce8352002-02-28 00:41:10 +0000438 }
drh8912d102002-05-26 21:34:58 +0000439 strcpy(p->z, argv[0]);
drh0bce8352002-02-28 00:41:10 +0000440 }
441}
442static void minMaxFinalize(sqlite_func *context){
443 MinMaxCtx *p;
444 p = sqlite_aggregate_context(context, sizeof(*p));
drh739105c2002-05-29 23:22:23 +0000445 if( p && p->z ){
drh0bce8352002-02-28 00:41:10 +0000446 sqlite_set_result_string(context, p->z, strlen(p->z));
447 }
448 if( p && p->z && p->z!=p->zBuf ){
449 sqliteFree(p->z);
450 }
451}
drhdd5baa92002-02-27 19:50:59 +0000452
drhd3a149e2002-02-24 17:12:53 +0000453/*
drha2ed5602002-02-26 23:55:31 +0000454** This function registered all of the above C functions as SQL
455** functions. This should be the only routine in this file with
456** external linkage.
drhdc04c582002-02-24 01:55:15 +0000457*/
drh28f4b682002-06-09 10:14:18 +0000458void sqliteRegisterBuiltinFunctions(sqlite *db){
drh0bce8352002-02-28 00:41:10 +0000459 static struct {
460 char *zName;
461 int nArg;
drhc9b84a12002-06-20 11:36:48 +0000462 int dataType;
drh0bce8352002-02-28 00:41:10 +0000463 void (*xFunc)(sqlite_func*,int,const char**);
464 } aFuncs[] = {
drhc9b84a12002-06-20 11:36:48 +0000465 { "min", -1, SQLITE_ARGS, minFunc },
466 { "min", 0, 0, 0 },
467 { "max", -1, SQLITE_ARGS, maxFunc },
468 { "max", 0, 0, 0 },
469 { "length", 1, SQLITE_NUMERIC, lengthFunc },
470 { "substr", 3, SQLITE_TEXT, substrFunc },
471 { "abs", 1, SQLITE_NUMERIC, absFunc },
472 { "round", 1, SQLITE_NUMERIC, roundFunc },
473 { "round", 2, SQLITE_NUMERIC, roundFunc },
474 { "upper", 1, SQLITE_TEXT, upperFunc },
475 { "lower", 1, SQLITE_TEXT, lowerFunc },
476 { "coalesce", -1, SQLITE_ARGS, ifnullFunc },
477 { "coalesce", 0, 0, 0 },
478 { "coalesce", 1, 0, 0 },
479 { "ifnull", 2, SQLITE_ARGS, ifnullFunc },
480 { "random", -1, SQLITE_NUMERIC, randomFunc },
481 { "like", 2, SQLITE_NUMERIC, likeFunc },
482 { "glob", 2, SQLITE_NUMERIC, globFunc },
483 { "nullif", 2, SQLITE_ARGS, nullifFunc },
drh193a6b42002-07-07 16:52:46 +0000484#ifdef SQLITE_TEST
485 { "randstr", 2, SQLITE_TEXT, randStr },
486#endif
drh0bce8352002-02-28 00:41:10 +0000487 };
488 static struct {
489 char *zName;
490 int nArg;
drhc9b84a12002-06-20 11:36:48 +0000491 int dataType;
drh0bce8352002-02-28 00:41:10 +0000492 void (*xStep)(sqlite_func*,int,const char**);
493 void (*xFinalize)(sqlite_func*);
494 } aAggs[] = {
drhc9b84a12002-06-20 11:36:48 +0000495 { "min", 1, 0, minStep, minMaxFinalize },
496 { "max", 1, 0, maxStep, minMaxFinalize },
497 { "sum", 1, SQLITE_NUMERIC, sumStep, sumFinalize },
498 { "avg", 1, SQLITE_NUMERIC, sumStep, avgFinalize },
499 { "count", 0, SQLITE_NUMERIC, countStep, countFinalize },
500 { "count", 1, SQLITE_NUMERIC, countStep, countFinalize },
drhef2daf52002-03-04 02:26:15 +0000501#if 0
drhc9b84a12002-06-20 11:36:48 +0000502 { "stddev", 1, SQLITE_NUMERIC, stdDevStep, stdDevFinalize },
drhef2daf52002-03-04 02:26:15 +0000503#endif
drh0bce8352002-02-28 00:41:10 +0000504 };
505 int i;
506
507 for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
508 sqlite_create_function(db, aFuncs[i].zName,
509 aFuncs[i].nArg, aFuncs[i].xFunc, 0);
drhc9b84a12002-06-20 11:36:48 +0000510 if( aFuncs[i].xFunc ){
511 sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
512 }
drh0bce8352002-02-28 00:41:10 +0000513 }
drh6ed41ad2002-04-06 14:10:47 +0000514 sqlite_create_function(db, "last_insert_rowid", 0,
515 last_insert_rowid, db);
drhc9b84a12002-06-20 11:36:48 +0000516 sqlite_function_type(db, "last_insert_rowid", SQLITE_NUMERIC);
drh0bce8352002-02-28 00:41:10 +0000517 for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
518 sqlite_create_aggregate(db, aAggs[i].zName,
519 aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, 0);
drhc9b84a12002-06-20 11:36:48 +0000520 sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType);
drh0bce8352002-02-28 00:41:10 +0000521 }
drhdc04c582002-02-24 01:55:15 +0000522}