From: drh Date: Wed, 12 Sep 2007 15:41:01 +0000 (+0000) Subject: In the query optimizer, make sure table dependencies from all terms X-Git-Tag: version-3.6.10~1755 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a430ae8e54bc0f61b3398f81139f188fcfda915a;p=thirdparty%2Fsqlite.git In the query optimizer, make sure table dependencies from all terms of a compound SELECT statement are recognized so that subqueries in a WHERE clause are not evaluated too early. Fix for ticket #2640. (CVS 4422) FossilOrigin-Name: 9c9c2a1da2b6235b3b0541d1f55a02a1f350567f --- diff --git a/manifest b/manifest index 118ed4a850..98f7ef32db 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\smissing\ssemi-colon\sto\sos_win.c.\sTicket\s#2642.\s(CVS\s4421) -D 2007-09-12T14:09:23 +C In\sthe\squery\soptimizer,\smake\ssure\stable\sdependencies\sfrom\sall\sterms\nof\sa\scompound\sSELECT\sstatement\sare\srecognized\sso\sthat\ssubqueries\sin\na\sWHERE\sclause\sare\snot\sevaluated\stoo\searly.\s\sFix\sfor\sticket\s#2640.\s(CVS\s4422) +D 2007-09-12T15:41:01 F Makefile.in cbfb898945536a8f9ea8b897e1586dd1fdbcc5db F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -172,7 +172,7 @@ F src/vdbeblob.c 82f51cdf9b0c0af729732fde48c824e498c0a1ca F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 246d434fa60bde6553490eb686adfd86adcd6712 F src/vtab.c 6776605198e0b844391335f1b77e3595b3616331 -F src/where.c 4687a2a56bc0fe66ad457958ea9f72b6cae17426 +F src/where.c 1b3a67bba14cb19b44496090a66f58370b8c768d F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test b59d1bd8b0c1d4a08b845e8af48fd43926f01f11 @@ -456,6 +456,7 @@ F test/tkt2339.test 7016415bda86af1406a27260ac46f44885617606 F test/tkt2391.test ab7a11be7402da8b51a5be603425367aa0684567 F test/tkt2409.test f130054aedff681883466ad04332bd3f7db51a02 F test/tkt2450.test 77ed94863f2049c1420288ddfea2d41e5e0971d6 +F test/tkt2640.test c513e7992a602a87ef3a2cc9ca1cba4146924e9b F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567 F test/trans.test d132b8af1429a1e006bf4473de9a6e4c7f67a3f4 F test/trigger1.test b361161cf20614024cc1e52ea0bdec250776b2ae @@ -575,7 +576,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 4dbeb915b3138194abd5554b52003162235f9a5f -R 02383b5025ac23032b71caa8921229ac -U danielk1977 -Z 8ca913804fd51c8a1ac42ebd8d8ec287 +P c6ee5929e7d1f9b7c351f57ee8886f71ea0b6619 +R d30c1161749c146af96e8835cb148fe8 +U drh +Z 7de72dd4fad27cd8d1629bca893a1041 diff --git a/manifest.uuid b/manifest.uuid index dffb745686..623c5c09be 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c6ee5929e7d1f9b7c351f57ee8886f71ea0b6619 \ No newline at end of file +9c9c2a1da2b6235b3b0541d1f55a02a1f350567f \ No newline at end of file diff --git a/src/where.c b/src/where.c index a9a3c7594b..126b0847c4 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.259 2007/08/29 14:06:23 danielk1977 Exp $ +** $Id: where.c,v 1.260 2007/09/12 15:41:01 drh Exp $ */ #include "sqliteInt.h" @@ -350,15 +350,14 @@ static Bitmask exprListTableUsage(ExprMaskSet *pMaskSet, ExprList *pList){ return mask; } static Bitmask exprSelectTableUsage(ExprMaskSet *pMaskSet, Select *pS){ - Bitmask mask; - if( pS==0 ){ - mask = 0; - }else{ - mask = exprListTableUsage(pMaskSet, pS->pEList); + Bitmask mask = 0; + while( pS ){ + mask |= exprListTableUsage(pMaskSet, pS->pEList); mask |= exprListTableUsage(pMaskSet, pS->pGroupBy); mask |= exprListTableUsage(pMaskSet, pS->pOrderBy); mask |= exprTableUsage(pMaskSet, pS->pWhere); mask |= exprTableUsage(pMaskSet, pS->pHaving); + pS = pS->pPrior; } return mask; } diff --git a/test/tkt2640.test b/test/tkt2640.test new file mode 100644 index 0000000000..d2fa0e6092 --- /dev/null +++ b/test/tkt2640.test @@ -0,0 +1,119 @@ +# 2007 Sep 12 +# +# 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 is to test that ticket #2640 has been fixed. +# +# $Id: tkt2640.test,v 1.1 2007/09/12 15:41:01 drh Exp $ +# + +# The problem in ticket #2640 was that the query optimizer was +# not recognizing all uses of tables within subqueries in the +# WHERE clause. If the subquery contained a compound SELECT, +# then tables that were used by terms of the compound other than +# the last term would not be recognized as dependencies. +# So if one of the SELECT statements within a compound made +# use of a table that occurs later in a join, the query +# optimizer would not recognize this and would try to evaluate +# the subquery too early, before that tables value had been +# established. + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_test tkt2640-1.1 { + execsql { + CREATE TABLE persons(person_id, name); + INSERT INTO persons VALUES(1,'fred'); + INSERT INTO persons VALUES(2,'barney'); + INSERT INTO persons VALUES(3,'wilma'); + INSERT INTO persons VALUES(4,'pebbles'); + INSERT INTO persons VALUES(5,'bambam'); + CREATE TABLE directors(person_id); + INSERT INTO directors VALUES(5); + INSERT INTO directors VALUES(3); + CREATE TABLE writers(person_id); + INSERT INTO writers VALUES(2); + INSERT INTO writers VALUES(3); + INSERT INTO writers VALUES(4); + SELECT DISTINCT p.name + FROM persons p, directors d + WHERE d.person_id=p.person_id + AND NOT EXISTS ( + SELECT person_id FROM directors d1 WHERE d1.person_id=p.person_id + EXCEPT + SELECT person_id FROM writers w + ); + } +} {wilma} +do_test tkt2640-1.2 { + execsql { + SELECT DISTINCT p.name + FROM persons p CROSS JOIN directors d + WHERE d.person_id=p.person_id + AND NOT EXISTS ( + SELECT person_id FROM directors d1 WHERE d1.person_id=p.person_id + EXCEPT + SELECT person_id FROM writers w + ); + } +} {wilma} +do_test tkt2640-1.3 { + execsql { + SELECT DISTINCT p.name + FROM directors d CROSS JOIN persons p + WHERE d.person_id=p.person_id + AND NOT EXISTS ( + SELECT person_id FROM directors d1 WHERE d1.person_id=p.person_id + EXCEPT + SELECT person_id FROM writers w + ); + } +} {wilma} +do_test tkt2640-1.4 { + execsql { + SELECT DISTINCT p.name + FROM persons p, directors d + WHERE d.person_id=p.person_id + AND NOT EXISTS ( + SELECT person_id FROM directors d1 WHERE d1.person_id=d.person_id + EXCEPT + SELECT person_id FROM writers w + ); + } +} {wilma} +do_test tkt2640-1.5 { + execsql { + SELECT DISTINCT p.name + FROM persons p CROSS JOIN directors d + WHERE d.person_id=p.person_id + AND NOT EXISTS ( + SELECT person_id FROM directors d1 WHERE d1.person_id=d.person_id + EXCEPT + SELECT person_id FROM writers w + ); + } +} {wilma} +do_test tkt2640-1.6 { + execsql { + SELECT DISTINCT p.name + FROM directors d CROSS JOIN persons p + WHERE d.person_id=p.person_id + AND NOT EXISTS ( + SELECT person_id FROM directors d1 WHERE d1.person_id=d.person_id + EXCEPT + SELECT person_id FROM writers w + ); + } +} {wilma} + + + +finish_test