]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Additional changes toward fixing ticket #3292. (CVS 5562)
authordrh <drh@noemail.net>
Wed, 13 Aug 2008 19:11:48 +0000 (19:11 +0000)
committerdrh <drh@noemail.net>
Wed, 13 Aug 2008 19:11:48 +0000 (19:11 +0000)
FossilOrigin-Name: 0b92cbf5255020d4fde382f81590ff0488936667

manifest
manifest.uuid
src/btree.c
src/btree.h
src/sqliteInt.h
src/test3.c
src/vdbe.c
src/vdbe.h
src/vdbeInt.h
src/vdbeaux.c

index 4a0b7cfdf207b4baea6582104e4bc4fccdeb5011..7592083adc0fe49b1863776f623334184dcb9103 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C A\spartial\sfix\sfor\sticket\s#3292.\s\sThis\sfixes\sthe\soriginal\sproblem\sbut\sthere\nare\sother\ssimilar\sproblems\slurking\sin\sthe\scode\sstill.\s(CVS\s5561)
-D 2008-08-13T14:07:40
+C Additional\schanges\stoward\sfixing\sticket\s#3292.\s(CVS\s5562)
+D 2008-08-13T19:11:48
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 2713ea64947be3b35f35d9a3158bb8299c90b019
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -96,8 +96,8 @@ F src/attach.c a85c14612e7e3410e0c3d2e0241832fa9688bd14
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/bitvec.c 95c86bd18d8fedf0533f5af196192546e10a7e7d
 F src/btmutex.c 709cad2cdca0afd013f0f612363810e53f59ec53
-F src/btree.c 2ae1092eee58d2d89e5d2f59f711f805dec59bbc
-F src/btree.h 03256ed7ee42b5ecacbe887070b0f8249e7d069d
+F src/btree.c c38431aed9dcdf62916c9009d6f9971e588189fe
+F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
 F src/btreeInt.h ab18c7b4980314e9e4b402e5dcde09f3c2545576
 F src/build.c 931ed94fd3bbd67b6ac9d5ac6a45dc01e9f01726
 F src/callback.c c9f75a4c403f166af3761df47d78a806587d63af
@@ -146,14 +146,14 @@ F src/select.c 390d1bdde0c24f0225e369896da8e60ef2aeffbe
 F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
 F src/sqlite.h.in 54e51c22e2294c5989156b0aec87aa44168ac1f0
 F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e
-F src/sqliteInt.h df48efd8c4cb7b833bd7299a41c59c6651be0072
+F src/sqliteInt.h 7c68cacc760e8038ba6221c4d9ee3a7f0580e181
 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
 F src/status.c 8caa772cd9310bc297280f7cf0ede4d69ed5b801
 F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
 F src/tclsqlite.c ec46084184f033ba396a9ee7b5514b695083d0f3
 F src/test1.c 0ae2203b03dec8ecf8ad731038df47ba27bfe68c
 F src/test2.c 7a634c1e044be3ea5845e65155fdd1cab13936cb
-F src/test3.c e00795839be38f0345a4845170426fb17d828bf9
+F src/test3.c e85b7ce5c28c3ce7fbdbf7f98e1467b19786c62b
 F src/test4.c 41056378671e7b00e6305fa9ac6fa27e6f96f406
 F src/test5.c 162a1cea2105a2c460a3f39fa6919617b562a288
 F src/test6.c 0a0304a69cfa4962a429d084c6d451ff9e4fb572
@@ -183,11 +183,11 @@ F src/update.c 79b77a3cc8ed5f8903a7f37055fcedd69388dcae
 F src/utf.c c63e6f69082f85c19ab88d62dedaf91d71ac1a50
 F src/util.c afe659ccc05d1f8af9e8631dabfec3ee3a7144af
 F src/vacuum.c ef342828002debc97514617af3424aea8ef8522c
-F src/vdbe.c cda10a8e6ac05c783d6cd8a1d4852754fa73cf3b
-F src/vdbe.h ccca49ce3db3486ae27f9baec68a77ccc29c43a9
-F src/vdbeInt.h 6f04c2bf65a0d5c2bb8318b226278a35d1f7a8f5
+F src/vdbe.c e2dd0c78c5579e23db49ed8265f0b44d7b22c51d
+F src/vdbe.h 17bcc2b41082f9b99718b3757cbf97145a72023a
+F src/vdbeInt.h b48c74d86a9fb62b707a3186ccca76bb32f1c6be
 F src/vdbeapi.c f21971516880fd3a10821b2cdd0e64a5a63952c9
-F src/vdbeaux.c 7b25fbbbdbd548b71c0a44d2f90fd3d0b06e70b8
+F src/vdbeaux.c 3e2e1f36c25eae32bdd605456c8be99f73e71eaf
 F src/vdbeblob.c f93110888ddc246215e9ba1f831d3d375bfd8355
 F src/vdbefifo.c 20fda2a7c4c0bcee1b90eb7e545fefcdbf2e1de7
 F src/vdbemem.c c37b2a266a49eaf0c0f5080157f9f1a908fdaac3
@@ -618,7 +618,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P d6aacc5dc7c06f97fb5faa3d85a8f2d8ab0dd554
-R 9b480ed8f28854c07567551a082c6f07
+P 055f173ab1b6fb657bf817faa3a37335d8fa60d5
+R 3660b918f4cbadc772ff6c9bb7d03fb8
 U drh
-Z d0f90d7840e7d910b5f941e8ef52ae1d
+Z ef96eabf3e6f46a636feb3cbdfe8a28b
index c7a7043d69b3d32289c5cdf3e0505e8916811ee4..db4a82ec543e4dfd13206422a83430f3011a9a20 100644 (file)
@@ -1 +1 @@
-055f173ab1b6fb657bf817faa3a37335d8fa60d5
\ No newline at end of file
+0b92cbf5255020d4fde382f81590ff0488936667
\ No newline at end of file
index a75da9c615ab91b050633ee54cc9591c2e1c391c..f00422da43c56d61fc6036a6312d7f4bedacc608 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.496 2008/08/13 14:07:40 drh Exp $
+** $Id: btree.c,v 1.497 2008/08/13 19:11:48 drh Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** See the header comment on "btreeInt.h" for additional information.
@@ -375,7 +375,7 @@ int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur){
     return pCur->skip;
   }
   pCur->eState = CURSOR_INVALID;
-  rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip);
+  rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip);
   if( rc==SQLITE_OK ){
     sqlite3_free(pCur->pKey);
     pCur->pKey = 0;
@@ -3648,12 +3648,11 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
 }
 
 /* Move the cursor so that it points to an entry near the key 
-** specified by pKey/nKey/pUnKey. Return a success code.
+** specified by pIdxKey or intKey.   Return a success code.
 **
-** For INTKEY tables, only the nKey parameter is used.  pKey 
-** and pUnKey must be NULL.  For index tables, either pUnKey
-** must point to a key that has already been unpacked, or else
-** pKey/nKey describes a blob containing the key.
+** For INTKEY tables, the intKey parameter is used.  pIdxKey 
+** must be NULL.  For index tables, pIdxKey is used and intKey
+** is ignored.
 **
 ** If an exact match is not found, then the cursor is always
 ** left pointing at a leaf page which would hold the entry if it
@@ -3675,16 +3674,14 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
 **                  is larger than pKey.
 **
 */
-int sqlite3BtreeMoveto(
-  BtCursor *pCur,        /* The cursor to be moved */
-  const void *pKey,      /* The key content for indices.  Not used by tables */
-  UnpackedRecord *pUnKey,/* Unpacked version of pKey */
-  i64 nKey,              /* Size of pKey.  Or the key for tables */
-  int biasRight,         /* If true, bias the search to the high end */
-  int *pRes              /* Search result flag */
+int sqlite3BtreeMovetoUnpacked(
+  BtCursor *pCur,          /* The cursor to be moved */
+  UnpackedRecord *pIdxKey, /* Unpacked index key */
+  i64 intKey,              /* The table key */
+  int biasRight,           /* If true, bias the search to the high end */
+  int *pRes                /* Write search results here */
 ){
   int rc;
-  char aSpace[200];
 
   assert( cursorHoldsMutex(pCur) );
   assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
@@ -3692,11 +3689,11 @@ int sqlite3BtreeMoveto(
   /* If the cursor is already positioned at the point we are trying
   ** to move to, then just return without doing any work */
   if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->pPage->intKey ){
-    if( pCur->info.nKey==nKey ){
+    if( pCur->info.nKey==intKey ){
       *pRes = 0;
       return SQLITE_OK;
     }
-    if( pCur->atLast && pCur->info.nKey<nKey ){
+    if( pCur->atLast && pCur->info.nKey<intKey ){
       *pRes = -1;
       return SQLITE_OK;
     }
@@ -3714,24 +3711,7 @@ int sqlite3BtreeMoveto(
     assert( pCur->pPage->nCell==0 );
     return SQLITE_OK;
   }
-  if( pCur->pPage->intKey ){
-    /* We are given an SQL table to search.  The key is the integer
-    ** rowid contained in nKey.  pKey and pUnKey should both be NULL */
-    assert( pUnKey==0 );
-    assert( pKey==0 );
-  }else if( pUnKey==0 ){
-    /* We are to search an SQL index using a key encoded as a blob.
-    ** The blob is found at pKey and is nKey bytes in length.  Unpack
-    ** this key so that we can use it. */
-    assert( pKey!=0 );
-    pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
-                                   aSpace, sizeof(aSpace));
-    if( pUnKey==0 ) return SQLITE_NOMEM;
-  }else{
-    /* We are to search an SQL index using a key that is already unpacked
-    ** and handed to us in pUnKey. */
-    assert( pKey==0 );
-  }
+  assert( pCur->pPage->intKey || pIdxKey );
   for(;;){
     int lwr, upr;
     Pgno chldPg;
@@ -3739,7 +3719,7 @@ int sqlite3BtreeMoveto(
     int c = -1;  /* pRes return if table is empty must be -1 */
     lwr = 0;
     upr = pPage->nCell-1;
-    if( !pPage->intKey && pUnKey==0 ){
+    if( !pPage->intKey && pIdxKey==0 ){
       rc = SQLITE_CORRUPT_BKPT;
       goto moveto_finish;
     }
@@ -3761,12 +3741,12 @@ int sqlite3BtreeMoveto(
           pCell += getVarint32(pCell, dummy);
         }
         getVarint(pCell, (u64*)&nCellKey);
-        if( nCellKey==nKey ){
+        if( nCellKey==intKey ){
           c = 0;
-        }else if( nCellKey<nKey ){
+        }else if( nCellKey<intKey ){
           c = -1;
         }else{
-          assert( nCellKey>nKey );
+          assert( nCellKey>intKey );
           c = +1;
         }
       }else{
@@ -3774,7 +3754,7 @@ int sqlite3BtreeMoveto(
         pCellKey = (void *)fetchPayload(pCur, &available, 0);
         nCellKey = pCur->info.nKey;
         if( available>=nCellKey ){
-          c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, 0, pUnKey);
+          c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
         }else{
           pCellKey = sqlite3Malloc( nCellKey );
           if( pCellKey==0 ){
@@ -3782,7 +3762,7 @@ int sqlite3BtreeMoveto(
             goto moveto_finish;
           }
           rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
-          c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, 0, pUnKey);
+          c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
           sqlite3_free(pCellKey);
           if( rc ) goto moveto_finish;
         }
@@ -3832,10 +3812,35 @@ int sqlite3BtreeMoveto(
     if( rc ) goto moveto_finish;
   }
 moveto_finish:
+  return rc;
+}
+
+/*
+** In this version of BtreeMoveto, pKey is a packed index record
+** such as is generated by the OP_MakeRecord opcode.  Unpack the
+** record and then call BtreeMovetoUnpacked() to do the work.
+*/
+int sqlite3BtreeMoveto(
+  BtCursor *pCur,     /* Cursor open on the btree to be searched */
+  const void *pKey,   /* Packed key if the btree is an index */
+  i64 nKey,           /* Integer key for tables.  Size of pKey for indices */
+  int bias,           /* Bias search to the high end */
+  int *pRes           /* Write search results here */
+){
+  int rc;                    /* Status code */
+  UnpackedRecord *pIdxKey;   /* Unpacked index key */
+  char aSpace[200];          /* Temp space for pIdxKey - to avoid a malloc */
+
+  if( pKey ){
+    pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
+                                   aSpace, sizeof(aSpace));
+    if( pIdxKey==0 ) return SQLITE_NOMEM;
+  }else{
+    pIdxKey = 0;
+  }
+  rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
   if( pKey ){
-    /* If we created our own unpacked key at the top of this
-    ** procedure, then destroy that key before returning. */
-    sqlite3VdbeDeleteUnpackedRecord(pUnKey);
+    sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
   }
   return rc;
 }
@@ -5836,7 +5841,7 @@ int sqlite3BtreeInsert(
   clearCursorPosition(pCur);
   if( 
     SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
-    SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc))
+    SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
   ){
     return rc;
   }
index 3fe01cbd23085bc4ae076f280448794e2554d733..5db917b5dc3939448a9b5b921792da5ffa2ea8a8 100644 (file)
@@ -13,7 +13,7 @@
 ** subsystem.  See comments in the source code for a detailed description
 ** of what each interface routine does.
 **
-** @(#) $Id: btree.h,v 1.102 2008/07/11 21:02:54 drh Exp $
+** @(#) $Id: btree.h,v 1.103 2008/08/13 19:11:48 drh Exp $
 */
 #ifndef _BTREE_H_
 #define _BTREE_H_
@@ -122,8 +122,6 @@ int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
 int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
 void sqlite3BtreeTripAllCursors(Btree*, int);
 
-struct UnpackedRecord;  /* Forward declaration.  Definition in vdbeaux.c. */
-
 int sqlite3BtreeCursor(
   Btree*,                              /* BTree containing table to open */
   int iTable,                          /* Index of root page */
@@ -137,11 +135,17 @@ int sqlite3BtreeCloseCursor(BtCursor*);
 int sqlite3BtreeMoveto(
   BtCursor*,
   const void *pKey,
-  struct UnpackedRecord *pUnKey,
   i64 nKey,
   int bias,
   int *pRes
 );
+int sqlite3BtreeMovetoUnpacked(
+  BtCursor*,
+  UnpackedRecord *pUnKey,
+  i64 intKey,
+  int bias,
+  int *pRes
+);
 int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
 int sqlite3BtreeDelete(BtCursor*);
 int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
index 45c787e1f0485ff7ac95ef1b2aef9a23639c4e9c..1851b41522f8456388f3c8f16a04862802100c22 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.754 2008/08/13 14:07:40 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.755 2008/08/13 19:11:48 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -470,6 +470,7 @@ typedef struct Token Token;
 typedef struct TriggerStack TriggerStack;
 typedef struct TriggerStep TriggerStep;
 typedef struct Trigger Trigger;
+typedef struct UnpackedRecord UnpackedRecord;
 typedef struct WhereInfo WhereInfo;
 typedef struct WhereLevel WhereLevel;
 
@@ -1037,21 +1038,45 @@ struct FKey {
 ** An instance of the following structure is passed as the first
 ** argument to sqlite3VdbeKeyCompare and is used to control the 
 ** comparison of the two index keys.
-**
-** If the KeyInfo.incrKey value is true and the comparison would
-** otherwise be equal, then return a result as if the second key
-** were larger.
 */
 struct KeyInfo {
   sqlite3 *db;        /* The database connection */
   u8 enc;             /* Text encoding - one of the TEXT_Utf* values */
-  u8 incrKey;         /* Increase 2nd key by epsilon before comparison */
-  u8 ckPrefixOnly;    /* Records are equal if shorter is a prefix of longer */
-  int nField;         /* Number of entries in aColl[] */
+  u16 nField;         /* Number of entries in aColl[] */
   u8 *aSortOrder;     /* If defined an aSortOrder[i] is true, sort DESC */
   CollSeq *aColl[1];  /* Collating sequence for each term of the key */
 };
 
+/*
+** An instance of the following structure holds information about a
+** single index record that has already been parsed out into individual
+** values.
+**
+** A record is an object that contains one or more fields of data.
+** Records are used to store the content of a table row and to store
+** the key of an index.  A blob encoding of a record is created by
+** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
+** OP_Column opcode.
+**
+** This structure holds a record that has already been disassembled
+** into its constitutent fields.
+*/
+struct UnpackedRecord {
+  KeyInfo *pKeyInfo;  /* Collation and sort-order information */
+  u16 nField;         /* Number of entries in apMem[] */
+  u16 flags;          /* Boolean settings.  UNPACKED_... below */
+  Mem *aMem;          /* Values */
+};
+
+/*
+** Allowed values of UnpackedRecord.flags
+*/
+#define UNPACKED_NEED_FREE     0x0001  /* Memory is from sqlite3Malloc() */
+#define UNPACKED_NEED_DESTROY  0x0002  /* apMem[]s should all be destroyed */
+#define UNPACKED_IGNORE_ROWID  0x0004  /* Ignore trailing rowid on key1 */
+#define UNPACKED_INCRKEY       0x0008  /* Make this key an epsilon larger */
+#define UNPACKED_PREFIX_MATCH  0x0010  /* A prefix match is considered OK */
+
 /*
 ** Each SQL index is represented in memory by an
 ** instance of the following structure.
index 6b06dfcfc06c56015a8247b924527ab4d597e056..4b75690fffe97cd9c6037c3c462ee3d25a79f569 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test3.c,v 1.100 2008/07/12 14:52:20 drh Exp $
+** $Id: test3.c,v 1.101 2008/08/13 19:11:48 drh Exp $
 */
 #include "sqliteInt.h"
 #include "btreeInt.h"
@@ -697,9 +697,9 @@ static int btree_move_to(
       sqlite3BtreeLeave(pCur->pBtree);
       return TCL_ERROR;
     }
-    rc = sqlite3BtreeMoveto(pCur, 0, 0, iKey, 0, &res);
+    rc = sqlite3BtreeMovetoUnpacked(pCur, 0, iKey, 0, &res);
   }else{
-    rc = sqlite3BtreeMoveto(pCur, argv[2], 0, strlen(argv[2]), 0, &res);  
+    rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res);  
   }
   sqlite3BtreeLeave(pCur->pBtree);
   if( rc ){
index d02bc8da7370007052c862f874f17cbb00fa3da2..f2e39dd2d6cb24f1716705e3bb3a7706f01122ff 100644 (file)
@@ -43,7 +43,7 @@
 ** 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.774 2008/08/13 14:07:40 drh Exp $
+** $Id: vdbe.c,v 1.775 2008/08/13 19:11:48 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -555,6 +555,8 @@ int sqlite3VdbeExec(
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
   int nProgressOps = 0;      /* Opcodes executed since progress callback. */
 #endif
+  char zTempSpace[200];      /* Space to hold a transient UnpackedRecord */
+
 
   assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
   assert( db->magic==SQLITE_MAGIC_BUSY );
@@ -2705,11 +2707,9 @@ case OP_OpenWrite: {
   rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor);
   if( pOp->p4type==P4_KEYINFO ){
     pCur->pKeyInfo = pOp->p4.pKeyInfo;
-    pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
     pCur->pKeyInfo->enc = ENC(p->db);
   }else{
     pCur->pKeyInfo = 0;
-    pCur->pIncrKey = &pCur->bogusIncrKey;
   }
   switch( rc ){
     case SQLITE_BUSY: {
@@ -2809,13 +2809,11 @@ case OP_OpenEphemeral: {
                                 (KeyInfo*)pOp->p4.z, pCx->pCursor);
         pCx->pKeyInfo = pOp->p4.pKeyInfo;
         pCx->pKeyInfo->enc = ENC(p->db);
-        pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
       }
       pCx->isTable = 0;
     }else{
       rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
       pCx->isTable = 1;
-      pCx->pIncrKey = &pCx->bogusIncrKey;
     }
   }
   pCx->isIndex = !pCx->isTable;
@@ -2851,7 +2849,6 @@ case OP_OpenPseudo: {
   pCx->nullRow = 1;
   pCx->pseudoTable = 1;
   pCx->ephemPseudoTable = pOp->p2;
-  pCx->pIncrKey = &pCx->bogusIncrKey;
   pCx->isTable = 1;
   pCx->isIndex = 0;
   break;
@@ -2943,7 +2940,6 @@ case OP_MoveGt: {       /* jump, in3 */
     int res, oc;
     oc = pOp->opcode;
     pC->nullRow = 0;
-    *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
     if( pC->isTable ){
       i64 iKey = sqlite3VdbeIntValue(pIn3);
       if( pOp->p2==0 ){
@@ -2953,7 +2949,7 @@ case OP_MoveGt: {       /* jump, in3 */
         pC->deferredMoveto = 1;
         break;
       }
-      rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res);
+      rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
@@ -2966,10 +2962,13 @@ case OP_MoveGt: {       /* jump, in3 */
       assert( nField>0 );
       r.pKeyInfo = pC->pKeyInfo;
       r.nField = nField;
-      r.needFree = 0;
-      r.needDestroy = 0;
+      if( oc==OP_MoveGt || oc==OP_MoveLe ){
+        r.flags = UNPACKED_INCRKEY;
+      }else{
+        r.flags = 0;
+      }
       r.aMem = &p->aMem[pOp->p3];
-      rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
+      rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
@@ -2977,7 +2976,6 @@ case OP_MoveGt: {       /* jump, in3 */
     }
     pC->deferredMoveto = 0;
     pC->cacheStatus = CACHE_STALE;
-    *pC->pIncrKey = 0;
 #ifdef SQLITE_TEST
     sqlite3_search_count++;
 #endif
@@ -3055,13 +3053,20 @@ case OP_Found: {        /* jump, in3 */
   assert( p->apCsr[i]!=0 );
   if( (pC = p->apCsr[i])->pCursor!=0 ){
     int res;
+    UnpackedRecord *pIdxKey;
+
     assert( pC->isTable==0 );
     assert( pIn3->flags & MEM_Blob );
+    pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
+                                      zTempSpace, sizeof(zTempSpace));
+    if( pIdxKey==0 ){
+      goto no_mem;
+    }
     if( pOp->opcode==OP_Found ){
-      pC->pKeyInfo->ckPrefixOnly = 1;
+      pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
     }
-    rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
-    pC->pKeyInfo->ckPrefixOnly = 0;
+    rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
+    sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
     if( rc!=SQLITE_OK ){
       break;
     }
@@ -3081,7 +3086,7 @@ case OP_Found: {        /* jump, in3 */
 **
 ** The P3 register contains an integer record number.  Call this
 ** record number R.  The P4 register contains an index key created
-** using MakeIdxRec.  Call it K.
+** using MakeRecord.  Call it K.
 **
 ** P1 is an index.  So it has no data and its key consists of a
 ** record generated by OP_MakeRecord where the last field is the 
@@ -3117,45 +3122,39 @@ case OP_IsUnique: {        /* jump, in3 */
   pCrsr = pCx->pCursor;
   if( pCrsr!=0 ){
     int res;
-    i64 v;         /* The record number on the P1 entry that matches K */
-    char *zKey;    /* The value of K */
-    int nKey;      /* Number of bytes in K */
-    int len;       /* Number of bytes in K without the rowid at the end */
-    int szRowid;   /* Size of the rowid column at the end of zKey */
+    i64 v;                     /* The record number that matches K */
+    UnpackedRecord *pIdxKey;   /* Unpacked version of P4 */
 
     /* Make sure K is a string and make zKey point to K
     */
     assert( pK->flags & MEM_Blob );
-    zKey = pK->z;
-    nKey = pK->n;
-
-    /* sqlite3VdbeIdxRowidLen() only returns other than SQLITE_OK when the
-    ** record passed as an argument corrupt. Since the record in this case
-    ** has just been created by an OP_MakeRecord instruction, and not loaded
-    ** from the database file, it is not possible for it to be corrupt.
-    ** Therefore, assert(rc==SQLITE_OK).
-    */
-    rc = sqlite3VdbeIdxRowidLen((u8*)zKey, nKey, &szRowid);
-    assert(rc==SQLITE_OK);
-    len = nKey-szRowid;
+    pIdxKey = sqlite3VdbeRecordUnpack(pCx->pKeyInfo, pK->n, pK->z,
+                                      zTempSpace, sizeof(zTempSpace));
+    if( pIdxKey==0 ){
+      goto no_mem;
+    }
+    pIdxKey->flags |= UNPACKED_IGNORE_ROWID;
 
-    /* Search for an entry in P1 where all but the last four bytes match K.
+    /* Search for an entry in P1 where all but the last rowid match K
     ** If there is no such entry, jump immediately to P2.
     */
     assert( pCx->deferredMoveto==0 );
     pCx->cacheStatus = CACHE_STALE;
-    rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res);
+    rc = sqlite3BtreeMovetoUnpacked(pCrsr, pIdxKey, 0, 0, &res);
     if( rc!=SQLITE_OK ){
+      sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
       goto abort_due_to_error;
     }
     if( res<0 ){
       rc = sqlite3BtreeNext(pCrsr, &res);
       if( res ){
         pc = pOp->p2 - 1;
+        sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
         break;
       }
     }
-    rc = sqlite3VdbeIdxKeyCompare(pCx, 0, len, (u8*)zKey, &res); 
+    rc = sqlite3VdbeIdxKeyCompare(pCx, pIdxKey, &res); 
+    sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
     if( rc!=SQLITE_OK ) goto abort_due_to_error;
     if( res>0 ){
       pc = pOp->p2 - 1;
@@ -3212,7 +3211,7 @@ case OP_NotExists: {        /* jump, in3 */
     assert( pIn3->flags & MEM_Int );
     assert( p->apCsr[i]->isTable );
     iKey = intToKey(pIn3->u.i);
-    rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res);
+    rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0,&res);
     pC->lastRowid = pIn3->u.i;
     pC->rowidIsValid = res==0;
     pC->nullRow = 0;
@@ -3389,7 +3388,7 @@ case OP_NewRowid: {           /* out2-prerelease */
         }
         if( v==0 ) continue;
         x = intToKey(v);
-        rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res);
+        rx = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)x, 0, &res);
         cnt++;
       }while( cnt<100 && rx==SQLITE_OK && res==0 );
       db->priorNewRowid = v;
@@ -3885,10 +3884,9 @@ case OP_IdxDelete: {
     UnpackedRecord r;
     r.pKeyInfo = pC->pKeyInfo;
     r.nField = pOp->p3;
-    r.needFree = 0;
-    r.needDestroy = 0;
+    r.flags = 0;
     r.aMem = &p->aMem[pOp->p2];
-    rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res);
+    rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
     if( rc==SQLITE_OK && res==0 ){
       rc = sqlite3BtreeDelete(pCrsr);
     }
@@ -3971,12 +3969,13 @@ case OP_IdxGE: {        /* jump, in3 */
     assert( pOp->p4type==P4_INT32 );
     r.pKeyInfo = pC->pKeyInfo;
     r.nField = pOp->p4.i;
-    r.needFree = 0;
-    r.needDestroy = 0;
+    if( pOp->p5 ){
+      r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
+    }else{
+      r.flags = UNPACKED_IGNORE_ROWID;
+    }
     r.aMem = &p->aMem[pOp->p3];
-    *pC->pIncrKey = pOp->p5;
-    rc = sqlite3VdbeIdxKeyCompare(pC, &r, 0, 0, &res);
-    *pC->pIncrKey = 0;
+    rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
     if( pOp->opcode==OP_IdxLT ){
       res = -res;
     }else{
index 37d9f68639ce0ae73e37f7a712c34c78e02ede48..f82c8b163b7965af7b3fb1ec0a97af8944eaad9c 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.136 2008/08/13 14:07:41 drh Exp $
+** $Id: vdbe.h,v 1.137 2008/08/13 19:11:48 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -34,7 +34,6 @@ typedef struct Vdbe Vdbe;
 */
 typedef struct VdbeFunc VdbeFunc;
 typedef struct Mem Mem;
-typedef struct UnpackedRecord UnpackedRecord;
 
 /*
 ** A single instruction of the virtual machine has an opcode
@@ -190,7 +189,7 @@ int sqlite3VdbeReleaseMemory(int);
 #endif
 UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int);
 void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
-int sqlite3VdbeRecordCompare(int,const void*,int,UnpackedRecord*);
+int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
 
 
 #ifndef NDEBUG
index 6516f131c0720e477d902f5e059017272ba88aaf..f910e4be1f66337b0f0e50c91e7fdf0680e9bd6f 100644 (file)
@@ -15,7 +15,7 @@
 ** 6000 lines long) it was split up into several smaller files and
 ** this header information was factored out.
 **
-** $Id: vdbeInt.h,v 1.153 2008/08/02 03:50:39 drh Exp $
+** $Id: vdbeInt.h,v 1.154 2008/08/13 19:11:48 drh Exp $
 */
 #ifndef _VDBEINT_H_
 #define _VDBEINT_H_
@@ -71,13 +71,11 @@ struct Cursor {
   Bool deferredMoveto;  /* A call to sqlite3BtreeMoveto() is needed */
   Bool isTable;         /* True if a table requiring integer keys */
   Bool isIndex;         /* True if an index containing keys only - no data */
-  u8 bogusIncrKey;      /* Something for pIncrKey to point to if pKeyInfo==0 */
   i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
   Btree *pBt;           /* Separate file holding temporary table */
   int nData;            /* Number of bytes in pData */
   char *pData;          /* Data for a NEW or OLD pseudo-table */
   i64 iKey;             /* Key for the NEW or OLD pseudo-table row */
-  u8 *pIncrKey;         /* Pointer to pKeyInfo->incrKey */
   KeyInfo *pKeyInfo;    /* Info about index keys needed by index cursors */
   int nField;           /* Number of fields in the header */
   i64 seqCount;         /* Sequence counter */
@@ -341,28 +339,6 @@ struct Vdbe {
 #endif
 };
 
-/*
-** An instance of the following structure holds information about a
-** single index record that has already been parsed out into individual
-** values.
-**
-** A record is an object that contains one or more fields of data.
-** Records are used to store the content of a table row and to store
-** the key of an index.  A blob encoding of a record is created by
-** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
-** OP_Column opcode.
-**
-** This structure holds a record that has already been disassembled
-** into its constitutent fields.
-*/
-struct UnpackedRecord {
-  KeyInfo *pKeyInfo;  /* Collation and sort-order information */
-  u16 nField;         /* Number of entries in apMem[] */
-  u8 needFree;        /* True if memory obtained from sqlite3_malloc() */
-  u8 needDestroy;     /* True if apMem[]s should be destroyed on close */
-  Mem *aMem;          /* Values */
-};
-
 /*
 ** The following are allowed values for Vdbe.magic
 */
@@ -387,10 +363,9 @@ int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
 void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
 
 int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
-int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord *,int,const unsigned char*,int*);
+int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord*,int*);
 int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
 int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
-int sqlite3VdbeIdxRowidLen(const u8*, int, int*);
 int sqlite3VdbeExec(Vdbe*);
 int sqlite3VdbeList(Vdbe*);
 int sqlite3VdbeHalt(Vdbe*);
index 12827851123ce28937a74c59f888ab60f27d265d..2d8d2a835d014d61e26f2e7e43886b415b3a2126 100644 (file)
@@ -14,7 +14,7 @@
 ** to version 2.8.7, all this code was combined into the vdbe.c source file.
 ** But that file was getting too big so this subroutines were split out.
 **
-** $Id: vdbeaux.c,v 1.406 2008/08/13 14:07:41 drh Exp $
+** $Id: vdbeaux.c,v 1.407 2008/08/13 19:11:48 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1850,9 +1850,8 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
     extern int sqlite3_search_count;
 #endif
     assert( p->isTable );
-    rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res);
+    rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
     if( rc ) return rc;
-    *p->pIncrKey = 0;
     p->lastRowid = keyToInt(p->movetoTarget);
     p->rowidIsValid = res==0;
     if( res<0 ){
@@ -2215,14 +2214,13 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(
   if( nByte>szSpace ){
     p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
     if( p==0 ) return 0;
-    p->needFree = 1;
+    p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
   }else{
     p = pSpace;
-    p->needFree = 0;
+    p->flags = UNPACKED_NEED_DESTROY;
   }
   p->pKeyInfo = pKeyInfo;
   p->nField = pKeyInfo->nField + 1;
-  p->needDestroy = 1;
   p->aMem = pMem = &((Mem*)p)[1];
   idx = getVarint32(aKey, szHdr);
   d = szHdr;
@@ -2249,7 +2247,7 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(
 */
 void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
   if( p ){
-    if( p->needDestroy ){
+    if( p->flags & UNPACKED_NEED_DESTROY ){
       int i;
       Mem *pMem;
       for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
@@ -2258,7 +2256,7 @@ void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
         }
       }
     }
-    if( p->needFree ){
+    if( p->flags & UNPACKED_NEED_FREE ){
       sqlite3DbFree(p->pKeyInfo->db, p);
     }
   }
@@ -2267,38 +2265,31 @@ void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
 /*
 ** This function compares the two table rows or index records
 ** specified by {nKey1, pKey1} and pPKey2.  It returns a negative, zero
-** or positive integer if {nKey1, pKey1} is less than, equal to or 
-** greater than pPKey2.  The {nKey1, pKey1} key must be a blob
+** or positive integer if key1 is less than, equal to or 
+** greater than key2.  The {nKey1, pKey1} key must be a blob
 ** created by th OP_MakeRecord opcode of the VDBE.  The pPKey2
 ** key must be a parsed key such as obtained from
 ** sqlite3VdbeParseRecord.
 **
 ** Key1 and Key2 do not have to contain the same number of fields.
-** The key with fewer fields is usually considered lessor than the 
-** longer.  However if pPKey2->pKeyInfo->incrKey is set and
-** the common prefixes are equal, then key1 is less than key2.
-** Or if pPKey2->pKeyInfo->ckPrefixOnly flag is set and the 
-** prefixes are equal, then the keys are considered to be equal and
+** The key with fewer fields is usually compares less than the 
+** longer key.  However if the UNPACKED_INCRKEY flags in pPKey2 is set
+** and the common prefixes are equal, then key1 is less than key2.
+** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
+** equal, then the keys are considered to be equal and
 ** the parts beyond the common prefix are ignored.
 **
-** The last nHdrIgnore1 bytes of the header of pKey1 are ignored,
-** as if they do not exist.  Usually nHdrIgnore1 is 0 which means
-** that we look at the entire key.  But sometimes nHdrIgnore1 is 1.
-** When nHdrIgnore1 is 1, the keys are index records and so the last
-** column is a rowid.  The type code is always one byte in length.
-** Hence, setting nHdrIgnore1 to 1 means that the final rowid at the
-** end of the record should be treated as if it does not exist.
-**
-** Historical note: In earlier versions of this routine both Key1
-** and Key2 were blobs obtained from OP_MakeRecord.  But we found
-** that in typical use the same Key2 would be submitted multiple times
-** in a row.  So an optimization was added to parse the Key2 key
-** separately and submit the parsed version.  In this way, we avoid
-** parsing the same Key2 multiple times.
+** If the UNPACKED_IGNORE_ROWID flag is set, then the last byte of
+** the header of pKey1 is ignored.  It is assumed that pKey1 is
+** an index key, and thus ends with a rowid value.  The last byte
+** of the header will therefore be the serial type of the rowid:
+** one of 1, 2, 3, 4, 5, 6, 8, or 9 - the integer serial types.
+** The serial type of the final rowid will always be a single byte.
+** By ignoring this last byte of the header, we force the comparison
+** to ignore the rowid at the end of key1.
 */
 int sqlite3VdbeRecordCompare(
   int nKey1, const void *pKey1, /* Left key */
-  int nHdrIgnore1,              /* Omit this much from end of key1 header */
   UnpackedRecord *pPKey2        /* Right key */
 ){
   u32 d1;            /* Offset into aKey[] of next data element */
@@ -2319,7 +2310,9 @@ int sqlite3VdbeRecordCompare(
   
   idx1 = getVarint32(aKey1, szHdr1);
   d1 = szHdr1;
-  szHdr1 -= nHdrIgnore1;
+  if( pPKey2->flags & UNPACKED_IGNORE_ROWID ){
+    szHdr1--;
+  }
   nField = pKeyInfo->nField;
   while( idx1<szHdr1 && i<pPKey2->nField ){
     u32 serial_type1;
@@ -2345,16 +2338,16 @@ int sqlite3VdbeRecordCompare(
 
   if( rc==0 ){
     /* rc==0 here means that one of the keys ran out of fields and
-    ** all the fields up to that point were equal. If the incrKey 
-    ** flag is true, then break the tie by treating the second key 
-    ** as larger.  If ckPrefixOnly is true, then keys with common prefixes
+    ** all the fields up to that point were equal. If the UNPACKED_INCRKEY
+    ** flag is set, then break the tie by treating key2 as larger.
+    ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
     ** are considered to be equal.  Otherwise, the longer key is the 
     ** larger.  As it happens, the pPKey2 will always be the longer
     ** if there is a difference.
     */
-    if( pKeyInfo->incrKey ){
+    if( pPKey2->flags & UNPACKED_INCRKEY ){
       rc = -1;
-    }else if( pKeyInfo->ckPrefixOnly ){
+    }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
       /* Leave rc==0 */
     }else if( idx1<szHdr1 ){
       rc = 1;
@@ -2366,25 +2359,6 @@ int sqlite3VdbeRecordCompare(
 
   return rc;
 }
-  
-/*
-** The argument is an index entry composed using the OP_MakeRecord opcode.
-** The last entry in this record should be an integer (specifically
-** an integer rowid).  This routine returns the number of bytes in
-** that integer.
-*/
-int sqlite3VdbeIdxRowidLen(const u8 *aKey, int nKey, int *pRowidLen){
-  u32 szHdr;        /* Size of the header */
-  u32 typeRowid;    /* Serial type of the rowid */
-
-  (void)getVarint32(aKey, szHdr);
-  if( szHdr>nKey ){
-    return SQLITE_CORRUPT_BKPT;
-  }
-  (void)getVarint32(&aKey[szHdr-1], typeRowid);
-  *pRowidLen = sqlite3VdbeSerialTypeLen(typeRowid);
-  return SQLITE_OK;
-}
  
 
 /*
@@ -2437,15 +2411,12 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
 int sqlite3VdbeIdxKeyCompare(
   Cursor *pC,                 /* The cursor to compare against */
   UnpackedRecord *pUnpacked,  /* Unpacked version of pKey and nKey */
-  int nKey, const u8 *pKey,   /* The key to compare */
   int *res                    /* Write the comparison result here */
 ){
   i64 nCellKey = 0;
   int rc;
   BtCursor *pCur = pC->pCursor;
   Mem m;
-  UnpackedRecord *pRec;
-  char zSpace[200];
 
   sqlite3BtreeKeySize(pCur, &nCellKey);
   if( nCellKey<=0 ){
@@ -2459,19 +2430,8 @@ int sqlite3VdbeIdxKeyCompare(
   if( rc ){
     return rc;
   }
-  if( !pUnpacked ){
-    pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey,
-                                zSpace, sizeof(zSpace));
-  }else{
-    pRec = pUnpacked;
-  }
-  if( pRec==0 ){
-    return SQLITE_NOMEM;
-  }
-  *res = sqlite3VdbeRecordCompare(m.n, m.z, 1, pRec);
-  if( !pUnpacked ){
-    sqlite3VdbeDeleteUnpackedRecord(pRec);
-  }
+  assert( pUnpacked->flags & UNPACKED_IGNORE_ROWID );
+  *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
   sqlite3VdbeMemRelease(&m);
   return SQLITE_OK;
 }