Пример #1
0
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;
}
Пример #2
0
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++;
}
Пример #3
0
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;
}