diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/select.c | 29 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/tokenize.c | 7 |
3 files changed, 35 insertions, 5 deletions
diff --git a/src/select.c b/src/select.c index 90611aa99..f616c1bd9 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.471 2008/08/26 12:56:14 drh Exp $ +** $Id: select.c,v 1.472 2008/09/01 15:52:11 drh Exp $ */ #include "sqliteInt.h" @@ -2427,6 +2427,9 @@ static void substSelect( int iTable, /* Table to be replaced */ ExprList *pEList /* Substitute values */ ){ + SrcList *pSrc; + struct SrcList_item *pItem; + int i; if( !p ) return; substExprList(db, p->pEList, iTable, pEList); substExprList(db, p->pGroupBy, iTable, pEList); @@ -2434,6 +2437,12 @@ static void substSelect( substExpr(db, p->pHaving, iTable, pEList); substExpr(db, p->pWhere, iTable, pEList); substSelect(db, p->pPrior, iTable, pEList); + pSrc = p->pSrc; + if( pSrc ){ + for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ + substSelect(db, pItem->pSelect, iTable, pEList); + } + } } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ @@ -2718,17 +2727,31 @@ static int flattenSubquery( ** elements we are now copying in. */ if( pSrc ){ + Table *pTabToDel; pSubitem = &pSrc->a[iFrom]; nSubSrc = pSubSrc->nSrc; jointype = pSubitem->jointype; - sqlite3DeleteTable(pSubitem->pTab); sqlite3DbFree(db, pSubitem->zDatabase); sqlite3DbFree(db, pSubitem->zName); sqlite3DbFree(db, pSubitem->zAlias); - pSubitem->pTab = 0; pSubitem->zDatabase = 0; pSubitem->zName = 0; pSubitem->zAlias = 0; + + /* If the FROM element is a subquery, defer deleting the Table + ** object associated with that subquery until code generation is + ** complete, since there may still exist Expr.pTab entires that + ** refer to the subquery even after flattening. Ticket #3346. + */ + if( (pTabToDel = pSubitem->pTab)!=0 ){ + if( pTabToDel->nRef==1 ){ + pTabToDel->pNextZombie = pParse->pZombieTab; + pParse->pZombieTab = pTabToDel; + }else{ + pTabToDel->nRef--; + } + } + pSubitem->pTab = 0; } if( nSubSrc!=1 || !pSrc ){ int extra = nSubSrc - 1; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 26971fb47..b581303f9 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.764 2008/08/29 18:42:30 rse Exp $ +** @(#) $Id: sqliteInt.h,v 1.765 2008/09/01 15:52:11 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -983,6 +983,7 @@ struct Table { char **azModuleArg; /* Text of all module args. [0] is module name */ #endif Schema *pSchema; /* Schema that contains this table */ + Table *pNextZombie; /* Next on the Parse.pZombieTab list */ }; /* @@ -1701,6 +1702,7 @@ struct Parse { Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif int nHeight; /* Expression tree height of current sub-select */ + Table *pZombieTab; /* List of Table objects to delete after code gen */ }; #ifdef SQLITE_OMIT_VIRTUALTABLE diff --git a/src/tokenize.c b/src/tokenize.c index 802c16397..9682cc206 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.151 2008/08/29 02:14:03 drh Exp $ +** $Id: tokenize.c,v 1.152 2008/09/01 15:52:11 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -504,6 +504,11 @@ abort_parse: sqlite3DeleteTrigger(db, pParse->pNewTrigger); sqlite3DbFree(db, pParse->apVarExpr); sqlite3DbFree(db, pParse->aAlias); + while( pParse->pZombieTab ){ + Table *p = pParse->pZombieTab; + pParse->pZombieTab = p->pNextZombie; + sqlite3DeleteTable(p); + } if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ pParse->rc = SQLITE_ERROR; } |