]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Some elements of the new malloc() failure handling. Not all cases work properly yet...
authordanielk1977 <danielk1977@noemail.net>
Tue, 6 Dec 2005 12:52:59 +0000 (12:52 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Tue, 6 Dec 2005 12:52:59 +0000 (12:52 +0000)
FossilOrigin-Name: e1606658f1b4530e3001db4779b5669c8d13c853

30 files changed:
manifest
manifest.uuid
src/alter.c
src/attach.c
src/build.c
src/callback.c
src/delete.c
src/expr.c
src/insert.c
src/legacy.c
src/main.c
src/os_unix.c
src/pager.c
src/prepare.c
src/select.c
src/sqliteInt.h
src/test1.c
src/tokenize.c
src/trigger.c
src/update.c
src/util.c
src/vacuum.c
src/vdbe.c
src/vdbeapi.c
src/vdbeaux.c
src/where.c
test/malloc.test
test/malloc2.test
test/schema.test
tool/memleak3.tcl

index 61d269e41e0e79377b75a65ecb044c0c2cb40145..be88dfba8091c990e582842382e3f01a3835b7cc 100644 (file)
--- 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
index 0ca22337b3d055eb29ae6a25d4c56df53c518bd2..499c42cce618670057a800e0c0dc16fbe8d252c0 100644 (file)
@@ -1 +1 @@
-41a7aeeeb427d59e3d7cc71c94a8c5be832bd0fa
\ No newline at end of file
+e1606658f1b4530e3001db4779b5669c8d13c853
\ No newline at end of file
index ff02c5dfcf8f6bf4613c21aa115f66bb15f70220..3b032678f02e0865af375b3d3a6573d5bea90b7d 100644 (file)
@@ -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;
 
index f548aa5eb392bbccb3bc6713dacc45c2ec924498..d7d9ef824effe75627321d7936fa2f20b8e5a7b7 100644 (file)
@@ -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:
index fe86a86c8915c87e45aabfea11c787387e28bda3..78b7c3a1f3aee859d0878451cbeac1cc45282cd8 100644 (file)
@@ -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);
index 7884a816734b3a01538ee18cb72e742d3eb9324b..3b8acd335190b8a1ac538e301fae29679292019e 100644 (file)
@@ -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);
     }
   }
index 4f5b8a3f5b9f0b19e17cce635c224a2836f3ad48..75f10d1158787a1281ffd4ebbc06febe1f878b87 100644 (file)
@@ -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;
index 50edb902dcbda3a8e31136b12c1a7e75bc1e61bd..be1f556d4ff9a79f18b49a5e0eda0052a2a75789 100644 (file)
@@ -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);
   }
 
index 38d5cf1e3b177b4f33ceb8d7872ca393b4bd87ad..af5854df437a64ac3117b81f8ef8d75f0b93a9ee 100644 (file)
@@ -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);
index a44af16ec31552b5cb20895a1d9cf5f62fdff1b9..4a3c2d248d2a9f192c21073e5700d2c8bc6c40dd 100644 (file)
@@ -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 ){
index 4efdb39bf0f8320ffd978ee5f8074d813ba94d74..c2ab9df427ffc221713696aab3d0a324825b51f3 100644 (file)
@@ -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
 
index 7074c546ecfdcaa2debfe51ab43546d0a47e9e55..3beaf3b910f270f7f3e4ddae3ae02768b8d1a9ec 100644 (file)
@@ -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);
 }
 
index 6583493ad263cbd555b551a4ddd7025c70604b6d..813ccf888244d906ada334961b1fa25ed149bf4d 100644 (file)
@@ -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
index b3222a82f7b65270018248939b8636d4eb4ac0b5..4a9b2b1cef9ec47de50bc8fd99cc920bb3d11753 100644 (file)
@@ -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;
 }
 
index 856ba881dcaafce078806a910f104a4814a0128a..b52fa2dfcb1086583ccb320450ce40c5f7afea4f 100644 (file)
@@ -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.
index 45070cbcf411c3d6f6d58675928a1175191f50ee..05a5b3abe5a2e5492ea5b28d27e72c2eda8cff29 100644 (file)
@@ -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"
index 3ae9d20fb5b5d1e60494fa0f2ace88b0b5c2fcad..d29346410f40de6085a4ad0682678e306ed930e2 100644 (file)
@@ -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;
 }
 
index 457de9abbc71dc5eb246be18cdcba5ca77151c6d..45b12e4e7866fb6e651ce05bb68aaff77ba6f079 100644 (file)
@@ -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 ){
index 3da62decb03aee4dd2a19798303282a1bedde294..cc5fc080e77b567fd2bf9f80d30264a95fdfea3f 100644 (file)
@@ -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;
   }
index c5d4f036a1ff27482d7d6fec53d22e23482c6e66..5b5c2e9544eb5cbe517a6da52b366a29c3f18d3a 100644 (file)
@@ -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 );
 
index 53b97738448a53171e6cdd2d569ce970e30e6855..88924fbebbe945f75b60c031c5a06177010bfae2 100644 (file)
@@ -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;
+}
+
+
+
index b0b1a6d5168f14259ba75a1e814e83b6909bca0c..13784c820f3cd2a4ce4da84c49886ba7d98fd809 100644 (file)
@@ -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);
index e4cba6c37fd09ada6794d6c4c1c0adca6a9ad5c8..7a178a2a4ecab7dea403a16b71f011204640c379 100644 (file)
@@ -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;
index 4a5dc985f7bf346db0f498e7766eaefd92a64312..bc774b4f143cc8e0d14906f3f403d5d233995263 100644 (file)
@@ -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;
 }
 
index 0c62c07d4b260e92bc31ca349cf2bff4289dfc85..3949087b7567f96cc95775400c070a465bc4740f 100644 (file)
@@ -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");
index ce94b102d5bba872c2ecff395a3e197af2730f8e..d952d078feb054ef28379c71a1b2b1ff812b05fa 100644 (file)
@@ -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;
   }
 
index cdbf9f1f2ba438c36a601ab02ff1ab58b4f3d9b1..31098310e8cb339b387c30922754ea8b1882c31b 100644 (file)
@@ -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]
index 51164872a0f1b164dca15da2b7969e9b24175f1c..bce5b0141c57f6c7886e5e351f7297b49714f42e 100644 (file)
@@ -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
index 76783b510230dde16aabf20653248244968e869f..1606f162d4a1833bde26d8bf5ecdb87234f51de7 100644 (file)
@@ -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
index 2e3f43bc13673145ff23d8f7f0570840f1ae4479..3c6e9b9c562641b4bec09244a097cb8d06dc96c9 100644 (file)
@@ -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