1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Additional code cleanup resulting from a review of the new trigger code. (CVS 572)

FossilOrigin-Name: 37dbdd551e88440933066133ec9cc1e10b03fc1a
This commit is contained in:
drh
2002-05-21 11:38:11 +00:00
parent f29ce55958
commit c977f7f596
10 changed files with 185 additions and 148 deletions

View File

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