Permit sqlite_exec() to be called from within user-defined functions. (CVS 1166)
FossilOrigin-Name: 03636c94a542b1f90a3acfbe65a9c2976872073f
This commit is contained in:
parent
a11846b77a
commit
d1d9fc3397
16
manifest
16
manifest
@ -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
|
60
src/test1.c
60
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"
|
||||
@ -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.
|
||||
#
|
||||
|
Loading…
x
Reference in New Issue
Block a user