11728bcb0Sdrh /*
21728bcb0Sdrh ** 2014-11-10
31728bcb0Sdrh **
41728bcb0Sdrh ** The author disclaims copyright to this source code. In place of
51728bcb0Sdrh ** a legal notice, here is a blessing:
61728bcb0Sdrh **
71728bcb0Sdrh ** May you do good and not evil.
81728bcb0Sdrh ** May you find forgiveness for yourself and forgive others.
91728bcb0Sdrh ** May you share freely, never taking more than you give.
101728bcb0Sdrh **
111728bcb0Sdrh ******************************************************************************
121728bcb0Sdrh **
131728bcb0Sdrh ** This SQLite extension implements SQL function eval() which runs
141728bcb0Sdrh ** SQL statements recursively.
151728bcb0Sdrh */
161728bcb0Sdrh #include "sqlite3ext.h"
171728bcb0Sdrh SQLITE_EXTENSION_INIT1
181728bcb0Sdrh #include <string.h>
191728bcb0Sdrh
201728bcb0Sdrh /*
211728bcb0Sdrh ** Structure used to accumulate the output
221728bcb0Sdrh */
231728bcb0Sdrh struct EvalResult {
241728bcb0Sdrh char *z; /* Accumulated output */
251728bcb0Sdrh const char *zSep; /* Separator */
261728bcb0Sdrh int szSep; /* Size of the separator string */
272c3abeb8Sdrh sqlite3_int64 nAlloc; /* Number of bytes allocated for z[] */
282c3abeb8Sdrh sqlite3_int64 nUsed; /* Number of bytes of z[] actually used */
291728bcb0Sdrh };
301728bcb0Sdrh
311728bcb0Sdrh /*
321728bcb0Sdrh ** Callback from sqlite_exec() for the eval() function.
331728bcb0Sdrh */
callback(void * pCtx,int argc,char ** argv,char ** colnames)341728bcb0Sdrh static int callback(void *pCtx, int argc, char **argv, char **colnames){
351728bcb0Sdrh struct EvalResult *p = (struct EvalResult*)pCtx;
361728bcb0Sdrh int i;
3733fc2779Smistachkin if( argv==0 ) return 0;
381728bcb0Sdrh for(i=0; i<argc; i++){
391728bcb0Sdrh const char *z = argv[i] ? argv[i] : "";
401728bcb0Sdrh size_t sz = strlen(z);
412c3abeb8Sdrh if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
421728bcb0Sdrh char *zNew;
431728bcb0Sdrh p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
442c3abeb8Sdrh /* Using sqlite3_realloc64() would be better, but it is a recent
452c3abeb8Sdrh ** addition and will cause a segfault if loaded by an older version
462c3abeb8Sdrh ** of SQLite. */
472d77d80aSdrh zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc64(p->z, p->nAlloc) : 0;
481728bcb0Sdrh if( zNew==0 ){
491728bcb0Sdrh sqlite3_free(p->z);
501728bcb0Sdrh memset(p, 0, sizeof(*p));
511728bcb0Sdrh return 1;
521728bcb0Sdrh }
531728bcb0Sdrh p->z = zNew;
541728bcb0Sdrh }
551728bcb0Sdrh if( p->nUsed>0 ){
561728bcb0Sdrh memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
571728bcb0Sdrh p->nUsed += p->szSep;
581728bcb0Sdrh }
591728bcb0Sdrh memcpy(&p->z[p->nUsed], z, sz);
601728bcb0Sdrh p->nUsed += sz;
611728bcb0Sdrh }
621728bcb0Sdrh return 0;
631728bcb0Sdrh }
641728bcb0Sdrh
651728bcb0Sdrh /*
661728bcb0Sdrh ** Implementation of the eval(X) and eval(X,Y) SQL functions.
671728bcb0Sdrh **
681728bcb0Sdrh ** Evaluate the SQL text in X. Return the results, using string
691728bcb0Sdrh ** Y as the separator. If Y is omitted, use a single space character.
701728bcb0Sdrh */
sqlEvalFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)711728bcb0Sdrh static void sqlEvalFunc(
721728bcb0Sdrh sqlite3_context *context,
731728bcb0Sdrh int argc,
741728bcb0Sdrh sqlite3_value **argv
751728bcb0Sdrh ){
761728bcb0Sdrh const char *zSql;
771728bcb0Sdrh sqlite3 *db;
781728bcb0Sdrh char *zErr = 0;
791728bcb0Sdrh int rc;
801728bcb0Sdrh struct EvalResult x;
811728bcb0Sdrh
821728bcb0Sdrh memset(&x, 0, sizeof(x));
831728bcb0Sdrh x.zSep = " ";
841728bcb0Sdrh zSql = (const char*)sqlite3_value_text(argv[0]);
851728bcb0Sdrh if( zSql==0 ) return;
861728bcb0Sdrh if( argc>1 ){
871728bcb0Sdrh x.zSep = (const char*)sqlite3_value_text(argv[1]);
881728bcb0Sdrh if( x.zSep==0 ) return;
891728bcb0Sdrh }
901728bcb0Sdrh x.szSep = (int)strlen(x.zSep);
911728bcb0Sdrh db = sqlite3_context_db_handle(context);
921728bcb0Sdrh rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
931728bcb0Sdrh if( rc!=SQLITE_OK ){
941728bcb0Sdrh sqlite3_result_error(context, zErr, -1);
951728bcb0Sdrh sqlite3_free(zErr);
961728bcb0Sdrh }else if( x.zSep==0 ){
971728bcb0Sdrh sqlite3_result_error_nomem(context);
981728bcb0Sdrh sqlite3_free(x.z);
991728bcb0Sdrh }else{
1002c3abeb8Sdrh sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
1011728bcb0Sdrh }
1021728bcb0Sdrh }
1031728bcb0Sdrh
1041728bcb0Sdrh
1051728bcb0Sdrh #ifdef _WIN32
1061728bcb0Sdrh __declspec(dllexport)
1071728bcb0Sdrh #endif
sqlite3_eval_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)1081728bcb0Sdrh int sqlite3_eval_init(
1091728bcb0Sdrh sqlite3 *db,
1101728bcb0Sdrh char **pzErrMsg,
1111728bcb0Sdrh const sqlite3_api_routines *pApi
1121728bcb0Sdrh ){
1131728bcb0Sdrh int rc = SQLITE_OK;
1141728bcb0Sdrh SQLITE_EXTENSION_INIT2(pApi);
1151728bcb0Sdrh (void)pzErrMsg; /* Unused parameter */
116*2b1c2aadSdrh rc = sqlite3_create_function(db, "eval", 1,
117*2b1c2aadSdrh SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
1181728bcb0Sdrh sqlEvalFunc, 0, 0);
1191728bcb0Sdrh if( rc==SQLITE_OK ){
120*2b1c2aadSdrh rc = sqlite3_create_function(db, "eval", 2,
121*2b1c2aadSdrh SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
1221728bcb0Sdrh sqlEvalFunc, 0, 0);
1231728bcb0Sdrh }
1241728bcb0Sdrh return rc;
1251728bcb0Sdrh }
126