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:
124
src/vdbe.c
124
src/vdbe.c
@@ -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
|
||||
|
Reference in New Issue
Block a user