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

Reply via email to