diff --git a/manifest b/manifest index b264809eda..c8331f4e7f 100644 --- a/manifest +++ b/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 diff --git a/manifest.uuid b/manifest.uuid index e864bbe7b0..6723151d82 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ae61a34378d3ed2f454ba8768029d6f5fef849e4 \ No newline at end of file +e6650e16dd11327afd25961b2feb29ec8778c2ca \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 28fa1d357b..c6d3900ceb 100644 --- a/src/insert.c +++ b/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); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c99cdb2070..0d5a68d504 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 diff --git a/src/vdbe.c b/src/vdbe.c index d9f01837ee..0747e26fb6 100644 --- a/src/vdbe.c +++ b/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; iip2 - 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->p1nCursor ); - - /* 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; iip2 - 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; iu.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 diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 68a9fbd51e..ee57392690 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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++;