modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/eval.c (about)

     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  }