Reference count Table structures so that they are not deallocated too soon.

Ticket #1210. (CVS 2498)

FossilOrigin-Name: e73d25c7419d580c47925494621df26d2fb9f27e
This commit is contained in:
drh 2005-06-06 21:19:56 +00:00
parent 473d179d8a
commit ed8a3bb108
9 changed files with 79 additions and 64 deletions

View File

@ -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

View File

@ -1 +1 @@
12c32f139bae3cb7ca520451bfc15f9f7d94833d
e73d25c7419d580c47925494621df26d2fb9f27e

View 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);

View 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);

View 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;
}

View 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);

View 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);

View 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 */

View 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