From: drh Date: Wed, 26 Mar 2008 14:56:34 +0000 (+0000) Subject: Make sure ON clause terms of a LEFT JOIN are not used with an index on the X-Git-Tag: version-3.6.10~1258 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42165be18c00e0d328dc2c2123da3dbbbc693c5e;p=thirdparty%2Fsqlite.git Make sure ON clause terms of a LEFT JOIN are not used with an index on the right table of the join. Ticket #3015. (CVS 4919) FossilOrigin-Name: 3fafa562593b51d38f58e7a691c193d34a812a05 --- diff --git a/manifest b/manifest index 5df67c98ec..5af571e160 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Comment\schange\son\sthe\sprevious\scheck-in.\s\sNo\schanges\sto\scode.\s(CVS\s4918) -D 2008-03-26T12:50:15 +C Make\ssure\sON\sclause\sterms\sof\sa\sLEFT\sJOIN\sare\snot\sused\swith\san\sindex\son\sthe\nright\stable\sof\sthe\sjoin.\s\sTicket\s#3015.\s(CVS\s4919) +D 2008-03-26T14:56:35 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -183,7 +183,7 @@ F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736 F src/vdbemem.c d48a71d66a7afd564b6537ab7e7442f7729fa5af F src/vtab.c 00cd16317b29495c185ff40e4b227917d5a371b2 -F src/where.c f18bac2f87c965811727be1be05deeaf5229fcd0 +F src/where.c 7aeeec6731dc2f423e6a77ff2964bc3c38985625 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test d12210212bada2bde6d5aeb90969b86c1aa977d2 @@ -537,6 +537,7 @@ F test/where2.test 7012c0ad022a54430dd22c98288d3f4d6599dbcf F test/where3.test 0a30fe9808b0fa01c46d0fcf4fac0bf6cf75bb30 F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 +F test/where6.test 81e93cc92f08379f4ade484956c0be622b72bda3 F test/zeroblob.test 7d1854ea79d048e023e5f2e38106a7e99a17435c F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439 @@ -617,7 +618,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 50de87dc808820a70d3a99277f532e418a2f97e2 -R a9214388e1bd4f84433e05f4820411e2 +P 72ae456239eb9f75b744f6733c4441b380bd1be1 +R 9d9078dbdb76203a989a8fc288298d2a U drh -Z 2631d714b3b1ed6116e6910f891b739c +Z 23ccaa57eab8690967dced96f6c90551 diff --git a/manifest.uuid b/manifest.uuid index 86a7964cd3..795685831a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -72ae456239eb9f75b744f6733c4441b380bd1be1 \ No newline at end of file +3fafa562593b51d38f58e7a691c193d34a812a05 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 71bc51bc4e..49c76fe0c7 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.291 2008/03/25 09:47:35 danielk1977 Exp $ +** $Id: where.c,v 1.292 2008/03/26 14:56:35 drh Exp $ */ #include "sqliteInt.h" @@ -743,7 +743,10 @@ static void exprAnalyze( } prereqAll = exprTableUsage(pMaskSet, pExpr); if( ExprHasProperty(pExpr, EP_FromJoin) ){ - prereqAll |= getMask(pMaskSet, pExpr->iRightJoinTable); + Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable); + prereqAll |= x; + pTerm->prereqRight |= x-1; /* ON clause terms may not be used with an index + ** on left table of a LEFT JOIN. Ticket #3015 */ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; @@ -2043,14 +2046,36 @@ WhereInfo *sqlite3WhereBegin( pWhere = 0; } + /* Assign a bit from the bitmask to every term in the FROM clause. + ** + ** When assigning bitmask values to FROM clause cursors, it must be + ** the case that if X is the bitmask for the N-th FROM clause term then + ** the bitmask for all FROM clause terms to the left of the N-th term + ** is (X-1). An expression from the ON clause of a LEFT JOIN can use + ** its Expr.iRightJoinTable value to find the bitmask of the right table + ** of the join. Subtracting one from the right table bitmask gives a + ** bitmask for all tables to the left of the join. Knowing the bitmask + ** for all tables to the left of a left join is important. Ticket #3015. + */ + for(i=0; inSrc; i++){ + createMask(&maskSet, pTabList->a[i].iCursor); + } +#ifndef NDEBUG + { + Bitmask toTheLeft = 0; + for(i=0; inSrc; i++){ + Bitmask m = getMask(&maskSet, pTabList->a[i].iCursor); + assert( (m-1)==toTheLeft ); + toTheLeft |= m; + } + } +#endif + /* Analyze all of the subexpressions. Note that exprAnalyze() might ** add new virtual terms onto the end of the WHERE clause. We do not ** want to analyze these virtual terms, so start analyzing at the end ** and work forward so that the added virtual terms are never processed. */ - for(i=0; inSrc; i++){ - createMask(&maskSet, pTabList->a[i].iCursor); - } exprAnalyzeAll(pTabList, &wc); if( db->mallocFailed ){ goto whereBeginNoMem; diff --git a/test/where6.test b/test/where6.test new file mode 100644 index 0000000000..2e803b17aa --- /dev/null +++ b/test/where6.test @@ -0,0 +1,51 @@ +# 2007 June 8 +# +# 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 that terms in the ON clause of +# a LEFT OUTER JOIN are not used with indices. See ticket #3015. +# +# $Id: where6.test,v 1.1 2008/03/26 14:56:35 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Build some test data +# +do_test where6-1.0 { + execsql { + CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c); + INSERT INTO t1 VALUES(1,3,1); + INSERT INTO t1 VALUES(2,4,2); + CREATE TABLE t2(x INTEGER PRIMARY KEY); + INSERT INTO t2 VALUES(3); + + SELECT * FROM t1 LEFT JOIN t2 ON b=x AND c=1; + } +} {1 3 1 3 2 4 2 {}} +do_test where6-1.1 { + execsql { + SELECT * FROM t1 LEFT JOIN t2 ON b=x WHERE c=1; + } +} {1 3 1 3} +do_test where6-1.2 { + execsql { + CREATE INDEX i1 ON t1(c); + + SELECT * FROM t1 LEFT JOIN t2 ON b=x AND c=1; + } +} {1 3 1 3 2 4 2 {}} +do_test where6-1.3 { + execsql { + SELECT * FROM t1 LEFT JOIN t2 ON b=x WHERE c=1; + } +} {1 3 1 3} + +finish_test