Modify UPDATE so that two-pass updates on a rowid table use an ephemeral

table to store rowids rather than a RowSet.  This uses less memory, though
it is slower.

FossilOrigin-Name: 4673096dd8c5ed7aed098ff518a6d01d35c40fad991b89fddd91c19a727a4308
This commit is contained in:
drh
2020-11-14 20:03:34 +00:00
parent b035b87ef8
commit ea2487200f
3 changed files with 22 additions and 14 deletions
+12 -7
View File
@@ -651,6 +651,9 @@ void sqlite3Update(
if( nChangeFrom==0 && HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
iEph = pParse->nTab++;
addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, 0);
sqlite3VdbeLoadString(v, regRowSet, "");
}else{
assert( pPk!=0 || HasRowid(pTab) );
nPk = pPk ? pPk->nKeyCol : 0;
@@ -742,9 +745,10 @@ void sqlite3Update(
** leave it in register regOldRowid. */
sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
if( eOnePass==ONEPASS_OFF ){
/* We need to use regRowSet, so reallocate aRegIdx[nAllIdx] */
aRegIdx[nAllIdx] = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iEph, regRowSet, regOldRowid);
}else{
if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen);
}
}else{
/* Read the PK of the current row into an array of registers. In
@@ -832,8 +836,9 @@ void sqlite3Update(
VdbeCoverage(v);
}
}else{
labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak,
regOldRowid);
sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
labelContinue = sqlite3VdbeMakeLabel(pParse);
addrTop = sqlite3VdbeAddOp2(v, OP_Rowid, iEph, regOldRowid);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
VdbeCoverage(v);
@@ -1083,11 +1088,11 @@ void sqlite3Update(
}else if( eOnePass==ONEPASS_MULTI ){
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3WhereEnd(pWInfo);
}else if( pPk || nChangeFrom ){
}else /*if( pPk || nChangeFrom )*/{
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
}else{
sqlite3VdbeGoto(v, labelContinue);
// }else{
// sqlite3VdbeGoto(v, labelContinue);
}
sqlite3VdbeResolveLabel(v, labelBreak);