-C Update\smailing\slist\shyperlink\son\sthe\ssupport\spage.\s(CVS\s2799)
-D 2005-12-05T22:22:40
+C Some\selements\sof\sthe\snew\smalloc()\sfailure\shandling.\sNot\sall\scases\swork\sproperly\syet.\sAlso,\slibrary\sis\snot\sthreadsafe\sif\smalloc()\sfails\sright\snow.\s(CVS\s2800)
+D 2005-12-06T12:52:59
F Makefile.in e3c6b3a38d734d41574c04f2fc90d18de2b87102
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.def c413e514217736884254739a105c8c942fdf0c2f
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
-F src/alter.c 149e871e1ad6648da9b72e69feb1bd1407bf5226
+F src/alter.c 7ed4b794c2e3a8ad8c1effe50202eaef42cedc23
F src/analyze.c ea42005eed52c382fcc7ef66969e7f1858597633
-F src/attach.c 4b21689700a72ae281fa85dbaff06b2a62bd49ee
+F src/attach.c 8c3e09452be967e005a016299a110ed8ee33606a
F src/auth.c 31e2304bef67f44d635655f44234387ea7d21454
F src/btree.c aa88194f460becf8fff6196996d6e38f1b37286e
F src/btree.h 1ed561263ca0e335bc3e81d761c9d5ff8c22f61e
-F src/build.c 8c93ae10563e8b92d3d7ea532a606424be3cb4f7
-F src/callback.c 90ab4f235a2603c4cb8e6a2497091a71fb732bfa
+F src/build.c 41350367dc5837b0dafa83cbd5bf08f0108031b0
+F src/callback.c 4bc404e9912eecb28be1235581833f6269920c27
F src/complete.c 4de937dfdd4c79a501772ab2035b26082f337a79
F src/date.c 8bc8d084a17d19c44d9cbf357b5f656db6706ce1
-F src/delete.c 29dac493f4d83b05f91233b116827c133bcdab72
+F src/delete.c 6010a081edda9871895260def092e852f0bb60a0
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
-F src/expr.c 80ceb8c7d15dd53985831f0b4c660b3c3df796a3
+F src/expr.c 540ed7eb44b79e5603c3656466bf1d7381abcfc7
F src/func.c 7d81dccd9c440c6c4e761056333e629192814af0
F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
-F src/insert.c da031c3ed8e1675fac891990095d277c2ba6e205
-F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
-F src/main.c 7d719efe04b760c5e0faa9e910c6d4f00f85f2f3
+F src/insert.c 5393479164f317ea0aeec954c6500cafa097ef33
+F src/legacy.c 7b88d20efc8e6c208f262d97aee9c8e2cf02bc91
+F src/main.c 2babbdbc5f0ad8a4dc9152b27ba3436b55572a2d
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
F src/os.c bdd3a2fd089777e7ad18b57c896f1141d5a0c1fd
F src/os.h d5ae3f4c1c7731437b6cddec279b7c06f761c44e
F src/os_common.h d74a11728ad2444b6b695b94c28c06881f049e49
F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c
F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3
-F src/os_unix.c 1a7278bf7ad95f8c62a946d6b1726a539ab5e790
+F src/os_unix.c 76189e4cb5e1ad451293ce1aeb348c3b829e7e13
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
F src/os_win.c d962ac2dd0e482847e42b846d46cd044f97d1c32
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c bcb54653c3020d7cde88b4e8bad81ff6f93402b4
+F src/pager.c 893cb2106261a4f77d84c1fa0d10a083e889b23b
F src/pager.h e7b41ce8e7b5f629d456708b7ad9a8c8ede37140
F src/parse.y e4d57c2fd5cc02f19822ec41f6dc2bfc9bc85609
F src/pragma.c 2793699ab0d73fa730fa8c1c7521e9436604f024
-F src/prepare.c fc098db25d2a121affb08686cf04833fd50452d4
+F src/prepare.c e93967011379051316728d316755f533a9bb438c
F src/printf.c 3ea3a17d25d7ac498efc18007c70371a42c968f8
F src/random.c ff5e9a8cad790e2a51cd4d2e7737dc8540e09d1d
-F src/select.c 4a9e5366f4a16bd2e6e93c05f585633887be6372
+F src/select.c 0e4d3627fec4a445b45f6cb471f68aab9c97a8b3
F src/shell.c 3596c1e559b82663057940d19ba533ad421c7dd3
F src/sqlite.h.in 8e648e1f386e4509f2f96c09ded7c07b0df0c9a2
-F src/sqliteInt.h 4148c9778e350014c2e27b332d7a2ef7278fe62e
+F src/sqliteInt.h 71dc0f753e9a646d9c9b3b6b5bb9d2fcc2dad9e5
F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316
F src/tclsqlite.c a497c3adfd2c85da6a934331ec0041e47884fbcb
-F src/test1.c 3d1803af3232fbe29c1902735a7eadd5b4598ffe
+F src/test1.c 0b4bf8ab9afb37f34a83c46f81de54adf519b23d
F src/test2.c 36390cdfc70c08e5ee0b466d0654a117f398bbff
F src/test3.c f4e6a16a602091696619a1171bda25c0e3df49f7
F src/test4.c a8fd681e139e1c61f22a77d07fc3a99cb28fff3f
F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5
F src/test6.c cb811391ec0b7c75f29e545d4820a9cf19f3637e
-F src/tokenize.c bdb79702217af49eba44c2a3b4f5fc7bd9ed2917
-F src/trigger.c aea0283a3ef729a3e9c8dc5dc1a11c9fcc0a12a7
-F src/update.c fec7665138ccf2a2133f11dcd24c1134c6b33526
+F src/tokenize.c a189d7466524076220f41a21baed05e1639a82f4
+F src/trigger.c 388c13a2f07584decdb88413a63017391f9a7f7a
+F src/update.c ec8e540617b116725b5a55c8d6b4db8bc67fdd7d
F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
-F src/util.c 48fecbbef4391d102a23096d32f0d74173428406
-F src/vacuum.c c9fe2660919bd1595a7fbdeddadc16c7d9723400
-F src/vdbe.c 91b91272446d0a62b2d27d330d6a1a622acfb0fb
+F src/util.c 88ebafb5708f04002e58a373386e3c8c31bfd858
+F src/vacuum.c b99062005217f72568c4023390e0331e1b4568b3
+F src/vdbe.c 7f4a2affee140b7b57952ab2c081a9c22b950638
F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13
F src/vdbeInt.h 0055c37eccbf3a189fd893a90f8eb6a5fa60c871
-F src/vdbeapi.c 73d56a8899d46cf0353e32a85aa1ff7f36cb24ea
-F src/vdbeaux.c 0c4af4af29d42a7f008c7562afee58b470dd6d4a
+F src/vdbeapi.c 4fd33e87aa6cbd77e59da142e1df67ec0430225f
+F src/vdbeaux.c 90143aaffbe232a700fd05e4b2e7428d512b605b
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
F src/vdbemem.c cd9609c1e7f71ec76d9840c84c3a57ebfa6539cf
-F src/where.c a9fed5a5b549f5dae1aa95dc9463cd1f35efa0f1
+F src/where.c c0882f2d42e636f78fb45b9279e2739d4291e6ab
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
F test/alter.test 9d6837a3d946b73df692b7cef2a7644d2e2f6bc6
F test/lock2.test d83ba79d3c4fffdb5b926c7d8ca7a36c34288a55
F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9
F test/main.test b12f01d49a5c805a33fa6c0ef168691f63056e79
-F test/malloc.test 666c77a878ce50f5c22b9211ed43e889cabb63a6
-F test/malloc2.test 655b972372d2754a3f6c6ed54d7cfd18fde9bd32
+F test/malloc.test a5ed721cf7d1b12602ede4f98c11b65ab1582cc0
+F test/malloc2.test e6e321db96d6c94cb18bf82ad7215070c41e624e
F test/manydb.test d81debbf5871242e3b5df1d3bb5e14c50431b6f8
F test/memdb.test 1860e060be810bf0775bc57408a5b7c4954bcaea
F test/memleak.test df2b2b96e77f8ba159a332299535b1e5f18e49ac
F test/rollback.test 94cd981ee3a627d9f6466f69dcf1f7dbfe695d7a
F test/rowid.test 040a3bef06f970c45f5fcd14b2355f7f4d62f0cf
F test/safety.test 907b64fee719554a3622853812af3886fddbbb4f
-F test/schema.test 21cbe7dac652f6d7eb058f3dec369bdbf46bbde6
+F test/schema.test 8a2ae440fb15f5798a68059e8746402f3137be46
F test/select1.test 480233d4f5a81d7d59a55e40d05084d97e57ecdf
F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3
F test/select3.test 8fece41cd8f2955131b3f973a7123bec60b6e65e
F tool/lempar.c 424df14a48736bb961ed47acf30c26d66ed85a62
F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
-F tool/memleak3.tcl 009da0ea82dc5893edca76cf1a21fb7260e9412e
+F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf
F tool/mkkeywordhash.c 5263a654e5c9fd8d6e3238fb39c2d5c3126be32f
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 9d6057cd141e7cdaf32ce68dea39e67c2c67a08d
-R dd2af97c916f976a63f6fe8ff108d90a
-U drh
-Z d032ae7a997d740a148585b12b585af9
+P 41a7aeeeb427d59e3d7cc71c94a8c5be832bd0fa
+R ce02aa0c65608cead49ff0e73829ca6c
+U danielk1977
+Z 3b6d26a30c726439418b3a6a9650fe3d
-41a7aeeeb427d59e3d7cc71c94a8c5be832bd0fa
\ No newline at end of file
+e1606658f1b4530e3001db4779b5669c8d13c853
\ No newline at end of file
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
**
-** $Id: alter.c,v 1.9 2005/10/20 07:28:18 drh Exp $
+** $Id: alter.c,v 1.10 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
char *zWhere = 0; /* Where clause to locate temp triggers */
#endif
- if( sqlite3_malloc_failed ) goto exit_rename_table;
+ if( sqlite3Tsd()->mallocFailed ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
/* Look up the table being altered. */
assert( pParse->pNewTable==0 );
- if( sqlite3_malloc_failed ) goto exit_begin_add_column;
+ if( sqlite3Tsd()->mallocFailed ) goto exit_begin_add_column;
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
if( !pTab ) goto exit_begin_add_column;
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
-** $Id: attach.c,v 1.34 2005/08/20 03:03:04 drh Exp $
+** $Id: attach.c,v 1.35 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
if( pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
}
+ db->nDb = i;
}
attach_end:
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.355 2005/11/14 22:29:05 drh Exp $
+** $Id: build.c,v 1.356 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
sqlite3 *db;
Vdbe *v;
- if( sqlite3_malloc_failed ) return;
+ if( sqlite3Tsd()->mallocFailed ) return;
if( pParse->nested ) return;
if( !pParse->pVdbe ){
if( pParse->rc==SQLITE_OK && pParse->nErr ){
Table *p;
sqlite3 *db = pParse->db;
- if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3_malloc_failed ) return;
+ if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3Tsd()->mallocFailed ) {
+ return;
+ }
p = pParse->pNewTable;
if( p==0 ) return;
*/
p->pSelect = sqlite3SelectDup(pSelect);
sqlite3SelectDelete(pSelect);
+ if( sqlite3Tsd()->mallocFailed ){
+ return;
+ }
if( !pParse->db->init.busy ){
sqlite3ViewGetColumnNames(pParse, p);
}
*/
assert( pTable->pSelect );
pSel = sqlite3SelectDup(pTable->pSelect);
- n = pParse->nTab;
- sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
- pTable->nCol = -1;
- pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
- pParse->nTab = n;
- if( pSelTab ){
- assert( pTable->aCol==0 );
- pTable->nCol = pSelTab->nCol;
- pTable->aCol = pSelTab->aCol;
- pSelTab->nCol = 0;
- pSelTab->aCol = 0;
- sqlite3DeleteTable(0, pSelTab);
- DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews);
- }else{
- pTable->nCol = 0;
+ if( pSel ){
+ n = pParse->nTab;
+ sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
+ pTable->nCol = -1;
+ pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
+ pParse->nTab = n;
+ if( pSelTab ){
+ assert( pTable->aCol==0 );
+ pTable->nCol = pSelTab->nCol;
+ pTable->aCol = pSelTab->aCol;
+ pSelTab->nCol = 0;
+ pSelTab->aCol = 0;
+ sqlite3DeleteTable(0, pSelTab);
+ DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews);
+ }else{
+ pTable->nCol = 0;
+ nErr++;
+ }
+ sqlite3SelectDelete(pSel);
+ } else {
nErr++;
}
- sqlite3SelectDelete(pSel);
return nErr;
}
#endif /* SQLITE_OMIT_VIEW */
sqlite3 *db = pParse->db;
int iDb;
- if( pParse->nErr || sqlite3_malloc_failed ) goto exit_drop_table;
+ if( pParse->nErr || sqlite3Tsd()->mallocFailed ) goto exit_drop_table;
assert( pName->nSrc==1 );
pTab = sqlite3LocateTable(pParse, pName->a[0].zName, pName->a[0].zDatabase);
int iDb; /* Index of the database that is being written */
Token *pName = 0; /* Unqualified name of the index to create */
- if( pParse->nErr || sqlite3_malloc_failed ) goto exit_create_index;
+ if( pParse->nErr || sqlite3Tsd()->mallocFailed ) goto exit_create_index;
/*
** Find the table that is to be indexed. Return early if not found.
*/
pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + sizeof(int) +
(sizeof(int)*2 + sizeof(CollSeq*))*pList->nExpr );
- if( sqlite3_malloc_failed ) goto exit_create_index;
+ if( sqlite3Tsd()->mallocFailed ) goto exit_create_index;
pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nExpr];
pIndex->aiRowEst = (unsigned*)&pIndex->aiColumn[pList->nExpr];
pIndex->zName = (char*)&pIndex->aiRowEst[pList->nExpr+1];
Vdbe *v;
sqlite3 *db = pParse->db;
- if( pParse->nErr || sqlite3_malloc_failed ){
+ if( pParse->nErr || sqlite3Tsd()->mallocFailed ){
goto exit_drop_index;
}
assert( pName->nSrc==1 );
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
struct SrcList_item *pItem;
- for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pItem->iCursor>=0 ) break;
- pItem->iCursor = pParse->nTab++;
- if( pItem->pSelect ){
- sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
+ assert(pList || sqlite3Tsd()->mallocFailed);
+ if( pList ){
+ for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
+ if( pItem->iCursor>=0 ) break;
+ pItem->iCursor = pParse->nTab++;
+ if( pItem->pSelect ){
+ sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
+ }
}
}
}
int i;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
- if( pParse->nErr || sqlite3_malloc_failed ) return;
+ if( pParse->nErr || sqlite3Tsd()->mallocFailed ) return;
if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return;
v = sqlite3GetVdbe(pParse);
Vdbe *v;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
- if( pParse->nErr || sqlite3_malloc_failed ) return;
+ if( pParse->nErr || sqlite3Tsd()->mallocFailed ) return;
if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return;
v = sqlite3GetVdbe(pParse);
Vdbe *v;
if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return;
- if( pParse->nErr || sqlite3_malloc_failed ) return;
+ if( pParse->nErr || sqlite3Tsd()->mallocFailed ) return;
if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return;
v = sqlite3GetVdbe(pParse);
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
-** $Id: callback.c,v 1.4 2005/10/20 07:28:18 drh Exp $
+** $Id: callback.c,v 1.5 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
** return the pColl pointer to be deleted (because it wasn't added
** to the hash table).
*/
- assert( !pDel || (sqlite3_malloc_failed && pDel==pColl) );
+ assert( !pDel || (sqlite3Tsd()->mallocFailed && pDel==pColl) );
sqliteFree(pDel);
}
}
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.111 2005/09/20 17:42:23 drh Exp $
+** $Id: delete.c,v 1.112 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
#endif
sContext.pParse = 0;
- if( pParse->nErr || sqlite3_malloc_failed ){
+ if( pParse->nErr || sqlite3Tsd()->mallocFailed ){
goto delete_from_cleanup;
}
db = pParse->db;
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.240 2005/11/29 03:13:22 drh Exp $
+** $Id: expr.c,v 1.241 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
assert( pRight!=0 );
assert( pLeft!=0 );
- if( !sqlite3_malloc_failed && pRight->z && pLeft->z ){
+ if( !sqlite3Tsd()->mallocFailed && pRight->z && pLeft->z ){
assert( pLeft->dyn==0 || pLeft->z[pLeft->n]==0 );
if( pLeft->dyn==0 && pRight->dyn==0 ){
pExpr->span.z = pLeft->z;
sqlite3ReallocOrFree((void**)&pParse->apVarExpr,
pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) );
}
- if( !sqlite3_malloc_failed ){
+ if( !sqlite3Tsd()->mallocFailed ){
assert( pParse->apVarExpr!=0 );
pParse->apVarExpr[pParse->nVarExpr++] = pExpr;
}
sqlite3TokenCopy(&pNewExpr->span, &pOldExpr->span);
}
assert( pNewExpr==0 || pNewExpr->span.z!=0
- || pOldExpr->span.z==0 || sqlite3_malloc_failed );
+ || pOldExpr->span.z==0 || sqlite3Tsd()->mallocFailed );
pItem->zName = sqliteStrDup(pOldItem->zName);
pItem->sortOrder = pOldItem->sortOrder;
pItem->isAgg = pOldItem->isAgg;
zDb = sqlite3NameFromToken(pDbToken);
zTab = sqlite3NameFromToken(pTableToken);
zCol = sqlite3NameFromToken(pColumnToken);
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
goto lookupname_end;
}
int mem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);
testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0);
- assert( testAddr>0 || sqlite3_malloc_failed );
+ assert( testAddr>0 || sqlite3Tsd()->mallocFailed );
sqlite3VdbeAddOp(v, OP_MemInt, 1, mem);
}
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.149 2005/11/24 13:15:33 drh Exp $
+** $Id: insert.c,v 1.150 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
int counterRowid; /* Memory cell holding rowid of autoinc counter */
#endif
- if( pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup;
+ if( pParse->nErr || sqlite3Tsd()->mallocFailed ) goto insert_cleanup;
db = pParse->db;
/* Locate the table into which we will be inserting new information.
/* Resolve the expressions in the SELECT statement and execute it. */
rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0);
- if( rc || pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup;
+ if( rc || pParse->nErr || sqlite3Tsd()->mallocFailed ) goto insert_cleanup;
iCleanup = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup);
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: legacy.c,v 1.7 2004/09/06 17:34:13 drh Exp $
+** $Id: legacy.c,v 1.8 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
if( pStmt ) sqlite3_finalize(pStmt);
if( azCols ) sqliteFree(azCols);
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
rc = SQLITE_NOMEM;
}
if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.304 2005/11/30 03:20:31 drh Exp $
+** $Id: main.c,v 1.305 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
*/
const char *sqlite3_errmsg(sqlite3 *db){
const char *z;
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
return sqlite3ErrStr(SQLITE_NOMEM);
}
if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){
};
const void *z;
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]);
}
if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){
** Return the most recent error code generated by an SQLite routine.
*/
int sqlite3_errcode(sqlite3 *db){
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
return SQLITE_NOMEM;
}
if( sqlite3SafetyCheck(db) ){
if( sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) ||
sqlite3_create_collation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) ||
(db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0))==0 ){
- rc = db->errCode;
- assert( rc!=SQLITE_OK );
+ assert(rc!=SQLITE_OK || sqlite3Tsd()->mallocFailed);
db->magic = SQLITE_MAGIC_CLOSED;
goto opendb_out;
}
db->magic = SQLITE_MAGIC_OPEN;
opendb_out:
- if( sqlite3_errcode(db)==SQLITE_OK && sqlite3_malloc_failed ){
+ if( sqlite3_errcode(db)==SQLITE_OK && sqlite3Tsd()->mallocFailed ){
sqlite3Error(db, SQLITE_NOMEM, 0);
}
*ppDb = db;
** dangerous and will almost certainly result in malfunctions.
*/
int sqlite3_global_recover(){
+#if 0
int rc = SQLITE_OK;
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
sqlite3 *db;
int i;
- sqlite3_malloc_failed = 0;
+ sqlite3Tsd()->mallocFailed = 0;
for(db=pDbList; db; db=db->pNext ){
sqlite3ExpirePreparedStatements(db);
for(i=0; i<db->nDb; i++){
recover_out:
if( rc!=SQLITE_OK ){
- sqlite3_malloc_failed = 1;
+ sqlite3Tsd()->mallocFailed = 1;
}
return rc;
+#endif
+ return SQLITE_OK;
}
#endif
}
f.locktype = 0;
TRACE3("OPEN-RO %-3d %s\n", f.h, zFilename);
+
return allocateUnixFile(&f, pId);
}
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.222 2005/11/30 03:20:31 drh Exp $
+** @(#) $Id: pager.c,v 1.223 2005/12/06 12:52:59 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
*ppPager = 0;
memset(&fd, 0, sizeof(fd));
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
return SQLITE_NOMEM;
}
if( zFilename && zFilename[0] ){
+ sizeof(u32) + pPager->nExtra
+ MEMDB*sizeof(PgHistory) );
if( pPg==0 ){
- pPager->errMask |= PAGER_ERR_MEM;
+ // pPager->errMask |= PAGER_ERR_MEM;
return SQLITE_NOMEM;
}
memset(pPg, 0, sizeof(*pPg));
if( pPager->stmtAutoopen && rc==SQLITE_OK ){
rc = sqlite3pager_stmt_begin(pPager);
}
- if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
rc = pager_unwritelock(pPager);
if( rc==SQLITE_OK ){
rc = SQLITE_FULL;
failed_to_open_journal:
sqliteFree(pPager->aInJournal);
pPager->aInJournal = 0;
- sqlite3OsUnlock(pPager->fd, NO_LOCK);
- pPager->state = PAGER_UNLOCK;
+ if( rc==SQLITE_NOMEM ){
+ /* If this was a malloc() failure, then we will not be closing the pager
+ ** file. So delete any journal file we may have just created. Otherwise,
+ ** the system will get confused, we have a read-lock on the file and a
+ ** mysterious journal has appeared in the filesystem.
+ */
+ sqlite3Os.xDelete(pPager->zJournal);
+ }else{
+ sqlite3OsUnlock(pPager->fd, NO_LOCK);
+ pPager->state = PAGER_UNLOCK;
+ }
return rc;
}
assert( pPager->journalOpen );
pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 );
if( pPager->aInStmt==0 ){
- sqlite3OsLock(pPager->fd, SHARED_LOCK);
+ /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */
return SQLITE_NOMEM;
}
#ifndef NDEBUG
** interface, and routines that contribute to loading the database schema
** from disk.
**
-** $Id: prepare.c,v 1.4 2005/09/10 16:46:13 drh Exp $
+** $Id: prepare.c,v 1.5 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
** that the database is corrupt.
*/
static void corruptSchema(InitData *pData, const char *zExtra){
- if( !sqlite3_malloc_failed ){
+ if( !sqlite3Tsd()->mallocFailed ){
sqlite3SetString(pData->pzErrMsg, "malformed database schema",
zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}
rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
db->init.iDb = 0;
if( SQLITE_OK!=rc ){
- corruptSchema(pData, zErr);
+ if( rc==SQLITE_NOMEM ){
+ sqlite3Tsd()->mallocFailed = 1;
+ }else{
+ corruptSchema(pData, zErr);
+ }
sqlite3_free(zErr);
return rc;
}
#endif
sqlite3BtreeCloseCursor(curMain);
}
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
sqlite3SetString(pzErrMsg, "out of memory", (char*)0);
rc = SQLITE_NOMEM;
sqlite3ResetInternalSchema(db, 0);
char *zErrMsg = 0;
int rc = SQLITE_OK;
- if( sqlite3_malloc_failed ){
- return SQLITE_NOMEM;
- }
+ assert(!sqlite3Tsd()->mallocFailed);
assert( ppStmt );
*ppStmt = 0;
sParse.db = db;
sqlite3RunParser(&sParse, zSql, &zErrMsg);
- if( sqlite3_malloc_failed ){
- rc = SQLITE_NOMEM;
+ if( sqlite3Tsd()->mallocFailed ){
+ sParse.rc = SQLITE_NOMEM;
+#if 0
+ sqlite3RollbackInternalChanges(db);
sqlite3RollbackAll(db);
- sqlite3ResetInternalSchema(db, 0);
db->flags &= ~SQLITE_InTrans;
- goto prepare_out;
+ db->autoCommit = 1;
+#endif
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){
}else{
sqlite3Error(db, rc, 0);
}
+
+ /* We must check for malloc failure last of all, in case malloc() failed
+ ** inside of the sqlite3Error() call above or something.
+ */
+ if( sqlite3Tsd()->mallocFailed ){
+ rc = SQLITE_NOMEM;
+ sqlite3Error(db, rc, 0);
+ }
+
+ sqlite3ClearMallocFailed();
return rc;
}
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.280 2005/11/16 13:47:51 drh Exp $
+** $Id: select.c,v 1.281 2005/12/06 12:52:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
*/
static void setToken(Token *p, const char *z){
p->z = z;
- p->n = strlen(z);
+ p->n = z ? strlen(z) : 0;
p->dyn = 0;
}
#endif
assert( v!=0 );
- if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return;
+ if( pParse->colNamesSet || v==0 || sqlite3Tsd()->mallocFailed ) return;
pParse->colNamesSet = 1;
fullNames = (db->flags & SQLITE_FullColNames)!=0;
shortNames = (db->flags & SQLITE_ShortColNames)!=0;
zName = sqlite3MPrintf("column%d", i+1);
}
sqlite3Dequote(zName);
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
sqliteFree(zName);
sqlite3DeleteTable(0, pTab);
return 0;
Table *pTab;
struct SrcList_item *pFrom;
- if( p==0 || p->pSrc==0 || sqlite3_malloc_failed ) return 1;
+ if( p==0 || p->pSrc==0 || sqlite3Tsd()->mallocFailed ) return 1;
pTabList = p->pSrc;
pEList = p->pEList;
/* This particular expression does not need to be expanded.
*/
pNew = sqlite3ExprListAppend(pNew, a[k].pExpr, 0);
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
+ if( pNew ){
+ pNew->a[pNew->nExpr-1].zName = a[k].zName;
+ }else{
+ rc = 1;
+ }
a[k].pExpr = 0;
a[k].zName = 0;
}else{
AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
- if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1;
+ if( sqlite3Tsd()->mallocFailed || pParse->nErr || p==0 ) return 1;
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
memset(&sAggInfo, 0, sizeof(sAggInfo));
goto select_end;
}
}
- if( sqlite3_malloc_failed ) goto select_end;
+ if( sqlite3Tsd()->mallocFailed ) goto select_end;
/* Processing for aggregates with GROUP BY is very different and
** much more complex tha aggregates without a GROUP BY.
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.428 2005/11/14 22:29:05 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.429 2005/12/06 12:52:59 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
# define sqliteStrNDup sqlite3StrNDup
#endif
-/*
-** This variable gets set if malloc() ever fails. After it gets set,
-** the SQLite library shuts down permanently.
-*/
-extern int sqlite3_malloc_failed;
-
/*
** The following global variables are used for testing and debugging
** only. They only work if SQLITE_DEBUG is defined.
char **pzErrMsg; /* Error message stored here */
} InitData;
+/*
+** An instance of this structure is allocated for each thread that uses SQLite.
+*/
+typedef struct SqliteTsd SqliteTsd;
+struct SqliteTsd {
+ int mallocFailed; /* True after a malloc() has failed */
+};
+
/*
* This global flag is set for performance testing of triggers. When it is set
* SQLite will perform the overhead of building new and old trigger references
void sqlite3DefaultRowEst(Index*);
void sqlite3RegisterLikeFunctions(sqlite3*, int);
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
+SqliteTsd *sqlite3Tsd();
+void sqlite3ClearMallocFailed();
#ifdef SQLITE_SSE
#include "sseInt.h"
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test1.c,v 1.170 2005/12/05 13:20:02 drh Exp $
+** $Id: test1.c,v 1.171 2005/12/06 12:53:00 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
** first failure will continue to fail on every call. If REPEAT-INTERVAL is
** 2 then every other malloc will fail. And so forth.
**
-** Turn off this mechanism and reset the sqlite3_malloc_failed variable is N==0.
+** Turn off this mechanism and reset the sqlite3Tsd()->mallocFailed variable is N==0.
*/
#ifdef SQLITE_MEMDEBUG
static int sqlite_malloc_fail(
}
sqlite3_iMallocFail = n;
sqlite3_iMallocReset = rep;
- sqlite3_malloc_failed = 0;
+ sqlite3Tsd()->mallocFailed = 0;
return TCL_OK;
}
#endif
/*
** Usage: sqlite3_reset STMT
**
-** Finalize a statement handle.
+** Reset a statement handle.
*/
static int test_reset(
void * clientData,
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
rc = sqlite3_reset(pStmt);
- if( pStmt &&
- sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
+ if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
+ return TCL_ERROR;
+ }
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
+/*
if( rc ){
return TCL_ERROR;
}
+*/
return TCL_OK;
}
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.108 2005/10/23 11:29:40 drh Exp $
+** $Id: tokenize.c,v 1.109 2005/12/06 12:53:00 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
i = 0;
pEngine = sqlite3ParserAlloc((void*(*)(int))sqlite3MallocX);
if( pEngine==0 ){
- sqlite3SetString(pzErrMsg, "out of memory", (char*)0);
return SQLITE_NOMEM;
}
assert( pParse->sLastToken.dyn==0 );
assert( pParse->nVarExprAlloc==0 );
assert( pParse->apVarExpr==0 );
pParse->zTail = pParse->zSql = zSql;
- while( sqlite3_malloc_failed==0 && zSql[i]!=0 ){
+ while( sqlite3Tsd()->mallocFailed==0 && zSql[i]!=0 ){
assert( i>=0 );
pParse->sLastToken.z = &zSql[i];
assert( pParse->sLastToken.dyn==0 );
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
}
sqlite3ParserFree(pEngine, sqlite3FreeX);
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
pParse->rc = SQLITE_NOMEM;
}
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
- sqlite3SetString(&pParse->zErrMsg, sqlite3ErrStr(pParse->rc),
- (char*)0);
+ sqlite3SetString(&pParse->zErrMsg, sqlite3ErrStr(pParse->rc), (char*)0);
}
if( pParse->zErrMsg ){
if( pzErrMsg && *pzErrMsg==0 ){
** If sqlite3SrcListLookup() returns 0, indicating the table does not
** exist, the error is caught by the block below.
*/
- if( !pTableName || sqlite3_malloc_failed ) goto trigger_cleanup;
+ if( !pTableName || sqlite3Tsd()->mallocFailed ) goto trigger_cleanup;
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( pName2->n==0 && pTab && pTab->iDb==1 ){
iDb = 1;
}
/* Ensure the table name matches database name and that the table exists */
- if( sqlite3_malloc_failed ) goto trigger_cleanup;
+ if( sqlite3Tsd()->mallocFailed ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
sqlite3FixSrcList(&sFix, pTableName) ){
pDel = sqlite3HashInsert(&db->aDb[pTrig->iDb].trigHash,
pTrig->name, strlen(pTrig->name)+1, pTrig);
if( pDel ){
- assert( sqlite3_malloc_failed && pDel==pTrig );
+ assert( sqlite3Tsd()->mallocFailed && pDel==pTrig );
goto triggerfinish_cleanup;
}
pTab = sqlite3LocateTable(pParse,pTrig->table,db->aDb[pTrig->iTabDb].zName);
int nName;
sqlite3 *db = pParse->db;
- if( sqlite3_malloc_failed ) goto drop_trigger_cleanup;
+ if( sqlite3Tsd()->mallocFailed ) goto drop_trigger_cleanup;
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto drop_trigger_cleanup;
}
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.113 2005/11/14 22:29:05 drh Exp $
+** $Id: update.c,v 1.114 2005/12/06 12:53:01 danielk1977 Exp $
*/
#include "sqliteInt.h"
int oldIdx = -1; /* index of trigger "old" temp table */
sContext.pParse = 0;
- if( pParse->nErr || sqlite3_malloc_failed ) goto update_cleanup;
+ if( pParse->nErr || sqlite3Tsd()->mallocFailed ) goto update_cleanup;
db = pParse->db;
assert( pTabList->nSrc==1 );
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.148 2005/10/20 07:28:19 drh Exp $
+** $Id: util.c,v 1.149 2005/12/06 12:53:01 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#define print_stack_trace()
#endif
+#if 0
/*
** If malloc() ever fails, this global variable gets set to 1.
** This causes the library to abort and never again function.
*/
-int sqlite3_malloc_failed = 0;
+int sqlite3Tsd()->mallocFailed = 0;
+#endif
/*
** If SQLITE_MEMDEBUG is defined, then use versions of malloc() and
if( sqlite3_iMallocFail>=0 ){
sqlite3_iMallocFail--;
if( sqlite3_iMallocFail==0 ){
- sqlite3_malloc_failed++;
+ sqlite3Tsd()->mallocFailed++;
#if SQLITE_MEMDEBUG>1
fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n",
n, zFile,line);
void *p;
int *pi;
int i, k;
+
+ /* Any malloc() calls between a malloc() failure and clearing the
+ ** mallocFailed flag (done before returning control to the user)
+ ** automatically fail. Although this restriction may have to be relaxed in
+ ** the future, for now it makes the system easier to test.
+ **
+ ** TODO: This will eventually be done as part of the same wrapper that may
+ ** call sqlite3_release_memory(). Above the sqlite3OsMalloc() level.
+ */
+ if( sqlite3Tsd()->mallocFailed ){
+ return 0;
+ }
+
if( n==0 ){
return 0;
}
k = (n+sizeof(int)-1)/sizeof(int);
pi = malloc( (N_GUARD*2+1+k)*sizeof(int));
if( pi==0 ){
- if( n>0 ) sqlite3_malloc_failed++;
+ if( n>0 ) sqlite3Tsd()->mallocFailed++;
return 0;
}
sqlite3_nMalloc++;
k = (n + sizeof(int) - 1)/sizeof(int);
pi = malloc( (k+N_GUARD*2+1)*sizeof(int) );
if( pi==0 ){
- if( n>0 ) sqlite3_malloc_failed++;
+ if( n>0 ) sqlite3Tsd()->mallocFailed++;
return 0;
}
for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122;
void *p;
if( n==0 ) return 0;
if( (p = malloc(n))==0 ){
- if( n>0 ) sqlite3_malloc_failed++;
+ if( n>0 ) sqlite3Tsd()->mallocFailed++;
}else{
memset(p, 0, n);
}
void *p;
if( n==0 ) return 0;
if( (p = malloc(n))==0 ){
- if( n>0 ) sqlite3_malloc_failed++;
+ if( n>0 ) sqlite3Tsd()->mallocFailed++;
}
return p;
}
}
p2 = realloc(p, n);
if( p2==0 ){
- if( n>0 ) sqlite3_malloc_failed++;
+ if( n>0 ) sqlite3Tsd()->mallocFailed++;
}
return p2;
}
return p;
}
#endif
+
+/*
+** Return a pointer to the SqliteTsd associated with the calling thread.
+*/
+static SqliteTsd tsd = { 0 };
+SqliteTsd *sqlite3Tsd(){
+ return &tsd;
+}
+
+void sqlite3ClearMallocFailed(){
+ sqlite3Tsd()->mallocFailed = 0;
+}
+
+
+
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
-** $Id: vacuum.c,v 1.49 2005/11/30 03:20:32 drh Exp $
+** $Id: vacuum.c,v 1.50 2005/12/06 12:53:01 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain),
sqlite3BtreeGetReserve(pMain));
assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) );
- execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
+ rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
+ if( rc!=SQLITE_OK ){
+ goto end_of_vacuum;
+ }
#ifndef SQLITE_OMIT_AUTOVACUUM
sqlite3BtreeSetAutoVacuum(pTemp, sqlite3BtreeGetAutoVacuum(pMain));
}
end_of_vacuum:
+ /* If one of the execSql() calls above returned SQLITE_NOMEM, then the
+ ** mallocFailed flag will be clear (because execSql() calls sqlite3_exec()).
+ ** Fix this so the flag and return code match.
+ */
+ if( rc==SQLITE_NOMEM ){
+ sqlite3Tsd()->mallocFailed = 1;
+ }
+
/* Restore the original value of db->flags */
db->flags = saved_flags;
** is closed by the DETACH.
*/
db->autoCommit = 1;
- rc2 = execSql(db, "DETACH vacuum_db;");
- if( rc==SQLITE_OK ){
- rc = rc2;
+
+ /* TODO: We need to detach vacuum_db (if it is attached) even if malloc()
+ ** failed. Right now trying to do so will cause an assert() to fail in **
+ **_prepare() (because it should be impossible to call _prepare() with the **
+ ** mallocFailed flag set). So really, we need to be able to detach a database
+ ** without calling malloc(). Which seems plausible.
+ */
+ if( !sqlite3Tsd()->mallocFailed ){
+ rc2 = execSql(db, "DETACH vacuum_db;");
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
}
if( zTemp ){
sqlite3Os.xDelete(zTemp);
** 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.501 2005/11/30 03:20:32 drh Exp $
+** $Id: vdbe.c,v 1.502 2005/12/06 12:53:01 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
p->rc = SQLITE_OK;
assert( p->explain==0 );
pTos = p->pTos;
- if( sqlite3_malloc_failed ) goto no_mem;
+ if( sqlite3Tsd()->mallocFailed ) goto no_mem;
if( p->popStack ){
popStack(&pTos, p->popStack);
p->popStack = 0;
for(pc=p->pc; rc==SQLITE_OK; pc++){
assert( pc>=0 && pc<p->nOp );
assert( pTos<=&p->aStack[pc] );
- if( sqlite3_malloc_failed ) goto no_mem;
+ if( sqlite3Tsd()->mallocFailed ) goto no_mem;
#ifdef VDBE_PROFILE
origPc = pc;
start = hwtime();
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
(*ctx.pFunc->xFunc)(&ctx, n, apVal);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
- if( sqlite3_malloc_failed ) goto no_mem;
+ if( sqlite3Tsd()->mallocFailed ) goto no_mem;
popStack(&pTos, n);
/* If any auxilary data functions have been called by this user function,
if( pC->nextRowidValid ){
v = pC->nextRowid;
}else{
- rx = sqlite3BtreeLast(pC->pCursor, &res);
+ rc = sqlite3BtreeLast(pC->pCursor, &res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
if( res ){
v = 1;
}else{
sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
+ assert(0==sqlite3Tsd()->mallocFailed);
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
db->init.busy = 0;
sqlite3SafetyOn(db);
+ if( rc==SQLITE_NOMEM ){
+ sqlite3Tsd()->mallocFailed = 1;
+ goto no_mem;
+ }
sqliteFree(zSql);
break;
}
*/
abort_due_to_error:
if( p->zErrMsg==0 ){
- if( sqlite3_malloc_failed ) rc = SQLITE_NOMEM;
+ if( sqlite3Tsd()->mallocFailed ) rc = SQLITE_NOMEM;
sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
}
goto vdbe_halt;
sqlite3 *db;
int rc;
+ assert(!sqlite3Tsd()->mallocFailed);
+
if( p==0 || p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_MISUSE;
}
#endif
sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
+ sqlite3ClearMallocFailed();
return rc;
}
p->nOp++;
assert( p->magic==VDBE_MAGIC_INIT );
resizeOpArray(p, i+1);
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
return 0;
}
pOp = &p->aOp[i];
int addr;
assert( p->magic==VDBE_MAGIC_INIT );
resizeOpArray(p, p->nOp + nOp);
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
return 0;
}
addr = p->nOp;
Op *pOp;
assert( p->magic==VDBE_MAGIC_INIT );
if( p==0 || p->aOp==0 ){
- freeP3(n, (void*)*(char**)&zP3);
+ if (n != P3_KEYINFO) {
+ freeP3(n, (void*)*(char**)&zP3);
+ }
return;
}
if( addr<0 || addr>=p->nOp ){
+ nMem*sizeof(Mem) /* aMem */
+ nCursor*sizeof(Cursor*) /* apCsr */
);
- if( !sqlite3_malloc_failed ){
+ if( !sqlite3Tsd()->mallocFailed ){
p->aMem = &p->aStack[nStack];
p->nMem = nMem;
p->aVar = &p->aMem[nMem];
int rc;
Mem *pColName;
assert( idx<(2*p->nResColumn) );
- if( sqlite3_malloc_failed ) return SQLITE_NOMEM;
+ if( sqlite3Tsd()->mallocFailed ) return SQLITE_NOMEM;
assert( p->aColName!=0 );
pColName = &(p->aColName[idx]);
if( N==P3_DYNAMIC || N==P3_STATIC ){
int i;
int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */
+ if( sqlite3Tsd()->mallocFailed ){
+ p->rc = SQLITE_NOMEM;
+ }
+
if( p->magic!=VDBE_MAGIC_RUN ){
/* Already halted. Nothing to do. */
assert( p->magic==VDBE_MAGIC_HALT );
if( p->pc<0 ){
/* No commit or rollback needed if the program never started */
}else if( db->autoCommit && db->activeVdbeCnt==1 ){
- if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
+
+ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && p->rc!=SQLITE_NOMEM)){
/* The auto-commit flag is true, there are no other active queries
** using this handle and the vdbe program was successful or hit an
** 'OR FAIL' constraint. This means a commit is required.
}else if( rc!=SQLITE_OK ){
p->rc = rc;
xFunc = sqlite3BtreeRollback;
+ }else{
+ sqlite3CommitInternalChanges(db);
}
}else{
xFunc = sqlite3BtreeRollback;
}
}else{
+
+ if( p->rc==SQLITE_NOMEM ){
+ /* This loop does static analysis of the query to see which of the
+ ** following three categories it falls into:
+ **
+ ** Read-only
+ ** Query with statement journal -> rollback statement
+ ** Query without statement journal -> rollback transaction
+ **
+ ** We could do something more elegant than this static analysis (i.e.
+ ** store the type of query as part of the compliation phase), but
+ ** handling malloc() failure is a fairly obscure edge case so this is
+ ** probably easier.
+ **
+ ** Todo: This means we always override the p->errorAction value for a
+ ** malloc() failure. Is there any other choice here though?
+ */
+ int isReadOnly = 1;
+ int isStatement = 0;
+ assert(p->aOp || p->nOp==0);
+ for(i=0; i<p->nOp; i++){
+ switch( p->aOp[i].opcode ){
+ case OP_Transaction:
+ isReadOnly = 0;
+ break;
+ case OP_Statement:
+ isStatement = 1;
+ break;
+ }
+ }
+ if( (isReadOnly||isStatement) && p->errorAction!=OE_Rollback ){
+ p->errorAction = OE_Abort;
+ }else{
+ p->errorAction = OE_Rollback;
+ }
+ }
+
if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
xFunc = sqlite3BtreeCommitStmt;
}else if( p->errorAction==OE_Abort ){
}
/* Rollback or commit any schema changes that occurred. */
- if( p->rc!=SQLITE_OK ){
- sqlite3RollbackInternalChanges(db);
- }else if( db->flags & SQLITE_InternChanges ){
- sqlite3CommitInternalChanges(db);
+ if( p->rc!=SQLITE_OK && db->flags&SQLITE_InternChanges ){
+ sqlite3ResetInternalSchema(db, 0);
+ if( xFunc!=sqlite3BtreeRollback ){
+ db->flags = (db->flags | SQLITE_InternChanges);
+ }
}
/* We have successfully halted and closed the VM. Record this fact. */
/* Save profiling information from this VDBE run.
*/
- assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || sqlite3_malloc_failed==1 );
+ assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || !p->aStack );
#ifdef VDBE_PROFILE
{
FILE *out = fopen("vdbe_profile.out", "a");
** 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.185 2005/11/26 14:24:41 drh Exp $
+** $Id: where.c,v 1.186 2005/12/06 12:53:01 danielk1977 Exp $
*/
#include "sqliteInt.h"
int nPattern;
int isComplete;
- if( sqlite3_malloc_failed ) return;
+ if( sqlite3Tsd()->mallocFailed ) return;
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
if( pExpr->op==TK_IN ){
assert( pExpr->pRight==0 );
** return value.
*/
pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
goto whereBeginNoMem;
}
pWInfo->pParse = pParse;
createMask(&maskSet, pTabList->a[i].iCursor);
}
exprAnalyzeAll(pTabList, &maskSet, &wc);
- if( sqlite3_malloc_failed ){
+ if( sqlite3Tsd()->mallocFailed ){
goto whereBeginNoMem;
}
# special feature is used to see what happens in the library if a malloc
# were to really fail due to an out-of-memory situation.
#
-# $Id: malloc.test,v 1.24 2005/09/08 00:13:28 drh Exp $
+# $Id: malloc.test,v 1.25 2005/12/06 12:53:01 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Only run these tests if memory debugging is turned on.
#
if {[info command sqlite_malloc_stat]==""} {
- puts "Skipping malloc tests: not compiled with -DSQLITE_DEBUG..."
+ puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
finish_test
return
}
# 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} {incr ::n} {
+ for {set ::n 1} {$::go && $::n < 50000} {incr ::n} {
do_test malloc-$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 test2.db-journal}
set ::DB [sqlite3 db test.db]
+ # Execute any -tclprep and -sqlprep scripts.
+ #
if {[info exists ::mallocopts(-tclprep)]} {
eval $::mallocopts(-tclprep)
}
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)]} {
if {[info exists ::mallocopts(-sqlbody)]} {
append ::mallocbody "db eval {$::mallocopts(-sqlbody)}"
}
-
set v [catch $::mallocbody msg]
set leftover [lindex [sqlite_malloc_stat] 2]
# This file attempts to check that the library can recover from a malloc()
# failure when sqlite3_global_recover() is invoked.
#
-# $Id: malloc2.test,v 1.3 2005/06/06 14:45:43 drh Exp $
+# $Id: malloc2.test,v 1.4 2005/12/06 12:53:01 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Nothing should work now, because the allocator should refuse to
# allocate any memory.
+ #
+ # Update: SQLite now automatically recovers from a malloc() failure.
+ # So the statement in the test below would work.
+if 0 {
do_test malloc2-$tn.$::n.3 {
catchsql {SELECT 'nothing should work'}
} {1 {out of memory}}
+}
# Recover from the malloc failure.
+ #
+ # Update: The new malloc() failure handling means that a transaction may
+ # still be active even if a malloc() has failed. But when these tests were
+ # written this was not the case. So do a manual ROLLBACK here so that the
+ # tests pass.
do_test malloc2-$tn.$::n.4 {
- if 0 {
- db close
- sqlite_malloc_fail -1
- set ::DB [sqlite3 db test.db]
- set dummy SQLITE_OK
- } else {
- sqlite3_global_recover
+ sqlite3_global_recover
+ catch {
+ execsql {
+ ROLLBACK;
+ }
}
- } {SQLITE_OK}
+ expr 0
+ } {0}
# Checksum the database.
do_test malloc2-$tn.$::n.5 {
########################################################################
# Check that if a statement is active sqlite3_global_recover doesn't reset
# the sqlite3_malloc_failed variable.
-do_test malloc2-6.1 {
- set ::STMT [sqlite3_prepare $::DB {SELECT * FROM def} -1 DUMMY]
- sqlite3_step $::STMT
-} {SQLITE_ROW}
-do_test malloc2-6.2 {
- sqlite3 db1 test.db
- sqlite_malloc_fail 100
- catchsql {
- SELECT * FROM def;
- } db1
-} {1 {out of memory}}
-do_test malloc2-6.3 {
- sqlite3_global_recover
-} {SQLITE_BUSY}
-do_test malloc2-6.4 {
- catchsql {
- SELECT 'hello';
- }
-} {1 {out of memory}}
-do_test malloc2-6.5 {
- sqlite3_reset $::STMT
-} {SQLITE_OK}
-do_test malloc2-6.6 {
- sqlite3_global_recover
-} {SQLITE_OK}
-do_test malloc2-6.7 {
- catchsql {
- SELECT 'hello';
- }
-} {0 hello}
-do_test malloc2-6.8 {
- sqlite3_step $::STMT
-} {SQLITE_ERROR}
-do_test malloc2-6.9 {
- sqlite3_finalize $::STMT
-} {SQLITE_SCHEMA}
-do_test malloc2-6.10 {
- db1 close
-} {}
+#
+# Update: There is now no sqlite3_malloc_failed variable, so these tests
+# are not run.
+#
+# do_test malloc2-6.1 {
+# set ::STMT [sqlite3_prepare $::DB {SELECT * FROM def} -1 DUMMY]
+# sqlite3_step $::STMT
+# } {SQLITE_ROW}
+# do_test malloc2-6.2 {
+# sqlite3 db1 test.db
+# sqlite_malloc_fail 100
+# catchsql {
+# SELECT * FROM def;
+# } db1
+# } {1 {out of memory}}
+# do_test malloc2-6.3 {
+# sqlite3_global_recover
+# } {SQLITE_BUSY}
+# do_test malloc2-6.4 {
+# catchsql {
+# SELECT 'hello';
+# }
+# } {1 {out of memory}}
+# do_test malloc2-6.5 {
+# sqlite3_reset $::STMT
+# } {SQLITE_OK}
+# do_test malloc2-6.6 {
+# sqlite3_global_recover
+# } {SQLITE_OK}
+# do_test malloc2-6.7 {
+# catchsql {
+# SELECT 'hello';
+# }
+# } {0 hello}
+# do_test malloc2-6.8 {
+# sqlite3_step $::STMT
+# } {SQLITE_ERROR}
+# do_test malloc2-6.9 {
+# sqlite3_finalize $::STMT
+# } {SQLITE_SCHEMA}
+# do_test malloc2-6.10 {
+# db1 close
+# } {}
########################################################################
# Check that if an in-memory database is being used it is not possible
# to recover from a malloc() failure.
-ifcapable memorydb {
- do_test malloc2-7.1 {
- sqlite3 db1 :memory:
- list
- } {}
- do_test malloc2-7.2 {
- sqlite_malloc_fail 100
- catchsql {
- SELECT * FROM def;
- }
- } {1 {out of memory}}
- do_test malloc2-7.3 {
- sqlite3_global_recover
- } {SQLITE_ERROR}
- do_test malloc2-7.4 {
- catchsql {
- SELECT 'hello';
- }
- } {1 {out of memory}}
- do_test malloc2-7.5 {
- db1 close
- } {}
- do_test malloc2-7.6 {
- sqlite3_global_recover
- } {SQLITE_OK}
- do_test malloc2-7.7 {
- catchsql {
- SELECT 'hello';
- }
- } {0 hello}
-}
+#
+# Update: An in-memory database can now survive a malloc() failure, so these
+# tests are not run.
+#
+# ifcapable memorydb {
+# do_test malloc2-7.1 {
+# sqlite3 db1 :memory:
+# list
+# } {}
+# do_test malloc2-7.2 {
+# sqlite_malloc_fail 100
+# catchsql {
+# SELECT * FROM def;
+# }
+# } {1 {out of memory}}
+# do_test malloc2-7.3 {
+# sqlite3_global_recover
+# } {SQLITE_ERROR}
+# do_test malloc2-7.4 {
+# catchsql {
+# SELECT 'hello';
+# }
+# } {1 {out of memory}}
+# do_test malloc2-7.5 {
+# db1 close
+# } {}
+# do_test malloc2-7.6 {
+# sqlite3_global_recover
+# } {SQLITE_OK}
+# do_test malloc2-7.7 {
+# catchsql {
+# SELECT 'hello';
+# }
+# } {0 hello}
+# }
finish_test
# This file tests the various conditions under which an SQLITE_SCHEMA
# error should be returned.
#
-# $Id: schema.test,v 1.4 2005/01/29 01:54:18 danielk1977 Exp $
+# $Id: schema.test,v 1.5 2005/12/06 12:53:01 danielk1977 Exp $
#---------------------------------------------------------------------
# When any of the following types of SQL statements or actions are
# Deleting a collation sequence.......................schema-7.*
# Setting or changing the authorization function......schema-8.*
#
-# Note: Test cases schema-6.* are missing right now.
-#
# Test cases schema-9.* and schema-10.* test some specific bugs
# that came up during development.
#
# change a collation sequence or user-function while SQL statements
# are executing. Adding new collations or functions is allowed.
#
-# Note: Test cases schema-11.* are also missing right now.
set testdir [file dirname $argv0]
source $testdir/tester.tcl
lappend summarymap($stack) $bytes
}
+ set sorted [list]
foreach stack [array names summarymap] {
set allocs $summarymap($stack)
set sum 0