Changeset: e5e39c80efa4 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e5e39c80efa4
Modified Files:
sql/backends/monet5/sql.c
sql/backends/monet5/sql_cat.c
sql/server/rel_psm.c
Branch: Jul2021
Log Message:
Replace triggers on the backend
diffs (209 lines):
diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -5890,7 +5890,7 @@ static mel_func sql_init_funcs[] = {
pattern("sqlcatalog", "drop_index", SQLdrop_index, false, "Catalog operation
drop_index", args(0,3, arg("sname",str),arg("iname",str),arg("action",int))),
pattern("sqlcatalog", "drop_function", SQLdrop_function, false, "Catalog
operation drop_function", args(0,5,
arg("sname",str),arg("fname",str),arg("fid",int),arg("type",int),arg("action",int))),
pattern("sqlcatalog", "create_function", SQLcreate_function, false, "Catalog
operation create_function", args(0,4,
arg("sname",str),arg("fname",str),arg("fcn",ptr),arg("replace",int))),
- pattern("sqlcatalog", "create_trigger", SQLcreate_trigger, false, "Catalog
operation create_trigger", args(0,10,
arg("sname",str),arg("tname",str),arg("triggername",str),arg("time",int),arg("orientation",int),arg("event",int),arg("old",str),arg("new",str),arg("cond",str),arg("qry",str))),
+ pattern("sqlcatalog", "create_trigger", SQLcreate_trigger, false, "Catalog
operation create_trigger", args(0,11,
arg("sname",str),arg("tname",str),arg("triggername",str),arg("time",int),arg("orientation",int),arg("event",int),arg("old",str),arg("new",str),arg("cond",str),arg("qry",str),arg("replace",int))),
pattern("sqlcatalog", "drop_trigger", SQLdrop_trigger, false, "Catalog
operation drop_trigger", args(0,3,
arg("sname",str),arg("nme",str),arg("ifexists",int))),
pattern("sqlcatalog", "alter_add_table", SQLalter_add_table, false, "Catalog
operation alter_add_table", args(0,5,
arg("sname",str),arg("mtnme",str),arg("psnme",str),arg("ptnme",str),arg("action",int))),
pattern("sqlcatalog", "alter_del_table", SQLalter_del_table, false, "Catalog
operation alter_del_table", args(0,5,
arg("sname",str),arg("mtnme",str),arg("psnme",str),arg("ptnme",str),arg("action",int))),
diff --git a/sql/backends/monet5/sql_cat.c b/sql/backends/monet5/sql_cat.c
--- a/sql/backends/monet5/sql_cat.c
+++ b/sql/backends/monet5/sql_cat.c
@@ -524,23 +524,37 @@ alter_table_set_access(mvc *sql, char *s
}
static char *
-create_trigger(mvc *sql, char *sname, char *tname, char *triggername, int
time, int orientation, int event, char *old_name, char *new_name, char
*condition, char *query)
+create_trigger(mvc *sql, char *sname, char *tname, char *triggername, int
time, int orientation, int event, char *old_name, char *new_name, char
*condition, char *query, int replace)
{
- sql_trigger *tri = NULL;
+ sql_trigger *tri = NULL, *other = NULL;
sql_schema *s = NULL;
sql_table *t;
+ const char *base = replace ? "CREATE OR REPLACE TRIGGER" : "CREATE
TRIGGER";
if (!(s = mvc_bind_schema(sql, sname)))
- throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "CREATE TRIGGER:
no such schema '%s'", sname);
+ throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "%s: no such
schema '%s'", base, sname);
if (!mvc_schema_privs(sql, s))
- throw(SQL,"sql.create_trigger",SQLSTATE(42000) "CREATE TRIGGER:
access denied for %s to schema '%s'", get_string_global_var(sql,
"current_user"), s->base.name);
- if (mvc_bind_trigger(sql, s, triggername))
- throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "CREATE TRIGGER:
name '%s' already in use", triggername);
+ throw(SQL,"sql.create_trigger",SQLSTATE(42000) "%s: access
denied for %s to schema '%s'", base, get_string_global_var(sql,
"current_user"), s->base.name);
+ if ((other = mvc_bind_trigger(sql, s, triggername)) && !replace)
+ throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "%s: name '%s'
already in use", base, triggername);
if (!(t = mvc_bind_table(sql, s, tname)))
- throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "CREATE TRIGGER:
unknown table '%s'", tname);
+ throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "%s: unknown
table '%s'", base, tname);
if (isView(t))
- throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "CREATE TRIGGER:
cannot create trigger on view '%s'", tname);
+ throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "%s: cannot
create trigger on view '%s'", base, tname);
+ if (replace && other) {
+ if (other->t->base.id != t->base.id) /* defensive line */
+ throw(SQL,"sql.create_trigger",SQLSTATE(3F000) "%s: the
to be replaced trigger '%s' is not from table '%s'", base, triggername, tname);
+ switch (mvc_drop_trigger(sql, s, other)) {
+ case -1:
+ throw(SQL,"sql.create_trigger", SQLSTATE(HY013)
MAL_MALLOC_FAIL);
+ case -2:
+ case -3:
+ throw(SQL,"sql.create_trigger", SQLSTATE(42000)
"%s: transaction conflict detected", base);
+ default:
+ break;
+ }
+ }
if ((tri = mvc_create_trigger(sql, t, triggername, time, orientation,
event, old_name, new_name, condition, query))) {
char *buf;
sql_rel *r = NULL;
@@ -575,7 +589,7 @@ create_trigger(mvc *sql, char *sname, ch
throw(SQL, "sql.create_trigger",
SQLSTATE(42000) "%s", sql->errstr);
}
} else {
- throw(SQL,"sql.create_trigger", SQLSTATE(42000) "CREATE
TRIGGER: transaction conflict detected");
+ throw(SQL,"sql.create_trigger", SQLSTATE(42000) "%s:
transaction conflict detected", base);
}
return MAL_SUCCEED;
}
@@ -942,17 +956,17 @@ create_func(mvc *sql, char *sname, char
sql_subfunc *sf;
sql_schema *s = NULL;
int clientid = sql->clientid, res = 0;
- char *F = NULL, *fn = NULL;
+ char *F = NULL, *fn = NULL, *base = replace ? "CREATE OR REPLACE" :
"CREATE";
FUNC_TYPE_STR(f->type, F, fn)
(void) fn;
if (!(s = mvc_bind_schema(sql, sname)))
- throw(SQL,"sql.create_func", SQLSTATE(3F000) "CREATE %s: no
such schema '%s'", F, sname);
+ throw(SQL,"sql.create_func", SQLSTATE(3F000) "%s %s: no such
schema '%s'", base, F, sname);
if (!mvc_schema_privs(sql, s))
- throw(SQL,"sql.create_func", SQLSTATE(42000) "CREATE %s: access
denied for %s to schema '%s'", F, get_string_global_var(sql, "current_user"),
s->base.name);
+ throw(SQL,"sql.create_func", SQLSTATE(42000) "%s %s: access
denied for %s to schema '%s'", base, F, get_string_global_var(sql,
"current_user"), s->base.name);
if (strlen(fname) >= IDLENGTH)
- throw(SQL,"sql.create_func", SQLSTATE(42000) "CREATE %s: name
'%s' too large for the backend", F, fname);
+ throw(SQL,"sql.create_func", SQLSTATE(42000) "%s %s: name '%s'
too large for the backend", base, F, fname);
if (replace) {
list *tl = sa_list(sql->sa);
@@ -970,7 +984,7 @@ create_func(mvc *sql, char *sname, char
char *fimp = NULL;
if (!sff->s || sff->system)
- throw(SQL,"sql.create_func", SQLSTATE(42000)
"CREATE OR REPLACE %s: not allowed to replace system %s %s;", F, fn,
sff->base.name);
+ throw(SQL,"sql.create_func", SQLSTATE(42000)
"%s %s: not allowed to replace system %s %s;", base, F, fn, sff->base.name);
if (sff->lang == FUNC_LANG_MAL &&
!mal_function_find_implementation_address(&fimp, sql, sff)) {
backend_ok = false;
@@ -993,13 +1007,13 @@ create_func(mvc *sql, char *sname, char
_DELETE(fimp);
if (mvc_check_dependency(sql, sff->base.id,
!IS_PROC(sff) ? FUNC_DEPENDENCY : PROC_DEPENDENCY, NULL))
- throw(SQL,"sql.create_func", SQLSTATE(42000)
"CREATE OR REPLACE %s: there are database objects dependent on %s %s;", F, fn,
sff->base.name);
+ throw(SQL,"sql.create_func", SQLSTATE(42000)
"%s %s: there are database objects dependent on %s %s;", base, F, fn,
sff->base.name);
switch ((res = mvc_drop_func(sql, s, sff, 0))) {
case -1:
throw(SQL,"sql.create_func",
SQLSTATE(HY013) MAL_MALLOC_FAIL);
case -2:
case -3:
- throw(SQL,"sql.create_func",
SQLSTATE(42000) "CREATE OR REPLACE %s: transaction conflict detected", F);
+ throw(SQL,"sql.create_func",
SQLSTATE(42000) "%s %s: transaction conflict detected", base, F);
default:
break;
}
@@ -1010,12 +1024,12 @@ create_func(mvc *sql, char *sname, char
}
if (!(nf = mvc_create_func(sql, NULL, s, f->base.name, f->ops, f->res,
f->type, f->lang, f->mod, f->imp, f->query, f->varres, f->vararg, f->system)))
- throw(SQL,"sql.create_func", SQLSTATE(42000) "CREATE %s:
transaction conflict detected", F);
+ throw(SQL,"sql.create_func", SQLSTATE(42000) "%s %s:
transaction conflict detected", base, F);
switch (nf->lang) {
case FUNC_LANG_INT:
case FUNC_LANG_MAL: /* shouldn't be reachable, but leave it here */
if (!backend_resolve_function(&clientid, nf))
- throw(SQL,"sql.create_func", SQLSTATE(3F000) "CREATE
%s: external name %s.%s not bound", F, nf->mod, nf->base.name);
+ throw(SQL,"sql.create_func", SQLSTATE(3F000) "%s %s:
external name %s.%s not bound", base, F, nf->mod, nf->base.name);
if (nf->query == NULL)
break;
/* fall through */
@@ -1828,12 +1842,13 @@ SQLcreate_trigger(Client cntxt, MalBlkPt
char *new_name = *getArgReference_str(stk, pci, 8);
char *condition = *getArgReference_str(stk, pci, 9);
char *query = *getArgReference_str(stk, pci, 10);
+ int replace = *getArgReference_int(stk, pci, 11);
initcontext();
old_name=(strNil(old_name))?NULL:old_name;
new_name=(strNil(new_name))?NULL:new_name;
condition=(strNil(condition))?NULL:condition;
- msg = create_trigger(sql, sname, tname, triggername, time, orientation,
event, old_name, new_name, condition, query);
+ msg = create_trigger(sql, sname, tname, triggername, time, orientation,
event, old_name, new_name, condition, query, replace);
return msg;
}
diff --git a/sql/server/rel_psm.c b/sql/server/rel_psm.c
--- a/sql/server/rel_psm.c
+++ b/sql/server/rel_psm.c
@@ -1158,7 +1158,7 @@ rel_drop_all_func(mvc *sql, dlist *qname
}
static sql_rel *
-rel_create_trigger(mvc *sql, const char *sname, const char *tname, const char
*triggername, int time, int orientation, int event, const char *old_name, const
char *new_name, symbol *condition, const char *query)
+rel_create_trigger(mvc *sql, const char *sname, const char *tname, const char
*triggername, int time, int orientation, int event, const char *old_name, const
char *new_name, symbol *condition, const char *query, int replace)
{
sql_rel *rel = rel_create(sql->sa);
list *exps = new_exp_list(sql->sa);
@@ -1176,6 +1176,7 @@ rel_create_trigger(mvc *sql, const char
(void)condition;
append(exps, exp_atom_str(sql->sa, NULL, sql_bind_localtype("str") ));
append(exps, exp_atom_str(sql->sa, query, sql_bind_localtype("str") ));
+ append(exps, exp_atom_int(sql->sa, replace));
rel->l = NULL;
rel->r = NULL;
rel->op = op_ddl;
@@ -1207,7 +1208,6 @@ create_trigger(sql_query *query, dlist *
int create = (!instantiate && sql->emode != m_deps), event, orientation;
sql_schema *ss = cur_schema(sql), *old_schema = cur_schema(sql);
sql_table *t = NULL;
- sql_trigger *st = NULL;
list *sq = NULL;
sql_rel *r = NULL;
char *q, *base = replace ? "CREATE OR REPLACE TRIGGER" : "CREATE
TRIGGER";
@@ -1243,21 +1243,8 @@ create_trigger(sql_query *query, dlist *
return sql_error(sql, 02, SQLSTATE(42000) "%s: access
denied for %s to schema '%s'", base, get_string_global_var(sql,
"current_user"), ss->base.name);
if (isView(t))
return sql_error(sql, 02, SQLSTATE(42000) "%s: cannot
create trigger on view '%s'", base, tname);
- if ((st = mvc_bind_trigger(sql, ss, triggername)) != NULL) {
- if (replace) {
- switch (mvc_drop_trigger(sql, ss, st)) {
- case -1:
- return sql_error(sql, 02,
SQLSTATE(HY013) "%s: %s", base, MAL_MALLOC_FAIL);
- case -2:
- case -3:
- return sql_error(sql, 02,
SQLSTATE(42000) "%s: transaction conflict detected", base);
- default:
- break;
- }
- } else {
- return sql_error(sql, 02, SQLSTATE(42000) "%s:
name '%s' already in use", base, triggername);
- }
- }
+ if (!replace && mvc_bind_trigger(sql, ss, triggername) != NULL)
+ return sql_error(sql, 02, SQLSTATE(42000) "%s: name
'%s' already in use", base, triggername);
switch (trigger_event->token) {
case SQL_INSERT: {
if (old_name)
@@ -1290,8 +1277,7 @@ create_trigger(sql_query *query, dlist *
assert(triggered_action->h->type == type_int);
orientation = triggered_action->h->data.i_val;
q = query_cleaned(sql->ta, QUERY(sql->scanner));
- r = rel_create_trigger(sql, t->s->base.name, t->base.name,
triggername, time, orientation, event, old_name, new_name, condition, q);
- return r;
+ return rel_create_trigger(sql, t->s->base.name, t->base.name,
triggername, time, orientation, event, old_name, new_name, condition, q,
replace);
}
if (!instantiate) {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list