1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Bug fix: sqlite_exec() would sometimes return SQLITE_PROTOCOL when it

should have returned SQLITE_BUSY.  There was also a deadlock that the
previous bug was masking. (CVS 322)

FossilOrigin-Name: 585ed5ebf1c1afc8ae1d569b121208018d8ecd49
This commit is contained in:
drh
2001-12-05 00:21:20 +00:00
parent 6ff13859d5
commit b8ca307e7b
10 changed files with 101 additions and 61 deletions

View File

@ -1,5 +1,5 @@
C Add\sthe\sability\sto\sdo\sa\ssingle\s.command\sas\sthe\ssecond\sargument\nto\sthe\scommand-line\sshell.\s(CVS\s321) C Bug\sfix:\ssqlite_exec()\swould\ssometimes\sreturn\sSQLITE_PROTOCOL\swhen\sit\nshould\shave\sreturned\sSQLITE_BUSY.\s\sThere\swas\salso\sa\sdeadlock\sthat\sthe\nprevious\sbug\swas\smasking.\s(CVS\s322)
D 2001-11-25T13:18:24 D 2001-12-05T00:21:20
F Makefile.in 352fed589f09dd94347e0bb391d047118ebd6105 F Makefile.in 352fed589f09dd94347e0bb391d047118ebd6105
F Makefile.template b6c3d3ba089e97e3a721e967f3151350f36cb42b F Makefile.template b6c3d3ba089e97e3a721e967f3151350f36cb42b
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
@ -19,19 +19,19 @@ F libtool c56e618713c9510a103bda6b95f3ea3900dcacd6
F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1 F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1
F publish.sh 33cbe6798969f637698044023c139080e5d772a6 F publish.sh 33cbe6798969f637698044023c139080e5d772a6
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
F src/btree.c d40fa46c8c578f1d166f4ea70d7a9d365399e0f3 F src/btree.c 5fbfeb383465ca311ac202cbf6ba8f18196426de
F src/btree.h 0250a0a577a98cc64ddf1582d50c08b8d2451650 F src/btree.h 0250a0a577a98cc64ddf1582d50c08b8d2451650
F src/build.c 2e21d425328e7c8bd6ade235e9eef51bf6fa870f F src/build.c 83733f96255db003363e786d1b28a5b85611acca
F src/delete.c 5d93a21c1388cfb1359bda01c072f25583a2f4f2 F src/delete.c 5d93a21c1388cfb1359bda01c072f25583a2f4f2
F src/expr.c 6b25c5bb1e750af2e2217c0134a7aa1fc0b11444 F src/expr.c 6b25c5bb1e750af2e2217c0134a7aa1fc0b11444
F src/hash.c 6f1a7712ae3aac8351662969aec5693740a2fbf7 F src/hash.c 6f1a7712ae3aac8351662969aec5693740a2fbf7
F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
F src/insert.c 3526be771a01035198bef28d8f370cbcab94f46d F src/insert.c 3526be771a01035198bef28d8f370cbcab94f46d
F src/main.c 799bdaf30cb33409b04a282aac53a9616d707c0d F src/main.c e5fa4773e6684b81fc0bcd9d9ae4578d56660c0c
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
F src/os.c d7dc681438f311cf8211a78d8d87a7cbdccc2f14 F src/os.c d7dc681438f311cf8211a78d8d87a7cbdccc2f14
F src/os.h bed702c9e3b768bc3cb1b12c90b83d099c1546be F src/os.h c5c12f5f25b0a1baf9a62937b456fabcad2c1f49
F src/pager.c fd9fc86686319a11cb0eebe5ebb4a250e45e7984 F src/pager.c 16173a7b7aff0c7bd7da94070e46d38778ab0f76
F src/pager.h df1fb8a759ab69112ea88b9f14601a7633d0ccc0 F src/pager.h df1fb8a759ab69112ea88b9f14601a7633d0ccc0
F src/parse.y 5295f393f41ea89958287e5738e6c12c7cd67482 F src/parse.y 5295f393f41ea89958287e5738e6c12c7cd67482
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
@ -40,7 +40,7 @@ F src/select.c fa1c7144a9ad7ce3f16373b443bc25e764af4be7
F src/shell.c 407095aaeeae78f42deb3e846b1ad77f8ed3b4ef F src/shell.c 407095aaeeae78f42deb3e846b1ad77f8ed3b4ef
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 934de9112747ad8d8e7d5fec44876246b24ca5a3 F src/sqlite.h.in 934de9112747ad8d8e7d5fec44876246b24ca5a3
F src/sqliteInt.h 1d812fd1eed0008d31f7e31293f058bb6dbe3f09 F src/sqliteInt.h 3990eeee362d1fb48dff841b56b7fe39577ea590
F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a
F src/tclsqlite.c b82e4faeae89fdb7304b3c970979ade299336a1f F src/tclsqlite.c b82e4faeae89fdb7304b3c970979ade299336a1f
F src/test1.c 41eabe255970ef947263b94145c9b2766bab8675 F src/test1.c 41eabe255970ef947263b94145c9b2766bab8675
@ -104,11 +104,11 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
F www/c_interface.tcl 58922228e8fdb0f6af3561a051ee8ccec6dbfd17 F www/c_interface.tcl 58922228e8fdb0f6af3561a051ee8ccec6dbfd17
F www/changes.tcl 6aa1912a7da010dee96b904bbf74694eb4d4445c F www/changes.tcl 9e0fc062862a3f99081b5a42ff91567c92b4bd64
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060 F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
F www/download.tcl 1ea61f9d89a2a5a9b2cee36b0d5cf97321bdefe0 F www/download.tcl 1ea61f9d89a2a5a9b2cee36b0d5cf97321bdefe0
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
F www/faq.tcl f1fd488bef706934f6e13cc56bc642ae09c72515 F www/faq.tcl 3c26fb2f2acfc9254f2685e23a34acae2490b44f
F www/index.tcl 6d6d847dd3e39e9aa7b0c9b8f3144819ff3f9f51 F www/index.tcl 6d6d847dd3e39e9aa7b0c9b8f3144819ff3f9f51
F www/lang.tcl 6482d90e40fb5ee004a86cf98f3007312a75444e F www/lang.tcl 6482d90e40fb5ee004a86cf98f3007312a75444e
F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc
@ -117,7 +117,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 880ef67cb4f2797b95bf1368fc4e0d8ca0fda956 F www/tclsqlite.tcl 880ef67cb4f2797b95bf1368fc4e0d8ca0fda956
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
P 3be8a189e8ccf8a82acc4ee72cc75b6cc92aa193 P 653f37c365a0b5d59c11b7dbba57905ffaeff2dc
R bef40867b94c97a0a18ccef8081a3db9 R 63aae37ccfcafcca670cad8f7e9ab9ed
U drh U drh
Z c7c502054afc4f55970b082ddb69834b Z 57898bef4e7a90862dc49491082c0c29

View File

@ -1 +1 @@
653f37c365a0b5d59c11b7dbba57905ffaeff2dc 585ed5ebf1c1afc8ae1d569b121208018d8ecd49

View File

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give. ** May you share freely, never taking more than you give.
** **
************************************************************************* *************************************************************************
** $Id: btree.c,v 1.41 2001/11/23 00:24:12 drh Exp $ ** $Id: btree.c,v 1.42 2001/12/05 00:21:20 drh Exp $
** **
** This file implements a external (disk-based) database using BTrees. ** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to ** For a detailed discussion of BTrees, refer to
@ -676,6 +676,24 @@ page1_init_failed:
return rc; return rc;
} }
/*
** If there are no outstanding cursors and we are not in the middle
** of a transaction but there is a read lock on the database, then
** this routine unrefs the first page of the database file which
** has the effect of releasing the read lock.
**
** If there are any outstanding cursors, this routine is a no-op.
**
** If there is a transaction in progress, this routine is a no-op.
*/
static void unlockBtreeIfUnused(Btree *pBt){
if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
sqlitepager_unref(pBt->page1);
pBt->page1 = 0;
pBt->inTrans = 0;
}
}
/* /*
** Create a new database by initializing the first two pages of the ** Create a new database by initializing the first two pages of the
** file. ** file.
@ -725,33 +743,19 @@ int sqliteBtreeBeginTrans(Btree *pBt){
return rc; return rc;
} }
} }
if( !sqlitepager_isreadonly(pBt->pPager) ){ if( sqlitepager_isreadonly(pBt->pPager) ){
rc = sqlitepager_write(pBt->page1); return SQLITE_READONLY;
if( rc!=SQLITE_OK ){ }
return rc; rc = sqlitepager_write(pBt->page1);
} if( rc==SQLITE_OK ){
rc = newDatabase(pBt); rc = newDatabase(pBt);
} }
pBt->inTrans = 1; if( rc==SQLITE_OK ){
return rc; pBt->inTrans = 1;
} }else{
unlockBtreeIfUnused(pBt);
/*
** If there are no outstanding cursors and we are not in the middle
** of a transaction but there is a read lock on the database, then
** this routine unrefs the first page of the database file which
** has the effect of releasing the read lock.
**
** If there are any outstanding cursors, this routine is a no-op.
**
** If there is a transaction in progress, this routine is a no-op.
*/
static void unlockBtreeIfUnused(Btree *pBt){
if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
sqlitepager_unref(pBt->page1);
pBt->page1 = 0;
pBt->inTrans = 0;
} }
return rc;
} }
/* /*

View File

@ -25,7 +25,7 @@
** ROLLBACK ** ROLLBACK
** PRAGMA ** PRAGMA
** **
** $Id: build.c,v 1.57 2001/11/22 00:01:27 drh Exp $ ** $Id: build.c,v 1.58 2001/12/05 00:21:20 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -553,7 +553,7 @@ void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
*/ */
static void changeCookie(sqlite *db){ static void changeCookie(sqlite *db){
if( db->next_cookie==db->schema_cookie ){ if( db->next_cookie==db->schema_cookie ){
db->next_cookie = db->schema_cookie + sqliteRandomByte(db) + 1; db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1;
db->flags |= SQLITE_InternChanges; db->flags |= SQLITE_InternChanges;
} }
} }

View File

@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be ** other files are for internal use by SQLite and should not be
** accessed by users of the library. ** accessed by users of the library.
** **
** $Id: main.c,v 1.50 2001/11/23 00:24:12 drh Exp $ ** $Id: main.c,v 1.51 2001/12/05 00:21:20 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "os.h" #include "os.h"
@ -265,7 +265,7 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
if( db==0 ) goto no_mem_on_open; if( db==0 ) goto no_mem_on_open;
sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
db->nextRowid = sqliteRandomInteger(db); db->nextRowid = sqliteRandomInteger();
/* Open the backend database driver */ /* Open the backend database driver */
rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe); rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);

View File

@ -59,8 +59,8 @@ int sqliteOsLock(OsFile, int wrlock);
int sqliteOsUnlock(OsFile); int sqliteOsUnlock(OsFile);
int sqliteOsRandomSeed(char*); int sqliteOsRandomSeed(char*);
int sqliteOsSleep(int ms); int sqliteOsSleep(int ms);
void sqliteOsEnterMutex(); void sqliteOsEnterMutex(void);
void sqliteOsLeaveMutex(); void sqliteOsLeaveMutex(void);

View File

@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while ** file simultaneously, or one process from reading the database while
** another is writing. ** another is writing.
** **
** @(#) $Id: pager.c,v 1.31 2001/11/22 00:01:27 drh Exp $ ** @(#) $Id: pager.c,v 1.32 2001/12/05 00:21:20 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "pager.h" #include "pager.h"
@ -955,13 +955,20 @@ int sqlitepager_write(void *pData){
} }
sqliteOsUnlock(pPager->fd); sqliteOsUnlock(pPager->fd);
if( sqliteOsLock(pPager->fd, 1)!=SQLITE_OK ){ if( sqliteOsLock(pPager->fd, 1)!=SQLITE_OK ){
sqliteOsUnlock(pPager->fd);
rc = sqliteOsLock(pPager->fd, 0);
sqliteFree(pPager->aInJournal); sqliteFree(pPager->aInJournal);
sqliteOsClose(pPager->jfd); sqliteOsClose(pPager->jfd);
sqliteOsDelete(pPager->zJournal); sqliteOsDelete(pPager->zJournal);
pPager->journalOpen = 0; pPager->journalOpen = 0;
pPager->state = SQLITE_UNLOCK; if( rc ){
pPager->errMask |= PAGER_ERR_LOCK; pPager->state = SQLITE_UNLOCK;
return SQLITE_PROTOCOL; pPager->errMask |= PAGER_ERR_LOCK;
return SQLITE_PROTOCOL;
}else{
pPager->state = SQLITE_READLOCK;
return SQLITE_BUSY;
}
} }
pPager->state = SQLITE_WRITELOCK; pPager->state = SQLITE_WRITELOCK;
sqlitepager_pagecount(pPager); sqlitepager_pagecount(pPager);

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.71 2001/11/22 00:01:27 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.72 2001/12/05 00:21:20 drh Exp $
*/ */
#include "sqlite.h" #include "sqlite.h"
#include "hash.h" #include "hash.h"
@ -519,8 +519,8 @@ void sqliteExprResolveInSelect(Parse*, Expr*);
int sqliteExprAnalyzeAggregates(Parse*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*);
void sqliteParseInfoReset(Parse*); void sqliteParseInfoReset(Parse*);
Vdbe *sqliteGetVdbe(Parse*); Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte(); int sqliteRandomByte(void);
int sqliteRandomInteger(); int sqliteRandomInteger(void);
void sqliteBeginTransaction(Parse*); void sqliteBeginTransaction(Parse*);
void sqliteCommitTransaction(Parse*); void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*); void sqliteRollbackTransaction(Parse*);

View File

@ -17,9 +17,14 @@ proc chng {date desc} {
puts "<DD><P><UL>$desc</UL></P></DD>" puts "<DD><P><UL>$desc</UL></P></DD>"
} }
chng {2001 Nov ?? (2.1.4)} { chng {2001 Dec 4 (2.1.4)} {
<li>Sometime <b>sqlite_exec()</b> would return SQLITE_PROTOCOL when it
should have returned SQLITE_BUSY.</li>
<li>The fix to the previous bug uncovered a deadlock which was also
fixed.</li>
<li>Add the ability to put a single .command in the second argument <li>Add the ability to put a single .command in the second argument
of the sqlite shell</li> of the sqlite shell</li>
<li>Updates to the FAQ</li>
} }
chng {2001 Nov 23 (2.1.3)} { chng {2001 Nov 23 (2.1.3)} {

View File

@ -1,7 +1,7 @@
# #
# Run this script to generated a faq.html output file # Run this script to generated a faq.html output file
# #
set rcsid {$Id: faq.tcl,v 1.2 2001/11/24 13:23:05 drh Exp $} set rcsid {$Id: faq.tcl,v 1.3 2001/12/05 00:21:21 drh Exp $}
puts {<html> puts {<html>
<head> <head>
@ -93,14 +93,13 @@ faq {
} }
faq { faq {
The second INSERT in the following sequence of commands returns with Why does the second INSERT in the following sequence of commands throw
constraint error. a constraint exception?
<blockquote> <blockquote>
CREATE TABLE t(s varchar(10) primary key);<br> CREATE TABLE t(s varchar(10) primary key);<br>
INSERT INTO t VALUES('0');<br> INSERT INTO t VALUES('0');<br>
INSERT INTO t VALUES('0.0');<br> INSERT INTO t VALUES('0.0');<br>
</blockquote> </blockquote>
Why is this?
} { } {
<p>Because column <b>s</b> is a primary key, all values of <b>s</b> must <p>Because column <b>s</b> is a primary key, all values of <b>s</b> must
be unique. But SQLite thinks that <b>'0'</b> and <b>'0.0'</b> are the be unique. But SQLite thinks that <b>'0'</b> and <b>'0.0'</b> are the
@ -124,7 +123,7 @@ faq {
My linux box is not able to read an SQLite database that was created My linux box is not able to read an SQLite database that was created
on my SparcStation. on my SparcStation.
} { } {
<p>The x86 processor on your windows box is little-endian (meaning that <p>The x86 processor on your linux box is little-endian (meaning that
the least signification byte of integers comes first) but the Sparc is the least signification byte of integers comes first) but the Sparc is
big-endian (the most significant bytes comes first). SQLite databases big-endian (the most significant bytes comes first). SQLite databases
created on a little-endian architecture cannot be used on a big-endian created on a little-endian architecture cannot be used on a big-endian
@ -234,6 +233,30 @@ ORDER BY name;
there is no way to get a listing of temporary tables and indices.</p> there is no way to get a listing of temporary tables and indices.</p>
} }
faq {
Is there any known size limits to SQLite databases.
} {
<p>Internally, SQLite can handle databases up to 2^40 bytes (1 terabyte)
in size. But the backend interface to POSIX and Win32 limits files to
2^31 (2 gigabytes).</p>
<p>SQLite arbitrarily limits the amount of data in one row to 1 megabyte.
There is a single #define in the source code that can be changed to raise
this limit as high as 16 megabytes if desired.</p>
<p>There is a theoretical limit of about 2^32 (4 billion) rows
in a single table, but there
is no way to test this limit without exceeding the maximum file size, so
it is not really an issue. There is also a theoretical limit of about 2^32
tables and indices, but again it is not really possible to reach this
limit due to the file size constraint.</p>
<p>The name and "CREATE TABLE" statement for a table must fit entirely
within a 1-megabyte row of the SQLITE_MASTER table. Other than this,
there are no constraints on the length of the name of a table, or on the
number of columns, etc. Indices are similarly unconstrained.</p>
}
# End of questions and answers. # End of questions and answers.
############# #############
@ -242,15 +265,16 @@ for {set i 1} {$i<$cnt} {incr i} {
puts " <DT><A HREF=\"#q$i\">($i)</A></DT>" puts " <DT><A HREF=\"#q$i\">($i)</A></DT>"
puts " <DD>[lindex $faq($i) 0]</DD>" puts " <DD>[lindex $faq($i) 0]</DD>"
} }
puts {</DL><HR />} puts {</DL>}
for {set i 1} {$i<$cnt} {incr i} { for {set i 1} {$i<$cnt} {incr i} {
puts "<A NAME=\"q$i\">" puts "<A NAME=\"q$i\"><HR />"
puts "<P><B>($i) [lindex $faq($i) 0]</B></P>\n" puts "<P><B>($i) [lindex $faq($i) 0]</B></P>\n"
puts "<BLOCKQUOTE>[lindex $faq($i) 1]</BLOCKQUOTE>\n" puts "<BLOCKQUOTE>[lindex $faq($i) 1]</BLOCKQUOTE></LI>\n"
} }
puts { puts {
</OL>
<p><hr /></p> <p><hr /></p>
<p><a href="index.html"><img src="/goback.jpg" border=0 /> <p><a href="index.html"><img src="/goback.jpg" border=0 />
Back to the SQLite Home Page</a> Back to the SQLite Home Page</a>