Skip to content

Commit

Permalink
box: introduce trigger_event_manipulation enum
Browse files Browse the repository at this point in the history
This patch introduces a new trigger_event_manipulation enum
that describes a trigger event. This is the type of operation on
the associated space for which the trigger activates.
The value could be `INSERT` (a row was inserted), `DELETE`
(a row was deleted), or `UPDATE` (a row was modified).

Using the enum instead of sql-specific TK_ token identified is
an important step to introduce a trigger_def structure in
further patches.

Needed for #4343
  • Loading branch information
kshcherbatov committed Oct 14, 2019
1 parent 13b180b commit 440986c
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 51 deletions.
1 change: 1 addition & 0 deletions src/box/CMakeLists.txt
Expand Up @@ -102,6 +102,7 @@ add_library(box STATIC
fk_constraint.c
func.c
func_def.c
trigger_def.c
key_list.c
alter.cc
schema.cc
Expand Down
15 changes: 15 additions & 0 deletions src/box/sql.c
Expand Up @@ -1265,3 +1265,18 @@ vdbe_field_ref_prepare_tuple(struct vdbe_field_ref *field_ref,
vdbe_field_ref_create(field_ref, tuple, tuple_data(tuple),
tuple->bsize);
}

enum trigger_event_manipulation
trigger_event_manipulation_by_op(int op)
{
switch (op) {
case TK_DELETE:
return TRIGGER_EVENT_MANIPULATION_DELETE;
case TK_UPDATE:
return TRIGGER_EVENT_MANIPULATION_UPDATE;
case TK_INSERT:
return TRIGGER_EVENT_MANIPULATION_INSERT;
default:
unreachable();
}
}
8 changes: 8 additions & 0 deletions src/box/sql.h
Expand Up @@ -33,6 +33,7 @@

#include <stdbool.h>
#include <stdint.h>
#include "box/trigger_def.h"

#if defined(__cplusplus)
extern "C" {
Expand Down Expand Up @@ -420,6 +421,13 @@ void
vdbe_field_ref_prepare_tuple(struct vdbe_field_ref *field_ref,
struct tuple *tuple);

/**
* Convert a given OP_INSERT/OP_UPDATE/OP_DELETE operation
* to trigger_event_manipulation value.
*/
enum trigger_event_manipulation
trigger_event_manipulation_by_op(int op);

#if defined(__cplusplus)
} /* extern "C" { */
#endif
Expand Down
9 changes: 6 additions & 3 deletions src/box/sql/delete.c
Expand Up @@ -150,7 +150,8 @@ sql_table_delete_from(struct Parse *parse, struct SrcList *tab_list,
struct space *space = sql_lookup_space(parse, tab_list->a);
if (space == NULL)
goto delete_from_cleanup;
trigger_list = sql_triggers_exist(space->def, TK_DELETE,
trigger_list = sql_triggers_exist(space->def,
TRIGGER_EVENT_MANIPULATION_DELETE,
NULL, parse->sql_flags, NULL);
bool is_complex = trigger_list != NULL || fk_constraint_is_required(space, NULL);
bool is_view = space->def->opts.is_view;
Expand Down Expand Up @@ -486,7 +487,8 @@ sql_generate_row_delete(struct Parse *parse, struct space *space,

/* Invoke BEFORE DELETE trigger programs. */
int addr_start = sqlVdbeCurrentAddr(v);
vdbe_code_row_trigger(parse, trigger_list, TK_DELETE, NULL,
vdbe_code_row_trigger(parse, trigger_list,
TRIGGER_EVENT_MANIPULATION_DELETE, NULL,
TRIGGER_BEFORE, space, first_old_reg,
onconf, label);

Expand Down Expand Up @@ -540,7 +542,8 @@ sql_generate_row_delete(struct Parse *parse, struct space *space,
fk_constraint_emit_actions(parse, space, first_old_reg, NULL);

/* Invoke AFTER DELETE trigger programs. */
vdbe_code_row_trigger(parse, trigger_list, TK_DELETE, 0,
vdbe_code_row_trigger(parse, trigger_list,
TRIGGER_EVENT_MANIPULATION_DELETE, 0,
TRIGGER_AFTER, space, first_old_reg,
onconf, label);
}
Expand Down
6 changes: 4 additions & 2 deletions src/box/sql/fk_constraint.c
Expand Up @@ -897,10 +897,12 @@ fk_constraint_action_trigger(struct Parse *pParse, struct space_def *def,

if (is_update) {
fk->on_update_trigger = trigger;
trigger->op = TK_UPDATE;
trigger->event_manipulation =
TRIGGER_EVENT_MANIPULATION_UPDATE;
} else {
fk->on_delete_trigger = trigger;
trigger->op = TK_DELETE;
trigger->event_manipulation =
TRIGGER_EVENT_MANIPULATION_DELETE;
}
return trigger;
}
Expand Down
15 changes: 9 additions & 6 deletions src/box/sql/insert.c
Expand Up @@ -293,7 +293,8 @@ sqlInsert(Parse * pParse, /* Parser context */
* inserted into is a view
*/
struct space_def *space_def = space->def;
trigger = sql_triggers_exist(space_def, TK_INSERT, NULL,
trigger = sql_triggers_exist(space_def,
TRIGGER_EVENT_MANIPULATION_INSERT, NULL,
pParse->sql_flags, &tmask);

bool is_view = space_def->opts.is_view;
Expand Down Expand Up @@ -599,7 +600,8 @@ sqlInsert(Parse * pParse, /* Parser context */
sql_emit_table_types(v, space_def, regCols + 1);

/* Fire BEFORE or INSTEAD OF triggers */
vdbe_code_row_trigger(pParse, trigger, TK_INSERT, 0,
vdbe_code_row_trigger(pParse, trigger,
TRIGGER_EVENT_MANIPULATION_INSERT, 0,
TRIGGER_BEFORE, space,
regCols - space_def->field_count - 1, on_error,
endOfLoop);
Expand Down Expand Up @@ -753,7 +755,8 @@ sqlInsert(Parse * pParse, /* Parser context */

if (trigger != NULL) {
/* Code AFTER triggers */
vdbe_code_row_trigger(pParse, trigger, TK_INSERT, 0,
vdbe_code_row_trigger(pParse, trigger,
TRIGGER_EVENT_MANIPULATION_INSERT, 0,
TRIGGER_AFTER, space,
regData - 2 - space_def->field_count, on_error,
endOfLoop);
Expand Down Expand Up @@ -961,9 +964,9 @@ process_index: ;
part_count);
sql_set_multi_write(parse_context, true);
struct sql_trigger *trigger =
sql_triggers_exist(space->def, TK_DELETE, NULL,
parse_context->sql_flags,
NULL);
sql_triggers_exist(space->def,
TRIGGER_EVENT_MANIPULATION_DELETE, NULL,
parse_context->sql_flags, NULL);
sql_generate_row_delete(parse_context, space, trigger,
cursor, idx_key_reg, part_count,
true,
Expand Down
7 changes: 4 additions & 3 deletions src/box/sql/parse_def.h
Expand Up @@ -35,6 +35,7 @@
#include "box/fk_constraint.h"
#include "box/key_def.h"
#include "box/sql.h"
#include "box/trigger_def.h"

/**
* This file contains auxiliary structures and functions which
Expand Down Expand Up @@ -268,8 +269,8 @@ struct create_trigger_def {
struct create_entity_def base;
/** One of TK_BEFORE, TK_AFTER, TK_INSTEAD. */
int tr_tm;
/** One of TK_INSERT, TK_UPDATE, TK_DELETE. */
int op;
/** The trigger event: INSERT, UPDATE or DELETE. */
enum trigger_event_manipulation event_manipulation;
/** Column list if this is an UPDATE trigger. */
struct IdList *cols;
/** When clause. */
Expand Down Expand Up @@ -413,7 +414,7 @@ create_trigger_def_init(struct create_trigger_def *trigger_def,
create_entity_def_init(&trigger_def->base, ENTITY_TYPE_TRIGGER,
table_name, name, if_not_exists);
trigger_def->tr_tm = tr_tm;
trigger_def->op = op;
trigger_def->event_manipulation = trigger_event_manipulation_by_op(op);
trigger_def->cols = cols;
trigger_def->when = when;
}
Expand Down
15 changes: 9 additions & 6 deletions src/box/sql/resolve.c
Expand Up @@ -39,6 +39,7 @@
#include <stdlib.h>
#include <string.h>
#include "box/schema.h"
#include "box/trigger_def.h"

/*
* Walk the expression tree pExpr and increase the aggregate function
Expand Down Expand Up @@ -313,15 +314,17 @@ lookupName(Parse * pParse, /* The parsing context */
*/
if (zTab != NULL && cntTab == 0 &&
pParse->triggered_space != NULL) {
int op = pParse->eTriggerOp;
assert(op == TK_DELETE || op == TK_UPDATE
|| op == TK_INSERT);
enum trigger_event_manipulation event_manipulation =
pParse->trigger_event_manipulation;
struct space_def *space_def = NULL;
if (op != TK_DELETE && sqlStrICmp("new", zTab) == 0) {
if (event_manipulation !=
TRIGGER_EVENT_MANIPULATION_DELETE &&
sqlStrICmp("new", zTab) == 0) {
pExpr->iTable = 1;
space_def = pParse->triggered_space->def;
} else if (op != TK_INSERT
&& sqlStrICmp("old", zTab) == 0) {
} else if (event_manipulation !=
TRIGGER_EVENT_MANIPULATION_INSERT &&
sqlStrICmp("old", zTab) == 0) {
pExpr->iTable = 0;
space_def = pParse->triggered_space->def;
}
Expand Down
23 changes: 16 additions & 7 deletions src/box/sql/sqlInt.h
Expand Up @@ -72,6 +72,7 @@
#include "box/field_def.h"
#include "box/func.h"
#include "box/func_def.h"
#include "box/trigger_def.h"
#include "box/sql.h"
#include "box/txn.h"
#include "trivia/util.h"
Expand Down Expand Up @@ -2140,7 +2141,7 @@ struct Parse {
uint64_t oldmask;
/* Mask of new.* columns referenced. */
uint64_t newmask;
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
enum trigger_event_manipulation trigger_event_manipulation;
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
/** Region to make SQL temp allocations. */
struct region region;
Expand Down Expand Up @@ -2298,8 +2299,14 @@ struct sql_trigger {
char *zName;
/** The ID of space the trigger refers to. */
uint32_t space_id;
/** One of TK_DELETE, TK_UPDATE, TK_INSERT. */
u8 op;
/**
* The trigger event. This is the type of operation
* on the associated space for which the trigger
* activates. The value is `INSERT` (a row was inserted),
* `DELETE` (a row was deleted), or `UPDATE` (a row was
* modified).
*/
enum trigger_event_manipulation event_manipulation;
/** One of TRIGGER_BEFORE, TRIGGER_AFTER. */
u8 tr_tm;
/** The WHEN clause of the expression (may be NULL). */
Expand Down Expand Up @@ -3457,13 +3464,14 @@ vdbe_code_drop_trigger(struct Parse *parser, const char *trigger_name,
*
* @param space_def The definition of the space that contains
* the triggers.
* @param op operation one of TK_DELETE, TK_INSERT, TK_UPDATE.
* @param event_manipulation The event of the trigger to be find.
* @param changes_list Columns that change in an UPDATE statement.
* @param sql_flags SQL flags which describe how to parse request.
* @param[out] pMask Mask of TRIGGER_BEFORE|TRIGGER_AFTER
*/
struct sql_trigger *
sql_triggers_exist(struct space_def *space_def, int op,
sql_triggers_exist(struct space_def *space_def,
enum trigger_event_manipulation event_manipulation,
struct ExprList *changes_list, uint32_t sql_flags,
int *mask_ptr);

Expand Down Expand Up @@ -3512,7 +3520,7 @@ sql_triggers_exist(struct space_def *space_def, int op,
*
* @param parser Parse context.
* @param trigger List of triggers on table.
* @param op operation, one of TK_UPDATE, TK_INSERT, TK_DELETE.
* @param event_manipulation Trigger operation.
* @param changes_list Changes list for any UPDATE OF triggers.
* @param tr_tm One of TRIGGER_BEFORE, TRIGGER_AFTER.
* @param space The space to code triggers from.
Expand All @@ -3522,7 +3530,8 @@ sql_triggers_exist(struct space_def *space_def, int op,
*/
void
vdbe_code_row_trigger(struct Parse *parser, struct sql_trigger *trigger,
int op, struct ExprList *changes_list, int tr_tm,
enum trigger_event_manipulation event_manipulation,
struct ExprList *changes_list, int tr_tm,
struct space *space, int reg, int orconf, int ignore_jump);

/**
Expand Down
40 changes: 22 additions & 18 deletions src/box/sql/trigger.c
Expand Up @@ -35,6 +35,7 @@

#include "box/box.h"
#include "box/schema.h"
#include "box/trigger_def.h"
#include "sqlInt.h"
#include "tarantoolInt.h"
#include "vdbeInt.h"
Expand Down Expand Up @@ -125,9 +126,7 @@ sql_trigger_begin(struct Parse *parse)
trigger->space_id = space_id;
trigger->zName = trigger_name;
trigger_name = NULL;
assert(trigger_def->op == TK_INSERT || trigger_def->op == TK_UPDATE ||
trigger_def->op== TK_DELETE);
trigger->op = (u8) trigger_def->op;
trigger->event_manipulation = trigger_def->event_manipulation;
trigger->tr_tm = trigger_def->tr_tm;
trigger->pWhen = sqlExprDup(db, trigger_def->when, EXPRDUP_REDUCE);
trigger->pColumns = sqlIdListDup(db, trigger_def->cols);
Expand Down Expand Up @@ -530,7 +529,8 @@ checkColumnOverlap(IdList * pIdList, ExprList * pEList)
}

struct sql_trigger *
sql_triggers_exist(struct space_def *space_def, int op,
sql_triggers_exist(struct space_def *space_def,
enum trigger_event_manipulation event_manipulation,
struct ExprList *changes_list, uint32_t sql_flags,
int *mask_ptr)
{
Expand All @@ -539,8 +539,8 @@ sql_triggers_exist(struct space_def *space_def, int op,
if ((sql_flags & SQL_EnableTrigger) != 0)
trigger_list = space_trigger_list(space_def->id);
for (struct sql_trigger *p = trigger_list; p != NULL; p = p->next) {
if (p->op == op && checkColumnOverlap(p->pColumns,
changes_list) != 0)
if (p->event_manipulation == event_manipulation &&
checkColumnOverlap(p->pColumns, changes_list) != 0)
mask |= p->tr_tm;
}
if (mask_ptr != NULL)
Expand Down Expand Up @@ -755,19 +755,18 @@ sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
sNC.pParse = pSubParse;
pSubParse->triggered_space = space;
pSubParse->pToplevel = pTop;
pSubParse->eTriggerOp = trigger->op;
pSubParse->trigger_event_manipulation = trigger->event_manipulation;
pSubParse->nQueryLoop = parser->nQueryLoop;

/* Temporary VM. */
struct Vdbe *v = sqlGetVdbe(pSubParse);
if (v != NULL) {
VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
VdbeComment((v, "Start: %s.%s (%s %s ON %s)",
trigger->zName, onErrorText(orconf),
(trigger->tr_tm ==
TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
(trigger->op == TK_UPDATE ? "UPDATE" : ""),
(trigger->op == TK_INSERT ? "INSERT" : ""),
(trigger->op == TK_DELETE ? "DELETE" : ""),
trigger_event_manipulation_strs[
trigger->event_manipulation],
space->def->name));
sqlVdbeChangeP4(v, -1,
sqlMPrintf(db, "-- TRIGGER %s",
Expand Down Expand Up @@ -912,16 +911,18 @@ vdbe_code_row_trigger_direct(struct Parse *parser, struct sql_trigger *trigger,

void
vdbe_code_row_trigger(struct Parse *parser, struct sql_trigger *trigger,
int op, struct ExprList *changes_list, int tr_tm,
enum trigger_event_manipulation event_manipulation,
struct ExprList *changes_list, int tr_tm,
struct space *space, int reg, int orconf, int ignore_jump)
{
assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER);
assert((op == TK_UPDATE) == (changes_list != NULL));
assert((event_manipulation == TRIGGER_EVENT_MANIPULATION_UPDATE) ==
(changes_list != NULL));

for (struct sql_trigger *p = trigger; p != NULL; p = p->next) {
/* Determine whether we should code trigger. */
if (p->op == op && p->tr_tm == tr_tm &&
if (p->event_manipulation == event_manipulation &&
p->tr_tm == tr_tm &&
checkColumnOverlap(p->pColumns, changes_list)) {
vdbe_code_row_trigger_direct(parser, p, space, reg,
orconf, ignore_jump);
Expand All @@ -934,13 +935,16 @@ sql_trigger_colmask(Parse *parser, struct sql_trigger *trigger,
ExprList *changes_list, int new, int tr_tm,
struct space *space, int orconf)
{
const int op = changes_list != NULL ? TK_UPDATE : TK_DELETE;
enum trigger_event_manipulation event_manipulation =
changes_list != NULL ? TRIGGER_EVENT_MANIPULATION_UPDATE :
TRIGGER_EVENT_MANIPULATION_DELETE;
uint64_t mask = 0;

assert(new == 1 || new == 0);
for (struct sql_trigger *p = trigger; p != NULL; p = p->next) {
if (p->op == op && (tr_tm & p->tr_tm)
&& checkColumnOverlap(p->pColumns, changes_list)) {
if (p->event_manipulation == event_manipulation &&
(tr_tm & p->tr_tm) &&
checkColumnOverlap(p->pColumns, changes_list)) {
TriggerPrg *prg =
sql_row_trigger(parser, p, space, orconf);
if (prg != NULL)
Expand Down

0 comments on commit 440986c

Please sign in to comment.