mirror of https://github.com/sqlite/sqlite
Clarification of the operation of the OR-term optimizer in where.c. (CVS 6730)
FossilOrigin-Name: 6b42dc3d04e98f91c203c277926ed6ead62a9270
This commit is contained in:
parent
a50d9aa784
commit
4e8be3bb5d
14
manifest
14
manifest
|
@ -1,5 +1,5 @@
|
|||
C Change\sthe\sbtree\sbalance\scode\sso\sthat\sit\sdoes\snot\scall\sbalance_nonroot()\srecursively.\s(CVS\s6729)
|
||||
D 2009-06-08T14:49:46
|
||||
C Clarification\sof\sthe\soperation\sof\sthe\sOR-term\soptimizer\sin\swhere.c.\s(CVS\s6730)
|
||||
D 2009-06-08T17:11:08
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 8b8fb7823264331210cddf103831816c286ba446
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
|
@ -212,7 +212,7 @@ F src/vdbeblob.c c25d7e7bc6d5917feeb17270bd275fa771f26e5c
|
|||
F src/vdbemem.c 05183d46094aa99b8f8350e5761b9369dbef35a8
|
||||
F src/vtab.c e2f4c92df7d06330b151448718c4724742ff444b
|
||||
F src/walker.c ec4b9742a4077ef80346e2f9aaf0f44c2d95087a
|
||||
F src/where.c 01b8d4733f177f047014c0b391b4ecbcc867dfd8
|
||||
F src/where.c 21555aa8b48345f5a1c706cf8ca485012f2cea03
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
|
||||
|
@ -733,7 +733,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
|||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746
|
||||
P 456ea541d67221a573b63e264c83f4448f2ed569
|
||||
R 7ada04c9a78d367df09e91faed8b31d8
|
||||
U danielk1977
|
||||
Z 47cd44a7ec9eea431d4519541126ee12
|
||||
P 7863db904d6fc36417c923e3d135eb2c145b9013
|
||||
R 6ef9e53cd5ad2b3cbcbea9afea1bc9a7
|
||||
U drh
|
||||
Z aebb118da6ff464bb9146e5d93538e1c
|
||||
|
|
|
@ -1 +1 @@
|
|||
7863db904d6fc36417c923e3d135eb2c145b9013
|
||||
6b42dc3d04e98f91c203c277926ed6ead62a9270
|
44
src/where.c
44
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.402 2009/06/07 23:45:11 drh Exp $
|
||||
** $Id: where.c,v 1.403 2009/06/08 17:11:08 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
@ -892,6 +892,22 @@ static void exprAnalyzeOrTerm(
|
|||
** chngToIN holds a set of tables that *might* satisfy case 1. But
|
||||
** we have to do some additional checking to see if case 1 really
|
||||
** is satisfied.
|
||||
**
|
||||
** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means
|
||||
** that there is no possibility of transforming the OR clause into an
|
||||
** IN operator because one or more terms in the OR clause contain
|
||||
** something other than == on a column in the single table. The 1-bit
|
||||
** case means that every term of the OR clause is of the form
|
||||
** "table.column=expr" for some single table. The one bit that is set
|
||||
** will correspond to the common table. We still need to check to make
|
||||
** sure the same column is used on all terms. The 2-bit case is when
|
||||
** the all terms are of the form "table1.column=table2.column". It
|
||||
** might be possible to form an IN operator with either table1.column
|
||||
** or table2.column as the LHS if either is common to every term of
|
||||
** the OR clause.
|
||||
**
|
||||
** Note that terms of the form "table.column1=table.column2" (the
|
||||
** same table on both sizes of the ==) cannot be optimized.
|
||||
*/
|
||||
if( chngToIN ){
|
||||
int okToChngToIN = 0; /* True if the conversion to IN is valid */
|
||||
|
@ -910,18 +926,38 @@ static void exprAnalyzeOrTerm(
|
|||
for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
|
||||
assert( pOrTerm->eOperator==WO_EQ );
|
||||
pOrTerm->wtFlags &= ~TERM_OR_OK;
|
||||
if( pOrTerm->leftCursor==iColumn ) continue;
|
||||
if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ) continue;
|
||||
if( pOrTerm->leftCursor==iCursor ){
|
||||
/* This is the 2-bit case and we are on the second iteration and
|
||||
** current term is from the first iteration. So skip this term. */
|
||||
assert( j==1 );
|
||||
continue;
|
||||
}
|
||||
if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){
|
||||
/* This term must be of the form t1.a==t2.b where t2 is in the
|
||||
** chngToIN set but t1 is not. This term will be either preceeded
|
||||
** or follwed by an inverted copy (t2.b==t1.a). Skip this term
|
||||
** and use its inversion. */
|
||||
testcase( pOrTerm->wtFlags & TERM_COPIED );
|
||||
testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
|
||||
assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
|
||||
continue;
|
||||
}
|
||||
iColumn = pOrTerm->u.leftColumn;
|
||||
iCursor = pOrTerm->leftCursor;
|
||||
break;
|
||||
}
|
||||
if( i<0 ){
|
||||
/* No candidate table+column was found. This can only occur
|
||||
** on the second iteration */
|
||||
assert( j==1 );
|
||||
assert( (chngToIN&(chngToIN-1))==0 );
|
||||
assert( chngToIN==getMask(pMaskSet, iColumn) );
|
||||
assert( chngToIN==getMask(pMaskSet, iCursor) );
|
||||
break;
|
||||
}
|
||||
testcase( j==1 );
|
||||
|
||||
/* We have found a candidate table and column. Check to see if that
|
||||
** table and column is common to every term in the OR clause */
|
||||
okToChngToIN = 1;
|
||||
for(; i>=0 && okToChngToIN; i--, pOrTerm++){
|
||||
assert( pOrTerm->eOperator==WO_EQ );
|
||||
|
|
Loading…
Reference in New Issue