Permit sqlite_exec() to be called from within user-defined functions. (CVS 1166)

FossilOrigin-Name: 03636c94a542b1f90a3acfbe65a9c2976872073f
This commit is contained in:
drh 2004-01-07 19:24:48 +00:00
parent a11846b77a
commit d1d9fc3397
5 changed files with 79 additions and 17 deletions

@ -1,5 +1,5 @@
C Defer\sthe\s{quote:\sMoveTo}\r\nopcode\sin\sVDBE\suntil\sthe\sdata\sis\sactually\sneeded.\s\sSometimes\r\nthe\sdata\sis\snever\sneeded,\sresulting\sin\sa\sperformance\sincrease.\s\sOn\san\sindexed\r\norder\ssearch\swith\sa\slarge\sOFFSET,\squeries\stimes\scan\sbe\san\sorder\sof\smagnitude\r\nfaster.\s(CVS\s1165)
D 2004-01-07T18:52:57
C Permit\ssqlite_exec()\sto\sbe\scalled\sfrom\swithin\suser-defined\sfunctions.\s(CVS\s1166)
D 2004-01-07T19:24:48
F Makefile.in 0515ff9218ad8d5a8f6220f0494b8ef94c67013b
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -53,7 +53,7 @@ F src/sqlite.h.in e6cfff01fafc8a82ce82cd8c932af421dc9adb54
F src/sqliteInt.h d9f2391451ae9636eb447dfa4dc35b70bfa3759d
F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895
F src/tclsqlite.c dcd18d1f0d51ac4863d1f9059f614f903bc1fffe
F src/test1.c 1d297ca6c01601ee38d723ff08343dc01f351985
F src/test1.c e8652055d04d241d4fb437b5c33ff07d9f13b4b4
F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700
F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
F src/test4.c dcbbbb382626fd466a7c46907f74db35fc8bad64
@ -63,7 +63,7 @@ F src/trigger.c ce83e017b407d046e909d05373d7f8ee70f9f7f9
F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397
F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e
F src/vacuum.c 77485a64a6e4e358170f150fff681c1624a092b0
F src/vdbe.c 651f294e3a56baf50d56e11fed822b963f3bf41f
F src/vdbe.c 651fcdac5c865711169d5046836b31bd81e0cb8a
F src/vdbe.h 3957844e46fea71fd030e78f6a3bd2f7e320fb43
F src/vdbeInt.h eab39bc209b267271bc4afbcf4991d6c229bae9a
F src/vdbeaux.c 6f2d43643f83656b2555b7ee320397805db11d4c
@ -107,7 +107,7 @@ F test/minmax.test 6d9b6d6ee34f42e2a58dffece1f76d35f446b3af
F test/misc1.test 0b98d493b0cf55cb5f53e1f3df8107c166eecb5a
F test/misc2.test 10c2ce26407d37411b96273e552d5095393732be
F test/misc3.test 73bdce2b7f82699fb4771e7acfbd37461263f59e
F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162
F test/misuse.test 1095f26d1aed406c65e1d2eba651c4bb7c38cbff
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
F test/null.test c14d0f4739f21e929b8115b72bf0c765b6bb1721
F test/pager.test dd31da9bee94a82e2e87e58cf286cfe809f8fc5f
@ -179,7 +179,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3
F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
P 6c858db2c099c7ba73d72e02b19bf6173620db13
R 4cb210b9d1a4f8eeca46f83ab493882a
P d3e96da20d269a068188915b3cc0eb02d330d316
R ed517c12ad32df3998805d703dfd3733
U drh
Z c064aa79b059a29becbc8ed82d605d9d
Z 9db3a07230e97c9741564f07ae589d3e

@ -1 +1 @@
d3e96da20d269a068188915b3cc0eb02d330d316
03636c94a542b1f90a3acfbe65a9c2976872073f

@ -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"
@ -296,16 +296,72 @@ 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);
}
/*

@ -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;

@ -13,7 +13,7 @@
# This file implements tests for the SQLITE_MISUSE detection logic.
# This test file leaks memory and file descriptors.
#
# $Id: misuse.test,v 1.3 2002/05/21 11:38:12 drh Exp $
# $Id: misuse.test,v 1.4 2004/01/07 19:24:48 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -41,19 +41,23 @@ do_test misuse-1.3 {
# Use the x_sqlite_exec() SQL function to simulate the effect of two
# threads trying to use the same database at the same time.
#
# It used to be prohibited to invoke sqlite_exec() from within a function,
# but that has changed. The following tests used to cause errors but now
# they do not.
#
do_test misuse-1.4 {
sqlite_exec_printf $::DB {
SELECT x_sqlite_exec('SELECT * FROM t1');
SELECT x_sqlite_exec('SELECT * FROM t1') AS xyz;
} {}
} {21 {library routine called out of sequence}}
} {0 {xyz {1 2}}}
do_test misuse-1.5 {
sqlite_exec_printf $::DB {SELECT * FROM t1} {}
} {21 {library routine called out of sequence}}
} {0 {a b 1 2}}
do_test misuse-1.6 {
catchsql {
SELECT * FROM t1
}
} {1 {library routine called out of sequence}}
} {0 {1 2}}
# Attempt to register a new SQL function while an sqlite_exec() is active.
#