From 588a9a1a1cf1b4f577b30af675b1c1cc956fc24e Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Sep 2008 15:52:10 +0000 Subject: [PATCH] Defer deleting Table objects associated with flattened subqueries until all code has been generated, in case some expression node still references the Table object. Ticket #3346. (CVS 5650) FossilOrigin-Name: d04d70336727a0db959c672e6c22cdaa0505dce5 --- manifest | 23 ++++++++++++----------- manifest.uuid | 2 +- src/select.c | 29 ++++++++++++++++++++++++++--- src/sqliteInt.h | 4 +++- src/tokenize.c | 7 ++++++- test/capi2.test | 3 ++- test/tkt3346.test | 31 +++++++++++++++++++++++++++++++ test/where.test | 4 ++-- 8 files changed, 83 insertions(+), 20 deletions(-) create mode 100644 test/tkt3346.test diff --git a/manifest b/manifest index 089b8dfd81..a41983bc45 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Have\sthe\srtree\smodule\sset\sthe\sestimatedCost\soutput\svariable.\sTicket\s#3312.\s(CVS\s5649) -D 2008-09-01T12:47:00 +C Defer\sdeleting\sTable\sobjects\sassociated\swith\sflattened\ssubqueries\suntil\nall\scode\shas\sbeen\sgenerated,\sin\scase\ssome\sexpression\snode\sstill\sreferences\nthe\sTable\sobject.\s\sTicket\s#3346.\s(CVS\s5650) +D 2008-09-01T15:52:11 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 689e14735f862a5553bceef206d8c13e29504e44 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -145,11 +145,11 @@ F src/prepare.c c197041e0c4770672cda75e6bfe10242f885e510 F src/printf.c 785f87120589c1db672e37c6eb1087c456e6f84d F src/random.c 5c754319d38abdd6acd74601ee0105504adc508a F src/resolve.c a6abf83125bce0c80ba04acc27c3565155ad305c -F src/select.c 8187927315ee592a8ee94d753b8a1a3625c33523 +F src/select.c eec7c5f28a0c75fdd8500630435af176bba73219 F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967 F src/sqlite.h.in c0e84a2d6e9f3263599174ff7261ba6daf730b4f F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e -F src/sqliteInt.h e7f9e974763e93707ba4fe564b50744ba2a08658 +F src/sqliteInt.h 2243b0eadb5dd32de8f0a38571afedb711fa2cc5 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8 F src/status.c 8caa772cd9310bc297280f7cf0ede4d69ed5b801 F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8 @@ -180,7 +180,7 @@ F src/test_schema.c 4b4bf7bb329326458c491b0e6facd4c8c4c5b479 F src/test_server.c f0a403b5f699c09bd2b1236b6f69830fd6221f6b F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4 F src/test_thread.c d74fc445e0dba0e00806117eb449b307c0b146bf -F src/tokenize.c 76fe4cb8a606c24c76843ee2170cf84085f40817 +F src/tokenize.c aaa5fa6a4536a9dd7c855a3f66f32508f1612138 F src/trigger.c 649940b5bf5838a33721fb72372e7c9d1faf56a9 F src/update.c f2cf6f00d542956bd49ba4b9815c2900d9225bf2 F src/utf.c c63e6f69082f85c19ab88d62dedaf91d71ac1a50 @@ -229,7 +229,7 @@ F test/bitvec.test 62a512c3f7041d1df12558eb25990e5a19820571 F test/blob.test 2a38d867bdf08f9ce081776acec1ac8d4bca66be F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 3ff445c445742a7b6b9ba6e1d62a25263f9424b9 -F test/capi2.test cc64df7560a96f848f919ea2926c60acf639684b +F test/capi2.test 36f87803c811b5986dd31eb5492cb704552776b4 F test/capi3.test ffc1156d1f28738eb335df0b88dd294bb3c94c27 F test/capi3b.test 664eb55318132f292f2c436f90906f578cad6b97 F test/capi3c.test 208713e5f3a63442c3574c55b83baa7cf8ac5f28 @@ -555,6 +555,7 @@ F test/tkt3201.test 607d433ad2c1f6a8cb1af55aaca427f63c83191b F test/tkt3292.test 962465a0984a3b8c757efe59c2c59144871ee1dd F test/tkt3298.test a735582095ca2e90a0c1391c7e781a90de6c1f34 F test/tkt3334.test ea13a53cb176e90571a76c86605b14a09efe366d +F test/tkt3346.test 2f9a2be8621a87cbdb6283177dd419c7c46dd2a1 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 F test/trace.test 951cd0f5f571e7f36bf7bfe04be70f90fb16fb00 F test/trans.test 2fd24cd7aa0b879d49a224cbd647d698f1e7ac5c @@ -597,7 +598,7 @@ F test/vtabC.test 9f2d9eb84bf65e606d6616f20977c5a32a11f548 F test/vtab_alter.test 3a299749fee97ca3d53bd55717f536e4a2284856 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 F test/vtab_shared.test c19b2555b807ef2ee014c882cdda5bc8d84fcf48 -F test/where.test 4f1b9a403bba6855681eb7e7e9230e5decb67309 +F test/where.test ea8e56f3c7b18fa4d250d32a08ffab44c0ff64ba F test/where2.test 7012c0ad022a54430dd22c98288d3f4d6599dbcf F test/where3.test 97d3936e6a443b968f1a61cdcc0f673252000e94 F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2 @@ -628,7 +629,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P d68791e35d13f5ae4befeb0bb5f8ccaf14fd3763 -R cf8a1d32d459a4e4e9a02a25baa421e1 -U danielk1977 -Z d770b724d467b2bb63feddfe02dfb4bf +P 483932c4e08901a11b7ab671073fd0a048b10d66 +R 952afbcc44da7926eca4d46e950df9fb +U drh +Z a76eb0281ee8fa910a9148137fb4d127 diff --git a/manifest.uuid b/manifest.uuid index 6a60fbfb2e..642acf99f2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -483932c4e08901a11b7ab671073fd0a048b10d66 \ No newline at end of file +d04d70336727a0db959c672e6c22cdaa0505dce5 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 90611aa992..f616c1bd97 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 26971fb473..b581303f94 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 802c163973..9682cc2065 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 @@ -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; } diff --git a/test/capi2.test b/test/capi2.test index 147b234092..c6a65f38db 100644 --- a/test/capi2.test +++ b/test/capi2.test @@ -11,7 +11,7 @@ # 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] @@ -722,6 +722,7 @@ ifcapable view&&subquery { 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 { diff --git a/test/tkt3346.test b/test/tkt3346.test new file mode 100644 index 0000000000..46ec07f80e --- /dev/null +++ b/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 diff --git a/test/where.test b/test/where.test index 1213617376..06219f610f 100644 --- a/test/where.test +++ b/test/where.test @@ -1,4 +1,4 @@ -# 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: @@ -11,7 +11,7 @@ # 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