Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** 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" /* @@ -2425,17 +2425,26 @@ sqlite3 *db, /* Report malloc errors here */ Select *p, /* SELECT statement in which to make substitutions */ 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); substExprList(db, p->pOrderBy, iTable, pEList); 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) */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* @@ -2716,21 +2725,35 @@ ** will scan expressions looking for iParent references and replace ** those references with expressions that resolve to the subquery FROM ** 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; for(i=(pSrc?1:0); i #include @@ -502,10 +502,15 @@ } 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; } return nErr; } Index: test/capi2.test ================================================================== --- test/capi2.test +++ test/capi2.test @@ -9,11 +9,11 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # -# $Id: capi2.test,v 1.35 2008/01/16 17:46:38 drh Exp $ +# $Id: capi2.test,v 1.36 2008/09/01 15:52:11 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -720,10 +720,11 @@ } [list {main tab1 col2} {main tab1 col1}] do_test capi2-12.4 { check_origins {SELECT b, a FROM (SELECT col1 AS a, col2 AS b FROM view1)} } [list {main tab1 col2} {main tab1 col1}] do_test capi2-12.5 { +breakpoint check_origins {SELECT (SELECT col2 FROM view1), (SELECT col1 FROM view1)} } [list {main tab1 col2} {main tab1 col1}] do_test capi2-12.6 { check_origins {SELECT (SELECT col2), (SELECT col1) FROM view1} } [list {main tab1 col2} {main tab1 col1}] ADDED test/tkt3346.test Index: test/tkt3346.test ================================================================== --- /dev/null +++ test/tkt3346.test @@ -0,0 +1,31 @@ +# 2008 September 1 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file implements regression tests for SQLite library. The +# focus of this file is testing the fix for ticket #3346 +# +# $Id: tkt3346.test,v 1.1 2008/09/01 15:52:11 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_test tkt3346-1.1 { + db eval { + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(2,'bob'); + INSERT INTO t1 VALUES(1,'alice'); + INSERT INTO t1 VALUES(3,'claire'); + SELECT *, ( SELECT y FROM (SELECT x.b='alice' AS y) ) + FROM ( SELECT * FROM t1 ) AS x; + } +} {2 bob 0 1 alice 1 3 claire 0} + +finish_test Index: test/where.test ================================================================== --- test/where.test +++ test/where.test @@ -1,6 +1,6 @@ -# 4 2001 September 15 +# 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. @@ -9,11 +9,11 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the use of indices in WHERE clases. # -# $Id: where.test,v 1.46 2008/07/15 00:27:35 drh Exp $ +# $Id: where.test,v 1.47 2008/09/01 15:52:11 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Build some test data