aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/resolve.c2
-rw-r--r--src/select.c32
-rw-r--r--src/sqliteInt.h3
-rw-r--r--src/update.c47
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{