aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c3
-rw-r--r--src/fkey.c1
-rw-r--r--src/sqliteInt.h4
-rw-r--r--src/trigger.c63
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;