Prevent collation sequences and user functions from being deleted or changed while SQL statements are executing. (CVS 2275)

FossilOrigin-Name: cabab62bc10568d435806a7059fad7274f0dd4c8
This commit is contained in:
danielk1977 2005-01-25 04:27:54 +00:00
parent 86c4948198
commit 9636c4e102
7 changed files with 174 additions and 23 deletions

View File

@ -1,5 +1,5 @@
C Clarify\sdocumentation\sof\sDEFAULT\sCURRENT_TIME\setc.\s(version\s3.1.0\sand\sgreater\sonly).\s(CVS\s2274)
D 2005-01-24T23:27:32
C Prevent\scollation\ssequences\sand\suser\sfunctions\sfrom\sbeing\sdeleted\sor\schanged\swhile\sSQL\sstatements\sare\sexecuting.\s(CVS\s2275)
D 2005-01-25T04:27:55
F Makefile.in ffd81f5e926d40b457071b4de8d7c1fa18f39b5a
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@ -42,7 +42,7 @@ F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/insert.c 037eb46630f027d0f93584db180d08ce163f3dbb
F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
F src/main.c 1fe0216dc01e1929e7e009cdedfb3e6e2391d717
F src/main.c 302e21bdaa015f590fdb7e69d50f45788da0fb0b
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
F src/os.h ae44064dc118b20d39450cb331409a775e8bb1c6
F src/os_common.h 0e7f428ba0a6c40a61bc56c4e96f493231301b73
@ -63,8 +63,8 @@ F src/shell.c 1f0da77ef0520afd6df71f4781076021874310f3
F src/sqlite.h.in 7d7c28344e2bd770491b56ed9169be20859c707d
F src/sqliteInt.h be6fa5e31c65e2b8e10112ee47a6e63ec7de37b5
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
F src/tclsqlite.c 47ecdb00e9bc135b37ad5bed84fefe20d7c19611
F src/test1.c 0a71a150659dd261be775c5eb60ae6c0c856c8a5
F src/tclsqlite.c 101994a2c4c0eaa69f1de9bfe4a02167f6049e7d
F src/test1.c 8c320f043b869c08fca86c4f01de027774eb85a8
F src/test2.c bbc2ecc58ceeab12d1e40970f831b1017524e40d
F src/test3.c 683e1e3819152ffd35da2f201e507228921148d0
F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
@ -174,9 +174,9 @@ F test/reindex.test 3552c6b944a3fab28cfd3049c04c65cb79419757
F test/rollback.test 94cd981ee3a627d9f6466f69dcf1f7dbfe695d7a
F test/rowid.test 040a3bef06f970c45f5fcd14b2355f7f4d62f0cf
F test/safety.test 907b64fee719554a3622853812af3886fddbbb4f
F test/schema.test 8725b41e19dec6c2d060b134417fe3da83c22d70
F test/schema.test 3787768619706fc6f47c53cbe23472e782302e1e
F test/select1.test ad700a2a1c325a23a7206ad4d189e33917de526f
F test/select2.test 04103fbd55fca9558fd79d637fb7819d9d0b2f52
F test/select2.test 01b9cbc06e5ed662ce0289aa5f47314d54541e82
F test/select3.test 9de435aa84fc406708cd8dc1b1d60e7f27cea685
F test/select4.test c239f516aa31f42f2ef7c6d7cd01105f08f934ca
F test/select5.test 94db800bbeff2e426c0175e07f7a71d4617853b5
@ -272,7 +272,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl 3e522a06ad41992023c80ca29a048ae2331ca5bd
P b243681a0e328ee0bbf1140abfb60d65d2102ad5
R ccb6447e7156933de8fc182a220c72ff
P 557eb2ec9d825c0a2830d3355d0d27b4b5937de2
R ccc679b6d9c5516b3defef2b60c271aa
U danielk1977
Z dad25937f9866029c7d3ceaad1989791
Z 95e1deb222b350d5a7b99118f5214f27

View File

@ -1 +1 @@
557eb2ec9d825c0a2830d3355d0d27b4b5937de2
cabab62bc10568d435806a7059fad7274f0dd4c8

View File

@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.274 2005/01/24 10:25:59 danielk1977 Exp $
** $Id: main.c,v 1.275 2005/01/25 04:27:55 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -736,6 +736,22 @@ int sqlite3_create_function(
#else
enc = SQLITE_UTF8;
#endif
/* Check if an existing function is being overridden or deleted. If so,
** and there are active VMs, then return SQLITE_BUSY. If a function
** is being overridden/deleted but there are no active VMs, allow the
** operation to continue but invalidate all precompiled statements.
*/
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0);
if( p && p->iPrefEnc==enc && p->nArg==nArg ){
if( db->activeVdbeCnt ){
sqlite3Error(db, SQLITE_BUSY,
"Unable to delete/modify user-function due to active statements");
return SQLITE_BUSY;
}else{
sqlite3ExpirePreparedStatements(db);
}
}
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
if( p==0 ) return SQLITE_NOMEM;
@ -1288,10 +1304,17 @@ int sqlite3_create_collation(
return SQLITE_ERROR;
}
/* If removing a collation sequence, then set the expired flag for
** all precompiled statements.
/* Check if this call is removing or replacing an existing collation
** sequence. If so, and there are active VMs, return busy. If there
** are no active VMs, invalidate any pre-compiled statements.
*/
if( !xCompare ){
pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 0);
if( pColl && pColl->xCmp ){
if( db->activeVdbeCnt ){
sqlite3Error(db, SQLITE_BUSY,
"Unable to delete/modify collation sequence due to active statements");
return SQLITE_BUSY;
}
sqlite3ExpirePreparedStatements(db);
}

View File

@ -11,7 +11,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.117 2005/01/24 10:25:59 danielk1977 Exp $
** $Id: tclsqlite.c,v 1.118 2005/01/25 04:27:55 danielk1977 Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@ -696,6 +696,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
strcpy(pCollate->zScript, zScript);
if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,
pCollate, tclSqlCollate) ){
Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
return TCL_ERROR;
}
break;
@ -1128,7 +1129,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8,
pFunc, tclSqlFunc, 0, 0);
if( rc!=SQLITE_OK ){
rc = TCL_ERROR;
rc = TCL_ERROR;
Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
}else{
/* Must flush any cached statements */
flushStmtCache( pDb );

View File

@ -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.127 2005/01/22 03:03:55 drh Exp $
** $Id: test1.c,v 1.128 2005/01/25 04:27:55 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@ -2599,6 +2599,58 @@ static int test_sleep(
}
#endif
/*
** Usage: sqlite_delete_function DB function-name
**
** Delete the user function 'function-name' from database handle DB. It
** is assumed that the user function was created as UTF8, any number of
** arguments (the way the TCL interface does it).
*/
static int delete_function(
void * clientData,
Tcl_Interp *interp,
int argc,
char **argv
){
int rc;
sqlite3 *db;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" DB function-name", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
return TCL_OK;
}
/*
** Usage: sqlite_delete_collation DB collation-name
**
** Delete the collation sequence 'collation-name' from database handle
** DB. It is assumed that the collation sequence was created as UTF8 (the
** way the TCL interface does it).
*/
static int delete_collation(
void * clientData,
Tcl_Interp *interp,
int argc,
char **argv
){
int rc;
sqlite3 *db;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" DB function-name", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
return TCL_OK;
}
/*
** Usage: tcl_variable_type VARIABLENAME
**
@ -2840,6 +2892,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
#if 0
{ "sqlite3_sleep", (Tcl_CmdProc*)test_sleep },
#endif
{ "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
{ "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation }
};
static struct {
char *zName;

View File

@ -1,4 +1,4 @@
# 2004 Jan 24
# 2005 Jan 24
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
@ -13,7 +13,7 @@
# This file tests the various conditions under which an SQLITE_SCHEMA
# error should be returned.
#
# $Id: schema.test,v 1.2 2005/01/24 13:03:32 danielk1977 Exp $
# $Id: schema.test,v 1.3 2005/01/25 04:27:55 danielk1977 Exp $
#---------------------------------------------------------------------
# When any of the following types of SQL statements or actions are
@ -31,6 +31,14 @@
#
# Note: Test cases schema-6.* are missing right now.
#
# Test cases schema-9.* and schema-10.* test some specific bugs
# that came up during development.
#
# Test cases schema-11.* test that it is impossible to delete or
# change a collation sequence or user-function while SQL statements
# are executing. Adding new collations or functions is allowed.
#
# Note: Test cases schema-11.* are also missing right now.
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -153,6 +161,26 @@ do_test schema-5.4 {
sqlite3_finalize $::STMT
} {SQLITE_SCHEMA}
#---------------------------------------------------------------------
# Tests 6.* check that prepared statements are invalidated when
# a user-function is deleted (but not when one is added).
do_test schema-6.1 {
set sql {SELECT * FROM abc;}
set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL]
db function hello_function {}
sqlite3_step $::STMT
} {SQLITE_DONE}
do_test schema-6.2 {
sqlite3_reset $::STMT
} {SQLITE_OK}
do_test schema-6.3 {
sqlite_delete_function $::DB hello_function
sqlite3_step $::STMT
} {SQLITE_ERROR}
do_test schema-6.4 {
sqlite3_finalize $::STMT
} {SQLITE_SCHEMA}
#---------------------------------------------------------------------
# Tests 7.* check that prepared statements are invalidated when
# a collation sequence is deleted (but not when one is added).
@ -255,5 +283,49 @@ do_test schema-10.5 {
db2 close
} {}
#---------------------------------------------------------------------
# Attempting to delete or replace a user-function or collation sequence
# while there are active statements returns an SQLITE_BUSY error.
#
# schema-11.1 - 11.4: User function.
# schema-11.5 - 11.8: Collation sequence.
#
do_test schema-11.1 {
db function tstfunc {}
set sql {SELECT * FROM abc}
set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL]
sqlite3_step $::STMT
} {SQLITE_ROW}
do_test schema-11.2 {
sqlite_delete_function $::DB tstfunc
} {SQLITE_BUSY}
do_test schema-11.3 {
set rc [catch {
db function tstfunc {}
} msg]
list $rc $msg
} {1 {Unable to delete/modify user-function due to active statements}}
do_test schema-11.4 {
sqlite3_finalize $::STMT
} {SQLITE_OK}
do_test schema-11.5 {
db collate tstcollate {}
set sql {SELECT * FROM abc}
set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL]
sqlite3_step $::STMT
} {SQLITE_ROW}
do_test schema-11.6 {
sqlite_delete_collation $::DB tstcollate
} {SQLITE_BUSY}
do_test schema-11.7 {
set rc [catch {
db collate tstcollate {}
} msg]
list $rc $msg
} {1 {Unable to delete/modify collation sequence due to active statements}}
do_test schema-11.8 {
sqlite3_finalize $::STMT
} {SQLITE_OK}
finish_test

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SELECT statement.
#
# $Id: select2.test,v 1.23 2005/01/24 12:46:14 drh Exp $
# $Id: select2.test,v 1.24 2005/01/25 04:27:55 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -71,7 +71,7 @@ ifcapable tclvar {
}
execsql {COMMIT}
}]
set result {}
list
} {}
puts "time with cache: $::t1"
}
@ -86,7 +86,7 @@ do_test select2-2.0.2 {
}
execsql {COMMIT}
}]
set result {}
list
} {}
puts "time without cache: $t2"
ifcapable tclvar {