1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-04 04:42:17 +03:00

Better integrate the changes on this branch with OP_Insert and OP_IdxInsert.

FossilOrigin-Name: 101cef14910d6e865a94bc870aed599321b893188062a9a61d70a9434992cf23
This commit is contained in:
dan
2020-12-10 18:06:24 +00:00
parent cd1b2d0b54
commit 7aae73588a
8 changed files with 129 additions and 127 deletions

View 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;
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[] */
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;
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;