mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Permit sqlite_exec() to be called from within user-defined functions. (CVS 1166)
FossilOrigin-Name: 03636c94a542b1f90a3acfbe65a9c2976872073f
This commit is contained in:
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)
|
C Permit\ssqlite_exec()\sto\sbe\scalled\sfrom\swithin\suser-defined\sfunctions.\s(CVS\s1166)
|
||||||
D 2004-01-07T18:52:57
|
D 2004-01-07T19:24:48
|
||||||
F Makefile.in 0515ff9218ad8d5a8f6220f0494b8ef94c67013b
|
F Makefile.in 0515ff9218ad8d5a8f6220f0494b8ef94c67013b
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@ -53,7 +53,7 @@ F src/sqlite.h.in e6cfff01fafc8a82ce82cd8c932af421dc9adb54
|
|||||||
F src/sqliteInt.h d9f2391451ae9636eb447dfa4dc35b70bfa3759d
|
F src/sqliteInt.h d9f2391451ae9636eb447dfa4dc35b70bfa3759d
|
||||||
F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895
|
F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895
|
||||||
F src/tclsqlite.c dcd18d1f0d51ac4863d1f9059f614f903bc1fffe
|
F src/tclsqlite.c dcd18d1f0d51ac4863d1f9059f614f903bc1fffe
|
||||||
F src/test1.c 1d297ca6c01601ee38d723ff08343dc01f351985
|
F src/test1.c e8652055d04d241d4fb437b5c33ff07d9f13b4b4
|
||||||
F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700
|
F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700
|
||||||
F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
|
F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
|
||||||
F src/test4.c dcbbbb382626fd466a7c46907f74db35fc8bad64
|
F src/test4.c dcbbbb382626fd466a7c46907f74db35fc8bad64
|
||||||
@ -63,7 +63,7 @@ F src/trigger.c ce83e017b407d046e909d05373d7f8ee70f9f7f9
|
|||||||
F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397
|
F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397
|
||||||
F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e
|
F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e
|
||||||
F src/vacuum.c 77485a64a6e4e358170f150fff681c1624a092b0
|
F src/vacuum.c 77485a64a6e4e358170f150fff681c1624a092b0
|
||||||
F src/vdbe.c 651f294e3a56baf50d56e11fed822b963f3bf41f
|
F src/vdbe.c 651fcdac5c865711169d5046836b31bd81e0cb8a
|
||||||
F src/vdbe.h 3957844e46fea71fd030e78f6a3bd2f7e320fb43
|
F src/vdbe.h 3957844e46fea71fd030e78f6a3bd2f7e320fb43
|
||||||
F src/vdbeInt.h eab39bc209b267271bc4afbcf4991d6c229bae9a
|
F src/vdbeInt.h eab39bc209b267271bc4afbcf4991d6c229bae9a
|
||||||
F src/vdbeaux.c 6f2d43643f83656b2555b7ee320397805db11d4c
|
F src/vdbeaux.c 6f2d43643f83656b2555b7ee320397805db11d4c
|
||||||
@ -107,7 +107,7 @@ F test/minmax.test 6d9b6d6ee34f42e2a58dffece1f76d35f446b3af
|
|||||||
F test/misc1.test 0b98d493b0cf55cb5f53e1f3df8107c166eecb5a
|
F test/misc1.test 0b98d493b0cf55cb5f53e1f3df8107c166eecb5a
|
||||||
F test/misc2.test 10c2ce26407d37411b96273e552d5095393732be
|
F test/misc2.test 10c2ce26407d37411b96273e552d5095393732be
|
||||||
F test/misc3.test 73bdce2b7f82699fb4771e7acfbd37461263f59e
|
F test/misc3.test 73bdce2b7f82699fb4771e7acfbd37461263f59e
|
||||||
F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162
|
F test/misuse.test 1095f26d1aed406c65e1d2eba651c4bb7c38cbff
|
||||||
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
|
F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0
|
||||||
F test/null.test c14d0f4739f21e929b8115b72bf0c765b6bb1721
|
F test/null.test c14d0f4739f21e929b8115b72bf0c765b6bb1721
|
||||||
F test/pager.test dd31da9bee94a82e2e87e58cf286cfe809f8fc5f
|
F test/pager.test dd31da9bee94a82e2e87e58cf286cfe809f8fc5f
|
||||||
@ -179,7 +179,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3
|
|||||||
F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||||
P 6c858db2c099c7ba73d72e02b19bf6173620db13
|
P d3e96da20d269a068188915b3cc0eb02d330d316
|
||||||
R 4cb210b9d1a4f8eeca46f83ab493882a
|
R ed517c12ad32df3998805d703dfd3733
|
||||||
U drh
|
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
|
** is not included in the SQLite library. It is used for automated
|
||||||
** testing of the SQLite library.
|
** 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 "sqliteInt.h"
|
||||||
#include "tcl.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
|
** Implementation of the x_sqlite_exec() function. This function takes
|
||||||
** a single argument and attempts to execute that argument as SQL code.
|
** 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.
|
** 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
|
** This routine simulates the effect of having two threads attempt to
|
||||||
** use the same database at the same time.
|
** use the same database at the same time.
|
||||||
*/
|
*/
|
||||||
static void sqliteExecFunc(sqlite_func *context, int argc, const char **argv){
|
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
|
** in this file for details. If in doubt, do not deviate from existing
|
||||||
** commenting and indentation practices when changing or adding code.
|
** 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 "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@ -1121,7 +1121,9 @@ case OP_Function: {
|
|||||||
ctx.z = 0;
|
ctx.z = 0;
|
||||||
ctx.isError = 0;
|
ctx.isError = 0;
|
||||||
ctx.isStep = 0;
|
ctx.isStep = 0;
|
||||||
|
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
|
||||||
(*ctx.pFunc->xFunc)(&ctx, n, (const char**)&zStack[p->tos-n+1]);
|
(*ctx.pFunc->xFunc)(&ctx, n, (const char**)&zStack[p->tos-n+1]);
|
||||||
|
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
|
||||||
sqliteVdbePopStack(p, n);
|
sqliteVdbePopStack(p, n);
|
||||||
p->tos++;
|
p->tos++;
|
||||||
aStack[p->tos] = ctx.s;
|
aStack[p->tos] = ctx.s;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# This file implements tests for the SQLITE_MISUSE detection logic.
|
# This file implements tests for the SQLITE_MISUSE detection logic.
|
||||||
# This test file leaks memory and file descriptors.
|
# 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]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
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
|
# Use the x_sqlite_exec() SQL function to simulate the effect of two
|
||||||
# threads trying to use the same database at the same time.
|
# 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 {
|
do_test misuse-1.4 {
|
||||||
sqlite_exec_printf $::DB {
|
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 {
|
do_test misuse-1.5 {
|
||||||
sqlite_exec_printf $::DB {SELECT * FROM t1} {}
|
sqlite_exec_printf $::DB {SELECT * FROM t1} {}
|
||||||
} {21 {library routine called out of sequence}}
|
} {0 {a b 1 2}}
|
||||||
do_test misuse-1.6 {
|
do_test misuse-1.6 {
|
||||||
catchsql {
|
catchsql {
|
||||||
SELECT * FROM t1
|
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.
|
# Attempt to register a new SQL function while an sqlite_exec() is active.
|
||||||
#
|
#
|
||||||
|
Reference in New Issue
Block a user