mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-11 01:42:22 +03:00
Cleanup and simplification of constraint processing. Simplifications
to the VM for better test coverage. (CVS 4729) FossilOrigin-Name: d9ebe9d78c558af050c44ac4437ce0ef8193a4a8
This commit is contained in:
82
src/insert.c
82
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 @@ insert_cleanup:
|
||||
**
|
||||
** 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 @@ insert_cleanup:
|
||||
**
|
||||
** 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 @@ insert_cleanup:
|
||||
** 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 @@ void sqlite3GenerateConstraintChecks(
|
||||
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 @@ void sqlite3GenerateConstraintChecks(
|
||||
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 @@ void sqlite3GenerateConstraintChecks(
|
||||
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 */
|
||||
}
|
||||
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;
|
||||
}
|
||||
seenReplace = 1;
|
||||
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 @@ void sqlite3GenerateConstraintChecks(
|
||||
}
|
||||
case OE_Replace: {
|
||||
sqlite3GenerateRowDelete(pParse, pTab, baseCur, regR, 0);
|
||||
if( isUpdate ){
|
||||
sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-hasTwoRowids);
|
||||
}
|
||||
seenReplace = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user