diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/select.c | 31 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/update.c | 15 |
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); |