From: drh Date: Sat, 4 Jun 2016 20:37:10 +0000 (+0000) Subject: Change the sqlite3BtreeKeySize() interface into sqlite3BtreeIntegerKey() and X-Git-Tag: version-3.14.0~110^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a7c90c42eaf1badd141ca21bd64669e03de9830c;p=thirdparty%2Fsqlite.git Change the sqlite3BtreeKeySize() interface into sqlite3BtreeIntegerKey() and make it only work for table btrees. Change sqlite3BtreeDataSize() into sqlite3BtreePayloadSize() and make it work for all btrees. Combine sqlite3BtreeDataFetch() and sqlite3BtreeKeyFetch() into a single sqlite3BtreePayloadFetch() routine. These changes seem to make the b-tree interface more rational and they reduce both binary size and CPU usage. FossilOrigin-Name: bef35e18dd19732f7859287b097feeb593e5900f --- diff --git a/manifest b/manifest index 5cfb3e8240..f5cc249751 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allocate\sKeyInfo\sobjects\sfrom\slookaside\sif\spossible. -D 2016-06-04T17:12:26.466 +C Change\sthe\ssqlite3BtreeKeySize()\sinterface\sinto\ssqlite3BtreeIntegerKey()\sand\nmake\sit\sonly\swork\sfor\stable\sbtrees.\s\sChange\ssqlite3BtreeDataSize()\sinto\nsqlite3BtreePayloadSize()\sand\smake\sit\swork\sfor\sall\sbtrees.\s\sCombine\nsqlite3BtreeDataFetch()\sand\ssqlite3BtreeKeyFetch()\sinto\sa\ssingle\nsqlite3BtreePayloadFetch()\sroutine.\s\sThese\schanges\sseem\sto\smake\sthe\nb-tree\sinterface\smore\srational\sand\sthey\sreduce\sboth\sbinary\ssize\sand\nCPU\susage. +D 2016-06-04T20:37:10.186 F Makefile.in 7321ef0b584224781ec7731408857fa8962c32cc F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 831503fc4e988f571590af1405645fff121b5f1e @@ -326,8 +326,8 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 6df65fdd569c901a418887a1a76f82ec35044556 F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 2128172fc1c420a6fa6878827fa595407795069a -F src/btree.h 1342a9b2cc2089e3534d3ef00204786783f6aea6 +F src/btree.c b55e96857e89734ae0ef2e77ed07b5e55314f1d9 +F src/btree.h 2107a2630e02c8cba58bb12ce14e731e734ea29c F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c e827e57e4a29c00e8429c5fd4d9d4572cb1b32a4 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 @@ -394,7 +394,7 @@ F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 F src/tclsqlite.c 9c4c4589d078de37813ded708d8838b338ffb060 F src/test1.c 43b37ab2b7338fd3313e74902f0d6c821eae843b F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b -F src/test3.c d2c9efd2985ff8f5502ffd3253156984778d77d8 +F src/test3.c c75c8af0eadb335236c9e61b51044c58a8f7dd59 F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1 F src/test6.c a684b7abd01352ab50cb79c0bf727e6b3f381a3d @@ -448,13 +448,13 @@ F src/update.c 4f05ea8cddfa367d045e03589756c02199e8f9bd F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52 -F src/vdbe.c 45e4da739187028281e342f79fae0f4145055bec +F src/vdbe.c f6d37b366fe426637708ad6ad21d93e8b52512e2 F src/vdbe.h 5591b5add447096e31288b5a0a78ec5d7b5c5170 F src/vdbeInt.h ddb157974436d87652de7dc641f7191496d9a8cd -F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c -F src/vdbeaux.c 1d6b9a979d1036db7bc39990e9e683f19520bc5c -F src/vdbeblob.c c9f2f494b911c6fa34efd9803f0a10807da80f77 -F src/vdbemem.c 5cfef60e60e19cab6275d1b975bf4c791d575beb +F src/vdbeapi.c 02bcbc2ca5d2004b029088b05b468b394881e103 +F src/vdbeaux.c c90275b0e55a2b32c03dc09314194fe46f2429d8 +F src/vdbeblob.c 83d2d266383157b02e2b809350bb197e89d7895b +F src/vdbemem.c 1ecaa5ee0caff07255f25d04e8dc88befb6f88d1 F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 F src/vtab.c 948d2d4984219eee37a7bf427d6667e21e6eb92e @@ -1500,7 +1500,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9583c0fb39f357a76e0c99ea03b034aea3e03c75 -R 065fce549d6916be91d3267449fff27c +P b411107a3609d53af4e147f01e311b858b78420b +R 80a60ad5ffc5ad6e753a2a298aeee05c +T *branch * btree-refactor +T *sym-btree-refactor * +T -sym-trunk * U drh -Z 36eef125b8bc40e49e28e0447e72ab1c +Z 4c3d5b0be019f44c3e1bc23daff07019 diff --git a/manifest.uuid b/manifest.uuid index b10b2154c9..2fca7ce9d8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b411107a3609d53af4e147f01e311b858b78420b \ No newline at end of file +bef35e18dd19732f7859287b097feeb593e5900f \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 7a2b80c23b..4003352a5e 100644 --- a/src/btree.c +++ b/src/btree.c @@ -609,20 +609,17 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){ ** the key. */ static int saveCursorKey(BtCursor *pCur){ - int rc; + int rc = SQLITE_OK; assert( CURSOR_VALID==pCur->eState ); assert( 0==pCur->pKey ); assert( cursorHoldsMutex(pCur) ); - rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); - assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ - - /* If this is an intKey table, then the above call to BtreeKeySize() - ** stores the integer key in pCur->nKey. In this case this value is - ** all that is required. Otherwise, if pCur is not open on an intKey - ** table, then malloc space for and store the pCur->nKey bytes of key - ** data. */ - if( 0==pCur->curIntKey ){ + if( pCur->curIntKey ){ + /* Only the rowid is required for a table btree */ + pCur->nKey = sqlite3BtreeIntegerKey(pCur); + }else{ + /* For an index btree, save the complete key content */ + pCur->nKey = sqlite3BtreePayloadSize(pCur); void *pKey = sqlite3Malloc( pCur->nKey ); if( pKey ){ rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); @@ -4262,46 +4259,33 @@ int sqlite3BtreeCursorIsValid(BtCursor *pCur){ #endif /* NDEBUG */ /* -** Set *pSize to the size of the buffer needed to hold the value of -** the key for the current entry. If the cursor is not pointing -** to a valid entry, *pSize is set to 0. -** -** For a table with the INTKEY flag set, this routine returns the key -** itself, not the number of bytes in the key. -** -** The caller must position the cursor prior to invoking this routine. -** -** This routine cannot fail. It always returns SQLITE_OK. +** Return the value of the integer key or "rowid" for a table btree. +** This routine is only valid for a cursor that is pointing into a +** ordinary table btree. If the cursor points to an index btree or +** is invalid, the result of this routine is undefined. */ -int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ +i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); + assert( pCur->curIntKey ); getCellInfo(pCur); - *pSize = pCur->info.nKey; - return SQLITE_OK; + return pCur->info.nKey; } /* -** Set *pSize to the number of bytes of data in the entry the -** cursor currently points to. +** Return the number of bytes of payload for the entry that pCur is +** currently pointing to. For table btrees, this will be the amount +** of data. For index btrees, this will be the size of the key. ** ** The caller must guarantee that the cursor is pointing to a non-NULL ** valid entry. In other words, the calling procedure must guarantee ** that the cursor has Cursor.eState==CURSOR_VALID. -** -** Failure is not possible. This function always returns SQLITE_OK. -** It might just as well be a procedure (returning void) but we continue -** to return an integer result code for historical reasons. */ -int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ - assert( cursorOwnsBtShared(pCur) ); +u32 sqlite3BtreePayloadSize(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 ); - assert( pCur->iPageapPage[pCur->iPage]->intKeyLeaf==1 ); getCellInfo(pCur); - *pSize = pCur->info.nPayload; - return SQLITE_OK; + return pCur->info.nPayload; } /* @@ -4743,10 +4727,7 @@ static const void *fetchPayload( ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ -const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){ - return fetchPayload(pCur, pAmt); -} -const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){ +const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){ return fetchPayload(pCur, pAmt); } diff --git a/src/btree.h b/src/btree.h index 5ac119c40a..5720df90f7 100644 --- a/src/btree.h +++ b/src/btree.h @@ -284,11 +284,10 @@ int sqlite3BtreeLast(BtCursor*, int *pRes); int sqlite3BtreeNext(BtCursor*, int *pRes); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int *pRes); -int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); +i64 sqlite3BtreeIntegerKey(BtCursor*); int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); -const void *sqlite3BtreeKeyFetch(BtCursor*, u32 *pAmt); -const void *sqlite3BtreeDataFetch(BtCursor*, u32 *pAmt); -int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); +const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); +u32 sqlite3BtreePayloadSize(BtCursor*); int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); diff --git a/src/test3.c b/src/test3.c index 1e4baf7577..bfd7c30b65 100644 --- a/src/test3.c +++ b/src/test3.c @@ -385,8 +385,7 @@ static int btree_payload_size( const char **argv /* Text of each argument */ ){ BtCursor *pCur; - int n2; - u64 n1; + u32 n; char zBuf[50]; if( argc!=2 ){ @@ -396,17 +395,9 @@ static int btree_payload_size( } pCur = sqlite3TestTextToPtr(argv[1]); sqlite3BtreeEnter(pCur->pBtree); - - /* The cursor may be in "require-seek" state. If this is the case, the - ** call to BtreeDataSize() will fix it. */ - sqlite3BtreeDataSize(pCur, (u32*)&n2); - if( pCur->apPage[pCur->iPage]->intKey ){ - n1 = 0; - }else{ - sqlite3BtreeKeySize(pCur, (i64*)&n1); - } + n = sqlite3BtreePayloadSize(pCur); sqlite3BtreeLeave(pCur->pBtree); - sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", (int)(n1+n2)); + sqlite3_snprintf(sizeof(zBuf),zBuf, "%u", n); Tcl_AppendResult(interp, zBuf, 0); return SQLITE_OK; } diff --git a/src/vdbe.c b/src/vdbe.c index d4392a89d9..356cf52f01 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2380,7 +2380,6 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ ** skipped for length() and all content loading can be skipped for typeof(). */ case OP_Column: { - i64 payloadSize64; /* Number of bytes in the record */ int p2; /* column number to retrieve */ VdbeCursor *pC; /* The VDBE cursor */ BtCursor *pCrsr; /* The BTree cursor */ @@ -2433,22 +2432,9 @@ case OP_Column: { }else{ assert( pC->eCurType==CURTYPE_BTREE ); assert( pCrsr ); - if( pC->isTable==0 ){ - assert( sqlite3BtreeCursorIsValid(pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64); - assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ - /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the - ** payload size, so it is impossible for payloadSize64 to be - ** larger than 32 bits. */ - assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 ); - pC->aRow = sqlite3BtreeKeyFetch(pCrsr, &avail); - pC->payloadSize = (u32)payloadSize64; - }else{ - assert( sqlite3BtreeCursorIsValid(pCrsr) ); - VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &pC->payloadSize); - assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ - pC->aRow = sqlite3BtreeDataFetch(pCrsr, &avail); - } + assert( sqlite3BtreeCursorIsValid(pCrsr) ); + pC->payloadSize = sqlite3BtreePayloadSize(pCrsr); + pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &avail); assert( avail<=65536 ); /* Maximum page size is 64KiB */ if( pC->payloadSize <= (u32)avail ){ pC->szRow = pC->payloadSize; @@ -4201,8 +4187,7 @@ case OP_NewRowid: { /* out2 */ v = 1; /* IMP: R-61914-48074 */ }else{ assert( sqlite3BtreeCursorIsValid(pC->uc.pCursor) ); - rc = sqlite3BtreeKeySize(pC->uc.pCursor, &v); - assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ + v = sqlite3BtreeIntegerKey(pC->uc.pCursor); if( v>=MAX_ROWID ){ pC->useRandomRowid = 1; }else{ @@ -4459,8 +4444,7 @@ case OP_Delete: { /* If p5 is zero, the seek operation that positioned the cursor prior to ** OP_Delete will have also set the pC->movetoTarget field to the rowid of ** the row that is being deleted */ - i64 iKey = 0; - sqlite3BtreeKeySize(pC->uc.pCursor, &iKey); + i64 iKey = sqlite3BtreeIntegerKey(pC->uc.pCursor); assert( pC->movetoTarget==iKey ); } #endif @@ -4476,7 +4460,7 @@ case OP_Delete: { zDb = db->aDb[pC->iDb].zName; pTab = pOp->p4.pTab; if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){ - sqlite3BtreeKeySize(pC->uc.pCursor, &pC->movetoTarget); + pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor); } }else{ zDb = 0; /* Not needed. Silence a compiler warning. */ @@ -4630,7 +4614,6 @@ case OP_RowData: { VdbeCursor *pC; BtCursor *pCrsr; u32 n; - i64 n64; pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); @@ -4662,20 +4645,9 @@ case OP_RowData: { if( rc!=SQLITE_OK ) goto abort_due_to_error; #endif - if( pC->isTable==0 ){ - assert( !pC->isTable ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64); - assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */ - if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } - n = (u32)n64; - }else{ - VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &n); - assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ - if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } + n = sqlite3BtreePayloadSize(pCrsr); + if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; } testcase( n==0 ); if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){ @@ -4740,8 +4712,7 @@ case OP_Rowid: { /* out2 */ pOut->flags = MEM_Null; break; } - rc = sqlite3BtreeKeySize(pC->uc.pCursor, &v); - assert( rc==SQLITE_OK ); /* Always so because of CursorRestore() above */ + v = sqlite3BtreeIntegerKey(pC->uc.pCursor); } pOut->u.i = v; break; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 1feecb3e11..83718eae39 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1650,8 +1650,7 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ u32 nRec; u8 *aRec; - rc = sqlite3BtreeDataSize(p->pCsr->uc.pCursor, &nRec); - if( rc!=SQLITE_OK ) goto preupdate_old_out; + nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); aRec = sqlite3DbMallocRaw(db, nRec); if( !aRec ) goto preupdate_old_out; rc = sqlite3BtreeData(p->pCsr->uc.pCursor, 0, nRec, aRec); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index bce676f10c..63609d72dd 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -4315,8 +4315,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ ** this code can safely assume that nCellKey is 32-bits */ assert( sqlite3BtreeCursorIsValid(pCur) ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey); - assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ + nCellKey = sqlite3BtreePayloadSize(pCur); assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); /* Read in the complete content of the index entry */ @@ -4393,8 +4392,7 @@ int sqlite3VdbeIdxKeyCompare( assert( pC->eCurType==CURTYPE_BTREE ); pCur = pC->uc.pCursor; assert( sqlite3BtreeCursorIsValid(pCur) ); - VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey); - assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */ + nCellKey = sqlite3BtreePayloadSize(pCur); /* nCellKey will always be between 0 and 0xffffffff because of the way ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ if( nCellKey<=0 || nCellKey>0x7fffffff ){ diff --git a/src/vdbeblob.c b/src/vdbeblob.c index f2b3ffef2b..01827f94d0 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -415,7 +415,7 @@ static int blobReadWrite( ** anyhow. */ sqlite3_int64 iKey; - sqlite3BtreeKeySize(p->pCsr, &iKey); + iKey = sqlite3BtreeIntegerKey(p->pCsr); sqlite3VdbePreUpdateHook( v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1 ); diff --git a/src/vdbemem.c b/src/vdbemem.c index f9396e570c..04cb9c5c63 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -991,11 +991,7 @@ int sqlite3VdbeMemFromBtree( /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() ** that both the BtShared and database handle mutexes are held. */ assert( (pMem->flags & MEM_RowSet)==0 ); - if( key ){ - zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); - }else{ - zData = (char *)sqlite3BtreeDataFetch(pCur, &available); - } + zData = (char *)sqlite3BtreePayloadFetch(pCur, &available); assert( zData!=0 ); if( offset+amt<=available ){