]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Reference count Table structures so that they are not deallocated too soon.
authordrh <drh@noemail.net>
Mon, 6 Jun 2005 21:19:56 +0000 (21:19 +0000)
committerdrh <drh@noemail.net>
Mon, 6 Jun 2005 21:19:56 +0000 (21:19 +0000)
Ticket #1210. (CVS 2498)

FossilOrigin-Name: e73d25c7419d580c47925494621df26d2fb9f27e

manifest
manifest.uuid
src/alter.c
src/build.c
src/delete.c
src/expr.c
src/select.c
src/sqliteInt.h
test/misc5.test

index eb95199fa75a6e27dafd47ac9d39a3f1c4f0ae81..409ff6a532c43d1aa45012e999be838172b31c0a 100644 (file)
--- 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
index 7c41719c5376eeae60785bd1f9e35b10735cf552..04b4759b395db6376ccfb2c9b87b457688710c1a 100644 (file)
@@ -1 +1 @@
-12c32f139bae3cb7ca520451bfc15f9f7d94833d
\ No newline at end of file
+e73d25c7419d580c47925494621df26d2fb9f27e
\ No newline at end of file
index f2d58affcfd456d23aa7589a606c29036869ef54..363af7a312f460bb3887632476f3698393eb1bea 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.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 <ctype.h>
@@ -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);
index 75ada684f28314a538738220c7179a09887f435a..a948e280cfbd4321b288188f0abb658aa339913a 100644 (file)
@@ -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 <ctype.h>
@@ -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);
index 308509e439cfe1fddf6bd5fb7bfa74888f13bc93..515842cd3c3e118ab300cba2ec089efb952a90c6 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.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; i<pSrc->nSrc; i++, pItem++){
     pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
+    sqlite3DeleteTable(pParse->db, pItem->pTab);
     pItem->pTab = pTab;
+    if( pTab ){
+      pTab->nRef++;
+    }
   }
   return pTab;
 }
index 5cfd280c7a0037ecf1a5005c61f79ea75aff3dc5..39d928ad4598f4f2f3a5f239bdda168f42533588 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.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 <ctype.h>
@@ -474,14 +474,15 @@ SrcList *sqlite3SrcListDup(SrcList *p){
   for(i=0; i<p->nSrc; 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);
index 37b4a0f74cc2ce352b97c8729d194f3c8a34b73d..f27db280adac49b1bb914affa0d4be95b053553a 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.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; i<pSrc->nSrc; 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);
index dc0cb75988c5d0cac8045787fa93503fc680691c..86a54d1e6495c019f57097fa11e746adffdf28e2 100644 (file)
@@ -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 */
index 5ffd08b3eda5c83d8414df42c7019e5baacb1a9f..20e8bdbdc1b197692fca3b498684297f14c71681 100644 (file)
@@ -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