mirror of https://github.com/sqlite/sqlite
Add tests and fixes for handling malloc() failures related to the virtual table feature. (CVS 3285)
FossilOrigin-Name: 5d1d907189ff3ca7afada83033280cf258984ac0
This commit is contained in:
parent
a298e90d50
commit
be71889703
32
manifest
32
manifest
|
@ -1,5 +1,5 @@
|
|||
C Test\sthe\shandling\sof\serrors\sin\svirtual\stable\smethods.\s(CVS\s3284)
|
||||
D 2006-06-22T09:53:49
|
||||
C Add\stests\sand\sfixes\sfor\shandling\smalloc()\sfailures\srelated\sto\sthe\svirtual\stable\sfeature.\s(CVS\s3285)
|
||||
D 2006-06-23T08:05:19
|
||||
F Makefile.in f839b470345d3cb4b0644068474623fe2464b5d3
|
||||
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
|
@ -72,9 +72,9 @@ F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
|
|||
F src/select.c 380fa06c99ae01050c0054c4b1db91e9f1d8322d
|
||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||
F src/shell.c ad73192b30a338a58fe81183d4a5d5a1d4e51d36
|
||||
F src/sqlite.h.in b8c6139b3af13a2c361a8a5aeabb28aa3eef1ae1
|
||||
F src/sqlite.h.in 698928d10c9960e14c008a9dfcbb1d785fc1d039
|
||||
F src/sqlite3ext.h e334107f6cad0d00c0414e04189742a45ce916b1
|
||||
F src/sqliteInt.h d79b031593462dfcbc8c122a5f698a00e6b124fa
|
||||
F src/sqliteInt.h 83920044668752bc05fde6176e5dea30851cdce0
|
||||
F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e
|
||||
F src/tclsqlite.c 32d9e0147077f2e2c127c5f214fb3fe03ef97d18
|
||||
F src/test1.c 233d5c83d11f34aa1c02eb72011ba9a30b72e078
|
||||
|
@ -84,7 +84,7 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
|
|||
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
|
||||
F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
|
||||
F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
|
||||
F src/test8.c b8014836e18b9f42d0ac5c190efcc8318694c14e
|
||||
F src/test8.c e09bf2654269ff025350d1a40f4b1058a6a07dbb
|
||||
F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
|
||||
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
|
||||
F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
|
||||
|
@ -97,15 +97,15 @@ F src/update.c 686b13db8b28a129a2407aaffc8b7588d1104e0b
|
|||
F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44
|
||||
F src/util.c ca6ee72772c0f5dc04d2e0ab1973fd3b6a9bf79d
|
||||
F src/vacuum.c 5b37d0f436f8e1ffacd17934e44720b38d2247f9
|
||||
F src/vdbe.c 2c36e0badc0bcc14f099e95ec84470c479fbd399
|
||||
F src/vdbe.c b4232a43e8603ed2aced49865bb1de82aa8371e1
|
||||
F src/vdbe.h 258b5d1c0aaa72192f09ff0568ce42b383f156fa
|
||||
F src/vdbeInt.h 6ccb7eaae76ebd761470f6a035501ff33aa92c20
|
||||
F src/vdbeInt.h de89a3475a0a914c49f92e51c303f7dd6f2b21fe
|
||||
F src/vdbeapi.c 6af0e7160af260052a7a4500464221a03dada75f
|
||||
F src/vdbeaux.c 2e4cb97e6d1612c0e108d68e038a7cd612bceb72
|
||||
F src/vdbeaux.c d8cf95bc96fbcd933db14cf6cd196098146d2afd
|
||||
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
|
||||
F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3
|
||||
F src/vtab.c 99ca599e9e4af1a63a3caf4389410a16adacf9f6
|
||||
F src/where.c 0a13357175678d51a218326bca389f20bb41e38b
|
||||
F src/vtab.c 7edad77e201cc83b7826e53393c21d617e472fe1
|
||||
F src/where.c 6175449f1ff97a5bfea4068a35c050456c632e89
|
||||
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/all.test 5df90d015ca63fcef2a4b62c24f7316b66c4bfd4
|
||||
|
@ -225,7 +225,7 @@ F test/pagesize.test 05c74ea49f790734ec1e9ab765d9bf1cce79b8f2
|
|||
F test/pragma.test e2d72d9e9a24744356cd5a4d25ea842c5020d345
|
||||
F test/printf.test cdd8e20dd901382a385afcbaa777b9377815c2ad
|
||||
F test/progress.test 8b22b4974b0a95272566385f8cb8c341c7130df8 x
|
||||
F test/quick.test fc44005d54bc6b43609e3942ddf22babd8230fcc
|
||||
F test/quick.test 4eabf0fd67dc6e116cbebe3f8d899608239eae50
|
||||
F test/quote.test 5891f2338980916cf7415484b4ce785294044adb
|
||||
F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b
|
||||
F test/rollback.test 673cd8c44c685ad54987fe7f0eeba84efa09685d
|
||||
|
@ -252,7 +252,7 @@ F test/table.test 1c1539af8db89c68e467df02ec2607ec61c67bac
|
|||
F test/tableapi.test 6a66d58b37d46dc0f2b3c7d4bd2617d209399bd1
|
||||
F test/tclsqlite.test 93c399414273d829f3fc5fc4a8349b484fe84d5b
|
||||
F test/temptable.test c36f3e5a94507abb64f7ba23deeb4e1a8a8c3821
|
||||
F test/tester.tcl 66a4bfa61a05e08ea523ef077e7ad0eab090c327
|
||||
F test/tester.tcl 0436eda9b45cd937662b9766262cc2527448413f
|
||||
F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35
|
||||
F test/thread2.test 6d7b30102d600f51b4055ee3a5a19228799049fb
|
||||
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
|
||||
|
@ -297,7 +297,7 @@ F test/vtab3.test f38d6d7d19f08bffdadce4d5b8cba078f8118587
|
|||
F test/vtab4.test 4b4293341443839ef6dc02f8d9e614702a6c67ff
|
||||
F test/vtab5.test 9fb8f335651afe8f870011e2f68e5b00c5ad03cd
|
||||
F test/vtab6.test 0b4fe07e421b2b9a334bec8781e75cbd8e230bd3
|
||||
F test/vtab_err.test 7b435152e5555ca01645cbd15864430a80c44765
|
||||
F test/vtab_err.test 11b90203ad60d63746d0de547b1ca014704d8f0e
|
||||
F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
|
||||
F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
|
||||
F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
|
||||
|
@ -373,7 +373,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
|||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||
P d50c37975de7639627422cbed40eb03a431874d5
|
||||
R deba37635ada8fb35f1bc556c53eccea
|
||||
P 51b729d9d9f8a60cdfb552809e4aa10012f4eb68
|
||||
R c21237f21b6a4ca0ffad3dda7ecba2f2
|
||||
U danielk1977
|
||||
Z fb72a1410426354cd3d1ca1870332bcd
|
||||
Z 9f0e1165f66a8128b5c09a2e388b1740
|
||||
|
|
|
@ -1 +1 @@
|
|||
51b729d9d9f8a60cdfb552809e4aa10012f4eb68
|
||||
5d1d907189ff3ca7afada83033280cf258984ac0
|
|
@ -12,7 +12,7 @@
|
|||
** This header file defines the interface that the SQLite library
|
||||
** presents to client programs.
|
||||
**
|
||||
** @(#) $Id: sqlite.h.in,v 1.181 2006/06/22 09:53:50 danielk1977 Exp $
|
||||
** @(#) $Id: sqlite.h.in,v 1.182 2006/06/23 08:05:19 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITE3_H_
|
||||
#define _SQLITE3_H_
|
||||
|
@ -1662,6 +1662,7 @@ int sqlite3_create_module(
|
|||
*/
|
||||
struct sqlite3_vtab {
|
||||
const sqlite3_module *pModule; /* The module for this virtual table */
|
||||
int nRef; /* Used internally */
|
||||
/* Virtual table implementations will typically add additional fields */
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.510 2006/06/17 10:44:42 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.511 2006/06/23 08:05:19 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
|
@ -1820,13 +1820,11 @@ void sqlite3CloseExtensions(sqlite3*);
|
|||
|
||||
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||
# define sqlite3VtabClear(X)
|
||||
# define sqlite3VtabCodeLock(X,Y)
|
||||
# define sqlite3VtabSync(X,Y) (Y)
|
||||
# define sqlite3VtabRollback(X)
|
||||
# define sqlite3VtabCommit(X)
|
||||
#else
|
||||
void sqlite3VtabClear(Table*);
|
||||
void sqlite3VtabCodeLock(Parse *pParse, Table *pTab);
|
||||
int sqlite3VtabSync(sqlite3 *db, int rc);
|
||||
int sqlite3VtabRollback(sqlite3 *db);
|
||||
int sqlite3VtabCommit(sqlite3 *db);
|
||||
|
|
57
src/test8.c
57
src/test8.c
|
@ -13,7 +13,7 @@
|
|||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test8.c,v 1.31 2006/06/22 09:53:50 danielk1977 Exp $
|
||||
** $Id: test8.c,v 1.32 2006/06/23 08:05:26 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
|
@ -72,7 +72,7 @@ static int getColumnNames(
|
|||
char zBuf[1024];
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int rc = SQLITE_OK;
|
||||
int nCol;
|
||||
int nCol = 0;
|
||||
|
||||
sprintf(zBuf, "SELECT * FROM %s", zTab);
|
||||
rc = sqlite3_prepare(db, zBuf, -1, &pStmt, 0);
|
||||
|
@ -143,14 +143,18 @@ static int getIndexArray(sqlite3 *db, const char *zTab, int **paIndex){
|
|||
assert( cid>=0 && cid<nCol );
|
||||
aIndex[cid] = 1;
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt2);
|
||||
if( pStmt2 ){
|
||||
rc = sqlite3_finalize(pStmt2);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_finalize(pStmt);
|
||||
goto get_index_array_out;
|
||||
}
|
||||
}
|
||||
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( pStmt ){
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
get_index_array_out:
|
||||
if( rc!=SQLITE_OK ){
|
||||
|
@ -206,10 +210,14 @@ static int echoDeclareVtab(
|
|||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
sqlite3_declare_vtab(db, zCreateTable);
|
||||
#endif
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
} else {
|
||||
rc = SQLITE_ERROR;
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = getIndexArray(db, argv[3], &pVtab->aIndex);
|
||||
}
|
||||
|
@ -244,9 +252,16 @@ static int echoConstructor(
|
|||
echo_vtab *pVtab;
|
||||
|
||||
pVtab = sqliteMalloc( sizeof(*pVtab) );
|
||||
if( !pVtab ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pVtab->interp = (Tcl_Interp *)pAux;
|
||||
pVtab->db = db;
|
||||
pVtab->zTableName = sqlite3MPrintf("%s", argv[3]);
|
||||
if( !pVtab->zTableName ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
for(i=0; i<argc; i++){
|
||||
appendToEchoModule(pVtab->interp, argv[i]);
|
||||
}
|
||||
|
@ -318,14 +333,17 @@ static int echoOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
|||
echo_cursor *pCur;
|
||||
pCur = sqliteMalloc(sizeof(echo_cursor));
|
||||
*ppCursor = (sqlite3_vtab_cursor *)pCur;
|
||||
return SQLITE_OK;
|
||||
return (pCur ? SQLITE_OK : SQLITE_NOMEM);
|
||||
}
|
||||
|
||||
static int echoClose(sqlite3_vtab_cursor *cur){
|
||||
int rc;
|
||||
echo_cursor *pCur = (echo_cursor *)cur;
|
||||
sqlite3_finalize(pCur->pStmt);
|
||||
sqlite3_stmt *pStmt = pCur->pStmt;
|
||||
pCur->pStmt = 0;
|
||||
sqliteFree(pCur);
|
||||
return SQLITE_OK;
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -339,7 +357,7 @@ static int echoEof(sqlite3_vtab_cursor *cur){
|
|||
static int echoNext(sqlite3_vtab_cursor *cur){
|
||||
int rc;
|
||||
echo_cursor *pCur = (echo_cursor *)cur;
|
||||
|
||||
sqlite3_stmt *pStmt = pCur->pStmt;
|
||||
rc = sqlite3_step(pCur->pStmt);
|
||||
|
||||
if( rc==SQLITE_ROW ){
|
||||
|
@ -398,13 +416,18 @@ static int echoFilter(
|
|||
int argc, sqlite3_value **argv
|
||||
){
|
||||
int rc;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
echo_cursor *pCur = (echo_cursor *)pVtabCursor;
|
||||
echo_vtab *pVtab = (echo_vtab *)pVtabCursor->pVtab;
|
||||
sqlite3 *db = pVtab->db;
|
||||
|
||||
appendToEchoModule(pVtab->interp, "xFilter");
|
||||
appendToEchoModule(pVtab->interp, idxStr);
|
||||
for(i=0; i<argc; i++){
|
||||
appendToEchoModule(pVtab->interp, sqlite3_value_text(argv[i]));
|
||||
}
|
||||
|
||||
assert( idxNum==hashString(idxStr) );
|
||||
sqlite3_finalize(pCur->pStmt);
|
||||
pCur->pStmt = 0;
|
||||
|
@ -437,20 +460,12 @@ static int echoFilter(
|
|||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
ret = echoNext(pVtabCursor);
|
||||
rc = echoNext(pVtabCursor);
|
||||
}else{
|
||||
assert( !pCur->pStmt );
|
||||
ret = 0;
|
||||
pCur->errcode = rc;
|
||||
}
|
||||
|
||||
appendToEchoModule(pVtab->interp, "xFilter");
|
||||
appendToEchoModule(pVtab->interp, idxStr);
|
||||
for(i=0; i<argc; i++){
|
||||
appendToEchoModule(pVtab->interp, sqlite3_value_text(argv[i]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
15
src/vdbe.c
15
src/vdbe.c
|
@ -43,7 +43,7 @@
|
|||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.565 2006/06/22 09:53:50 danielk1977 Exp $
|
||||
** $Id: vdbe.c,v 1.566 2006/06/23 08:05:26 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
@ -180,7 +180,7 @@ static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){
|
|||
Cursor *pCx;
|
||||
assert( iCur<p->nCursor );
|
||||
if( p->apCsr[iCur] ){
|
||||
sqlite3VdbeFreeCursor(p->apCsr[iCur]);
|
||||
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
|
||||
}
|
||||
p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) );
|
||||
if( pCx ){
|
||||
|
@ -2733,7 +2733,7 @@ case OP_OpenPseudo: { /* no-push */
|
|||
case OP_Close: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
if( i>=0 && i<p->nCursor ){
|
||||
sqlite3VdbeFreeCursor(p->apCsr[i]);
|
||||
sqlite3VdbeFreeCursor(p, p->apCsr[i]);
|
||||
p->apCsr[i] = 0;
|
||||
}
|
||||
break;
|
||||
|
@ -4597,7 +4597,10 @@ case OP_VOpen: { /* no-push */
|
|||
|
||||
/* Initialise vdbe cursor object */
|
||||
pCur = allocateCursor(p, pOp->p1, -1);
|
||||
pCur->pVtabCursor = pVtabCursor;
|
||||
if( pCur ){
|
||||
pCur->pVtabCursor = pVtabCursor;
|
||||
pCur->pModule = pVtabCursor->pVtab->pModule;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -4651,7 +4654,9 @@ case OP_VFilter: { /* no-push */
|
|||
}
|
||||
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
p->inVtabMethod = 1;
|
||||
rc = pModule->xFilter(pCur->pVtabCursor, pTos->i, pOp->p3, nArg, apArg);
|
||||
p->inVtabMethod = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
res = pModule->xEof(pCur->pVtabCursor);
|
||||
}
|
||||
|
@ -4762,7 +4767,9 @@ case OP_VNext: { /* no-push */
|
|||
** some other method is next invoked on the save virtual table cursor.
|
||||
*/
|
||||
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
|
||||
p->inVtabMethod = 1;
|
||||
rc = pModule->xNext(pCur->pVtabCursor);
|
||||
p->inVtabMethod = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
res = pModule->xEof(pCur->pVtabCursor);
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ struct Cursor {
|
|||
i64 seqCount; /* Sequence counter */
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
|
||||
sqlite3_module *pModule; /* Module for cursor pVtabCursor */
|
||||
#endif
|
||||
|
||||
/* Cached information about the header for the data record that the
|
||||
|
@ -324,6 +325,9 @@ struct Vdbe {
|
|||
int fetchId; /* Statement number used by sqlite3_fetch_statement */
|
||||
int lru; /* Counter used for LRU cache replacement */
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
int inVtabMethod;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -337,7 +341,7 @@ struct Vdbe {
|
|||
/*
|
||||
** Function prototypes
|
||||
*/
|
||||
void sqlite3VdbeFreeCursor(Cursor*);
|
||||
void sqlite3VdbeFreeCursor(Vdbe *, Cursor*);
|
||||
void sqliteVdbePopStack(Vdbe*,int);
|
||||
int sqlite3VdbeCursorMoveto(Cursor*);
|
||||
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
||||
|
|
|
@ -841,7 +841,7 @@ void sqlite3VdbeMakeReady(
|
|||
** Close a cursor and release all the resources that cursor happens
|
||||
** to hold.
|
||||
*/
|
||||
void sqlite3VdbeFreeCursor(Cursor *pCx){
|
||||
void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
|
||||
if( pCx==0 ){
|
||||
return;
|
||||
}
|
||||
|
@ -855,8 +855,10 @@ void sqlite3VdbeFreeCursor(Cursor *pCx){
|
|||
if( pCx->pVtabCursor ){
|
||||
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
|
||||
sqlite3_vtab *pVtab = pVtabCursor->pVtab;
|
||||
const sqlite3_module *pModule = pVtab->pModule;
|
||||
const sqlite3_module *pModule = pCx->pModule;
|
||||
p->inVtabMethod = 1;
|
||||
pModule->xClose(pVtabCursor);
|
||||
p->inVtabMethod = 0;
|
||||
}
|
||||
#endif
|
||||
sqliteFree(pCx->pData);
|
||||
|
@ -871,7 +873,9 @@ static void closeAllCursors(Vdbe *p){
|
|||
int i;
|
||||
if( p->apCsr==0 ) return;
|
||||
for(i=0; i<p->nCursor; i++){
|
||||
sqlite3VdbeFreeCursor(p->apCsr[i]);
|
||||
if( !p->inVtabMethod || (p->apCsr[i] && !p->apCsr[i]->pVtabCursor) ){
|
||||
sqlite3VdbeFreeCursor(p, p->apCsr[i]);
|
||||
}
|
||||
p->apCsr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1149,23 +1153,6 @@ static int vdbeCommit(sqlite3 *db){
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Find every active VM other than pVdbe and change its status to
|
||||
** aborted. This happens when one VM causes a rollback due to an
|
||||
** ON CONFLICT ROLLBACK clause (for example). The other VMs must be
|
||||
** aborted so that they do not have data rolled out from underneath
|
||||
** them leading to a segfault.
|
||||
*/
|
||||
void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
|
||||
Vdbe *pOther;
|
||||
for(pOther=db->pVdbe; pOther; pOther=pOther->pNext){
|
||||
if( pOther==pExcept ) continue;
|
||||
if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;
|
||||
closeAllCursors(pOther);
|
||||
pOther->aborted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine checks that the sqlite3.activeVdbeCnt count variable
|
||||
** matches the number of vdbe's in the list sqlite3.pVdbe that are
|
||||
|
@ -1192,6 +1179,25 @@ static void checkActiveVdbeCnt(sqlite3 *db){
|
|||
#define checkActiveVdbeCnt(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Find every active VM other than pVdbe and change its status to
|
||||
** aborted. This happens when one VM causes a rollback due to an
|
||||
** ON CONFLICT ROLLBACK clause (for example). The other VMs must be
|
||||
** aborted so that they do not have data rolled out from underneath
|
||||
** them leading to a segfault.
|
||||
*/
|
||||
void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
|
||||
Vdbe *pOther;
|
||||
for(pOther=db->pVdbe; pOther; pOther=pOther->pNext){
|
||||
if( pOther==pExcept ) continue;
|
||||
if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;
|
||||
checkActiveVdbeCnt(db);
|
||||
closeAllCursors(pOther);
|
||||
checkActiveVdbeCnt(db);
|
||||
pOther->aborted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called the when a VDBE tries to halt. If the VDBE
|
||||
** has made changes and is in autocommit mode, then commit those
|
||||
|
@ -1375,8 +1381,7 @@ int sqlite3VdbeHalt(Vdbe *p){
|
|||
}
|
||||
}
|
||||
|
||||
/* We have successfully halted and closed the VM. Record this fact. */
|
||||
if( p->pc>=0 ){
|
||||
if( p->pc>=0 ){
|
||||
db->activeVdbeCnt--;
|
||||
}
|
||||
p->magic = VDBE_MAGIC_HALT;
|
||||
|
|
39
src/vtab.c
39
src/vtab.c
|
@ -11,7 +11,7 @@
|
|||
*************************************************************************
|
||||
** This file contains code used to help implement virtual tables.
|
||||
**
|
||||
** $Id: vtab.c,v 1.20 2006/06/21 16:02:43 danielk1977 Exp $
|
||||
** $Id: vtab.c,v 1.21 2006/06/23 08:05:30 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
#include "sqliteInt.h"
|
||||
|
@ -46,9 +46,14 @@ int sqlite3_create_module(
|
|||
** record.
|
||||
*/
|
||||
void sqlite3VtabClear(Table *p){
|
||||
if( p->pVtab ){
|
||||
sqlite3_vtab *pVtab = p->pVtab;
|
||||
if( pVtab ){
|
||||
assert( p->pMod && p->pMod->pModule );
|
||||
p->pMod->pModule->xDisconnect(p->pVtab);
|
||||
pVtab->nRef--;
|
||||
if( pVtab->nRef==0 ){
|
||||
pVtab->pModule->xDisconnect(pVtab);
|
||||
}
|
||||
p->pVtab = 0;
|
||||
}
|
||||
if( p->azModuleArg ){
|
||||
int i;
|
||||
|
@ -91,7 +96,6 @@ void sqlite3VtabBeginParse(
|
|||
){
|
||||
int iDb; /* The database the table is being created in */
|
||||
Table *pTable; /* The new virtual table */
|
||||
Token *pDummy; /* Dummy arg for sqlite3TwoPartName() */
|
||||
|
||||
sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
|
||||
pTable = pParse->pNewTable;
|
||||
|
@ -114,10 +118,9 @@ void sqlite3VtabBeginParse(
|
|||
** sqlite_master table, has already been made by sqlite3StartTable().
|
||||
** The second call, to obtain permission to create the table, is made now.
|
||||
*/
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
|
||||
pTable->azModuleArg[0], pParse->db->aDb[iDb].zName)
|
||||
){
|
||||
return;
|
||||
if( pTable->azModuleArg ){
|
||||
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
|
||||
pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -272,6 +275,7 @@ static int vtabCallConstructor(
|
|||
int rc2;
|
||||
char **azArg = pTab->azModuleArg;
|
||||
int nArg = pTab->nModuleArg;
|
||||
char *zErr = sqlite3MPrintf("vtable constructor failed: %s", pTab->zName);
|
||||
|
||||
assert( !db->pVTab );
|
||||
assert( xConstruct );
|
||||
|
@ -281,12 +285,14 @@ static int vtabCallConstructor(
|
|||
assert( rc==SQLITE_OK );
|
||||
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab);
|
||||
rc2 = sqlite3SafetyOn(db);
|
||||
if( pTab->pVtab ){
|
||||
if( rc==SQLITE_OK && pTab->pVtab ){
|
||||
pTab->pVtab->pModule = pMod->pModule;
|
||||
pTab->pVtab->nRef = 1;
|
||||
}
|
||||
|
||||
if( SQLITE_OK!=rc ){
|
||||
*pzErr = sqlite3MPrintf("vtable constructor failed: %s", pTab->zName);
|
||||
*pzErr = zErr;
|
||||
zErr = 0;
|
||||
} else if( db->pVTab ){
|
||||
const char *zFormat = "vtable constructor did not declare schema: %s";
|
||||
*pzErr = sqlite3MPrintf(zFormat, pTab->zName);
|
||||
|
@ -296,6 +302,7 @@ static int vtabCallConstructor(
|
|||
rc = rc2;
|
||||
}
|
||||
db->pVTab = 0;
|
||||
sqliteFree(zErr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -337,7 +344,7 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
|
|||
/*
|
||||
** Add the virtual table pVtab to the array sqlite3.aVTrans[].
|
||||
*/
|
||||
int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){
|
||||
static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){
|
||||
const int ARRAY_INCR = 5;
|
||||
|
||||
/* Grow the sqlite3.aVTrans array if required */
|
||||
|
@ -354,6 +361,7 @@ int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){
|
|||
|
||||
/* Add pVtab to the end of sqlite3.aVTrans */
|
||||
db->aVTrans[db->nVTrans++] = pVtab;
|
||||
pVtab->nRef++;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -471,11 +479,6 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab)
|
|||
return rc;
|
||||
}
|
||||
|
||||
void sqlite3VtabCodeLock(Parse *pParse, Table *pTab){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
sqlite3VdbeOp3(v, OP_VBegin, 0, 0, (const char*)pTab->pVtab, P3_VTAB);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function invokes either the xRollback or xCommit method
|
||||
** of each of the virtual tables in the sqlite3.aVTrans array. The method
|
||||
|
@ -491,6 +494,10 @@ static void callFinaliser(sqlite3 *db, int offset){
|
|||
int (*x)(sqlite3_vtab *);
|
||||
x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
|
||||
if( x ) x(pVtab);
|
||||
pVtab->nRef--;
|
||||
if( pVtab->nRef==0 ){
|
||||
pVtab->pModule->xDisconnect(pVtab);
|
||||
}
|
||||
}
|
||||
sqliteFree(db->aVTrans);
|
||||
db->nVTrans = 0;
|
||||
|
|
14
src/where.c
14
src/where.c
|
@ -16,7 +16,7 @@
|
|||
** so is applicable. Because this module is responsible for selecting
|
||||
** indices, you might also think of this module as the "query optimizer".
|
||||
**
|
||||
** $Id: where.c,v 1.221 2006/06/20 13:07:28 danielk1977 Exp $
|
||||
** $Id: where.c,v 1.222 2006/06/23 08:05:31 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
@ -1125,10 +1125,16 @@ static double bestVirtualIndex(
|
|||
}
|
||||
|
||||
sqlite3SafetyOff(pParse->db);
|
||||
pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);
|
||||
rc = sqlite3SafetyOn(pParse->db);
|
||||
rc = pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
sqlite3FailedMalloc();
|
||||
}else {
|
||||
sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
|
||||
}
|
||||
sqlite3SafetyOn(pParse->db);
|
||||
}else{
|
||||
rc = sqlite3SafetyOn(pParse->db);
|
||||
}
|
||||
|
||||
*(int*)&pIdxInfo->nOrderBy = nOrderBy;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#***********************************************************************
|
||||
# This file runs all tests.
|
||||
#
|
||||
# $Id: quick.test,v 1.44 2006/06/14 10:38:03 danielk1977 Exp $
|
||||
# $Id: quick.test,v 1.45 2006/06/23 08:05:38 danielk1977 Exp $
|
||||
|
||||
proc lshift {lvar} {
|
||||
upvar $lvar l
|
||||
|
@ -55,6 +55,7 @@ set EXCLUDE {
|
|||
btree8.test
|
||||
utf16.test
|
||||
shared_err.test
|
||||
vtab_err.test
|
||||
}
|
||||
|
||||
if {[sqlite3 -has-codec]} {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# This file implements some common TCL routines used for regression
|
||||
# testing the SQLite library
|
||||
#
|
||||
# $Id: tester.tcl,v 1.64 2006/01/24 13:09:33 danielk1977 Exp $
|
||||
# $Id: tester.tcl,v 1.65 2006/06/23 08:05:38 danielk1977 Exp $
|
||||
|
||||
# Make sure tclsqlite3 was compiled correctly. Abort now with an
|
||||
# error message if not.
|
||||
|
@ -149,6 +149,7 @@ proc finalize_testing {} {
|
|||
catch {
|
||||
pp_check_for_leaks
|
||||
}
|
||||
breakpoint
|
||||
sqlite3 db {}
|
||||
# sqlite3_clear_tsd_memdebug
|
||||
db close
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# $Id: vtab_err.test,v 1.1 2006/06/22 09:53:50 danielk1977 Exp $
|
||||
# $Id: vtab_err.test,v 1.2 2006/06/23 08:05:39 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
@ -19,6 +19,107 @@ ifcapable !vtab {
|
|||
return
|
||||
}
|
||||
|
||||
# Usage: do_malloc_test <test number> <options...>
|
||||
#
|
||||
# The first argument, <test number>, is an integer used to name the
|
||||
# tests executed by this proc. Options are as follows:
|
||||
#
|
||||
# -tclprep TCL script to run to prepare test.
|
||||
# -sqlprep SQL script to run to prepare test.
|
||||
# -tclbody TCL script to run with malloc failure simulation.
|
||||
# -sqlbody TCL script to run with malloc failure simulation.
|
||||
# -cleanup TCL script to run after the test.
|
||||
#
|
||||
# This command runs a series of tests to verify SQLite's ability
|
||||
# to handle an out-of-memory condition gracefully. It is assumed
|
||||
# that if this condition occurs a malloc() call will return a
|
||||
# NULL pointer. Linux, for example, doesn't do that by default. See
|
||||
# the "BUGS" section of malloc(3).
|
||||
#
|
||||
# Each iteration of a loop, the TCL commands in any argument passed
|
||||
# to the -tclbody switch, followed by the SQL commands in any argument
|
||||
# passed to the -sqlbody switch are executed. Each iteration the
|
||||
# Nth call to sqliteMalloc() is made to fail, where N is increased
|
||||
# each time the loop runs starting from 1. When all commands execute
|
||||
# successfully, the loop ends.
|
||||
#
|
||||
proc do_malloc_test {tn args} {
|
||||
array unset ::mallocopts
|
||||
array set ::mallocopts $args
|
||||
|
||||
set ::go 1
|
||||
for {set ::n 1} {$::go && $::n < 50000} {incr ::n} {
|
||||
do_test $tn.$::n {
|
||||
|
||||
# Remove all traces of database files test.db and test2.db from the files
|
||||
# system. Then open (empty database) "test.db" with the handle [db].
|
||||
#
|
||||
sqlite_malloc_fail 0
|
||||
catch {db close}
|
||||
catch {file delete -force test.db}
|
||||
catch {file delete -force test.db-journal}
|
||||
catch {file delete -force test2.db}
|
||||
catch {file delete -force test2.db-journal}
|
||||
catch {sqlite3 db test.db}
|
||||
set ::DB [sqlite3_connection_pointer db]
|
||||
|
||||
# Execute any -tclprep and -sqlprep scripts.
|
||||
#
|
||||
if {[info exists ::mallocopts(-tclprep)]} {
|
||||
eval $::mallocopts(-tclprep)
|
||||
}
|
||||
if {[info exists ::mallocopts(-sqlprep)]} {
|
||||
execsql $::mallocopts(-sqlprep)
|
||||
}
|
||||
|
||||
# Now set the ${::n}th malloc() to fail and execute the -tclbody and
|
||||
# -sqlbody scripts.
|
||||
#
|
||||
sqlite_malloc_fail $::n
|
||||
set ::mallocbody {}
|
||||
if {[info exists ::mallocopts(-tclbody)]} {
|
||||
append ::mallocbody "$::mallocopts(-tclbody)\n"
|
||||
}
|
||||
if {[info exists ::mallocopts(-sqlbody)]} {
|
||||
append ::mallocbody "db eval {$::mallocopts(-sqlbody)}"
|
||||
}
|
||||
set v [catch $::mallocbody msg]
|
||||
|
||||
# If the test fails (if $v!=0) and the database connection actually
|
||||
# exists, make sure the failure code is SQLITE_NOMEM.
|
||||
if {$v&&[info command db]=="db"&&[info exists ::mallocopts(-sqlbody)]} {
|
||||
if {[db errorcode]!=7 && $msg!="vtable constructor failed: e"} {
|
||||
set v 999
|
||||
}
|
||||
}
|
||||
|
||||
set leftover [lindex [sqlite_malloc_stat] 2]
|
||||
if {$leftover>0} {
|
||||
if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"}
|
||||
set ::go 0
|
||||
if {$v} {
|
||||
puts "\nError message returned: $msg"
|
||||
} else {
|
||||
set v {1 1}
|
||||
}
|
||||
} else {
|
||||
set v2 [expr {
|
||||
$msg == "" || $msg == "out of memory" ||
|
||||
$msg == "vtable constructor failed: e"
|
||||
}]
|
||||
if {!$v2} {puts "\nError message returned: $msg"}
|
||||
lappend v $v2
|
||||
}
|
||||
} {1 1}
|
||||
|
||||
if {[info exists ::mallocopts(-cleanup)]} {
|
||||
catch [list uplevel #0 $::mallocopts(-cleanup)] msg
|
||||
}
|
||||
}
|
||||
unset ::mallocopts
|
||||
}
|
||||
|
||||
|
||||
do_ioerr_test vtab_err-1 -tclprep {
|
||||
register_echo_module [sqlite3_connection_pointer db]
|
||||
} -sqlbody {
|
||||
|
@ -38,5 +139,24 @@ do_ioerr_test vtab_err-1 -tclprep {
|
|||
}
|
||||
|
||||
|
||||
do_malloc_test vtab_err-2 -tclprep {
|
||||
register_echo_module [sqlite3_connection_pointer db]
|
||||
} -sqlbody {
|
||||
BEGIN;
|
||||
CREATE TABLE r(a PRIMARY KEY, b, c);
|
||||
CREATE VIRTUAL TABLE e USING echo(r);
|
||||
INSERT INTO e VALUES(1, 2, 3);
|
||||
INSERT INTO e VALUES('a', 'b', 'c');
|
||||
UPDATE e SET c = 10;
|
||||
DELETE FROM e WHERE a = 'a';
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
CREATE TABLE r2(a, b, c);
|
||||
INSERT INTO r2 SELECT * FROM e;
|
||||
INSERT INTO e SELECT a||'x', b, c FROM r2;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
sqlite_malloc_fail 0
|
||||
finish_test
|
||||
|
||||
|
|
Loading…
Reference in New Issue