]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Change the record format to include an extra varint at the beginning to record the...
authordrh <drh@noemail.net>
Thu, 27 May 2004 19:59:32 +0000 (19:59 +0000)
committerdrh <drh@noemail.net>
Thu, 27 May 2004 19:59:32 +0000 (19:59 +0000)
FossilOrigin-Name: 0c4d138807f367d75b3fb5b2dadf206df725659f

manifest
manifest.uuid
src/vdbe.c
src/vdbeInt.h
src/vdbeaux.c
test/types.test

index 86bad0e3f11f1bfb76b43b64d1b024df1e2a0015..cfdaa138982332f3cbed216f307453a6a37a041a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Remove\sthe\sCOPY\scommand.\s(CVS\s1477)
-D 2004-05-27T17:22:55
+C Change\sthe\srecord\sformat\sto\sinclude\san\sextra\svarint\sat\sthe\sbeginning\sto\srecord\sthe\snumber\sof\sbytes\sin\sthe\sheader.\s(CVS\s1478)
+D 2004-05-27T19:59:32
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -69,11 +69,11 @@ F src/update.c 96461bcf4e946697e83c09c77c7e61b545a2f66e
 F src/utf.c 59b5c8f06a4384a9f64933d6c57a2de02ce3673b
 F src/util.c d299404febd509556e720fbecadd880756b0f899
 F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad
-F src/vdbe.c 2f2c9859ad19836b31825d2d70c4a8e6a9eba0d1
+F src/vdbe.c c068f9ab3d82906de297c1f20e50d601981328fb
 F src/vdbe.h e73f890e0f2a6c42b183d7d6937947930fe4fdeb
-F src/vdbeInt.h fab8bb7f7a7f4e0714d9b3217c3db97366e16b99
+F src/vdbeInt.h 0c30699ea21371980bc278e4e3d17d80ced722df
 F src/vdbeapi.c b0bb1f98c899ba00c8a5cbca612c2a28a1bb79de
-F src/vdbeaux.c 5b886ac74a68e7e956259eba53e3d002a8ddc6a7
+F src/vdbeaux.c c1beed304947bcfe49bd7c2abe45a58c2db0c67b
 F src/vdbemem.c b487e8a903012de1c0b7f603e8efeede2b51b21d
 F src/where.c efe5d25fe18cd7381722457898cd863e84097a0c
 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
@@ -154,7 +154,7 @@ F test/trigger1.test 4538c1c7d6bbca5dfe619ea6e1682b07ece95b21
 F test/trigger2.test 0767ab30cb5a2c8402c8524f3d566b410b6f5263
 F test/trigger3.test a95ccace88291449f5eae7139ec438a42f90654d
 F test/trigger4.test 542afce45774e8f8e1130b96b8675f414d6e4bd8
-F test/types.test 8fa51489d4765b8baa2d3c92de32aba06315a655
+F test/types.test 6c49e574970866558365a025b44c9fd8a162ef0d
 F test/types2.test 5d725fcb68dbd032c6d4950d568d75fa33872687
 F test/unique.test 0e38d4cc7affeef2527720d1dafd1f6870f02f2b
 F test/update.test b29bd9061a1150426dab6959806fcc73a41b1217
@@ -203,7 +203,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P c85e5f1528d098ea330ed0cf7e3c01cf9be93c10
-R 0f424c162c35b47a72bb56f63064dff2
+P 287f86731c71401dbac098e08357367b4f8e5a43
+R ae5f0056bb6540c5d0436f9717bf751b
 U drh
-Z 4f618cbd73c341429c69a19968301445
+Z 6b3a034bd2c2b8589e4d067a67b642dc
index 1e9ff0d83b1ea38c7f16ff1e80b258e42d41e9a6..50be98f33eef8e91b84c6439838307c08079d4e4 100644 (file)
@@ -1 +1 @@
-287f86731c71401dbac098e08357367b4f8e5a43
\ No newline at end of file
+0c4d138807f367d75b3fb5b2dadf206df725659f
\ No newline at end of file
index c7ee88962bdb90f8de23f7c8221da0d841d2f524..3930fd691976002777d4232f01cbce88bc4b498f 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.340 2004/05/27 17:22:56 drh Exp $
+** $Id: vdbe.c,v 1.341 2004/05/27 19:59:32 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -241,32 +241,6 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight, KeyInfo *pKeyInfo){
   return sHead.pNext;
 }
 
-/*
-** The following routine works like a replacement for the standard
-** library routine fgets().  The difference is in how end-of-line (EOL)
-** is handled.  Standard fgets() uses LF for EOL under unix, CRLF
-** under windows, and CR under mac.  This routine accepts any of these
-** character sequences as an EOL mark.  The EOL mark is replaced by
-** a single LF character in zBuf.
-*/
-static char *vdbe_fgets(char *zBuf, int nBuf, FILE *in){
-  int i, c;
-  for(i=0; i<nBuf-1 && (c=getc(in))!=EOF; i++){
-    zBuf[i] = c;
-    if( c=='\r' || c=='\n' ){
-      if( c=='\r' ){
-        zBuf[i] = '\n';
-        c = getc(in);
-        if( c!=EOF && c!='\n' ) ungetc(c, in);
-      }
-      i++;
-      break;
-    }
-  }
-  zBuf[i]  = 0;
-  return i>0 ? zBuf : 0;
-}
-
 /*
 ** Make sure there is space in the Vdbe structure to hold at least
 ** mxCursor cursors.  If there is not currently enough space, then
@@ -1846,75 +1820,46 @@ case OP_SetNumColumns: {
 */
 case OP_Column: {
   int payloadSize;   /* Number of bytes in the record */
-  int i = pOp->p1;
+  int p1 = pOp->p1;  /* P1 value of the opcode */
   int p2 = pOp->p2;  /* column number to retrieve */
-  Cursor *pC = 0;
+  Cursor *pC = 0;    /* The VDBE cursor */
   char *zRec;        /* Pointer to record-data from stack or pseudo-table. */
-  BtCursor *pCrsr;
-
+  BtCursor *pCrsr;   /* The BTree cursor */
+  u32 *aType;        /* aType[i] holds the numeric type of the i-th column */
+  u32 *aOffset;      /* aOffset[i] is offset to start of data for i-th column */
   u64 nField;        /* number of fields in the record */
+  u32 szHdr;         /* Number of bytes in the record header */
   int len;           /* The length of the serialized data for the column */
-  int offset = 0;
-  int nn;
+  int offset = 0;    /* Offset into the data */
+  int idx;           /* Index into the header */
+  int i;             /* Loop counter */
+  char *zData;       /* Part of the record being decoded */
+  Mem sMem;          /* For storing the record being decoded */
 
-  char *zData;       
-  Mem sMem;
   sMem.flags = 0;
-
-  assert( i<p->nCursor );
+  assert( p1<p->nCursor );
   pTos++;
 
-  /* If the record is coming from the stack, not from a cursor, then there
-  ** is nowhere to cache the record header infomation. This simplifies
-  ** things greatly, so deal with this case seperately.
-  */
-  if( i<0 ){
-    char *zRec;     /* Pointer to record data from the stack. */
-    int off = 0;    /* Offset in zRec to start of the columns data. */
-    int off2 = 0;   /* Offset in zRec to the next serial type to read */
-    u64 colType;    /* The serial type of the value being read. */
-
-    assert( &pTos[i-1]>=p->aStack );
-
-    /* FIX ME: I don't understand this either. How is it related to
-    ** OP_SortNext? (I thought it would be the commented out assert())
-    */
-    /* assert( pTos[i].flags & MEM_Blob ); */
-    assert( pTos[i].flags & (MEM_Blob|MEM_Str) );
-    assert( pTos[i-1].flags & MEM_Int );
-
-    if( pTos[i].n==0 ){
-      pTos->flags = MEM_Null;
-      break;
-    }
-
-    zRec = pTos[i].z;
-    nField = pTos[i-1].i;
-     
-    for( nn=0; nn<nField; nn++ ){
-      u64 v;
-      off2 += sqlite3GetVarint(&zRec[off2], &v);
-      if( nn==p2 ){
-        colType = v;
-      }else if( nn<p2 ){
-        off += sqlite3VdbeSerialTypeLen(v);
-      }
-    }
-    off += off2;
-    
-    sqlite3VdbeSerialGet(&zRec[off], colType, pTos, p->db->enc);
-    if( rc!=SQLITE_OK ){
-      goto abort_due_to_error;
-    }
-    break;
-  }
-
-
   /* This block sets the variable payloadSize, and if the data is coming
   ** from the stack or from a pseudo-table zRec. If the data is coming
   ** from a real cursor, then zRec is left as NULL.
+  **
+  ** We also compute the number of columns in the record.  For cursors,
+  ** the number of columns is stored in the Cursor.nField element.  For
+  ** records on the stack, the next entry down on the stack is an integer
+  ** which is the number of records.
   */
-  if( (pC = p->apCsr[i])->pCursor!=0 ){
+  if( p1<0 ){
+    Mem *pRec = &pTos[p1];
+    Mem *pCnt = &pRec[-1];
+    assert( pRec>=p->aStack );
+    assert( pRec->flags & MEM_Blob );
+    payloadSize = pRec->n;
+    zRec = pRec->z;
+    assert( pCnt>=p->aStack );
+    assert( pCnt->flags & MEM_Int );
+    nField = pCnt->i;
+  }else if( (pC = p->apCsr[p1])->pCursor!=0 ){
     sqlite3VdbeCursorMoveto(pC);
     zRec = 0;
     pCrsr = pC->pCursor;
@@ -1929,11 +1874,13 @@ case OP_Column: {
     }else{
       sqlite3BtreeDataSize(pCrsr, &payloadSize);
     }
+    nField = pC->nField;
   }else if( pC->pseudoTable ){
     payloadSize = pC->nData;
     zRec = pC->pData;
     pC->cacheValid = 0;
     assert( payloadSize==0 || zRec!=0 );
+    nField = pC->nField;
   }else{
     payloadSize = 0;
   }
@@ -1944,93 +1891,104 @@ case OP_Column: {
     break;
   }
 
-  /* If the row data is coming from a cursor, then OP_SetNumColumns must of
-  ** been executed on that cursor. Also, p2 (the column to read) must be
-  ** less than nField.
-  */
-  assert( !pC || pC->nField>0 );
-  assert( p2<pC->nField );
-  nField = pC->nField;
+  assert( p2<nField );
 
   /* Read and parse the table header.  Store the results of the parse
   ** into the record header cache fields of the cursor.
   */
-  if( !pC || !pC->cacheValid ){
-    pC->payloadSize = payloadSize;
-    if( !pC->aType ){
-      pC->aType = sqliteMallocRaw( nField*sizeof(pC->aType[0]) );
-      if( pC->aType==0 ){
-        goto no_mem;
-      }
+  if( pC && pC->cacheValid ){
+    aType = pC->aType;
+    aOffset = pC->aOffset;
+  }else{
+    aType = sqliteMallocRaw( 2*nField*sizeof(aType) );
+    aOffset = &aType[nField];
+    if( aType==0 ){
+      goto no_mem;
     }
 
+    /* Figure out how many bytes are in the header */
     if( zRec ){
       zData = zRec;
     }else{
-      /* Estimate the maximum space required by the nField varints by
-      ** assuming the maximum space for each is the length required to store:
-      **
-      **     (<record length> * 2) + 13
-      **
-      ** This is the serial-type for a text object as long as the record
-      ** itself. In almost all cases the length required to store this is
-      ** three bytes or less. 
-      */
-      int max_space = sqlite3VarintLen((((u64)payloadSize)<<1)+13)*nField;
-      if( max_space>payloadSize ){
-        max_space = payloadSize;
+      int sz = payloadSize<5 ? payloadSize : 5;
+      if( pC->keyAsData ){
+        zData = (char*)sqlite3BtreeKeyFetch(pCrsr, sz);
+      }else{
+        zData = (char*)sqlite3BtreeDataFetch(pCrsr, sz);
       }
+    }
+    idx = sqlite3GetVarint32(zData, &szHdr);
 
-      rc = getBtreeMem(pCrsr, 0, max_space, pC->keyAsData, &sMem);
+    /* Get the complete header text */
+    if( !zRec ){
+      rc = getBtreeMem(pCrsr, 0, szHdr, pC->keyAsData, &sMem);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
       zData = sMem.z;
     }
 
-    /* Read all the serial types for the record.  At the end of this block
-    ** variable offset is set to the offset to the start of Data0 in the record.
+    /* Scan the header and use it to fill in the aType[] and aOffset[]
+    ** arrays.  aType[i] will contain the type integer for the i-th
+    ** column and aOffset[i] will contain the offset from the beginning
+    ** of the record to the start of the data for the i-th column
     */
-    for(nn=0; nn<nField; nn++){
-      offset += sqlite3GetVarint(&zData[offset], &pC->aType[nn]);
+    offset = szHdr;
+    i = 0;
+    while( idx<szHdr && i<nField && offset<=payloadSize ){
+      aOffset[i] = offset;
+      idx += sqlite3GetVarint32(&zData[idx], &aType[i]);
+      offset += sqlite3VdbeSerialTypeLen(aType[i]);
+      i++;
     }
-    pC->nHeader = offset;
-    pC->cacheValid = 1;
-
     Release(&sMem);
-    sMem.flags = 0;
-  }
+    sMem.flags = MEM_Null;
 
-  /* Compute the offset from the beginning of the record to the beginning
-  ** of the data.  And get the length of the data.
-  */
-  offset = pC->nHeader;
-  for(nn=0; nn<p2; nn++){
-    offset += sqlite3VdbeSerialTypeLen(pC->aType[nn]);
+    /* The header should end at the start of data and the data should
+    ** end at last byte of the record. If this is not the case then
+    ** we are dealing with a malformed record.
+    */
+    if( idx!=szHdr || offset!=payloadSize ){
+      sqliteFree(aType);
+      if( pC ) pC->aType = 0;
+      rc = SQLITE_CORRUPT;
+      break;
+    }
+
+    /* Remember all aType and aColumn information if we have a cursor
+    ** to remember it in. */
+    if( pC ){
+      pC->payloadSize = payloadSize;
+      pC->aType = aType;
+      pC->aOffset = aOffset;
+      pC->cacheValid = 1;
+    }
   }
 
+  /* Get the column information.
+  */
   if( zRec ){
-    zData = &zRec[offset];
+    zData = &zRec[aOffset[p2]];
   }else{
-    len = sqlite3VdbeSerialTypeLen(pC->aType[p2]);
-    getBtreeMem(pCrsr, offset, len, pC->keyAsData, &sMem);
+    len = sqlite3VdbeSerialTypeLen(aType[p2]);
+    getBtreeMem(pCrsr, aOffset[p2], len, pC->keyAsData, &sMem);
     zData = sMem.z;
   }
-  sqlite3VdbeSerialGet(zData, pC->aType[p2], pTos, p->db->enc);
+  sqlite3VdbeSerialGet(zData, aType[p2], pTos, p->db->enc);
   if( rc!=SQLITE_OK ){
     goto abort_due_to_error;
   }
-
   Release(&sMem);
+
+  /* Release the aType[] memory if we are not dealing with cursor */
+  if( !pC ){
+    sqliteFree(aType);
+  }
   break;
 }
 
 /* Opcode MakeRecord P1 * P3
 **
-** This opcode (not yet in use) is a replacement for the current
-** OP_MakeRecord that supports the SQLite3 manifest typing feature.
-** It drops the (P2==1) option that was never use.
-**
 ** Convert the top P1 entries of the stack into a single entry
 ** suitable for use as a data record in a database table.  The
 ** details of the format are irrelavant as long as the OP_Column
@@ -2056,7 +2014,7 @@ case OP_MakeRecord: {
   ** like this:
   **
   ** --------------------------------------------------------------------------
-  ** | num-fields | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | 
+  ** | header-siz | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | 
   ** --------------------------------------------------------------------------
   **
   ** Data(0) is taken from the lowest element of the stack and data(N-1) is
@@ -2074,7 +2032,9 @@ case OP_MakeRecord: {
   unsigned char *zCsr;
   char *zAffinity;
   Mem *pRec;
-  int nBytes = 0;    /* Space required for this record */
+  int nData = 0;     /* Number of bytes of data space */
+  int nHdr = 0;      /* Number of bytes of header space */
+  int nByte = 0;     /* Space required for this record */
 
   Mem *pData0 = &pTos[1-nField];
   assert( pData0>=p->aStack );
@@ -2089,23 +2049,26 @@ case OP_MakeRecord: {
       applyAffinity(pRec, zAffinity[pRec-pData0], db->enc);
     }
     serial_type = sqlite3VdbeSerialType(pRec);
-    nBytes += sqlite3VdbeSerialTypeLen(serial_type);
-    nBytes += sqlite3VarintLen(serial_type);
+    nData += sqlite3VdbeSerialTypeLen(serial_type);
+    nHdr += sqlite3VarintLen(serial_type);
   }
+  nHdr += sqlite3VarintLen(nHdr);
+  nByte = nHdr+nData;
 
-  if( nBytes>MAX_BYTES_PER_ROW ){
+  if( nByte>MAX_BYTES_PER_ROW ){
     rc = SQLITE_TOOBIG;
     goto abort_due_to_error;
   }
 
   /* Allocate space for the new record. */
-  zNewRecord = sqliteMallocRaw(nBytes);
+  zNewRecord = sqliteMallocRaw(nByte);
   if( !zNewRecord ){
     goto no_mem;
   }
 
   /* Write the record */
   zCsr = zNewRecord;
+  zCsr += sqlite3PutVarint(zCsr, nHdr);
   for(pRec=pData0; pRec<=pTos; pRec++){
     u64 serial_type = sqlite3VdbeSerialType(pRec);
     zCsr += sqlite3PutVarint(zCsr, serial_type);      /* serial type */
@@ -2114,11 +2077,11 @@ case OP_MakeRecord: {
     zCsr += sqlite3VdbeSerialPut(zCsr, pRec);  /* serial data */
   }
 
-  /* If zCsr has not been advanced exactly nBytes bytes, then one
+  /* If zCsr has not been advanced exactly nByte bytes, then one
   ** of the sqlite3PutVarint() or sqlite3VdbeSerialPut() calls above
   ** failed. This indicates a corrupted memory cell or code bug.
   */
-  if( zCsr!=(zNewRecord+nBytes) ){
+  if( zCsr!=(zNewRecord+nByte) ){
     rc = SQLITE_INTERNAL;
     goto abort_due_to_error;
   }
@@ -2126,7 +2089,7 @@ case OP_MakeRecord: {
   /* Pop nField entries from the stack and push the new entry on */
   popStack(&pTos, nField);
   pTos++;
-  pTos->n = nBytes;
+  pTos->n = nByte;
   pTos->z = zNewRecord;
   pTos->flags = MEM_Blob | MEM_Dyn;
 
index c0c99b12aa81e2567c592881b13bcac2b5215488..9e8abcbcb9c2c4e18f46300e57df2c9aca98fdd3 100644 (file)
@@ -80,14 +80,14 @@ struct Cursor {
   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 */
 
   /* Cached information about the header for the data record that the
   ** cursor is currently pointing to */
   Bool cacheValid;      /* True if the cache is valid */
-  int nField;           /* Number of fields in the header */
-  int nHeader;          /* Number of bytes in the entire header */
   int payloadSize;      /* Total number of bytes in the record */
-  u64 *aType;           /* Type values for all entries in the record */
+  u32 *aType;           /* Type values for all entries in the record */
+  u32 *aOffset;         /* Cached offsets to the start of each columns data */
 };
 typedef struct Cursor Cursor;
 
@@ -367,4 +367,3 @@ int sqlite3VdbeMemRealify(Mem*);
 #ifndef NDEBUG
 void sqlite3VdbeMemSanity(Mem*, u8);
 #endif
-
index 5028dc938188456fd625974e0b21f8859bd14a6c..e6c3606bfbc2bc0348074acef9ba3e5471f47992 100644 (file)
@@ -1431,44 +1431,37 @@ int sqlite3VdbeRowCompare(
   int nKey2, const void *pKey2
 ){
   KeyInfo *pKeyInfo = (KeyInfo*)userData;
-  int offset1 = 0;
-  int offset2 = 0;
-  int toffset1 = 0;
-  int toffset2 = 0;
-  int i;
-  u8 enc = pKeyInfo->enc;
+  u32 d1, d2;          /* Offset into aKey[] of next data element */
+  u32 idx1, idx2;      /* Offset into aKey[] of next header element */
+  u32 szHdr1, szHdr2;  /* Number of bytes in header */
+  int i = 0;
+  int nField;
+  int rc = 0;
   const unsigned char *aKey1 = (const unsigned char *)pKey1;
   const unsigned char *aKey2 = (const unsigned char *)pKey2;
-
-  assert( pKeyInfo );
-  assert( pKeyInfo->nField>0 );
-
-  for( i=0; i<pKeyInfo->nField; i++ ){
-    u64 dummy;
-    offset1 += sqlite3GetVarint(&aKey1[offset1], &dummy);
-    offset2 += sqlite3GetVarint(&aKey1[offset1], &dummy);
-  }
-
-  for( i=0; i<pKeyInfo->nField; i++ ){
+  
+  idx1 = sqlite3GetVarint32(pKey1, &szHdr1);
+  d1 = szHdr1;
+  idx2 = sqlite3GetVarint32(pKey2, &szHdr2);
+  d2 = szHdr2;
+  nField = pKeyInfo->nField;
+  while( idx1<szHdr1 && idx2<szHdr2 && d1<nKey1 && d2<nKey2 && i<nField ){
     Mem mem1;
     Mem mem2;
-    u64 serial_type1;
-    u64 serial_type2;
-    int rc;
+    u32 serial_type1;
+    u32 serial_type2;
 
     /* Read the serial types for the next element in each key. */
-    toffset1 += sqlite3GetVarint(&aKey1[toffset1], &serial_type1);
-    toffset2 += sqlite3GetVarint(&aKey2[toffset2], &serial_type2);
-
-    assert( serial_type1 && serial_type2 );
+    idx1 += sqlite3GetVarint32(&aKey1[idx1], &serial_type1);
+    idx2 += sqlite3GetVarint32(&aKey2[idx2], &serial_type2);
 
     /* Assert that there is enough space left in each key for the blob of
     ** data to go with the serial type just read. This assert may fail if
     ** the file is corrupted.  Then read the value from each key into mem1
     ** and mem2 respectively.
     */
-    offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1, enc);
-    offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2, enc);
+    d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1, 0);
+    d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2, 0);
 
     rc = sqlite3MemCompare(&mem1, &mem2, pKeyInfo->aColl[i]);
     if( mem1.flags&MEM_Dyn ){
@@ -1478,11 +1471,31 @@ int sqlite3VdbeRowCompare(
       sqliteFree(mem2.z);
     }
     if( rc!=0 ){
-      return rc;
+      break;
     }
+    i++;
   }
 
-  return 0;
+  /* One of the keys ran out of fields, but all the fields up to that point
+  ** were equal. If the incrKey flag is true, then the second key is
+  ** treated as larger.
+  */
+  if( rc==0 ){
+    if( pKeyInfo->incrKey ){
+      assert( d2==nKey2 );
+      rc = -1;
+    }else if( d1<nKey1 ){
+      rc = 1;
+    }else if( d2<nKey2 ){
+      rc = -1;
+    }
+  }
+
+  if( pKeyInfo->aSortOrder && i<pKeyInfo->nField && pKeyInfo->aSortOrder[i] ){
+    rc = -rc;
+  }
+
+  return rc;
 }
   
 
index 7d9cbb67d4aac02cc7512d36fc02693c880e0e4f..9ca194748260f8087784e7c705e4593e595aaa7c 100644 (file)
@@ -12,7 +12,7 @@
 # it tests that the different storage classes (integer, real, text etc.)
 # all work correctly.
 #
-# $Id: types.test,v 1.6 2004/05/24 12:55:55 danielk1977 Exp $
+# $Id: types.test,v 1.7 2004/05/27 19:59:33 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -199,7 +199,7 @@ do_test types-2.1.8 {
 do_test types-2.1.9 {
   set root [db eval {select rootpage from sqlite_master where name = 't1'}]
   record_sizes $root
-} {2 2 2 3 3 5 5 9 9}
+} {3 3 3 4 4 6 6 10 10}
 
 # Insert some reals. These should be 10 byte records.
 do_test types-2.2.1 {
@@ -220,7 +220,7 @@ do_test types-2.2.2 {
 do_test types-2.2.3 {
   set root [db eval {select rootpage from sqlite_master where name = 't2'}]
   record_sizes $root
-} {9 9 9}
+} {10 10 10}
 
 # Insert a NULL. This should be a two byte record.
 do_test types-2.3.1 {
@@ -239,7 +239,7 @@ do_test types-2.3.2 {
 do_test types-2.3.3 {
   set root [db eval {select rootpage from sqlite_master where name = 't3'}]
   record_sizes $root
-} {1}
+} {2}
 
 # Insert a couple of strings.
 do_test types-2.4.1 {
@@ -264,7 +264,7 @@ do_test types-2.4.2 {
 do_test types-2.4.3 {
   set root [db eval {select rootpage from sqlite_master where name = 't4'}]
   record_sizes $root
-} {11 502 500003}
+} {12 503 500004}
 
 do_test types-2.5.1 {
   execsql {