]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Bug fix: The IN operator was not working if either side derived from
authordrh <drh@noemail.net>
Mon, 28 Jan 2002 15:53:03 +0000 (15:53 +0000)
committerdrh <drh@noemail.net>
Mon, 28 Jan 2002 15:53:03 +0000 (15:53 +0000)
an INTEGER PRIMARY KEY. (CVS 354)

FossilOrigin-Name: dbcfe198fbaa155874ef82a96b6a4b993ccf3931

12 files changed:
VERSION
manifest
manifest.uuid
src/build.c
src/insert.c
src/select.c
src/update.c
src/vdbe.c
src/vdbe.h
src/where.c
test/in.test
www/changes.tcl

diff --git a/VERSION b/VERSION
index 530cdd91a205aaea0795fccb77f9314290e441e6..21bb5e156fbe2f70cdf3f02a8123b099130eeacb 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.4
+2.2.5
index 1e78302997d37ad57f67138b7d455742c535778e..beebc463552f22cd0e05df7bc3b3faa125d3fe25 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Do\snot\sescape\sthe\sbackslash\scharacter\sin\sshell\soutput.\s(CVS\s353)
-D 2002-01-24T00:00:21
+C Bug\sfix:\sThe\sIN\soperator\swas\snot\sworking\sif\seither\sside\sderived\sfrom\nan\sINTEGER\sPRIMARY\sKEY.\s(CVS\s354)
+D 2002-01-28T15:53:04
 F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
 F Makefile.template 3e26a3b9e7aee1b811deaf673e8d8973bdb3f22d
 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
-F VERSION 2af606990ed9af7308a6e04cd7c9efd550f4e7be
+F VERSION 79f8cff9811acbf454323afd9f2fa6cd2a8b7674
 F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
 F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588
 F config.log 6a73d03433669b10a3f0c221198c3f26b9413914
@@ -21,12 +21,12 @@ F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9
 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
 F src/btree.c c796e387da340cb628dc1e41f684fc20253f561e
 F src/btree.h 9ead7f54c270d8a554e59352ca7318fdaf411390
-F src/build.c bf8456b56011bb3761f11ff4a14121cfbbbd78da
+F src/build.c 3f40a6e6cea4180fb742a3d0ce71f06df8121cab
 F src/delete.c cc200609f927ee8fefdda5d11d3f3b2288493c0f
 F src/expr.c 4cae8bf44d5732182e5e8c25b4552c05ea55593e
 F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46
 F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
-F src/insert.c 813c37719866c583e6ca7660f94f10230f4e385d
+F src/insert.c e3a3b5a1d46a02778feb3e2ccd9a6989201c03b5
 F src/main.c 0205771a6c31a9858ff131fc1e797b589afb76bf
 F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
 F src/os.c c615faa4d23e742e0650e0751a6ad2a18438ad53
@@ -36,7 +36,7 @@ F src/pager.h f78d064c780855ff70beacbeba0e2324471b26fe
 F src/parse.y f3fc4fb5766393003577bd175eb611495f6efd9f
 F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
 F src/random.c f6b36bec5ebd3edb3440224bf5bf811fe4ac9a1b
-F src/select.c de0d1d12e258d339a7936556512680366177f277
+F src/select.c fc11d5a8c2bae1b62d8028ffb111c773ad6bf161
 F src/shell.c c102dfe388c7618a668c944ff157c49cb48f28e3
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
 F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c
@@ -47,11 +47,11 @@ F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f
 F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
 F src/test3.c d6775f95fd91f5b3cf0e2382a28e5aaeb68f745b
 F src/tokenize.c 830e9ef684334070a26583d94770bb869e2727bf
-F src/update.c f30a47928fb7e894221eab2a81c8fa2653f96fb0
+F src/update.c 6f87a9aa0b3ec0dfec0b0758104461445e701fdb
 F src/util.c 8f8973dd55a6ec63be9632fc5de86965c99d6327
-F src/vdbe.c 158bab65e4eafceb75a83f616caafa2c58f00242
-F src/vdbe.h e5cc6fb13d1905a4339db4d6dba4ab393c0765fa
-F src/where.c a9b286ac7323e7ebed5d3d217b3963acf1e6a355
+F src/vdbe.c 71c0b7d368dd4c58867d7e577df0ee5404e25722
+F src/vdbe.h 22d4df31cc16ca50b66b8125caec3495e5b407b2
+F src/where.c 2dda39367f193194e4c7d2e0dcab31527d9d8aba
 F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe
 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
 F test/btree.test 6ab4dc5f595905a276ef588fad3c9236dc07a47b
@@ -61,7 +61,7 @@ F test/copy.test 768e6f1701a07d08090e1ca7f7dcce0a7a72b43e
 F test/delete.test c904a62129fe102b314a96111a8417f10249e4d8
 F test/expr.test c8a495050dcec3f9e68538c3ef466726933302c1
 F test/func.test 51dbe3f8a4c28972751697423e6acc5d6b551df1
-F test/in.test 9323681388be301dc73f370b4cd62c5a33f79d1e
+F test/in.test c09312672e3f0709fa02c8e2e9cd8fb4bd6269aa
 F test/index.test c8a471243bbf878974b99baf5badd59407237cf3
 F test/insert.test a5c122aa726f1cef6f07d6767e8fd6f220994c11
 F test/insert2.test d6901ca931e308fea7fca8c95ebe7dc957cc9fc2
@@ -105,7 +105,7 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
 F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
 F www/c_interface.tcl 82a026b1681757f13b3f62e035f3a31407c1d353
-F www/changes.tcl f3f730787338087282e50bd27d152ed68686df15
+F www/changes.tcl 6b802e152436c7596308b6a4901e91415be0d9d4
 F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
 F www/download.tcl 1ea61f9d89a2a5a9b2cee36b0d5cf97321bdefe0
 F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
@@ -119,7 +119,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5
 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
 F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 16712dae4feedd001d8153141a55e298b3a80a94
-R 0530842c82f7bef6b5f9c0ae1cc69c65
+P 5f8c097ebef28315ac2335a768d101e995ccbba2
+R 8bfbd1ab9c2165331e9740c7a67704b7
 U drh
-Z 61c11f99131a5810bde1ae96d98c46d4
+Z 7c022c8c65d60ef92494dfd3fd54cead
index 6eeda72068f028392c873527426de0d2d225e3f2..fc78220e96bc810653e7a46f9b6f9c0b854930c0 100644 (file)
@@ -1 +1 @@
-5f8c097ebef28315ac2335a768d101e995ccbba2
\ No newline at end of file
+dbcfe198fbaa155874ef82a96b6a4b993ccf3931
\ No newline at end of file
index 1fbf6351d14bea69f77f460379c832d6e39188d1..22e68df83c2940e829f881eedde69cbf433f4cae 100644 (file)
@@ -25,7 +25,7 @@
 **     ROLLBACK
 **     PRAGMA
 **
-** $Id: build.c,v 1.65 2002/01/22 03:13:42 drh Exp $
+** $Id: build.c,v 1.66 2002/01/28 15:53:05 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -730,7 +730,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd){
       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);
+      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
       changeCookie(db);
       sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0);
       sqliteVdbeAddOp(v, OP_Close, 0, 0);
@@ -1074,7 +1074,7 @@ void sqliteCreateIndex(
         sqliteVdbeChangeP3(v, addr, pStart->z, n);
       }
       sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
-      sqliteVdbeAddOp(v, OP_Put, 0, 0);
+      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
     }
     if( pTable ){
       sqliteVdbeAddOp(v, isTemp ? OP_OpenAux : OP_Open, 2, pTab->tnum);
@@ -1383,7 +1383,7 @@ void sqliteCopy(
       }
     }
     sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
-    sqliteVdbeAddOp(v, OP_Put, 0, 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);
index d6d7638778b90d028f03338e4bc4672052bf23d1..c24d019e535212685d403034fca7c27fcd7b8b62 100644 (file)
@@ -12,7 +12,7 @@
 ** 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 $
+** $Id: insert.c,v 1.33 2002/01/28 15:53:05 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -252,7 +252,7 @@ void sqliteInsert(
   /* Create the new record and put it into the database.
   */
   sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
-  sqliteVdbeAddOp(v, OP_Put, base, keyColumn>=0);
+  sqliteVdbeAddOp(v, OP_PutIntKey, base, keyColumn>=0);
   
   /* Create appropriate entries for the new data row in all indices
   ** of the table.
index 9395d6f76a4e92118cd773b49694f0476a6d0a43..b0ef7081fedffcd45e1a4ef47bd2882722aa0d66 100644 (file)
@@ -12,7 +12,7 @@
 ** 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 $
+** $Id: select.c,v 1.56 2002/01/28 15:53:05 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -130,7 +130,7 @@ static int selectInnerLoop(
     sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
     sqliteVdbeResolveLabel(v, lbl);
     sqliteVdbeAddOp(v, OP_String, 0, 0);
-    sqliteVdbeAddOp(v, OP_Put, distinct, 0);
+    sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);
   }
 
   /* If there is an ORDER BY clause, then store the results
@@ -158,7 +158,7 @@ static int selectInnerLoop(
   if( eDest==SRT_Union ){
     sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
     sqliteVdbeAddOp(v, OP_String, iParm, 0);
-    sqliteVdbeAddOp(v, OP_Put, iParm, 0);
+    sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
   }else 
 
   /* Store the result as data using a unique key.
@@ -167,7 +167,7 @@ static int selectInnerLoop(
     sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
     sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);
     sqliteVdbeAddOp(v, OP_Pull, 1, 0);
-    sqliteVdbeAddOp(v, OP_Put, iParm, 0);
+    sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0);
   }else 
 
   /* Construct a record from the query result, but instead of
@@ -187,7 +187,7 @@ static int selectInnerLoop(
   if( eDest==SRT_Set ){
     assert( nColumn==1 );
     sqliteVdbeAddOp(v, OP_String, 0, 0);
-    sqliteVdbeAddOp(v, OP_Put, iParm, 0);
+    sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);
   }else 
 
 
index 016545aa9e3654c367b853f8183baf89ab971063..88df296423c4cdb3e7b9f6f9ddf078ceadc03fe2 100644 (file)
@@ -12,7 +12,7 @@
 ** 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 $
+** $Id: update.c,v 1.28 2002/01/28 15:53:05 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -265,7 +265,7 @@ void sqliteUpdate(
   /* Write the new data back into the database.
   */
   sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
-  sqliteVdbeAddOp(v, OP_Put, base, 0);
+  sqliteVdbeAddOp(v, OP_PutIntKey, base, 0);
 
   /* Increment the count of rows affected by the update
   */
index 602f9503bf573dca346e040be1ce9b7cb45b4e57..ce025f4624bc9a5fc3b3fa77fec3e139d15628e0 100644 (file)
@@ -30,7 +30,7 @@
 ** 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 $
+** $Id: vdbe.c,v 1.108 2002/01/28 15:53:05 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -852,31 +852,32 @@ 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",           
+  "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",           
 };
 
 /*
@@ -2645,7 +2646,7 @@ case OP_MoveTo: {
 
 /* Opcode: Distinct P1 P2 *
 **
-** Use the top of the stack as a key.  If a record with that key does
+** 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.
@@ -2657,7 +2658,7 @@ case OP_MoveTo: {
 */
 /* Opcode: Found P1 P2 *
 **
-** Use the top of the stack as a key.  If a record with that key
+** 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.
@@ -2666,7 +2667,7 @@ case OP_MoveTo: {
 */
 /* Opcode: NotFound P1 P2 *
 **
-** Use the top of the stack as a key.  If a record with that key
+** 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.
@@ -2674,7 +2675,7 @@ case OP_MoveTo: {
 ** The difference between this operation and Distinct is that
 ** Distinct does not pop the key from the stack.
 **
-** See also: Distinct, Found, MoveTo
+** See also: Distinct, Found, MoveTo, NotExists
 */
 case OP_Distinct:
 case OP_NotFound:
@@ -2686,13 +2687,8 @@ case OP_Found: {
   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);
-    }
+    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 ){
@@ -2706,6 +2702,38 @@ case OP_Found: {
   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.
@@ -2770,18 +2798,30 @@ case OP_NewRecno: {
   break;
 }
 
-/* Opcode: Put P1 P2 *
+/* 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 stack
-** is popped twice by this instruction.
+** 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_Put: {
+case OP_PutIntKey:
+case OP_PutStrKey: {
   int tos = p->tos;
   int nos = p->tos-1;
   int i = pOp->p1;
@@ -2789,11 +2829,12 @@ case OP_Put: {
   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( 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;
index 4f48f23a0750d87263b057ad9b8842d9c1854538..0f270b92fdaa4808a7c8d330dbb7b3fd892d58dc 100644 (file)
@@ -15,7 +15,7 @@
 ** 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 $
+** $Id: vdbe.h,v 1.38 2002/01/28 15:53:05 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -84,120 +84,122 @@ typedef struct VdbeOp VdbeOp;
 #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
+#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
index 526f2aeed223bcd15dddfabd27570b07712fceb9..022cfbb7b51a5fad2232675398eca3642581e197 100644 (file)
@@ -13,7 +13,7 @@
 ** 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 $
+** $Id: where.c,v 1.33 2002/01/28 15:53:05 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -439,12 +439,19 @@ WhereInfo *sqliteWhereBegin(
       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_Distinct, base+idx, brk);
+        sqliteVdbeAddOp(v, OP_Dup, 0, 0);
       }else{
-        sqliteVdbeAddOp(v, OP_NotFound, base+idx, brk);
         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.
index e8c9417f651421a851b3f09375b43d84133a45a3..92bc422507664c83c0de4b276fa50b1b7f5e5fda 100644 (file)
@@ -11,7 +11,7 @@
 # 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 $
+# $Id: in.test,v 1.6 2002/01/28 15:53:05 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -156,4 +156,72 @@ do_test in-5.1 {
   }
 } {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
index 02e9d74a41f9a7d4ac787276306ab1f3777a6163..2a6ba3c237c232abb19e61b7bad2d2785856ddfb 100644 (file)
@@ -17,6 +17,13 @@ proc chng {date desc} {
   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