mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Support UPDATE...FROM statements in trigger programs.
FossilOrigin-Name: 4f6d8d0ebf40029218a1d3b05ea657c0c5953b01c6f0b6a628465aa44c67e7f3
This commit is contained in:
@@ -26,6 +26,7 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
|
||||
sqlite3SelectDelete(db, pTmp->pSelect);
|
||||
sqlite3IdListDelete(db, pTmp->pIdList);
|
||||
sqlite3UpsertDelete(db, pTmp->pUpsert);
|
||||
sqlite3SrcListDelete(db, pTmp->pFrom);
|
||||
sqlite3DbFree(db, pTmp->zSpan);
|
||||
|
||||
sqlite3DbFree(db, pTmp);
|
||||
@@ -486,6 +487,7 @@ TriggerStep *sqlite3TriggerInsertStep(
|
||||
TriggerStep *sqlite3TriggerUpdateStep(
|
||||
Parse *pParse, /* Parser */
|
||||
Token *pTableName, /* Name of the table to be updated */
|
||||
SrcList *pFrom,
|
||||
ExprList *pEList, /* The SET clause: list of column and new values */
|
||||
Expr *pWhere, /* The WHERE clause */
|
||||
u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
|
||||
@@ -500,16 +502,22 @@ TriggerStep *sqlite3TriggerUpdateStep(
|
||||
if( IN_RENAME_OBJECT ){
|
||||
pTriggerStep->pExprList = pEList;
|
||||
pTriggerStep->pWhere = pWhere;
|
||||
pTriggerStep->pFrom = pFrom;
|
||||
pEList = 0;
|
||||
pWhere = 0;
|
||||
pFrom = 0;
|
||||
}else{
|
||||
pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
|
||||
pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
|
||||
pTriggerStep->pFrom = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE);
|
||||
}
|
||||
pTriggerStep->orconf = orconf;
|
||||
}else{
|
||||
sqlite3SrcListDelete(db, pFrom);
|
||||
}
|
||||
sqlite3ExprListDelete(db, pEList);
|
||||
sqlite3ExprDelete(db, pWhere);
|
||||
sqlite3SrcListDelete(db, pFrom);
|
||||
return pTriggerStep;
|
||||
}
|
||||
|
||||
@@ -736,25 +744,28 @@ Trigger *sqlite3TriggersExist(
|
||||
** trigger is in TEMP in which case it can refer to any other database it
|
||||
** wants.
|
||||
*/
|
||||
static SrcList *targetSrcList(
|
||||
SrcList *sqlite3TriggerStepSrc(
|
||||
Parse *pParse, /* The parsing context */
|
||||
TriggerStep *pStep /* The trigger containing the target token */
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb; /* Index of the database to use */
|
||||
SrcList *pSrc; /* SrcList to be returned */
|
||||
|
||||
SrcList *pSrc; /* SrcList to be returned */
|
||||
char *zName = sqlite3DbStrDup(db, pStep->zTarget);
|
||||
pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
|
||||
assert( pSrc==0 || pSrc->nSrc==1 );
|
||||
assert( zName || pSrc==0 );
|
||||
if( pSrc ){
|
||||
assert( pSrc->nSrc>0 );
|
||||
pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
|
||||
iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema);
|
||||
if( iDb==0 || iDb>=2 ){
|
||||
const char *zDb;
|
||||
assert( iDb<db->nDb );
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb);
|
||||
Schema *pSchema = pStep->pTrig->pSchema;
|
||||
pSrc->a[0].zName = zName;
|
||||
if( pSchema!=db->aDb[1].pSchema ){
|
||||
pSrc->a[0].pSchema = pSchema;
|
||||
}
|
||||
if( pStep->pFrom ){
|
||||
SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0);
|
||||
pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
|
||||
}
|
||||
}else{
|
||||
sqlite3DbFree(db, zName);
|
||||
}
|
||||
return pSrc;
|
||||
}
|
||||
@@ -803,7 +814,7 @@ static int codeTriggerProgram(
|
||||
switch( pStep->op ){
|
||||
case TK_UPDATE: {
|
||||
sqlite3Update(pParse,
|
||||
targetSrcList(pParse, pStep),
|
||||
sqlite3TriggerStepSrc(pParse, pStep),
|
||||
sqlite3ExprListDup(db, pStep->pExprList, 0),
|
||||
sqlite3ExprDup(db, pStep->pWhere, 0),
|
||||
pParse->eOrconf, 0, 0, 0
|
||||
@@ -812,7 +823,7 @@ static int codeTriggerProgram(
|
||||
}
|
||||
case TK_INSERT: {
|
||||
sqlite3Insert(pParse,
|
||||
targetSrcList(pParse, pStep),
|
||||
sqlite3TriggerStepSrc(pParse, pStep),
|
||||
sqlite3SelectDup(db, pStep->pSelect, 0),
|
||||
sqlite3IdListDup(db, pStep->pIdList),
|
||||
pParse->eOrconf,
|
||||
@@ -822,7 +833,7 @@ static int codeTriggerProgram(
|
||||
}
|
||||
case TK_DELETE: {
|
||||
sqlite3DeleteFrom(pParse,
|
||||
targetSrcList(pParse, pStep),
|
||||
sqlite3TriggerStepSrc(pParse, pStep),
|
||||
sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
|
||||
);
|
||||
break;
|
||||
|
Reference in New Issue
Block a user