mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Attempt to detect when two or more threads try to use the same database at
the same time and return an SQLITE_MISUSE error. Also return this error if an attempt is made to use a closed database. (CVS 558) FossilOrigin-Name: a05fabd2df1cb38c555a7b2f31b0ca687db500c2
This commit is contained in:
24
manifest
24
manifest
@@ -1,5 +1,5 @@
|
||||
C Fix\sfor\sticket\s#35:\sIgnore\sany\sORDER\sBY\sclause\son\sa\ssubquery\sin\sa\sFROM\sclause.\s(CVS\s557)
|
||||
D 2002-05-08T21:46:15
|
||||
C Attempt\sto\sdetect\swhen\stwo\sor\smore\sthreads\stry\sto\suse\sthe\ssame\sdatabase\sat\nthe\ssame\stime\sand\sreturn\san\sSQLITE_MISUSE\serror.\s\sAlso\sreturn\sthis\serror\nif\san\sattempt\sis\smade\sto\suse\sa\sclosed\sdatabase.\s(CVS\s558)
|
||||
D 2002-05-10T05:44:56
|
||||
F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d
|
||||
F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296
|
||||
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
|
||||
@@ -28,7 +28,7 @@ F src/func.c a31dcba85bc2ecb9b752980289cf7e6cd0cafbce
|
||||
F src/hash.c cc259475e358baaf299b00a2c7370f2b03dda892
|
||||
F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9
|
||||
F src/insert.c 31233f44fc79edbb43523a830e54736a8e222ff4
|
||||
F src/main.c df43fe585d2bfb925c837b6822783c0ee3dd6e1c
|
||||
F src/main.c a7041c9a32515a33dea8150dd33f748ce6e57861
|
||||
F src/md5.c b2b1a34fce66ceca97f4e0dabc20be8be7933c92
|
||||
F src/os.c 5ab8b6b4590d0c1ab8e96c67996c170e4462e0fc
|
||||
F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10
|
||||
@@ -40,18 +40,18 @@ F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
|
||||
F src/select.c 1b623a7d826ec7c245bc542b665d61724da2a62d
|
||||
F src/shell.c 5acbe59e137d60d8efd975c683dbea74ab626530
|
||||
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
|
||||
F src/sqlite.h.in ffcacf73b5ed1a4939205d29a704a185758fa6a6
|
||||
F src/sqliteInt.h e47ca9267a4c4a98e9f8d90c2df994a18f23d699
|
||||
F src/sqlite.h.in 0038faa6d642de06b91143ee65a131bd831d020b
|
||||
F src/sqliteInt.h b850d1013577be1aa34ca3b7985fa8aca733709b
|
||||
F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
|
||||
F src/tclsqlite.c c9e9039762d9866eae70bf782237d0206a13f57e
|
||||
F src/test1.c d46ab7a82a9c16a3b1ee363cb4c0f98c5ff65743
|
||||
F src/test2.c d410dbd8a90faa466c3ab694fa0aa57f5a773aa6
|
||||
F src/test2.c 669cc22781c6461a273416ec1a7414d25c081730
|
||||
F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e
|
||||
F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f
|
||||
F src/tokenize.c 5624d342601f616157ba266abccc1368a5afee70
|
||||
F src/update.c 7dd714a6a7fa47f849ebb36b6d915974d6c6accb
|
||||
F src/util.c b34cd91387bbfdc79319ea451a7d120cef478120
|
||||
F src/vdbe.c 0ed88fff32273c103a24396d491b71bc69b4b596
|
||||
F src/util.c 79bcc175e48662faa523d4d00d34bfa246ae219f
|
||||
F src/vdbe.c aa5d5f76f2d7f76b1f63d81c5fd2dc91e66c49a4
|
||||
F src/vdbe.h 67840a462e1daedb958cca0ccc97db140d3d9152
|
||||
F src/where.c 5e3e97adfa5800378f2ed45bb9312dd3a70e239c
|
||||
F test/all.test 6aa106eee4d7127afa5cee97c51a783a79694ead
|
||||
@@ -114,7 +114,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
|
||||
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
|
||||
F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
|
||||
F www/c_interface.tcl 79f63ffa8c6e7adb9e3449ff325d093cfb0ce3e3
|
||||
F www/c_interface.tcl fbaddacc3fed376d4aebfddceb31a1fac00cf158
|
||||
F www/changes.tcl 2178c2f6a259885904f6406864006a1602d5d498
|
||||
F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
|
||||
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
|
||||
@@ -130,7 +130,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f
|
||||
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
|
||||
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
||||
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
||||
P 5f22d21571acedbd6348b61445a7c408cde8d229
|
||||
R 8bb0ddf73035f1de9a05b9cb9c9657bb
|
||||
P 1b0ee944c9af10078aba628e85d79f8682afa2b6
|
||||
R af1468ce6a17da4c94780c1e8568bbbf
|
||||
U drh
|
||||
Z 9f4be155fc56c5c79e292303d6e98925
|
||||
Z 8cea50e279e02e056a890661e5730afa
|
||||
|
@@ -1 +1 @@
|
||||
1b0ee944c9af10078aba628e85d79f8682afa2b6
|
||||
a05fabd2df1cb38c555a7b2f31b0ca687db500c2
|
48
src/main.c
48
src/main.c
@@ -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.69 2002/04/12 10:08:59 drh Exp $
|
||||
** $Id: main.c,v 1.70 2002/05/10 05:44:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -332,6 +332,7 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
|
||||
sqliteRegisterBuildinFunctions(db);
|
||||
db->onError = OE_Default;
|
||||
db->priorNewRowid = 0;
|
||||
db->magic = SQLITE_MAGIC_BUSY;
|
||||
|
||||
/* Open the backend database driver */
|
||||
rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);
|
||||
@@ -359,6 +360,7 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
|
||||
sqliteFree(*pzErrMsg);
|
||||
*pzErrMsg = 0;
|
||||
}
|
||||
db->magic = SQLITE_MAGIC_OPEN;
|
||||
return db;
|
||||
|
||||
no_mem_on_open:
|
||||
@@ -433,6 +435,8 @@ int sqlite_changes(sqlite *db){
|
||||
*/
|
||||
void sqlite_close(sqlite *db){
|
||||
HashElem *i;
|
||||
if( sqliteSafetyOn(db) ){ return; }
|
||||
db->magic = SQLITE_MAGIC_CLOSED;
|
||||
sqliteBtreeClose(db->pBe);
|
||||
clearHashTable(db, 0);
|
||||
if( db->pBeTemp ){
|
||||
@@ -526,10 +530,12 @@ int sqlite_exec(
|
||||
Parse sParse;
|
||||
|
||||
if( pzErrMsg ) *pzErrMsg = 0;
|
||||
if( sqliteSafetyOn(db) ){ return SQLITE_MISUSE; }
|
||||
if( (db->flags & SQLITE_Initialized)==0 ){
|
||||
int rc = sqliteInit(db, pzErrMsg);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqliteStrRealloc(pzErrMsg);
|
||||
sqliteSafetyOff(db);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -554,9 +560,49 @@ int sqlite_exec(
|
||||
clearHashTable(db, 1);
|
||||
}
|
||||
db->recursionDepth--;
|
||||
if( sqliteSafetyOff(db) ){ sParse.rc = SQLITE_MISUSE; }
|
||||
return sParse.rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY.
|
||||
** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN
|
||||
** when this routine is called.
|
||||
**
|
||||
** This routine is a attempt to detect if two threads attempt
|
||||
** to use the same sqlite* pointer at the same time. There is a
|
||||
** race condition so it is possible that the error is not detected.
|
||||
** But usually the problem will be seen. The result will be an
|
||||
** error which can be used to debugging the application that is
|
||||
** using SQLite incorrectly.
|
||||
*/
|
||||
int sqliteSafetyOn(sqlite *db){
|
||||
if( db->magic==SQLITE_MAGIC_OPEN ){
|
||||
db->magic = SQLITE_MAGIC_BUSY;
|
||||
return 0;
|
||||
}else{
|
||||
db->magic = SQLITE_MAGIC_ERROR;
|
||||
db->flags |= SQLITE_Interrupt;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN.
|
||||
** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY
|
||||
** when this routine is called.
|
||||
*/
|
||||
int sqliteSafetyOff(sqlite *db){
|
||||
if( db->magic==SQLITE_MAGIC_BUSY ){
|
||||
db->magic = SQLITE_MAGIC_OPEN;
|
||||
return 0;
|
||||
}else{
|
||||
db->magic = SQLITE_MAGIC_ERROR;
|
||||
db->flags |= SQLITE_Interrupt;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine implements a busy callback that sleeps and tries
|
||||
** again until a timeout value is reached. The timeout value is
|
||||
|
@@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the SQLite library
|
||||
** presents to client programs.
|
||||
**
|
||||
** @(#) $Id: sqlite.h.in,v 1.30 2002/04/12 10:08:59 drh Exp $
|
||||
** @(#) $Id: sqlite.h.in,v 1.31 2002/05/10 05:44:56 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_H_
|
||||
#define _SQLITE_H_
|
||||
@@ -161,6 +161,7 @@ int sqlite_exec(
|
||||
#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
|
||||
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
|
||||
#define SQLITE_MISMATCH 20 /* Data type mismatch */
|
||||
#define SQLITE_MISUSE 21 /* Library used incorrectly */
|
||||
|
||||
/*
|
||||
** Each entry in an SQLite table has a unique integer key. (The key is
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.105 2002/04/12 10:08:59 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.106 2002/05/10 05:44:56 drh Exp $
|
||||
*/
|
||||
#include "sqlite.h"
|
||||
#include "hash.h"
|
||||
@@ -167,6 +167,7 @@ struct sqlite {
|
||||
int lastRowid; /* ROWID of most recent insert */
|
||||
int priorNewRowid; /* Last randomly generated ROWID */
|
||||
int onError; /* Default conflict algorithm */
|
||||
int magic; /* Magic number for detect library misuse */
|
||||
int nChange; /* Number of rows changed */
|
||||
int recursionDepth; /* Number of nested calls to sqlite_exec() */
|
||||
};
|
||||
@@ -189,6 +190,16 @@ struct sqlite {
|
||||
#define SQLITE_UnresetViews 0x00000200 /* True if one or more views have */
|
||||
/* defined column names */
|
||||
|
||||
/*
|
||||
** Possible values for the sqlite.magic field.
|
||||
** The numbers are obtained at random and have no special meaning, other
|
||||
** than being distinct from one another.
|
||||
*/
|
||||
#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */
|
||||
#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */
|
||||
#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */
|
||||
#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */
|
||||
|
||||
/*
|
||||
** Each SQL function is defined by an instance of the following
|
||||
** structure. A pointer to this structure is stored in the sqlite.aFunc
|
||||
@@ -648,3 +659,5 @@ IdList *sqliteIdListDup(IdList*);
|
||||
Select *sqliteSelectDup(Select*);
|
||||
FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int);
|
||||
void sqliteRegisterBuildinFunctions(sqlite*);
|
||||
int sqliteSafetyOn(sqlite*);
|
||||
int sqliteSafetyOff(sqlite*);
|
||||
|
@@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test2.c,v 1.7 2002/02/02 15:01:16 drh Exp $
|
||||
** $Id: test2.c,v 1.8 2002/05/10 05:44:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "pager.h"
|
||||
@@ -42,6 +42,12 @@ static char *errorName(int rc){
|
||||
case SQLITE_FULL: zName = "SQLITE_FULL"; break;
|
||||
case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
|
||||
case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
|
||||
case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
|
||||
case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
|
||||
case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
|
||||
case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
|
||||
case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
|
||||
case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
|
||||
default: zName = "SQLITE_Unknown"; break;
|
||||
}
|
||||
return zName;
|
||||
|
@@ -14,7 +14,7 @@
|
||||
** This file contains functions for allocating memory, comparing
|
||||
** strings, and stuff like that.
|
||||
**
|
||||
** $Id: util.c,v 1.41 2002/03/06 03:08:26 drh Exp $
|
||||
** $Id: util.c,v 1.42 2002/05/10 05:44:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdarg.h>
|
||||
@@ -1096,6 +1096,7 @@ const char *sqlite_error_string(int rc){
|
||||
case SQLITE_TOOBIG: z = "too much data for one table row"; break;
|
||||
case SQLITE_CONSTRAINT: z = "constraint failed"; break;
|
||||
case SQLITE_MISMATCH: z = "datatype mismatch"; break;
|
||||
case SQLITE_MISUSE: z = "SQLite library used incorrectly"; break;
|
||||
default: z = "unknown error"; break;
|
||||
}
|
||||
return z;
|
||||
|
26
src/vdbe.c
26
src/vdbe.c
@@ -30,7 +30,7 @@
|
||||
** But other routines are also provided to help in building up
|
||||
** a program instruction by instruction.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.139 2002/04/20 14:24:42 drh Exp $
|
||||
** $Id: vdbe.c,v 1.140 2002/05/10 05:44:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -1092,6 +1092,7 @@ int sqliteVdbeList(
|
||||
void *pArg, /* 1st argument to callback */
|
||||
char **pzErrMsg /* Error msg written here */
|
||||
){
|
||||
sqlite *db = p->db;
|
||||
int i, rc;
|
||||
char *azValue[6];
|
||||
char zAddr[20];
|
||||
@@ -1109,8 +1110,8 @@ int sqliteVdbeList(
|
||||
azValue[5] = 0;
|
||||
rc = SQLITE_OK;
|
||||
for(i=0; rc==SQLITE_OK && i<p->nOp; i++){
|
||||
if( p->db->flags & SQLITE_Interrupt ){
|
||||
p->db->flags &= ~SQLITE_Interrupt;
|
||||
if( db->flags & SQLITE_Interrupt ){
|
||||
db->flags &= ~SQLITE_Interrupt;
|
||||
sqliteSetString(pzErrMsg, "interrupted", 0);
|
||||
rc = SQLITE_INTERRUPT;
|
||||
break;
|
||||
@@ -1125,9 +1126,16 @@ int sqliteVdbeList(
|
||||
azValue[4] = p->aOp[i].p3;
|
||||
}
|
||||
azValue[1] = zOpName[p->aOp[i].opcode];
|
||||
if( sqliteSafetyOff(db) ){
|
||||
rc = SQLITE_MISUSE;
|
||||
break;
|
||||
}
|
||||
if( xCallback(pArg, 5, azValue, azColumnNames) ){
|
||||
rc = SQLITE_ABORT;
|
||||
}
|
||||
if( sqliteSafetyOn(db) ){
|
||||
rc = SQLITE_MISUSE;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -1577,9 +1585,11 @@ case OP_Callback: {
|
||||
if( p->iOffset>0 ){
|
||||
p->iOffset--;
|
||||
}else{
|
||||
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
|
||||
if( xCallback(pArg, pOp->p1, &zStack[i], p->azColName)!=0 ){
|
||||
rc = SQLITE_ABORT;
|
||||
}
|
||||
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
|
||||
p->nCallback++;
|
||||
if( p->iLimit>0 ){
|
||||
p->iLimit--;
|
||||
@@ -1612,9 +1622,11 @@ case OP_Callback: {
|
||||
*/
|
||||
case OP_NullCallback: {
|
||||
if( xCallback!=0 && p->nCallback==0 ){
|
||||
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
|
||||
if( xCallback(pArg, pOp->p1, 0, p->azColName)!=0 ){
|
||||
rc = SQLITE_ABORT;
|
||||
}
|
||||
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
|
||||
p->nCallback++;
|
||||
}
|
||||
if( sqlite_malloc_failed ) goto no_mem;
|
||||
@@ -3988,9 +4000,11 @@ case OP_SortCallback: {
|
||||
if( p->iOffset>0 ){
|
||||
p->iOffset--;
|
||||
}else{
|
||||
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
|
||||
if( xCallback(pArg, pOp->p1, (char**)zStack[i], p->azColName)!=0 ){
|
||||
rc = SQLITE_ABORT;
|
||||
}
|
||||
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
|
||||
p->nCallback++;
|
||||
if( p->iLimit>0 ){
|
||||
p->iLimit--;
|
||||
@@ -4655,6 +4669,12 @@ no_mem:
|
||||
rc = SQLITE_NOMEM;
|
||||
goto cleanup;
|
||||
|
||||
/* Jump to here for an SQLITE_MISUSE error.
|
||||
*/
|
||||
abort_due_to_misuse:
|
||||
rc = SQLITE_MISUSE;
|
||||
/* Fall thru into abort_due_to_error */
|
||||
|
||||
/* Jump to here for any other kind of fatal error. The "rc" variable
|
||||
** should hold the error number.
|
||||
*/
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Run this Tcl script to generate the sqlite.html file.
|
||||
#
|
||||
set rcsid {$Id: c_interface.tcl,v 1.26 2002/04/12 10:09:00 drh Exp $}
|
||||
set rcsid {$Id: c_interface.tcl,v 1.27 2002/05/10 05:44:57 drh Exp $}
|
||||
|
||||
puts {<html>
|
||||
<head>
|
||||
@@ -186,6 +186,7 @@ the type of error. Here is a complete list of the return codes:
|
||||
#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
|
||||
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
|
||||
#define SQLITE_MISMATCH 20 /* Data type mismatch */
|
||||
#define SQLITE_MISUSE 21 /* Library used incorrectly */
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
@@ -294,6 +295,15 @@ data into a column labeled INTEGER PRIMARY KEY. For most columns, SQLite
|
||||
ignores the data type and allows any kind of data to be stored. But
|
||||
an INTEGER PRIMARY KEY column is only allowed to store integer data.
|
||||
</p></dd>
|
||||
<dt>SQLITE_MISUSE</dt>
|
||||
<dd><p>This error might occur if one or more of the SQLite API routines
|
||||
is used incorrectly. Examples of incorrect usage include calling
|
||||
<b>sqlite_exec()</b> after the database has been closed using
|
||||
<b>sqlite_close()</b> or calling <b>sqlite_exec()</b> with the same
|
||||
database pointer simultaneously from two separate threads. The
|
||||
library makes an effort to detect these sorts of problems, but it
|
||||
cannot detect them with 100% accuracy.
|
||||
</p></dd>
|
||||
</dl>
|
||||
</blockquote>
|
||||
|
||||
|
Reference in New Issue
Block a user