xref: /sqlite-3.40.0/ext/misc/eval.c (revision 1728bcb0)
1 /*
2 ** 2014-11-10
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 **
13 ** This SQLite extension implements SQL function eval() which runs
14 ** SQL statements recursively.
15 */
16 #include "sqlite3ext.h"
17 SQLITE_EXTENSION_INIT1
18 #include <string.h>
19 
20 /*
21 ** Structure used to accumulate the output
22 */
23 struct EvalResult {
24   char *z;            /* Accumulated output */
25   const char *zSep;   /* Separator */
26   int szSep;          /* Size of the separator string */
27   int nAlloc;         /* Number of bytes allocated for z[] */
28   int nUsed;          /* Number of bytes of z[] actually used */
29 };
30 
31 /*
32 ** Callback from sqlite_exec() for the eval() function.
33 */
34 static int callback(void *pCtx, int argc, char **argv, char **colnames){
35   struct EvalResult *p = (struct EvalResult*)pCtx;
36   int i;
37   for(i=0; i<argc; i++){
38     const char *z = argv[i] ? argv[i] : "";
39     size_t sz = strlen(z);
40     if( sz+p->nUsed+p->szSep+1 > p->nAlloc ){
41       char *zNew;
42       p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
43       zNew = sqlite3_realloc(p->z, p->nAlloc);
44       if( zNew==0 ){
45         sqlite3_free(p->z);
46         memset(p, 0, sizeof(*p));
47         return 1;
48       }
49       p->z = zNew;
50     }
51     if( p->nUsed>0 ){
52       memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
53       p->nUsed += p->szSep;
54     }
55     memcpy(&p->z[p->nUsed], z, sz);
56     p->nUsed += sz;
57   }
58   return 0;
59 }
60 
61 /*
62 ** Implementation of the eval(X) and eval(X,Y) SQL functions.
63 **
64 ** Evaluate the SQL text in X.  Return the results, using string
65 ** Y as the separator.  If Y is omitted, use a single space character.
66 */
67 static void sqlEvalFunc(
68   sqlite3_context *context,
69   int argc,
70   sqlite3_value **argv
71 ){
72   const char *zSql;
73   sqlite3 *db;
74   char *zErr = 0;
75   int rc;
76   struct EvalResult x;
77 
78   memset(&x, 0, sizeof(x));
79   x.zSep = " ";
80   zSql = (const char*)sqlite3_value_text(argv[0]);
81   if( zSql==0 ) return;
82   if( argc>1 ){
83     x.zSep = (const char*)sqlite3_value_text(argv[1]);
84     if( x.zSep==0 ) return;
85   }
86   x.szSep = (int)strlen(x.zSep);
87   db = sqlite3_context_db_handle(context);
88   rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
89   if( rc!=SQLITE_OK ){
90     sqlite3_result_error(context, zErr, -1);
91     sqlite3_free(zErr);
92   }else if( x.zSep==0 ){
93     sqlite3_result_error_nomem(context);
94     sqlite3_free(x.z);
95   }else{
96     sqlite3_result_text(context, x.z, x.nUsed, sqlite3_free);
97   }
98 }
99 
100 
101 #ifdef _WIN32
102 __declspec(dllexport)
103 #endif
104 int sqlite3_eval_init(
105   sqlite3 *db,
106   char **pzErrMsg,
107   const sqlite3_api_routines *pApi
108 ){
109   int rc = SQLITE_OK;
110   SQLITE_EXTENSION_INIT2(pApi);
111   (void)pzErrMsg;  /* Unused parameter */
112   rc = sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0,
113                                sqlEvalFunc, 0, 0);
114   if( rc==SQLITE_OK ){
115     rc = sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0,
116                                  sqlEvalFunc, 0, 0);
117   }
118   return rc;
119 }
120