Clarification of the operation of the OR-term optimizer in where.c. (CVS 6730)

FossilOrigin-Name: 6b42dc3d04e98f91c203c277926ed6ead62a9270
This commit is contained in:
drh 2009-06-08 17:11:08 +00:00
parent a50d9aa784
commit 4e8be3bb5d
3 changed files with 48 additions and 12 deletions

View File

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

View File

@ -1 +1 @@
7863db904d6fc36417c923e3d135eb2c145b9013
6b42dc3d04e98f91c203c277926ed6ead62a9270

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.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 );