Thanks for your explaintion! I understand why function `whereScanNext` also return the term `"Y <op> <expr>"`. But, if I force the query planner(by modifying source code) to choose that weird whereloop(using index t1_c0 for constrains t1.c1==t0.c0). It generates incorrect BYTECODE. It first uses the value of t0.c0 as key to search t1.c0 through index t1_c0, then it judge t1.c0 == t0.c0 again. The query result is also incorrect. I think it needs judge "t1.c0 == t1.c1" after index searching. The query plan and incorrect BYTECODE are shown below. ``` QUERY PLAN |--SCAN TABLE t0 `--SEARCH TABLE t1 USING INDEX t1_c0 (c0=?) ``` ``` addr opcode p1 p2 p3 p4 p5 comment ---- ------------- ---- ---- ---- ------------- -- ------------- 0 Init 0 25 0 0 Start at 25 1 OpenRead 0 2 1 1 0 root=2 iDb=1; t0 2 OpenRead 1 3 1 2 0 root=3 iDb=1; t1 3 OpenRead 2 4 1 k(2,,) 2 root=4 iDb=1; t1_c0 4 Explain 4 0 0 SCAN TABLE t0 0 5 Rewind 0 24 0 0 6 Explain 6 0 0 SEARCH TABLE t1 USING INDEX t1_c0 (c0=?) 0 7 Column 0 0 1 0 r[1]=t0.c0 8 IsNull 1 23 0 0 if r[1]==NULL goto 23 9 Affinity 1 1 0 C 0 affinity(r[1]) 10 SeekGE 2 23 1 1 0 key=r[1] 11 IdxGT 2 23 1 1 0 key=r[1] 12 DeferredSeek 2 0 1 0 Move 1 to 2.rowid if needed 13 Column 2 0 2 0 r[2]=t1.c0 14 Column 0 0 3 0 r[3]=t0.c0 15 Ne 3 22 2 BINARY-8 83 if r[2]!=r[3] goto 22 16 ReleaseReg 2 1 0 0 release r[2] mask 0 17 ReleaseReg 3 1 0 0 release r[3] mask 0 18 Column 0 0 4 0 r[4]=t0.c0 19 Column 2 0 5 0 r[5]=t1.c0 20 Column 1 1 6 0 r[6]=t1.c1 21 ResultRow 4 3 0 0 output=r[4..6] 22 Next 2 11 1 0 23 Next 0 6 0 1 24 Halt 0 0 0 0 25 Transaction 1 0 3 0 1 usesStmtJournal=0 26 Goto 0 1 0 0 ```