From 51846b56edaba72e986cd7128f38547690c48671 Mon Sep 17 00:00:00 2001
From: drh <drh@noemail.net>
Date: Fri, 28 May 2004 16:00:21 +0000
Subject: [PATCH] Factor common code for generating index keys into a
 procedure.  Other speed improvements and bug fixes. (CVS 1487)

FossilOrigin-Name: 6661bb5f9c1692f94b8b7d900b6be07f027e6324
---
 manifest        | 28 ++++++++++++++--------------
 manifest.uuid   |  2 +-
 src/build.c     | 17 ++++-------------
 src/delete.c    | 41 +++++++++++++++++++++++++++++------------
 src/pragma.c    | 14 ++------------
 src/sqliteInt.h |  3 ++-
 src/utf.c       |  8 ++++----
 src/util.c      |  8 ++------
 src/vdbe.c      | 32 +++++++++++++++++++++++++-------
 src/vdbeaux.c   |  9 ++++++++-
 10 files changed, 91 insertions(+), 71 deletions(-)

diff --git a/manifest b/manifest
index 15f258b83b..925dcad8ce 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sbug\sin\sthe\ssqlite3_column_decltype()\sAPI.\s(CVS\s1486)
-D 2004-05-28T13:13:02
+C Factor\scommon\scode\sfor\sgenerating\sindex\skeys\sinto\sa\sprocedure.\s\sOther\nspeed\simprovements\sand\sbug\sfixes.\s(CVS\s1487)
+D 2004-05-28T16:00:22
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -26,9 +26,9 @@ F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5
 F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
 F src/btree.c 6db76fbf63efd6008c5e6cb038ea40f94abffcf7
 F src/btree.h b65140b5ae891f30d2a39e64b9f0343225553545
-F src/build.c 3d6fd4a919c82f6b3dbbe2845bd0c087c73397ae
+F src/build.c 60ec4b38c0f158c9f2e4778ef6af13d19af7bfcd
 F src/date.c 0eb922af5c5f5e2455f8dc2f98023ed3e04a857e
-F src/delete.c 66c5ab98cbad7e6b315fc997bfe6c8080784a701
+F src/delete.c 72f8febf6170cda830f509c8f9dffbed3df3596c
 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
 F src/expr.c 1f7b853b097806ff6b0a3edd884c9b6675698745
 F src/func.c 1fe0763675eb38b6e3992d3edfbec2271798b658
@@ -49,13 +49,13 @@ F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
 F src/pager.c 6ff6b906427d4824099140776cb8768f922f3dc5
 F src/pager.h 78a00ac280899bcba1a89dc51585dcae6b7b3253
 F src/parse.y 9d3be712abc9005495701efbec741c58408f1343
-F src/pragma.c f2b05b087a5764802296a28d7abdd75728beedee
+F src/pragma.c 0c17b613d719c62a0dbad659b7d8a6e7ce7e9733
 F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
 F src/select.c ee54bf2faa76f5e30832fd589a1f10c485047469
 F src/shell.c ed4d237b3e52a0a42512bfcc53530e46de20c28f
 F src/sqlite.h.in edc6408c7f53c2104f781a76b926036e17018ec9
-F src/sqliteInt.h 1c3fc5d7a2bf33b1ea64284c81dbd07d00d9d1bd
+F src/sqliteInt.h d95d08442d19e2ee592ce1ec7865cbbcf23640bd
 F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
 F src/tclsqlite.c 877d0b96013a25b03ed6bd2d32917c42e84403bc
 F src/test1.c 32934478366531503d634968db414df17cb38238
@@ -66,14 +66,14 @@ F src/test5.c 9a1f15133f6955f067c5246e564723b5f23ff221
 F src/tokenize.c 50a87c7414de54a008427c9fed22e4e86efb6844
 F src/trigger.c 9ab75040aec65b593b54a7c1d4546f2f9ca058ef
 F src/update.c 96461bcf4e946697e83c09c77c7e61b545a2f66e
-F src/utf.c 59b5c8f06a4384a9f64933d6c57a2de02ce3673b
-F src/util.c 79a813dfc81329c5a1c5c9f7f40fbd4c570a7c75
+F src/utf.c d87fffc1ea7e52d73014ccea06afe1382bbb28b2
+F src/util.c 4df9d9b0d930d81ec581bcb68748e7c48bdc8c7d
 F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad
-F src/vdbe.c 3b208964add3da0c35c41955a95e6aa44ce75850
+F src/vdbe.c 68f3583ba2cb13ef0121be99e0edccfff133281a
 F src/vdbe.h e73f890e0f2a6c42b183d7d6937947930fe4fdeb
 F src/vdbeInt.h c2bcd6e5a6e6a3753e4c5a368629c3a625719bfc
 F src/vdbeapi.c 0c5d64c81871cb4fe5407e639604ee95738b6942
-F src/vdbeaux.c b1e176b1c9027b4a4eff7b936a449d926956f283
+F src/vdbeaux.c bbcf1bb953526130495b01b23751cf756cfed2fb
 F src/vdbemem.c c97c145ff6d9fc5b4236704c04a65849117e6214
 F src/where.c efe5d25fe18cd7381722457898cd863e84097a0c
 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
@@ -204,7 +204,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P ad879a957d93c0b49c289947826b451d3ea37e5b
-R b9f9e8717dc68172e0562ef2fe6cb24a
-U danielk1977
-Z 50937c4114738747c8662b16c4256cda
+P c8a40218c20cf5d0abad330e8fa59ca4c36e7608
+R 3143f6cfe246debfe7547a873f48094e
+U drh
+Z 33a80435a29a583c43c0f69454c7f7ae
diff --git a/manifest.uuid b/manifest.uuid
index adf7d768a9..c1e422d992 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-c8a40218c20cf5d0abad330e8fa59ca4c36e7608
\ No newline at end of file
+6661bb5f9c1692f94b8b7d900b6be07f027e6324
\ No newline at end of file
diff --git a/src/build.c b/src/build.c
index 92efbf084a..bf208acd22 100644
--- a/src/build.c
+++ b/src/build.c
@@ -23,7 +23,7 @@
 **     ROLLBACK
 **     PRAGMA
 **
-** $Id: build.c,v 1.196 2004/05/28 12:33:31 danielk1977 Exp $
+** $Id: build.c,v 1.197 2004/05/28 16:00:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1875,7 +1875,7 @@ void sqlite3CreateIndex(
     }
     sqlite3VdbeAddOp(v, OP_String, 0, 0);
     if( pStart && pEnd ){
-      sqlite3VdbeChangeP3(v, -1, "CREATE INDEX ", n);
+      sqlite3VdbeChangeP3(v, -1, "CREATE INDEX ", P3_STATIC);
       sqlite3VdbeAddOp(v, OP_String, 0, 0);
       n = Addr(pEnd->z) - Addr(pName->z) + 1;
       sqlite3VdbeChangeP3(v, -1, pName->z, n);
@@ -1890,17 +1890,8 @@ void sqlite3CreateIndex(
       sqlite3VdbeAddOp(v, OP_SetNumColumns, 2, pTab->nCol);
       lbl2 = sqlite3VdbeMakeLabel(v);
       sqlite3VdbeAddOp(v, OP_Rewind, 2, lbl2);
-      lbl1 = sqlite3VdbeAddOp(v, OP_Recno, 2, 0);
-      for(i=0; i<pIndex->nColumn; i++){
-        int iCol = pIndex->aiColumn[i];
-        if( pTab->iPKey==iCol ){
-          sqlite3VdbeAddOp(v, OP_Dup, i, 0);
-        }else{
-          sqlite3VdbeAddOp(v, OP_Column, 2, iCol);
-        }
-      }
-      sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
-      sqlite3IndexAffinityStr(v, pIndex);
+      lbl1 = sqlite3VdbeCurrentAddr(v);
+      sqlite3GenerateIndexKey(v, pIndex, 2);
       sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
                       "indexed columns are not unique", P3_STATIC);
       sqlite3VdbeAddOp(v, OP_Next, 2, lbl1);
diff --git a/src/delete.c b/src/delete.c
index 2e69961d76..bd77b59bc9 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle DELETE FROM statements.
 **
-** $Id: delete.c,v 1.70 2004/05/26 10:11:05 danielk1977 Exp $
+** $Id: delete.c,v 1.71 2004/05/28 16:00:22 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -379,17 +379,34 @@ void sqlite3GenerateRowIndexDelete(
   for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
     int j;
     if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
-    sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
-    for(j=0; j<pIdx->nColumn; j++){
-      int idx = pIdx->aiColumn[j];
-      if( idx==pTab->iPKey ){
-        sqlite3VdbeAddOp(v, OP_Dup, j, 0);
-      }else{
-        sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
-      }
-    }
-    sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
-    sqlite3IndexAffinityStr(v, pIdx);
+    sqlite3GenerateIndexKey(v, pIdx, iCur);
     sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
   }
 }
+
+/*
+** Generate code that will assemble an index key and put it on the top
+** of the tack.  The key with be for index pIdx which is an index on pTab.
+** iCur is the index of a cursor open on the pTab table and pointing to
+** the entry that needs indexing.
+*/
+void sqlite3GenerateIndexKey(
+  Vdbe *v,           /* Generate code into this VDBE */
+  Index *pIdx,       /* The index for which to generate a key */
+  int iCur           /* Cursor number for the pIdx->pTable table */
+){
+  int j;
+  Table *pTab = pIdx->pTable;
+
+  sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
+  for(j=0; j<pIdx->nColumn; j++){
+    int idx = pIdx->aiColumn[j];
+    if( idx==pTab->iPKey ){
+      sqlite3VdbeAddOp(v, OP_Dup, j, 0);
+    }else{
+      sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
+    }
+  }
+  sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
+  sqlite3IndexAffinityStr(v, pIdx);
+}
diff --git a/src/pragma.c b/src/pragma.c
index 002408bc2e..19552f2455 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.32 2004/05/26 10:11:06 danielk1977 Exp $
+** $Id: pragma.c,v 1.33 2004/05/28 16:00:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -642,17 +642,7 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
             { OP_Concat,      4,  0,  0},
             { OP_Callback,    1,  0,  0},
           };
-          sqlite3VdbeAddOp(v, OP_Recno, 1, 0);
-          for(k=0; k<pIdx->nColumn; k++){
-            int idx = pIdx->aiColumn[k];
-            if( idx==pTab->iPKey ){
-              sqlite3VdbeAddOp(v, OP_Recno, 1, 0);
-            }else{
-              sqlite3VdbeAddOp(v, OP_Column, 1, idx);
-            }
-          }
-          sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
-          sqlite3IndexAffinityStr(v, pIdx);
+          sqlite3GenerateIndexKey(v, pIdx, 1);
           jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0);
           addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
           sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 7f7e049dd6..c19a6cc354 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.259 2004/05/28 12:33:31 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.260 2004/05/28 16:00:22 drh Exp $
 */
 #include "config.h"
 #include "sqlite.h"
@@ -1267,6 +1267,7 @@ int sqlite3ExprIsInteger(Expr*, int*);
 int sqlite3IsRowid(const char*);
 void sqlite3GenerateRowDelete(sqlite*, Vdbe*, Table*, int, int);
 void sqlite3GenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*);
+void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
 void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
 void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int);
 int sqlite3OpenTableAndIndices(Parse*, Table*, int);
diff --git a/src/utf.c b/src/utf.c
index 255df323ad..ff51eed514 100644
--- a/src/utf.c
+++ b/src/utf.c
@@ -12,7 +12,7 @@
 ** This file contains routines used to translate between UTF-8, 
 ** UTF-16, UTF-16BE, and UTF-16LE.
 **
-** $Id: utf.c,v 1.12 2004/05/27 09:28:43 danielk1977 Exp $
+** $Id: utf.c,v 1.13 2004/05/28 16:00:22 drh Exp $
 **
 ** Notes on UTF-8:
 **
@@ -25,9 +25,9 @@
 **
 ** Notes on UTF-16:  (with wwww+1==uuuuu)
 **
-**      Word-0            Word-1             Value
-**  110110wwwwxxxxxx 110111yyyyyyyyyy        000uuuuu xxxxxxyy yyyyyyyy
-**  xxxxxxxxyyyyyyyy                         00000000 xxxxxxxx yyyyyyyy
+**      Word-0               Word-1          Value
+**  110110ww wwzzzzyy   110111yy yyxxxxxx    000uuuuu zzzzyyyy yyxxxxxx
+**  zzzzyyyy yyxxxxxx                        00000000 zzzzyyyy yyxxxxxx
 **
 **
 ** BOM or Byte Order Mark:
diff --git a/src/util.c b/src/util.c
index 92dff9131e..4aea0c802d 100644
--- a/src/util.c
+++ b/src/util.c
@@ -14,7 +14,7 @@
 ** This file contains functions for allocating memory, comparing
 ** strings, and stuff like that.
 **
-** $Id: util.c,v 1.93 2004/05/28 11:37:28 danielk1977 Exp $
+** $Id: util.c,v 1.94 2004/05/28 16:00:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -393,7 +393,7 @@ void sqlite3SetNString(char **pz, ...){
   while( (z = va_arg(ap, const char*))!=0 ){
     n = va_arg(ap, int);
     if( n<=0 ) n = strlen(z);
-    strncpy(zResult, z, n);
+    memcpy(zResult, z, n);
     zResult += n;
   }
   *zResult = 0;
@@ -1330,7 +1330,3 @@ void *sqlite3HexToBlob(const char *z){
   }
   return zBlob;
 }
-
-
-
-
diff --git a/src/vdbe.c b/src/vdbe.c
index e695961b97..22b61be7f8 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -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.344 2004/05/28 11:37:28 danielk1977 Exp $
+** $Id: vdbe.c,v 1.345 2004/05/28 16:00:22 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -1869,7 +1869,11 @@ case OP_Column: {
     aType = pC->aType;
     aOffset = pC->aOffset;
   }else{
-    aType = sqliteMallocRaw( 2*nField*sizeof(aType) );
+    if( pC && pC->aType ){
+      aType = pC->aType;
+    }else{
+      aType = sqliteMallocRaw( 2*nField*sizeof(aType) );
+    }
     aOffset = &aType[nField];
     if( aType==0 ){
       goto no_mem;
@@ -1944,6 +1948,7 @@ case OP_Column: {
     zData = sMem.z;
   }
   sqlite3VdbeSerialGet(zData, aType[p2], pTos);
+  sqlite3VdbeMemMakeWriteable(pTos);
   pTos->enc = db->enc;
   if( rc!=SQLITE_OK ){
     goto abort_due_to_error;
@@ -2049,6 +2054,7 @@ case OP_MakeRecord: {
   int addRowid;      /* True to append a rowid column at the end */
   u32 serial_type;   /* Type field */
   int containsNull;  /* True if any of the data fields are NULL */
+  char zTemp[NBFS];  /* Space to hold small records */
 
   Mem *pData0 = &pTos[1-nField];
   assert( pData0>=p->aStack );
@@ -2094,9 +2100,13 @@ case OP_MakeRecord: {
   }
 
   /* Allocate space for the new record. */
-  zNewRecord = sqliteMallocRaw(nByte);
-  if( !zNewRecord ){
-    goto no_mem;
+  if( nByte>sizeof(zTemp) ){
+    zNewRecord = sqliteMallocRaw(nByte);
+    if( !zNewRecord ){
+      goto no_mem;
+    }
+  }else{
+    zNewRecord = zTemp;
   }
 
   /* Write the record */
@@ -2131,8 +2141,16 @@ case OP_MakeRecord: {
   }
   pTos++;
   pTos->n = nByte;
-  pTos->z = zNewRecord;
-  pTos->flags = MEM_Blob | MEM_Dyn;
+  if( nByte<=sizeof(zTemp) ){
+    assert( zNewRecord==zTemp );
+    pTos->z = pTos->zShort;
+    memcpy(pTos->zShort, zTemp, nByte);
+    pTos->flags = MEM_Blob | MEM_Short;
+  }else{
+    assert( zNewRecord!=zTemp );
+    pTos->z = zNewRecord;
+    pTos->flags = MEM_Blob | MEM_Dyn;
+  }
 
   /* If P2 is non-zero, and if the key contains a NULL value, and if this
   ** was an OP_MakeIdxKey instruction, not OP_MakeKey, jump to P2.
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 1ad5d3c8b6..4bb52261de 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -1219,6 +1219,13 @@ u32 sqlite3VdbeSerialType(Mem *pMem){
 */
 int sqlite3VdbeSerialTypeLen(u32 serial_type){
   assert( serial_type!=0 );
+  if( serial_type>6 ){
+    return (serial_type-12)/2;
+  }else{
+    static u8 aSize[] = { 0, 1, 2, 4, 8, 8, 0, };
+    return aSize[serial_type];
+  }
+#if 0
   switch(serial_type){
     case 6: return 0;                  /* NULL */
     case 1: return 1;                  /* 1 byte integer */
@@ -1229,6 +1236,7 @@ int sqlite3VdbeSerialTypeLen(u32 serial_type){
   }
   assert( serial_type>=12 );
   return ((serial_type-12)>>1);        /* text or blob */
+#endif
 }
 
 /*
@@ -1329,7 +1337,6 @@ int sqlite3VdbeSerialGet(
   }else{
     pMem->flags = MEM_Blob | MEM_Ephem;
   }
-  sqlite3VdbeMemMakeWriteable(pMem);
   return len;
 }