Reference count Table structures so that they are not deallocated too soon.
Ticket #1210. (CVS 2498) FossilOrigin-Name: e73d25c7419d580c47925494621df26d2fb9f27e
This commit is contained in:
parent
473d179d8a
commit
ed8a3bb108
24
manifest
24
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
|
||||
|
@ -1 +1 @@
|
||||
12c32f139bae3cb7ca520451bfc15f9f7d94833d
|
||||
e73d25c7419d580c47925494621df26d2fb9f27e
|
@ -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);
|
||||
|
14
src/build.c
14
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 <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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
45
src/select.c
45
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; 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);
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user