Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3fafa562593b51d38f58e7a691c193d3 |
User & Date: | drh 2008-03-26 14:56:35.000 |
Context
2008-03-26
| ||
15:56 | Change comment in sqliteLimit.h to correctly describe the SQLITE_MAX_ATTACHED #define. Ticket #3016. (CVS 4920) (check-in: d016d07840 user: drh tags: trunk) | |
14:56 | 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) (check-in: 3fafa56259 user: drh tags: trunk) | |
12:50 | Comment change on the previous check-in. No changes to code. (CVS 4918) (check-in: 72ae456239 user: drh tags: trunk) | |
Changes
Changes to src/where.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** 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.292 2008/03/26 14:56:35 drh Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) |
︙ | ︙ | |||
739 740 741 742 743 744 745 | }else if( op==TK_ISNULL ){ pTerm->prereqRight = 0; }else{ pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); } prereqAll = exprTableUsage(pMaskSet, pExpr); if( ExprHasProperty(pExpr, EP_FromJoin) ){ | | > > > | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 | }else if( op==TK_ISNULL ){ pTerm->prereqRight = 0; }else{ pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight); } prereqAll = exprTableUsage(pMaskSet, pExpr); if( ExprHasProperty(pExpr, EP_FromJoin) ){ 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; pTerm->iParent = -1; pTerm->eOperator = 0; if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ Expr *pLeft = pExpr->pLeft; |
︙ | ︙ | |||
2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 | /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){ sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL); pWhere = 0; } /* 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. */ | > > > > > > > > > > > > > > > > > > > > > > > > > < < < | 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 | /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){ sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL); 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. */ exprAnalyzeAll(pTabList, &wc); if( db->mallocFailed ){ goto whereBeginNoMem; } /* Chose the best index to use for each table in the FROM clause. ** |
︙ | ︙ |
Added test/where6.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 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 |