/ Check-in [8f249c45]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Change opcode names and comments to better describe the operation of the incrKey flag. OP_MoveTo becomes OP_MoveGe. (CVS 1407)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:8f249c45cbc77f4320798ff1a830b55e5c74888a
User & Date: drh 2004-05-19 14:56:56
Context
2004-05-19
20:41
Correctly handle 64-bit integers in SQL statements. (CVS 1408) check-in: 34f03ba6 user: drh tags: trunk
14:56
Change opcode names and comments to better describe the operation of the incrKey flag. OP_MoveTo becomes OP_MoveGe. (CVS 1407) check-in: 8f249c45 user: drh tags: trunk
13:13
Bug fixes in where.c. The where.test test works again. (CVS 1406) check-in: 7c31e257 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
390
391
392
393
394
395
396
397
398
399
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.67 2004/05/18 09:58:07 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
      addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      if( !isView ){
        sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
        sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
        sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
      }
      sqlite3VdbeAddOp(v, OP_MoveTo, iCur, 0);

      sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
      sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
      sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
      if( !isView ){
        sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
      }

................................................................................
      }
    }
    sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    sqlite3IndexAffinityStr(v, pIdx);
    sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
  }
}










|







 







|
<







 







<
<
<
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
...
389
390
391
392
393
394
395



**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.68 2004/05/19 14:56:56 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
      addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      if( !isView ){
        sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
        sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
        sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
      }
      sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);

      sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
      sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
      sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
      if( !isView ){
        sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
      }

................................................................................
      }
    }
    sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    sqlite3IndexAffinityStr(v, pIdx);
    sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
  }
}



Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
...
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
....
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.102 2004/05/18 09:58:07 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
                         "PRIMARY KEY must be unique", P3_STATIC);
        break;
      }
      case OE_Replace: {
        sqlite3GenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1);
          sqlite3VdbeAddOp(v, OP_MoveTo, base, 0);
        }
        seenReplace = 1;
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
................................................................................
      }
    }
    contAddr = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeChangeP2(v, jumpInst2, contAddr);
    if( isUpdate ){
      sqlite3VdbeChangeP2(v, jumpInst1, contAddr);
      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);
      sqlite3VdbeAddOp(v, OP_MoveTo, base, 0);
    }
  }

  /* Test all UNIQUE constraints by creating entries for each UNIQUE
  ** index and making sure that duplicate entries do not already exist.
  ** Add the new records to the indices as we go.
  */
................................................................................
        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {
        sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
          sqlite3VdbeAddOp(v, OP_MoveTo, base, 0);
        }
        seenReplace = 1;
        break;
      }
      default: assert(0);
    }
    contAddr = sqlite3VdbeCurrentAddr(v);
................................................................................
  sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol);
  for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
    sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
    sqlite3VdbeOp3(v, OP_OpenWrite, i+base, pIdx->tnum, pIdx->zName, P3_STATIC);
  }
  return i;
}










|







 







|







 







|







 







|







 







<
<
<
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
...
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
....
1006
1007
1008
1009
1010
1011
1012



**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.103 2004/05/19 14:56:56 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
                         "PRIMARY KEY must be unique", P3_STATIC);
        break;
      }
      case OE_Replace: {
        sqlite3GenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1);
          sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
        }
        seenReplace = 1;
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
................................................................................
      }
    }
    contAddr = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeChangeP2(v, jumpInst2, contAddr);
    if( isUpdate ){
      sqlite3VdbeChangeP2(v, jumpInst1, contAddr);
      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);
      sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
    }
  }

  /* Test all UNIQUE constraints by creating entries for each UNIQUE
  ** index and making sure that duplicate entries do not already exist.
  ** Add the new records to the indices as we go.
  */
................................................................................
        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {
        sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
          sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
        }
        seenReplace = 1;
        break;
      }
      default: assert(0);
    }
    contAddr = sqlite3VdbeCurrentAddr(v);
................................................................................
  sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol);
  for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
    sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
    sqlite3VdbeOp3(v, OP_OpenWrite, i+base, pIdx->tnum, pIdx->zName, P3_STATIC);
  }
  return i;
}



Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.168 2004/05/18 22:38:32 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
    sqlite3VdbeAddOp(v, seekOp, base, 0);
  }else{
    sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
    sqlite3VdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
    sqlite3VdbeAddOp(v, seekOp, base+1, 0);
    sqlite3VdbeAddOp(v, OP_IdxRecno, base+1, 0);
    sqlite3VdbeAddOp(v, OP_Close, base+1, 0);
    sqlite3VdbeAddOp(v, OP_MoveTo, base, 0);
  }
  eList.nExpr = 1;
  memset(&eListItem, 0, sizeof(eListItem));
  eList.a = &eListItem;
  eList.a[0].pExpr = pExpr;
  selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont, 0);
  sqlite3VdbeResolveLabel(v, cont);







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.169 2004/05/19 14:56:56 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
    sqlite3VdbeAddOp(v, seekOp, base, 0);
  }else{
    sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
    sqlite3VdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
    sqlite3VdbeAddOp(v, seekOp, base+1, 0);
    sqlite3VdbeAddOp(v, OP_IdxRecno, base+1, 0);
    sqlite3VdbeAddOp(v, OP_Close, base+1, 0);
    sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
  }
  eList.nExpr = 1;
  memset(&eListItem, 0, sizeof(eListItem));
  eList.a = &eListItem;
  eList.a[0].pExpr = pExpr;
  selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont, 0);
  sqlite3VdbeResolveLabel(v, cont);

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
454
455
456
457
458
459
460
461
462
463
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.76 2004/05/18 09:58:08 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
    */
    sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
    if( !isView ){
      sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
      sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
      sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
    }
    sqlite3VdbeAddOp(v, OP_MoveTo, iCur, 0);

    /* Generate the OLD table
    */
    sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
    sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
    sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0);

................................................................................
  sqliteFree(apIdx);
  sqliteFree(aXRef);
  sqlite3SrcListDelete(pTabList);
  sqlite3ExprListDelete(pChanges);
  sqlite3ExprDelete(pWhere);
  return;
}










|







 







|







 







<
<
<
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
454
455
456
457
458
459
460



**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.77 2004/05/19 14:56:57 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
    */
    sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
    if( !isView ){
      sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
      sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
      sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
    }
    sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);

    /* Generate the OLD table
    */
    sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
    sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
    sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0);

................................................................................
  sqliteFree(apIdx);
  sqliteFree(aXRef);
  sqlite3SrcListDelete(pTabList);
  sqlite3ExprListDelete(pChanges);
  sqlite3ExprDelete(pWhere);
  return;
}



Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
....
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767

2768

2769
2770
2771
2772
2773


2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789

2790
2791



2792
2793

2794
2795
2796


2797
2798
2799
2800
2801
2802
2803
2804

2805

2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
....
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840


2841
2842
2843
2844
2845
2846
2847
2848
....
2923
2924
2925
2926
2927
2928
2929
2930
2931

2932
2933
2934

2935
2936
2937
2938
2939
2940
2941
2942
....
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
....
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
....
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828



3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840

3841
3842
3843
3844
3845
3846
3847
....
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858

3859
3860
3861
3862
3863
3864
3865
3866
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.303 2004/05/19 13:13:08 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
** procedures use this information to make sure that indices are
** working correctly.  This variable has no function other than to
** help verify the correct operation of the library.
*/
int sqlite3_search_count = 0;

/*
................................................................................
  int i = pOp->p1;
  if( i>=0 && i<p->nCursor ){
    sqlite3VdbeCleanupCursor(p->apCsr[i]);
  }
  break;
}

/* Opcode: MoveTo P1 P2 *
**
** Pop the top of the stack and use its value as a key.  Reposition
** cursor P1 so that it points to an entry with a matching key.  If
** the table contains no record with a matching key, then the cursor
** is left pointing at the first record that is greater than the key.
** If there are no records greater than the key and P2 is not zero,
** then an immediate jump to P2 is made.

**

** If P3 is the "+" string (or any other non-NULL string) then the
** index taken from the top of the stack is temporarily increased by
** an epsilon prior to the move.  This causes the P1 cursor to move
** to the first entry which is greater than the index on the top of
** the stack rather than the first entry that is equal to the top of


** the stack.
**
** See also: Found, NotFound, Distinct, MoveLt
*/
/* Opcode: MoveLt P1 P2 *
**
** Pop the top of the stack and use its value as a key.  Reposition
** cursor P1 so that it points to the entry with the largest key that is
** less than the key popped from the stack.
** If there are no records less than than the key and P2
** is not zero then an immediate jump to P2 is made.
**
** If P3 is the "+" string (or any other non-NULL string) then the
** index taken from the top of the stack is temporarily increased by
** an epsilon prior to the move.  This causes the P1 cursor to move
** to the smallest entry that is greater than or equal to the top of

** the stack rather than the largest entry that is less than the top
** of the stack.



**
** See also: MoveTo

*/
case OP_MoveLt:
case OP_MoveTo: {


  int i = pOp->p1;
  Cursor *pC;

  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  pC = p->apCsr[i];
  if( pC->pCursor!=0 ){
    int res, oc;

    pC->nullRow = 0;

    if( pC->intKey ){
      i64 iKey;
      assert( !pOp->p3 );
      Integerify(pTos);
      iKey = intToKey(pTos->i);
      if( pOp->p2==0 && pOp->opcode==OP_MoveTo ){
        pC->movetoTarget = iKey;
        pC->deferredMoveto = 1;
        Release(pTos);
        pTos--;
        break;
      }
      sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res);
................................................................................
      pC->incrKey = 0;
      pC->recnoIsValid = 0;
    }
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
    pC->incrKey = 0;
    sqlite3_search_count++;
    oc = pOp->opcode;
    if( oc==OP_MoveTo && res<0 ){
      sqlite3BtreeNext(pC->pCursor, &res);
      pC->recnoIsValid = 0;
      if( res && pOp->p2>0 ){
        pc = pOp->p2 - 1;
      }


    }else if( oc==OP_MoveLt ){
      if( res>=0 ){
        sqlite3BtreePrevious(pC->pCursor, &res);
        pC->recnoIsValid = 0;
      }else{
        /* res might be negative because the table is empty.  Check to
        ** see if this is the case.
        */
................................................................................
/* Opcode: IsUnique P1 P2 *
**
** The top of the stack is an integer record number.  Call this
** record number R.  The next on the stack is an index key created
** using MakeIdxKey.  Call it K.  This instruction pops R from the
** stack but it leaves K unchanged.
**
** P1 is an index.  So all but the last four bytes of K are an
** index string.  The last four bytes of K are a record number.

**
** This instruction asks if there is an entry in P1 where the
** index string matches K but the record number is different

** from R.  If there is no such entry, then there is an immediate
** jump to P2.  If any entry does exist where the index string
** matches K but the record number is not R, then the record
** number for that entry is pushed onto the stack and control
** falls through to the next instruction.
**
** See also: Distinct, NotFound, NotExists, Found
*/
................................................................................
    if( res<0 ){
      rc = sqlite3BtreeNext(pCrsr, &res);
      if( res ){
        pc = pOp->p2 - 1;
        break;
      }
    }
    rc = sqlite3VdbeIdxKeyCompare(pCx, len, zKey, 0, &res); 
    if( rc!=SQLITE_OK ) goto abort_due_to_error;
    if( res>0 ){
      pc = pOp->p2 - 1;
      break;
    }

    /* At this point, pCrsr is pointing to an entry in P1 where all but
................................................................................

      rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
      if( rc!=SQLITE_OK ) goto abort_due_to_error;
      while( res!=0 ){
        int c;
        sqlite3BtreeKeySize(pCrsr, &n);
        if( n==nKey && 
            sqlite3VdbeIdxKeyCompare(pC, len, zKey, 0, &c)==SQLITE_OK
            && c==0
        ){
          rc = SQLITE_CONSTRAINT;
          if( pOp->p3 && pOp->p3[0] ){
            sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0);
          }
          goto abort_due_to_error;
................................................................................
#endif
  }else{
    pTos->flags = MEM_Null;
  }
  break;
}

/* Opcode: IdxGT P1 P2 P3
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to.  Ignore the ROWID of the
** index entry.  If the index entry is greater than the top of the stack
** then jump to P2.  Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
**
** If P3 is the "+" string (or any other non-NULL string) then the
** index taken from the top of the stack is temporarily increased by
** an epsilon prior to the comparison.
*/
/* Opcode: IdxGE P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to.  Ignore the ROWID of the
** index entry.  If the index entry is greater than or equal to 
** the top of the stack
** then jump to P2.  Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
**
** If P3 is the "+" string (or any other non-NULL string) then the
** index taken from the top of the stack is temporarily increased by
** an epsilon prior to the comparison.



*/
/* Opcode: IdxLT P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to.  Ignore the ROWID of the
** index entry.  If the index entry is less than the top of the stack
** then jump to P2.  Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
**
** If P3 is the "+" string (or any other non-NULL string) then the
** index taken from the top of the stack is temporarily increased by
** an epsilon prior to the comparison.

*/
case OP_IdxLT:
case OP_IdxGT:
case OP_IdxGE: {
  int i= pOp->p1;
  BtCursor *pCrsr;
  Cursor *pC;
................................................................................
  assert( i>=0 && i<p->nCursor );
  assert( pTos>=p->aStack );
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    int res, rc;
 
    Stringify(pTos);
    assert( pC->deferredMoveto==0 );
    if( pOp->p3 ){
      pC->incrKey = 1;
    }

    rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, pTos->z, 0, &res);
    pC->incrKey = 0;
    if( rc!=SQLITE_OK ){
      break;
    }
    if( pOp->opcode==OP_IdxLT ){
      res = -res;
    }else if( pOp->opcode==OP_IdxGE ){







|








|







 







|


|
|
<
|
<
>

>
|
|
|
|
|
>
>
|

|




|
|
|
|

|
|
|
|
>
|
<
>
>
>

<
>


|
>
>








>

>





|







 







|
|
|
|
|
|
|
>
>
|







 







|
|
>


<
>
|







 







|







 







|







 







|






<
<
<
<

|



|






|
>
>
>

|









|
>







 







<
|
<
>
|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
....
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764

2765

2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793

2794
2795
2796
2797

2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
....
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
....
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945

2946
2947
2948
2949
2950
2951
2952
2953
2954
....
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
....
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
....
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823




3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
....
3861
3862
3863
3864
3865
3866
3867

3868

3869
3870
3871
3872
3873
3874
3875
3876
3877
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.304 2004/05/19 14:56:57 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveXX, OP_Next, or OP_Prev opcodes.  The test
** procedures use this information to make sure that indices are
** working correctly.  This variable has no function other than to
** help verify the correct operation of the library.
*/
int sqlite3_search_count = 0;

/*
................................................................................
  int i = pOp->p1;
  if( i>=0 && i<p->nCursor ){
    sqlite3VdbeCleanupCursor(p->apCsr[i]);
  }
  break;
}

/* Opcode: MoveGe P1 P2 *
**
** Pop the top of the stack and use its value as a key.  Reposition
** cursor P1 so that it points to the smallest entry that is greater
** than or equal to the key that was popped ffrom the stack.

** If there are no records greater than or equal to the key and P2 

** is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe
*/
/* Opcode: MoveGt P1 P2 *
**
** Pop the top of the stack and use its value as a key.  Reposition
** cursor P1 so that it points to the smallest entry that is greater
** than the key from the stack.
** If there are no records greater than the key and P2 is not zero,
** then jump to P2.
**
** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe
*/
/* Opcode: MoveLt P1 P2 *
**
** Pop the top of the stack and use its value as a key.  Reposition
** cursor P1 so that it points to the largest entry that is less
** than the key from the stack.
** If there are no records less than the key and P2 is not zero,
** then jump to P2.
**
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe
*/
/* Opcode: MoveLe P1 P2 *
**
** Pop the top of the stack and use its value as a key.  Reposition
** cursor P1 so that it points to the largest entry that is less than

** or equal to the key that was popped from the stack.
** If there are no records less than or eqal to the key and P2 is not zero,
** then jump to P2.
**

** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
*/
case OP_MoveLt:
case OP_MoveLe:
case OP_MoveGe:
case OP_MoveGt: {
  int i = pOp->p1;
  Cursor *pC;

  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  pC = p->apCsr[i];
  if( pC->pCursor!=0 ){
    int res, oc;
    oc = pOp->opcode;
    pC->nullRow = 0;
    pC->incrKey = oc==OP_MoveGt || oc==OP_MoveLe;
    if( pC->intKey ){
      i64 iKey;
      assert( !pOp->p3 );
      Integerify(pTos);
      iKey = intToKey(pTos->i);
      if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){
        pC->movetoTarget = iKey;
        pC->deferredMoveto = 1;
        Release(pTos);
        pTos--;
        break;
      }
      sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res);
................................................................................
      pC->incrKey = 0;
      pC->recnoIsValid = 0;
    }
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
    pC->incrKey = 0;
    sqlite3_search_count++;
    if( oc==OP_MoveGe || oc==OP_MoveGt ){
      if( res<0 ){
        sqlite3BtreeNext(pC->pCursor, &res);
        pC->recnoIsValid = 0;
        if( res && pOp->p2>0 ){
          pc = pOp->p2 - 1;
        }
      }
    }else{
      assert( oc==OP_MoveLt || oc==OP_MoveLe );
      if( res>=0 ){
        sqlite3BtreePrevious(pC->pCursor, &res);
        pC->recnoIsValid = 0;
      }else{
        /* res might be negative because the table is empty.  Check to
        ** see if this is the case.
        */
................................................................................
/* Opcode: IsUnique P1 P2 *
**
** The top of the stack is an integer record number.  Call this
** record number R.  The next on the stack is an index key created
** using MakeIdxKey.  Call it K.  This instruction pops R from the
** stack but it leaves K unchanged.
**
** P1 is an index.  So it has no data and its key consists of a
** record generated by OP_MakeIdxKey.  This key contains one or more
** fields followed by a varint ROWID.
**
** This instruction asks if there is an entry in P1 where the

** fields matches K but the rowid is different from R.
** If there is no such entry, then there is an immediate
** jump to P2.  If any entry does exist where the index string
** matches K but the record number is not R, then the record
** number for that entry is pushed onto the stack and control
** falls through to the next instruction.
**
** See also: Distinct, NotFound, NotExists, Found
*/
................................................................................
    if( res<0 ){
      rc = sqlite3BtreeNext(pCrsr, &res);
      if( res ){
        pc = pOp->p2 - 1;
        break;
      }
    }
    rc = sqlite3VdbeIdxKeyCompare(pCx, len, zKey, &res); 
    if( rc!=SQLITE_OK ) goto abort_due_to_error;
    if( res>0 ){
      pc = pOp->p2 - 1;
      break;
    }

    /* At this point, pCrsr is pointing to an entry in P1 where all but
................................................................................

      rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
      if( rc!=SQLITE_OK ) goto abort_due_to_error;
      while( res!=0 ){
        int c;
        sqlite3BtreeKeySize(pCrsr, &n);
        if( n==nKey && 
            sqlite3VdbeIdxKeyCompare(pC, len, zKey, &c)==SQLITE_OK
            && c==0
        ){
          rc = SQLITE_CONSTRAINT;
          if( pOp->p3 && pOp->p3[0] ){
            sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0);
          }
          goto abort_due_to_error;
................................................................................
#endif
  }else{
    pTos->flags = MEM_Null;
  }
  break;
}

/* Opcode: IdxGT P1 P2 *
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to.  Ignore the ROWID of the
** index entry.  If the index entry is greater than the top of the stack
** then jump to P2.  Otherwise fall through to the next instruction.
** In either case, the stack is popped once.




*/
/* Opcode: IdxGE P1 P2 P3
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to.  Ignore the ROWID of the
** index entry.  If the index in the cursor is greater than or equal to 
** the top of the stack
** then jump to P2.  Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
**
** If P3 is the "+" string (or any other non-NULL string) then the
** index taken from the top of the stack is temporarily increased by
** an epsilon prior to the comparison.  This make the opcode work
** like IdxGT except that if the key from the stack is a prefix of
** the key in the cursor, the result is false whereas it would be
** true with IdxGT.
*/
/* Opcode: IdxLT P1 P2 P3
**
** Compare the top of the stack against the key on the index entry that
** cursor P1 is currently pointing to.  Ignore the ROWID of the
** index entry.  If the index entry is less than the top of the stack
** then jump to P2.  Otherwise fall through to the next instruction.
** In either case, the stack is popped once.
**
** If P3 is the "+" string (or any other non-NULL string) then the
** index taken from the top of the stack is temporarily increased by
** an epsilon prior to the comparison.  This makes the opcode work
** like IdxLE.
*/
case OP_IdxLT:
case OP_IdxGT:
case OP_IdxGE: {
  int i= pOp->p1;
  BtCursor *pCrsr;
  Cursor *pC;
................................................................................
  assert( i>=0 && i<p->nCursor );
  assert( pTos>=p->aStack );
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    int res, rc;
 
    Stringify(pTos);
    assert( pC->deferredMoveto==0 );

    pC->incrKey = pOp->p3!=0;

    assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT );
    rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, pTos->z, &res);
    pC->incrKey = 0;
    if( rc!=SQLITE_OK ){
      break;
    }
    if( pOp->opcode==OP_IdxLT ){
      res = -res;
    }else if( pOp->opcode==OP_IdxGE ){

Changes to src/vdbeInt.h.

324
325
326
327
328
329
330
331
332
333
334
335
#endif
int sqlite3VdbeSerialTypeLen(u64);
u64 sqlite3VdbeSerialType(const Mem *);
int sqlite3VdbeSerialPut(unsigned char *, const Mem *);
int sqlite3VdbeSerialGet(const unsigned char *, u64, Mem *);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(Mem *, Mem *);
int sqlite3VdbeKeyCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeRowCompare(void*,int,const void*,int, const void*);







|




324
325
326
327
328
329
330
331
332
333
334
335
#endif
int sqlite3VdbeSerialTypeLen(u64);
u64 sqlite3VdbeSerialType(const Mem *);
int sqlite3VdbeSerialPut(unsigned char *, const Mem *);
int sqlite3VdbeSerialGet(const unsigned char *, u64, Mem *);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(Mem *, Mem *);
int sqlite3VdbeKeyCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeRowCompare(void*,int,const void*,int, const void*);

Changes to src/vdbeaux.c.

1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633





1634
1635
1636
1637
1638
1639
1640
....
1658
1659
1660
1661
1662
1663
1664

1665
1666
1667
1668

1669
1670
1671
1672
1673
1674
1675
  while( buf[len-1] && --len );

  sqlite3GetVarint(&buf[len], &r);
  *rowid = r;
  return SQLITE_OK;
}

int sqlite3VdbeIdxKeyCompare(
  Cursor *pC, 
  int nKey, const unsigned char *pKey,
  int ignorerowid,
  int *res





){
  unsigned char *pCellKey;
  u64 nCellKey;
  int freeCellKey = 0;
  int rc;
  int len;
  BtCursor *pCur = pC->pCursor;
................................................................................
      return rc;
    }
  }
 
  len = nCellKey-2;
  while( pCellKey[len] && --len );


  if( ignorerowid ){
    nKey--;
    while( pKey[nKey] && --nKey );
  }

  *res = sqlite3VdbeKeyCompare(pC, len, pCellKey, nKey, pKey);
  
  if( freeCellKey ){
    sqliteFree(pCellKey);
  }
  return SQLITE_OK;
}







|
|
|
|
|
>
>
>
>
>







 







>




>







1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
....
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
  while( buf[len-1] && --len );

  sqlite3GetVarint(&buf[len], &r);
  *rowid = r;
  return SQLITE_OK;
}

/*
** Compare the key of index entry that cursor pC is point to against
** the key string in pKey (of length nKey).  Write into *pRes a number
** that is negative, zero, or positive if pC is less than, equal to,
** or greater than pKey.  Return SQLITE_OK on success.
*/
int sqlite3VdbeIdxKeyCompare(
  Cursor *pC,                 /* The cursor to compare against */
  int nKey, const u8 *pKey,   /* The key to compare */
  int *res                    /* Write the comparison result here */
){
  unsigned char *pCellKey;
  u64 nCellKey;
  int freeCellKey = 0;
  int rc;
  int len;
  BtCursor *pCur = pC->pCursor;
................................................................................
      return rc;
    }
  }
 
  len = nCellKey-2;
  while( pCellKey[len] && --len );

#if 0
  if( ignorerowid ){
    nKey--;
    while( pKey[nKey] && --nKey );
  }
#endif
  *res = sqlite3VdbeKeyCompare(pC, len, pCellKey, nKey, pKey);
  
  if( freeCellKey ){
    sqliteFree(pCellKey);
  }
  return SQLITE_OK;
}

Changes to src/where.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836

837
838
839

840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
...
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
....
1019
1020
1021
1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
....
1079
1080
1081
1082
1083
1084
1085

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
....
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
....
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
....
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.97 2004/05/19 13:13:08 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
      sqlite3VdbeAddOp(v, OP_Goto, 0, brk);

      /* Generate an index key from the top nColumn elements of the stack */
      sqlite3VdbeAddOp(v, OP_MakeKey, nColumn, 0);
      sqlite3IndexAffinityStr(v, pIdx);
      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);

      /* Choose a testOp that will determine when we have moved past the
      ** last element of the table that matches the index key we just
      ** created */
      if( nColumn==pIdx->nColumn || pLevel->bRev ){
        testOp = OP_IdxGT;
      }else{
        testOp = OP_IdxGE;
      }

      /* Generate code (1) to move to the first matching element of the table.
      ** Then generate code (2) that jumps to "brk" after the cursor is past
      ** the last matching element of the table.  The code (1) is executed
      ** once to initialize the search, the code (2) is executed before each
      ** iteration of the scan to see if the scan has finished. */
      if( pLevel->bRev ){
        /* Scan in reverse order */
        sqlite3VdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
        sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
        sqlite3VdbeAddOp(v, OP_IdxLT, pLevel->iCur, brk);
        pLevel->op = OP_Prev;
      }else{
        /* Scan in the forward order */
        sqlite3VdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);

        sqlite3VdbeAddOp(v, testOp, pLevel->iCur, brk);
        if( testOp==OP_IdxGE ){
          sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);

        }
        pLevel->op = OP_Next;
      }
      sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
      sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
      sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
      if( i==pTabList->nSrc-1 && pushKey ){
        haveKey = 1;
      }else{
        sqlite3VdbeAddOp(v, OP_MoveTo, iCur, 0);
        haveKey = 0;
      }
      pLevel->p1 = pLevel->iCur;
      pLevel->p2 = start;
    }else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){
      /* Case 3:  We have an inequality comparison against the ROWID field.
      */
................................................................................
        if( aExpr[k].idxLeft==iCur ){
          sqlite3ExprCode(pParse, aExpr[k].p->pRight);
        }else{
          sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
        }
        sqlite3VdbeAddOp(v, OP_ForceInt,
          aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
        sqlite3VdbeAddOp(v, OP_MoveTo, iCur, brk);
        aExpr[k].p = 0;
      }else{
        sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
      }
      if( iDirectLt[i]>=0 ){
        k = iDirectLt[i];
        assert( k<nExpr );
................................................................................
        pLevel->iMem = pParse->nMem++;
        sqlite3VdbeAddOp(v, OP_NotNull, -nCol, sqlite3VdbeCurrentAddr(v)+3);
        sqlite3VdbeAddOp(v, OP_Pop, nCol, 0);
        sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
        sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
        sqlite3IndexAffinityStr(v, pIdx);
        if( pLevel->bRev ){

          sqlite3VdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
          if( leFlag ){
            sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
          }
        }else{
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
        }
      }else if( pLevel->bRev ){
        sqlite3VdbeAddOp(v, OP_Last, pLevel->iCur, brk);
      }

................................................................................
        sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
        sqlite3IndexAffinityStr(v, pIdx);
        if( pLevel->bRev ){
          pLevel->iMem = pParse->nMem++;
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
          testOp = OP_IdxLT;
        }else{

          sqlite3VdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
          if( !geFlag ){
            sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
          }
        }
      }else if( pLevel->bRev ){
        testOp = OP_Noop;
      }else{
        sqlite3VdbeAddOp(v, OP_Rewind, pLevel->iCur, brk);
      }

................................................................................
      }
      sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + (score & 1), cont);
      sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
      if( i==pTabList->nSrc-1 && pushKey ){
        haveKey = 1;
      }else{
        sqlite3VdbeAddOp(v, OP_MoveTo, iCur, 0);
        haveKey = 0;
      }

      /* Record the instruction used to terminate the loop.
      */
      pLevel->op = pLevel->bRev ? OP_Prev : OP_Next;
      pLevel->p1 = pLevel->iCur;
................................................................................
      if( aExpr[j].p==0 ) continue;
      if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
      if( pLevel->iLeftJoin && !ExprHasProperty(aExpr[j].p,EP_FromJoin) ){
        continue;
      }
      if( haveKey ){
        haveKey = 0;
        sqlite3VdbeAddOp(v, OP_MoveTo, iCur, 0);
      }
      sqlite3ExprIfFalse(pParse, aExpr[j].p, cont, 1);
      aExpr[j].p = 0;
    }
    brk = cont;

    /* For a LEFT OUTER JOIN, generate code that will record the fact that
................................................................................
        if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
        if( haveKey ){
          /* Cannot happen.  "haveKey" can only be true if pushKey is true
          ** an pushKey can only be true for DELETE and UPDATE and there are
          ** no outer joins with DELETE and UPDATE.
          */
          haveKey = 0;
          sqlite3VdbeAddOp(v, OP_MoveTo, iCur, 0);
        }
        sqlite3ExprIfFalse(pParse, aExpr[j].p, cont, 1);
        aExpr[j].p = 0;
      }
    }
  }
  pWInfo->iContinue = cont;







|







 







<
<
<
<
<
<
<
<
<







|
<





|

>
|
<
|
>









|







 







|







 







>
|
<
<
<







 







>
|
<
<
<







 







|







 







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
805
806
807
808
809
810
811









812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
...
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
....
1010
1011
1012
1013
1014
1015
1016
1017
1018



1019
1020
1021
1022
1023
1024
1025
....
1068
1069
1070
1071
1072
1073
1074
1075
1076



1077
1078
1079
1080
1081
1082
1083
....
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
....
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
....
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.98 2004/05/19 14:56:57 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
      sqlite3VdbeAddOp(v, OP_Goto, 0, brk);

      /* Generate an index key from the top nColumn elements of the stack */
      sqlite3VdbeAddOp(v, OP_MakeKey, nColumn, 0);
      sqlite3IndexAffinityStr(v, pIdx);
      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);










      /* Generate code (1) to move to the first matching element of the table.
      ** Then generate code (2) that jumps to "brk" after the cursor is past
      ** the last matching element of the table.  The code (1) is executed
      ** once to initialize the search, the code (2) is executed before each
      ** iteration of the scan to see if the scan has finished. */
      if( pLevel->bRev ){
        /* Scan in reverse order */
        sqlite3VdbeAddOp(v, OP_MoveLe, pLevel->iCur, brk);

        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
        sqlite3VdbeAddOp(v, OP_IdxLT, pLevel->iCur, brk);
        pLevel->op = OP_Prev;
      }else{
        /* Scan in the forward order */
        sqlite3VdbeAddOp(v, OP_MoveGe, pLevel->iCur, brk);
        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
        if( nColumn==pIdx->nColumn || 0 ){
          sqlite3VdbeAddOp(v, OP_IdxGT, pLevel->iCur, brk);

        }else{
          sqlite3VdbeOp3(v, OP_IdxGE, pLevel->iCur, brk, "+", P3_STATIC);
        }
        pLevel->op = OP_Next;
      }
      sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
      sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
      sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
      if( i==pTabList->nSrc-1 && pushKey ){
        haveKey = 1;
      }else{
        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
        haveKey = 0;
      }
      pLevel->p1 = pLevel->iCur;
      pLevel->p2 = start;
    }else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){
      /* Case 3:  We have an inequality comparison against the ROWID field.
      */
................................................................................
        if( aExpr[k].idxLeft==iCur ){
          sqlite3ExprCode(pParse, aExpr[k].p->pRight);
        }else{
          sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
        }
        sqlite3VdbeAddOp(v, OP_ForceInt,
          aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, brk);
        aExpr[k].p = 0;
      }else{
        sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
      }
      if( iDirectLt[i]>=0 ){
        k = iDirectLt[i];
        assert( k<nExpr );
................................................................................
        pLevel->iMem = pParse->nMem++;
        sqlite3VdbeAddOp(v, OP_NotNull, -nCol, sqlite3VdbeCurrentAddr(v)+3);
        sqlite3VdbeAddOp(v, OP_Pop, nCol, 0);
        sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
        sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
        sqlite3IndexAffinityStr(v, pIdx);
        if( pLevel->bRev ){
          int op = leFlag ? OP_MoveLe : OP_MoveLt;
          sqlite3VdbeAddOp(v, op, pLevel->iCur, brk);



        }else{
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
        }
      }else if( pLevel->bRev ){
        sqlite3VdbeAddOp(v, OP_Last, pLevel->iCur, brk);
      }

................................................................................
        sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
        sqlite3IndexAffinityStr(v, pIdx);
        if( pLevel->bRev ){
          pLevel->iMem = pParse->nMem++;
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
          testOp = OP_IdxLT;
        }else{
          int op = geFlag ? OP_MoveGe : OP_MoveGt;
          sqlite3VdbeAddOp(v, op, pLevel->iCur, brk);



        }
      }else if( pLevel->bRev ){
        testOp = OP_Noop;
      }else{
        sqlite3VdbeAddOp(v, OP_Rewind, pLevel->iCur, brk);
      }

................................................................................
      }
      sqlite3VdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + (score & 1), cont);
      sqlite3VdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
      if( i==pTabList->nSrc-1 && pushKey ){
        haveKey = 1;
      }else{
        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
        haveKey = 0;
      }

      /* Record the instruction used to terminate the loop.
      */
      pLevel->op = pLevel->bRev ? OP_Prev : OP_Next;
      pLevel->p1 = pLevel->iCur;
................................................................................
      if( aExpr[j].p==0 ) continue;
      if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
      if( pLevel->iLeftJoin && !ExprHasProperty(aExpr[j].p,EP_FromJoin) ){
        continue;
      }
      if( haveKey ){
        haveKey = 0;
        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
      }
      sqlite3ExprIfFalse(pParse, aExpr[j].p, cont, 1);
      aExpr[j].p = 0;
    }
    brk = cont;

    /* For a LEFT OUTER JOIN, generate code that will record the fact that
................................................................................
        if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
        if( haveKey ){
          /* Cannot happen.  "haveKey" can only be true if pushKey is true
          ** an pushKey can only be true for DELETE and UPDATE and there are
          ** no outer joins with DELETE and UPDATE.
          */
          haveKey = 0;
          sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
        }
        sqlite3ExprIfFalse(pParse, aExpr[j].p, cont, 1);
        aExpr[j].p = 0;
      }
    }
  }
  pWInfo->iContinue = cont;

Changes to test/where.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
136
137
138
139
140
141
142

143
144
145
146
147
148
149
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the use of indices in WHERE clases.
#
# $Id: where.test,v 1.18 2004/05/19 13:13:08 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
do_test where-1.0 {
................................................................................
# do_test where-1.26 {
#   count {SELECT w FROM t1 WHERE x=3 AND y BETWEEN 121 AND 196}
# } {10 11 12 13 9}

do_test where-1.27 {
  count {SELECT w FROM t1 WHERE x=3 AND y+1==122}
} {10 17}

do_test where-1.28 {
  count {SELECT w FROM t1 WHERE x+1=4 AND y+1==122}
} {10 99}
do_test where-1.29 {
  count {SELECT w FROM t1 WHERE y==121}
} {10 99}








|







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the use of indices in WHERE clases.
#
# $Id: where.test,v 1.19 2004/05/19 14:56:57 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
do_test where-1.0 {
................................................................................
# do_test where-1.26 {
#   count {SELECT w FROM t1 WHERE x=3 AND y BETWEEN 121 AND 196}
# } {10 11 12 13 9}

do_test where-1.27 {
  count {SELECT w FROM t1 WHERE x=3 AND y+1==122}
} {10 17}

do_test where-1.28 {
  count {SELECT w FROM t1 WHERE x+1=4 AND y+1==122}
} {10 99}
do_test where-1.29 {
  count {SELECT w FROM t1 WHERE y==121}
} {10 99}