From: drh Date: Fri, 25 Oct 2013 14:46:15 +0000 (+0000) Subject: Basic DELETE operations now working on WITHOUT ROWID tables. X-Git-Tag: version-3.8.2~137^2~57 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=261c02d96375b8b05ed36adc8d00c63abfb2084b;p=thirdparty%2Fsqlite.git Basic DELETE operations now working on WITHOUT ROWID tables. FossilOrigin-Name: 9eafafa31c4a2bbcf48418743e0fcb17c374e9a6 --- diff --git a/manifest b/manifest index a44ff79d39..13d1feecb8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\sinterface\sto\sthe\ssqlite3GenerateRowDelete()\sutility\sso\sthat\sit\sis\nable\sto\shandle\sWITHOUT\sROWID\stables.\s\sThe\simplementation\sstill\sneeds\sto\sbe\s\ncompleted. -D 2013-10-24T19:48:39.042 +C Basic\sDELETE\soperations\snow\sworking\son\sWITHOUT\sROWID\stables. +D 2013-10-25T14:46:15.958 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -159,7 +159,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083 -F src/analyze.c ee880a4c0deb1c4090a4bbff03adfbf934451f50 +F src/analyze.c b6b115d69adaf0d2fa15001748b12735832fb296 F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3 @@ -168,12 +168,12 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 509722ce305471b626d3401c0631a808fd33237b F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0 -F src/build.c f99c6980a258e32e0e0068b04dd8eed6a4af9445 +F src/build.c 4d62e99fa36db1793cc1bed63e6775defdf8c587 F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 -F src/delete.c 3a750695133bf8646124b07cf8a51222110885a6 +F src/delete.c 8b9aa9c935fdd48a7a8ac0eff22c03cb29f12e96 F src/expr.c 3180b6332072b263f845592e72e92971af562ab0 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 628f81177299660a86e40359b3689b81f517e125 @@ -182,7 +182,7 @@ F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c a188b1abcc80cb835a1a9b76e78190d1516d22bc +F src/insert.c 71b3d1f551ab8e0ba59fdbaff3feef8d931a424e F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -212,18 +212,18 @@ F src/parse.y 073a8294e1826f1b1656e84806b77e4199f4bb57 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63 -F src/pragma.c d6eee7e1b6343996883e5c7e0f60bfad77be2180 +F src/pragma.c 5986f119f6350839a28936fce4e2d6a4c703922c F src/prepare.c f47ba2bba7ac5650881ab6c41f6d33a6de1a8d52 F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 F src/resolve.c e729889b2c7a680ba4aa7296efa72c09369956d8 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c dbcd2271470b5d074252ea75e2e50f3544638b49 +F src/select.c 8290456f2a516abaf8cbbed5e61944d3082e497e F src/shell.c 6f11f0e9ded63d48e306f2c6858c521e568a47bb F src/sqlite.h.in 547a44dd4ff4d975e92a645ea2d609e543a83d0f F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h a0834a450cd990eadcb18b790557abfe6dc52270 +F src/sqliteInt.h 674cee6761771e7c1d6446671fcf7daf27b4c0f7 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -279,7 +279,7 @@ F src/update.c 2bb5a267796e6d0177ef5689487c3688de5c309e F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918 F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 -F src/vdbe.c cca2c5eb4eb85ff10955c766cc75b78b4cbb5b08 +F src/vdbe.c f7a2fb5d707db64f59ebb2d054485790350f84db F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4 F src/vdbeInt.h ff57f67aee1ba26a3a47e786533dab155ab6dad6 F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed @@ -292,7 +292,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74 -F src/where.c 04217a957c1423dd5f177b21b4ced319bf24b77c +F src/where.c 512ddbf2884f5560a0ad5b076efc142ad7a07c7b F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1127,7 +1127,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 0e56ba69f0fcd12a5166c32f6e4eacdcc29fba04 -R 23965d1fb428e8ef205e9927049056c2 +P 85daf5174679630474b3bccf3d662d5d56bf00d5 +R 98e4cedace27c103667612897f7b7404 U drh -Z 7e96dccb2394803edfe091e61702bf27 +Z b296ee4a843fc7eab50d30ebcbf09f32 diff --git a/manifest.uuid b/manifest.uuid index 6c09c1517a..ddaf3cea50 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85daf5174679630474b3bccf3d662d5d56bf00d5 \ No newline at end of file +9eafafa31c4a2bbcf48418743e0fcb17c374e9a6 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 89d666c05f..d04e51da6e 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -244,8 +244,7 @@ static void openStatTable( /* Open the sqlite_stat[134] tables for writing. */ for(i=0; aTable[i].zCols; i++){ assert( inTab==0 ){ p->nTab = 1; } diff --git a/src/delete.c b/src/delete.c index b80db6f6b2..35d06aafe8 100644 --- a/src/delete.c +++ b/src/delete.c @@ -352,18 +352,70 @@ void sqlite3DeleteFrom( ){ assert( !isView ); sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); - sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, - pTab->zName, P4_STATIC); + if( HasRowid(pTab) ){ + sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, + pTab->zName, P4_STATIC); + } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ - /* The usual case: There is a WHERE clause so we have to scan through - ** the table and pick which records to delete. - */ - { + if( !HasRowid(pTab) ){ + /* There is a WHERE clause on a WITHOUT ROWID table. + */ + Index *pPk; /* The PRIMARY KEY index on the table */ + int iPk; /* First of nPk memory cells holding PRIMARY KEY value */ + int iEph; /* Ephemeral table holding all primary key values */ + int iKey; /* Key value inserting into iEph */ + i16 nPk; /* Number of components of the PRIMARY KEY */ + + pPk = sqlite3PrimaryKeyIndex(pTab); + assert( pPk!=0 ); + nPk = pPk->nKeyCol; + iPk = pParse->nMem+1; + pParse->nMem += nPk; + iKey = ++pParse->nMem; + iEph = pParse->nTab++; + + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iEph, nPk, 0, + (char*)sqlite3IndexKeyinfo(pParse, pPk), + P4_KEYINFO_HANDOFF); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 0, 0); + if( pWInfo==0 ) goto delete_from_cleanup; + for(i=0; iaiColumn[i], iPk+i); + } + sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, + sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, iKey); + sqlite3WhereEnd(pWInfo); + + /* Open cursors for all indices of the table. + */ + sqlite3OpenTableAndIndices(pParse, pTab, iCur, iCur, OP_OpenWrite); + + /* Loop over the primary keys to be deleted. */ + addr = sqlite3VdbeAddOp1(v, OP_Rewind, iEph); + sqlite3VdbeAddOp2(v, OP_RowKey, iEph, iPk); + + /* Delete the row */ + sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iCur, iPk, 0, + 1, OE_Default); + + /* End of the delete loop */ + sqlite3VdbeAddOp2(v, OP_Next, iEph, addr+1); + sqlite3VdbeJumpHere(v, addr); + + /* Close the cursors open on the table and its indexes. */ + for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ + sqlite3VdbeAddOp2(v, OP_Close, pIdx==pPk ? iCur : iCur + i, pIdx->tnum); + } + }else{ + /* There is a WHERE clause on a rowid table. Run a loop that extracts + ** all rowids to be deleted into a RowSet. + */ int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */ int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ int regRowid; /* Actual register containing rowids */ @@ -392,7 +444,7 @@ void sqlite3DeleteFrom( ** only effect this statement has is to fire the INSTEAD OF ** triggers. */ if( !isView ){ - sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); + sqlite3OpenTableAndIndices(pParse, pTab, iCur, -1, OP_OpenWrite); } addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid); @@ -475,10 +527,7 @@ delete_from_cleanup: ** cursor number iCur+i for the i-th index. ** ** 3. The primary key for the row to be deleted must be stored in a -** sequence of memory cells starting at iPk. If nPk==0 then the -** primary key is a rowid an uses just one memory cell. If nPk>0 -** then a WITHOUT ROWID table is being used and there are nPk elements -** of the primary key. +** sequence of memory cells starting at iPk. ** ** This routine generates code to remove both the table record and all ** index entries that point to that record. @@ -496,6 +545,7 @@ void sqlite3GenerateRowDelete( Vdbe *v = pParse->pVdbe; /* Vdbe */ int iOld = 0; /* First register in OLD.* array */ int iLabel; /* Label resolved to end of generated code */ + u8 opSeek; /* Seek opcode */ /* Vdbe is guaranteed to have been allocated by this stage. */ assert( v ); @@ -504,7 +554,8 @@ void sqlite3GenerateRowDelete( ** (this can happen if a trigger program has already deleted it), do ** not attempt to delete it or fire any DELETE triggers. */ iLabel = sqlite3VdbeMakeLabel(v); - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iPk); + opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound; + sqlite3VdbeAddOp4Int(v, opSeek, iCur, iLabel, iPk, nPk); /* If there are any triggers to fire, allocate a range of registers to ** use for the old.* references in the triggers. */ @@ -539,7 +590,7 @@ void sqlite3GenerateRowDelete( ** the BEFORE triggers coded above have already removed the row ** being deleted. Do not attempt to delete the row a second time, and ** do not fire AFTER triggers. */ - sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iPk); + sqlite3VdbeAddOp4Int(v, opSeek, iCur, iLabel, iPk, nPk); /* Do FK processing. This call checks that any FK constraints that ** refer to this table (i.e. constraints attached to other tables) @@ -600,28 +651,22 @@ void sqlite3GenerateRowIndexDelete( int iCur, /* Cursor number for the table */ int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ ){ - int i, iPk = 0; + int i; Index *pIdx; int r1; int iPartIdxLabel; Vdbe *v = pParse->pVdbe; Index *pPk; - pPk = sqlite3PrimaryKeyIndex(pTab); + pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue; - if( pIdx==pPk ){ iPk = iCur+i; continue; } + if( pIdx==pPk ) continue; r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 1, &iPartIdxLabel); sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); sqlite3VdbeResolveLabel(v, iPartIdxLabel); } - if( iPk ){ - r1 = sqlite3GenerateIndexKey(pParse, pPk, iCur, 0, 1, &iPartIdxLabel); - sqlite3VdbeAddOp3(v, OP_IdxDelete, iPk, r1, - pPk->uniqNotNull ? pPk->nKeyCol : pPk->nColumn); - sqlite3VdbeResolveLabel(v, iPartIdxLabel); - } } /* @@ -677,7 +722,7 @@ int sqlite3GenerateIndexKey( sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+j); }else{ sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); - sqlite3ColumnDefault(v, pTab, idx, -1); + sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[j], -1); } } if( regOut ){ diff --git a/src/insert.c b/src/insert.c index 29eb264b3a..c3d3af7235 100644 --- a/src/insert.c +++ b/src/insert.c @@ -36,8 +36,7 @@ void sqlite3OpenTable( assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName); if( HasRowid(pTab) ){ - sqlite3VdbeAddOp4(v, opcode, iCur, pTab->tnum, iDb, - SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32); + sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol); VdbeComment((v, "%s", pTab->zName)); }else if( opcode==OP_OpenRead ){ Index *pPk = sqlite3PrimaryKeyIndex(pTab); @@ -825,7 +824,7 @@ void sqlite3Insert( int nIdx; baseCur = pParse->nTab - withoutRowid; - nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite); + nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, -1, OP_OpenWrite); aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; @@ -1411,7 +1410,7 @@ void sqlite3GenerateConstraintChecks( } /* Create a key for accessing the index entry */ - regIdx = sqlite3GetTempRange(pParse, pIdx->nKeyCol+1); + regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1); for(i=0; inColumn; i++){ i16 idx = pIdx->aiColumn[i]; if( idx<0 || idx==pTab->iPKey ){ @@ -1444,9 +1443,7 @@ void sqlite3GenerateConstraintChecks( /* Check to see if the new index entry will be unique */ regR = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR); - j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0, - regR, SQLITE_INT_TO_PTR(regIdx), - P4_INT32); + j3 = sqlite3VdbeAddOp4Int(v, OP_IsUnique, baseCur+iCur+1, 0, regR, regIdx); sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1); /* Generate code that executes if the new index entry is not unique */ @@ -1582,6 +1579,7 @@ int sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ Table *pTab, /* Table to be opened */ int baseCur, /* Cursor number assigned to the table */ + int pkCur, /* Cursor number for the primary key */ int op /* OP_OpenRead or OP_OpenWrite */ ){ int i; @@ -1596,14 +1594,13 @@ int sqlite3OpenTableAndIndices( sqlite3OpenTable(pParse, baseCur, iDb, pTab, op); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + int iCur = (pkCur>=0 && pIdx->autoIndex==2) ? pkCur : i+baseCur; assert( pIdx->pSchema==pTab->pSchema ); - sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb, + sqlite3VdbeAddOp4(v, op, iCur, pIdx->tnum, iDb, (char*)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); } - if( pParse->nTabnTab = baseCur+i; - } + if( pParse->nTab<=i+baseCur ) pParse->nTab = i+baseCur; return i-1; } diff --git a/src/pragma.c b/src/pragma.c index ee85445654..d64bcf633f 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1847,7 +1847,7 @@ void sqlite3Pragma( sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); sqlite3VdbeJumpHere(v, addr); sqlite3ExprCacheClear(pParse); - sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); + sqlite3OpenTableAndIndices(pParse, pTab, 1, -1, OP_OpenRead); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ sqlite3VdbeAddOp2(v, OP_Integer, 0, 7+j); /* index entries counter */ } diff --git a/src/select.c b/src/select.c index 3382c26b5d..c54837ba1d 100644 --- a/src/select.c +++ b/src/select.c @@ -4656,8 +4656,7 @@ int sqlite3Select( } /* Open a read-only cursor, execute the OP_Count, close the cursor. */ - sqlite3VdbeAddOp4(v, OP_OpenRead, iCsr, iRoot, iDb, - SQLITE_INT_TO_PTR(1), P4_INT32); + sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1); if( pKeyInfo ){ sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 99730e4d2a..c99cdb2070 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2920,7 +2920,7 @@ int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*); void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int, int*,int,int,int,int,int*); void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int); -int sqlite3OpenTableAndIndices(Parse*, Table*, int, int); +int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, int); void sqlite3BeginWriteOperation(Parse*, int, int); void sqlite3MultiWrite(Parse*); void sqlite3MayAbort(Parse*); diff --git a/src/vdbe.c b/src/vdbe.c index 3b35aa8b58..d9f01837ee 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3681,6 +3681,7 @@ case OP_Found: { /* jump, in3 */ break; } alreadyExists = (res==0); + pC->nullRow = 1-alreadyExists; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; } @@ -3781,15 +3782,14 @@ case OP_IsUnique: { /* jump, in3 */ /* Opcode: NotExists P1 P2 P3 * * ** -** Use the content of register P3 as an integer key. If a record -** with that key does not exist in table of P1, then jump to P2. -** If the record does exist, then fall through. The cursor is left -** pointing to the record if it exists. +** P1 is the index of a cursor open on an SQL table btree (with integer +** keys). P3 is an integer rowid. If P1 does not contain a record with +** rowid P3 then jump immediately to P2. If P1 does contain a record +** with rowid P3 then leave the cursor pointing at that record and fall +** through to the next instruction. ** -** The difference between this operation and NotFound is that this -** operation assumes the key is an integer and that P1 is a table whereas -** NotFound assumes key is a blob constructed from MakeRecord and -** P1 is an index. +** The OP_NotFound opcode performs the same operation on index btrees +** (with arbitrary multi-value keys). ** ** See also: Found, NotFound, IsUnique */ diff --git a/src/where.c b/src/where.c index af654e984b..dcc034cff1 100644 --- a/src/where.c +++ b/src/where.c @@ -3565,8 +3565,8 @@ static Bitmask codeOneLoopStart( k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j); } - sqlite3VdbeAddOp4(v, OP_NotFound, iCur, addrCont, iRowidReg, - SQLITE_INT_TO_PTR(pPk->nKeyCol), P4_INT32); + sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, + iRowidReg, pPk->nKeyCol); } /* Record the instruction used to terminate the loop. Disable @@ -4603,7 +4603,7 @@ static int whereLoopAddBtree( if( b || ( m==0 && pProbe->bUnordered==0 - && pProbe->szIdxRowszTabRow + && (!HasRowid(pTab) || pProbe->szIdxRowszTabRow) && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 && sqlite3GlobalConfig.bUseCis && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)