1
0
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:
dan
2020-07-14 19:51:01 +00:00
parent f067ae8eba
commit e7877b2d6b
10 changed files with 213 additions and 38 deletions

View File

@@ -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;