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:
parent
d82b50212e
commit
6f225d0d7f
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Minor\srefactoring\sof\svariable\snames\sand\sfixes\sto\scomments\sin\sinsert.c.
|
||||
D 2013-10-26T00:58:34.188
|
||||
C Replace\sthe\sOP_IsUnique\sopcode\swith\sOP_NoConflict.\s\sThis\scode\ssimplification\nmight\sbe\suseful\sto\smove\sonto\strunk\seven\sif\sthis\sbranch\sis\snever\smerged.
|
||||
D 2013-10-26T13:36:51.811
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -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 684154a70880e8a8b6f390227440db336ae6172c
|
||||
F src/insert.c e87728415d32d6f572f5578c2107e382d1dd8203
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
@ -223,7 +223,7 @@ 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 674cee6761771e7c1d6446671fcf7daf27b4c0f7
|
||||
F src/sqliteInt.h 2653257af49bf87af81d7c35899297043f10879a
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -279,11 +279,11 @@ F src/update.c e39378bc5ed0c42e80624229703e59b5c7a4d50a
|
||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c f7a2fb5d707db64f59ebb2d054485790350f84db
|
||||
F src/vdbe.c 115f2c06e4d943d289599a46634514bf94479db4
|
||||
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
|
||||
F src/vdbeInt.h ff57f67aee1ba26a3a47e786533dab155ab6dad6
|
||||
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
||||
F src/vdbeaux.c 6d59c132174a7e9152f0ca2db8f0f3ec97ef199b
|
||||
F src/vdbeaux.c 4ccdfd27f97fec98385f53fc8c880f1873137d95
|
||||
F src/vdbeblob.c ef973d8d9f8170015343dd8824f795da675caa87
|
||||
F src/vdbemem.c 6087553f2c61c06c8e1ab3959a60e174d6240c98
|
||||
F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017
|
||||
@ -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 e557b7d80f1ede63427a31b16757bf5d8dbfb66d
|
||||
R 8ecb8965e88397a72e81a0bfa7fd01e8
|
||||
P ae61a34378d3ed2f454ba8768029d6f5fef849e4
|
||||
R 4e2e179014c5b2ce47e50b4ad5c73b59
|
||||
U drh
|
||||
Z ed26d40c375e5bd903fb1bf3e632fe62
|
||||
Z bf09176aa6b2dce2a1f786b527e72d8e
|
||||
|
@ -1 +1 @@
|
||||
ae61a34378d3ed2f454ba8768029d6f5fef849e4
|
||||
e6650e16dd11327afd25961b2feb29ec8778c2ca
|
10
src/insert.c
10
src/insert.c
@ -1392,13 +1392,12 @@ void sqlite3GenerateConstraintChecks(
|
||||
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
|
||||
int regIdx;
|
||||
int regR;
|
||||
int addrSkipRow = 0;
|
||||
int addrSkipRow = sqlite3VdbeMakeLabel(v);
|
||||
|
||||
if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
|
||||
|
||||
if( pIdx->pPartIdxWhere ){
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[iCur]);
|
||||
addrSkipRow = sqlite3VdbeMakeLabel(v);
|
||||
pParse->ckBase = regData;
|
||||
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrSkipRow,
|
||||
SQLITE_JUMPIFNULL);
|
||||
@ -1438,8 +1437,10 @@ void sqlite3GenerateConstraintChecks(
|
||||
|
||||
/* Check to see if the new index entry will be unique */
|
||||
regR = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
|
||||
j3 = sqlite3VdbeAddOp4Int(v, OP_IsUnique, baseCur+iCur+1, 0, regR, regIdx);
|
||||
sqlite3VdbeAddOp4Int(v, OP_NoConflict, baseCur+iCur+1, addrSkipRow,
|
||||
regIdx, pIdx->nKeyCol);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, baseCur+iCur+1, regR);
|
||||
sqlite3VdbeAddOp3(v, OP_Eq, regR, addrSkipRow, regOldRowid);
|
||||
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
|
||||
|
||||
/* Generate code that executes if the new index entry is not unique */
|
||||
@ -1490,7 +1491,6 @@ void sqlite3GenerateConstraintChecks(
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, j3);
|
||||
sqlite3VdbeResolveLabel(v, addrSkipRow);
|
||||
sqlite3ReleaseTempReg(pParse, regR);
|
||||
}
|
||||
|
@ -1542,7 +1542,6 @@ struct UnpackedRecord {
|
||||
KeyInfo *pKeyInfo; /* Collation and sort-order information */
|
||||
u16 nField; /* Number of entries in apMem[] */
|
||||
u8 flags; /* Boolean settings. UNPACKED_... below */
|
||||
i64 rowid; /* Used by UNPACKED_PREFIX_SEARCH */
|
||||
Mem *aMem; /* Values */
|
||||
};
|
||||
|
||||
@ -1551,7 +1550,6 @@ struct UnpackedRecord {
|
||||
*/
|
||||
#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */
|
||||
#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */
|
||||
#define UNPACKED_PREFIX_SEARCH 0x04 /* Ignore final (rowid) field */
|
||||
|
||||
/*
|
||||
** Each SQL index is represented in memory by an
|
||||
|
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
|
||||
|
@ -3060,24 +3060,9 @@ int sqlite3VdbeRecordCompare(
|
||||
rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
|
||||
if( rc!=0 ){
|
||||
assert( mem1.zMalloc==0 ); /* See comment below */
|
||||
|
||||
/* Invert the result if we are using DESC sort order. */
|
||||
if( pKeyInfo->aSortOrder[i] ){
|
||||
rc = -rc;
|
||||
rc = -rc; /* Invert the result for DESC sort order. */
|
||||
}
|
||||
|
||||
/* If the PREFIX_SEARCH flag is set and all fields except the final
|
||||
** rowid field were equal, then clear the PREFIX_SEARCH flag and set
|
||||
** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1).
|
||||
** This is used by the OP_IsUnique opcode.
|
||||
*/
|
||||
if( (pPKey2->flags & UNPACKED_PREFIX_SEARCH) && i==(pPKey2->nField-1) ){
|
||||
assert( idx1==szHdr1 && rc );
|
||||
assert( mem1.flags & MEM_Int );
|
||||
pPKey2->flags &= ~UNPACKED_PREFIX_SEARCH;
|
||||
pPKey2->rowid = mem1.u.i;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
i++;
|
||||
|
Loading…
Reference in New Issue
Block a user