1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-16 23:02:26 +03:00

Fix an additional problem with the IS NULL optimization on LEFT JOINs.

Ticket #2189.  See also ticket #2177. (CVS 3602)

FossilOrigin-Name: 358dd82d3a921228155e2cf9e22aedd2b651ca9c
This commit is contained in:
drh
2007-01-25 16:56:06 +00:00
parent 4e653855ab
commit f2d315d0c2
4 changed files with 69 additions and 25 deletions

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.235 2007/01/19 01:06:03 drh Exp $
** $Id: where.c,v 1.236 2007/01/25 16:56:07 drh Exp $
*/
#include "sqliteInt.h"
@@ -160,20 +160,28 @@ struct ExprMaskSet {
#define WO_ISNULL 128
/*
** Value for flags returned by bestIndex()
** Value for flags returned by bestIndex().
**
** The least significant byte is reserved as a mask for WO_ values above.
** The WhereLevel.flags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
** But if the table is the right table of a left join, WhereLevel.flags
** is set to WO_IN|WO_EQ. The WhereLevel.flags field can then be used as
** the "op" parameter to findTerm when we are resolving equality constraints.
** ISNULL constraints will then not be used on the right table of a left
** join. Tickets #2177 and #2189.
*/
#define WHERE_ROWID_EQ 0x0001 /* rowid=EXPR or rowid IN (...) */
#define WHERE_ROWID_RANGE 0x0002 /* rowid<EXPR and/or rowid>EXPR */
#define WHERE_COLUMN_EQ 0x0010 /* x=EXPR or x IN (...) */
#define WHERE_COLUMN_RANGE 0x0020 /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN 0x0040 /* x IN (...) */
#define WHERE_TOP_LIMIT 0x0100 /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT 0x0200 /* x>EXPR or x>=EXPR constraint */
#define WHERE_IDX_ONLY 0x0800 /* Use index only - omit table */
#define WHERE_ORDERBY 0x1000 /* Output will appear in correct order */
#define WHERE_REVERSE 0x2000 /* Scan in reverse order */
#define WHERE_UNIQUE 0x4000 /* Selects no more than one row */
#define WHERE_VIRTUALTABLE 0x8000 /* Use virtual-table processing */
#define WHERE_ROWID_EQ 0x000100 /* rowid=EXPR or rowid IN (...) */
#define WHERE_ROWID_RANGE 0x000200 /* rowid<EXPR and/or rowid>EXPR */
#define WHERE_COLUMN_EQ 0x001000 /* x=EXPR or x IN (...) */
#define WHERE_COLUMN_RANGE 0x002000 /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN 0x004000 /* x IN (...) */
#define WHERE_TOP_LIMIT 0x010000 /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT 0x020000 /* x>EXPR or x>=EXPR constraint */
#define WHERE_IDX_ONLY 0x080000 /* Use index only - omit table */
#define WHERE_ORDERBY 0x100000 /* Output will appear in correct order */
#define WHERE_REVERSE 0x200000 /* Scan in reverse order */
#define WHERE_UNIQUE 0x400000 /* Selects no more than one row */
#define WHERE_VIRTUALTABLE 0x800000 /* Use virtual-table processing */
/*
** Initialize a preallocated WhereClause structure.
@@ -1486,7 +1494,7 @@ static double bestIndex(
*ppIndex = bestIdx;
TRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n",
bestIdx ? bestIdx->zName : "(none)", lowestCost, bestFlags, bestNEq));
*pFlags = bestFlags;
*pFlags = bestFlags | eqTermMask;
*pnEq = bestNEq;
return lowestCost;
}
@@ -1651,7 +1659,7 @@ static void codeAllEqualityTerms(
assert( pIdx->nColumn>=nEq );
for(j=0; j<nEq; j++){
int k = pIdx->aiColumn[j];
pTerm = findTerm(pWC, iCur, k, notReady, WO_EQ|WO_IN|WO_ISNULL, pIdx);
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
if( pTerm==0 ) break;
assert( (pTerm->flags & TERM_CODED)==0 );
codeEqualityTerm(pParse, pTerm, brk, pLevel);