Some elements of the new malloc() failure handling. Not all cases work properly yet. Also, library is not threadsafe if malloc() fails right now. (CVS 2800)
FossilOrigin-Name: e1606658f1b4530e3001db4779b5669c8d13c853
This commit is contained in:
parent
67e0b84f7d
commit
261919cc16
68
manifest
68
manifest
@ -1,5 +1,5 @@
|
||||
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
|
||||
@ -30,68 +30,68 @@ F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
||||
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
|
||||
@ -177,8 +177,8 @@ F test/lock.test 9b7afcb24f53d24da502abb33daaad2cd6d44107
|
||||
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
|
||||
@ -204,7 +204,7 @@ F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b
|
||||
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
|
||||
@ -260,7 +260,7 @@ F tool/lemon.c 26d271a753ef87fe1e6194f53c594ab5e6783d85
|
||||
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
|
||||
@ -324,7 +324,7 @@ F www/tclsqlite.tcl ddcf912ea48695603c8ed7efb29f0812ef8d1b49
|
||||
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
|
||||
|
@ -1 +1 @@
|
||||
41a7aeeeb427d59e3d7cc71c94a8c5be832bd0fa
|
||||
e1606658f1b4530e3001db4779b5669c8d13c853
|
@ -12,7 +12,7 @@
|
||||
** 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>
|
||||
@ -258,7 +258,7 @@ void sqlite3AlterRenameTable(
|
||||
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);
|
||||
@ -504,7 +504,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** 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"
|
||||
|
||||
@ -150,6 +150,7 @@ void sqlite3Attach(
|
||||
if( pParse->rc==SQLITE_OK ){
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
}
|
||||
db->nDb = i;
|
||||
}
|
||||
|
||||
attach_end:
|
||||
|
74
src/build.c
74
src/build.c
@ -22,7 +22,7 @@
|
||||
** 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>
|
||||
@ -50,7 +50,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
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 ){
|
||||
@ -1296,7 +1296,9 @@ void sqlite3EndTable(
|
||||
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;
|
||||
|
||||
@ -1522,6 +1524,9 @@ void sqlite3CreateView(
|
||||
*/
|
||||
p->pSelect = sqlite3SelectDup(pSelect);
|
||||
sqlite3SelectDelete(pSelect);
|
||||
if( sqlite3Tsd()->mallocFailed ){
|
||||
return;
|
||||
}
|
||||
if( !pParse->db->init.busy ){
|
||||
sqlite3ViewGetColumnNames(pParse, p);
|
||||
}
|
||||
@ -1592,24 +1597,28 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
*/
|
||||
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 */
|
||||
@ -1749,7 +1758,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
|
||||
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);
|
||||
|
||||
@ -2098,7 +2107,7 @@ void sqlite3CreateIndex(
|
||||
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.
|
||||
@ -2226,7 +2235,7 @@ void sqlite3CreateIndex(
|
||||
*/
|
||||
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];
|
||||
@ -2472,7 +2481,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
|
||||
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 );
|
||||
@ -2679,11 +2688,14 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2725,7 +2737,7 @@ void sqlite3BeginTransaction(Parse *pParse, int type){
|
||||
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);
|
||||
@ -2746,7 +2758,7 @@ void sqlite3CommitTransaction(Parse *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);
|
||||
@ -2763,7 +2775,7 @@ void sqlite3RollbackTransaction(Parse *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);
|
||||
|
@ -13,7 +13,7 @@
|
||||
** 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"
|
||||
@ -175,7 +175,7 @@ static CollSeq *findCollSeqEntry(
|
||||
** 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);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
** 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"
|
||||
|
||||
@ -102,7 +102,7 @@ void sqlite3DeleteFrom(
|
||||
#endif
|
||||
|
||||
sContext.pParse = 0;
|
||||
if( pParse->nErr || sqlite3_malloc_failed ){
|
||||
if( pParse->nErr || sqlite3Tsd()->mallocFailed ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
db = pParse->db;
|
||||
|
12
src/expr.c
12
src/expr.c
@ -12,7 +12,7 @@
|
||||
** 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>
|
||||
@ -263,7 +263,7 @@ Expr *sqlite3ExprAnd(Expr *pLeft, Expr *pRight){
|
||||
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;
|
||||
@ -358,7 +358,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||
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;
|
||||
}
|
||||
@ -462,7 +462,7 @@ ExprList *sqlite3ExprListDup(ExprList *p){
|
||||
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;
|
||||
@ -831,7 +831,7 @@ static int lookupName(
|
||||
zDb = sqlite3NameFromToken(pDbToken);
|
||||
zTab = sqlite3NameFromToken(pTableToken);
|
||||
zCol = sqlite3NameFromToken(pColumnToken);
|
||||
if( sqlite3_malloc_failed ){
|
||||
if( sqlite3Tsd()->mallocFailed ){
|
||||
goto lookupname_end;
|
||||
}
|
||||
|
||||
@ -1305,7 +1305,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
** 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"
|
||||
|
||||
@ -224,7 +224,7 @@ void sqlite3Insert(
|
||||
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.
|
||||
@ -338,7 +338,7 @@ void sqlite3Insert(
|
||||
|
||||
/* 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);
|
||||
|
@ -14,7 +14,7 @@
|
||||
** 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"
|
||||
@ -122,7 +122,7 @@ exec_out:
|
||||
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 ){
|
||||
|
22
src/main.c
22
src/main.c
@ -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.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"
|
||||
@ -635,7 +635,7 @@ int sqlite3BtreeFactory(
|
||||
*/
|
||||
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 ){
|
||||
@ -674,7 +674,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
|
||||
};
|
||||
|
||||
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 ){
|
||||
@ -694,7 +694,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
|
||||
** 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) ){
|
||||
@ -742,8 +742,7 @@ static int openDatabase(
|
||||
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;
|
||||
}
|
||||
@ -786,7 +785,7 @@ static int openDatabase(
|
||||
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;
|
||||
@ -1010,12 +1009,13 @@ int sqlite3_collation_needed16(
|
||||
** 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++){
|
||||
@ -1030,9 +1030,11 @@ int sqlite3_global_recover(){
|
||||
|
||||
recover_out:
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_malloc_failed = 1;
|
||||
sqlite3Tsd()->mallocFailed = 1;
|
||||
}
|
||||
return rc;
|
||||
#endif
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -689,6 +689,7 @@ static int unixOpenReadOnly(const char *zFilename, OsFile **pId){
|
||||
}
|
||||
f.locktype = 0;
|
||||
TRACE3("OPEN-RO %-3d %s\n", f.h, zFilename);
|
||||
|
||||
return allocateUnixFile(&f, pId);
|
||||
}
|
||||
|
||||
|
23
src/pager.c
23
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.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"
|
||||
@ -1598,7 +1598,7 @@ int sqlite3pager_open(
|
||||
|
||||
*ppPager = 0;
|
||||
memset(&fd, 0, sizeof(fd));
|
||||
if( sqlite3_malloc_failed ){
|
||||
if( sqlite3Tsd()->mallocFailed ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( zFilename && zFilename[0] ){
|
||||
@ -2413,7 +2413,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
|
||||
+ 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));
|
||||
@ -2692,7 +2692,7 @@ static int pager_open_journal(Pager *pPager){
|
||||
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;
|
||||
@ -2703,8 +2703,17 @@ static int pager_open_journal(Pager *pPager){
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3270,7 +3279,7 @@ int sqlite3pager_stmt_begin(Pager *pPager){
|
||||
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
|
||||
|
@ -13,7 +13,7 @@
|
||||
** 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"
|
||||
@ -24,7 +24,7 @@
|
||||
** 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);
|
||||
}
|
||||
@ -71,7 +71,11 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
|
||||
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;
|
||||
}
|
||||
@ -301,7 +305,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
#endif
|
||||
sqlite3BtreeCloseCursor(curMain);
|
||||
}
|
||||
if( sqlite3_malloc_failed ){
|
||||
if( sqlite3Tsd()->mallocFailed ){
|
||||
sqlite3SetString(pzErrMsg, "out of memory", (char*)0);
|
||||
rc = SQLITE_NOMEM;
|
||||
sqlite3ResetInternalSchema(db, 0);
|
||||
@ -425,9 +429,7 @@ int sqlite3_prepare(
|
||||
char *zErrMsg = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( sqlite3_malloc_failed ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
assert(!sqlite3Tsd()->mallocFailed);
|
||||
|
||||
assert( ppStmt );
|
||||
*ppStmt = 0;
|
||||
@ -439,12 +441,14 @@ int sqlite3_prepare(
|
||||
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) ){
|
||||
@ -490,6 +494,16 @@ prepare_out:
|
||||
}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;
|
||||
}
|
||||
|
||||
|
20
src/select.c
20
src/select.c
@ -12,7 +12,7 @@
|
||||
** 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"
|
||||
|
||||
@ -155,7 +155,7 @@ static int columnIndex(Table *pTab, const char *zCol){
|
||||
*/
|
||||
static void setToken(Token *p, const char *z){
|
||||
p->z = z;
|
||||
p->n = strlen(z);
|
||||
p->n = z ? strlen(z) : 0;
|
||||
p->dyn = 0;
|
||||
}
|
||||
|
||||
@ -856,7 +856,7 @@ static void generateColumnNames(
|
||||
#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;
|
||||
@ -984,7 +984,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
||||
zName = sqlite3MPrintf("column%d", i+1);
|
||||
}
|
||||
sqlite3Dequote(zName);
|
||||
if( sqlite3_malloc_failed ){
|
||||
if( sqlite3Tsd()->mallocFailed ){
|
||||
sqliteFree(zName);
|
||||
sqlite3DeleteTable(0, pTab);
|
||||
return 0;
|
||||
@ -1056,7 +1056,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
|
||||
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;
|
||||
|
||||
@ -1164,7 +1164,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){
|
||||
/* 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{
|
||||
@ -2639,7 +2643,7 @@ int sqlite3Select(
|
||||
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));
|
||||
|
||||
@ -2893,7 +2897,7 @@ int sqlite3Select(
|
||||
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.
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** 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_
|
||||
@ -263,12 +263,6 @@ struct BusyHandler {
|
||||
# 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.
|
||||
@ -1385,6 +1379,14 @@ typedef struct {
|
||||
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
|
||||
@ -1674,6 +1676,8 @@ void sqlite3AnalysisLoad(sqlite3*,int iDB);
|
||||
void sqlite3DefaultRowEst(Index*);
|
||||
void sqlite3RegisterLikeFunctions(sqlite3*, int);
|
||||
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
|
||||
SqliteTsd *sqlite3Tsd();
|
||||
void sqlite3ClearMallocFailed();
|
||||
|
||||
#ifdef SQLITE_SSE
|
||||
#include "sseInt.h"
|
||||
|
15
src/test1.c
15
src/test1.c
@ -13,7 +13,7 @@
|
||||
** 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"
|
||||
@ -787,7 +787,7 @@ static int sqlite3_mprintf_hexdouble(
|
||||
** 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(
|
||||
@ -810,7 +810,7 @@ static int sqlite_malloc_fail(
|
||||
}
|
||||
sqlite3_iMallocFail = n;
|
||||
sqlite3_iMallocReset = rep;
|
||||
sqlite3_malloc_failed = 0;
|
||||
sqlite3Tsd()->mallocFailed = 0;
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
@ -952,7 +952,7 @@ static int test_finalize(
|
||||
/*
|
||||
** Usage: sqlite3_reset STMT
|
||||
**
|
||||
** Finalize a statement handle.
|
||||
** Reset a statement handle.
|
||||
*/
|
||||
static int test_reset(
|
||||
void * clientData,
|
||||
@ -972,12 +972,15 @@ static int test_reset(
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
** 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"
|
||||
@ -348,7 +348,6 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
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 );
|
||||
@ -359,7 +358,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
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 );
|
||||
@ -407,12 +406,11 @@ abort_parse:
|
||||
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 ){
|
||||
|
@ -80,14 +80,14 @@ void sqlite3BeginTrigger(
|
||||
** 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) ){
|
||||
@ -250,7 +250,7 @@ void sqlite3FinishTrigger(
|
||||
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);
|
||||
@ -430,7 +430,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName){
|
||||
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;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
** 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"
|
||||
|
||||
@ -99,7 +99,7 @@ void sqlite3Update(
|
||||
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 );
|
||||
|
||||
|
46
src/util.c
46
src/util.c
@ -14,7 +14,7 @@
|
||||
** 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>
|
||||
@ -37,11 +37,13 @@ void print_stack_trace(){
|
||||
#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
|
||||
@ -81,7 +83,7 @@ static int simulatedMallocFailure(int n, char *zFile, int line){
|
||||
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);
|
||||
@ -101,6 +103,19 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int 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;
|
||||
}
|
||||
@ -112,7 +127,7 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
|
||||
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++;
|
||||
@ -228,7 +243,7 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
|
||||
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;
|
||||
@ -294,7 +309,7 @@ void *sqlite3Malloc(int n){
|
||||
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);
|
||||
}
|
||||
@ -309,7 +324,7 @@ void *sqlite3MallocRaw(int 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;
|
||||
}
|
||||
@ -339,7 +354,7 @@ void *sqlite3Realloc(void *p, int n){
|
||||
}
|
||||
p2 = realloc(p, n);
|
||||
if( p2==0 ){
|
||||
if( n>0 ) sqlite3_malloc_failed++;
|
||||
if( n>0 ) sqlite3Tsd()->mallocFailed++;
|
||||
}
|
||||
return p2;
|
||||
}
|
||||
@ -1007,3 +1022,18 @@ void *sqlite3TextToPtr(const char *z){
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
30
src/vacuum.c
30
src/vacuum.c
@ -14,7 +14,7 @@
|
||||
** 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"
|
||||
@ -170,7 +170,10 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
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));
|
||||
@ -284,6 +287,14 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@ -295,9 +306,18 @@ end_of_vacuum:
|
||||
** 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);
|
||||
|
20
src/vdbe.c
20
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.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"
|
||||
@ -394,7 +394,7 @@ int sqlite3VdbeExec(
|
||||
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;
|
||||
@ -405,7 +405,7 @@ int sqlite3VdbeExec(
|
||||
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();
|
||||
@ -1135,7 +1135,7 @@ case OP_Function: {
|
||||
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,
|
||||
@ -3113,7 +3113,10 @@ case OP_NewRowid: {
|
||||
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{
|
||||
@ -3893,9 +3896,14 @@ case OP_ParseSchema: { /* no-push */
|
||||
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;
|
||||
}
|
||||
@ -4433,7 +4441,7 @@ abort_due_to_misuse:
|
||||
*/
|
||||
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;
|
||||
|
@ -156,6 +156,8 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
|
||||
assert(!sqlite3Tsd()->mallocFailed);
|
||||
|
||||
if( p==0 || p->magic!=VDBE_MAGIC_RUN ){
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
@ -239,6 +241,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
#endif
|
||||
|
||||
sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
|
||||
sqlite3ClearMallocFailed();
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
|
||||
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];
|
||||
@ -301,7 +301,7 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
|
||||
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;
|
||||
@ -416,7 +416,9 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
|
||||
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 ){
|
||||
@ -734,7 +736,7 @@ void sqlite3VdbeMakeReady(
|
||||
+ 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];
|
||||
@ -884,7 +886,7 @@ int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){
|
||||
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 ){
|
||||
@ -1148,6 +1150,10 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
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 );
|
||||
@ -1158,7 +1164,8 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
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.
|
||||
@ -1169,11 +1176,50 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
}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 ){
|
||||
@ -1210,10 +1256,11 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
@ -1278,7 +1325,7 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
|
||||
/* 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");
|
||||
|
@ -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.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"
|
||||
|
||||
@ -567,7 +567,7 @@ static void exprAnalyze(
|
||||
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 );
|
||||
@ -1432,7 +1432,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** return value.
|
||||
*/
|
||||
pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
|
||||
if( sqlite3_malloc_failed ){
|
||||
if( sqlite3Tsd()->mallocFailed ){
|
||||
goto whereBeginNoMem;
|
||||
}
|
||||
pWInfo->pParse = pParse;
|
||||
@ -1456,7 +1456,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
createMask(&maskSet, pTabList->a[i].iCursor);
|
||||
}
|
||||
exprAnalyzeAll(pTabList, &maskSet, &wc);
|
||||
if( sqlite3_malloc_failed ){
|
||||
if( sqlite3Tsd()->mallocFailed ){
|
||||
goto whereBeginNoMem;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
# 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
|
||||
@ -22,7 +22,7 @@ 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
|
||||
}
|
||||
@ -52,12 +52,16 @@ if {[info command sqlite_malloc_stat]==""} {
|
||||
# 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}
|
||||
@ -66,6 +70,8 @@ proc do_malloc_test {tn args} {
|
||||
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)
|
||||
}
|
||||
@ -73,6 +79,9 @@ proc do_malloc_test {tn args} {
|
||||
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)]} {
|
||||
@ -81,7 +90,6 @@ proc do_malloc_test {tn args} {
|
||||
if {[info exists ::mallocopts(-sqlbody)]} {
|
||||
append ::mallocbody "db eval {$::mallocopts(-sqlbody)}"
|
||||
}
|
||||
|
||||
set v [catch $::mallocbody msg]
|
||||
|
||||
set leftover [lindex [sqlite_malloc_stat] 2]
|
||||
|
@ -11,7 +11,7 @@
|
||||
# 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
|
||||
@ -87,21 +87,30 @@ proc do_malloc2_test {tn args} {
|
||||
|
||||
# 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 {
|
||||
@ -264,79 +273,87 @@ do_test malloc2-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
|
||||
|
@ -13,7 +13,7 @@
|
||||
# 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
|
||||
@ -29,8 +29,6 @@
|
||||
# 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.
|
||||
#
|
||||
@ -38,7 +36,6 @@
|
||||
# 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
|
||||
|
@ -198,6 +198,7 @@ proc report {} {
|
||||
lappend summarymap($stack) $bytes
|
||||
}
|
||||
|
||||
set sorted [list]
|
||||
foreach stack [array names summarymap] {
|
||||
set allocs $summarymap($stack)
|
||||
set sum 0
|
||||
|
Loading…
Reference in New Issue
Block a user