diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 3 | ||||
-rw-r--r-- | src/fkey.c | 1 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/trigger.c | 63 |
4 files changed, 60 insertions, 11 deletions
diff --git a/src/build.c b/src/build.c index 99ecad4d6..a25c9c6d8 100644 --- a/src/build.c +++ b/src/build.c @@ -1282,8 +1282,7 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){ pRet->retTrig.bReturning = 1; pRet->retTrig.pSchema = db->aDb[1].pSchema; pRet->retTrig.step_list = &pRet->retTStep; - pRet->retTStep.op = TK_SELECT; - pRet->retTStep.eTrigDest = SRT_Output; + pRet->retTStep.op = TK_RETURNING; pRet->retTStep.pTrig = &pRet->retTrig; pRet->retTStep.pSelect = &pRet->retSel; pRet->retSel.op = TK_ALL; diff --git a/src/fkey.c b/src/fkey.c index 4cb92e291..59e12b5fa 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1353,7 +1353,6 @@ static Trigger *fkActionTrigger( switch( action ){ case OE_Restrict: pStep->op = TK_SELECT; - pStep->eTrigDest = SRT_Discard; break; case OE_Cascade: if( !pChanges ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 231ead506..3cadb7f53 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3639,9 +3639,9 @@ struct Trigger { * */ struct TriggerStep { - u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ + u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT, + ** or TK_RETURNING */ u8 orconf; /* OE_Rollback etc. */ - u8 eTrigDest; /* SRT_ destination value for SELECT */ Trigger *pTrig; /* The trigger that this step is a part of */ Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ diff --git a/src/trigger.c b/src/trigger.c index 5508e4d15..a20c14197 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -410,7 +410,6 @@ TriggerStep *sqlite3TriggerSelectStep( return 0; } pTriggerStep->op = TK_SELECT; - pTriggerStep->eTrigDest = SRT_Discard; pTriggerStep->pSelect = pSelect; pTriggerStep->orconf = OE_Default; pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); @@ -788,6 +787,46 @@ SrcList *sqlite3TriggerStepSrc( return pSrc; } +/* The input list pList is the list of result set terms from a RETURNING +** clause. The table that we are returning from is pTab. +** +** This routine makes a copy of the pList, and at the same time expands +** any "*" wildcards to be the complete set of columns from pTab. +*/ +static ExprList *sqlite3ExpandReturning( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* The arguments to RETURNING */ + Table *pTab /* The table being updated */ +){ + ExprList *pNew = 0; + sqlite3 *db = pParse->db; + int i; + for(i=0; i<pList->nExpr; i++){ + Expr *pOldExpr = pList->a[i].pExpr; + if( ALWAYS(pOldExpr!=0) && pOldExpr->op==TK_ASTERISK ){ + int j; + for(j=0; j<pTab->nCol; j++){ + Expr *pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[j].zName); + pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr); + if( !db->mallocFailed ){ + struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1]; + pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[j].zName); + pItem->eEName = ENAME_NAME; + } + } + }else{ + Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0); + pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr); + if( pList->a[i].zEName!=0 && !db->mallocFailed ){ + struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1]; + pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName); + pItem->eEName = pList->a[i].eEName; + } + } + } + return pNew; +} + /* ** Generate VDBE code for the statements inside the body of a single ** trigger. @@ -837,6 +876,7 @@ static int codeTriggerProgram( sqlite3ExprDup(db, pStep->pWhere, 0), pParse->eOrconf, 0, 0, 0 ); + sqlite3VdbeAddOp0(v, OP_ResetCount); break; } case TK_INSERT: { @@ -847,6 +887,7 @@ static int codeTriggerProgram( pParse->eOrconf, sqlite3UpsertDup(db, pStep->pUpsert) ); + sqlite3VdbeAddOp0(v, OP_ResetCount); break; } case TK_DELETE: { @@ -854,20 +895,30 @@ static int codeTriggerProgram( sqlite3TriggerStepSrc(pParse, pStep), sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0 ); + sqlite3VdbeAddOp0(v, OP_ResetCount); break; } - default: assert( pStep->op==TK_SELECT ); { + case TK_SELECT: { SelectDest sDest; Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0); - sqlite3SelectDestInit(&sDest, pStep->eTrigDest, 0); + sqlite3SelectDestInit(&sDest, SRT_Discard, 0); sqlite3Select(pParse, pSelect, &sDest); sqlite3SelectDelete(db, pSelect); break; } + default: assert( pStep->op==TK_RETURNING ); { + Select *pSelect = pStep->pSelect; + ExprList *pList = pSelect->pEList; + SelectDest sDest; + pSelect->pEList = + sqlite3ExpandReturning(pParse, pList, pParse->pTriggerTab); + sqlite3SelectDestInit(&sDest, SRT_Output, 0); + sqlite3Select(pParse, pSelect, &sDest); + sqlite3ExprListDelete(db, pSelect->pEList); + pSelect->pEList = pList; + break; + } } - if( pStep->op!=TK_SELECT ){ - sqlite3VdbeAddOp0(v, OP_ResetCount); - } } return 0; |