diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/resolve.c | 2 | ||||
-rw-r--r-- | src/select.c | 32 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/update.c | 47 |
4 files changed, 58 insertions, 26 deletions
diff --git a/src/resolve.c b/src/resolve.c index 60fed0b10..76cdc8ccd 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -756,7 +756,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ case TK_ROW: { SrcList *pSrcList = pNC->pSrcList; struct SrcList_item *pItem; - assert( pSrcList && pSrcList->nSrc==1 ); + assert( pSrcList && pSrcList->nSrc>=1 ); pItem = pSrcList->a; assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 ); pExpr->op = TK_COLUMN; diff --git a/src/select.c b/src/select.c index fdffe9163..757fa3265 100644 --- a/src/select.c +++ b/src/select.c @@ -1006,7 +1006,8 @@ static void selectInnerLoop( testcase( eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); assert( eDest==SRT_Set || eDest==SRT_Mem - || eDest==SRT_Coroutine || eDest==SRT_Output ); + || eDest==SRT_Coroutine || eDest==SRT_Output + || eDest==SRT_Upfrom ); } sRowLoadInfo.regResult = regResult; sRowLoadInfo.ecelFlags = ecelFlags; @@ -1156,14 +1157,18 @@ static void selectInnerLoop( } 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); + if( pSort ){ + pushOntoSorter( + pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else{ - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, i2); + 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; } @@ -1600,6 +1605,17 @@ static void generateSortTail( break; } #endif + case SRT_Upfrom: { + int i2 = pDest->iSDParm2; + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord,regRow+(i2<0),nColumn-(i2<0),r1); + if( i2<0 ){ + sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regRow); + }else{ + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regRow, i2); + } + break; + } default: { assert( eDest==SRT_Output || eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 34d6fea7e..c668e6bee 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3187,8 +3187,7 @@ struct Select { #define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */ #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 */ +#define SRT_Upfrom 15 /* Store result as data with rowid */ /* ** An instance of this object describes where to put of the results of diff --git a/src/update.c b/src/update.c index 80f07d3de..5d4e5ae7d 100644 --- a/src/update.c +++ b/src/update.c @@ -164,7 +164,9 @@ static void updatePopulateEphTable( Index *pPk, /* PK if table 0 is WITHOUT ROWID */ ExprList *pChanges, /* List of expressions to return */ SrcList *pTabList, /* List of tables to select from */ - Expr *pWhere /* WHERE clause for query */ + Expr *pWhere, /* WHERE clause for query */ + ExprList *pOrderBy, + Expr *pLimit ){ int i; sqlite3 *db = pParse->db; @@ -174,6 +176,9 @@ static void updatePopulateEphTable( Table *pTab = pTabList->a[0].pTab; SrcList *pSrc = sqlite3SrcListDup(db, pTabList, 0); Expr *pWhere2 = sqlite3ExprDup(db, pWhere, 0); + Expr *pLimit2 = sqlite3ExprDup(db, pLimit, 0); + ExprList *pOrderBy2 = sqlite3ExprListDup(db, pOrderBy, 0); + ExprList *pGroupBy = 0; int eDest; assert( pTabList->nSrc>1 ); @@ -184,11 +189,16 @@ static void updatePopulateEphTable( } if( pPk ){ for(i=0; i<pPk->nKeyCol; i++){ - pList = sqlite3ExprListAppend(pParse, pList, - sqlite3PExpr(pParse, TK_DOT, - sqlite3Expr(db, TK_ID, pTab->zName), - sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName) - )); + Expr *pNew = sqlite3PExpr(pParse, TK_DOT, + sqlite3Expr(db, TK_ID, pTab->zName), + sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName) + ); + if( pLimit ){ + pGroupBy = sqlite3ExprListAppend(pParse, pGroupBy, + sqlite3ExprDup(db, pNew, 0) + ); + } + pList = sqlite3ExprListAppend(pParse, pList, pNew); } eDest = SRT_Upfrom; }else if( pTab->pSelect ){ @@ -199,19 +209,24 @@ static void updatePopulateEphTable( )); eDest = SRT_Table; }else{ - pList = sqlite3ExprListAppend(pParse, pList, - sqlite3PExpr(pParse, TK_DOT, - sqlite3Expr(db, TK_ID, pTab->zName), - sqlite3Expr(db, TK_ID, "_rowid_") - )); eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom; + pList = sqlite3ExprListAppend(pParse, pList, + sqlite3PExpr(pParse, TK_ROW, 0, 0) + ); + if( pLimit ){ + pGroupBy = sqlite3ExprListAppend(pParse, pGroupBy, + sqlite3PExpr(pParse, TK_ROW, 0, 0) + ); + } } for(i=0; i<pChanges->nExpr; i++){ pList = sqlite3ExprListAppend(pParse, pList, sqlite3ExprDup(db, pChanges->a[i].pExpr, 0) ); } - pSelect = sqlite3SelectNew(pParse, pList, pSrc, pWhere2, 0, 0, 0, 0, 0); + pSelect = sqlite3SelectNew( + pParse, pList, pSrc, pWhere2, pGroupBy, 0, pOrderBy2, 0, pLimit2 + ); sqlite3SelectDestInit(&dest, eDest, iEph); dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1); sqlite3Select(pParse, pSelect, &dest); @@ -323,7 +338,7 @@ void sqlite3Update( assert( nChangeFrom==0 || pUpsert==0 ); #ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT - if( !isView ){ + if( !isView && nChangeFrom==0 ){ pWhere = sqlite3LimitWhere( pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE" ); @@ -608,7 +623,9 @@ void sqlite3Update( addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nEphCol); if( pPk ) sqlite3VdbeSetP4KeyInfo(pParse, pPk); if( nChangeFrom ){ - updatePopulateEphTable(pParse, iEph, pPk, pChanges, pTabList, pWhere); + updatePopulateEphTable( + pParse, iEph, pPk, pChanges, pTabList, pWhere, pOrderBy, pLimit + ); #ifndef SQLITE_OMIT_SUBQUERY if( isView ) iDataCur = iEph; #endif @@ -1148,7 +1165,7 @@ static void updateVirtualTable( } } - updatePopulateEphTable(pParse, ephemTab, 0, pList, pSrc, pWhere); + updatePopulateEphTable(pParse, ephemTab, 0, pList, pSrc, pWhere, 0, 0); sqlite3ExprListDelete(db, pList); eOnePass = ONEPASS_OFF; }else{ |