mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-10 01:02:56 +03:00
Merge latest begin-concurrent changes into this branch.
FossilOrigin-Name: 6f3dd9809fdef7d6195f1f93428a662d5a8c01dba9815daa22d1b94059a2eb43
This commit is contained in:
70
src/update.c
70
src/update.c
@@ -79,6 +79,57 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if column iCol of index pIdx references any of the
|
||||
** columns defined by aXRef and chngRowid. Return true if it does
|
||||
** and false if not. This is an optimization. False-positives are a
|
||||
** performance degradation, but false-negatives can result in a corrupt
|
||||
** index and incorrect answers.
|
||||
**
|
||||
** aXRef[j] will be non-negative if column j of the original table is
|
||||
** being updated. chngRowid will be true if the rowid of the table is
|
||||
** being updated.
|
||||
*/
|
||||
static int indexColumnIsBeingUpdated(
|
||||
Index *pIdx, /* The index to check */
|
||||
int iCol, /* Which column of the index to check */
|
||||
int *aXRef, /* aXRef[j]>=0 if column j is being updated */
|
||||
int chngRowid /* true if the rowid is being updated */
|
||||
){
|
||||
i16 iIdxCol = pIdx->aiColumn[iCol];
|
||||
assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */
|
||||
if( iIdxCol>=0 ){
|
||||
return aXRef[iIdxCol]>=0;
|
||||
}
|
||||
assert( iIdxCol==XN_EXPR );
|
||||
assert( pIdx->aColExpr!=0 );
|
||||
assert( pIdx->aColExpr->a[iCol].pExpr!=0 );
|
||||
return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr,
|
||||
aXRef,chngRowid);
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if index pIdx is a partial index whose conditional
|
||||
** expression might change values due to an UPDATE. Return true if
|
||||
** the index is subject to change and false if the index is guaranteed
|
||||
** to be unchanged. This is an optimization. False-positives are a
|
||||
** performance degradation, but false-negatives can result in a corrupt
|
||||
** index and incorrect answers.
|
||||
**
|
||||
** aXRef[j] will be non-negative if column j of the original table is
|
||||
** being updated. chngRowid will be true if the rowid of the table is
|
||||
** being updated.
|
||||
*/
|
||||
static int indexWhereClauseMightChange(
|
||||
Index *pIdx, /* The index to check */
|
||||
int *aXRef, /* aXRef[j]>=0 if column j is being updated */
|
||||
int chngRowid /* true if the rowid is being updated */
|
||||
){
|
||||
if( pIdx->pPartIdxWhere==0 ) return 0;
|
||||
return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere,
|
||||
aXRef, chngRowid);
|
||||
}
|
||||
|
||||
/*
|
||||
** Process an UPDATE statement.
|
||||
**
|
||||
@@ -313,19 +364,18 @@ void sqlite3Update(
|
||||
/* There is one entry in the aRegIdx[] array for each index on the table
|
||||
** being updated. Fill in aRegIdx[] with a register number that will hold
|
||||
** the key for accessing each index.
|
||||
**
|
||||
** FIXME: Be smarter about omitting indexes that use expressions.
|
||||
*/
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int reg;
|
||||
if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){
|
||||
if( chngKey || hasFK>1 || pIdx==pPk
|
||||
|| indexWhereClauseMightChange(pIdx,aXRef,chngRowid)
|
||||
){
|
||||
reg = ++pParse->nMem;
|
||||
pParse->nMem += pIdx->nColumn;
|
||||
}else{
|
||||
reg = 0;
|
||||
for(i=0; i<pIdx->nKeyCol; i++){
|
||||
i16 iIdxCol = pIdx->aiColumn[i];
|
||||
if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
|
||||
if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
|
||||
reg = ++pParse->nMem;
|
||||
pParse->nMem += pIdx->nColumn;
|
||||
if( (onError==OE_Replace)
|
||||
@@ -621,13 +671,7 @@ void sqlite3Update(
|
||||
*/
|
||||
testcase( i==31 );
|
||||
testcase( i==32 );
|
||||
sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i);
|
||||
if( tmask & TRIGGER_BEFORE ){
|
||||
/* This value will be recomputed in After-BEFORE-trigger-reload-loop
|
||||
** below, so make sure that it is not cached and reused.
|
||||
** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28. */
|
||||
sqlite3ExprCacheRemove(pParse, regNew+i, 1);
|
||||
}
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
||||
}
|
||||
@@ -880,7 +924,7 @@ static void updateVirtualTable(
|
||||
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
|
||||
}else{
|
||||
sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
|
||||
sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */
|
||||
}
|
||||
}
|
||||
if( HasRowid(pTab) ){
|
||||
|
Reference in New Issue
Block a user