Cleanup and simplification of constraint processing. Simplifications
to the VM for better test coverage. (CVS 4729)
FossilOrigin-Name: d9ebe9d78c558af050c44ac4437ce0ef8193a4a8
diff --git a/src/insert.c b/src/insert.c
index e62e623..6136454 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.225 2008/01/17 16:22:15 drh Exp $
+** $Id: insert.c,v 1.226 2008/01/19 03:35:59 drh Exp $
*/
#include "sqliteInt.h"
@@ -943,7 +943,7 @@
**
** 1. The rowid of the row to be updated before the update. This
** value is omitted unless we are doing an UPDATE that involves a
-** change to the record number. (Or writing to a virtual table.)
+** change to the record number or writing to a virtual table.
**
** 2. The rowid of the row after the update.
**
@@ -957,7 +957,10 @@
**
** The old rowid shown as entry (1) above is omitted unless both isUpdate
** and rowidChng are 1. isUpdate is true for UPDATEs and false for
-** INSERTs and rowidChng is true if the record number is being changed.
+** INSERTs. RowidChng means that the new rowid is explicitly specified by
+** the update or insert statement. If rowidChng is false, it means that
+** the rowid is computed automatically in an insert or that the rowid value
+** is not modified by the update.
**
** The code generated by this routine store new index entries into
** registers identified by aRegIdx[]. No index entry is created for
@@ -1009,12 +1012,6 @@
** read/write cursors with cursor number baseCur+i for the i-th cursor.
** Except, if there is no possibility of a REPLACE action then
** cursors do not need to be open for indices where aRegIdx[i]==0.
-**
-** If the isUpdate flag is true, it means that the "baseCur" cursor is
-** initially pointing to an entry that is being updated. The isUpdate
-** flag causes extra code to be generated so that the "baseCur" cursor
-** is still pointing at the same entry after the routine returns.
-** Without the isUpdate flag, the "baseCur" cursor might be moved.
*/
void sqlite3GenerateConstraintChecks(
Parse *pParse, /* The parser context */
@@ -1022,7 +1019,7 @@
int baseCur, /* Index of a read/write cursor pointing at pTab */
int regRowid, /* Index of the range of input registers */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
- int rowidChng, /* True if the rowid will change */
+ int rowidChng, /* True if the rowid might collide with existing entry */
int isUpdate, /* True for UPDATE, False for INSERT */
int overrideError, /* Override onError to this if not OE_Default */
int ignoreDest /* Jump to this label on an OE_Ignore resolution */
@@ -1031,7 +1028,7 @@
Vdbe *v;
int nCol;
int onError;
- int j1, j2, j3; /* Address of jump instructions */
+ int j1, j2, j3; /* Addresses of jump instructions */
int regData; /* Register containing first data column */
int iCur;
Index *pIdx;
@@ -1116,41 +1113,41 @@
onError = OE_Abort;
}
- if( isUpdate ){
- j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1);
- }
- j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
- switch( onError ){
- default: {
- onError = OE_Abort;
- /* Fall thru into the next case */
+ if( onError==OE_Replace && pTab->pIndex==0 ){
+ seenReplace = 1;
+ }else{
+ if( isUpdate ){
+ j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1);
}
- case OE_Rollback:
- case OE_Abort:
- case OE_Fail: {
- sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
- "PRIMARY KEY must be unique", P4_STATIC);
- break;
- }
- case OE_Replace: {
- sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
- if( isUpdate ){
- sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-hasTwoRowids);
+ j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
+ switch( onError ){
+ default: {
+ onError = OE_Abort;
+ /* Fall thru into the next case */
}
- seenReplace = 1;
- break;
+ case OE_Rollback:
+ case OE_Abort:
+ case OE_Fail: {
+ sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
+ "PRIMARY KEY must be unique", P4_STATIC);
+ break;
+ }
+ case OE_Replace: {
+ sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
+ seenReplace = 1;
+ break;
+ }
+ case OE_Ignore: {
+ assert( seenReplace==0 );
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
+ break;
+ }
}
- case OE_Ignore: {
- assert( seenReplace==0 );
- sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
- break;
+ sqlite3VdbeJumpHere(v, j3);
+ if( isUpdate ){
+ sqlite3VdbeJumpHere(v, j2);
}
}
- sqlite3VdbeJumpHere(v, j3);
- if( isUpdate ){
- sqlite3VdbeJumpHere(v, j2);
- sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-1);
- }
}
/* Test all UNIQUE constraints by creating entries for each UNIQUE
@@ -1239,9 +1236,6 @@
}
case OE_Replace: {
sqlite3GenerateRowDelete(pParse, pTab, baseCur, regR, 0);
- if( isUpdate ){
- sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-hasTwoRowids);
- }
seenReplace = 1;
break;
}