/* ** 2002 February 23 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** 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.60 2004/05/27 09:28:42 danielk1977 Exp $ */ #include #include #include #include #include "sqliteInt.h" #include "vdbeInt.h" #include "os.h" /* ** Implementation of the non-aggregate min() and max() functions */ static void minmaxFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ int i; int mask; /* 0 for min() or 0xffffffff for max() */ int iBest; if( argc==0 ) return; mask = (int)sqlite3_user_data(context); assert( mask==-1 || mask==0 ); iBest = 0; for(i=1; i=0 ){ iBest = i; } } sqlite3_result_value(context, argv[iBest]); } /* ** Return the type of the argument. */ static void typeofFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *z = 0; switch( sqlite3_value_type(argv[0]) ){ case SQLITE3_NULL: z = "null"; break; case SQLITE3_INTEGER: z = "integer"; break; case SQLITE3_TEXT: z = "text"; break; case SQLITE3_FLOAT: z = "real"; break; case SQLITE3_BLOB: z = "blob"; break; } sqlite3_result_text(context, z, -1, 0); } /* ** Implementation of the length() function */ static void lengthFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ int len; assert( argc==1 ); switch( sqlite3_value_type(argv[0]) ){ case SQLITE3_BLOB: case SQLITE3_INTEGER: case SQLITE3_FLOAT: { sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); break; } case SQLITE3_TEXT: { const char *z = sqlite3_value_text(argv[0]); for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } sqlite3_result_int(context, len); break; } default: { sqlite3_result_null(context); break; } } } /* ** Implementation of the abs() function */ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ assert( argc==1 ); switch( sqlite3_value_type(argv[0]) ){ case SQLITE3_INTEGER: { sqlite3_result_int64(context, -sqlite3_value_int64(argv[0])); break; } case SQLITE3_NULL: { sqlite3_result_null(context); break; } default: { sqlite3_result_double(context, -sqlite3_value_double(argv[0])); break; } } } /* ** Implementation of the substr() function */ static void substrFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *z; const char *z2; int i; int p1, p2, len; assert( argc==3 ); z = sqlite3_value_text(argv[0]); if( z==0 ) return; p1 = sqlite3_value_int(argv[1]); p2 = sqlite3_value_int(argv[2]); for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z2)!=0x80 ) len++; } if( p1<0 ){ p1 += len; if( p1<0 ){ p2 += p1; p1 = 0; } }else if( p1>0 ){ p1--; } if( p1+p2>len ){ p2 = len-p1; } for(i=0; i30 ) n = 30; if( n<0 ) n = 0; } if( SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return; r = sqlite3_value_double(argv[0]); sprintf(zBuf,"%.*f",n,r); sqlite3_result_text(context, zBuf, -1, 1); } /* ** Implementation of the upper() and lower() SQL functions. */ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ char *z; int i; if( argc<1 || SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); if( z==0 ) return; strcpy(z, sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ if( islower(z[i]) ) z[i] = toupper(z[i]); } sqlite3_result_text(context, z, -1, 1); sqliteFree(z); } static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ char *z; int i; if( argc<1 || SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])+1); if( z==0 ) return; strcpy(z, sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ if( isupper(z[i]) ) z[i] = tolower(z[i]); } sqlite3_result_text(context, z, -1, 1); sqliteFree(z); } /* ** Implementation of the IFNULL(), NVL(), and COALESCE() functions. ** All three do the same thing. They return the first non-NULL ** argument. */ static void ifnullFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ int i; for(i=0; i0 ){ zResult[j++] = code + '0'; } } while( j<4 ){ zResult[j++] = '0'; } zResult[j] = 0; sqlite3_result_text(context, zResult, 4, 1); }else{ sqlite3_result_text(context, "?000", 4, 0); } } #endif #ifdef SQLITE_TEST /* ** This function generates a string of random characters. Used for ** generating test data. */ static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ static const unsigned char zSrc[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" ".-!,:*^+=_|?/<> "; int iMin, iMax, n, r, i; unsigned char zBuf[1000]; if( argc>=1 ){ iMin = sqlite3_value_int(argv[0]); if( iMin<0 ) iMin = 0; if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; }else{ iMin = 1; } if( argc>=2 ){ iMax = sqlite3_value_int(argv[1]); if( iMax=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; }else{ iMax = 50; } n = iMin; if( iMax>iMin ){ sqlite3Randomness(sizeof(r), &r); r &= 0x7fffffff; n += r%(iMax + 1 - iMin); } assert( nsum += sqlite3_value_double(argv[0]); p->cnt++; } } static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, sizeof(*p)); sqlite3_result_double(context, p ? p->sum : 0.0); } static void avgFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, sizeof(*p)); if( p && p->cnt>0 ){ sqlite3_result_double(context, p->sum/(double)p->cnt); } } /* ** 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 cnt; /* Number of terms counted */ }; #if 0 /* Omit because math library is required */ /* ** Routines used to compute the standard deviation as an aggregate. */ static void stdDevStep(sqlite3_context *context, int argc, const char **argv){ StdDevCtx *p; double x; if( argc<1 ) return; p = sqlite3_aggregate_context(context, sizeof(*p)); if( p && argv[0] ){ x = sqlite3AtoF(argv[0], 0); p->sum += x; p->sum2 += x*x; p->cnt++; } } static void stdDevFinalize(sqlite3_context *context){ double rN = sqlite3_aggregate_count(context); StdDevCtx *p = sqlite3_aggregate_context(context, sizeof(*p)); if( p && p->cnt>1 ){ double rCnt = cnt; sqlite3_set_result_double(context, sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0))); } } #endif /* ** The following structure keeps track of state information for the ** count() aggregate function. */ typedef struct CountCtx CountCtx; struct CountCtx { int n; }; /* ** Routines to implement the count() aggregate function. */ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ CountCtx *p; p = sqlite3_aggregate_context(context, sizeof(*p)); if( (argc==0 || SQLITE3_NULL!=sqlite3_value_type(argv[0])) && p ){ p->n++; } } static void countFinalize(sqlite3_context *context){ CountCtx *p; p = sqlite3_aggregate_context(context, sizeof(*p)); sqlite3_result_int(context, p ? p->n : 0); } /* ** This function tracks state information for the min() and max() ** aggregate functions. */ typedef struct MinMaxCtx MinMaxCtx; struct MinMaxCtx { char *z; /* The best so far */ char zBuf[28]; /* Space that can be used for storage */ }; /* ** Routines to implement min() and max() aggregate functions. */ static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv){ int max = 0; int cmp = 0; Mem *pArg = (Mem *)argv[0]; Mem *pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); if( SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return; if( pBest->flags ){ /* This step function is used for both the min() and max() aggregates, ** the only difference between the two being that the sense of the ** comparison is inverted. For the max() aggregate, the ** sqlite3_user_data() function returns (void *)-1. For min() it ** returns (void *)db, where db is the sqlite3* database pointer. ** Therefore the next statement sets variable 'max' to 1 for the max() ** aggregate, or 0 for min(). */ max = ((sqlite3_user_data(context)==(void *)-1)?1:0); cmp = sqlite3MemCompare(pBest, pArg, 0); if( (max && cmp<0) || (!max && cmp>0) ){ sqlite3VdbeMemCopy(pBest, pArg); } }else{ sqlite3VdbeMemCopy(pBest, pArg); } } static void minMaxFinalize(sqlite3_context *context){ sqlite3_value *pRes; pRes = (sqlite3_value *)sqlite3_aggregate_context(context, sizeof(Mem)); if( pRes->flags ){ sqlite3_result_value(context, pRes); } } /* ** 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 sqlite3RegisterBuiltinFunctions(sqlite *db){ static struct { char *zName; signed char nArg; u8 argType; /* 0: none. 1: db 2: (-1) */ void (*xFunc)(sqlite3_context*,int,sqlite3_value **); } aFuncs[] = { { "min", -1, 0, minmaxFunc }, { "min", 0, 0, 0 }, { "max", -1, 2, minmaxFunc }, { "max", 0, 2, 0 }, { "typeof", 1, 0, typeofFunc }, { "classof", 1, 0, typeofFunc }, /* FIX ME: hack */ { "length", 1, 0, lengthFunc }, { "substr", 3, 0, substrFunc }, { "abs", 1, 0, absFunc }, { "round", 1, 0, roundFunc }, { "round", 2, 0, roundFunc }, { "upper", 1, 0, upperFunc }, { "lower", 1, 0, lowerFunc }, { "coalesce", -1, 0, ifnullFunc }, { "coalesce", 0, 0, 0 }, { "coalesce", 1, 0, 0 }, { "ifnull", 2, 0, ifnullFunc }, { "random", -1, 0, randomFunc }, { "like", 2, 0, likeFunc }, { "glob", 2, 0, globFunc }, { "nullif", 2, 0, nullifFunc }, { "sqlite_version", 0, 0, versionFunc}, { "quote", 1, 0, quoteFunc }, { "last_insert_rowid", 0, 1, last_insert_rowid }, { "change_count", 0, 1, change_count }, { "last_statement_change_count", 0, 1, last_statement_change_count }, #ifdef SQLITE_SOUNDEX { "soundex", 1, 0, soundexFunc}, #endif #ifdef SQLITE_TEST { "randstr", 2, 0, randStr }, #endif }; static struct { char *zName; signed char nArg; u8 argType; void (*xStep)(sqlite3_context*,int,sqlite3_value**); void (*xFinalize)(sqlite3_context*); } aAggs[] = { { "min", 1, 0, minmaxStep, minMaxFinalize }, { "max", 1, 2, minmaxStep, minMaxFinalize }, { "sum", 1, 0, sumStep, sumFinalize }, { "avg", 1, 0, sumStep, avgFinalize }, { "count", 0, 0, countStep, countFinalize }, { "count", 1, 0, countStep, countFinalize }, #if 0 { "stddev", 1, 0, stdDevStep, stdDevFinalize }, #endif }; int i; for(i=0; i