diff --git a/manifest b/manifest index 61d269e41e..be88dfba80 100644 --- a/manifest +++ b/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 diff --git a/manifest.uuid b/manifest.uuid index 0ca22337b3..499c42cce6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -41a7aeeeb427d59e3d7cc71c94a8c5be832bd0fa \ No newline at end of file +e1606658f1b4530e3001db4779b5669c8d13c853 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index ff02c5dfcf..3b032678f0 100644 --- a/src/alter.c +++ b/src/alter.c @@ -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 @@ -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; diff --git a/src/attach.c b/src/attach.c index f548aa5eb3..d7d9ef824e 100644 --- a/src/attach.c +++ b/src/attach.c @@ -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: diff --git a/src/build.c b/src/build.c index fe86a86c89..78b7c3a1f3 100644 --- a/src/build.c +++ b/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 @@ -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; inSrc; 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; inSrc; 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); diff --git a/src/callback.c b/src/callback.c index 7884a81673..3b8acd3351 100644 --- a/src/callback.c +++ b/src/callback.c @@ -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); } } diff --git a/src/delete.c b/src/delete.c index 4f5b8a3f5b..75f10d1158 100644 --- a/src/delete.c +++ b/src/delete.c @@ -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; diff --git a/src/expr.c b/src/expr.c index 50edb902dc..be1f556d4f 100644 --- a/src/expr.c +++ b/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 @@ -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); } diff --git a/src/insert.c b/src/insert.c index 38d5cf1e3b..af5854df43 100644 --- a/src/insert.c +++ b/src/insert.c @@ -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); diff --git a/src/legacy.c b/src/legacy.c index a44af16ec3..4a3c2d248d 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -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 ){ diff --git a/src/main.c b/src/main.c index 4efdb39bf0..c2ab9df427 100644 --- a/src/main.c +++ b/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; inDb; 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 diff --git a/src/os_unix.c b/src/os_unix.c index 7074c546ec..3beaf3b910 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -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); } diff --git a/src/pager.c b/src/pager.c index 6583493ad2..813ccf8882 100644 --- a/src/pager.c +++ b/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 diff --git a/src/prepare.c b/src/prepare.c index b3222a82f7..4a9b2b1cef 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -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; } diff --git a/src/select.c b/src/select.c index 856ba881dc..b52fa2dfcb 100644 --- a/src/select.c +++ b/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. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 45070cbcf4..05a5b3abe5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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" diff --git a/src/test1.c b/src/test1.c index 3ae9d20fb5..d29346410f 100644 --- a/src/test1.c +++ b/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; } diff --git a/src/tokenize.c b/src/tokenize.c index 457de9abbc..45b12e4e78 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -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 ){ diff --git a/src/trigger.c b/src/trigger.c index 3da62decb0..cc5fc080e7 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -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; } diff --git a/src/update.c b/src/update.c index c5d4f036a1..5b5c2e9544 100644 --- a/src/update.c +++ b/src/update.c @@ -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 ); diff --git a/src/util.c b/src/util.c index 53b9773844..88924fbebb 100644 --- a/src/util.c +++ b/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 @@ -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; i0 ) 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; +} + + + diff --git a/src/vacuum.c b/src/vacuum.c index b0b1a6d516..13784c820f 100644 --- a/src/vacuum.c +++ b/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); diff --git a/src/vdbe.c b/src/vdbe.c index e4cba6c37f..7a178a2a4e 100644 --- a/src/vdbe.c +++ b/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 && pcnOp ); 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; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 4a5dc985f7..bc774b4f14 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -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; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 0c62c07d4b..3949087b75 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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; inOp; 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"); diff --git a/src/where.c b/src/where.c index ce94b102d5..d952d078fe 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.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; } diff --git a/test/malloc.test b/test/malloc.test index cdbf9f1f2b..31098310e8 100644 --- a/test/malloc.test +++ b/test/malloc.test @@ -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] diff --git a/test/malloc2.test b/test/malloc2.test index 51164872a0..bce5b0141c 100644 --- a/test/malloc2.test +++ b/test/malloc2.test @@ -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 diff --git a/test/schema.test b/test/schema.test index 76783b5102..1606f162d4 100644 --- a/test/schema.test +++ b/test/schema.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 diff --git a/tool/memleak3.tcl b/tool/memleak3.tcl index 2e3f43bc13..3c6e9b9c56 100644 --- a/tool/memleak3.tcl +++ b/tool/memleak3.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