Fix an assertion failure when the disk fills up. Add tests for a full
disk situation. (CVS 285) FossilOrigin-Name: 0a7848b6190981cb7eb673bbe68cb217694daf2e
This commit is contained in:
parent
4299020922
commit
81a20f21d5
@ -99,6 +99,7 @@ SRC = \
|
||||
#
|
||||
TESTSRC = \
|
||||
$(TOP)/src/btree.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/test1.c \
|
||||
$(TOP)/src/test2.c \
|
||||
|
@ -146,6 +146,7 @@ SRC = \
|
||||
#
|
||||
TESTSRC = \
|
||||
$(TOP)/src/btree.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/pager.c \
|
||||
$(TOP)/src/test1.c \
|
||||
$(TOP)/src/test2.c \
|
||||
|
37
manifest
37
manifest
@ -1,7 +1,7 @@
|
||||
C Version\s2.0.2\s(CVS\s468)
|
||||
D 2001-10-09T14:00:00
|
||||
F Makefile.in 98d4627cb364537e4c3a29ee806171f3abf5211a
|
||||
F Makefile.template 1e54087c0390c4ce0bb5be43e14ba028283751e6
|
||||
C Fix\san\sassertion\sfailure\swhen\sthe\sdisk\sfills\sup.\s\sAdd\stests\sfor\sa\sfull\ndisk\ssituation.\s(CVS\s285)
|
||||
D 2001-10-12T17:30:04
|
||||
F Makefile.in 6801df952cb1df64aa32e4de85fed24511d28efd
|
||||
F Makefile.template 582916b263aa40a70521dfb3d99d574028abd47b
|
||||
F README 93d2977cc5c6595c448de16bdefc312b9d401533
|
||||
F VERSION 73e5f5e088b67ed1629b08ca531b81c778ab8695
|
||||
F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
|
||||
@ -21,36 +21,36 @@ F publish.sh badcd69b8e3a8bc69b162c4c9d7c209b2a0b119e
|
||||
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
|
||||
F src/btree.c 7e9c33a714ed1630562f89ad19847f5f28bd6d4d
|
||||
F src/btree.h 57d653ef5137b91f2a068aaf71a2905468dd2cb7
|
||||
F src/build.c 707f6ef58dcdd50ead9ead914d673b08e7121bc5
|
||||
F src/build.c cb3607c86f20dd3c18dccbe21f1b9bcd33ef9a36
|
||||
F src/delete.c 93c9d5e160395020a25d59371625db74c97c7c4d
|
||||
F src/expr.c 2f68829d983ec3f92eeb8b89ce4b9e5704169a80
|
||||
F src/hash.c bf36fb4cba114015123b0050f137d2c4553778a1
|
||||
F src/hash.c b7ced0735287c142a3b2db46c3cae3e6826afb75
|
||||
F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
|
||||
F src/insert.c a48ba850461b203fb8dbc7add83fc6b6a9cf47f3
|
||||
F src/main.c ece73e5a44fab98144c4a93084d68b4fc413ba66
|
||||
F src/main.c 9a18e97290d41844e8c12e021fb7c42948a19dc9
|
||||
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
|
||||
F src/os.c a83f4cb85e4d3b98c1659a799f9e318fcaf1c76c
|
||||
F src/os.c cece4ac6cabc9d377ef0a4ab4c16f6f0f6c84377
|
||||
F src/os.h bed702c9e3b768bc3cb1b12c90b83d099c1546be
|
||||
F src/pager.c 3445bd7c18cbfdffd8d6d1077f0b2bdf788da4fe
|
||||
F src/pager.c e2e189a15e230c60e811f5e2ab25e68ae41c90be
|
||||
F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca
|
||||
F src/parse.y e88f1efe096a1a01c9076099fe1d81deedfa11de
|
||||
F src/parse.y 2275a832b544e8b57c422880a0d9badd4976d042
|
||||
F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9
|
||||
F src/random.c 2a9cc2c9716d14815fd4c2accf89d87a1143e46b
|
||||
F src/select.c 0ef8ca1b7de2467fe082bcb35a5ab3b5be56153c
|
||||
F src/shell.c cb8c41f1b2173efd212dab3f35f1fc6bf32ead76
|
||||
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
|
||||
F src/sqlite.h.in b95c161abf1d58bceb05290fa3f657d8f388fc11
|
||||
F src/sqliteInt.h 603566f58dff0e0295e57792e9313fe5d253f1a2
|
||||
F src/sqliteInt.h 141b57b9eee7e8c937ac603f6cb7ecca77c1dd77
|
||||
F src/table.c abd0adbe0fee39d995287b3bcccd908d174dfcac
|
||||
F src/tclsqlite.c 765599686c19ed777ac379928d732c8bfc63ebac
|
||||
F src/test1.c e4b31f62ea71963cbae44338acf477a04fc8fc49
|
||||
F src/test2.c 0168b39225b768cfdadd534406f9dec58c27879e
|
||||
F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
|
||||
F src/test3.c 4a0d7b882fdae731dbb759f512ad867122452f96
|
||||
F src/tokenize.c 15d349b68d9dc5722956bd7549752ace62034787
|
||||
F src/update.c 49a1edb1a3e44dfff3f799e00f2a3319f2393cd8
|
||||
F src/util.c 4da3be37d0fd3c640d2d3033503768afdc8e5387
|
||||
F src/vdbe.c 594050d9a8dc51b97320c52d4665de313b842c27
|
||||
F src/vdbe.h 7eb7e9e6c58fe9430efab35e168f96cb4bd6cb45
|
||||
F src/vdbe.h adecb0f37d2c1aa34f2cbd359b63b8c922e72c1f
|
||||
F src/where.c b676765ad0360769173b09f46265ddec8d48367a
|
||||
F test/all.test a2320eb40b462f25bd3e33115b1cabf3791450dd
|
||||
F test/bigrow.test a35f2de9948b24e427fb292c35947795efe182d0
|
||||
@ -64,6 +64,7 @@ F test/in.test 9323681388be301dc73f370b4cd62c5a33f79d1e
|
||||
F test/index.test 6076f29d09a4f26a2efa38b03b8cc338b8662f0e
|
||||
F test/insert.test a5c122aa726f1cef6f07d6767e8fd6f220994c11
|
||||
F test/insert2.test 252d7130d8cc20f649b31a4f503cd87e660abda8
|
||||
F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a
|
||||
F test/lock.test 19593689260c419efe7ced55b1418653a4b7bcd1
|
||||
F test/main.test 085ece17913a487caacbc0a392638c958c83a75d
|
||||
F test/malloc.test f1400a8d002eb96f1ca0a34abe56d2ab3e324740
|
||||
@ -100,8 +101,8 @@ F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
|
||||
F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
|
||||
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
|
||||
F www/arch.tcl 03b521d252575f93b9c52f7c8b0007011512fcfb
|
||||
F www/c_interface.tcl 8e8d9e66e8467c5751116c3427296bde77f474a6
|
||||
F www/changes.tcl 2b416b49a136312678317f509821cf9359e421b5
|
||||
F www/c_interface.tcl a59ee0835d1b33fcddab7d4fd65cf9e50f7d2dc7
|
||||
F www/changes.tcl 4c722e1271b9c25477f2483dad1a96681ce73380
|
||||
F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
|
||||
F www/download.tcl 3e51c9ff1326b0a182846134987301310dff7d60
|
||||
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
|
||||
@ -113,7 +114,7 @@ F www/speed.tcl ab7d6d3bc898472bd94320a5d3c63de928d4804b
|
||||
F www/sqlite.tcl 6a21242a272e9c0939a04419a51c3d50cae33e3e
|
||||
F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa
|
||||
F www/vdbe.tcl bb7d620995f0a987293e9d4fb6185a3b077e9b44
|
||||
P abe5a25b9dcf1e47f3cb37fd419f620db03bd4da
|
||||
R 811a44282886ed3bd9485148120cee71
|
||||
P 44d00a6f58c71ca11423df12530177baaa054a01
|
||||
R 8b125f0466bafcf592b4cb611703e2d3
|
||||
U drh
|
||||
Z bb72d0236472bbdc7b77722d8537d4bf
|
||||
Z c3df09919ca8934d0890578a526b0048
|
||||
|
@ -1 +1 @@
|
||||
44d00a6f58c71ca11423df12530177baaa054a01
|
||||
0a7848b6190981cb7eb673bbe68cb217694daf2e
|
32
src/build.c
32
src/build.c
@ -25,7 +25,7 @@
|
||||
** ROLLBACK
|
||||
** PRAGMA
|
||||
**
|
||||
** $Id: build.c,v 1.46 2001/10/09 04:19:47 drh Exp $
|
||||
** $Id: build.c,v 1.47 2001/10/12 17:30:05 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -1477,6 +1477,36 @@ void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
|
||||
}
|
||||
}else
|
||||
|
||||
if( sqliteStrICmp(zLeft, "index_list")==0 ){
|
||||
Index *pIdx;
|
||||
Table *pTab;
|
||||
Vdbe *v;
|
||||
pTab = sqliteFindTable(db, zRight);
|
||||
if( pTab ){
|
||||
v = sqliteGetVdbe(pParse);
|
||||
pIdx = pTab->pIndex;
|
||||
}
|
||||
if( pTab && pIdx && v ){
|
||||
int i = 0;
|
||||
static VdbeOp indexListPreface[] = {
|
||||
{ OP_ColumnCount, 3, 0, 0},
|
||||
{ OP_ColumnName, 0, 0, "seq"},
|
||||
{ OP_ColumnName, 1, 0, "name"},
|
||||
{ OP_ColumnName, 2, 0, "unique"},
|
||||
};
|
||||
|
||||
sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
|
||||
while(pIdx){
|
||||
sqliteVdbeAddOp(v, OP_Integer, i, 0, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_String, 0, 0, pIdx->zName, 0);
|
||||
sqliteVdbeAddOp(v, OP_Integer, pIdx->isUnique, 0, 0, 0);
|
||||
sqliteVdbeAddOp(v, OP_Callback, 3, 0, 0, 0);
|
||||
++i;
|
||||
pIdx = pIdx->pNext;
|
||||
}
|
||||
}
|
||||
}else
|
||||
|
||||
#ifndef NDEBUG
|
||||
if( sqliteStrICmp(zLeft, "parser_trace")==0 ){
|
||||
extern void sqliteParserTrace(FILE*, char *);
|
||||
|
18
src/hash.c
18
src/hash.c
@ -12,7 +12,7 @@
|
||||
** This is the implementation of generic hash-tables
|
||||
** used in SQLite.
|
||||
**
|
||||
** $Id: hash.c,v 1.1 2001/09/22 18:12:10 drh Exp $
|
||||
** $Id: hash.c,v 1.2 2001/10/12 17:30:05 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <assert.h>
|
||||
@ -197,7 +197,7 @@ static HashElem *findElementGivenHash(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remove a single entry from the pH given a pointer to that
|
||||
/* Remove a single entry from the hash table given a pointer to that
|
||||
** element and a hash on the element's key.
|
||||
*/
|
||||
static void removeElementGivenHash(
|
||||
@ -228,7 +228,7 @@ static void removeElementGivenHash(
|
||||
}
|
||||
|
||||
/* Attempt to locate an element of the associative pH with a key
|
||||
** that matches "key". Return the data for this element if it is
|
||||
** that matches pKey,nKey. Return the data for this element if it is
|
||||
** found, or NULL if no match is found.
|
||||
*/
|
||||
void *sqliteHashFind(const Hash *pH, const void *pKey, int nKey){
|
||||
@ -245,19 +245,19 @@ void *sqliteHashFind(const Hash *pH, const void *pKey, int nKey){
|
||||
return elem ? elem->data : 0;
|
||||
}
|
||||
|
||||
/* Insert an element into the pH. The key will be "key" and
|
||||
** the data will be "data".
|
||||
/* Insert an element into the hash table pH. The key is pKey,nKey
|
||||
** and the data is "data".
|
||||
**
|
||||
** If no pH element exists with a matching key, then a new
|
||||
** pH element is created. The key is copied (using the copy
|
||||
** function of the key class) into the new element. NULL is returned.
|
||||
** If no element exists with a matching key, then a new
|
||||
** element is created. A copy of the key is made if the copyKey
|
||||
** flag is set. NULL is returned.
|
||||
**
|
||||
** If another element already exists with the same key, then the
|
||||
** new data replaces the old data and the old data is returned.
|
||||
** The key is not copied in this instance.
|
||||
**
|
||||
** If the "data" parameter to this function is NULL, then the
|
||||
** element corresponding to "key" is removed from the pH.
|
||||
** element corresponding to "key" is removed from the hash table.
|
||||
*/
|
||||
void *sqliteHashInsert(Hash *pH, void *pKey, int nKey, void *data){
|
||||
int hraw; /* Raw hash value of the key */
|
||||
|
@ -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.45 2001/10/09 13:46:01 drh Exp $
|
||||
** $Id: main.c,v 1.46 2001/10/12 17:30:05 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
29
src/os.c
29
src/os.c
@ -11,7 +11,7 @@
|
||||
******************************************************************************
|
||||
**
|
||||
** This file contains code that is specific to particular operating
|
||||
** systems. The purpose of this file is to provide a uniform abstract
|
||||
** systems. The purpose of this file is to provide a uniform abstraction
|
||||
** on which the rest of SQLite can operate.
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
@ -158,6 +158,23 @@ static void releaseLockInfo(struct lockInfo *pInfo){
|
||||
}
|
||||
#endif /** POSIX advisory lock work-around **/
|
||||
|
||||
/*
|
||||
** If we compile with the SQLITE_TEST macro set, then the following block
|
||||
** of code will give us the ability to simulate a disk I/O error. This
|
||||
** is used for testing the I/O recovery logic.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite_io_error_pending = 0;
|
||||
#define SimulateIOError(A) \
|
||||
if( sqlite_io_error_pending ) \
|
||||
if( sqlite_io_error_pending-- == 1 ){ local_ioerr(); return A; }
|
||||
static void local_ioerr(){
|
||||
sqlite_io_error_pending = 0; /* Really just a place to set a breakpoint */
|
||||
}
|
||||
#else
|
||||
#define SimulateIOError(A)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Delete the named file
|
||||
@ -248,7 +265,7 @@ int sqliteOsOpenReadWrite(
|
||||
NULL
|
||||
);
|
||||
if( h==INVALID_HANDLE_VALUE ){
|
||||
HANDLE h = CreateFile(zFilename,
|
||||
h = CreateFile(zFilename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
@ -443,12 +460,14 @@ int sqliteOsClose(OsFile id){
|
||||
int sqliteOsRead(OsFile id, void *pBuf, int amt){
|
||||
#if OS_UNIX
|
||||
int got;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
got = read(id.fd, pBuf, amt);
|
||||
if( got<0 ) got = 0;
|
||||
return got==amt ? SQLITE_OK : SQLITE_IOERR;
|
||||
#endif
|
||||
#if OS_WIN
|
||||
DWORD got;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
if( !ReadFile(id, pBuf, amt, &got, 0) ){
|
||||
got = 0;
|
||||
}
|
||||
@ -463,12 +482,14 @@ int sqliteOsRead(OsFile id, void *pBuf, int amt){
|
||||
int sqliteOsWrite(OsFile id, const void *pBuf, int amt){
|
||||
#if OS_UNIX
|
||||
int wrote;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
wrote = write(id.fd, pBuf, amt);
|
||||
if( wrote<amt ) return SQLITE_FULL;
|
||||
return SQLITE_OK;
|
||||
#endif
|
||||
#if OS_WIN
|
||||
DWORD wrote;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
if( !WriteFile(id, pBuf, amt, &wrote, 0) || wrote<amt ){
|
||||
return SQLITE_FULL;
|
||||
}
|
||||
@ -494,6 +515,7 @@ int sqliteOsSeek(OsFile id, int offset){
|
||||
** Make sure all writes to a particular file are committed to disk.
|
||||
*/
|
||||
int sqliteOsSync(OsFile id){
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
#if OS_UNIX
|
||||
return fsync(id.fd)==0 ? SQLITE_OK : SQLITE_IOERR;
|
||||
#endif
|
||||
@ -506,6 +528,7 @@ int sqliteOsSync(OsFile id){
|
||||
** Truncate an open file to a specified size
|
||||
*/
|
||||
int sqliteOsTruncate(OsFile id, int nByte){
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
#if OS_UNIX
|
||||
return ftruncate(id.fd, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
|
||||
#endif
|
||||
@ -522,6 +545,7 @@ int sqliteOsTruncate(OsFile id, int nByte){
|
||||
int sqliteOsFileSize(OsFile id, int *pSize){
|
||||
#if OS_UNIX
|
||||
struct stat buf;
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
if( fstat(id.fd, &buf)!=0 ){
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
@ -529,6 +553,7 @@ int sqliteOsFileSize(OsFile id, int *pSize){
|
||||
return SQLITE_OK;
|
||||
#endif
|
||||
#if OS_WIN
|
||||
SimulateIOError(SQLITE_IOERR);
|
||||
*pSize = GetFileSize(id, 0);
|
||||
return SQLITE_OK;
|
||||
#endif
|
||||
|
30
src/pager.c
30
src/pager.c
@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.26 2001/10/08 13:22:33 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.27 2001/10/12 17:30:05 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "pager.h"
|
||||
@ -128,6 +128,7 @@ struct Pager {
|
||||
#define PAGER_ERR_MEM 0x02 /* malloc() failed */
|
||||
#define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */
|
||||
#define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */
|
||||
#define PAGER_ERR_DISK 0x10 /* general disk I/O error - bad hard drive? */
|
||||
|
||||
/*
|
||||
** The journal file contains page records in the following
|
||||
@ -178,6 +179,7 @@ static const unsigned char aJournalMagic[] = {
|
||||
static int pager_errcode(Pager *pPager){
|
||||
int rc = SQLITE_OK;
|
||||
if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL;
|
||||
if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR;
|
||||
if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL;
|
||||
if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM;
|
||||
if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT;
|
||||
@ -305,20 +307,25 @@ static int pager_playback(Pager *pPager){
|
||||
sqliteOsSeek(pPager->jfd, 0);
|
||||
rc = sqliteOsRead(pPager->jfd, aMagic, sizeof(aMagic));
|
||||
if( rc!=SQLITE_OK || memcmp(aMagic,aJournalMagic,sizeof(aMagic))!=0 ){
|
||||
return SQLITE_PROTOCOL;
|
||||
rc = SQLITE_PROTOCOL;
|
||||
goto end_playback;
|
||||
}
|
||||
rc = sqliteOsRead(pPager->jfd, &mxPg, sizeof(mxPg));
|
||||
if( rc!=SQLITE_OK ){
|
||||
return SQLITE_PROTOCOL;
|
||||
goto end_playback;
|
||||
}
|
||||
rc = sqliteOsTruncate(pPager->fd, mxPg*SQLITE_PAGE_SIZE);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto end_playback;
|
||||
}
|
||||
sqliteOsTruncate(pPager->fd, mxPg*SQLITE_PAGE_SIZE);
|
||||
pPager->dbSize = mxPg;
|
||||
|
||||
/* Begin reading the journal beginning at the end and moving
|
||||
** toward the beginning.
|
||||
*/
|
||||
if( sqliteOsFileSize(pPager->jfd, &nRec)!=SQLITE_OK ){
|
||||
return SQLITE_OK;
|
||||
rc = sqliteOsFileSize(pPager->jfd, &nRec);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto end_playback;
|
||||
}
|
||||
nRec = (nRec - (sizeof(aMagic)+sizeof(Pgno))) / sizeof(PageRecord);
|
||||
|
||||
@ -353,6 +360,8 @@ static int pager_playback(Pager *pPager){
|
||||
rc = sqliteOsWrite(pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
}
|
||||
|
||||
end_playback:
|
||||
if( rc!=SQLITE_OK ){
|
||||
pager_unwritelock(pPager);
|
||||
pPager->errMask |= PAGER_ERR_CORRUPT;
|
||||
@ -470,6 +479,7 @@ int sqlitepager_pagecount(Pager *pPager){
|
||||
return pPager->dbSize;
|
||||
}
|
||||
if( sqliteOsFileSize(pPager->fd, &n)!=SQLITE_OK ){
|
||||
pPager->errMask |= PAGER_ERR_DISK;
|
||||
return 0;
|
||||
}
|
||||
n /= SQLITE_PAGE_SIZE;
|
||||
@ -589,7 +599,7 @@ static int syncAllPages(Pager *pPager){
|
||||
pPg->dirty = 0;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -790,8 +800,12 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
|
||||
if( pPager->dbSize<pgno ){
|
||||
memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
|
||||
}else{
|
||||
int rc;
|
||||
sqliteOsSeek(pPager->fd, (pgno-1)*SQLITE_PAGE_SIZE);
|
||||
sqliteOsRead(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
|
||||
rc = sqliteOsRead(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if( pPager->nExtra>0 ){
|
||||
memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
|
||||
|
22
src/parse.y
22
src/parse.y
@ -14,7 +14,7 @@
|
||||
** the parser. Lemon will also generate a header file containing
|
||||
** numeric codes for all of the tokens.
|
||||
**
|
||||
** @(#) $Id: parse.y,v 1.35 2001/10/08 13:22:33 drh Exp $
|
||||
** @(#) $Id: parse.y,v 1.36 2001/10/12 17:30:05 drh Exp $
|
||||
*/
|
||||
%token_prefix TK_
|
||||
%token_type {Token}
|
||||
@ -329,10 +329,11 @@ inscollist(A) ::= ids(Y). {A = sqliteIdListAppend(0,&Y);}
|
||||
%right NOT.
|
||||
%left EQ NE ISNULL NOTNULL IS LIKE GLOB BETWEEN IN.
|
||||
%left GT GE LT LE.
|
||||
%left BITAND BITOR LSHIFT RSHIFT.
|
||||
%left PLUS MINUS.
|
||||
%left STAR SLASH.
|
||||
%left STAR SLASH MOD.
|
||||
%left CONCAT.
|
||||
%right UMINUS.
|
||||
%right UMINUS BITNOT.
|
||||
|
||||
%type expr {Expr*}
|
||||
%destructor expr {sqliteExprDelete($$);}
|
||||
@ -364,7 +365,11 @@ expr(A) ::= expr(X) LE expr(Y). {A = sqliteExpr(TK_LE, X, Y, 0);}
|
||||
expr(A) ::= expr(X) GE expr(Y). {A = sqliteExpr(TK_GE, X, Y, 0);}
|
||||
expr(A) ::= expr(X) NE expr(Y). {A = sqliteExpr(TK_NE, X, Y, 0);}
|
||||
expr(A) ::= expr(X) EQ expr(Y). {A = sqliteExpr(TK_EQ, X, Y, 0);}
|
||||
expr(A) ::= expr(X) LIKE expr(Y). {A = sqliteExpr(TK_LIKE, X, Y, 0);}
|
||||
expr(A) ::= expr(X) BITAND expr(Y). {A = sqliteExpr(TK_BITAND, X, Y, 0);}
|
||||
expr(A) ::= expr(X) BITOR expr(Y). {A = sqliteExpr(TK_BITOR, X, Y, 0);}
|
||||
expr(A) ::= expr(X) LSHIFT expr(Y). {A = sqliteExpr(TK_LSHIFT, X, Y, 0);}
|
||||
expr(A) ::= expr(X) RSHIFT expr(Y). {A = sqliteExpr(TK_RSHIFT, X, Y, 0);}
|
||||
expr(A) ::= expr(X) LIKE expr(Y). {A = sqliteExpr(TK_LIKE, X, Y, 0);}
|
||||
expr(A) ::= expr(X) NOT LIKE expr(Y). {
|
||||
A = sqliteExpr(TK_LIKE, X, Y, 0);
|
||||
A = sqliteExpr(TK_NOT, A, 0, 0);
|
||||
@ -380,6 +385,7 @@ expr(A) ::= expr(X) PLUS expr(Y). {A = sqliteExpr(TK_PLUS, X, Y, 0);}
|
||||
expr(A) ::= expr(X) MINUS expr(Y). {A = sqliteExpr(TK_MINUS, X, Y, 0);}
|
||||
expr(A) ::= expr(X) STAR expr(Y). {A = sqliteExpr(TK_STAR, X, Y, 0);}
|
||||
expr(A) ::= expr(X) SLASH expr(Y). {A = sqliteExpr(TK_SLASH, X, Y, 0);}
|
||||
expr(A) ::= expr(X) MOD expr(Y). {A = sqliteExpr(TK_MOD, X, Y, 0);}
|
||||
expr(A) ::= expr(X) CONCAT expr(Y). {A = sqliteExpr(TK_CONCAT, X, Y, 0);}
|
||||
expr(A) ::= expr(X) ISNULL(E). {
|
||||
A = sqliteExpr(TK_ISNULL, X, 0, 0);
|
||||
@ -397,10 +403,18 @@ expr(A) ::= expr(X) NOT NULL(E). {
|
||||
A = sqliteExpr(TK_NOTNULL, X, 0, 0);
|
||||
sqliteExprSpan(A,&X->span,&E);
|
||||
}
|
||||
expr(A) ::= expr(X) IS NOT NULL(E). {
|
||||
A = sqliteExpr(TK_NOTNULL, X, 0, 0);
|
||||
sqliteExprSpan(A,&X->span,&E);
|
||||
}
|
||||
expr(A) ::= NOT(B) expr(X). {
|
||||
A = sqliteExpr(TK_NOT, X, 0, 0);
|
||||
sqliteExprSpan(A,&B,&X->span);
|
||||
}
|
||||
expr(A) ::= BITNOT(B) expr(X). {
|
||||
A = sqliteExpr(TK_BITNOT, X, 0, 0);
|
||||
sqliteExprSpan(A,&B,&X->span);
|
||||
}
|
||||
expr(A) ::= MINUS(B) expr(X). [UMINUS] {
|
||||
A = sqliteExpr(TK_UMINUS, X, 0, 0);
|
||||
sqliteExprSpan(A,&B,&X->span);
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.59 2001/10/09 04:19:47 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.60 2001/10/12 17:30:05 drh Exp $
|
||||
*/
|
||||
#include "sqlite.h"
|
||||
#include "hash.h"
|
||||
@ -117,6 +117,21 @@ extern int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */
|
||||
#define FN_Fcnt 6
|
||||
#define FN_Length 7
|
||||
#define FN_Substr 8
|
||||
#if 0
|
||||
#define FN_Abs 9
|
||||
#define FN_Ceil 10
|
||||
#define FN_Floor 11
|
||||
#define FN_Frac 12
|
||||
#define FN_Sin 13
|
||||
#define FN_Cos 14
|
||||
#define FN_Tan 15
|
||||
#define FN_Asin 16
|
||||
#define FN_Acos 17
|
||||
#define FN_Atan 18
|
||||
#define FN_Exp 19
|
||||
#define FN_Ln 20
|
||||
#define FN_Pow 21
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Forward references to structures
|
||||
|
@ -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.5 2001/09/16 00:13:27 drh Exp $
|
||||
** $Id: test2.c,v 1.6 2001/10/12 17:30:05 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "pager.h"
|
||||
@ -388,6 +388,7 @@ static int page_write(
|
||||
** Register commands with the TCL interpreter.
|
||||
*/
|
||||
int Sqlitetest2_Init(Tcl_Interp *interp){
|
||||
extern int sqlite_io_error_pending;
|
||||
Tcl_CreateCommand(interp, "pager_open", pager_open, 0, 0);
|
||||
Tcl_CreateCommand(interp, "pager_close", pager_close, 0, 0);
|
||||
Tcl_CreateCommand(interp, "pager_commit", pager_commit, 0, 0);
|
||||
@ -400,5 +401,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
|
||||
Tcl_CreateCommand(interp, "page_read", page_read, 0, 0);
|
||||
Tcl_CreateCommand(interp, "page_write", page_write, 0, 0);
|
||||
Tcl_CreateCommand(interp, "page_number", page_number, 0, 0);
|
||||
Tcl_LinkVar(interp, "sqlite_io_error_pending",
|
||||
(char*)&sqlite_io_error_pending, TCL_LINK_INT);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
11
src/vdbe.h
11
src/vdbe.h
@ -15,7 +15,7 @@
|
||||
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||
** simple program to access and modify the underlying database.
|
||||
**
|
||||
** $Id: vdbe.h,v 1.26 2001/10/08 13:22:33 drh Exp $
|
||||
** $Id: vdbe.h,v 1.27 2001/10/12 17:30:05 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_VDBE_H_
|
||||
#define _SQLITE_VDBE_H_
|
||||
@ -160,6 +160,15 @@ typedef struct VdbeOp VdbeOp;
|
||||
#define OP_Subtract 83
|
||||
#define OP_Multiply 84
|
||||
#define OP_Divide 85
|
||||
#define OP_Remainder
|
||||
#define OP_BitAnd
|
||||
#define OP_BitOr
|
||||
#define OP_BitNot
|
||||
#define OP_ShiftLeft
|
||||
#define OP_ShiftRight
|
||||
#define OP_Power
|
||||
#define OP_Exp
|
||||
#define OP_Log
|
||||
#define OP_Min 86
|
||||
#define OP_Max 87
|
||||
#define OP_Like 88
|
||||
|
59
test/ioerr.test
Normal file
59
test/ioerr.test
Normal file
@ -0,0 +1,59 @@
|
||||
# 2001 October 12
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing for correct handling of I/O errors
|
||||
# such as writes failing because the disk is full.
|
||||
#
|
||||
# The tests in this file use special facilities that are only
|
||||
# available in the SQLite test fixture.
|
||||
#
|
||||
# $Id: ioerr.test,v 1.1 2001/10/12 17:30:05 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
set ::go 1
|
||||
for {set n 1} {$go} {incr n} {
|
||||
do_test ioerr-1.$n.1 {
|
||||
set ::sqlite_io_error_pending 0
|
||||
db close
|
||||
catch {file delete -force test.db}
|
||||
sqlite db test.db
|
||||
execsql {SELECT * FROM sqlite_master}
|
||||
} {}
|
||||
do_test ioerr-1.$n.2 [subst {
|
||||
set ::sqlite_io_error_pending $n
|
||||
}] $n
|
||||
do_test ioerr-1.$n.3 {
|
||||
set r [catch {db eval {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
SELECT * FROM sqlite_master;
|
||||
BEGIN TRANSACTION;
|
||||
INSERT INTO t1 VALUES(1,2,3);
|
||||
INSERT INTO t1 VALUES(4,5,6);
|
||||
ROLLBACK;
|
||||
SELECT * FROM t1;
|
||||
BEGIN TRANSACTION;
|
||||
INSERT INTO t1 VALUES(1,2,3);
|
||||
INSERT INTO t1 VALUES(4,5,6);
|
||||
COMMIT;
|
||||
SELECT * FROM t1;
|
||||
DELETE FROM t1 WHERE a<100;
|
||||
}} msg]
|
||||
# if {$r} {puts $msg}
|
||||
set ::go [expr {$::sqlite_io_error_pending<=0}]
|
||||
expr {$::sqlite_io_error_pending>0 || $r!=0}
|
||||
} {1}
|
||||
}
|
||||
set ::sqlite_io_error_pending 0
|
||||
|
||||
|
||||
finish_test
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Run this Tcl script to generate the sqlite.html file.
|
||||
#
|
||||
set rcsid {$Id: c_interface.tcl,v 1.16 2001/09/28 23:11:24 drh Exp $}
|
||||
set rcsid {$Id: c_interface.tcl,v 1.17 2001/10/12 17:30:05 drh Exp $}
|
||||
|
||||
puts {<html>
|
||||
<head>
|
||||
@ -292,7 +292,10 @@ that there is no more space left on the disk.
|
||||
<dd><p>This value is returned if SQLite detects that the database it is
|
||||
working on has become corrupted. Corruption might occur due to a rogue
|
||||
process writing to the database file or it might happen due to an
|
||||
perviously undetected logic error in of SQLite.
|
||||
perviously undetected logic error in of SQLite. This value is also
|
||||
returned if a disk I/O error occurs in such a way that SQLite is forced
|
||||
to leave the database file in a corrupted state. The latter should only
|
||||
happen due to a hardware or operating system malfunction.
|
||||
</p></dd>
|
||||
<dt>SQLITE_FULL</dt>
|
||||
<dd><p>This value is returned if an insertion failed because there is
|
||||
|
@ -17,6 +17,14 @@ proc chng {date desc} {
|
||||
puts "<DD><P><UL>$desc</UL></P></DD>"
|
||||
}
|
||||
|
||||
chng {2001 Oct ? (2.0.3)} {
|
||||
<li>Bug fix: the <b>sqlite_busy_timeout()</b> function was delaying 1000
|
||||
times too long before failing.</li>
|
||||
<li>Bug fix: an assertion was failing if the disk holding the database
|
||||
file became full or stopped accepting writes for some other reason.
|
||||
New tests were added to detect similar problems in the future.</li>
|
||||
}
|
||||
|
||||
chng {2001 Oct 9 (2.0.2)} {
|
||||
<li>Fix two bugs in the locking protocol. (One was masking the other.)</li>
|
||||
<li>Removed some unused "#include <unistd.h>" that were causing problems
|
||||
|
Loading…
Reference in New Issue
Block a user