aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/select.c29
-rw-r--r--src/sqliteInt.h4
-rw-r--r--src/tokenize.c7
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;
}