Index: src/delete.c ================================================================== --- src/delete.c +++ src/delete.c @@ -583,21 +583,32 @@ int *aRegIdx /* Only delete if (aRegIdx && aRegIdx[i]>0) */ ){ Vdbe *v = pParse->pVdbe; Index *pPk; int iPk; + int iPkCsr; int i; int regKey; Index *pIdx; regKey = sqlite4GetTempReg(pParse); pPk = sqlite4FindPrimaryKey(pTab, &iPk); + iPkCsr = baseCur+iPk; for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - if( pIdx!=pPk && (aRegIdx==0 || aRegIdx[i]>0) ){ + if( pIdx->eIndexType==SQLITE4_INDEX_FTS5 ){ + int iCol; + int iReg = pParse->nMem+1; + pParse->nMem += (1 + pTab->nCol); + for(iCol=0; iColnCol; iCol++){ + sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, iCol, iReg+iCol); + } + sqlite4VdbeAddOp2(v, OP_RowKey, iPkCsr, iReg+pTab->nCol); + sqlite4Fts5CodeUpdate(pParse, pIdx, iReg+pTab->nCol, iReg, 1); + }else if( pIdx!=pPk && (aRegIdx==0 || aRegIdx[i]>0) ){ int addrNotFound; - sqlite4EncodeIndexKey(pParse, pPk, baseCur+iPk, pIdx, baseCur+i,0,regKey); + sqlite4EncodeIndexKey(pParse, pPk, baseCur+iPk,pIdx,baseCur+i,0,regKey); addrNotFound = sqlite4VdbeAddOp4(v, OP_NotFound, baseCur+i, 0, regKey, 0, P4_INT32 ); sqlite4VdbeAddOp1(v, OP_Delete, baseCur+i); sqlite4VdbeJumpHere(v, addrNotFound); Index: src/fts5.c ================================================================== --- src/fts5.c +++ src/fts5.c @@ -1092,11 +1092,11 @@ memcpy(&aKey[nKey], pPK, nPK); nKey += nPK; if( bDel ){ /* delete key aKey/nKey... */ - assert( 0 ); + rc = sqlite4KVStoreReplace(pStore, aKey, nKey, 0, -1); }else{ const KVByteArray *aData = (const KVByteArray *)&pTerm[1]; aData += pTerm->nToken; rc = sqlite4KVStoreReplace(pStore, aKey, nKey, aData, pTerm->nData); } @@ -1133,20 +1133,22 @@ void sqlite4Fts5CodeUpdate( Parse *pParse, Index *pIdx, int iRegPk, - int iRegData + int iRegData, + int bDel ){ Vdbe *v; Fts5Info *pInfo; /* p4 argument for FtsUpdate opcode */ if( 0==(pInfo = fts5InfoCreate(pParse, pIdx)) ) return; v = sqlite4GetVdbe(pParse); sqlite4VdbeAddOp3(v, OP_FtsUpdate, iRegPk, 0, iRegData); sqlite4VdbeChangeP4(v, -1, (const char *)pInfo, P4_FTS5INFO); + sqlite4VdbeChangeP5(v, (u8)bDel); } void sqlite4Fts5FreeInfo(sqlite4 *db, Fts5Info *p){ if( db->pnBytesFreed==0 ){ if( p->p ) p->pTokenizer->xDestroy(p->p); Index: src/insert.c ================================================================== --- src/insert.c +++ src/insert.c @@ -1420,11 +1420,11 @@ for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ assert( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY || aRegIdx[i] ); if( pIdx->eIndexType==SQLITE4_INDEX_FTS5 ){ int iPK; sqlite4FindPrimaryKey(pTab, &iPK); - sqlite4Fts5CodeUpdate(pParse, pIdx, aRegIdx[iPK], regContent); + sqlite4Fts5CodeUpdate(pParse, pIdx, aRegIdx[iPK], regContent, 0); } else if( aRegIdx[i] ){ int regData = 0; int flags = 0; if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -3269,9 +3269,9 @@ void sqlite4Fts5IndexInit(Parse *, Index *, ExprList *); void sqlite4Fts5IndexFree(sqlite4 *, Index *); int sqlite4Fts5Update(sqlite4 *, Fts5Info *, Mem *pPk, Mem *aArg, int, char **); void sqlite4Fts5FreeInfo(sqlite4 *db, Fts5Info *); -void sqlite4Fts5CodeUpdate(Parse *, Index *pIdx, int iRegPk, int iRegData); +void sqlite4Fts5CodeUpdate(Parse *, Index *pIdx, int iRegPk, int iRegData, int); void sqlite4Fts5CodeCksum(Parse *, Index *, int, int, int); #endif /* _SQLITEINT_H_ */ Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -506,11 +506,11 @@ j1 = sqlite4VdbeAddOp4(v, OP_NotFound, iCur+iPk, 0, regOldKey, 0, P4_INT32); sqlite4GenerateRowIndexDelete(pParse, pTab, 0, iCur, aRegIdx); /* Delete the old record */ if( hasFK || bChngPk ){ - sqlite4VdbeAddOp2(v, OP_Delete, iCur, 0); + sqlite4VdbeAddOp2(v, OP_Delete, iCur+iPk, 0); } sqlite4VdbeJumpHere(v, j1); if( hasFK ){ sqlite4FkCheck(pParse, pTab, 0, regNew); Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -3022,10 +3022,12 @@ WhereTerm *pTerm; /* A single term of the WHERE clause */ #ifdef SQLITE4_ENABLE_STAT3 WhereTerm *pFirstTerm = 0; /* First term matching the index */ #endif int nCol = pProbe->nColumn; /* Total columns in index record */ + + if( pProbe->eIndexType==SQLITE4_INDEX_FTS5 ) continue; /* Unless pProbe is the primary key index, then the encoded PK column ** values are at the end of each record. Set variable nCol to the total ** number of columns encoded into each index record, including the PK ** columns. */ ADDED test/fts5query1.test Index: test/fts5query1.test ================================================================== --- /dev/null +++ test/fts5query1.test @@ -0,0 +1,38 @@ +# 2012 December 17 +# +# 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 +set testprefix fts5query1 + +do_execsql_test 1.0 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + CREATE INDEX i1 ON t1 USING fts5(); +} + +foreach {tn stmt} { + 1 "INSERT INTO t1 VALUES(1, 'a b c', 'd e f')" + 2 "INSERT INTO t1 VALUES(2, 'b c e', 'A A a')" + 3 "INSERT INTO t1 VALUES(3, 'd A A', 'e c a')" + 4 "DELETE FROM t1 WHERE a=1" + 5 "DELETE FROM t1" + 6 "INSERT INTO t1 VALUES(1, 'May you do', 'good and not evil')" + 7 "INSERT INTO t1 VALUES(2, 'May you find', 'forgiveness for yourself')" + 8 "UPDATE t1 SET b = 'and forgive others' WHERE a = 2" + 9 "UPDATE t1 SET a = 4 AND c = 'a b c d' WHERE a = 2" +} { + do_execsql_test 1.$tn.1 $stmt + do_execsql_test 1.$tn.2 {PRAGMA fts_check(i1)} ok +} + +finish_test