aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2018-09-17 20:47:38 +0000
committerdrh <drh@noemail.net>2018-09-17 20:47:38 +0000
commit40b4e7a6923cde8c5ab0b8148c3b07bbf4414e8c (patch)
tree0cc3a205e0d0addd74ec83e3af4d0001adc61025 /src
parentd4cb09e3d26a2b507bf781b168922da81bb54b53 (diff)
downloadsqlite-40b4e7a6923cde8c5ab0b8148c3b07bbf4414e8c.tar.gz
sqlite-40b4e7a6923cde8c5ab0b8148c3b07bbf4414e8c.zip
Further optimizations to the UPDATE logic to avoid making changes to partial
indexes if none of the columns mentioned in the WHERE clause are modified by the UPDATE. FossilOrigin-Name: d1365a5bf0ee2f145427b81d2a593f539c3ad4705d579478703c1f65ae5f80bf
Diffstat (limited to 'src')
-rw-r--r--src/update.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/src/update.c b/src/update.c
index 9e76c445e..dd2b05c3e 100644
--- a/src/update.c
+++ b/src/update.c
@@ -82,7 +82,9 @@ 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.
+** 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
@@ -107,6 +109,28 @@ static int indexColumnIsBeingUpdated(
}
/*
+** 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.
**
** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
@@ -332,7 +356,9 @@ void sqlite3Update(
*/
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{