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
This commit is contained in:
drh 2008-03-26 14:56:34 +00:00
parent 995ae279b3
commit 42165be18c
4 changed files with 89 additions and 12 deletions

View File

@ -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

View File

@ -1 +1 @@
72ae456239eb9f75b744f6733c4441b380bd1be1
3fafa562593b51d38f58e7a691c193d34a812a05

View File

@ -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; i<pTabList->nSrc; i++){
createMask(&maskSet, pTabList->a[i].iCursor);
}
#ifndef NDEBUG
{
Bitmask toTheLeft = 0;
for(i=0; i<pTabList->nSrc; 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; i<pTabList->nSrc; i++){
createMask(&maskSet, pTabList->a[i].iCursor);
}
exprAnalyzeAll(pTabList, &wc);
if( db->mallocFailed ){
goto whereBeginNoMem;

51
test/where6.test Normal file
View File

@ -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