1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-01-06 08:01:16 +03:00

Fix a bug in the code for REPLACE conflict handling on IPK columns when there are no indexes on the table. Triggers and foreign key processing were being bypassed.

FossilOrigin-Name: beb2094f94849c66d98bab5999ff474cd91eea11
This commit is contained in:
dan
2009-09-24 16:52:28 +00:00
parent 8c430041f5
commit e1e2ae2d3f
3 changed files with 54 additions and 56 deletions

View File

@@ -1240,58 +1240,56 @@ void sqlite3GenerateConstraintChecks(
onError = OE_Abort;
}
if( onError!=OE_Replace || pTab->pIndex ){
if( isUpdate ){
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
if( isUpdate ){
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
}
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
switch( onError ){
default: {
onError = OE_Abort;
/* Fall thru into the next case */
}
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
switch( onError ){
default: {
onError = OE_Abort;
/* Fall thru into the next case */
}
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
sqlite3HaltConstraint(
pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
break;
}
case OE_Replace: {
/* If there are DELETE triggers on this table and the
** recursive-triggers flag is set, call GenerateRowDelete() to
** remove the conflicting row from the the table. This will fire
** the triggers and remove both the table and index b-tree entries.
**
** Otherwise, if there are no triggers or the recursive-triggers
** flag is not set, call GenerateRowIndexDelete(). This removes
** the index b-tree entries only. The table b-tree entry will be
** replaced by the new entry when it is inserted. */
Trigger *pTrigger = 0;
if( pParse->db->flags&SQLITE_RecTriggers ){
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
sqlite3MultiWrite(pParse);
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0) ){
sqlite3GenerateRowDelete(
pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
);
}else{
sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
}
seenReplace = 1;
break;
}
case OE_Ignore: {
assert( seenReplace==0 );
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
break;
}
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
sqlite3HaltConstraint(
pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
break;
}
sqlite3VdbeJumpHere(v, j3);
if( isUpdate ){
sqlite3VdbeJumpHere(v, j2);
case OE_Replace: {
/* If there are DELETE triggers on this table and the
** recursive-triggers flag is set, call GenerateRowDelete() to
** remove the conflicting row from the the table. This will fire
** the triggers and remove both the table and index b-tree entries.
**
** Otherwise, if there are no triggers or the recursive-triggers
** flag is not set, call GenerateRowIndexDelete(). This removes
** the index b-tree entries only. The table b-tree entry will be
** replaced by the new entry when it is inserted. */
Trigger *pTrigger = 0;
if( pParse->db->flags&SQLITE_RecTriggers ){
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
sqlite3MultiWrite(pParse);
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0) ){
sqlite3GenerateRowDelete(
pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
);
}else{
sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
}
seenReplace = 1;
break;
}
case OE_Ignore: {
assert( seenReplace==0 );
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
break;
}
}
sqlite3VdbeJumpHere(v, j3);
if( isUpdate ){
sqlite3VdbeJumpHere(v, j2);
}
}