-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
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
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
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
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
-1b0ee944c9af10078aba628e85d79f8682afa2b6
\ No newline at end of file
+a05fabd2df1cb38c555a7b2f31b0ca687db500c2
\ No newline at end of file
** 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"
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);
sqliteFree(*pzErrMsg);
*pzErrMsg = 0;
}
+ db->magic = SQLITE_MAGIC_OPEN;
return db;
no_mem_on_open:
*/
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 ){
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;
}
}
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
** 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_
#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
*************************************************************************
** 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"
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() */
};
#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
Select *sqliteSelectDup(Select*);
FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int);
void sqliteRegisterBuildinFunctions(sqlite*);
+int sqliteSafetyOn(sqlite*);
+int sqliteSafetyOff(sqlite*);
** 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"
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;
** 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>
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;
** 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>
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];
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;
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;
}
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--;
*/
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;
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--;
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.
*/
#
# 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>
#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>
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>