@@ -444,6 +444,18 @@ static SQLITE_INLINE void cursorCurrentTreeValue(
444444 * ppData = pNode -> pValData + off0 ;
445445 * pnData = (int )(off1 - off0 );
446446}
447+
448+ static SQLITE_INLINE void cacheCurrentTreePayloadIfIntKey (BtCursor * pCur ){
449+ if ( pCur -> curIntKey ){
450+ const u8 * pVal ; int nVal ;
451+ cursorCurrentTreeValue (pCur , & pVal , & nVal );
452+ if ( nVal > 0 ){
453+ pCur -> pCachedPayload = (u8 * )pVal ;
454+ pCur -> nCachedPayload = nVal ;
455+ pCur -> cachedPayloadOwned = 0 ;
456+ }
457+ }
458+ }
447459static int flushDeferredEdits (BtShared * pBt );
448460static int ensureMutMap (BtCursor * pCur );
449461static int saveCursorPosition (BtCursor * pCur );
@@ -5257,23 +5269,7 @@ static int prollyBtCursorNext(BtCursor *pCur, int flags){
52575269 if ( rc == SQLITE_OK ){
52585270 if ( pCur -> pCur .eState == PROLLY_CURSOR_VALID ){
52595271 pCur -> eState = CURSOR_VALID ;
5260- /* Pre-populate the payload cache for INTKEY clean-read scans
5261- ** (same idea as PR #770, restored on Tim's no-mutmap fast
5262- ** path). xPayloadSize then xPayloadFetch are both called per
5263- ** row during OP_Column / table scans; both go through
5264- ** getCursorPayload's multi-branch chain. Caching the
5265- ** (pData, nData) pair here makes both subsequent trips hit
5266- ** the early-return at the top of getCursorPayload. The
5267- ** pointer borrows the leaf node memory; CLEAR_CACHED_PAYLOAD
5268- ** on the next move keeps it valid for exactly one row. */
5269- if ( pCur -> curIntKey ){
5270- const u8 * pVal ; int nVal ;
5271- cursorCurrentTreeValue (pCur , & pVal , & nVal );
5272- if ( nVal > 0 ){
5273- pCur -> pCachedPayload = (u8 * )pVal ;
5274- pCur -> nCachedPayload = nVal ;
5275- }
5276- }
5272+ cacheCurrentTreePayloadIfIntKey (pCur );
52775273 } else {
52785274 pCur -> eState = CURSOR_INVALID ;
52795275 return SQLITE_DONE ;
@@ -5334,23 +5330,7 @@ static int prollyBtCursorNext(BtCursor *pCur, int flags){
53345330 if ( rc == SQLITE_OK ){
53355331 if ( pCur -> pCur .eState == PROLLY_CURSOR_VALID ){
53365332 pCur -> eState = CURSOR_VALID ;
5337- /* Table scans call xPayloadSize then xPayloadFetch on every
5338- ** advanced row. Both go through getCursorPayload which has
5339- ** a multi-branch chain (cache, mutmap, intkey). Cache the
5340- ** (pData, nData) pair eagerly here so both subsequent
5341- ** trips hit the early-return at the top of getCursorPayload.
5342- ** The pointer borrows the leaf node memory; the cache is
5343- ** invalidated by CLEAR_CACHED_PAYLOAD on the next move.
5344- ** INTKEY-only — non-INTKEY may need reconstruction which
5345- ** the original path handles. */
5346- if ( pCur -> curIntKey ){
5347- const u8 * pVal ; int nVal ;
5348- prollyCursorValue (& pCur -> pCur , & pVal , & nVal );
5349- if ( nVal > 0 ){
5350- pCur -> pCachedPayload = (u8 * )pVal ;
5351- pCur -> nCachedPayload = nVal ;
5352- }
5353- }
5333+ cacheCurrentTreePayloadIfIntKey (pCur );
53545334 } else {
53555335 pCur -> eState = CURSOR_INVALID ;
53565336 return SQLITE_DONE ;
0 commit comments