From: drh Date: Mon, 6 Jun 2005 21:19:56 +0000 (+0000) Subject: Reference count Table structures so that they are not deallocated too soon. X-Git-Tag: version-3.6.10~3661 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ed8a3bb1088b058fc9f7b7b2e7ca51d9cae13281;p=thirdparty%2Fsqlite.git Reference count Table structures so that they are not deallocated too soon. Ticket #1210. (CVS 2498) FossilOrigin-Name: e73d25c7419d580c47925494621df26d2fb9f27e --- diff --git a/manifest b/manifest index eb95199fa7..409ff6a532 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Return\sSQLITE_MISUSE\swhen\spassing\sa\sNULL\spointer\sinto\ssqlite3_bind\sroutines.\nTicket\s#1219.\s(CVS\s2497) -D 2005-06-06T17:54:56 +C Reference\scount\sTable\sstructures\sso\sthat\sthey\sare\snot\sdeallocated\stoo\ssoon.\nTicket\s#1210.\s(CVS\s2498) +D 2005-06-06T21:19:57 F Makefile.in 8129e7f261d405db783676f9ca31e0841768c652 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -27,17 +27,17 @@ F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def dbaeb20c153e1d366e8f421b55a573f5dfc00863 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a -F src/alter.c 9570af388bc99471ea6e1258817fbf06e3120030 +F src/alter.c 03041f2464e22532601254f87cb49997fa21dcdf F src/attach.c 3615dbe960cbee4aa5ea300b8a213dad36527b0f F src/auth.c 18c5a0befe20f3a58a41e3ddd78f372faeeefe1f F src/btree.c d2e09ebf755bfd665727133361b22c6a915b12d7 F src/btree.h 41a71ce027db9ddee72cb43df2316bbe3a1d92af -F src/build.c bea3107e3bfb7da534d60b1fa39b9fb1d100f6e3 +F src/build.c 407343b7dac62f7ea44f166943708f6557906ae1 F src/callback.c 0910b611e0c158f107ee3ff86f8a371654971e2b F src/date.c 2134ef4388256e8247405178df8a61bd60dc180a -F src/delete.c 75b53db21aa1879d3655bbbc208007db31d58a63 +F src/delete.c 811f90d1c5950e57f985fc9d207d7eee1800096e F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d -F src/expr.c e2aec43eda9d5f8cf6a7eb3adee59ec913effed7 +F src/expr.c e7245e9c3b1f890221cf5e7472c1aa1fed30d7ab F src/func.c f208d71f741d47b63277530939f552815af8ce35 F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 @@ -60,10 +60,10 @@ F src/pragma.c 0ed94a1aa982802a9cf2a932c48d99b60683fa53 F src/prepare.c d53602d2f8e097225ae7c76ec764ae68f759ba47 F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 -F src/select.c a057b1bb71ca2db3939e35994e16b718a83c93bf +F src/select.c ce4b9fd78d57693e756e8e51e9c7aa098c1508bb F src/shell.c 25b3217d7c64e6497225439d261a253a23efff26 F src/sqlite.h.in f28f5b018f03a66aaf0bc1ab6985d8605d6b964f -F src/sqliteInt.h 0aa1d1bd6f34db3955d8615b18b20426cfd15acc +F src/sqliteInt.h 42b464cd380dd81bf7873476fc5974985a506d71 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/tclsqlite.c af0f002d9d6ab4f7f32b9bee5b57665946e76ad9 F src/test1.c e9c26134a1c5f6de540dc604d70ac851dd5f6493 @@ -165,7 +165,7 @@ F test/misc1.test a4a36c19f05e4c8646efe7a0d7242ba645d07379 F test/misc2.test 5c699af2fede2694736a9f45aea7e2f052686e15 F test/misc3.test 7bd937e2c62bcc6be71939faf068d506467b1e03 F test/misc4.test edd3e3adf5b6e3b995b29843565ca58dd602f9a7 -F test/misc5.test 5158e1be2c878af42b60f99d963001e4cae309fc +F test/misc5.test a61df275d21516c87f6bb26f22766fda3b0f44a3 F test/misuse.test 1c7fee3c4c0cb4008717ecccf5c72281fac0008e F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0 F test/null.test 69c62daf1630bf54c87bbc7ef2e22012e58d6da8 @@ -281,7 +281,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b -P 0f7af623791d8d2ed35c3978ab12316912d9b6f8 -R 715394bbb98151a036e69d3628c59f03 +P 12c32f139bae3cb7ca520451bfc15f9f7d94833d +R e390bfee5cfa27b3e5512a8098188123 U drh -Z a809cb5efd2b91b9249be96f667899b8 +Z c771356a4d5670d2ac2c478ca19855b4 diff --git a/manifest.uuid b/manifest.uuid index 7c41719c53..04b4759b39 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -12c32f139bae3cb7ca520451bfc15f9f7d94833d \ No newline at end of file +e73d25c7419d580c47925494621df26d2fb9f27e \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index f2d58affcf..363af7a312 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.6 2005/03/28 00:07:16 danielk1977 Exp $ +** $Id: alter.c,v 1.7 2005/06/06 21:19:57 drh Exp $ */ #include "sqliteInt.h" #include @@ -538,6 +538,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ } pNew->iDb = iDb; pNew->addColOffset = pTab->addColOffset; + pNew->nRef = 1; /* Begin a transaction and increment the schema cookie. */ sqlite3BeginWriteOperation(pParse, 0, iDb); diff --git a/src/build.c b/src/build.c index 75ada684f2..a948e280cf 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.324 2005/06/06 15:32:08 drh Exp $ +** $Id: build.c,v 1.325 2005/06/06 21:19:57 drh Exp $ */ #include "sqliteInt.h" #include @@ -427,6 +427,13 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ if( pTable==0 ) return; + /* Do not delete the table until the reference count reaches zero. */ + pTable->nRef--; + if( pTable->nRef>0 ){ + return; + } + assert( pTable->nRef==0 ); + /* Delete all indices associated with this table */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ @@ -729,6 +736,7 @@ void sqlite3StartTable( pTable->iPKey = -1; pTable->pIndex = 0; pTable->iDb = iDb; + pTable->nRef = 1; if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; @@ -2585,9 +2593,7 @@ void sqlite3SrcListDelete(SrcList *pList){ sqliteFree(pItem->zDatabase); sqliteFree(pItem->zName); sqliteFree(pItem->zAlias); - if( pItem->pTab && pItem->pTab->isTransient ){ - sqlite3DeleteTable(0, pItem->pTab); - } + sqlite3DeleteTable(0, pItem->pTab); sqlite3SelectDelete(pItem->pSelect); sqlite3ExprDelete(pItem->pOn); sqlite3IdListDelete(pItem->pUsing); diff --git a/src/delete.c b/src/delete.c index 308509e439..515842cd3c 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.104 2005/04/22 02:38:38 drh Exp $ +** $Id: delete.c,v 1.105 2005/06/06 21:19:57 drh Exp $ */ #include "sqliteInt.h" @@ -27,7 +27,11 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ struct SrcList_item *pItem; for(i=0, pItem=pSrc->a; inSrc; i++, pItem++){ pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); + sqlite3DeleteTable(pParse->db, pItem->pTab); pItem->pTab = pTab; + if( pTab ){ + pTab->nRef++; + } } return pTab; } diff --git a/src/expr.c b/src/expr.c index 5cfd280c7a..39d928ad45 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.204 2005/06/06 17:11:46 drh Exp $ +** $Id: expr.c,v 1.205 2005/06/06 21:19:57 drh Exp $ */ #include "sqliteInt.h" #include @@ -474,14 +474,15 @@ SrcList *sqlite3SrcListDup(SrcList *p){ for(i=0; inSrc; i++){ struct SrcList_item *pNewItem = &pNew->a[i]; struct SrcList_item *pOldItem = &p->a[i]; + Table *pTab; pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; - pNewItem->pTab = pOldItem->pTab; - if( pNewItem->pTab ){ - pNewItem->pTab->isTransient = 0; + pTab = pNewItem->pTab = pOldItem->pTab; + if( pTab ){ + pTab->nRef++; } pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect); pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn); diff --git a/src/select.c b/src/select.c index 37b4a0f74c..f27db280ad 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.249 2005/06/06 16:34:33 drh Exp $ +** $Id: select.c,v 1.250 2005/06/06 21:19:57 drh Exp $ */ #include "sqliteInt.h" @@ -872,6 +872,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ if( pTab==0 ){ return 0; } + pTab->nRef = 1; pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0; pEList = pSelect->pEList; pTab->nCol = pEList->nExpr; @@ -1004,6 +1005,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){ pFrom->zAlias = sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect); } + assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); if( pTab==0 ){ @@ -1017,11 +1019,13 @@ static int prepSelectStmt(Parse *pParse, Select *p){ #endif }else{ /* An ordinary table or view name in the FROM clause */ + assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); if( pTab==0 ){ return 1; } + pTab->nRef++; #ifndef SQLITE_OMIT_VIEW if( pTab->pSelect ){ /* We reach here if the named table is a really a view */ @@ -1164,40 +1168,6 @@ static int prepSelectStmt(Parse *pParse, Select *p){ return rc; } -/* -** This routine recursively unlinks the Select.pSrc.a[].pTab pointers -** in a select structure. It just sets the pointers to NULL. This -** routine is recursive in the sense that if the Select.pSrc.a[].pSelect -** pointer is not NULL, this routine is called recursively on that pointer. -** -** This routine is called on the Select structure that defines a -** VIEW in order to undo any bindings to tables. This is necessary -** because those tables might be DROPed by a subsequent SQL command. -** If the bindings are not removed, then the Select.pSrc->a[].pTab field -** will be left pointing to a deallocated Table structure after the -** DROP and a coredump will occur the next time the VIEW is used. -*/ -#if 0 -void sqlite3SelectUnbind(Select *p){ - int i; - SrcList *pSrc = p->pSrc; - struct SrcList_item *pItem; - Table *pTab; - if( p==0 ) return; - for(i=0, pItem=pSrc->a; inSrc; i++, pItem++){ - if( (pTab = pItem->pTab)!=0 ){ - if( pTab->isTransient ){ - sqlite3DeleteTable(0, pTab); - } - pItem->pTab = 0; - if( pItem->pSelect ){ - sqlite3SelectUnbind(pItem->pSelect); - } - } - } -} -#endif - #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** This routine associates entries in an ORDER BY expression list with @@ -2048,11 +2018,8 @@ static int flattenSubquery( { int nSubSrc = pSubSrc->nSrc; int jointype = pSubitem->jointype; - Table *pTab = pSubitem->pTab; - if( pTab && pTab->isTransient ){ - sqlite3DeleteTable(0, pSubitem->pTab); - } + sqlite3DeleteTable(0, pSubitem->pTab); sqliteFree(pSubitem->zDatabase); sqliteFree(pSubitem->zName); sqliteFree(pSubitem->zAlias); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index dc0cb75988..86a54d1e64 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.385 2005/06/06 15:06:39 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.386 2005/06/06 21:19:57 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -607,6 +607,7 @@ struct Table { u8 hasPrimKey; /* True if there exists a primary key */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ u8 autoInc; /* True if the integer primary key is autoincrement */ + int nRef; /* Number of pointers to this Table */ Trigger *pTrigger; /* List of SQL triggers on this table */ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ diff --git a/test/misc5.test b/test/misc5.test index 5ffd08b3ed..20e8bdbdc1 100644 --- a/test/misc5.test +++ b/test/misc5.test @@ -13,7 +13,7 @@ # This file implements tests for miscellanous features that were # left out of other test files. # -# $Id: misc5.test,v 1.2 2005/04/15 12:04:34 drh Exp $ +# $Id: misc5.test,v 1.3 2005/06/06 21:19:58 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -436,6 +436,41 @@ do_test misc5-2.2 { 4611686018427387904\ 4611686018427387905" +# Ticket #1210. Do proper reference counting of Table structures +# so that deeply nested SELECT statements can be flattened correctly. +# +do_test misc5-3.1 { + execsql { + CREATE TABLE songs(songid, artist, timesplayed); + INSERT INTO songs VALUES(1,'one',1); + INSERT INTO songs VALUES(2,'one',2); + INSERT INTO songs VALUES(3,'two',3); + INSERT INTO songs VALUES(4,'three',5); + INSERT INTO songs VALUES(5,'one',7); + INSERT INTO songs VALUES(6,'two',11); + SELECT DISTINCT artist + FROM ( + SELECT DISTINCT artist + FROM songs + WHERE songid IN ( + SELECT songid + FROM songs + WHERE LOWER(artist) = ( + SELECT DISTINCT LOWER(artist) + FROM ( + SELECT DISTINCT artist,sum(timesplayed) AS total + FROM songs + GROUP BY LOWER(artist) + ORDER BY total DESC + LIMIT 10 + ) + WHERE artist <> '' + ) + ) + ) + ORDER BY LOWER(artist) ASC; + } +} {two} finish_test