/* ** Routines to implement min() and max() aggregate functions. */ static void minmaxStep(sqlite_func *context, int argc, const char **argv){ MinMaxCtx *p; int (*xCompare)(const char*, const char*); int mask; /* 0 for min() or 0xffffffff for max() */ assert( argc==2 ); if( argv[0]==0 ) return; /* Ignore NULL values */ if( argv[1][0]=='n' ){ xCompare = sqliteCompare; }else{ xCompare = strcmp; } mask = (int)sqlite_user_data(context); assert( mask==0 || mask==-1 ); p = sqlite_aggregate_context(context, sizeof(*p)); if( p==0 || argc<1 ) return; if( p->z==0 || (xCompare(argv[0],p->z)^mask)<0 ){ int len; if( p->zBuf[0] ){ sqliteFree(p->z); } len = strlen(argv[0]); if( len < sizeof(p->zBuf)-1 ){ p->z = &p->zBuf[1]; p->zBuf[0] = 0; }else{ p->z = sqliteMalloc( len+1 ); p->zBuf[0] = 1; if( p->z==0 ) return; } strcpy(p->z, argv[0]); } }
/* ** 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); }
/* ** 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); } }
/* ** 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); }
/* ** Implementation of the last_statement_change_count() SQL function. The ** return value is the same as the sqlite_last_statement_changes() API function. */ static void last_statement_change_count(sqlite_func *context, int arg, const char **argv){ sqlite *db = sqlite_user_data(context); sqlite_set_result_int(context, sqlite_last_statement_changes(db)); }
/* ** Implementation of the last_insert_rowid() SQL function. The return ** value is the same as the sqlite_last_insert_rowid() API function. */ static void last_insert_rowid(sqlite_func *context, int arg, const char **argv){ sqlite *db = sqlite_user_data(context); sqlite_set_result_int(context, sqlite_last_insert_rowid(db)); }