-C Make\sOP_IdxDelete\stolerant\sof\ssmall\svariations\sin\sindex\skey\svalues.
-D 2026-03-16T15:16:13.147
+C Fix\sa\sproblem\swith\sthe\sfind-delete-key\smethod\son\sthis\sbranch.
+D 2026-03-16T15:49:58.396
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 901499bed747c3b4b2be45be1abe912ba50a3f6a40ba88cc006ccf279f2d0e97
+F src/delete.c cc318f7e5e9d9606c3600c7af96e836597f0f4d77ff7914ef03c5f906f4a43b4
F src/expr.c 51e9c77ff5d9a21439e611fe6571a3cd50387e526e13c5614fd407e5b8571930
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 9a5b5b56af9f8fd5ddff8f83816de3e6d9b91ff392eeaefe707a59623e55aae7
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 0cb2e590e9dcac6807352017fcbf5a52e0f836d74a338cb8c02ee3162bcf6508
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
-F src/vdbe.c 303e8070a9d77509c754c2948cf1b61944930f1136001733e2bd5daaadefb8d1
+F src/vdbe.c 31ca4aaad332c3b973c5fb74bc76972a856fcb99c581e68efc35b6e9299a6d6c
F src/vdbe.h 966d0677a540b7ea6549b7c4e1312fc0d830fce3a235a58c801f2cc31cf5ecf9
-F src/vdbeInt.h e2ac1de191ba71b98daee4757950548f00b8bb169a794cf8cde51587cb147fe9
+F src/vdbeInt.h 68d4adddb1eb48cdbaff8cce1305ac6bc5ad9115f1a37087a13d01a045303e7a
F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
-F src/vdbeaux.c 4885cfc6a58b8bf7a8a367673649057dc4a076c0c8797edb6bf1470bb082a31d
+F src/vdbeaux.c 6af3a26cd0ecde496eb3a0ad5ac90da098ce923a5c93f48c8d4f0bbc768863bc
F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
F src/vdbemem.c 317ec5e870ddb16951b606c9fe8be22baef22ecbe46f58fdefc259662238afb7
F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
F test/e_walckpt.test 16e7d006e8687654ee59e7ad5a6d285ba23f0fe0eeb87f790afd6bc9cf1d1924
F test/e_walhook.test 01b494287ba9e60b70f6ebf3c6c62e0ffe01788e344a4846b08e5de0b344cb66
+F test/eiib1.test 810da7aa9d55c07c891599d48ef8f45a0fa37f036c9341884505e9e815fedab5
F test/emptytable.test a38110becbdfa6325cd65cb588dca658cd885f62
F test/enc.test b5503a87b31cea8a5084c6e447383f9ca08933bd2f29d97b6b6201081b2343eb
F test/enc2.test 872afe58db772e7dfa1ad8e0759f8cc820e9efc8172d460fae83023101c2e435
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P 80bc5bc07e221f837c28066f0a438f11c8ab6be4c8ba93615439eb1667967003
-R 5a3b7bcea17f97d45cd400c7992de61b
-T *branch * idxdelete-tolerance
-T *sym-idxdelete-tolerance *
-T -sym-trunk *
+P c4b0081f08bd0458dbcf269b43a4051941eec8067393aa8e6810d4b8422ce44a
+R a18915b4118c3d28a02387e1bb9fac1b
U dan
-Z 7bca9a15e7fe96dadf1d72ae49f0c8d2
+Z ddfe823bdcd5bb4257cbd5344ccd28d9
# Remove this line to create a well-formed Fossil manifest.
-c4b0081f08bd0458dbcf269b43a4051941eec8067393aa8e6810d4b8422ce44a
+6f49b5ecad5d924999d045a1ade93d95e731182be1781aefa5bc763b6202e9c3
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);
+ sqlite3VdbeAddOp4Int(v, OP_IdxDelete, iIdxCur+i, r1,
+ pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn, pIdx->nKeyCol);
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
pPrior = pIdx;
}
break;
}
-/* Opcode: IdxDelete P1 P2 P3 * *
+/* Opcode: IdxDelete P1 P2 P3 P4 *
** Synopsis: key=r[P2@P3]
**
** The content of P3 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the
** index opened by cursor P1.
**
+** P4 is the number of non-PK columns in the index entry.
+**
** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found
** and not in writable_schema mode.
*/
rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
if( rc ) goto abort_due_to_error;
if( res!=0 ){
- rc = sqlite3VdbeFindDeleteKey(pCrsr, &r, &res);
+ rc = sqlite3VdbeFindDeleteKey(pCrsr, pOp->p4.i, &r, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res!=0 ){
if( !sqlite3WritableSchema(db) ){
Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
#endif
int sqlite3VdbeTransferError(Vdbe *p);
-int sqlite3VdbeFindDeleteKey(BtCursor*, UnpackedRecord*, int*);
+int sqlite3VdbeFindDeleteKey(BtCursor*, int, UnpackedRecord*, int*);
int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
*/
static int vdbeIsDeleteKey(
BtCursor *pCur, /* Cursor open on index */
+ int nKeyCol,
UnpackedRecord *p, /* Index key being deleted */
int *piRes /* 0 for a match, non-zero for not a match */
){
idxRec += sqlite3VdbeSerialTypeLen(iSerial);
r2 = sqlite3MemCompare(&mem, &p->aMem[ii], p->pKeyInfo->aColl[ii]);
if( r2!=0 ){
- if( ii<p->pKeyInfo->nKeyField ){
+ if( ii<nKeyCol ){
if( recres==0 ) recres = r2;
}else{
res = recres;
** one entry. Then test the PK fields again. Repeat until the cursor
** points to an entry larger than (*p).
*/
-int sqlite3VdbeFindDeleteKey(BtCursor *pCur, UnpackedRecord *p, int *pRes){
+int sqlite3VdbeFindDeleteKey(
+ BtCursor *pCur,
+ int nKeyCol,
+ UnpackedRecord *p,
+ int *pRes
+){
int resCaller = *pRes;
int res = resCaller;
int rc = SQLITE_OK;
assert( resCaller==-1 || resCaller==0 || resCaller==+1 );
while( sqlite3BtreeEof(pCur)==0 && rc==SQLITE_OK ){
- rc = vdbeIsDeleteKey(pCur, p, &res);
+ rc = vdbeIsDeleteKey(pCur, nKeyCol, p, &res);
assert( res==-1 || res==0 || res==+1 );
if( res!=resCaller ) break;
--- /dev/null
+# 2026 March 16
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Check that OP_IdxDelete works when:
+#
+# 1.1.* The real value in the index is greater than that in the table,
+# 1.2.* The real value in the index is smaller than that in the table,
+# 1.3.* Duplicate distorted real values.
+#
+
+do_execsql_test 1.0.1 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b REAL);
+ INSERT INTO t1 VALUES(10, 10.0);
+ INSERT INTO t1 VALUES(15, 15.0);
+ INSERT INTO t1 VALUES(20, 20.0);
+ INSERT INTO t1 VALUES(25, 25.0);
+ INSERT INTO t1 VALUES(30, 30.0);
+ CREATE INDEX i1 ON t1(b);
+}
+
+set root [db one {SELECT rootpage FROM sqlite_schema WHERE name='i1'}]
+
+do_test 1.0.2 {
+ # Create an imposter table for index i1
+ sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 $root
+ db eval {
+ CREATE TABLE x1(b, rowid, PRIMARY KEY(b, rowid)) WITHOUT ROWID;
+ }
+ sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 0
+
+ db one { PRAGMA integrity_check }
+} ok
+
+do_execsql_test 1.1.1 {
+ UPDATE x1 SET b=21.0 WHERE rowid=20;
+ PRAGMA integrity_check;
+} {
+ {row 3 missing from index i1}
+}
+do_execsql_test 1.1.2 {
+ DELETE FROM t1 WHERE a=20;
+} {}
+do_execsql_test 1.1.3 {
+ PRAGMA integrity_check;
+} {ok}
+
+do_execsql_test 1.2.1 {
+ UPDATE x1 SET b=26.0 WHERE rowid=25;
+ PRAGMA integrity_check;
+} {
+ {row 3 missing from index i1}
+}
+do_execsql_test 1.2.2 {
+ DELETE FROM t1 WHERE a=25;
+} {}
+do_execsql_test 1.2.3 {
+ PRAGMA integrity_check;
+} {ok}
+
+do_execsql_test 1.3.1 {
+ DELETE FROM t1;
+ INSERT INTO t1 VALUES(5, 15.0);
+ INSERT INTO t1 VALUES(10, 20.0);
+ INSERT INTO t1 VALUES(15, 20.0);
+ INSERT INTO t1 VALUES(20, 20.0);
+ INSERT INTO t1 VALUES(25, 20.0);
+ INSERT INTO t1 VALUES(30, 20.0);
+ INSERT INTO t1 VALUES(35, 25.0);
+
+ UPDATE x1 SET b=19.0 WHERE b=20.0;
+ PRAGMA integrity_check;
+} {
+ {row 2 missing from index i1}
+ {row 3 missing from index i1}
+ {row 4 missing from index i1}
+ {row 5 missing from index i1}
+ {row 6 missing from index i1}
+}
+
+ # 1 15 2 30 3 20 4 10 5 25
+foreach {tn a} {
+ 1 15
+} {
+breakpoint
+ do_execsql_test 1.3.2.$tn {
+ DELETE FROM t1 WHERE a=$a
+ }
+}
+
+
+finish_test