-C Fix\sa\sinteger\stype\sbug\sin\sthe\sprevious\scheck-in.
-D 2026-04-22T13:41:20.203
+C Detect\sand\somit\scases\swhere\san\sindex\skey\sis\sbeing\sreplaced\swith\san\sidentical\skey.
+D 2026-04-22T16:58:36.117
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F src/date.c 61e92f1f7e2e88e1cd91e91dc69eb2b2854e7877254470f9fabd776bfac922b8
F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
-F src/delete.c 1f2268d6fe3c78fc1bf794ba65d7026498b78e2342ffaf85825dedae546e6fde
+F src/delete.c dbde329841d214a85b1fa9f4c7ce9f53e4fc3066d2f5d491b3364cd43ec3bc14
F src/expr.c 68400681c5f6e41231d2c85abf6bb432aeeb2e36c4abdf90eb7b78551a5ce0f3
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 377af5da226519a0f374dc3c6d408c9d303a92943e3ae5986432c7d52e6679a2
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
-F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
+F src/vdbe.c aeb80f9f9e3b7750b14dcaa439bbf026a4c71cd1881da86d04dfa1348ca8a474
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P dbc1d6f0a3452607e4e92155df0fdb1c5ea4ea5ad1654664f86383faf6c105ef
-R feff29d9635a2e79cc3708641148218b
-U drh
-Z 064078e48b7f7788e91c44276a045e81
+P 5e1b5ff1c170e94956bf77bd38afcad6369cb9f9333864711212af045281ad0e
+R 6a9d04ec755fb9001a47ce242326fc64
+T *branch * index-detect-noop
+T *sym-index-detect-noop *
+T -sym-trunk *
+U dan
+Z bd48131fa723540fccfa324eb37cb0d1
# Remove this line to create a well-formed Fossil manifest.
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
&iPartIdxLabel, pPrior, r1);
- sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
- pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn
- );
+ sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, aRegIdx ? aRegIdx[i] : 0);
sqlite3VdbeChangeP4(v, -1, (const char*)pIdx, P4_INDEX);
+ sqlite3VdbeChangeP5(v, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
pPrior = pIdx;
}
return h;
}
-
/*
** For OP_Column, factor out the case where content is loaded from
** overflow pages, so that the code to implement this case is separate
return rc;
}
+/*
+** Memory cell pMem may contain a blob or a NULL value. Cursor pCsr is
+** open on an index. If the current index entry matches the blob value in
+** pMem byte-for-byte, set pMem to NULL and return 1. Otherwise, return 0.
+**
+** If an error occurs, set (*pRc) to an SQLite error code. Return 1 in this
+** case as well.
+*/
+static SQLITE_NOINLINE int vdbeIndexKeyCompare(
+ BtCursor *pCsr, /* Cursor to compare key to */
+ Mem *pMem,
+ int *pRc
+){
+ int ret = 0;
+ u32 nKey = 0;
+
+ assert( pMem->flags & (MEM_Blob|MEM_Null) );
+ nKey = sqlite3BtreePayloadSize(pCsr);
+ if( nKey==pMem->n && (pMem->flags & MEM_Blob) ){
+ /* This code could just use sqlite3BtreePayloadFetch(). But calling that
+ ** function here apparently prevents compilers from inlining it in other,
+ ** more performance critical, places. So this code uses
+ ** MemFromBtreeZeroOffset(), which is just as fast in most cases, but also
+ ** handles the case where the index record uses overflow pages. */
+ Mem m;
+ memset(&m, 0, sizeof(m));
+ *pRc = sqlite3VdbeMemFromBtreeZeroOffset(pCsr, nKey, &m);
+ ret = (*pRc!=SQLITE_OK || 0==memcmp(pMem->z, m.z, nKey));
+ sqlite3VdbeMemReleaseMalloc(&m);
+ }
+
+ return ret;
+}
+
/*
** Send a "statement aborts" message to the error log.
*/
assert( pC!=0 );
assert( !isSorter(pC) );
pIn2 = &aMem[pOp->p2];
+ if( (pIn2->flags & MEM_Null) && (pOp->p5 & OPFLAG_PREFORMAT)==0 ) break;
assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) );
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
assert( pC->eCurType==CURTYPE_BTREE );
break;
}
-/* Opcode: IdxDelete P1 P2 P3 P4 *
-** Synopsis: key=r[P2@P3]
+/* Opcode: IdxDelete P1 P2 P3 P4 P5
+** Synopsis: key=r[P2@P5]
**
** The content of P3 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the
**
** P4 is a pointer to an Index structure.
**
+** If P3 is non-zero, it is the register number of a register holding
+** a record that will be inserted into this index. If that record is
+** identical to the one that would be deleted by this instruction,
+** skip the delete and set register P3 to NULL.
+**
** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
** and not in writable_schema mode.
*/
int res;
UnpackedRecord r;
- assert( pOp->p3>0 );
- assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem+1 - p->nCursor)+1 );
+ assert( pOp->p5>0 );
+ assert( pOp->p2>0 && pOp->p2+pOp->p5<=(p->nMem+1 - p->nCursor)+1 );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
r.pKeyInfo = pC->pKeyInfo;
- r.nField = (u16)pOp->p3;
+ r.nField = pOp->p5;
r.default_rc = 0;
r.aMem = &aMem[pOp->p2];
rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
break;
}
}
+
+ if( pOp->p3 && vdbeIndexKeyCompare(pCrsr, &aMem[pOp->p3], &rc) ){
+ if( rc ) goto abort_due_to_error;
+ sqlite3VdbeMemSetNull(&aMem[pOp->p3]);
+ break;
+ }
+
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
if( rc ) goto abort_due_to_error;
assert( pC->deferredMoveto==0 );