Enhance UPSERT so that the UPDATE uses the same set of cursors as the INSERT.
FossilOrigin-Name: c37f39d18d41ae5ba6c4561d87cbbf71f3b6896b86cc5cff9cdf046b02dc521a
diff --git a/src/insert.c b/src/insert.c
index b3a3138..782244a 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -812,6 +812,8 @@
pTabList->a[0].iCursor = iDataCur;
pUpsert->pUpsertSrc = pTabList;
pUpsert->regData = regData;
+ pUpsert->iDataCur = iDataCur;
+ pUpsert->iIdxCur = iIdxCur;
if( pUpsert->pUpsertTarget ){
sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert);
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 73cb629..ccbf846 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2743,8 +2743,14 @@
Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
+ /* The fields above comprise the parse tree for the upsert clause.
+ ** The fields below are used to transfer information from the INSERT
+ ** processing down into the UPDATE processing while generating code.
+ ** Upsert owns the memory allocated above, but not the memory below. */
SrcList *pUpsertSrc; /* Table to be updated */
int regData; /* First register holding array of VALUES */
+ int iDataCur; /* Index of the data cursor */
+ int iIdxCur; /* Index of the first index cursor */
};
/*
diff --git a/src/update.c b/src/update.c
index dd08b16..92164b6 100644
--- a/src/update.c
+++ b/src/update.c
@@ -211,6 +211,11 @@
}
pParse->nTab++;
}
+ if( pUpsert ){
+ iDataCur = pUpsert->iDataCur;
+ iIdxCur = pUpsert->iIdxCur;
+ pParse->nTab = iBaseCur;
+ }
pTabList->a[0].iCursor = iDataCur;
/* Allocate space for aXRef[], aRegIdx[], and aToOpen[].
@@ -476,7 +481,7 @@
}
labelBreak = sqlite3VdbeMakeLabel(v);
- if( !isView ){
+ if( !isView && pUpsert==0 ){
int addrOnce = 0;
/* Open every index that needs updating. */
diff --git a/src/upsert.c b/src/upsert.c
index 9e23c86..80c0056 100644
--- a/src/upsert.c
+++ b/src/upsert.c
@@ -222,7 +222,7 @@
pE1 = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( pE1 ){
pE1->pTab = pTab;
- pE1->iTable = pParse->nTab;
+ pE1->iTable = pUpsert->iDataCur;
pE1->iColumn = -1;
}
pE2 = sqlite3ExprAlloc(db, TK_REGISTER, 0, 0);
@@ -234,11 +234,6 @@
}else{
/* a WITHOUT ROWID table */
int i, j;
- int iTab = pParse->nTab+1;
- Index *pX;
- for(pX=pTab->pIndex; ALWAYS(pX) && !IsPrimaryKeyIndex(pX); pX=pX->pNext){
- iTab++;
- }
for(i=0; i<pIdx->nKeyCol; i++){
regKey = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regKey);
@@ -247,7 +242,7 @@
pE1 = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( pE1 ){
pE1->pTab = pTab;
- pE1->iTable = iTab;
+ pE1->iTable = pUpsert->iDataCur;
pE1->iColumn = j;
}
pE2 = sqlite3ExprAlloc(db, TK_REGISTER, 0, 0);