]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Better integrate the changes on this branch with OP_Insert and OP_IdxInsert.
authordan <Dan Kennedy>
Thu, 10 Dec 2020 18:06:24 +0000 (18:06 +0000)
committerdan <Dan Kennedy>
Thu, 10 Dec 2020 18:06:24 +0000 (18:06 +0000)
FossilOrigin-Name: 101cef14910d6e865a94bc870aed599321b893188062a9a61d70a9434992cf23

manifest
manifest.uuid
src/btree.c
src/btree.h
src/btreeInt.h
src/insert.c
src/sqliteInt.h
src/vdbe.c

index 3a5de7a2d673a287b6a88c2888cdf280f54bc441..d9b671f4138574b1b43e643588ae2c81bbf1b430 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Transfer\slarge\sindex\sor\sWITHOUT\sROWID\srecords\sbetween\sb-trees\swhen\svacuuming\swithout\sloading\sthem\sinto\smemory.
-D 2020-12-09T20:33:51.761
+C Better\sintegrate\sthe\schanges\son\sthis\sbranch\swith\sOP_Insert\sand\sOP_IdxInsert.
+D 2020-12-10T18:06:24.603
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -481,9 +481,9 @@ F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
 F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c ce6a27f7d8be22aed5914e3c5bb7293eb6bc8fa43b332c0c2cdd71afcceb81e7
-F src/btree.h 78908bc31dd4cbd54762825346d7a24534773ec4ca42e16faf10a0a164d74ec4
-F src/btreeInt.h ffd66480520d9d70222171b3a026d78b80833b5cea49c89867949f3e023d5f43
+F src/btree.c b14822d4dd984340d8b1c46bf5d49b12ab3adf6b639c5f3b395fa541153b1ba3
+F src/btree.h 285f8377aa1353185a32bf455faafa9ff9a0d40d074d60509534d14990c7829e
+F src/btreeInt.h 7614cae30f95b6aed0c7cac7718276a55cfe2c77058cbfd8bef5b75329757331
 F src/build.c f6449d4e85e998e14d3f537e8ea898dca2fcb83c277db3e60945af9b9177db81
 F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
@@ -501,7 +501,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 0c4f619e119dc6201fdc8f7ea4cbde9e71268cf3089b36c064c49c3e2d07077d
+F src/insert.c 153c5b438d44ba0b8ae7ca467f8f6390b18958d14e681a26e5e861a2ac480750
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
 F src/main.c 97e9f137354bc1f76dc9bb60a0a24f8c45cf73b33e80d3ee4c64155336fb820d
@@ -545,7 +545,7 @@ F src/shell.c.in e9f674ee4ec6c345679e8a5b16c869c6c59eb1540dd98ac69e4736ecddce009
 F src/sqlite.h.in 0e2b4259e49a0eda54d9118eb18a04fcd60e0727a2fd2c81aade0bf57520e706
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
-F src/sqliteInt.h 6ab40b33a1f5edbb7d71c78e82e0f9c5291dcff4704df8e4f0ab0d9c1a0c06af
+F src/sqliteInt.h 47bc1232d1c68525876c6c2d2b602bf8f614f84e7650de6031301435b535bf30
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -612,7 +612,7 @@ F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
 F src/util.c c0c7977de7ef9b8cb10f6c85f2d0557889a658f817b0455909a49179ba4c8002
 F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
-F src/vdbe.c 334c2626ad478fc85c992856e71a6bdd95dc11bf0d7cfe10856ec915f3d9fbe5
+F src/vdbe.c b8ac132f98ab4edb126c7784cfd6f479aa45e476c9e873c13ecd7bd6ffdd8668
 F src/vdbe.h 83603854bfa5851af601fc0947671eb260f4363e62e960e8a994fb9bbcd2aaa1
 F src/vdbeInt.h 3ca5e9fd6e095a8b6cf6bc3587a46fc93499503b2fe48951e1034ba9e2ce2f6e
 F src/vdbeapi.c c5e7cb2ab89a24d7f723e87b508f21bfb1359a04db5277d8a99fd1e015c12eb9
@@ -1889,7 +1889,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 0d2c3776065dc94119899ae4164995193b82fca7ac31868f3141b729d0b65ab9
-R 2ada74530286abe77d1ee50368ad4c2c
+P dfd4ca6891a893d0e9551689954d3e79114d5565f8a5264f96ad1d64fe1d6280
+R 649db055ff8e87cb8a713e180a0e255a
 U dan
-Z b452c10135ea2f1997d2fa69cc2163a3
+Z 6c3c81094000f4145ba4e14f9b1ea402
index 604f1fcaeb7eec082a20dfe0ba78cbc0cdd2125d..36af76a357dae6f0eefa99f158903d3458c6e98a 100644 (file)
@@ -1 +1 @@
-dfd4ca6891a893d0e9551689954d3e79114d5565f8a5264f96ad1d64fe1d6280
\ No newline at end of file
+101cef14910d6e865a94bc870aed599321b893188062a9a61d70a9434992cf23
\ No newline at end of file
index 8087d3935bb16d8f4ee7a335e2b2edd864cbdf12..224d533b7c10632ead5f1e34801dbdcb681efde4 100644 (file)
@@ -8679,7 +8679,7 @@ int sqlite3BtreeInsert(
   unsigned char *newCell = 0;
 
   assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
-  assert( (flags & BTREE_PREFORMAT)==0 || seekResult );
+  assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
 
   if( pCur->eState==CURSOR_FAULT ){
     assert( pCur->skipNext!=SQLITE_OK );
@@ -8825,14 +8825,21 @@ int sqlite3BtreeInsert(
   newCell = pBt->pTmpSpace;
   assert( newCell!=0 );
   if( flags & BTREE_PREFORMAT ){
-    assert( pX->pData==pBt->pTmpSpace );
-    szNew = pX->nData;
-    if( szNew<4 ) szNew = 4;
     rc = SQLITE_OK;
+    szNew = pBt->nPreformatSize;
+    if( szNew<4 ) szNew = 4;
+    if( ISAUTOVACUUM && szNew>pPage->maxLocal ){
+      CellInfo info;
+      pPage->xParseCell(pPage, newCell, &info);
+      if( ISAUTOVACUUM && info.nPayload!=info.nLocal ){
+        Pgno ovfl = get4byte(&newCell[szNew-4]);
+        ptrmapPut(pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc);
+      }
+    }
   }else{
     rc = fillInCell(pPage, newCell, pX, &szNew);
-    if( rc ) goto end_insert;
   }
+  if( rc ) goto end_insert;
   assert( szNew==pPage->xCellSize(pPage, newCell) );
   assert( szNew <= MX_CELL_SIZE(pBt) );
   idx = pCur->ix;
@@ -8938,97 +8945,88 @@ end_insert:
   return rc;
 }
 
-int sqlite3BtreeTransfer(
-  BtCursor *pDest,
-  BtCursor *pSrc,
-  i64 iKey,
-  int seekResult
-){
+int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
   int rc = SQLITE_OK;
-  BtreePayload x;
-  Pager *pSrcPager = pSrc->pBt->pPager;
-  u8 *pCell = pDest->pBt->pTmpSpace;
-  u8 *aOut;                     /* Pointer to next output buffer */
-  int nOut;                     /* Size of output buffer aOut[] */
+  BtShared *pBt = pDest->pBt;
+  u8 *aOut = pBt->pTmpSpace;    /* Pointer to next output buffer */
   const u8 *aIn;                /* Pointer to next input buffer */
   int nIn;                      /* Size of input buffer aIn[] */
   int nRem;                     /* Bytes of data still to copy */
-  u8 *pPgnoOut = 0;
-  Pgno ovflIn = 0;
-  DbPage *pPageIn = 0;
-  MemPage *pPageOut = 0;
 
-  memset(&x, 0, sizeof(x));
-  x.nKey = iKey;
   getCellInfo(pSrc);
-
-  x.pData = pCell;
-  x.nData += putVarint32(pCell, pSrc->info.nPayload);
-  if( pDest->pKeyInfo==0 ) x.nData += putVarint(&pCell[x.nData], iKey);
-
-  nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
-  aOut = &pCell[x.nData];
+  aOut += putVarint32(aOut, pSrc->info.nPayload);
+  if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
   nIn = pSrc->info.nLocal;
   aIn = pSrc->info.pPayload;
   nRem = pSrc->info.nPayload;
-
-  x.nData += nOut;
-  if( nOut<pSrc->info.nPayload ){
-    pPgnoOut = &pCell[x.nData];
-    x.nData += 4;
-  }
-
-  if( nRem>nIn ){
-    ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
-  }
-
-  do {
-    nRem -= nOut;
-    do{
-      assert( nOut>0 );
-      if( nIn>0 ){
-        int nCopy = MIN(nOut, nIn);
-        memcpy(aOut, aIn, nCopy);
-        nOut -= nCopy;
-        nIn -= nCopy;
-        aOut += nCopy;
-        aIn += nCopy;
-      }
-      if( nOut>0 ){
-        sqlite3PagerUnref(pPageIn);
-        pPageIn = 0;
-        rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
-        if( rc==SQLITE_OK ){
-          aIn = (const u8*)sqlite3PagerGetData(pPageIn);
-          ovflIn = get4byte(aIn);
-          aIn += 4;
-          nIn = pSrc->pBt->usableSize - 4;
+  if( nIn==nRem && nIn<pDest->pPage->maxLocal ){
+    memcpy(aOut, aIn, nIn);
+    pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
+  }else{
+    Pager *pSrcPager = pSrc->pBt->pPager;
+    u8 *pPgnoOut = 0;
+    Pgno ovflIn = 0;
+    DbPage *pPageIn = 0;
+    MemPage *pPageOut = 0;
+    int nOut;                     /* Size of output buffer aOut[] */
+
+    nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
+    pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
+    if( nOut<pSrc->info.nPayload ){
+      pPgnoOut = &aOut[nOut];
+      pBt->nPreformatSize += 4;
+    }
+  
+    if( nRem>nIn ){
+      ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
+    }
+  
+    do {
+      nRem -= nOut;
+      do{
+        assert( nOut>0 );
+        if( nIn>0 ){
+          int nCopy = MIN(nOut, nIn);
+          memcpy(aOut, aIn, nCopy);
+          nOut -= nCopy;
+          nIn -= nCopy;
+          aOut += nCopy;
+          aIn += nCopy;
+        }
+        if( nOut>0 ){
+          sqlite3PagerUnref(pPageIn);
+          pPageIn = 0;
+          rc = sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
+          if( rc==SQLITE_OK ){
+            aIn = (const u8*)sqlite3PagerGetData(pPageIn);
+            ovflIn = get4byte(aIn);
+            aIn += 4;
+            nIn = pSrc->pBt->usableSize - 4;
+          }
+        }
+      }while( rc==SQLITE_OK && nOut>0 );
+  
+      if( rc==SQLITE_OK && nRem>0 ){
+        Pgno pgnoNew;
+        MemPage *pNew = 0;
+        rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
+        put4byte(pPgnoOut, pgnoNew);
+        if( ISAUTOVACUUM && pPageOut ){
+          ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc);
+        }
+        releasePage(pPageOut);
+        pPageOut = pNew;
+        if( pPageOut ){
+          pPgnoOut = pPageOut->aData;
+          put4byte(pPgnoOut, 0);
+          aOut = &pPgnoOut[4];
+          nOut = MIN(pBt->usableSize - 4, nRem);
         }
       }
-    }while( rc==SQLITE_OK && nOut>0 );
-
-    if( rc==SQLITE_OK && nRem>0 ){
-      Pgno pgnoNew;
-      MemPage *pNew = 0;
-      rc = allocateBtreePage(pDest->pBt, &pNew, &pgnoNew, 0, 0);
-      put4byte(pPgnoOut, pgnoNew);
-      releasePage(pPageOut);
-      pPageOut = pNew;
-      if( pPageOut ){
-        pPgnoOut = pPageOut->aData;
-        put4byte(pPgnoOut, 0);
-        aOut = &pPgnoOut[4];
-        nOut = MIN(pDest->pBt->usableSize - 4, nRem);
-      }
-    }
-  }while( nRem>0 && rc==SQLITE_OK );
-
-  releasePage(pPageOut);
-  sqlite3PagerUnref(pPageIn);
-
-  if( rc==SQLITE_OK ){
-    int flags = BTREE_APPEND|BTREE_PREFORMAT;
-    rc = sqlite3BtreeInsert(pDest, &x, flags, seekResult);
+    }while( nRem>0 && rc==SQLITE_OK );
+  
+    releasePage(pPageOut);
+    sqlite3PagerUnref(pPageIn);
   }
 
   return rc;
index 4c2a872bb99aa79191972c32fc2e9c6d113d5d7a..e00c473c93b286699adf5f693706e29a29e8ae62 100644 (file)
@@ -262,7 +262,7 @@ int sqlite3BtreeDelete(BtCursor*, u8 flags);
 #define BTREE_SAVEPOSITION 0x02  /* Leave cursor pointing at NEXT or PREV */
 #define BTREE_AUXDELETE    0x04  /* not the primary delete operation */
 #define BTREE_APPEND       0x08  /* Insert is likely an append */
-#define BTREE_PREFORMAT    0x10  /* Insert is likely an append */
+#define BTREE_PREFORMAT    0x80  /* Insert is likely an append */
 
 /* An instance of the BtreePayload object describes the content of a single
 ** entry in either an index or table btree.
@@ -362,7 +362,7 @@ void sqlite3BtreeCursorList(Btree*);
   int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
 #endif
 
-int sqlite3BtreeTransfer(BtCursor*, BtCursor*, i64, int);
+int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
 
 /*
 ** If we are not using shared cache, then there is no need to
index c09699fbb56470b92f99bdb40418b86121f00018..851b8e6c1d1448c8db4cf7cff326f3f5a030629d 100644 (file)
@@ -455,6 +455,7 @@ struct BtShared {
   Btree *pWriter;       /* Btree with currently open write transaction */
 #endif
   u8 *pTmpSpace;        /* Temp space sufficient to hold a single cell */
+  int nPreformatSize;   /* Size of last cell written by TransferRow() */
 };
 
 /*
index 0af845e887fbfc4df0ef83b0d6199124a49b2f0f..2a40acaa0c9a819c3573072c9332e10f863bcd66 100644 (file)
@@ -2748,6 +2748,7 @@ static int xferOptimization(
   iDest = pParse->nTab++;
   regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
   regData = sqlite3GetTempReg(pParse);
+  sqlite3VdbeAddOp2(v, OP_Null, 0, regData);
   regRowid = sqlite3GetTempReg(pParse);
   sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
   assert( HasRowid(pDest) || destHasUniqueIdx );
@@ -2797,17 +2798,26 @@ static int xferOptimization(
       addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
       assert( (pDest->tabFlags & TF_Autoincrement)==0 );
     }
+
     if( db->mDbFlags & DBFLAG_Vacuum ){
       sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
-      insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
-      sqlite3VdbeAddOp3(v, OP_Transfer, iDest, iSrc, regRowid);
+      insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
     }else{
-      insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
+      insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT;
+    }
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+    if( db->xPreUpdateCallback ){
       sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
-      sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
-          (char*)pDest, P4_TABLE);
-      sqlite3VdbeChangeP5(v, insFlags);
+      insFlags &= ~OPFLAG_PREFORMAT;
+    }else
+#endif
+    {
+      sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regRowid);
     }
+    sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
+        (char*)pDest, P4_TABLE);
+    sqlite3VdbeChangeP5(v, insFlags);
+
     sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
     sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
     sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
@@ -2849,18 +2859,18 @@ static int xferOptimization(
         if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
       }
       if( i==pSrcIdx->nColumn ){
-        idxInsFlags = OPFLAG_USESEEKRESULT;
+        idxInsFlags = OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
         sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
-        sqlite3VdbeAddOp3(v, OP_Transfer, iDest, iSrc, 0);
+        sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regData);
       }
     }else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
       idxInsFlags |= OPFLAG_NCHANGE;
     }
-    if( idxInsFlags!=OPFLAG_USESEEKRESULT ){
+    if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){
       sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
-      sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
-      sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
     }
+    sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
+    sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
     sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
     sqlite3VdbeJumpHere(v, addr1);
     sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
index 438f79c0925649c9e71d3e9e9c0143beb5ec7d23..fa24bf9ac0aa86506963ab779be7dc76deea2af4 100644 (file)
@@ -3517,6 +3517,7 @@ struct AuthContext {
 #define OPFLAG_SAVEPOSITION  0x02    /* OP_Delete/Insert: save cursor pos */
 #define OPFLAG_AUXDELETE     0x04    /* OP_Delete: index in a DELETE op */
 #define OPFLAG_NOCHNG_MAGIC  0x6d    /* OP_MakeRecord: serialtype 10 is ok */
+#define OPFLAG_PREFORMAT     0x80    /* OP_Insert uses preformatted cell */ 
 
 /*
  * Each trigger present in the database schema is stored as an instance of
index 74fede85625988579ca9ba43cddbf89ab4e4bed1..e640dedbcdc701271fa883642f070c29759a3d90 100644 (file)
@@ -5126,7 +5126,8 @@ case OP_Insert: {
   }
   x.pKey = 0;
   rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
-      (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
+      (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), 
+      seekResult
   );
   pC->deferredMoveto = 0;
   pC->cacheStatus = CACHE_STALE;
@@ -5143,29 +5144,20 @@ case OP_Insert: {
   break;
 }
 
-/* Opcode: Transfer P1 P2 P3 * *
-** Synopsis: intkey=r[P3]
-**
-** P1 and P2 are both cursors open on either intkey or index btrees. This
-** instruction reads the current row from P2 and writes it into the
-** table opened by P1. If P1 and P2 are opened on intkey tables, register
-** P3 contains the rowid value to use when inserting into P1.
+/* Opcode: RowCell P1 P2 P3 * *
 */
-case OP_Transfer: {
+case OP_RowCell: {
   VdbeCursor *pDest;              /* Cursor to write to */
   VdbeCursor *pSrc;               /* Cursor to read from */
   i64 iKey;                       /* Rowid value to insert with */
-
+  assert( pOp[1].opcode==OP_Insert || pOp[1].opcode==OP_IdxInsert );
   pDest = p->apCsr[pOp->p1];
   pSrc = p->apCsr[pOp->p2];
   iKey = pOp->p3 ? aMem[pOp->p3].u.i : 0;
-
-  rc = sqlite3BtreeTransfer(
-      pDest->uc.pCursor, pSrc->uc.pCursor, iKey, pDest->seekResult
-  );
+  rc = sqlite3BtreeTransferRow(pDest->uc.pCursor, pSrc->uc.pCursor, iKey);
   if( rc!=SQLITE_OK ) goto abort_due_to_error;
   break;
-}
+};
 
 /* Opcode: Delete P1 P2 P3 P4 P5
 **
@@ -5822,7 +5814,7 @@ case OP_IdxInsert: {        /* in2 */
   assert( pC!=0 );
   assert( !isSorter(pC) );
   pIn2 = &aMem[pOp->p2];
-  assert( pIn2->flags & MEM_Blob );
+  assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) );
   if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
   assert( pC->eCurType==CURTYPE_BTREE );
   assert( pC->isTable==0 );
@@ -5833,7 +5825,7 @@ case OP_IdxInsert: {        /* in2 */
   x.aMem = aMem + pOp->p3;
   x.nMem = (u16)pOp->p4.i;
   rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
-       (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), 
+       (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)), 
       ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
       );
   assert( pC->deferredMoveto==0 );