From: dan Date: Mon, 16 Mar 2026 16:21:43 +0000 (+0000) Subject: If OP_IdxDelete cannot find an index entry to delete, first search 10 entries in... X-Git-Tag: major-release~74^2~21 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=066a5bcdd716b59dd471a8e4a6d04f71f61a7566;p=thirdparty%2Fsqlite.git If OP_IdxDelete cannot find an index entry to delete, first search 10 entries in either direction of where the entry should be in the index. If that fails, search the entire index for an entry with matching PK fields. FossilOrigin-Name: 2cb9f4e4178549144acd82e317a1646e71c9281ac9fc4aa26bf129f1068ded45 --- diff --git a/manifest b/manifest index 97b09a3fa0..d737e8c4bc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sthe\sfind-delete-key\smethod\son\sthis\sbranch. -D 2026-03-16T15:49:58.396 +C If\sOP_IdxDelete\scannot\sfind\san\sindex\sentry\sto\sdelete,\sfirst\ssearch\s10\sentries\sin\seither\sdirection\sof\swhere\sthe\sentry\sshould\sbe\sin\sthe\sindex.\sIf\sthat\sfails,\ssearch\sthe\sentire\sindex\sfor\san\sentry\swith\smatching\sPK\sfields. +D 2026-03-16T16:21:43.376 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -803,7 +803,7 @@ F src/vdbe.c 31ca4aaad332c3b973c5fb74bc76972a856fcb99c581e68efc35b6e9299a6d6c F src/vdbe.h 966d0677a540b7ea6549b7c4e1312fc0d830fce3a235a58c801f2cc31cf5ecf9 F src/vdbeInt.h 68d4adddb1eb48cdbaff8cce1305ac6bc5ad9115f1a37087a13d01a045303e7a F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1 -F src/vdbeaux.c 6af3a26cd0ecde496eb3a0ad5ac90da098ce923a5c93f48c8d4f0bbc768863bc +F src/vdbeaux.c df278c8a46a1e8ff9610f166167966de20b216016550d0d4fec26503c4e55006 F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692 F src/vdbemem.c 317ec5e870ddb16951b606c9fe8be22baef22ecbe46f58fdefc259662238afb7 F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70 @@ -2193,8 +2193,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P c4b0081f08bd0458dbcf269b43a4051941eec8067393aa8e6810d4b8422ce44a -R a18915b4118c3d28a02387e1bb9fac1b +P 6f49b5ecad5d924999d045a1ade93d95e731182be1781aefa5bc763b6202e9c3 +R 07aad91547589b98e374a31de7dba336 U dan -Z ddfe823bdcd5bb4257cbd5344ccd28d9 +Z da974e9658962ed0763a3b684d15cc9b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 5140ff4fc4..d600a01baa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6f49b5ecad5d924999d045a1ade93d95e731182be1781aefa5bc763b6202e9c3 +2cb9f4e4178549144acd82e317a1646e71c9281ac9fc4aa26bf129f1068ded45 diff --git a/src/vdbeaux.c b/src/vdbeaux.c index c024cce9f7..2a6833e765 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -5395,24 +5395,10 @@ void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ /* ** This function compares the unpacked record with the current key that -** cursor pCur points to. It returns the usual less than zero, zero, or -** greater than zero if the cursor key is less than, equal to or greater -** than p. i.e. -** -** (pCur->pKey) - (p) -** -** Except that: -** -** * if the PK fields of the keys match, zero is always returned, even -** if the preceding fields do not match. -** -** * otherwise, if the preceding fields are not identical, the result -** of comparing them is returned. -** -** * finally, if the preceding fields all match but the PK fields do -** not, the result of comparing the PK fields is returned. -** -** This function is not optimized. It is not expected to be called often. +** cursor pCur points to, ignoring the first nKeyCol fields. It returns +** the usual less than zero, zero, or greater than zero if the remaining +** fields of the cursor cursor key are less than, equal to or greater +** than those in (*p). */ static int vdbeIsDeleteKey( BtCursor *pCur, /* Cursor open on index */ @@ -5439,20 +5425,16 @@ static int vdbeIsDeleteKey( if( rc==SQLITE_OK ){ int szHdr = 0; /* Size of record header in bytes */ int idxHdr = 0; /* Current index in header */ - int idxRec = 0; /* Current index in record */ - int ii = 0; - int nCol = 0; - int res = 0; idxHdr = getVarint32(aRec, szHdr); if( szHdr>98307 ){ rc = SQLITE_CORRUPT; }else{ - int recres = 0; /* Result of comparing record fields */ int res = 0; /* Result of this function call */ + int idxRec = szHdr; /* Index of next field in record body */ + int ii = 0; /* Iterator variable */ - idxRec = szHdr; - nCol = p->pKeyInfo->nAllField; + int nCol = p->pKeyInfo->nAllField; for(ii=0; iinRec ){ rc = SQLITE_CORRUPT_BKPT; - }else{ + }else if( ii>=nKeyCol ){ sqlite3VdbeSerialGet(&aRec[idxRec], iSerial, &mem); - idxRec += sqlite3VdbeSerialTypeLen(iSerial); - r2 = sqlite3MemCompare(&mem, &p->aMem[ii], p->pKeyInfo->aColl[ii]); - if( r2!=0 ){ - if( iiaMem[ii], p->pKeyInfo->aColl[ii]); + if( res!=0 ) break; } + idxRec += sqlite3VdbeSerialTypeLen(iSerial); } *piRes = res; @@ -5503,16 +5477,9 @@ static int vdbeIsDeleteKey( ** ** The algorithm used to find the correct record is: ** -** * Test the PK columns of the current record to see if they match (*p). -** If so, delete the current record. +** * Scan up to BTREE_FDK_RANGE entries either side of the current entry. ** -** * If the caller's (*pRes) value was -ve, advance the cursor forward one -** entry. Then test the PK fields again. Repeat until the cursor points -** to an entry larger than (*p). -** -** * Or, if the caller's (*pRes) value was +ve, move the cursor backwards -** one entry. Then test the PK fields again. Repeat until the cursor -** points to an entry larger than (*p). +** * If the above fails to find an entry to delete, search the entire index. */ int sqlite3VdbeFindDeleteKey( BtCursor *pCur, @@ -5520,26 +5487,50 @@ int sqlite3VdbeFindDeleteKey( UnpackedRecord *p, int *pRes ){ - int resCaller = *pRes; - int res = resCaller; +#define BTREE_FDK_RANGE 10 + int nStep = 0; + int res = 1; int rc = SQLITE_OK; + int ii = 0; + + /* Move the cursor back BTREE_FDK_RANGE entries. If this hits an EOF, + ** position the cursor at the first entry in the index and set nStep + ** to -1 so that the first loop below scans the entire index. Otherwise, + ** set nStep to BTREE_FDK_RANGE*2 so that the first loop below scans + ** just that many entries. */ + for(ii=0; sqlite3BtreeEof(pCur)==0 && ii=0), or the entire index if (nStep<0). */ + while( 1 ){ + for(ii=0; rc==SQLITE_OK && (ii