xref: /sqlite-3.40.0/ext/misc/eval.c (revision bd41d566)
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   sqlite3_int64 nAlloc;  /* Number of bytes allocated for z[] */
28   sqlite3_int64 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( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
41       char *zNew;
42       p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
43       /* Using sqlite3_realloc64() would be better, but it is a recent
44       ** addition and will cause a segfault if loaded by an older version
45       ** of SQLite.  */
46       zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
47       if( zNew==0 ){
48         sqlite3_free(p->z);
49         memset(p, 0, sizeof(*p));
50         return 1;
51       }
52       p->z = zNew;
53     }
54     if( p->nUsed>0 ){
55       memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
56       p->nUsed += p->szSep;
57     }
58     memcpy(&p->z[p->nUsed], z, sz);
59     p->nUsed += sz;
60   }
61   return 0;
62 }
63 
64 /*
65 ** Implementation of the eval(X) and eval(X,Y) SQL functions.
66 **
67 ** Evaluate the SQL text in X.  Return the results, using string
68 ** Y as the separator.  If Y is omitted, use a single space character.
69 */
70 static void sqlEvalFunc(
71   sqlite3_context *context,
72   int argc,
73   sqlite3_value **argv
74 ){
75   const char *zSql;
76   sqlite3 *db;
77   char *zErr = 0;
78   int rc;
79   struct EvalResult x;
80 
81   memset(&x, 0, sizeof(x));
82   x.zSep = " ";
83   zSql = (const char*)sqlite3_value_text(argv[0]);
84   if( zSql==0 ) return;
85   if( argc>1 ){
86     x.zSep = (const char*)sqlite3_value_text(argv[1]);
87     if( x.zSep==0 ) return;
88   }
89   x.szSep = (int)strlen(x.zSep);
90   db = sqlite3_context_db_handle(context);
91   rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
92   if( rc!=SQLITE_OK ){
93     sqlite3_result_error(context, zErr, -1);
94     sqlite3_free(zErr);
95   }else if( x.zSep==0 ){
96     sqlite3_result_error_nomem(context);
97     sqlite3_free(x.z);
98   }else{
99     sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
100   }
101 }
102 
103 
104 #ifdef _WIN32
105 __declspec(dllexport)
106 #endif
107 int sqlite3_eval_init(
108   sqlite3 *db,
109   char **pzErrMsg,
110   const sqlite3_api_routines *pApi
111 ){
112   int rc = SQLITE_OK;
113   SQLITE_EXTENSION_INIT2(pApi);
114   (void)pzErrMsg;  /* Unused parameter */
115   rc = sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0,
116                                sqlEvalFunc, 0, 0);
117   if( rc==SQLITE_OK ){
118     rc = sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0,
119                                  sqlEvalFunc, 0, 0);
120   }
121   return rc;
122 }
123