Пример #1
0
static int 
keyword_or_ident(mvc * c, int cur)
{
	struct scanner *lc = &c->scanner;
	keyword *k = NULL;
	int s;

	lc->started = 1;
	utf8_putchar(lc, cur);
	s = lc->yycur;
	lc->yyval = IDENT;
	while ((cur = scanner_getc(lc)) != EOF) {
		if (!iswalnum(cur) && cur != '_') {
			utf8_putchar(lc, cur);
			(void)scanner_token(lc, IDENT);
			k = find_keyword_bs(lc,s);
			if (k) 
				lc->yyval = k->token;
			/* find keyword in SELECT/JOIN/UNION FUNCTIONS */
			else if (sql_find_func(c->sa, cur_schema(c), lc->rs->buf+lc->rs->pos+s, -1, F_FILT, NULL)) 
				lc->yyval = FILTER_FUNC;
			return lc->yyval;
		}
	}
	(void)scanner_token(lc, IDENT);
	k = find_keyword_bs(lc,s);
	if (k) 
		lc->yyval = k->token;
	/* find keyword in SELECT/JOIN/UNION FUNCTIONS */
	else if (sql_find_func(c->sa, cur_schema(c), lc->rs->buf+lc->rs->pos+s, -1, F_FILT, NULL)) 
		lc->yyval = FILTER_FUNC;
	return lc->yyval;
}
Пример #2
0
static sql_rel* 
rel_drop_all_func(mvc *sql, dlist *qname, int drop_action, int type)
{
	char *name = qname_table(qname);
	char *sname = qname_schema(qname);
	sql_schema *s = NULL;
	list * list_func = NULL; 

	char is_aggr = (type == F_AGGR);
	char is_func = (type != F_PROC);
	char *F = is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE");
	char *f = is_aggr?"aggregate":(is_func?"function":"procedure");
	char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";
	char *kf = type==F_FILT?"filter ": type==F_UNION?"union ": "";

	if (sname && !(s = mvc_bind_schema(sql, sname)))
		return sql_error(sql, 02, "3F000!DROP %s%s: no such schema '%s'", KF, F, sname);

	if (s == NULL) 
		s =  cur_schema(sql);
	
	list_func = schema_bind_func(sql, s, name, type);
	if (!list_func) 
		return sql_error(sql, 02, "DROP ALL %s%s: no such %s%s '%s'", KF, F, kf, f, name);
	list_destroy(list_func);
	return rel_drop_function(sql->sa, s->base.name, name, -1, type, drop_action);
}
Пример #3
0
static sql_exp *
rel_psm_declare_table(mvc *sql, dnode *n)
{
	sql_rel *rel = NULL, *baset = NULL;
	dlist *qname = n->next->data.lval;
	const char *name = qname_table(qname);
	const char *sname = qname_schema(qname);
	sql_table *t;

	if (sname)  /* not allowed here */
		return sql_error(sql, 02, SQLSTATE(42000) "DECLARE TABLE: qualified name not allowed");
	if (frame_find_var(sql, name))
		return sql_error(sql, 01, SQLSTATE(42000) "Variable '%s' already declared", name);

	assert(n->next->next->next->type == type_int);
	rel = rel_create_table(sql, cur_schema(sql), SQL_DECLARED_TABLE, NULL, name, n->next->next->data.sym,
			n->next->next->next->data.i_val, NULL, NULL, NULL, false, NULL, 0);

	if (!rel)
		return NULL;
	if(rel->op == op_ddl) {
		baset = rel;
	} else if(rel->op == op_insert) {
		baset = rel->l;
	} else {
		return NULL;
	}
	if(baset->flag != DDL_CREATE_TABLE)
		return NULL;
	t = (sql_table*)((atom*)((sql_exp*)baset->exps->t->data)->l)->data.val.pval;
	if(!stack_push_table(sql, name, baset, t))
		return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
	return exp_table(sql->sa, sa_strdup(sql->sa, name), t, sql->frame);
}
Пример #4
0
static sql_exp *
rel_psm_declare_table(mvc *sql, dnode *n)
{
	sql_rel *rel = NULL;
	dlist *qname = n->next->data.lval;
	char *name = qname_table(qname);
	char *sname = qname_schema(qname);
	sql_table *t;

	if (sname)  /* not allowed here */
		return sql_error(sql, 02, "DECLARE TABLE: qualified name not allowed");
	if (frame_find_var(sql, name)) 
		return sql_error(sql, 01, "Variable '%s' already declared", name);
	
	assert(n->next->next->next->type == type_int);
	
	rel = rel_create_table(sql, cur_schema(sql), SQL_DECLARED_TABLE, NULL, name, n->next->next->data.sym, n->next->next->next->data.i_val, NULL);

	if (!rel || rel->op != op_ddl || rel->flag != DDL_CREATE_TABLE)
		return NULL;

	t = (sql_table*)((atom*)((sql_exp*)rel->exps->t->data)->l)->data.val.pval;
	stack_push_table(sql, name, rel, t);
	return exp_table(sql->sa, sa_strdup(sql->sa, name), t, sql->frame);
}
Пример #5
0
static sql_rel* 
rel_drop_func(mvc *sql, dlist *qname, dlist *typelist, int drop_action, int type, int if_exists)
{
	const char *name = qname_table(qname);
	const char *sname = qname_schema(qname);
	sql_schema *s = NULL;
	sql_func *func = NULL;

	char is_aggr = (type == F_AGGR);
	char is_func = (type != F_PROC);
	char *F = is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE");
	char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";

	if (sname && !(s = mvc_bind_schema(sql, sname)))
		return sql_error(sql, 02, SQLSTATE(3F000) "DROP %s%s: no such schema '%s'", KF, F, sname);

	if (s == NULL) 
		s =  cur_schema(sql);
	
	func = resolve_func(sql, s, name, typelist, type, "DROP", if_exists);
	if (!func && !sname) {
		s = tmp_schema(sql);
		func = resolve_func(sql, s, name, typelist, type, "DROP", if_exists);
	}
	if (func)
		return rel_drop_function(sql->sa, s->base.name, name, func->base.id, type, drop_action);
	else if(if_exists && !sql->session->status)
		return rel_drop_function(sql->sa, s->base.name, name, -2, type, drop_action);
	return NULL;
}
Пример #6
0
static sql_rel *
drop_trigger(mvc *sql, dlist *qname)
{
	char *tname = qname_table(qname);
	sql_schema *ss = cur_schema(sql);

	if (!schema_privs(sql->role_id, ss)) 
		return sql_error(sql, 02, "DROP TRIGGER: access denied for %s to schema ;'%s'", stack_get_string(sql, "current_user"), ss->base.name);
	return rel_drop_trigger(sql, ss->base.name, tname);
}
Пример #7
0
static sql_rel *
drop_trigger(mvc *sql, dlist *qname, int if_exists)
{
	const char *sname = qname_schema(qname);
	const char *tname = qname_table(qname);
	sql_schema *ss = cur_schema(sql);

	if (!sname)
		sname = ss->base.name;

	if (sname && !(ss = mvc_bind_schema(sql, sname)))
		return sql_error(sql, 02, SQLSTATE(3F000) "DROP TRIGGER: no such schema '%s'", sname);

	if (!mvc_schema_privs(sql, ss)) 
		return sql_error(sql, 02, SQLSTATE(3F000) "DROP TRIGGER: access denied for %s to schema ;'%s'", stack_get_string(sql, "current_user"), ss->base.name);
	return rel_drop_trigger(sql, ss->base.name, tname, if_exists);
}
Пример #8
0
static sql_rel* 
rel_drop_func(mvc *sql, dlist *qname, dlist *typelist, int drop_action, int type)
{
	char *name = qname_table(qname);
	char *sname = qname_schema(qname);
	sql_schema *s = NULL;
	list * list_func = NULL, *type_list = NULL; 
	sql_subfunc *sub_func = NULL;
	sql_func *func = NULL;

	char is_aggr = (type == F_AGGR);
	char is_func = (type != F_PROC);
	char *F = is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE");
	char *f = is_aggr?"aggregate":(is_func?"function":"procedure");
	char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";
	char *kf = type==F_FILT?"filter ": type==F_UNION?"union ": "";

	if (sname && !(s = mvc_bind_schema(sql, sname)))
		return sql_error(sql, 02, "3F000!DROP %s%s: no such schema '%s'", KF, F, sname);

	if (s == NULL) 
		s =  cur_schema(sql);
	
	if (typelist) {	
		type_list = create_type_list(sql, typelist, 0);
		sub_func = sql_bind_func_(sql->sa, s, name, type_list, type);
		if (!sub_func && type == F_FUNC) {
			sub_func = sql_bind_func_(sql->sa, s, name, type_list, F_UNION);
			type = sub_func?F_UNION:F_FUNC;
		}
		if (!sub_func && !sname) {
			s = tmp_schema(sql);
			sub_func = sql_bind_func_(sql->sa, s, name, type_list, type);
			if (!sub_func && type == F_FUNC) {
				sub_func = sql_bind_func_(sql->sa, s, name, type_list, F_UNION);
				type = sub_func?F_UNION:F_FUNC;
			}
		}
		if ( sub_func && sub_func->func->type == type)
			func = sub_func->func;
	} else {
		list_func = schema_bind_func(sql,s,name, type);
		if (!list_func && type == F_FUNC) 
			list_func = schema_bind_func(sql,s,name, F_UNION);
		if (list_func && list_func->cnt > 1) {
			list_destroy(list_func);
			return sql_error(sql, 02, "DROP %s%s: there are more than one %s%s called '%s', please use the full signature", KF, F, kf, f,name);
		}
		if (list_func && list_func->cnt == 1)
			func = (sql_func*) list_func->h->data;
	}
	
	if (!func) { 
		if (typelist) {
			char *arg_list = NULL;
			node *n;
			
			if (type_list->cnt > 0) {
				for (n = type_list->h; n; n = n->next) {
					char *tpe =  subtype2string((sql_subtype *) n->data);
				
					if (arg_list) {
						arg_list = sql_message("%s, %s", arg_list, tpe);
						_DELETE(tpe);	
					} else {
						arg_list = tpe;
					}
				}
				list_destroy(list_func);
				list_destroy(type_list);
				return sql_error(sql, 02, "DROP %s%s: no such %s%s '%s' (%s)", KF, F, kf, f, name, arg_list);
			}
			list_destroy(list_func);
			list_destroy(type_list);
			return sql_error(sql, 02, "DROP %s%s: no such %s%s '%s' ()", KF, F, kf, f, name);

		} else {
			return sql_error(sql, 02, "DROP %s%s: no such %s%s '%s'", KF, F, kf, f, name);
		}
	} else if (((is_func && type != F_FILT) && !func->res) || 
		   (!is_func && func->res)) {
		list_destroy(list_func);
		list_destroy(type_list);
		return sql_error(sql, 02, "DROP %s%s: cannot drop %s '%s'", KF, F, is_func?"procedure":"function", name);
	}

	list_destroy(list_func);
	list_destroy(type_list);
	return rel_drop_function(sql->sa, s->base.name, name, func->base.id, type, drop_action);
}
Пример #9
0
static sql_rel *
rel_create_func(mvc *sql, dlist *qname, dlist *params, symbol *res, dlist *ext_name, dlist *body, int type, int lang)
{
	char *fname = qname_table(qname);
	char *sname = qname_schema(qname);
	sql_schema *s = NULL;
	sql_func *f = NULL;
	sql_subfunc *sf;
	dnode *n;
	list *type_list = NULL, *restype = NULL;
	int instantiate = (sql->emode == m_instantiate);
	int deps = (sql->emode == m_deps);
	int create = (!instantiate && !deps);
	bit vararg = FALSE;

	char is_table = (res && res->token == SQL_TABLE);
	char is_aggr = (type == F_AGGR);
	char is_func = (type != F_PROC);
	char *F = is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE");
	char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";

	assert(res || type == F_PROC || type == F_FILT);

	if (is_table)
		type = F_UNION;

	if (STORE_READONLY && create) 
		return sql_error(sql, 06, "schema statements cannot be executed on a readonly database.");
			
	if (sname && !(s = mvc_bind_schema(sql, sname)))
		return sql_error(sql, 02, "3F000!CREATE %s%s: no such schema '%s'", KF, F, sname);
	if (s == NULL)
		s = cur_schema(sql);

	type_list = create_type_list(sql, params, 1);
	if ((sf = sql_bind_func_(sql->sa, s, fname, type_list, type)) != NULL && create) {
		if (params) {
			char *arg_list = NULL;
			node *n;
			
			for (n = type_list->h; n; n = n->next) {
				char *tpe =  subtype2string((sql_subtype *) n->data);
				
				if (arg_list) {
					arg_list = sql_message("%s, %s", arg_list, tpe);
					_DELETE(tpe);	
				} else {
					arg_list = tpe;
				}
			}
			(void)sql_error(sql, 02, "CREATE %s%s: name '%s' (%s) already in use", KF, F, fname, arg_list);
			_DELETE(arg_list);
			list_destroy(type_list);
			return NULL;
		} else {
			list_destroy(type_list);
			return sql_error(sql, 02, "CREATE %s%s: name '%s' already in use", KF, F, fname);
		}
	} else {
		list_destroy(type_list);
		if (create && !schema_privs(sql->role_id, s)) {
			return sql_error(sql, 02, "CREATE %s%s: insufficient privileges "
					"for user '%s' in schema '%s'", KF, F,
					stack_get_string(sql, "current_user"), s->base.name);
		} else {
			char *q = QUERY(sql->scanner);
			list *l = NULL;

		 	if (params) {
				for (n = params->h; n; n = n->next) {
					dnode *an = n->data.lval->h;
					sql_add_param(sql, an->data.sval, &an->next->data.typeval);
				}
				l = sql->params;
				if (l && list_length(l) == 1) {
					sql_arg *a = l->h->data;

					if (strcmp(a->name, "*") == 0) {
						l = NULL;
						vararg = TRUE;
					}
				}
			}
			if (!l)
				l = sa_list(sql->sa);
			if (res) {
				restype = result_type(sql, res);
				if (!restype)
					return sql_error(sql, 01,
							"CREATE %s%s: failed to get restype", KF, F);
			}
			if (body && lang > FUNC_LANG_SQL) {
				char *lang_body = body->h->data.sval;
				char *mod = 	(lang == FUNC_LANG_R)?"rapi":
						(lang == FUNC_LANG_C)?"capi":
						(lang == FUNC_LANG_J)?"japi":"unknown";
				sql->params = NULL;
				if (create) {
					f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang,  mod, fname, lang_body, FALSE, vararg);
				} else if (!sf) {
					return sql_error(sql, 01, "CREATE %s%s: R function %s.%s not bound", KF, F, s->base.name, fname );
				} else {
					sql_func *f = sf->func;
					f->mod = _STRDUP("rapi");
					f->imp = _STRDUP("eval");
					if (res && restype)
						f->res = restype;
					f->sql = 0; /* native */
					f->lang = FUNC_LANG_INT;
				}
			} else if (body) {
				sql_arg *ra = (restype && !is_table)?restype->h->data:NULL;
				list *b = NULL;
				sql_schema *old_schema = cur_schema(sql);
	
				sql->session->schema = s;
				b = sequential_block(sql, (ra)?&ra->type:NULL, ra?NULL:restype, body, NULL, is_func);
				sql->session->schema = old_schema;
				sql->params = NULL;
				if (!b) 
					return NULL;
			
				/* check if we have a return statement */
				if (is_func && restype && !has_return(b)) {
					return sql_error(sql, 01,
							"CREATE %s%s: missing return statement", KF, F);
				}
				if (!is_func && !restype && has_return(b)) {
					return sql_error(sql, 01, "CREATE %s%s: procedures "
							"cannot have return statements", KF, F);
				}
	
				/* in execute mode we instantiate the function */
				if (instantiate || deps) {
					return rel_psm_block(sql->sa, b);
				} else if (create) {
					f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang, "user", q, q, FALSE, vararg);
				}
			} else {
				char *fmod = qname_module(ext_name);
				char *fnme = qname_fname(ext_name);

				if (!fmod || !fnme)
					return NULL;
				sql->params = NULL;
				if (create) {
					f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang, fmod, fnme, q, FALSE, vararg);
				} else if (!sf) {
					return sql_error(sql, 01, "CREATE %s%s: external name %s.%s not bound (%s,%s)", KF, F, fmod, fnme, s->base.name, fname );
				} else {
					sql_func *f = sf->func;
					f->mod = _STRDUP(fmod);
					f->imp = _STRDUP(fnme);
					f->sql = 0; /* native */
					f->lang = FUNC_LANG_INT;
				}
			}
		}
	}
	return rel_create_function(sql->sa, s->base.name, f);
}
Пример #10
0
static sql_rel *
psm_analyze(mvc *sql, dlist *qname, dlist *columns, symbol *sample )
{
	exp_kind ek = {type_value, card_value, FALSE};
	sql_exp *sample_exp = NULL, *call;
	char *sname = NULL, *tname = NULL;
	list *tl = sa_list(sql->sa);
	list *exps = sa_list(sql->sa), *analyze_calls = sa_list(sql->sa);
	sql_subfunc *f = NULL;

	if (sample) {
		sql_subtype *tpe = sql_bind_localtype("lng");

       		sample_exp = rel_value_exp( sql, NULL, sample, 0, ek);
		if (sample_exp)
			sample_exp = rel_check_type(sql, tpe, sample_exp, type_cast); 
	}
	if (qname) {
		if (qname->h->next)
			sname = qname_schema(qname);
		else
			sname = qname_table(qname);
		if (!sname)
			sname = cur_schema(sql)->base.name;
		if (qname->h->next)
			tname = qname_table(qname);
	}
	/* call analyze( [schema, [ table ]], opt_sample_size ) */
	if (sname) {
		sql_exp *sname_exp = exp_atom_clob(sql->sa, sname);

		append(exps, sname_exp);
		append(tl, exp_subtype(sname_exp));
	}
	if (tname) {
		sql_exp *tname_exp = exp_atom_clob(sql->sa, tname);

		append(exps, tname_exp);
		append(tl, exp_subtype(tname_exp));

		if (columns)
			append(tl, exp_subtype(tname_exp));
	}
	if (!columns) {
		if (sample_exp) {
			append(exps, sample_exp);
			append(tl, exp_subtype(sample_exp));
		}
		f = sql_bind_func_(sql->sa, mvc_bind_schema(sql, "sys"), "analyze", tl, F_PROC);
		if (!f)
			return sql_error(sql, 01, "Analyze procedure missing");
		call = exp_op(sql->sa, exps, f);
		append(analyze_calls, call);
	} else {
		dnode *n;

		if (sample_exp)
			append(tl, exp_subtype(sample_exp));
		f = sql_bind_func_(sql->sa, mvc_bind_schema(sql, "sys"), "analyze", tl, F_PROC);

		if (!f)
			return sql_error(sql, 01, "Analyze procedure missing");
		for( n = columns->h; n; n = n->next) {
			char *cname = n->data.sval;
			list *nexps = list_dup(exps, NULL);
			sql_exp *cname_exp = exp_atom_clob(sql->sa, cname);

			append(nexps, cname_exp);
			if (sample_exp)
				append(nexps, sample_exp);
			/* call analyze( sname, tname, cname, opt_sample_size ) */
			call = exp_op(sql->sa, nexps, f);
			append(analyze_calls, call);
		}
	}
	return rel_psm_block(sql->sa, analyze_calls);
}
Пример #11
0
static sql_rel *
create_trigger(mvc *sql, dlist *qname, int time, symbol *trigger_event, char *table_name, dlist *opt_ref, dlist *triggered_action)
{
	char *tname = qname_table(qname);
	sql_schema *ss = cur_schema(sql);
	sql_table *t = NULL;
	int instantiate = (sql->emode == m_instantiate);
	int create = (!instantiate && sql->emode != m_deps);
	list *sq = NULL;
	sql_rel *r = NULL;

	dlist *columns = trigger_event->data.lval;
	char *old_name = NULL, *new_name = NULL; 
	dlist *stmts = triggered_action->h->next->next->data.lval;
	
	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 && !schema_privs(sql->role_id, ss)) 
		return sql_error(sql, 02, "CREATE TRIGGER: access denied for %s to schema ;'%s'", stack_get_string(sql, "current_user"), ss->base.name);
	if (create && mvc_bind_trigger(sql, ss, tname) != NULL) 
		return sql_error(sql, 02, "CREATE TRIGGER: name '%s' already in use", tname);
	
	if (create && !(t = mvc_bind_table(sql, ss, table_name)))
		return sql_error(sql, 02, "CREATE TRIGGER: unknown table '%s'", table_name);
	if (create && isView(t)) 
		return sql_error(sql, 02, "CREATE TRIGGER: cannot create trigger on view '%s'", table_name);
	
	if (create) {
		int event = (trigger_event->token == SQL_INSERT)?0:
			    (trigger_event->token == SQL_DELETE)?1:2;
		int orientation = triggered_action->h->data.i_val;
		char *condition = triggered_action->h->next->data.sval;
		char *q = QUERY(sql->scanner);

		assert(triggered_action->h->type == type_int);
		return rel_create_trigger(sql, t->s->base.name, t->base.name, tname, time, orientation, event, old_name, new_name, condition, q);
	}

	t = mvc_bind_table(sql, ss, table_name);
	stack_push_frame(sql, "OLD-NEW");
	/* we need to add the old and new tables */
	if (new_name)
		_stack_push_table(sql, new_name, t);
	if (old_name)
		_stack_push_table(sql, old_name, t);
	sq = sequential_block(sql, NULL, NULL, stmts, NULL, 1);
	r = rel_psm_block(sql->sa, sq);

	/* todo trigger_columns */
	(void)columns;
	return r;
}
Пример #12
0
static sql_rel *
rel_create_func(mvc *sql, dlist *qname, dlist *params, symbol *res, dlist *ext_name, dlist *body, int type, int lang, int replace)
{
	const char *fname = qname_table(qname);
	const char *sname = qname_schema(qname);
	sql_schema *s = NULL;
	sql_func *f = NULL;
	sql_subfunc *sf;
	dnode *n;
	list *type_list = NULL, *restype = NULL;
	int instantiate = (sql->emode == m_instantiate);
	int deps = (sql->emode == m_deps);
	int create = (!instantiate && !deps);
	bit vararg = FALSE;

	char is_table = (res && res->token == SQL_TABLE);
	char is_aggr = (type == F_AGGR);
	char is_func = (type != F_PROC);
	char is_loader = (type == F_LOADER);

	char *F = is_loader?"LOADER":(is_aggr?"AGGREGATE":(is_func?"FUNCTION":"PROCEDURE"));
	char *fn = is_loader?"loader":(is_aggr ? "aggregate" : (is_func ? "function" : "procedure"));
	char *KF = type==F_FILT?"FILTER ": type==F_UNION?"UNION ": "";
	char *kf = type == F_FILT ? "filter " : type == F_UNION ? "union " : "";

	assert(res || type == F_PROC || type == F_FILT || type == F_LOADER);

	if (is_table)
		type = F_UNION;

	if (STORE_READONLY && create) 
		return sql_error(sql, 06, SQLSTATE(42000) "Schema statements cannot be executed on a readonly database.");
			
	if (sname && !(s = mvc_bind_schema(sql, sname)))
		return sql_error(sql, 02, SQLSTATE(3F000) "CREATE %s%s: no such schema '%s'", KF, F, sname);
	if (s == NULL)
		s = cur_schema(sql);

	type_list = create_type_list(sql, params, 1);
	if ((sf = sql_bind_func_(sql->sa, s, fname, type_list, type)) != NULL && create) {
		if (replace) {
			sql_func *func = sf->func;
			int action = 0;
			if (!mvc_schema_privs(sql, s)) {
				return sql_error(sql, 02, SQLSTATE(42000) "CREATE OR REPLACE %s%s: access denied for %s to schema ;'%s'", KF, F, stack_get_string(sql, "current_user"), s->base.name);
			}
			if (mvc_check_dependency(sql, func->base.id, !IS_PROC(func) ? FUNC_DEPENDENCY : PROC_DEPENDENCY, NULL))
				return sql_error(sql, 02, SQLSTATE(42000) "CREATE OR REPLACE %s%s: there are database objects dependent on %s%s %s;", KF, F, kf, fn, func->base.name);
			if (!func->s) {
				return sql_error(sql, 02, SQLSTATE(42000) "CREATE OR REPLACE %s%s: not allowed to replace system %s%s %s;", KF, F, kf, fn, func->base.name);
			}

			if(mvc_drop_func(sql, s, func, action))
				return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
			sf = NULL;
		} else {
			if (params) {
				char *arg_list = NULL;
				node *n;
				
				for (n = type_list->h; n; n = n->next) {
					char *tpe =  subtype2string((sql_subtype *) n->data);
					
					if (arg_list) {
						char *t = arg_list;
						arg_list = sql_message("%s, %s", arg_list, tpe);
						_DELETE(t);
						_DELETE(tpe);
					} else {
						arg_list = tpe;
					}
				}
				(void)sql_error(sql, 02, SQLSTATE(42000) "CREATE %s%s: name '%s' (%s) already in use", KF, F, fname, arg_list);
				_DELETE(arg_list);
				list_destroy(type_list);
				return NULL;
			} else {
				list_destroy(type_list);
				return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s%s: name '%s' already in use", KF, F, fname);
			}
		}
	}
	list_destroy(type_list);
	if (create && !mvc_schema_privs(sql, s)) {
		return sql_error(sql, 02, SQLSTATE(42000) "CREATE %s%s: insufficient privileges "
				"for user '%s' in schema '%s'", KF, F,
				stack_get_string(sql, "current_user"), s->base.name);
	} else {
		char *q = QUERY(sql->scanner);
		list *l = NULL;

	 	if (params) {
			for (n = params->h; n; n = n->next) {
				dnode *an = n->data.lval->h;
				sql_add_param(sql, an->data.sval, &an->next->data.typeval);
			}
			l = sql->params;
			if (l && list_length(l) == 1) {
				sql_arg *a = l->h->data;

				if (strcmp(a->name, "*") == 0) {
					l = NULL;
					vararg = TRUE;
				}
			}
		}
		if (!l)
			l = sa_list(sql->sa);
		if (res) {
			restype = result_type(sql, res);
			if (!restype)
				return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: failed to get restype", KF, F);
		}
		if (body && lang > FUNC_LANG_SQL) {
			char *lang_body = body->h->data.sval;
			char *mod = 	
					(lang == FUNC_LANG_R)?"rapi":
					(lang == FUNC_LANG_C || lang == FUNC_LANG_CPP)?"capi":
					(lang == FUNC_LANG_J)?"japi":
					(lang == FUNC_LANG_PY)?"pyapi":
 					(lang == FUNC_LANG_MAP_PY)?"pyapimap":"unknown";
			sql->params = NULL;
			if (create) {
				f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang,  mod, fname, lang_body, (type == F_LOADER)?TRUE:FALSE, vararg, FALSE);
			} else if (!sf) {
				return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: R function %s.%s not bound", KF, F, s->base.name, fname );
			} /*else {
				sql_func *f = sf->func;
				f->mod = _STRDUP("rapi");
				f->imp = _STRDUP("eval");
				if (res && restype)
					f->res = restype;
				f->sql = 0;
				f->lang = FUNC_LANG_INT;
			}*/
		} else if (body) {
			sql_arg *ra = (restype && !is_table)?restype->h->data:NULL;
			list *b = NULL;
			sql_schema *old_schema = cur_schema(sql);

			if (create) { /* needed for recursive functions */
				q = query_cleaned(q);
				sql->forward = f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang, "user", q, q, FALSE, vararg, FALSE);
				GDKfree(q);
			}
			sql->session->schema = s;
			b = sequential_block(sql, (ra)?&ra->type:NULL, ra?NULL:restype, body, NULL, is_func);
			sql->forward = NULL;
			sql->session->schema = old_schema;
			sql->params = NULL;
			if (!b) 
				return NULL;
		
			/* check if we have a return statement */
			if (is_func && restype && !has_return(b)) {
				return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: missing return statement", KF, F);
			}
			if (!is_func && !restype && has_return(b)) {
				return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: procedures "
						"cannot have return statements", KF, F);
			}

			/* in execute mode we instantiate the function */
			if (instantiate || deps) {
				return rel_psm_block(sql->sa, b);
			}
		} else {
			char *fmod = qname_module(ext_name);
			char *fnme = qname_fname(ext_name);

			if (!fmod || !fnme)
				return NULL;
			sql->params = NULL;
			if (create) {
				q = query_cleaned(q);
				f = mvc_create_func(sql, sql->sa, s, fname, l, restype, type, lang, fmod, fnme, q, FALSE, vararg, FALSE);
				GDKfree(q);
			} else if (!sf) {
				return sql_error(sql, 01, SQLSTATE(42000) "CREATE %s%s: external name %s.%s not bound (%s.%s)", KF, F, fmod, fnme, s->base.name, fname );
			} else {
				sql_func *f = sf->func;
				if (!f->mod || strcmp(f->mod, fmod))
					f->mod = _STRDUP(fmod);
				if (!f->imp || strcmp(f->imp, fnme)) 
					f->imp = (f->sa)?sa_strdup(f->sa, fnme):_STRDUP(fnme);
				if(!f->mod || !f->imp) {
					_DELETE(f->mod);
					_DELETE(f->imp);
					return sql_error(sql, 02, SQLSTATE(HY001) "CREATE %s%s: could not allocate space", KF, F);
				}
				f->sql = 0; /* native */
				f->lang = FUNC_LANG_INT;
			}
		}
	}
	return rel_create_function(sql->sa, s->base.name, f);
}
Пример #13
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;
}