diff --git a/manifest b/manifest index 1cbd8b072d..f2dbc032db 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\srecent\sfixes\sfrom\strunk. -D 2013-10-28T22:39:53.007 +C Improved\scomments\son\sthe\sconstraint\schecking\slogic. +D 2013-10-29T16:14:35.997 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 14ae816acbebd927bc070bf684de638f78cfccba +F src/insert.c 42e8dc617c4db4683b4b2aac4d40dabf0333bef2 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -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 086ec2a177b24ad90d5d705a99d93aa0c1545217 3a9e3ed94bf617f00c48009b1a6d348a8f23a3cf -R 8a68d5fd17d8dcd9d86fb48741f61369 +P 9f8191d1d833acaaf612fdff8cc6bd544c042986 +R 1ffaeb4130b0ebfe6aa0338f8dfd6db1 U drh -Z c438434c68bedb89ea1b9008c1cfe6f8 +Z 4dc4c03fad5693ab5ce15641b23c251b diff --git a/manifest.uuid b/manifest.uuid index d8fc2bda2f..e55b1428f5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9f8191d1d833acaaf612fdff8cc6bd544c042986 \ No newline at end of file +141a38a7a636e3e4255b59c27df4a1b3d6f26e97 \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index 5ab6b9902d..e665509f51 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1182,8 +1182,8 @@ static int sqlite3PrimaryKeyRegisters(Parse *pParse, Index *pPk, int regFirst){ ** false for INSERTs. If isUpdate is false then a non-zero pkChng ** indicates that the rowid was explicitly specified as part of the ** INSERT statement. If pkChng is false, it means that the rowid is -** computed automatically in an insert or that the rowid value is not -** modified by an update. The pkChng parameter is always false for inserts +** computed automatically in an insert and is therefore guaranteed to +** be unique. The pkChng parameter is always false for inserts ** into a WITHOUT ROWID table. ** ** The code generated by this routine should store new index entries into @@ -1275,6 +1275,7 @@ void sqlite3GenerateConstraintChecks( /* For WITHOUT ROWID tables, we'll need to know the Index and the cursor ** number for the PRIMARY KEY index */ if( !HasRowid(pTab) ){ + assert( pkChng==0 || isUpdate!=0 ); pkCur = baseCur+1; pPk = pTab->pIndex; while( ALWAYS(pPk) && pPk->autoIndex!=2 ){ @@ -1304,6 +1305,7 @@ void sqlite3GenerateConstraintChecks( switch( onError ){ case OE_Abort: sqlite3MayAbort(pParse); + /* Fall through */ case OE_Rollback: case OE_Fail: { char *zMsg; @@ -1356,7 +1358,7 @@ void sqlite3GenerateConstraintChecks( } #endif /* !defined(SQLITE_OMIT_CHECK) */ - /* If we have an INTEGER PRIMARY KEY, make sure the primary key + /* If there is an INTEGER PRIMARY KEY, make sure the primary key ** of the new record does not previously exist. Except, if this ** is an UPDATE and the primary key is not changing, that is OK. ** @@ -1446,7 +1448,7 @@ void sqlite3GenerateConstraintChecks( int idxCur = baseCur+iCur+1; int addrUniqueOk = sqlite3VdbeMakeLabel(v); - if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */ + if( aRegIdx[iCur]==0 ) continue; /* Skip indices that do not change */ if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[iCur]); @@ -1491,13 +1493,21 @@ void sqlite3GenerateConstraintChecks( regR = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4Int(v, OP_NoConflict, idxCur, addrUniqueOk, regIdx, pIdx->nKeyCol); +#if 0 + if( !isUpdate ){ + /* A pre-existing row is always a conflict on an insert */ + }else +#endif if( HasRowid(pTab) ){ - /* Conflict only if the rowid of the existing entry with the matching - ** key is different from old-rowid */ + /* Conflict only if the rowid of the existing index entry + ** is different from old-rowid */ sqlite3VdbeAddOp2(v, OP_IdxRowid, idxCur, regR); sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldPk); }else if( pIdx->autoIndex==2 ){ - /* If there is a matching entry on the PRIMARY KEY index ... */ + /* For PRIMARY KEY index on a WITHOUT ROWID table, conflict only + ** if the PRIMARY KEY has changed. If the PRIMARY KEY is unchanged, + ** then the matching entry is just the original row that is being + ** modified. */ int addrPkConflict = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol; for(i=0; inKeyCol-1; i++){ sqlite3VdbeAddOp3(v, OP_Ne, @@ -1506,6 +1516,9 @@ void sqlite3GenerateConstraintChecks( sqlite3VdbeAddOp3(v, OP_Eq, regOldPk+pPk->aiColumn[i], addrUniqueOk, regIdx+i); }else{ + /* For a UNIQUE index on a WITHOUT ROWID table, conflict only if the + ** PRIMARY KEY value of the match is different from the old PRIMARY KEY + ** value from before the update. */ int addrConflict = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol*2; assert( pIdx->nKeyCol + pPk->nKeyCol == pIdx->nColumn ); for(i=0; inKeyCol-1; i++){