mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-22 20:22:44 +03:00
Progress toward getting UPDATE to work in WITHOUT ROWID tables.
FossilOrigin-Name: e557b7d80f1ede63427a31b16757bf5d8dbfb66d
This commit is contained in:
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Basic\sDELETE\soperations\snow\sworking\son\sWITHOUT\sROWID\stables.
|
C Progress\stoward\sgetting\sUPDATE\sto\swork\sin\sWITHOUT\sROWID\stables.
|
||||||
D 2013-10-25T14:46:15.958
|
D 2013-10-25T19:17:17.511
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -182,7 +182,7 @@ F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
|
|||||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||||
F src/insert.c 71b3d1f551ab8e0ba59fdbaff3feef8d931a424e
|
F src/insert.c 976fc5c9b3ab32995b22f87ba3be52d11c9e50b9
|
||||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||||
@@ -275,7 +275,7 @@ F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
|
|||||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||||
F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2
|
F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2
|
||||||
F src/trigger.c ba0a883cd536b7dfdd4df3733001f5372a4299da
|
F src/trigger.c ba0a883cd536b7dfdd4df3733001f5372a4299da
|
||||||
F src/update.c 2bb5a267796e6d0177ef5689487c3688de5c309e
|
F src/update.c e39378bc5ed0c42e80624229703e59b5c7a4d50a
|
||||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||||
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
||||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||||
@@ -1127,7 +1127,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P 85daf5174679630474b3bccf3d662d5d56bf00d5
|
P 9eafafa31c4a2bbcf48418743e0fcb17c374e9a6
|
||||||
R 98e4cedace27c103667612897f7b7404
|
R bcff8223a4c38fdc4478f7b14868c2a5
|
||||||
U drh
|
U drh
|
||||||
Z b296ee4a843fc7eab50d30ebcbf09f32
|
Z 45e2a3e25d194ae58eddf07aeb33a8d9
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
9eafafa31c4a2bbcf48418743e0fcb17c374e9a6
|
e557b7d80f1ede63427a31b16757bf5d8dbfb66d
|
||||||
20
src/insert.c
20
src/insert.c
@@ -1145,16 +1145,16 @@ insert_cleanup:
|
|||||||
**
|
**
|
||||||
** The regRowid parameter is the index of the register containing (1).
|
** The regRowid parameter is the index of the register containing (1).
|
||||||
**
|
**
|
||||||
** If isUpdate is true and rowidChng is non-zero, then rowidChng contains
|
** If isUpdate is true and pkChng is non-zero, then pkChng contains
|
||||||
** the address of a register containing the rowid before the update takes
|
** the address of a register containing the rowid before the update takes
|
||||||
** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate
|
** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate
|
||||||
** is false, indicating an INSERT statement, then a non-zero rowidChng
|
** is false, indicating an INSERT statement, then a non-zero pkChng
|
||||||
** indicates that the rowid was explicitly specified as part of the
|
** indicates that the rowid was explicitly specified as part of the
|
||||||
** INSERT statement. If rowidChng is false, it means that the rowid is
|
** INSERT statement. If pkChng is false, it means that the rowid is
|
||||||
** computed automatically in an insert or that the rowid value is not
|
** computed automatically in an insert or that the rowid value is not
|
||||||
** modified by an update.
|
** modified by an update.
|
||||||
**
|
**
|
||||||
** The code generated by this routine store new index entries into
|
** The code generated by this routine should store new index entries into
|
||||||
** registers identified by aRegIdx[]. No index entry is created for
|
** registers identified by aRegIdx[]. No index entry is created for
|
||||||
** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is
|
** 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
|
** the same as the order of indices on the linked list of indices
|
||||||
@@ -1208,10 +1208,10 @@ insert_cleanup:
|
|||||||
void sqlite3GenerateConstraintChecks(
|
void sqlite3GenerateConstraintChecks(
|
||||||
Parse *pParse, /* The parser context */
|
Parse *pParse, /* The parser context */
|
||||||
Table *pTab, /* the table into which we are inserting */
|
Table *pTab, /* the table into which we are inserting */
|
||||||
int baseCur, /* Index of a read/write cursor pointing at pTab */
|
int baseCur, /* A read/write cursor pointing at pTab */
|
||||||
int regRowid, /* Index of the range of input registers */
|
int regRowid, /* First register in a range holding values to insert */
|
||||||
int *aRegIdx, /* Register used by each index. 0 for unused indices */
|
int *aRegIdx, /* Register used by each index. 0 for unused indices */
|
||||||
int rowidChng, /* True if the rowid might collide with existing entry */
|
int pkChng, /* Non-zero if the PRIMARY KEY might collide */
|
||||||
int isUpdate, /* True for UPDATE, False for INSERT */
|
int isUpdate, /* True for UPDATE, False for INSERT */
|
||||||
int overrideError, /* Override onError to this if not OE_Default */
|
int overrideError, /* Override onError to this if not OE_Default */
|
||||||
int ignoreDest, /* Jump to this label on an OE_Ignore resolution */
|
int ignoreDest, /* Jump to this label on an OE_Ignore resolution */
|
||||||
@@ -1228,7 +1228,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
Index *pIdx; /* Pointer to one of the indices */
|
Index *pIdx; /* Pointer to one of the indices */
|
||||||
sqlite3 *db; /* Database connection */
|
sqlite3 *db; /* Database connection */
|
||||||
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
|
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
|
||||||
int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid;
|
int regOldRowid = (pkChng && isUpdate) ? pkChng : regRowid;
|
||||||
|
|
||||||
db = pParse->db;
|
db = pParse->db;
|
||||||
v = sqlite3GetVdbe(pParse);
|
v = sqlite3GetVdbe(pParse);
|
||||||
@@ -1314,7 +1314,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
** of the new record does not previously exist. Except, if this
|
** 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, that is OK.
|
||||||
*/
|
*/
|
||||||
if( rowidChng ){
|
if( pkChng ){
|
||||||
onError = pTab->keyConf;
|
onError = pTab->keyConf;
|
||||||
if( overrideError!=OE_Default ){
|
if( overrideError!=OE_Default ){
|
||||||
onError = overrideError;
|
onError = overrideError;
|
||||||
@@ -1323,7 +1323,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
|
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, pkChng);
|
||||||
}
|
}
|
||||||
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
|
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
|
||||||
switch( onError ){
|
switch( onError ){
|
||||||
|
|||||||
102
src/update.c
102
src/update.c
@@ -99,6 +99,7 @@ void sqlite3Update(
|
|||||||
WhereInfo *pWInfo; /* Information about the WHERE clause */
|
WhereInfo *pWInfo; /* Information about the WHERE clause */
|
||||||
Vdbe *v; /* The virtual database engine */
|
Vdbe *v; /* The virtual database engine */
|
||||||
Index *pIdx; /* For looping over indices */
|
Index *pIdx; /* For looping over indices */
|
||||||
|
Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */
|
||||||
int nIdx; /* Number of indices that need updating */
|
int nIdx; /* Number of indices that need updating */
|
||||||
int iCur; /* VDBE Cursor number of pTab */
|
int iCur; /* VDBE Cursor number of pTab */
|
||||||
sqlite3 *db; /* The database structure */
|
sqlite3 *db; /* The database structure */
|
||||||
@@ -107,6 +108,7 @@ void sqlite3Update(
|
|||||||
** an expression for the i-th column of the table.
|
** an expression for the i-th column of the table.
|
||||||
** aXRef[i]==-1 if the i-th column is not changed. */
|
** aXRef[i]==-1 if the i-th column is not changed. */
|
||||||
int chngRowid; /* True if the record number is being changed */
|
int chngRowid; /* True if the record number is being changed */
|
||||||
|
int chngPk; /* The PRIMARY KEY of a WITHOUT ROWID table changed */
|
||||||
Expr *pRowidExpr = 0; /* Expression defining the new record number */
|
Expr *pRowidExpr = 0; /* Expression defining the new record number */
|
||||||
int openAll = 0; /* True if all indices need to be opened */
|
int openAll = 0; /* True if all indices need to be opened */
|
||||||
AuthContext sContext; /* The authorization context */
|
AuthContext sContext; /* The authorization context */
|
||||||
@@ -114,6 +116,8 @@ void sqlite3Update(
|
|||||||
int iDb; /* Database containing the table being updated */
|
int iDb; /* Database containing the table being updated */
|
||||||
int okOnePass; /* True for one-pass algorithm without the FIFO */
|
int okOnePass; /* True for one-pass algorithm without the FIFO */
|
||||||
int hasFK; /* True if foreign key processing is required */
|
int hasFK; /* True if foreign key processing is required */
|
||||||
|
int labelBreak; /* Jump here to break out of UPDATE loop */
|
||||||
|
int labelContinue; /* Jump here to continue next step of UPDATE loop */
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
int isView; /* True when updating a view (INSTEAD OF trigger) */
|
int isView; /* True when updating a view (INSTEAD OF trigger) */
|
||||||
@@ -121,6 +125,7 @@ void sqlite3Update(
|
|||||||
int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
|
int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
|
||||||
#endif
|
#endif
|
||||||
int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */
|
int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */
|
||||||
|
int iEph = 0; /* Ephemeral table holding all primary key values */
|
||||||
|
|
||||||
/* Register Allocations */
|
/* Register Allocations */
|
||||||
int regRowCount = 0; /* A count of rows changed */
|
int regRowCount = 0; /* A count of rows changed */
|
||||||
@@ -129,6 +134,7 @@ void sqlite3Update(
|
|||||||
int regNew; /* Content of the NEW.* table in triggers */
|
int regNew; /* Content of the NEW.* table in triggers */
|
||||||
int regOld = 0; /* Content of OLD.* table in triggers */
|
int regOld = 0; /* Content of OLD.* table in triggers */
|
||||||
int regRowSet = 0; /* Rowset of rows to be updated */
|
int regRowSet = 0; /* Rowset of rows to be updated */
|
||||||
|
int regKey = 0; /* composite PRIMARY KEY value */
|
||||||
|
|
||||||
memset(&sContext, 0, sizeof(sContext));
|
memset(&sContext, 0, sizeof(sContext));
|
||||||
db = pParse->db;
|
db = pParse->db;
|
||||||
@@ -179,6 +185,7 @@ void sqlite3Update(
|
|||||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||||
pParse->nTab++;
|
pParse->nTab++;
|
||||||
}
|
}
|
||||||
|
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||||
|
|
||||||
/* Initialize the name-context */
|
/* Initialize the name-context */
|
||||||
memset(&sNC, 0, sizeof(sNC));
|
memset(&sNC, 0, sizeof(sNC));
|
||||||
@@ -191,7 +198,7 @@ void sqlite3Update(
|
|||||||
** column to be updated, make sure we have authorization to change
|
** column to be updated, make sure we have authorization to change
|
||||||
** that column.
|
** that column.
|
||||||
*/
|
*/
|
||||||
chngRowid = 0;
|
chngPk = chngRowid = 0;
|
||||||
for(i=0; i<pChanges->nExpr; i++){
|
for(i=0; i<pChanges->nExpr; i++){
|
||||||
if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
|
if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
|
||||||
goto update_cleanup;
|
goto update_cleanup;
|
||||||
@@ -201,13 +208,15 @@ void sqlite3Update(
|
|||||||
if( j==pTab->iPKey ){
|
if( j==pTab->iPKey ){
|
||||||
chngRowid = 1;
|
chngRowid = 1;
|
||||||
pRowidExpr = pChanges->a[i].pExpr;
|
pRowidExpr = pChanges->a[i].pExpr;
|
||||||
|
}else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
|
||||||
|
chngPk = 1;
|
||||||
}
|
}
|
||||||
aXRef[j] = i;
|
aXRef[j] = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( j>=pTab->nCol ){
|
if( j>=pTab->nCol ){
|
||||||
if( sqlite3IsRowid(pChanges->a[i].zName) ){
|
if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){
|
||||||
j = -1;
|
j = -1;
|
||||||
chngRowid = 1;
|
chngRowid = 1;
|
||||||
pRowidExpr = pChanges->a[i].pExpr;
|
pRowidExpr = pChanges->a[i].pExpr;
|
||||||
@@ -250,7 +259,7 @@ void sqlite3Update(
|
|||||||
reg = ++pParse->nMem;
|
reg = ++pParse->nMem;
|
||||||
}else{
|
}else{
|
||||||
reg = 0;
|
reg = 0;
|
||||||
for(i=0; i<pIdx->nKeyCol; i++){
|
for(i=0; i<pIdx->nColumn; i++){
|
||||||
if( aXRef[pIdx->aiColumn[i]]>=0 ){
|
if( aXRef[pIdx->aiColumn[i]]>=0 ){
|
||||||
reg = ++pParse->nMem;
|
reg = ++pParse->nMem;
|
||||||
break;
|
break;
|
||||||
@@ -313,24 +322,49 @@ void sqlite3Update(
|
|||||||
|
|
||||||
/* Begin the database scan
|
/* Begin the database scan
|
||||||
*/
|
*/
|
||||||
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
|
if( HasRowid(pTab) ){
|
||||||
pWInfo = sqlite3WhereBegin(
|
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
|
||||||
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0
|
pWInfo = sqlite3WhereBegin(
|
||||||
);
|
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0
|
||||||
if( pWInfo==0 ) goto update_cleanup;
|
);
|
||||||
okOnePass = sqlite3WhereOkOnePass(pWInfo);
|
if( pWInfo==0 ) goto update_cleanup;
|
||||||
|
okOnePass = sqlite3WhereOkOnePass(pWInfo);
|
||||||
|
|
||||||
|
/* Remember the rowid of every item to be updated.
|
||||||
|
*/
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
|
||||||
|
if( !okOnePass ){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End the database scan loop.
|
||||||
|
*/
|
||||||
|
sqlite3WhereEnd(pWInfo);
|
||||||
|
}else{
|
||||||
|
int iPk; /* First of nPk memory cells holding PRIMARY KEY value */
|
||||||
|
i16 nPk; /* Number of components of the PRIMARY KEY */
|
||||||
|
|
||||||
/* Remember the rowid of every item to be updated.
|
assert( pPk!=0 );
|
||||||
*/
|
nPk = pPk->nKeyCol;
|
||||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
|
iPk = pParse->nMem+1;
|
||||||
if( !okOnePass ){
|
pParse->nMem += nPk;
|
||||||
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
|
regKey = ++pParse->nMem;
|
||||||
|
iEph = pParse->nTab++;
|
||||||
|
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iEph, nPk, 0,
|
||||||
|
(char*)sqlite3IndexKeyinfo(pParse, pPk),
|
||||||
|
P4_KEYINFO_HANDOFF);
|
||||||
|
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 0, 0);
|
||||||
|
if( pWInfo==0 ) goto update_cleanup;
|
||||||
|
for(i=0; i<nPk; i++){
|
||||||
|
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, pPk->aiColumn[i], iPk+i);
|
||||||
|
}
|
||||||
|
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
|
||||||
|
sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey);
|
||||||
|
sqlite3WhereEnd(pWInfo);
|
||||||
|
okOnePass = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End the database scan loop.
|
|
||||||
*/
|
|
||||||
sqlite3WhereEnd(pWInfo);
|
|
||||||
|
|
||||||
/* Initialize the count of updated rows
|
/* Initialize the count of updated rows
|
||||||
*/
|
*/
|
||||||
if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){
|
if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){
|
||||||
@@ -345,7 +379,9 @@ void sqlite3Update(
|
|||||||
** action, then we need to open all indices because we might need
|
** action, then we need to open all indices because we might need
|
||||||
** to be deleting some records.
|
** to be deleting some records.
|
||||||
*/
|
*/
|
||||||
if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
|
if( !okOnePass && HasRowid(pTab) ){
|
||||||
|
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
|
||||||
|
}
|
||||||
if( onError==OE_Replace ){
|
if( onError==OE_Replace ){
|
||||||
openAll = 1;
|
openAll = 1;
|
||||||
}else{
|
}else{
|
||||||
@@ -369,19 +405,22 @@ void sqlite3Update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Top of the update loop */
|
/* Top of the update loop */
|
||||||
if( okOnePass ){
|
labelBreak = sqlite3VdbeMakeLabel(v);
|
||||||
|
labelContinue = sqlite3VdbeMakeLabel(v);
|
||||||
|
if( pPk ){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak);
|
||||||
|
addr = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
|
||||||
|
sqlite3VdbeAddOp3(v, OP_NotFound, iEph, labelContinue, regKey);
|
||||||
|
}else if( okOnePass ){
|
||||||
int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
|
int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
|
||||||
addr = sqlite3VdbeAddOp0(v, OP_Goto);
|
addr = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelBreak);
|
||||||
sqlite3VdbeJumpHere(v, a1);
|
sqlite3VdbeJumpHere(v, a1);
|
||||||
}else{
|
}else{
|
||||||
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid);
|
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak,
|
||||||
|
regOldRowid);
|
||||||
|
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make cursor iCur point to the record that is being updated. If
|
|
||||||
** this record does not exist for some reason (deleted by a trigger,
|
|
||||||
** for example, then jump to the next iteration of the RowSet loop. */
|
|
||||||
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
|
|
||||||
|
|
||||||
/* If the record number will change, set register regNewRowid to
|
/* If the record number will change, set register regNewRowid to
|
||||||
** contain the new value. If the record number is not being modified,
|
** contain the new value. If the record number is not being modified,
|
||||||
** then regNewRowid is the same register as regOldRowid, which is
|
** then regNewRowid is the same register as regOldRowid, which is
|
||||||
@@ -528,8 +567,13 @@ void sqlite3Update(
|
|||||||
/* Repeat the above with the next record to be updated, until
|
/* Repeat the above with the next record to be updated, until
|
||||||
** all record selected by the WHERE clause have been updated.
|
** all record selected by the WHERE clause have been updated.
|
||||||
*/
|
*/
|
||||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
|
if( pPk ){
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
sqlite3VdbeResolveLabel(v, labelContinue);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Next, iEph, addr);
|
||||||
|
}else if( !okOnePass ){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
|
||||||
|
}
|
||||||
|
sqlite3VdbeResolveLabel(v, labelBreak);
|
||||||
|
|
||||||
/* Close all tables */
|
/* Close all tables */
|
||||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||||
|
|||||||
Reference in New Issue
Block a user