aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <dan@noemail.net>2020-04-29 17:41:29 +0000
committerdan <dan@noemail.net>2020-04-29 17:41:29 +0000
commit9ed322d6c3c2562dffd590c59dfc8f83c31937ea (patch)
tree0e5db4a8ed99f585bccd399d009f73c2fdc69bc3 /src
parent69887c99d4cd271fe6bf9b40e958c90e409120b1 (diff)
downloadsqlite-9ed322d6c3c2562dffd590c59dfc8f83c31937ea.tar.gz
sqlite-9ed322d6c3c2562dffd590c59dfc8f83c31937ea.zip
Fix various bugs in new feature on this branch.
FossilOrigin-Name: 823ba94e29dece1687e28711e503a1f56d392c306b0cbc0a20548180834530d1
Diffstat (limited to 'src')
-rw-r--r--src/select.c31
-rw-r--r--src/sqliteInt.h4
-rw-r--r--src/update.c15
3 files changed, 35 insertions, 15 deletions
diff --git a/src/select.c b/src/select.c
index f6b48b5a0..fdffe9163 100644
--- a/src/select.c
+++ b/src/select.c
@@ -117,6 +117,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
pDest->eDest = (u8)eDest;
pDest->iSDParm = iParm;
+ pDest->iSDParm2 = 0;
pDest->zAffSdst = 0;
pDest->iSdst = 0;
pDest->nSdst = 0;
@@ -1154,11 +1155,24 @@ static void selectInnerLoop(
break;
}
+ case SRT_Upfrom: {
+ assert( pSort==0 );
+ int i2 = pDest->iSDParm2;
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord,regResult+(i2<0),nResultCol-(i2<0),r1);
+ if( i2<0 ){
+ sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regResult);
+ }else{
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, i2);
+ }
+ break;
+ }
+
+#ifndef SQLITE_OMIT_SUBQUERY
/* If we are creating a set for an "expr IN (SELECT ...)" construct,
** then there should be a single item on the stack. Write this
** item into the set table with bogus data.
*/
- case SRT_ISet:
case SRT_Set: {
if( pSort ){
/* At first glance you would think we could optimize out the
@@ -1168,22 +1182,17 @@ static void selectInnerLoop(
pushOntoSorter(
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
- int bITab = (eDest==SRT_ISet);
int r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult+bITab, nResultCol-bITab,
- r1, pDest->zAffSdst, 0
- );
- if( bITab ){
- sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regResult);
- }else{
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1,regResult,nResultCol);
- }
+ assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
+ r1, pDest->zAffSdst, nResultCol);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
}
break;
}
-#ifndef SQLITE_OMIT_SUBQUERY
+
/* If any row exist in the result set, record that fact and abort.
*/
case SRT_Exists: {
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 3cbc65cdd..34d6fea7e 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3188,14 +3188,16 @@ struct Select {
#define SRT_Coroutine 13 /* Generate a single row of result */
#define SRT_Table 14 /* Store result as data with an automatic rowid */
#define SRT_ISet 15 /* Store result as data with rowid */
+#define SRT_Upfrom 16 /* Store result as data with rowid */
/*
** An instance of this object describes where to put of the results of
** a SELECT statement.
*/
struct SelectDest {
- u8 eDest; /* How to dispose of the results. On of SRT_* above. */
+ u8 eDest; /* How to dispose of the results. One of SRT_* above. */
int iSDParm; /* A parameter used by the eDest disposal method */
+ int iSDParm2; /* A second parameter for the eDest disposal method */
int iSdst; /* Base register where results are written */
int nSdst; /* Number of registers allocated */
char *zAffSdst; /* Affinity used when eDest==SRT_Set */
diff --git a/src/update.c b/src/update.c
index 7257b2c6f..80f07d3de 100644
--- a/src/update.c
+++ b/src/update.c
@@ -190,7 +190,7 @@ static void updatePopulateEphTable(
sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName)
));
}
- eDest = SRT_Set;
+ eDest = SRT_Upfrom;
}else if( pTab->pSelect ){
pList = sqlite3ExprListAppend(pParse, pList,
sqlite3PExpr(pParse, TK_DOT,
@@ -204,7 +204,7 @@ static void updatePopulateEphTable(
sqlite3Expr(db, TK_ID, pTab->zName),
sqlite3Expr(db, TK_ID, "_rowid_")
));
- eDest = IsVirtual(pTab) ? SRT_Table : SRT_ISet;
+ eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
}
for(i=0; i<pChanges->nExpr; i++){
pList = sqlite3ExprListAppend(pParse, pList,
@@ -213,6 +213,7 @@ static void updatePopulateEphTable(
}
pSelect = sqlite3SelectNew(pParse, pList, pSrc, pWhere2, 0, 0, 0, 0, 0);
sqlite3SelectDestInit(&dest, eDest, iEph);
+ dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
sqlite3Select(pParse, pSelect, &dest);
sqlite3SelectDelete(db, pSelect);
}
@@ -878,7 +879,15 @@ void sqlite3Update(
** documentation.
*/
if( pPk ){
- sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
+ int p3, p4;
+ if( nChangeFrom ){
+ p3 = iPk;
+ p4 = nPk;
+ }else{
+ p3 = regKey;
+ p4 = nKey;
+ }
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, p3, p4);
VdbeCoverage(v);
}else{
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);