Improved comments on the new code.

FossilOrigin-Name: a38f0c1d7c1d7635732ac370d8fbc7e6a2005378e4621da7bc4f51a2f99912d1
This commit is contained in:
drh
2021-01-30 21:55:38 +00:00
parent 1832f2921d
commit 28828c550f
4 changed files with 45 additions and 20 deletions
+23 -8
View File
@@ -1244,23 +1244,38 @@ void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
#endif
/*
** Name of the magic TEMP trigger used to implement RETURNING
** Name of the special TEMP trigger used to implement RETURNING. The
** name begins with "sqlite_" so that it is guaranteed not to collide
** with any application-generated triggers.
*/
#define RETURNING_TRIGGER "sqlite_returning"
#define RETURNING_TRIGGER_NAME "sqlite_returning"
/*
** Delete the data structures associated with the RETURNING clause.
** Clean up the data structures associated with the RETURNING clause.
*/
static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){
Hash *pHash;
pHash = &(db->aDb[1].pSchema->trigHash);
sqlite3HashInsert(pHash, RETURNING_TRIGGER, 0);
sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0);
sqlite3ExprListDelete(db, pRet->pReturnEL);
sqlite3DbFree(db, pRet);
}
/*
** Add the RETURNING clause to the parser currently underway.
** Add the RETURNING clause to the parse currently underway.
**
** This routine creates a special TEMP trigger that will fire for each row
** of the DML statement. That TEMP trigger contains a single SELECT
** statement with a result set that is the argument of the RETURNING clause.
** The trigger has the Trigger.bReturning flag and an opcode of
** TK_RETURNING instead of TK_SELECT, so that the trigger code generator
** knows to handle it specially. The TEMP trigger is automatically
** removed at the end of the parse.
**
** When this routine is called, we do not yet know if the RETURNING clause
** is attached to a DELETE, INSERT, or UPDATE, so construct it as a
** RETURNING trigger instead. It will then be converted into the appropriate
** type on the first call to sqlite3TriggersExist().
*/
void sqlite3AddReturning(Parse *pParse, ExprList *pList){
Returning *pRet;
@@ -1278,7 +1293,7 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet);
if( db->mallocFailed ) return;
pRet->retTrig.zName = "sqlite_returning";
pRet->retTrig.zName = RETURNING_TRIGGER_NAME;
pRet->retTrig.op = TK_RETURNING;
pRet->retTrig.tr_tm = TRIGGER_AFTER;
pRet->retTrig.bReturning = 1;
@@ -1291,8 +1306,8 @@ void sqlite3AddReturning(Parse *pParse, ExprList *pList){
pRet->retSel.pEList = pList;
pRet->retSel.pSrc = (SrcList*)&pRet->retSrcList;
pHash = &(db->aDb[1].pSchema->trigHash);
assert( sqlite3HashFind(pHash, RETURNING_TRIGGER)==0 );
if( sqlite3HashInsert(pHash, "sqlite_returning", &pRet->retTrig)
assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 );
if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)
==&pRet->retTrig ){
sqlite3OomFault(db);
}
+14 -4
View File
@@ -739,10 +739,14 @@ Trigger *sqlite3TriggersExist(
for(p=pList; p; p=p->pNext){
if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
mask |= p->tr_tm;
}else if( p->bReturning
&& (p->op==TK_RETURNING || (p->op!=TK_DELETE && op!=TK_DELETE)) ){
}else if( p->op==TK_RETURNING ){
/* The first time a RETURNING trigger is seen, the "op" value tells
** us what time of trigger it should be. */
p->op = op;
mask |= TRIGGER_AFTER;
}else if( p->bReturning && p->op==TK_INSERT && op==TK_UPDATE ){
/* Also fire a RETURNING trigger for INSERT on the UPDATE of an UPSERT */
mask |= TRIGGER_AFTER;
}
}
if( pMask ){
@@ -1216,13 +1220,19 @@ void sqlite3CodeRowTrigger(
assert( p->pSchema==p->pTabSchema
|| p->pSchema==pParse->db->aDb[1].pSchema );
/* Determine whether we should code this trigger */
if( (p->op==op || (p->bReturning && p->op!=TK_DELETE))
/* Determine whether we should code this trigger. One of two choices:
** 1. The trigger is an exact match to the current DML statement
** 2. This is a RETURNING trigger for INSERT but we are currently
** doing the UPDATE part of an UPSERT.
*/
if( (p->op==op || (p->bReturning && p->op==TK_INSERT && op==TK_UPDATE))
&& p->tr_tm==tr_tm
&& checkColumnOverlap(p->pColumns, pChanges)
){
u8 origOp = p->op;
p->op = op;
sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
p->op = origOp;
}
}
}