sql_rel * stack_find_rel_var(mvc *sql, const char *name) { int i; for (i = sql->topvars-1; i >= 0; i--) { if (!sql->vars[i].frame && !sql->vars[i].view && sql->vars[i].rel && strcmp(sql->vars[i].name, name)==0) return rel_dup(sql->vars[i].rel); } return NULL; }
void stack_push_rel_var(mvc *sql, char *name, sql_rel *var, sql_subtype *type) { if (sql->topvars == sql->sizevars) { sql->sizevars <<= 1; sql->vars = RENEW_ARRAY(sql_var,sql->vars,sql->sizevars); } sql->vars[sql->topvars].s = rel_dup(var); sql->vars[sql->topvars].name = _STRDUP(name); sql->vars[sql->topvars].value.vtype = 0; sql->vars[sql->topvars].type = *type; assert(sql->vars[sql->topvars].type.comp_type != NULL); sql->vars[sql->topvars].view = 0; sql->topvars++; }
static sql_rel * create_trigger(mvc *sql, dlist *qname, int time, symbol *trigger_event, dlist *tqname, dlist *opt_ref, dlist *triggered_action, int replace) { const char *triggerschema = qname_schema(qname); const char *triggername = qname_table(qname); const char *sname = qname_schema(tqname); const char *tname = qname_table(tqname); sql_schema *ss = cur_schema(sql); sql_table *t = NULL; sql_trigger *st = NULL; int instantiate = (sql->emode == m_instantiate); int create = (!instantiate && sql->emode != m_deps), event, orientation; list *sq = NULL; sql_rel *r = NULL; char *q, *base = replace ? "CREATE OR REPLACE" : "CREATE"; dlist *columns = trigger_event->data.lval; const char *old_name = NULL, *new_name = NULL; dlist *stmts = triggered_action->h->next->next->data.lval; symbol *condition = triggered_action->h->next->data.sym; if (!sname) sname = ss->base.name; if (sname && !(ss = mvc_bind_schema(sql, sname))) return sql_error(sql, 02, SQLSTATE(3F000) "%s TRIGGER: no such schema '%s'", base, sname); if (opt_ref) { dnode *dl = opt_ref->h; for ( ; dl; dl = dl->next) { /* list (new(1)/old(0)), char */ char *n = dl->data.lval->h->next->data.sval; assert(dl->data.lval->h->type == type_int); if (!dl->data.lval->h->data.i_val) /*?l_val?*/ old_name = n; else new_name = n; } } if (create && !mvc_schema_privs(sql, ss)) return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: access denied for %s to schema ;'%s'", base, stack_get_string(sql, "current_user"), ss->base.name); if (create && !(t = mvc_bind_table(sql, ss, tname))) return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: unknown table '%s'", base, tname); if (create && isView(t)) return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: cannot create trigger on view '%s'", base, tname); if (triggerschema && strcmp(triggerschema, sname) != 0) return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: trigger and respective table must belong to the same schema", base); if (create && (st = mvc_bind_trigger(sql, ss, triggername)) != NULL) { if (replace) { if(mvc_drop_trigger(sql, ss, st)) return sql_error(sql, 02, SQLSTATE(HY001) "%s TRIGGER: %s", base, MAL_MALLOC_FAIL); } else { return sql_error(sql, 02, SQLSTATE(42000) "%s TRIGGER: name '%s' already in use", base, triggername); } } if (create) { switch (trigger_event->token) { case SQL_INSERT: event = 0; break; case SQL_DELETE: event = 1; break; case SQL_TRUNCATE: event = 3; break; default: event = 2; break; } orientation = triggered_action->h->data.i_val; q = query_cleaned(QUERY(sql->scanner)); assert(triggered_action->h->type == type_int); r = rel_create_trigger(sql, t->s->base.name, t->base.name, triggername, time, orientation, event, old_name, new_name, condition, q); GDKfree(q); return r; } if (!instantiate) { t = mvc_bind_table(sql, ss, tname); if(!stack_push_frame(sql, "OLD-NEW")) return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL); /* we need to add the old and new tables */ if (!instantiate && new_name) { if(!_stack_push_table(sql, new_name, t)) return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL); } if (!instantiate && old_name) { if(!_stack_push_table(sql, old_name, t)) return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL); } } if (condition) { sql_rel *rel = NULL; if (new_name) /* in case of updates same relations is available via both names */ rel = stack_find_rel_view(sql, new_name); if (!rel && old_name) rel = stack_find_rel_view(sql, old_name); if (rel) rel = rel_logical_exp(sql, rel, condition, sql_where); if (!rel) return NULL; /* transition tables */ /* insert: rel_select(table [new], searchcondition) */ /* delete: rel_select(table [old], searchcondition) */ /* update: rel_select(table [old,new]), searchcondition) */ if (new_name) stack_update_rel_view(sql, new_name, rel); if (old_name) stack_update_rel_view(sql, old_name, new_name?rel_dup(rel):rel); } sq = sequential_block(sql, NULL, NULL, stmts, NULL, 1); r = rel_psm_block(sql->sa, sq); /* todo trigger_columns */ (void)columns; return r; }