-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
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
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
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
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
-ae61a34378d3ed2f454ba8768029d6f5fef849e4
\ No newline at end of file
+e6650e16dd11327afd25961b2feb29ec8778c2ca
\ No newline at end of file
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);
/* 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 */
break;
}
}
- sqlite3VdbeJumpHere(v, j3);
sqlite3VdbeResolveLabel(v, addrSkipRow);
sqlite3ReleaseTempReg(pParse, regR);
}
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 */
};
*/
#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
** 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 *
**
** 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;
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;
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);
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
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;
- }
-
- /* 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;
+ rc = -rc; /* Invert the result for DESC sort order. */
}
-
return rc;
}
i++;