/* ** EXPERIMENTAL - This is not an official function. The interface may ** change. This function may disappear. Do not write code that depends ** on this function. ** ** Implementation of the QUOTE() function. This function takes a single ** argument. If the argument is numeric, the return value is the same as ** the argument. If the argument is NULL, the return value is the string ** "NULL". Otherwise, the argument is enclosed in single quotes with ** single-quote escapes. */ static void quoteFunc(sqlite_func *context, int argc, const char **argv){ if( argc<1 ) return; if( argv[0]==0 ){ sqlite_set_result_string(context, "NULL", 4); }else if( sqliteIsNumber(argv[0]) ){ sqlite_set_result_string(context, argv[0], -1); }else{ int i,j,n; char *z; for(i=n=0; argv[0][i]; i++){ if( argv[0][i]=='\'' ) n++; } z = sqliteMalloc( i+n+3 ); if( z==0 ) return; z[0] = '\''; for(i=0, j=1; argv[0][i]; i++){ z[j++] = argv[0][i]; if( argv[0][i]=='\'' ){ z[j++] = '\''; } } z[j++] = '\''; z[j] = 0; sqlite_set_result_string(context, z, j); sqliteFree(z); } }
/* ** Compute the soundex encoding of a word. */ static void soundexFunc(sqlite_func *context, int argc, const char **argv){ char zResult[8]; const char *zIn; int i, j; static const unsigned char iCode[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, }; assert( argc==1 ); zIn = argv[0]; for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} if( zIn[i] ){ zResult[0] = toupper(zIn[i]); for(j=1; j<4 && zIn[i]; i++){ int code = iCode[zIn[i]&0x7f]; if( code>0 ){ zResult[j++] = code + '0'; } } while( j<4 ){ zResult[j++] = '0'; } zResult[j] = 0; sqlite_set_result_string(context, zResult, 4); }else{ sqlite_set_result_string(context, "?000", 4); } }
/* ** Implementation of the abs() function */ static void absFunc(sqlite_func *context, int argc, const char **argv){ const char *z; assert( argc==1 ); z = argv[0]; if( z==0 ) return; if( z[0]=='-' && isdigit(z[1]) ) z++; sqlite_set_result_string(context, z, -1); }
/* ** Implementation of the x_sqlite_exec() function. This function takes ** a single argument and attempts to execute that argument as SQL code. ** This is illegal and should set the SQLITE_MISUSE flag on the database. ** ** 2004-Jan-07: We have changed this to make it legal to call sqlite_exec() ** from within a function call. ** ** This routine simulates the effect of having two threads attempt to ** use the same database at the same time. */ static void sqliteExecFunc(sqlite_func *context, int argc, const char **argv){ struct dstr x; memset(&x, 0, sizeof(x)); sqlite_exec((sqlite*)sqlite_user_data(context), argv[0], execFuncCallback, &x, 0); sqlite_set_result_string(context, x.z, x.nUsed); sqliteFree(x.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(sqlite_func *context, int argc, const char **argv){ int i; for(i=0; i<argc; i++){ if( argv[i] ){ sqlite_set_result_string(context, argv[i], -1); break; } } }
/* ** time( TIMESTRING, MOD, MOD, ...) ** ** Return HH:MM:SS */ static void timeFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x)==0 ){ char zBuf[100]; computeHMS(&x); sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s); sqlite_set_result_string(context, zBuf, -1); } }
/* ** date( TIMESTRING, MOD, MOD, ...) ** ** Return YYYY-MM-DD */ static void dateFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; if( isDate(argc, argv, &x)==0 ){ char zBuf[100]; computeYMD(&x); sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D); sqlite_set_result_string(context, zBuf, -1); } }
static void minMaxFinalize(sqlite_func *context){ MinMaxCtx *p; p = sqlite_aggregate_context(context, sizeof(*p)); if( p && p->z && p->zBuf[0]<2 ){ sqlite_set_result_string(context, p->z, strlen(p->z)); } if( p && p->zBuf[0] ){ sqliteFree(p->z); } }
static void lowerFunc(sqlite_func *context, int argc, const char **argv){ unsigned char *z; int i; if( argc<1 || argv[0]==0 ) return; z = (unsigned char*)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]); } }
/* ** Implementation of the round() function */ static void roundFunc(sqlite_func *context, int argc, const char **argv){ int n; double r; char zBuf[100]; assert( argc==1 || argc==2 ); if( argv[0]==0 || (argc==2 && argv[1]==0) ) return; n = argc==2 ? atoi(argv[1]) : 0; if( n>30 ) n = 30; if( n<0 ) n = 0; r = sqliteAtoF(argv[0], 0); sprintf(zBuf,"%.*f",n,r); sqlite_set_result_string(context, zBuf, -1); }
/* ** Implementation of the substr() function */ static void substrFunc(sqlite_func *context, int argc, const char **argv) { const char *z; #ifdef SQLITE_UTF8 const char *z2; int i; #endif int p1, p2, len; assert( argc==3 ); z = argv[0]; if( z==0 ) return; p1 = atoi(argv[1]?argv[1]:0); p2 = atoi(argv[2]?argv[2]:0); #ifdef SQLITE_UTF8 for(len=0, z2=z; *z2; z2++) { if( (0xc0&*z2)!=0x80 ) len++; } #else len = strlen(z); #endif if( p1<0 ) { p1 += len; if( p1<0 ) { p2 += p1; p1 = 0; } } else if( p1>0 ) { p1--; } if( p1+p2>len ) { p2 = len-p1; } #ifdef SQLITE_UTF8 for(i=0; i<p1 && z[i]; i++) { if( (z[i]&0xc0)==0x80 ) p1++; } while( z[i] && (z[i]&0xc0)==0x80 ) { i++; p1++; } for(; i<p1+p2 && z[i]; i++) { if( (z[i]&0xc0)==0x80 ) p2++; } while( z[i] && (z[i]&0xc0)==0x80 ) { i++; p2++; } #endif if( p2<0 ) p2 = 0; sqlite_set_result_string(context, &z[p1], p2); }
/* ** This routine is called to evaluate an SQL function implemented ** using TCL script. */ static void tclSqlFunc(sqlite_func *context, int argc, const char **argv){ SqlFunc *p = sqlite_user_data(context); Tcl_DString cmd; int i; int rc; Tcl_DStringInit(&cmd); Tcl_DStringAppend(&cmd, p->zScript, -1); for(i=0; i<argc; i++){ Tcl_DStringAppendElement(&cmd, argv[i] ? argv[i] : ""); } rc = Tcl_Eval(p->interp, Tcl_DStringValue(&cmd)); if( rc ){ sqlite_set_result_error(context, Tcl_GetStringResult(p->interp), -1); }else{ sqlite_set_result_string(context, Tcl_GetStringResult(p->interp), -1); } }
/* ** The following routine is a user-defined SQL function whose purpose ** is to test the sqlite_set_result() API. */ static void testFunc(sqlite_func *context, int argc, const char **argv){ while( argc>=2 ){ if( argv[0]==0 ){ sqlite_set_result_error(context, "first argument to test function " "may not be NULL", -1); }else if( sqliteStrICmp(argv[0],"string")==0 ){ sqlite_set_result_string(context, argv[1], -1); }else if( argv[1]==0 ){ sqlite_set_result_error(context, "2nd argument may not be NULL if the " "first argument is not \"string\"", -1); }else if( sqliteStrICmp(argv[0],"int")==0 ){ sqlite_set_result_int(context, atoi(argv[1])); }else if( sqliteStrICmp(argv[0],"double")==0 ){ sqlite_set_result_double(context, sqliteAtoF(argv[1], 0)); }else{ sqlite_set_result_error(context,"first argument should be one of: " "string int double", -1); } argc -= 2; argv += 2; } }
/* ** Implementation of the non-aggregate min() and max() functions */ static void minmaxFunc(sqlite_func *context, int argc, const char **argv){ const char *zBest; int i; int (*xCompare)(const char*, const char*); int mask; /* 0 for min() or 0xffffffff for max() */ if( argc==0 ) return; mask = (int)sqlite_user_data(context); zBest = argv[0]; if( zBest==0 ) return; if( argv[1][0]=='n' ){ xCompare = sqliteCompare; }else{ xCompare = strcmp; } for(i=2; i<argc; i+=2){ if( argv[i]==0 ) return; if( (xCompare(argv[i], zBest)^mask)<0 ){ zBest = argv[i]; } } sqlite_set_result_string(context, zBest, -1); }
/* ** This function generates a string of random characters. Used for ** generating test data. */ static void randStr(sqlite_func *context, int argc, const char **argv){ static const unsigned char zSrc[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" ".-!,:*^+=_|?/<> "; int iMin, iMax, n, r, i; unsigned char zBuf[1000]; if( argc>=1 ){ iMin = atoi(argv[0]); if( iMin<0 ) iMin = 0; if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; }else{ iMin = 1; } if( argc>=2 ){ iMax = atoi(argv[1]); if( iMax<iMin ) iMax = iMin; if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; }else{ iMax = 50; } n = iMin; if( iMax>iMin ){ sqliteRandomness(sizeof(r), &r); r &= 0x7fffffff; n += r%(iMax + 1 - iMin); } assert( n<sizeof(zBuf) ); sqliteRandomness(n, zBuf); for(i=0; i<n; i++){ zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; } zBuf[n] = 0; sqlite_set_result_string(context, zBuf, n); }
/* ** Return the type of the argument. */ static void typeofFunc(sqlite_func *context, int argc, const char **argv){ assert( argc==2 ); sqlite_set_result_string(context, argv[1], -1); }
/* ** Implementation of the VERSION(*) function. The result is the version ** of the SQLite library that is running. */ static void versionFunc(sqlite_func *context, int argc, const char **argv){ sqlite_set_result_string(context, sqlite_version, -1); }
/* ** Implementation of the NULLIF(x,y) function. The result is the first ** argument if the arguments are different. The result is NULL if the ** arguments are equal to each other. */ static void nullifFunc(sqlite_func *context, int argc, const char **argv){ if( argv[0]!=0 && sqliteCompare(argv[0],argv[1])!=0 ){ sqlite_set_result_string(context, argv[0], -1); } }
void sqlite_set_result_error(sqlite_func *p, const char *zMsg, int n){ assert( !p->isStep ); sqlite_set_result_string(p, zMsg, n); p->isError = 1; }
/* ** strftime( FORMAT, TIMESTRING, MOD, MOD, ...) ** ** Return a string described by FORMAT. Conversions as follows: ** ** %d day of month ** %f ** fractional seconds SS.SSS ** %H hour 00-24 ** %j day of year 000-366 ** %J ** Julian day number ** %m month 01-12 ** %M minute 00-59 ** %s seconds since 1970-01-01 ** %S seconds 00-59 ** %w day of week 0-6 sunday==0 ** %W week of year 00-53 ** %Y year 0000-9999 ** %% % */ static void strftimeFunc(sqlite_func *context, int argc, const char **argv){ DateTime x; int n, i, j; char *z; const char *zFmt = argv[0]; char zBuf[100]; if( argv[0]==0 || isDate(argc-1, argv+1, &x) ) return; for(i=0, n=1; zFmt[i]; i++, n++){ if( zFmt[i]=='%' ){ switch( zFmt[i+1] ){ case 'd': case 'H': case 'm': case 'M': case 'S': case 'W': n++; /* fall thru */ case 'w': case '%': break; case 'f': n += 8; break; case 'j': n += 3; break; case 'Y': n += 8; break; case 's': case 'J': n += 50; break; default: return; /* ERROR. return a NULL */ } i++; } } if( n<sizeof(zBuf) ){ z = zBuf; }else{ z = sqliteMalloc( n ); if( z==0 ) return; } computeJD(&x); computeYMD_HMS(&x); for(i=j=0; zFmt[i]; i++){ if( zFmt[i]!='%' ){ z[j++] = zFmt[i]; }else{ i++; switch( zFmt[i] ){ case 'd': sprintf(&z[j],"%02d",x.D); j+=2; break; case 'f': { int s = x.s; int ms = (x.s - s)*1000.0; sprintf(&z[j],"%02d.%03d",s,ms); j += strlen(&z[j]); break; } case 'H': sprintf(&z[j],"%02d",x.h); j+=2; break; case 'W': /* Fall thru */ case 'j': { int n; DateTime y = x; y.validJD = 0; y.M = 1; y.D = 1; computeJD(&y); n = x.rJD - y.rJD + 1; if( zFmt[i]=='W' ){ sprintf(&z[j],"%02d",(n+6)/7); j += 2; }else{ sprintf(&z[j],"%03d",n); j += 3; } break; } case 'J': sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break; case 'm': sprintf(&z[j],"%02d",x.M); j+=2; break; case 'M': sprintf(&z[j],"%02d",x.m); j+=2; break; case 's': { sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5)); j += strlen(&z[j]); break; } case 'S': sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break; case 'w': z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break; case 'Y': sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break; case '%': z[j++] = '%'; break; } } } z[j] = 0; sqlite_set_result_string(context, z, -1); if( z!=zBuf ){ sqliteFree(z); } }