SQLite

Check-in [dbcfe198fb]
Login

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

Overview
Comment:Bug fix: The IN operator was not working if either side derived from an INTEGER PRIMARY KEY. (CVS 354)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: dbcfe198fbaa155874ef82a96b6a4b993ccf3931
User & Date: drh 2002-01-28 15:53:04.000
Context
2002-01-28
16:00
Version 2.2.5 (CVS 448) (check-in: af3bb80810 user: drh tags: trunk)
15:53
Bug fix: The IN operator was not working if either side derived from an INTEGER PRIMARY KEY. (CVS 354) (check-in: dbcfe198fb user: drh tags: trunk)
2002-01-24
00:00
Do not escape the backslash character in shell output. (CVS 353) (check-in: 5f8c097ebe user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to VERSION.
1
2.2.4
|
1
2.2.5
Changes to src/build.c.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.65 2002/01/22 03:13:42 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.66 2002/01/28 15:53:05 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
    addr = sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp);
    sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER);
    p->tnum = 0;
    if( !p->isTemp ){
      addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, addr, pParse->sFirstToken.z, n);
      sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
      sqliteVdbeAddOp(v, OP_Put, 0, 0);
      changeCookie(db);
      sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0);
      sqliteVdbeAddOp(v, OP_Close, 0, 0);
    }
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0);
    }







|







726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
    addr = sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp);
    sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER);
    p->tnum = 0;
    if( !p->isTemp ){
      addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, addr, pParse->sFirstToken.z, n);
      sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
      changeCookie(db);
      sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0);
      sqliteVdbeAddOp(v, OP_Close, 0, 0);
    }
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0);
    }
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
    if( !isTemp ){
      addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
      if( pStart && pEnd ){
        n = Addr(pEnd->z) - Addr(pStart->z) + 1;
        sqliteVdbeChangeP3(v, addr, pStart->z, n);
      }
      sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
      sqliteVdbeAddOp(v, OP_Put, 0, 0);
    }
    if( pTable ){
      sqliteVdbeAddOp(v, isTemp ? OP_OpenAux : OP_Open, 2, pTab->tnum);
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      lbl2 = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
      lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);







|







1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
    if( !isTemp ){
      addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
      if( pStart && pEnd ){
        n = Addr(pEnd->z) - Addr(pStart->z) + 1;
        sqliteVdbeChangeP3(v, addr, pStart->z, n);
      }
      sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
    }
    if( pTable ){
      sqliteVdbeAddOp(v, isTemp ? OP_OpenAux : OP_Open, 2, pTab->tnum);
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      lbl2 = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
      lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
        ** value is always pulled from the record number */
        sqliteVdbeAddOp(v, OP_String, 0, 0);
      }else{
        sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
      }
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_Put, 0, 0);
    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( pIdx->pNext ){
        sqliteVdbeAddOp(v, OP_Dup, 0, 0);
      }
      for(j=0; j<pIdx->nColumn; j++){
        sqliteVdbeAddOp(v, OP_FileColumn, pIdx->aiColumn[j], 0);
      }







|







1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
        ** value is always pulled from the record number */
        sqliteVdbeAddOp(v, OP_String, 0, 0);
      }else{
        sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
      }
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( pIdx->pNext ){
        sqliteVdbeAddOp(v, OP_Dup, 0, 0);
      }
      for(j=0; j<pIdx->nColumn; j++){
        sqliteVdbeAddOp(v, OP_FileColumn, pIdx->aiColumn[j], 0);
      }
Changes to src/insert.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.32 2002/01/06 17:07:40 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.33 2002/01/28 15:53:05 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
      sqliteExprCode(pParse, pList->a[j].pExpr);
    }
  }

  /* Create the new record and put it into the database.
  */
  sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
  sqliteVdbeAddOp(v, OP_Put, base, keyColumn>=0);
  
  /* Create appropriate entries for the new data row in all indices
  ** of the table.
  */
  for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
    if( pIdx->pNext ){
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);







|







248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
      sqliteExprCode(pParse, pList->a[j].pExpr);
    }
  }

  /* Create the new record and put it into the database.
  */
  sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
  sqliteVdbeAddOp(v, OP_PutIntKey, base, keyColumn>=0);
  
  /* Create appropriate entries for the new data row in all indices
  ** of the table.
  */
  for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
    if( pIdx->pNext ){
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
Changes to src/select.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.55 2002/01/22 14:11:29 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.56 2002/01/28 15:53:05 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    int lbl = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);
    sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl);
    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
    sqliteVdbeResolveLabel(v, lbl);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeAddOp(v, OP_Put, distinct, 0);
  }

  /* If there is an ORDER BY clause, then store the results
  ** in a sorter.
  */
  if( pOrderBy ){
    char *zSortOrder;







|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    int lbl = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);
    sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl);
    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
    sqliteVdbeResolveLabel(v, lbl);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);
  }

  /* If there is an ORDER BY clause, then store the results
  ** in a sorter.
  */
  if( pOrderBy ){
    char *zSortOrder;
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

  /* In this mode, write each query result to the key of the temporary
  ** table iParm.
  */
  if( eDest==SRT_Union ){
    sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
    sqliteVdbeAddOp(v, OP_String, iParm, 0);
    sqliteVdbeAddOp(v, OP_Put, iParm, 0);
  }else 

  /* Store the result as data using a unique key.
  */
  if( eDest==SRT_Table ){
    sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
    sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);
    sqliteVdbeAddOp(v, OP_Pull, 1, 0);
    sqliteVdbeAddOp(v, OP_Put, iParm, 0);
  }else 

  /* Construct a record from the query result, but instead of
  ** saving that record, use it as a key to delete elements from
  ** the temporary table iParm.
  */
  if( eDest==SRT_Except ){
    int addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
    sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3);
    sqliteVdbeAddOp(v, OP_Delete, iParm, 0);
  }else 

  /* If we are creating a set for an "expr IN (SELECT ...)" construct,
  ** then there should be a single item on the stack.  Write this
  ** item into the set table with bogus data.
  */
  if( eDest==SRT_Set ){
    assert( nColumn==1 );
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeAddOp(v, OP_Put, iParm, 0);
  }else 


  /* If this is a scalar select that is part of an expression, then
  ** store the results in the appropriate memory cell and break out
  ** of the scan loop.
  */







|








|



















|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

  /* In this mode, write each query result to the key of the temporary
  ** table iParm.
  */
  if( eDest==SRT_Union ){
    sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
    sqliteVdbeAddOp(v, OP_String, iParm, 0);
    sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
  }else 

  /* Store the result as data using a unique key.
  */
  if( eDest==SRT_Table ){
    sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
    sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);
    sqliteVdbeAddOp(v, OP_Pull, 1, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0);
  }else 

  /* Construct a record from the query result, but instead of
  ** saving that record, use it as a key to delete elements from
  ** the temporary table iParm.
  */
  if( eDest==SRT_Except ){
    int addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
    sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3);
    sqliteVdbeAddOp(v, OP_Delete, iParm, 0);
  }else 

  /* If we are creating a set for an "expr IN (SELECT ...)" construct,
  ** then there should be a single item on the stack.  Write this
  ** item into the set table with bogus data.
  */
  if( eDest==SRT_Set ){
    assert( nColumn==1 );
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
  }else 


  /* If this is a scalar select that is part of an expression, then
  ** store the results in the appropriate memory cell and break out
  ** of the scan loop.
  */
Changes to src/update.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.27 2002/01/22 03:13:42 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.28 2002/01/28 15:53:05 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
    sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, pIdx->isUnique);
  }

  /* Write the new data back into the database.
  */
  sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
  sqliteVdbeAddOp(v, OP_Put, base, 0);

  /* Increment the count of rows affected by the update
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
  }








|







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
    sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, pIdx->isUnique);
  }

  /* Write the new data back into the database.
  */
  sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
  sqliteVdbeAddOp(v, OP_PutIntKey, base, 0);

  /* Increment the count of rows affected by the update
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
  }

Changes to src/vdbe.c.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.107 2002/01/16 21:00:27 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.108 2002/01/28 15:53:05 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
848
849
850
851
852
853
854
855
856

857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
** "opNames.awk" awk script which is part of the source tree to regenerate
** this array, then copy and paste it into this file, if you want.
*/
static char *zOpName[] = { 0,
  "Transaction",       "Commit",            "Rollback",          "ReadCookie",
  "SetCookie",         "VerifyCookie",      "Open",              "OpenTemp",
  "OpenWrite",         "OpenAux",           "OpenWrAux",         "Close",
  "MoveTo",            "NewRecno",          "Put",               "Distinct",
  "Found",             "NotFound",          "Delete",            "Column",

  "KeyAsData",         "Recno",             "FullKey",           "Rewind",
  "Next",              "Destroy",           "Clear",             "CreateIndex",
  "CreateTable",       "Reorganize",        "IdxPut",            "IdxDelete",
  "IdxRecno",          "IdxGT",             "IdxGE",             "MemLoad",
  "MemStore",          "ListWrite",         "ListRewind",        "ListRead",
  "ListReset",         "SortPut",           "SortMakeRec",       "SortMakeKey",
  "Sort",              "SortNext",          "SortCallback",      "SortReset",
  "FileOpen",          "FileRead",          "FileColumn",        "AggReset",
  "AggFocus",          "AggIncr",           "AggNext",           "AggSet",
  "AggGet",            "SetInsert",         "SetFound",          "SetNotFound",
  "MakeRecord",        "MakeKey",           "MakeIdxKey",        "IncrKey",
  "Goto",              "If",                "Halt",              "ColumnCount",
  "ColumnName",        "Callback",          "NullCallback",      "Integer",
  "String",            "Pop",               "Dup",               "Pull",
  "MustBeInt",         "Add",               "AddImm",            "Subtract",
  "Multiply",          "Divide",            "Remainder",         "BitAnd",
  "BitOr",             "BitNot",            "ShiftLeft",         "ShiftRight",
  "AbsValue",          "Precision",         "Min",               "Max",
  "Like",              "Glob",              "Eq",                "Ne",
  "Lt",                "Le",                "Gt",                "Ge",
  "IsNull",            "NotNull",           "Negative",          "And",
  "Or",                "Not",               "Concat",            "Noop",
  "Strlen",            "Substr",            "Limit",           
};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.







|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
** "opNames.awk" awk script which is part of the source tree to regenerate
** this array, then copy and paste it into this file, if you want.
*/
static char *zOpName[] = { 0,
  "Transaction",       "Commit",            "Rollback",          "ReadCookie",
  "SetCookie",         "VerifyCookie",      "Open",              "OpenTemp",
  "OpenWrite",         "OpenAux",           "OpenWrAux",         "Close",
  "MoveTo",            "NewRecno",          "PutIntKey",         "PutStrKey",
  "Distinct",          "Found",             "NotFound",          "NotExists",
  "Delete",            "Column",            "KeyAsData",         "Recno",
  "FullKey",           "Rewind",            "Next",              "Destroy",
  "Clear",             "CreateIndex",       "CreateTable",       "Reorganize",
  "IdxPut",            "IdxDelete",         "IdxRecno",          "IdxGT",
  "IdxGE",             "MemLoad",           "MemStore",          "ListWrite",
  "ListRewind",        "ListRead",          "ListReset",         "SortPut",
  "SortMakeRec",       "SortMakeKey",       "Sort",              "SortNext",
  "SortCallback",      "SortReset",         "FileOpen",          "FileRead",
  "FileColumn",        "AggReset",          "AggFocus",          "AggIncr",
  "AggNext",           "AggSet",            "AggGet",            "SetInsert",
  "SetFound",          "SetNotFound",       "MakeRecord",        "MakeKey",
  "MakeIdxKey",        "IncrKey",           "Goto",              "If",
  "Halt",              "ColumnCount",       "ColumnName",        "Callback",
  "NullCallback",      "Integer",           "String",            "Pop",
  "Dup",               "Pull",              "MustBeInt",         "Add",
  "AddImm",            "Subtract",          "Multiply",          "Divide",
  "Remainder",         "BitAnd",            "BitOr",             "BitNot",
  "ShiftLeft",         "ShiftRight",        "AbsValue",          "Precision",
  "Min",               "Max",               "Like",              "Glob",
  "Eq",                "Ne",                "Lt",                "Le",
  "Gt",                "Ge",                "IsNull",            "NotNull",
  "Negative",          "And",               "Or",                "Not",
  "Concat",            "Noop",              "Strlen",            "Substr",
  "Limit",           
};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
































2708
2709
2710
2711
2712
2713
2714
  }
  POPSTACK;
  break;
}

/* Opcode: Distinct P1 P2 *
**
** Use the top of the stack as a key.  If a record with that key does
** not exist in the table of cursor P1, then jump to P2.  If the record
** does already exist, then fall thru.  The cursor is left pointing
** at the record if it exists. The key is not popped from the stack.
**
** This operation is similar to NotFound except that this operation
** does not pop the key from the stack.
**
** See also: Found, NotFound, MoveTo
*/
/* Opcode: Found P1 P2 *
**
** Use the top of the stack as a key.  If a record with that key
** does exist in table of P1, then jump to P2.  If the record
** does not exist, then fall thru.  The cursor is left pointing
** to the record if it exists.  The key is popped from the stack.
**
** See also: Distinct, NotFound, MoveTo
*/
/* Opcode: NotFound P1 P2 *
**
** Use the top of the stack as a key.  If a record with that key
** does not exist in table of P1, then jump to P2.  If the record
** does exist, then fall thru.  The cursor is left pointing to the
** record if it exists.  The key is popped from the stack.
**
** The difference between this operation and Distinct is that
** Distinct does not pop the key from the stack.
**
** See also: Distinct, Found, MoveTo
*/
case OP_Distinct:
case OP_NotFound:
case OP_Found: {
  int i = pOp->p1;
  int tos = p->tos;
  int alreadyExists = 0;
  Cursor *pC;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
    int res, rx;
    if( aStack[tos].flags & STK_Int ){
      int iKey = intToKey(aStack[tos].i);
      rx = sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
    }else{
      if( Stringify(p, tos) ) goto no_mem;
      rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
    }
    alreadyExists = rx==SQLITE_OK && res==0;
  }
  if( pOp->opcode==OP_Found ){
    if( alreadyExists ) pc = pOp->p2 - 1;
  }else{
    if( !alreadyExists ) pc = pOp->p2 - 1;
  }
  if( pOp->opcode!=OP_Distinct ){
    POPSTACK;
  }
  break;
}

































/* Opcode: NewRecno P1 * *
**
** Get a new integer record number used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to.  The new record number is pushed 
** onto the stack.







|











|








|







|











<
<
<
<
|
|
<












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689




2690
2691

2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
  }
  POPSTACK;
  break;
}

/* Opcode: Distinct P1 P2 *
**
** Use the top of the stack as a string key.  If a record with that key does
** not exist in the table of cursor P1, then jump to P2.  If the record
** does already exist, then fall thru.  The cursor is left pointing
** at the record if it exists. The key is not popped from the stack.
**
** This operation is similar to NotFound except that this operation
** does not pop the key from the stack.
**
** See also: Found, NotFound, MoveTo
*/
/* Opcode: Found P1 P2 *
**
** Use the top of the stack as a string key.  If a record with that key
** does exist in table of P1, then jump to P2.  If the record
** does not exist, then fall thru.  The cursor is left pointing
** to the record if it exists.  The key is popped from the stack.
**
** See also: Distinct, NotFound, MoveTo
*/
/* Opcode: NotFound P1 P2 *
**
** Use the top of the stack as a string key.  If a record with that key
** does not exist in table of P1, then jump to P2.  If the record
** does exist, then fall thru.  The cursor is left pointing to the
** record if it exists.  The key is popped from the stack.
**
** The difference between this operation and Distinct is that
** Distinct does not pop the key from the stack.
**
** See also: Distinct, Found, MoveTo, NotExists
*/
case OP_Distinct:
case OP_NotFound:
case OP_Found: {
  int i = pOp->p1;
  int tos = p->tos;
  int alreadyExists = 0;
  Cursor *pC;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
    int res, rx;




    if( Stringify(p, tos) ) goto no_mem;
    rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);

    alreadyExists = rx==SQLITE_OK && res==0;
  }
  if( pOp->opcode==OP_Found ){
    if( alreadyExists ) pc = pOp->p2 - 1;
  }else{
    if( !alreadyExists ) pc = pOp->p2 - 1;
  }
  if( pOp->opcode!=OP_Distinct ){
    POPSTACK;
  }
  break;
}

/* Opcode: NotExists P1 P2 *
**
** Use the top of the stack as a integer key.  If a record with that key
** does not exist in table of P1, then jump to P2.  If the record
** does exist, then fall thru.  The cursor is left pointing to the
** record if it exists.  The integer key is popped from the stack.
**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and NotFound assumes it
** is a string.
**
** See also: Distinct, Found, MoveTo, NotExists
*/
case OP_NotExists: {
  int i = pOp->p1;
  int tos = p->tos;
  int alreadyExists = 0;
  Cursor *pC;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
    int res, rx, iKey;
    assert( aStack[tos].flags & STK_Int );
    iKey = intToKey(aStack[tos].i);
    rx = sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
    if( rx!=SQLITE_OK || res!=0 ){
       pc = pOp->p2 - 1;
    }
  }
  POPSTACK;
  break;
}

/* Opcode: NewRecno P1 * *
**
** Get a new integer record number used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to.  The new record number is pushed 
** onto the stack.
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
  VERIFY( NeedStack(p, p->tos+1); )
  p->tos++;
  aStack[p->tos].i = v;
  aStack[p->tos].flags = STK_Int;
  break;
}

/* Opcode: Put P1 P2 *











**
** Write an entry into the database file P1.  A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten.  The data is the value on the top of the
** stack.  The key is the next value down on the stack.  The stack
** is popped twice by this instruction.
**
** If P2==1 then overwriting is prohibited.  If a prior entry with
** the same key exists, an SQLITE_CONSTRAINT exception is raised.
*/
case OP_Put: {

  int tos = p->tos;
  int nos = p->tos-1;
  int i = pOp->p1;
  VERIFY( if( nos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){
    char *zKey;
    int nKey, iKey;
    if( (aStack[nos].flags & STK_Int)==0 ){
      if( Stringify(p, nos) ) goto no_mem;
      nKey = aStack[nos].n;
      zKey = zStack[nos];
    }else{

      nKey = sizeof(int);
      iKey = intToKey(aStack[nos].i);
      zKey = (char*)&iKey;
      db->lastRowid = aStack[nos].i;
    }
    if( pOp->p2 ){
      int res;







|
>
>
>
>
>
>
>
>
>
>
>




|
|




|
>







|




>







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
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
  VERIFY( NeedStack(p, p->tos+1); )
  p->tos++;
  aStack[p->tos].i = v;
  aStack[p->tos].flags = STK_Int;
  break;
}

/* Opcode: PutIK P1 P2 *
**
** Write an entry into the database file P1.  A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten.  The data is the value on the top of the
** stack.  The key is the next value down on the stack.  The key must
** be an integer.  The stack is popped twice by this instruction.
**
** If P2==1 then overwriting is prohibited.  If a prior entry with
** the same key exists, an SQLITE_CONSTRAINT exception is raised.
*/
/* Opcode: PutSK P1 P2 *
**
** Write an entry into the database file P1.  A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten.  The data is the value on the top of the
** stack.  The key is the next value down on the stack.  The key must
** be a string.  The stack is popped twice by this instruction.
**
** If P2==1 then overwriting is prohibited.  If a prior entry with
** the same key exists, an SQLITE_CONSTRAINT exception is raised.
*/
case OP_PutIntKey:
case OP_PutStrKey: {
  int tos = p->tos;
  int nos = p->tos-1;
  int i = pOp->p1;
  VERIFY( if( nos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){
    char *zKey;
    int nKey, iKey;
    if( pOp->opcode==OP_PutStrKey ){
      if( Stringify(p, nos) ) goto no_mem;
      nKey = aStack[nos].n;
      zKey = zStack[nos];
    }else{
      assert( aStack[nos].flags & STK_Int );
      nKey = sizeof(int);
      iKey = intToKey(aStack[nos].i);
      zKey = (char*)&iKey;
      db->lastRowid = aStack[nos].i;
    }
    if( pOp->p2 ){
      int res;
Changes to src/vdbe.h.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.37 2001/12/22 14:49:26 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.38 2002/01/28 15:53:05 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
80
81
82
83
84
85
86
87

88
89
90

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#define OP_OpenTemp            8
#define OP_OpenWrite           9
#define OP_OpenAux            10
#define OP_OpenWrAux          11
#define OP_Close              12
#define OP_MoveTo             13
#define OP_NewRecno           14
#define OP_Put                15

#define OP_Distinct           16
#define OP_Found              17
#define OP_NotFound           18

#define OP_Delete             19
#define OP_Column             20
#define OP_KeyAsData          21
#define OP_Recno              22
#define OP_FullKey            23
#define OP_Rewind             24
#define OP_Next               25

#define OP_Destroy            26
#define OP_Clear              27
#define OP_CreateIndex        28
#define OP_CreateTable        29
#define OP_Reorganize         30

#define OP_IdxPut             31
#define OP_IdxDelete          32
#define OP_IdxRecno           33
#define OP_IdxGT              34
#define OP_IdxGE              35

#define OP_MemLoad            36
#define OP_MemStore           37

#define OP_ListWrite          38
#define OP_ListRewind         39
#define OP_ListRead           40
#define OP_ListReset          41

#define OP_SortPut            42
#define OP_SortMakeRec        43
#define OP_SortMakeKey        44
#define OP_Sort               45
#define OP_SortNext           46
#define OP_SortCallback       47
#define OP_SortReset          48

#define OP_FileOpen           49
#define OP_FileRead           50
#define OP_FileColumn         51

#define OP_AggReset           52
#define OP_AggFocus           53
#define OP_AggIncr            54
#define OP_AggNext            55
#define OP_AggSet             56
#define OP_AggGet             57

#define OP_SetInsert          58
#define OP_SetFound           59
#define OP_SetNotFound        60

#define OP_MakeRecord         61
#define OP_MakeKey            62
#define OP_MakeIdxKey         63
#define OP_IncrKey            64

#define OP_Goto               65
#define OP_If                 66
#define OP_Halt               67

#define OP_ColumnCount        68
#define OP_ColumnName         69
#define OP_Callback           70
#define OP_NullCallback       71

#define OP_Integer            72
#define OP_String             73
#define OP_Pop                74
#define OP_Dup                75
#define OP_Pull               76
#define OP_MustBeInt          77

#define OP_Add                78
#define OP_AddImm             79
#define OP_Subtract           80
#define OP_Multiply           81
#define OP_Divide             82
#define OP_Remainder          83
#define OP_BitAnd             84
#define OP_BitOr              85
#define OP_BitNot             86
#define OP_ShiftLeft          87
#define OP_ShiftRight         88
#define OP_AbsValue           89
#define OP_Precision          90
#define OP_Min                91
#define OP_Max                92
#define OP_Like               93
#define OP_Glob               94
#define OP_Eq                 95
#define OP_Ne                 96
#define OP_Lt                 97
#define OP_Le                 98
#define OP_Gt                 99
#define OP_Ge                100
#define OP_IsNull            101
#define OP_NotNull           102
#define OP_Negative          103
#define OP_And               104
#define OP_Or                105
#define OP_Not               106
#define OP_Concat            107
#define OP_Noop              108

#define OP_Strlen            109
#define OP_Substr            110

#define OP_Limit             111

#define OP_MAX               111

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(sqlite*);
void sqliteVdbeCreateCallback(Vdbe*, int*);







|
>
|
|
|
>
|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|

|
|
|
|

|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|

|
|
|

|
|
|
|

|
|
|

|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|

|

|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#define OP_OpenTemp            8
#define OP_OpenWrite           9
#define OP_OpenAux            10
#define OP_OpenWrAux          11
#define OP_Close              12
#define OP_MoveTo             13
#define OP_NewRecno           14
#define OP_PutIntKey          15
#define OP_PutStrKey          16
#define OP_Distinct           17
#define OP_Found              18
#define OP_NotFound           19
#define OP_NotExists          20
#define OP_Delete             21
#define OP_Column             22
#define OP_KeyAsData          23
#define OP_Recno              24
#define OP_FullKey            25
#define OP_Rewind             26
#define OP_Next               27

#define OP_Destroy            28
#define OP_Clear              29
#define OP_CreateIndex        30
#define OP_CreateTable        31
#define OP_Reorganize         32

#define OP_IdxPut             33
#define OP_IdxDelete          34
#define OP_IdxRecno           35
#define OP_IdxGT              36
#define OP_IdxGE              37

#define OP_MemLoad            38
#define OP_MemStore           39

#define OP_ListWrite          40
#define OP_ListRewind         41
#define OP_ListRead           42
#define OP_ListReset          43

#define OP_SortPut            44
#define OP_SortMakeRec        45
#define OP_SortMakeKey        46
#define OP_Sort               47
#define OP_SortNext           48
#define OP_SortCallback       49
#define OP_SortReset          50

#define OP_FileOpen           51
#define OP_FileRead           52
#define OP_FileColumn         53

#define OP_AggReset           54
#define OP_AggFocus           55
#define OP_AggIncr            56
#define OP_AggNext            57
#define OP_AggSet             58
#define OP_AggGet             59

#define OP_SetInsert          60
#define OP_SetFound           61
#define OP_SetNotFound        62

#define OP_MakeRecord         63
#define OP_MakeKey            64
#define OP_MakeIdxKey         65
#define OP_IncrKey            66

#define OP_Goto               67
#define OP_If                 68
#define OP_Halt               69

#define OP_ColumnCount        70
#define OP_ColumnName         71
#define OP_Callback           72
#define OP_NullCallback       73

#define OP_Integer            74
#define OP_String             75
#define OP_Pop                76
#define OP_Dup                77
#define OP_Pull               78
#define OP_MustBeInt          79

#define OP_Add                80
#define OP_AddImm             81
#define OP_Subtract           82
#define OP_Multiply           83
#define OP_Divide             84
#define OP_Remainder          85
#define OP_BitAnd             86
#define OP_BitOr              87
#define OP_BitNot             88
#define OP_ShiftLeft          89
#define OP_ShiftRight         90
#define OP_AbsValue           91
#define OP_Precision          92
#define OP_Min                93
#define OP_Max                94
#define OP_Like               95
#define OP_Glob               96
#define OP_Eq                 97
#define OP_Ne                 98
#define OP_Lt                 99
#define OP_Le                100
#define OP_Gt                101
#define OP_Ge                102
#define OP_IsNull            103
#define OP_NotNull           104
#define OP_Negative          105
#define OP_And               106
#define OP_Or                107
#define OP_Not               108
#define OP_Concat            109
#define OP_Noop              110

#define OP_Strlen            111
#define OP_Substr            112

#define OP_Limit             113

#define OP_MAX               113

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(sqlite*);
void sqliteVdbeCreateCallback(Vdbe*, int*);
Changes to src/where.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    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.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.32 2002/01/09 03:20:00 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.







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    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.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.33 2002/01/28 15:53:05 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.
435
436
437
438
439
440
441







442
443
444
445
446
447

448
449
450
451
452
453
454
        sqliteExprCode(pParse, aExpr[k].p->pLeft);
      }
      aExpr[k].p = 0;
      brk = pLevel->brk = sqliteVdbeMakeLabel(v);
      cont = pLevel->cont = brk;
      sqliteVdbeAddOp(v, OP_MustBeInt, 0, brk);
      if( i==pTabList->nId-1 && pushKey ){







        haveKey = 1;
        sqliteVdbeAddOp(v, OP_Distinct, base+idx, brk);
      }else{
        sqliteVdbeAddOp(v, OP_NotFound, base+idx, brk);
        haveKey = 0;
      }

      pLevel->op = OP_Noop;
    }else if( pIdx!=0 && pLevel->score%4==0 ){
      /* Case 2:  All index constraints are equality operators.
      */
      int start;
      int testOp;
      int nColumn = pLevel->score/4;







>
>
>
>
>
>
>

|

<


>







435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459
460
461
        sqliteExprCode(pParse, aExpr[k].p->pLeft);
      }
      aExpr[k].p = 0;
      brk = pLevel->brk = sqliteVdbeMakeLabel(v);
      cont = pLevel->cont = brk;
      sqliteVdbeAddOp(v, OP_MustBeInt, 0, brk);
      if( i==pTabList->nId-1 && pushKey ){
        /* Note: The OP_Dup below will cause the key to be left on the
        ** stack if the key does not exists and the OP_NotExists jump is
        ** taken.  This violates a general rule of the VDBE that you should
        ** never leave values on the stack in order to avoid a stack overflow.
        ** But in this case, the OP_Dup will never happen inside of a loop,
        ** so it is safe to leave it on the stack.
        */
        haveKey = 1;
        sqliteVdbeAddOp(v, OP_Dup, 0, 0);
      }else{

        haveKey = 0;
      }
      sqliteVdbeAddOp(v, OP_NotExists, base+idx, brk);
      pLevel->op = OP_Noop;
    }else if( pIdx!=0 && pLevel->score%4==0 ){
      /* Case 2:  All index constraints are equality operators.
      */
      int start;
      int testOp;
      int nColumn = pLevel->score/4;
Changes to test/in.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    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 IN and BETWEEN operator.
#
# $Id: in.test,v 1.5 2001/09/16 00:13:28 drh Exp $

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

# Generate the test data we will need for the first squences of tests.
#
do_test in-1.0 {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    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 IN and BETWEEN operator.
#
# $Id: in.test,v 1.6 2002/01/28 15:53:05 drh Exp $

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

# Generate the test data we will need for the first squences of tests.
#
do_test in-1.0 {
151
152
153
154
155
156
157
158




































































159
    WHERE a IN (
       'Do','an','IN','with','a','constant','RHS','but','where','the',
       'has','many','elements','We','need','to','test','that',
       'collisions','hash','table','are','resolved','properly',
       'This','in-set','contains','thirty','one','entries','hello');
  }
} {hello world}





































































finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    WHERE a IN (
       'Do','an','IN','with','a','constant','RHS','but','where','the',
       'has','many','elements','We','need','to','test','that',
       'collisions','hash','table','are','resolved','properly',
       'This','in-set','contains','thirty','one','entries','hello');
  }
} {hello world}

# Make sure the IN operator works with INTEGER PRIMARY KEY fields.
#
do_test in-6.1 {
  execsql {
    CREATE TABLE ta(a INTEGER PRIMARY KEY, b);
    INSERT INTO ta VALUES(1,1);
    INSERT INTO ta VALUES(2,2);
    INSERT INTO ta VALUES(3,3);
    INSERT INTO ta VALUES(4,4);
    INSERT INTO ta VALUES(6,6);
    INSERT INTO ta VALUES(8,8);
    SELECT * FROM ta;
  }
} {1 1 2 2 3 3 4 4 6 6 8 8}
do_test in-6.2 {
  execsql {
    CREATE TABLE tb(a INTEGER PRIMARY KEY, b);
    INSERT INTO tb VALUES(1,1);
    INSERT INTO tb VALUES(2,2);
    INSERT INTO tb VALUES(3,3);
    INSERT INTO tb VALUES(5,5);
    INSERT INTO tb VALUES(7,7);
    INSERT INTO tb VALUES(9,9);
    SELECT * FROM tb;
  }
} {1 1 2 2 3 3 5 5 7 7 9 9}
do_test in-6.3 {
  execsql {
    SELECT a FROM ta WHERE b IN (SELECT a FROM tb);
  }
} {1 2 3}
do_test in-6.4 {
  execsql {
    SELECT a FROM ta WHERE b NOT IN (SELECT a FROM tb);
  }
} {4 6 8}
do_test in-6.5 {
  execsql {
    SELECT a FROM ta WHERE b IN (SELECT b FROM tb);
  }
} {1 2 3}
do_test in-6.6 {
  execsql {
    SELECT a FROM ta WHERE b NOT IN (SELECT b FROM tb);
  }
} {4 6 8}
do_test in-6.7 {
  execsql {
    SELECT a FROM ta WHERE a IN (SELECT a FROM tb);
  }
} {1 2 3}
do_test in-6.8 {
  execsql {
    SELECT a FROM ta WHERE a NOT IN (SELECT a FROM tb);
  }
} {4 6 8}
do_test in-6.9 {
  execsql {
    SELECT a FROM ta WHERE a IN (SELECT b FROM tb);
  }
} {1 2 3}
do_test in-6.10 {
  execsql {
    SELECT a FROM ta WHERE a NOT IN (SELECT b FROM tb);
  }
} {4 6 8}


finish_test
Changes to www/changes.tcl.
12
13
14
15
16
17
18







19
20
21
22
23
24
25
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}








chng {2002 Jan 22 (2.2.4)} {
<li>The label to the right of an AS in the column list of a SELECT can now
    be used as part of an expression in the WHERE, ORDER BY, GROUP BY, and/or
    HAVING clauses.</li>
<li>Fix a bug in the <b>-separator</b> command-line option to the <b>sqlite</b>
    command.</li>







>
>
>
>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}

chng {2002 Jan 28 (2.2.5)} {
<li>Important bug fix: the IN operator was not working if either the
    left-hand or right-hand side was derived from an INTEGER PRIMARY KEY.</li>
<li>Do not escape the backslash '\' character in the output of the
    <b>sqlite</b> command-line access program.</li>
}

chng {2002 Jan 22 (2.2.4)} {
<li>The label to the right of an AS in the column list of a SELECT can now
    be used as part of an expression in the WHERE, ORDER BY, GROUP BY, and/or
    HAVING clauses.</li>
<li>Fix a bug in the <b>-separator</b> command-line option to the <b>sqlite</b>
    command.</li>