diff options
Diffstat (limited to 'src/update.c')
-rw-r--r-- | src/update.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/src/update.c b/src/update.c index 94e169fd0..c9ec95bb6 100644 --- a/src/update.c +++ b/src/update.c @@ -80,6 +80,29 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ } /* +** 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. +** +** The iCol-th column of pIdx will be an expression. +** +** 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 indexExprRefsUpdatedColumn( + Index *pIdx, /* The index containing the expression to analyze */ + int iCol, /* Which column of the index is the expression */ + int *aXRef, /* aXRef[j]>=0 if column j is being updated */ + int chngRowid /* true if the rowid is being updated */ +){ + assert( pIdx->aColExpr!=0 ); + assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); + return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr, + aXRef,chngRowid); +} + +/* ** Process an UPDATE statement. ** ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; @@ -302,8 +325,6 @@ 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; @@ -314,7 +335,11 @@ void sqlite3Update( reg = 0; for(i=0; i<pIdx->nKeyCol; i++){ i16 iIdxCol = pIdx->aiColumn[i]; - if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ + if( (iIdxCol>=0 && aXRef[iIdxCol]>=0) + || iIdxCol==XN_ROWID + || (iIdxCol==XN_EXPR + && indexExprRefsUpdatedColumn(pIdx,i,aXRef,chngRowid)) + ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; if( (onError==OE_Replace) |