1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-24 22:22:08 +03:00

Improved comments and variable names in infrastructure routines of UPDATE,

DELETE, and INSERT.

FossilOrigin-Name: ad90e762e51384ac7c311f08a641419f03f6d3f0
This commit is contained in:
drh
2013-10-31 15:37:49 +00:00
parent 77f64bb7b9
commit 6934fc7b6f
6 changed files with 144 additions and 134 deletions

View File

@ -1,5 +1,5 @@
C Moving\sUPDATE\stowards\sthe\siDataCur/iIdxCur\srepresentation.\s\sStill\snot\sworking\nfor\sWITHOUT\sROWID,\sthough.
D 2013-10-31T12:13:37.732
C Improved\scomments\sand\svariable\snames\sin\sinfrastructure\sroutines\sof\sUPDATE,\nDELETE,\sand\sINSERT.
D 2013-10-31T15:37:49.070
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -173,7 +173,7 @@ F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c d50cc704030139e19f2e9d5ac7a49db04dfe08a9
F src/delete.c 0e10849258efbdab48b8679de19edd661859dc7d
F src/expr.c 3180b6332072b263f845592e72e92971af562ab0
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 628f81177299660a86e40359b3689b81f517e125
@ -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 e8f0691953194cf1df85b463fed8b75b0dedf7d9
F src/insert.c 64eb6bf8eda1bbe003cc38394d721b4810f65182
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
@ -212,7 +212,7 @@ F src/parse.y 073a8294e1826f1b1656e84806b77e4199f4bb57
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
F src/pragma.c 74dec25a3f0d3e5da796345a0ca817cb445e9d2a
F src/pragma.c ff1a98998d2038bc9c770326986b7c4728de4973
F src/prepare.c f47ba2bba7ac5650881ab6c41f6d33a6de1a8d52
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
@ -1076,7 +1076,7 @@ F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
F test/win32longpath.test e2aafc07e6990fe86c69be22a3d1a0e210cd329b
F test/without_rowid1.test fb3ceaa20bda4e0338f594696a49014c3cbeb30c
F test/without_rowid1.test e4f023e49a57c90f6d25afd4b3e8b0305ad06e44
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F test/zerodamage.test 209d7ed441f44cc5299e4ebffbef06fd5aabfefd
F tool/build-all-msvc.bat 38623a30fd58288fda5cc7f7df2682aaab75c9d5 x
@ -1128,7 +1128,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 1adfca6019847d37dee4a297669f29d5ca184066
R 925135441c339dd20ca1becb38d6fbf2
P deacbd21b50cc8c63a1572d14a4bbc7af4052d37
R 868cea4e5c536af4b28fd795ccabbf1e
U drh
Z 72a84fe0a8232f3d99ba9db66435b958
Z 77c0455bfaa16e77ab3ac24edbdbd46c

View File

@ -1 +1 @@
deacbd21b50cc8c63a1572d14a4bbc7af4052d37
ad90e762e51384ac7c311f08a641419f03f6d3f0

View File

@ -523,24 +523,21 @@ delete_from_cleanup:
/*
** This routine generates VDBE code that causes a single row of a
** single table to be deleted.
** single table to be deleted. Both the original table entry and
** all indices are removed.
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
** Preconditions:
**
** 1. iDataCur is an open cursor on the btree that is the primary data
** repository for the table. This will be either the table itself,
** 1. iDataCur is an open cursor on the btree that is the canonical data
** store for the table. (This will be either the table itself,
** in the case of a rowid table, or the PRIMARY KEY index in the case
** of a WITHOUT ROWID table.
** of a WITHOUT ROWID table.)
**
** 2. Read/write cursors for all indices of pTab must be open as
** cursor number iIdxCur+i for the i-th index.
**
** 3. The primary key for the row to be deleted must be stored in a
** sequence of nPk memory cells starting at iPk.
**
** This routine generates code to remove both the table record and all
** index entries that point to that record.
*/
void sqlite3GenerateRowDelete(
Parse *pParse, /* Parsing context */
@ -560,7 +557,7 @@ void sqlite3GenerateRowDelete(
/* Vdbe is guaranteed to have been allocated by this stage. */
assert( v );
VdbeModuleComment((v, "BEGIN: GenerateRowDelete(%d,%d,%d,%d)",
VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)",
iDataCur, iIdxCur, iPk, (int)nPk));
/* Seek cursor iCur to the row to delete. If this row no longer exists
@ -636,26 +633,26 @@ void sqlite3GenerateRowDelete(
** trigger programs were invoked. Or if a trigger program throws a
** RAISE(IGNORE) exception. */
sqlite3VdbeResolveLabel(v, iLabel);
VdbeModuleComment((v, "END: GenerateRowDelete()"));
VdbeModuleComment((v, "END: GenRowDel()"));
}
/*
** This routine generates VDBE code that causes the deletion of all
** index entries associated with a single row of a single table.
** index entries associated with a single row of a single table, pTab
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
** Preconditions:
**
** 1. A read/write cursor "iDataCur" pointing to canonical storage
** tree for the table pTab, which will be either the table itself
** 1. A read/write cursor "iDataCur" must be open on the canonical storage
** btree for the table pTab. (This will be either the table itself
** for rowid tables or to the primary key index for WITHOUT ROWID
** tables.
** tables.)
**
** 2. Read/write cursors for all indices of pTab must be open as
** cursor number iIdxCur+i for the i-th index.
** cursor number iIdxCur+i for the i-th index. (The pTab->pIndex
** index is the 0-th index.)
**
** 3. The "iDataCur" cursor must be pointing to the row that is to be
** deleted.
** 3. The "iDataCur" cursor must be already be positioned on the row
** that is to be deleted.
*/
void sqlite3GenerateRowIndexDelete(
Parse *pParse, /* Parsing and code generating context */
@ -664,15 +661,17 @@ void sqlite3GenerateRowIndexDelete(
int iIdxCur, /* First index cursor */
int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
){
int i;
Index *pIdx;
int r1;
int iPartIdxLabel;
Vdbe *v = pParse->pVdbe;
Index *pPk;
int i; /* Index loop counter */
int r1; /* Register holding an index key */
int iPartIdxLabel; /* Jump destination for skipping partial index entries */
Index *pIdx; /* Current index */
Vdbe *v; /* The prepared statement under construction */
Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */
v = pParse->pVdbe;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
assert( iIdxCur+i!=iDataCur || pPk==pIdx );
if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
if( pIdx==pPk ) continue;
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, &iPartIdxLabel);

View File

@ -1123,36 +1123,47 @@ insert_cleanup:
#endif
/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE.
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
**
** The input is a range of consecutive registers as follows:
** The regNewData parameter is the first register in a range that contains
** the data to be inserted or the data after the update. There will be
** pTab->nCol+1 registers in this range. The first register (the one
** that regNewData points to) will contain the new rowid, or NULL in the
** case of a WITHOUT ROWID table. The second register in the range will
** contain the content of the first table column. The third register will
** contain the content of the second table column. And so forth.
**
** 1. The rowid of the row after the update, or NULL
** for WITHOUT ROWID tables.
** For an UPDATE (isUpdate!=0), if pkChng is non-zero then it contains
** the address of a range of registers containing the rowid and table
** data from before the change. In other words, pkChng is like
** regNewData except that it describes the row before the update rather
** than afterwards. If pkChng is zero, that means that the rowid does
** not change (for a normal rowid table) or the PRIMARY KEY does not
** change (for a WITHOUT ROWID table) in which case the old data is
** not needed.
**
** 2. The data in the first column of the entry after the update.
** For an INSERT (isUpdate==0), pkChng is just a boolean that indicates
** whether or not the rowid was explicitly specified as part of the
** INSERT statement. If pkChng is zero, it means that the either rowid
** is computed automatically or that the table is a WITHOUT ROWID table
** and has no rowid. On an INSERT, pkChng will only be true if the
** INSERT statement provides an integer value for either the rowid
** column or its INTEGER PRIMARY KEY alias.
**
** i. Data from middle columns...
**
** N. The data in the last column of the entry after the update.
**
** The regRowid parameter is the index of the register containing (1).
**
** If isUpdate is true and pkChng is non-zero, then pkChng contains
** the address of a range of registers containing the rowid or PRIMARY KEY
** value before the update takes place. isUpdate is true for UPDATEs and
** 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 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
** The code generated by this routine will store new index entries into
** registers identified by aRegIdx[]. No index entry is created for
** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is
** the same as the order of indices on the linked list of indices
** attached to the table.
** at pTab->pIndex.
**
** The caller must have already opened writeable cursors on the main
** table and all applicable indices (that is to say, all indices for which
** aRegIdx[] is not zero). iDataCur is the cursor for the main table when
** inserting or updating a rowid table, or the cursor for the PRIMARY KEY
** index when operating on a WITHOUT ROWID table. iIdxCur is the cursor
** for the first index in the pTab->pIndex list. Cursors for other indices
** are at iIdxCur+N for the N-th element of the pTab->pIndex list.
**
** This routine also generates code to check constraints. NOT NULL,
** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
@ -1162,22 +1173,23 @@ insert_cleanup:
** Constraint type Action What Happens
** --------------- ---------- ----------------------------------------
** any ROLLBACK The current transaction is rolled back and
** sqlite3_exec() returns immediately with a
** sqlite3_step() returns immediately with a
** return code of SQLITE_CONSTRAINT.
**
** any ABORT Back out changes from the current command
** only (do not do a complete rollback) then
** cause sqlite3_exec() to return immediately
** cause sqlite3_step() to return immediately
** with SQLITE_CONSTRAINT.
**
** any FAIL Sqlite3_exec() returns immediately with a
** any FAIL Sqlite3_step() returns immediately with a
** return code of SQLITE_CONSTRAINT. The
** transaction is not rolled back and any
** prior changes are retained.
** changes to prior rows are retained.
**
** any IGNORE The record number and data is popped from
** the stack and there is an immediate jump
** to label ignoreDest.
** any IGNORE The attempt in insert or update the current
** row is skipped, without throwing an error.
** Processing continues with the next row.
** (There is an immediate jump to ignoreDest.)
**
** NOT NULL REPLACE The NULL value is replace by the default
** value for that column. If the default value
@ -1192,50 +1204,44 @@ insert_cleanup:
** Or if overrideError==OE_Default, then the pParse->onError parameter
** is used. Or if pParse->onError==OE_Default then the onError value
** for the constraint is used.
**
** The calling routine must open a read/write cursor for pTab with
** cursor number "baseCur". All indices of pTab must also have open
** 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.
*/
void sqlite3GenerateConstraintChecks(
Parse *pParse, /* The parser context */
Table *pTab, /* the table into which we are inserting */
int iDataCur, /* Cursor of the canonical data tree */
int iIdxCur, /* First index cursor */
int regRowid, /* First register in a range holding values to insert */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
int pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */
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 */
int *pbMayReplace /* OUT: Set to true if constraint may cause a replace */
Parse *pParse, /* The parser context */
Table *pTab, /* The table being inserted or updated */
int iDataCur, /* Canonical data cursor (main table or PK index) */
int iIdxCur, /* First index cursor */
int regNewData, /* First register in a range holding values to insert */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
int pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */
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 */
int *pbMayReplace /* OUT: Set to true if constraint may cause a replace */
){
int i; /* loop counter */
Vdbe *v; /* VDBE under constrution */
int nCol; /* Number of columns */
int onError; /* Conflict resolution strategy */
int j1; /* Addresss of jump instruction */
int ix; /* Index loop counter */
int regData; /* Register containing first data column */
int i; /* loop counter */
Vdbe *v; /* VDBE under constrution */
int nCol; /* Number of columns */
int onError; /* Conflict resolution strategy */
int j1; /* Addresss of jump instruction */
int ix; /* Index loop counter */
Index *pIdx; /* Pointer to one of the indices */
Index *pPk = 0; /* The PRIMARY KEY index */
sqlite3 *db; /* Database connection */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int regOldPk; /* Previous rowid or PRIMARY KEY value */
int regOldData; /* Previous rowid and table data */
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
regOldPk = (pkChng && isUpdate) ? pkChng : regRowid;
regOldData = (pkChng && isUpdate) ? pkChng : regNewData;
db = pParse->db;
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
nCol = pTab->nCol;
regData = regRowid + 1;
/* For WITHOUT ROWID tables, we'll need to know the Index and the cursor
** number for the PRIMARY KEY index */
/* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
** normal rowid tables. nPkField is the number of key fields in the
** pPk index or 1 for a rowid table. In other words, nPkField is the
** number of fields in the true primary key of the table. */
if( HasRowid(pTab) ){
pPk = 0;
nPkField = 1;
@ -1246,7 +1252,7 @@ void sqlite3GenerateConstraintChecks(
/* Record that this module has started */
VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)",
iDataCur, iIdxCur, regRowid, pkChng, regOldPk));
iDataCur, iIdxCur, regNewData, regOldData, pkChng));
/* Test all NOT NULL constraints.
*/
@ -1274,20 +1280,20 @@ void sqlite3GenerateConstraintChecks(
case OE_Fail: {
char *zMsg;
sqlite3VdbeAddOp3(v, OP_HaltIfNull,
SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
SQLITE_CONSTRAINT_NOTNULL, onError, regNewData+1+i);
zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
pTab->zName, pTab->aCol[i].zName);
sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
break;
}
case OE_Ignore: {
sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest);
sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
break;
}
default: {
assert( onError==OE_Replace );
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i);
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i);
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
sqlite3VdbeJumpHere(v, j1);
break;
}
@ -1299,7 +1305,7 @@ void sqlite3GenerateConstraintChecks(
#ifndef SQLITE_OMIT_CHECK
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = pTab->pCheck;
pParse->ckBase = regData;
pParse->ckBase = regNewData+1;
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
for(i=0; i<pCheck->nExpr; i++){
int allOk = sqlite3VdbeMakeLabel(v);
@ -1324,7 +1330,8 @@ void sqlite3GenerateConstraintChecks(
/* 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.
** is an UPDATE and the primary key is not changing, then obviously
** it is OK for the previous rowid to exist in that case.
**
** This block only runs for tables that have a rowid.
*/
@ -1339,9 +1346,9 @@ void sqlite3GenerateConstraintChecks(
}
if( isUpdate ){
sqlite3VdbeAddOp3(v, OP_Eq, regRowid, addrRowidOk, pkChng);
sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
}
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regRowid);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
switch( onError ){
default: {
onError = OE_Abort;
@ -1384,7 +1391,7 @@ void sqlite3GenerateConstraintChecks(
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regRowid, 1, 0, OE_Replace);
regNewData, 1, 0, OE_Replace);
}else if( pTab->pIndex ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0);
@ -1406,37 +1413,41 @@ void sqlite3GenerateConstraintChecks(
** Compute the revised record entries for indices as we go.
*/
for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
int regIdx;
int regR;
int iThisCur = iIdxCur+ix;
int addrUniqueOk = sqlite3VdbeMakeLabel(v);
int regIdx; /* Range of registers hold conent for pIdx */
int regR; /* Range of registers holding conflicting PK */
int iThisCur; /* Cursor for this UNIQUE index */
int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */
if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
iThisCur = iIdxCur+ix;
addrUniqueOk = sqlite3VdbeMakeLabel(v);
if( pIdx->pPartIdxWhere ){
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
pParse->ckBase = regData;
pParse->ckBase = regNewData+1;
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
SQLITE_JUMPIFNULL);
pParse->ckBase = 0;
}
/* Create a key for accessing the index entry */
/* Create a record for this index entry as it should appear after
** the insert or update. */
regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
for(i=0; i<pIdx->nColumn; i++){
i16 iField = pIdx->aiColumn[i];
int iField = pIdx->aiColumn[i];
if( iField<0 || iField==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
iField = regNewData;
}else{
sqlite3VdbeAddOp2(v, OP_SCopy, regData+iField, regIdx+i);
iField += regNewData + 1;
}
sqlite3VdbeAddOp2(v, OP_SCopy, iField, regIdx+i);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
VdbeComment((v, "for %s", pIdx->zName));
sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn);
/* Find out what action to take in case there is an indexing conflict */
/* Find out what action to take in case there is a uniqueness conflict */
onError = pIdx->onError;
if( onError==OE_None ){
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
@ -1458,10 +1469,10 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol);
if( HasRowid(pTab) ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
/* Conflict only if the rowid of the existing index entry
** is different from old-rowid */
sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldPk);
sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
}else{
/* Extract the PRIMARY KEY from the end of the index entry and
** store it in register regR..regR+nPk-1 */
@ -1478,10 +1489,10 @@ void sqlite3GenerateConstraintChecks(
if( isUpdate ){
int addrPkConflict = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
for(i=0; i<pPk->nKeyCol-1; i++){
sqlite3VdbeAddOp3(v, OP_Ne, regOldPk+pPk->aiColumn[i]+1,
sqlite3VdbeAddOp3(v, OP_Ne, regOldData+pPk->aiColumn[i]+1,
addrPkConflict, regIdx+i);
}
sqlite3VdbeAddOp3(v, OP_Eq, regOldPk+pPk->aiColumn[i]+1,
sqlite3VdbeAddOp3(v, OP_Eq, regOldData+pPk->aiColumn[i]+1,
addrUniqueOk, regIdx+i);
}
}else{
@ -1492,10 +1503,10 @@ void sqlite3GenerateConstraintChecks(
assert( pIdx->nKeyCol + pPk->nKeyCol == pIdx->nColumn );
for(i=0; i<pPk->nKeyCol-1; i++){
sqlite3VdbeAddOp3(v, OP_Ne,
regOldPk+pPk->aiColumn[i], addrConflict, regR+i);
regOldData+pPk->aiColumn[i]+1, addrConflict, regR+i);
}
sqlite3VdbeAddOp3(v, OP_Eq,
regOldPk+pPk->aiColumn[i], addrUniqueOk, regR+i);
regOldData+pPk->aiColumn[i]+1, addrUniqueOk, regR+i);
}
}
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
@ -1560,7 +1571,7 @@ void sqlite3GenerateConstraintChecks(
/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
** A consecutive range of registers starting at regRowid contains the
** A consecutive range of registers starting at regNewData contains the
** rowid and the content to be inserted.
**
** The arguments to this routine should be the same as the first six
@ -1571,18 +1582,18 @@ void sqlite3CompleteInsertion(
Table *pTab, /* the table into which we are inserting */
int iDataCur, /* Cursor of the canonical data source */
int iIdxCur, /* First index cursor */
int regRowid, /* Range of content */
int regNewData, /* Range of content */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
int isUpdate, /* True for UPDATE, False for INSERT */
int appendBias, /* True if this is likely to be an append */
int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
int i;
Vdbe *v;
Index *pIdx;
u8 pik_flags;
int regData;
int regRec;
Vdbe *v; /* Prepared statements under construction */
Index *pIdx; /* An index being inserted or updated */
u8 pik_flags; /* flag values passed to the btree insert */
int regData; /* Content registers (after the rowid) */
int regRec; /* Register holding assemblied record for the table */
int i; /* Loop counter */
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
@ -1598,7 +1609,7 @@ void sqlite3CompleteInsertion(
}
}
if( !HasRowid(pTab) ) return;
regData = regRowid + 1;
regData = regNewData + 1;
regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
sqlite3TableAffinityStr(v, pTab);
@ -1615,7 +1626,7 @@ void sqlite3CompleteInsertion(
if( useSeekResult ){
pik_flags |= OPFLAG_USESEEKRESULT;
}
sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData);
if( !pParse->nested ){
sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
}

View File

@ -1917,7 +1917,7 @@ void sqlite3Pragma(
sqlite3VdbeJumpHere(v, jmp2);
sqlite3VdbeResolveLabel(v, jmp3);
}
sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop);
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop);
sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0,

View File

@ -59,6 +59,6 @@ do_test without_rowid1-1.21 {
do_execsql_test without_rowid1-1.22 {
REPLACE INTO t1 VALUES('dynamic','phone','flipper','harvard');
SELECT *, '|' FROM t1 ORDER BY c, a;
} {}
} {arctic sleep ammonia helena | journal sherman ammonia helena | dynamic phone flipper harvard | journal sherman gamma patriot |}
finish_test