diff options
author | drh <drh@noemail.net> | 2004-01-07 19:24:48 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2004-01-07 19:24:48 +0000 |
commit | d1d9fc3397e48561121a19010743ceda15a98a62 (patch) | |
tree | bfd6991477f0dae4e37f75d88d0f6a697ff6d218 /src | |
parent | a11846b77af8e8ef0fc89409beeabe73439bd412 (diff) | |
download | sqlite-d1d9fc3397e48561121a19010743ceda15a98a62.tar.gz sqlite-d1d9fc3397e48561121a19010743ceda15a98a62.zip |
Permit sqlite_exec() to be called from within user-defined functions. (CVS 1166)
FossilOrigin-Name: 03636c94a542b1f90a3acfbe65a9c2976872073f
Diffstat (limited to 'src')
-rw-r--r-- | src/test1.c | 60 | ||||
-rw-r--r-- | src/vdbe.c | 4 |
2 files changed, 61 insertions, 3 deletions
diff --git a/src/test1.c b/src/test1.c index 32896f889..dd452a447 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.31 2004/01/06 00:44:25 drh Exp $ +** $Id: test1.c,v 1.32 2004/01/07 19:24:48 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -297,15 +297,71 @@ static void ifnullFunc(sqlite_func *context, int argc, const char **argv){ } /* +** A structure into which to accumulate text. +*/ +struct dstr { + int nAlloc; /* Space allocated */ + int nUsed; /* Space used */ + char *z; /* The space */ +}; + +/* +** Append text to a dstr +*/ +static void dstrAppend(struct dstr *p, const char *z, int divider){ + int n = strlen(z); + if( p->nUsed + n + 2 > p->nAlloc ){ + char *zNew; + p->nAlloc = p->nAlloc*2 + n + 200; + zNew = sqliteRealloc(p->z, p->nAlloc); + if( zNew==0 ){ + sqliteFree(p->z); + memset(p, 0, sizeof(*p)); + return; + } + p->z = zNew; + } + if( divider && p->nUsed>0 ){ + p->z[p->nUsed++] = divider; + } + memcpy(&p->z[p->nUsed], z, n+1); + p->nUsed += n; +} + +/* +** Invoked for each callback from sqliteExecFunc +*/ +static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ + struct dstr *p = (struct dstr*)pData; + int i; + for(i=0; i<argc; i++){ + if( argv[i]==0 ){ + dstrAppend(p, "NULL", ' '); + }else{ + dstrAppend(p, argv[i], ' '); + } + } + return 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){ - sqlite_exec((sqlite*)sqlite_user_data(context), argv[0], 0, 0, 0); + 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); } /* diff --git a/src/vdbe.c b/src/vdbe.c index 50f6f95ca..667591e22 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.247 2004/01/07 18:52:57 drh Exp $ +** $Id: vdbe.c,v 1.248 2004/01/07 19:24:48 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -1121,7 +1121,9 @@ case OP_Function: { ctx.z = 0; ctx.isError = 0; ctx.isStep = 0; + if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; (*ctx.pFunc->xFunc)(&ctx, n, (const char**)&zStack[p->tos-n+1]); + if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; sqliteVdbePopStack(p, n); p->tos++; aStack[p->tos] = ctx.s; |