diff options
author | drh <drh@noemail.net> | 2013-11-04 21:44:54 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2013-11-04 21:44:54 +0000 |
commit | da475b8dbc6c2a74e3e489d07493a50fce0f54bc (patch) | |
tree | cd15923f550f22c79270d82bafa7cb19859e58dc /src/insert.c | |
parent | c3e356fe100da85a09c21b426ed64d001cf6a844 (diff) | |
download | sqlite-da475b8dbc6c2a74e3e489d07493a50fce0f54bc.tar.gz sqlite-da475b8dbc6c2a74e3e489d07493a50fce0f54bc.zip |
Bug fixes in the INSERT constraint checker. Refactor the Rowid handling logic
for ANALYZE with STAT3/4.
FossilOrigin-Name: 1ea43c0f236792a3bc13e1cb330f5ff3402c2851
Diffstat (limited to 'src/insert.c')
-rw-r--r-- | src/insert.c | 60 |
1 files changed, 34 insertions, 26 deletions
diff --git a/src/insert.c b/src/insert.c index 3cc88f96f..a6cab3e89 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1463,7 +1463,10 @@ void sqlite3GenerateConstraintChecks( ** of a WITHOUT ROWID table and there has been no change the ** primary key, then no collision is possible. The collision detection ** logic below can all be skipped. */ - if( isUpdate && pPk && pkChng==0 ) continue; + if( isUpdate && pPk && pkChng==0 ){ + sqlite3VdbeResolveLabel(v, addrUniqueOk); + continue; + } /* Find out what action to take in case there is a uniqueness conflict */ onError = pIdx->onError; @@ -1498,38 +1501,40 @@ void sqlite3GenerateConstraintChecks( }else{ int x; /* Extract the PRIMARY KEY from the end of the index entry and - ** store it in register regR..regR+nPk-1 */ - for(i=0; i<pPk->nKeyCol; i++){ - x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); - sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); - VdbeComment((v, "%s.%s", pTab->zName, - pTab->aCol[pPk->aiColumn[i]].zName)); + ** store it in registers regR..regR+nPk-1 */ + if( isUpdate || onError==OE_Replace ){ + for(i=0; i<pPk->nKeyCol; i++){ + x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); + sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); + VdbeComment((v, "%s.%s", pTab->zName, + pTab->aCol[pPk->aiColumn[i]].zName)); + } } - if( pIdx->autoIndex==2 ){ - /* For a PRIMARY KEY index on a WITHOUT ROWID table, always conflict - ** on an INSERT. On an UPDATE, only conflict if the PRIMARY KEY - ** has changed. */ - if( isUpdate ){ + if( isUpdate ){ + if( pIdx->autoIndex==2 ){ + /* For a PRIMARY KEY index on a WITHOUT ROWID table, always conflict + ** on an INSERT. On an UPDATE, only conflict if the PRIMARY KEY + ** has changed. */ int addrPkConflict = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol; for(i=0; i<pPk->nKeyCol-1; i++){ x = pPk->aiColumn[i]; sqlite3VdbeAddOp3(v, OP_Ne, regOldData+1+x, - addrPkConflict, regIdx+x); + addrPkConflict, regIdx+i); } x = pPk->aiColumn[i]; sqlite3VdbeAddOp3(v, OP_Eq, regOldData+1+x, 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; + for(i=0; i<pPk->nKeyCol-1; i++){ + sqlite3VdbeAddOp3(v, OP_Ne, regOldData+pPk->aiColumn[i]+1, + addrConflict, regR+i); + } + sqlite3VdbeAddOp3(v, OP_Eq, regOldData+pPk->aiColumn[i]+1, + addrUniqueOk, regR+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; - for(i=0; i<pPk->nKeyCol-1; i++){ - sqlite3VdbeAddOp3(v, OP_Ne, - regOldData+pPk->aiColumn[i]+1, addrConflict, regR+i); - } - sqlite3VdbeAddOp3(v, OP_Eq, - regOldData+pPk->aiColumn[i]+1, addrUniqueOk, regR+i); } } sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn); @@ -1827,8 +1832,8 @@ static int xferOptimization( int iDbSrc; /* The database of pSrc */ int iSrc, iDest; /* Cursors from source and destination */ int addr1, addr2; /* Loop addresses */ - int emptyDestTest; /* Address of test for empty pDest */ - int emptySrcTest; /* Address of test for empty pSrc */ + int emptyDestTest = 0; /* Address of test for empty pDest */ + int emptySrcTest = 0; /* Address of test for empty pSrc */ Vdbe *v; /* The VDBE we are building */ KeyInfo *pKey; /* Key information for an index */ int regAutoinc; /* Memory register used by AUTOINC */ @@ -2026,6 +2031,9 @@ static int xferOptimization( sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); + }else{ + sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName); + sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ |