SQLite Forum

index misuse?
Login
Yes, the query plan is right.  

I believe it needs to check, too. Look at these two whereloop objects.

```
   with: * 1.02.01           t1.t1_c0             1 f 10201 N 1 cost 0,62,32
TERM-0   56425A4276C0 .E.. left={1:0}   op=802 wtFlags=2008 prob=1   prereq=3,1
'-- EQ
    |-- {1:0} pTab=56425A430150 fg.af=800000.n
    '-- {0:0} pTab=56425A42E260 fg.af=800000.n
```

```
   skip: * 1.02.01           t1.t1_c0             1 f 10201 N 1 cost 0,62,32
TERM-0   56425A4276F8 .E.. left={1:1}   op=802 wtFlags=2008 prob=1   prereq=3,1
'-- EQ
    |-- {1:1} pTab=56425A430150 fg.af=800000.n
    '-- {0:0} pTab=56425A42E260 fg.af=800000.n
```
In my opinion, SQLite finds index t1_c0 is useless for the t1.c1 constraint only because the second whereloop's cost is not better than the first one. But I think SQLite should skip the second whereloop because this index shouldn't be used for the t1.c1 constraint. 

Do you think we can find a test case to make the second whereloop(using index t1_c0 for the "t1.c0==t0.c0" term) has a lower cost than the first one(using index  t1_c0 for the "t1.c1==t0.c0" term)? I decrease the cost of the second whereloop by modifying the source code and find it generates a mistake query plan. But I cannot provide 
a test case for unmodified SQLite.

I found that the function `whereScanInit` has related comments, which I quote here:
```
/*
** Initialize a WHERE clause scanner object.  Return a pointer to the
** first match.  Return NULL if there are no matches.
**
** The scanner will be searching the WHERE clause pWC.  It will look
** for terms of the form "X <op> <expr>" where X is column iColumn of table
** iCur.   Or if pIdx!=0 then X is column iColumn of index pIdx.  pIdx
** must be one of the indexes of table iCur.
**
** The <op> must be one of the operators described by opMask.
**
** If the search is for X and the WHERE clause contains terms of the
** form X=Y then this routine might also return terms of the form
** "Y <op> <expr>".  The number of levels of transitivity is limited,
** but is enough to handle most commonly occurring SQL statements.
**
** If X is not the INTEGER PRIMARY KEY then X must be compatible with
** index pIdx.
*/
```
In this case, X is t1.c0 and Y is t0.c0. So term "t0.c0=t1.c1" will also be returned by function `whereScanNext`.
Maybe that is the reason why SQLite tries using the index on t1.c0 to optimize the "t1.c1=t0.c0" term. 
I am confusing about "X must be compatible with index pIdx" in the comments.
From my view, t1.c1 is not compatible with index t1_c0.
Do you think it is a bug or not? Looking forward to your thoughts!