From: dan Date: Thu, 10 Dec 2020 18:06:24 +0000 (+0000) Subject: Better integrate the changes on this branch with OP_Insert and OP_IdxInsert. X-Git-Tag: version-3.35.0~190^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7aae73588aeb9fd33d26f0d0a654bfbebdccf72c;p=thirdparty%2Fsqlite.git Better integrate the changes on this branch with OP_Insert and OP_IdxInsert. FossilOrigin-Name: 101cef14910d6e865a94bc870aed599321b893188062a9a61d70a9434992cf23 --- diff --git a/manifest b/manifest index 3a5de7a2d6..d9b671f413 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 604f1fcaeb..36af76a357 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dfd4ca6891a893d0e9551689954d3e79114d5565f8a5264f96ad1d64fe1d6280 \ No newline at end of file +101cef14910d6e865a94bc870aed599321b893188062a9a61d70a9434992cf23 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 8087d3935b..224d533b7c 100644 --- a/src/btree.c +++ b/src/btree.c @@ -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( nOutinfo.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 && nInpPage->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( nOutinfo.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; diff --git a/src/btree.h b/src/btree.h index 4c2a872bb9..e00c473c93 100644 --- a/src/btree.h +++ b/src/btree.h @@ -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 diff --git a/src/btreeInt.h b/src/btreeInt.h index c09699fbb5..851b8e6c1d 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -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() */ }; /* diff --git a/src/insert.c b/src/insert.c index 0af845e887..2a40acaa0c 100644 --- a/src/insert.c +++ b/src/insert.c @@ -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); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 438f79c092..fa24bf9ac0 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 diff --git a/src/vdbe.c b/src/vdbe.c index 74fede8562..e640dedbcd 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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 );