aboutsummaryrefslogtreecommitdiff
path: root/src/trigger.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2002-05-21 11:38:11 +0000
committerdrh <drh@noemail.net>2002-05-21 11:38:11 +0000
commitc977f7f5968fcffbb8f35986059f396b830e40a3 (patch)
treec545a581fea4656189fe654b5824129fc33fffcb /src/trigger.c
parentf29ce5595883df5c035b5c6b97bf07f73eef5bc5 (diff)
downloadsqlite-c977f7f5968fcffbb8f35986059f396b830e40a3.tar.gz
sqlite-c977f7f5968fcffbb8f35986059f396b830e40a3.zip
Additional code cleanup resulting from a review of the new trigger code. (CVS 572)
FossilOrigin-Name: 37dbdd551e88440933066133ec9cc1e10b03fc1a
Diffstat (limited to 'src/trigger.c')
-rw-r--r--src/trigger.c140
1 files changed, 89 insertions, 51 deletions
diff --git a/src/trigger.c b/src/trigger.c
index d0141b0eb..d26ddb9ea 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -95,32 +95,32 @@ void sqliteCreateTrigger(
** build the sqlite_master entry
*/
if( !pParse->initFlag && !tab->isTemp ){
+ static VdbeOp insertTrig[] = {
+ { OP_OpenWrite, 0, 2, MASTER_NAME},
+ { OP_NewRecno, 0, 0, 0 },
+ { OP_String, 0, 0, "trigger" },
+ { OP_String, 0, 0, 0 }, /* 3: trigger name */
+ { OP_String, 0, 0, 0 }, /* 4: table name */
+ { OP_Integer, 0, 0, 0 },
+ { OP_String, 0, 0, 0 }, /* 6: SQL */
+ { OP_MakeRecord, 5, 0, 0 },
+ { OP_PutIntKey, 0, 0, 0 },
+ { OP_Integer, 0, 0, 0 }, /* 9: Next cookie */
+ { OP_SetCookie, 0, 0, 0 },
+ { OP_Close, 0, 0, 0 },
+ };
+ int addr;
+ Vdbe *v;
/* Make an entry in the sqlite_master table */
- sqliteBeginWriteOperation(pParse);
-
- sqliteVdbeAddOp(pParse->pVdbe, OP_OpenWrite, 0, 2);
- sqliteVdbeChangeP3(pParse->pVdbe, -1, MASTER_NAME, P3_STATIC);
- sqliteVdbeAddOp(pParse->pVdbe, OP_NewRecno, 0, 0);
- sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
- sqliteVdbeChangeP3(pParse->pVdbe, -1, "trigger", P3_STATIC);
- sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
- sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->name, 0);
- sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
- sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->table, 0);
- sqliteVdbeAddOp(pParse->pVdbe, OP_Integer, 0, 0);
- sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
- sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->strings, 0);
- sqliteVdbeAddOp(pParse->pVdbe, OP_MakeRecord, 5, 0);
- sqliteVdbeAddOp(pParse->pVdbe, OP_PutIntKey, 0, 1);
-
- /* Change the cookie, since the schema is changed */
+ v = sqliteGetVdbe(pParse);
+ sqliteBeginWriteOperation(pParse, 0);
+ addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
+ sqliteVdbeChangeP3(v, addr+3, nt->name, 0);
+ sqliteVdbeChangeP3(v, addr+4, nt->table, 0);
+ sqliteVdbeChangeP3(v, addr+6, nt->strings, 0);
sqliteChangeCookie(pParse->db);
- sqliteVdbeAddOp(pParse->pVdbe, OP_Integer, pParse->db->next_cookie, 0);
- sqliteVdbeAddOp(pParse->pVdbe, OP_SetCookie, 0, 0);
-
- sqliteVdbeAddOp(pParse->pVdbe, OP_Close, 0, 0);
-
+ sqliteVdbeChangeP1(v, addr+9, pParse->db->next_cookie);
sqliteEndWriteOperation(pParse);
}
@@ -160,8 +160,14 @@ trigger_cleanup:
}
}
-TriggerStep *sqliteTriggerSelectStep(Select * pSelect)
-{
+/*
+** Turn a SELECT statement (that the pSelect parameter points to) into
+** a trigger step. Return a pointer to a TriggerStep structure.
+**
+** The parser calls this routine when it finds a SELECT statement in
+** body of a TRIGGER.
+*/
+TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
pTriggerStep->op = TK_SELECT;
@@ -171,12 +177,19 @@ TriggerStep *sqliteTriggerSelectStep(Select * pSelect)
return pTriggerStep;
}
+/*
+** Build a trigger step out of an INSERT statement. Return a pointer
+** to the new trigger step.
+**
+** The parser calls this routine when it sees an INSERT inside the
+** body of a trigger.
+*/
TriggerStep *sqliteTriggerInsertStep(
- Token *pTableName,
- IdList *pColumn,
- ExprList *pEList,
- Select *pSelect,
- int orconf
+ Token *pTableName, /* Name of the table into which we insert */
+ IdList *pColumn, /* List of columns in pTableName to insert into */
+ ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
+ Select *pSelect, /* A SELECT statement that supplies values */
+ int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
@@ -193,12 +206,17 @@ TriggerStep *sqliteTriggerInsertStep(
return pTriggerStep;
}
+/*
+** Construct a trigger step that implements an UPDATE statement and return
+** a pointer to that trigger step. The parser calls this routine when it
+** sees an UPDATE statement inside the body of a CREATE TRIGGER.
+*/
TriggerStep *sqliteTriggerUpdateStep(
- Token *pTableName,
- ExprList *pEList,
- Expr *pWhere,
- int orconf)
-{
+ Token *pTableName, /* Name of the table to be updated */
+ ExprList *pEList, /* The SET clause: list of column and new values */
+ Expr *pWhere, /* The WHERE clause */
+ int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
+){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
pTriggerStep->op = TK_UPDATE;
@@ -210,8 +228,12 @@ TriggerStep *sqliteTriggerUpdateStep(
return pTriggerStep;
}
-TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere)
-{
+/*
+** Construct a trigger step that implements a DELETE statement and return
+** a pointer to that trigger step. The parser calls this routine when it
+** sees a DELETE statement inside the body of a CREATE TRIGGER.
+*/
+TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
TriggerStep * pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
pTriggerStep->op = TK_DELETE;
@@ -328,7 +350,7 @@ void sqliteDropTrigger(Parse *pParse, Token *pName, int nested)
};
if( !nested ){
- sqliteBeginWriteOperation(pParse);
+ sqliteBeginWriteOperation(pParse, 0);
}
base = sqliteVdbeAddOpList(pParse->pVdbe,
ArraySize(dropTrigger), dropTrigger);
@@ -345,8 +367,16 @@ void sqliteDropTrigger(Parse *pParse, Token *pName, int nested)
sqliteFree(zName);
}
-static int checkColumnOverLap(IdList * pIdList, ExprList * pEList)
-{
+/*
+** pEList is the SET clause of an UPDATE statement. Each entry
+** in pEList is of the format <id>=<expr>. If any of the entries
+** in pEList have an <id> which matches an identifier in pIdList,
+** then return TRUE. If pIdList==NULL, then it is considered a
+** wildcard that matches anything. Likewise if pEList==NULL then
+** it matches anything so always return true. Return false only
+** if there is no match.
+*/
+static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
int i, e;
if( !pIdList )return 1;
if( !pEList )return 1;
@@ -378,13 +408,13 @@ int always_code_trigger_setup = 0;
* found in the list specified as pTrigger.
*/
int sqliteTriggersExist(
- Parse *pParse,
- Trigger *pTrigger,
+ Parse *pParse, /* Used to check for recursive triggers */
+ Trigger *pTrigger, /* A list of triggers associated with a table */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
int tr_tm, /* one of TK_BEFORE, TK_AFTER */
int foreach, /* one of TK_ROW or TK_STATEMENT */
- ExprList *pChanges)
-{
+ ExprList *pChanges /* Columns that change in an UPDATE statement */
+){
Trigger * pTriggerCursor;
if( always_code_trigger_setup ){
@@ -410,10 +440,14 @@ int sqliteTriggersExist(
return 0;
}
+/*
+** Generate VDBE code for zero or more statements inside the body of a
+** trigger.
+*/
static int codeTriggerProgram(
- Parse *pParse,
- TriggerStep *pStepList,
- int orconfin
+ Parse *pParse, /* The parser context */
+ TriggerStep *pStepList, /* List of statements inside the trigger body */
+ int orconfin /* Conflict algorithm. (OE_Abort, etc) */
){
TriggerStep * pTriggerStep = pStepList;
int orconf;
@@ -470,11 +504,15 @@ static int codeTriggerProgram(
**
** When the code that this function generates is executed, the following
** must be true:
-** 1. NO vdbe cursors must be open.
+**
+** 1. No cursors may be open in the main database. (But newIdx and oldIdx
+** can be indices of cursors in temporary tables. See below.)
+**
** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
** a temporary vdbe cursor (index newIdx) must be open and pointing at
** a row containing values to be substituted for new.* expressions in the
** trigger program(s).
+**
** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
** a temporary vdbe cursor (index oldIdx) must be open and pointing at
** a row containing values to be substituted for old.* expressions in the
@@ -489,8 +527,8 @@ int sqliteCodeRowTrigger(
Table *pTab, /* The table to code triggers from */
int newIdx, /* The indice of the "new" row to access */
int oldIdx, /* The indice of the "old" row to access */
- int orconf) /* ON CONFLICT policy */
-{
+ int orconf /* ON CONFLICT policy */
+){
Trigger * pTrigger;
TriggerStack * pTriggerStack;
@@ -611,7 +649,7 @@ void sqliteViewTriggers(
v = sqliteGetVdbe(pParse);
assert(v);
- sqliteBeginMultiWriteOperation(pParse);
+ sqliteBeginWriteOperation(pParse, 1);
/* Allocate temp tables */
oldIdx = pParse->nTab++;