1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Replace the OP_IsUnique opcode with OP_NoConflict. This code simplification

might be useful to move onto trunk even if this branch is never merged.

FossilOrigin-Name: e6650e16dd11327afd25961b2feb29ec8778c2ca
This commit is contained in:
drh
2013-10-26 13:36:51 +00:00
parent d82b50212e
commit 6f225d0d7f
6 changed files with 51 additions and 122 deletions

View File

@@ -3616,6 +3616,8 @@ case OP_Seek: { /* in2 */
** Cursor P1 is on an index btree. If the record identified by P3 and P4
** is a prefix of any entry in P1 then a jump is made to P2 and
** P1 is left pointing at the matching entry.
**
** See also: NotFound, NoConflict, NotExists. SeekGe
*/
/* Opcode: NotFound P1 P2 P3 P4 *
**
@@ -3629,11 +3631,31 @@ case OP_Seek: { /* in2 */
** falls through to the next instruction and P1 is left pointing at the
** matching entry.
**
** See also: Found, NotExists, IsUnique
** See also: Found, NotExists, NoConflict
*/
/* Opcode: NoConflict P1 P2 P3 P4 *
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
** record.
**
** Cursor P1 is on an index btree. If the record identified by P3 and P4
** contains any NULL value, jump immediately to P2. If all terms of the
** record are not-NULL then a check is done to determine if any row in the
** P1 index btree has a matching key prefix. If there are no matches, jump
** immediately to P2. If there is a match, fall through and leave the P1
** cursor pointing to the matching row.
**
** This opcode is similar to OP_NotFound with the exceptions that the
** branch is always taken if any part of the search key input is NULL.
**
** See also: NotFound, Found, NotExists
*/
case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
int alreadyExists;
int ii;
VdbeCursor *pC;
int res;
char *pFree;
@@ -3642,7 +3664,7 @@ case OP_Found: { /* jump, in3 */
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
#ifdef SQLITE_TEST
sqlite3_found_count++;
if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
#endif
alreadyExists = 0;
@@ -3673,6 +3695,17 @@ case OP_Found: { /* jump, in3 */
sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
}
if( pOp->opcode==OP_NoConflict ){
/* For the OP_NoConflict opcode, take the jump if any of the
** input fields are NULL, since any key with a NULL will not
** conflict */
for(ii=0; ii<r.nField; ii++){
if( r.aMem[ii].flags & MEM_Null ){
pc = pOp->p2 - 1;
break;
}
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
if( pOp->p4.i==0 ){
sqlite3DbFree(db, pFree);
@@ -3693,93 +3726,6 @@ case OP_Found: { /* jump, in3 */
break;
}
/* Opcode: IsUnique P1 P2 P3 P4 *
**
** Cursor P1 is open on an index b-tree - that is to say, a btree which
** no data and where the key are records generated by OP_MakeRecord with
** the list field being the integer ROWID of the entry that the index
** entry refers to.
**
** The P3 register contains an integer record number. Call this record
** number R. Register P4 is the first in a set of N contiguous registers
** that make up an unpacked index key that can be used with cursor P1.
** The value of N can be inferred from the cursor. N includes the rowid
** value appended to the end of the index record. This rowid value may
** or may not be the same as R.
**
** If any of the N registers beginning with register P4 contains a NULL
** value, jump immediately to P2.
**
** Otherwise, this instruction checks if cursor P1 contains an entry
** where the first (N-1) fields match but the rowid value at the end
** of the index entry is not R. If there is no such entry, control jumps
** to instruction P2. Otherwise, the rowid of the conflicting index
** entry is copied to register P3 and control falls through to the next
** instruction.
**
** See also: NotFound, NotExists, Found
*/
case OP_IsUnique: { /* jump, in3 */
u16 ii;
VdbeCursor *pCx;
BtCursor *pCrsr;
u16 nField;
Mem *aMx;
UnpackedRecord r; /* B-Tree index search key */
i64 R; /* Rowid stored in register P3 */
pIn3 = &aMem[pOp->p3];
aMx = &aMem[pOp->p4.i];
/* Assert that the values of parameters P1 and P4 are in range. */
assert( pOp->p4type==P4_INT32 );
assert( pOp->p4.i>0 && pOp->p4.i<=(p->nMem-p->nCursor) );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
/* Find the index cursor. */
pCx = p->apCsr[pOp->p1];
assert( pCx->deferredMoveto==0 );
pCx->seekResult = 0;
pCx->cacheStatus = CACHE_STALE;
pCrsr = pCx->pCursor;
/* If any of the values are NULL, take the jump. */
nField = pCx->pKeyInfo->nField;
for(ii=0; ii<nField; ii++){
if( aMx[ii].flags & MEM_Null ){
pc = pOp->p2 - 1;
pCrsr = 0;
break;
}
}
assert( (aMx[nField].flags & MEM_Null)==0 );
if( pCrsr!=0 ){
/* Populate the index search key. */
r.pKeyInfo = pCx->pKeyInfo;
r.nField = nField + 1;
r.flags = UNPACKED_PREFIX_SEARCH;
r.aMem = aMx;
#ifdef SQLITE_DEBUG
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
/* Extract the value of R from register P3. */
sqlite3VdbeMemIntegerify(pIn3);
R = pIn3->u.i;
/* Search the B-Tree index. If no conflicting record is found, jump
** to P2. Otherwise, copy the rowid of the conflicting record to
** register P3 and fall through to the next instruction. */
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &pCx->seekResult);
if( (r.flags & UNPACKED_PREFIX_SEARCH) || r.rowid==R ){
pc = pOp->p2 - 1;
}else{
pIn3->u.i = r.rowid;
}
}
break;
}
/* Opcode: NotExists P1 P2 P3 * *
**
** P1 is the index of a cursor open on an SQL table btree (with integer