示例#1
0
文件: rel_exp.c 项目: lajus/monetinr
/* Set a name (alias) for the expression, such that we can refer 
   to this expression by this simple name.
 */
void 
exp_setname(sql_allocator *sa, sql_exp *e, char *rname, char *name )
{
	if (name) 
		e->name = sa_strdup(sa, name);
	e->rname = (rname)?sa_strdup(sa, rname):NULL;
}
示例#2
0
文件: rel_exp.c 项目: lajus/monetinr
sql_exp * 
exp_convert(sql_allocator *sa, sql_exp *exp, sql_subtype *fromtype, sql_subtype *totype )
{
	sql_exp *e = exp_create(sa, e_convert);
	e->card = exp->card;
	e->l = exp;
	totype = dup_subtype(sa, totype);
	e->r = append(append(sa_list(sa), dup_subtype(sa, fromtype)),totype);
	e->tpe = *totype; 
	if (exp->name)
		e->name = sa_strdup(sa, exp->name);
	if (exp->rname)
		e->rname = sa_strdup(sa, exp->rname);
	return e;
}
示例#3
0
static ValPtr
SA_VALcopy(sql_allocator *sa, ValPtr d, ValPtr s)
{
	if (!ATOMextern(s->vtype)) {
		*d = *s;
	} else if (s->val.pval == 0) {
		d->val.pval = ATOMnil(s->vtype);
		d->vtype = s->vtype;
	} else if (s->vtype == TYPE_str) {
		d->vtype = TYPE_str;
		d->val.sval = sa_strdup(sa, s->val.sval);
		d->len = strLen(d->val.sval);
	} else if (s->vtype == TYPE_bit) {
		d->vtype = s->vtype;
		d->len = 1;
		d->val.btval = s->val.btval;
	} else {
		ptr p = s->val.pval;

		d->vtype = s->vtype;
		d->len = ATOMlen(d->vtype, p);
		d->val.pval = sa_alloc(sa, d->len);
		memcpy(d->val.pval, p, d->len);
	}
	return d;
}
示例#4
0
文件: rel_psm.c 项目: MonetDB/MonetDB
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);
}
示例#5
0
static list *
rel_psm_declare(mvc *sql, dnode *n)
{
	list *l = sa_list(sql->sa);

	while(n) { /* list of 'identfiers with type' */
		dnode *ids = n->data.sym->data.lval->h->data.lval->h;
		sql_subtype *ctype = &n->data.sym->data.lval->h->next->data.typeval;
		while(ids) {
			char *name = ids->data.sval;
			sql_exp *r = NULL;

			/* check if we overwrite a scope local variable declare x; declare x; */
			if (frame_find_var(sql, name)) {
				return sql_error(sql, 01, 
					"Variable '%s' already declared", name);
			}
			/* variables are put on stack, 
 			 * TODO make sure on plan/explain etc they only 
 			 * exist during plan phase */
			stack_push_var(sql, name, ctype);
			r = exp_var(sql->sa, sa_strdup(sql->sa, name), ctype, sql->frame);
			append(l, r);
			ids = ids->next;
		}
		n = n->next;
	}
	return l;
}
示例#6
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);
}
示例#7
0
文件: rel_exp.c 项目: lajus/monetinr
sql_exp *
exp_atom_clob(sql_allocator *sa, str s) 
{
	sql_subtype clob;

	sql_find_subtype(&clob, "clob", 0, 0);
	return exp_atom(sa, atom_string(sa, &clob, s?sa_strdup(sa, s):NULL));
}
示例#8
0
文件: rel_exp.c 项目: lajus/monetinr
sql_exp*
exp_label(sql_allocator *sa, sql_exp *e, int nr)
{
	char name[16], *nme;

	nme = number2name(name, 16, nr);
	e->name = sa_strdup(sa, nme);
	return e;
}
示例#9
0
文件: rel_exp.c 项目: lajus/monetinr
sql_exp * 
exp_column(sql_allocator *sa, char *rname, char *cname, sql_subtype *t, int card, int has_nils, int intern) 
{
	sql_exp *e = exp_create(sa, e_column);

	assert(cname);
	e->card = card;
	e->name = sa_strdup(sa, cname);
	e->l = (rname)?sa_strdup(sa, rname):NULL;
	e->r = sa_strdup(sa, cname);
	if (t)
		e->tpe = *t;
	if (!has_nils)
		set_has_no_nil(e);
	if (intern)
		set_intern(e);
	return e;
}
示例#10
0
文件: rel_exp.c 项目: lajus/monetinr
sql_exp * 
exp_alias(sql_allocator *sa, char *arname, char *acname, char *org_rname, char *org_cname, sql_subtype *t, int card, int has_nils, int intern) 
{
	sql_exp *e = exp_create(sa, e_column);

	assert(acname && org_cname);
	e->card = card;
	e->rname = (arname)?sa_strdup(sa, arname):(org_rname)?sa_strdup(sa, org_rname):NULL;
	e->name = sa_strdup(sa, acname);
	e->l = (org_rname)?sa_strdup(sa, org_rname):NULL;
	e->r = sa_strdup(sa, org_cname);
	if (t)
		e->tpe = *t;
	if (!has_nils)
		set_has_no_nil(e);
	if (intern)
		set_intern(e);
	return e;
}
示例#11
0
文件: rel_exp.c 项目: lajus/monetinr
sql_exp * 
exp_param(sql_allocator *sa, char *name, sql_subtype *tpe, int frame) 
{
	sql_exp *e = exp_create(sa, e_atom);
	e->r = sa_strdup(sa, name);
	e->card = CARD_ATOM;
	e->flag = frame;
	if (tpe)
		e->tpe = *tpe;
	return e;
}
示例#12
0
文件: sql_mvc.c 项目: f7753/monetdb
sql_column *
mvc_storage(mvc *m, sql_column *col, char *storage)
{
	if (mvc_debug)
		fprintf(stderr, "#mvc_storage %s %s\n", col->base.name, storage);

	if (col->t->persistence == SQL_DECLARED_TABLE) {
		col->storage_type = storage?sa_strdup(m->sa, storage):NULL;
		return col;
	} else {
		return sql_trans_alter_storage(m->session->tr, col, storage);
	}
}
示例#13
0
文件: sql_mvc.c 项目: f7753/monetdb
sql_column *
mvc_default(mvc *m, sql_column *col, char *val)
{
	if (mvc_debug)
		fprintf(stderr, "#mvc_default %s %s\n", col->base.name, val);

	if (col->t->persistence == SQL_DECLARED_TABLE) {
		col->def = val?sa_strdup(m->sa, val):NULL;
		return col;
	} else {
		return sql_trans_alter_default(m->session->tr, col, val);
	}
}
示例#14
0
atom *
atom_general(sql_allocator *sa, sql_subtype *tpe, char *val)
{
	atom *a;
	ptr p = NULL;

	if (atom_debug)
		fprintf(stderr, "atom_general(%s,%s)\n", tpe->type->sqlname, val);

	if (tpe->type->localtype == TYPE_str)
		return atom_string(sa, tpe, val);
	a = atom_create(sa);
	a->tpe = *tpe;
	a->data.val.pval = NULL;
	a->data.vtype = tpe->type->localtype;
	a->data.len = 0;

	assert(a->data.vtype >= 0);

	if (val) {
		int type = a->data.vtype;

		a->isnull = 0;
		if (ATOMstorage(type) == TYPE_str) {
			a->isnull = 0;
			a->data.val.sval = sql2str(sa_strdup(sa, val));
			a->data.len = (int)strlen(a->data.val.sval);
		} else { 
			int res = ATOMfromstr(type, &p, &a->data.len, val);

			/* no result or nil means error (SQL has NULL not nil) */
			if (res < 0 || !p || ATOMcmp(type, p, ATOMnilptr(type)) == 0) {
				/*_DELETE(val);*/
				if (p)
					GDKfree(p);
				return NULL;
			}
			VALset(&a->data, a->data.vtype, p);
			SA_VALcopy(sa, &a->data, &a->data);

			if (p && ATOMextern(a->data.vtype) == 0)
				GDKfree(p);
			/*_DELETE(val);*/
		}
	} else { 
		p = ATOMnilptr(a->data.vtype);
		VALset(&a->data, a->data.vtype, p);
		a->isnull = 1;
	}
	return a;
}
示例#15
0
/* mapiuri_uri prefix including database name */
const char *
mapiuri_uri( const char *uri, sql_allocator *sa)
{
	const char *p = uri, *b = uri, *e;

	p = strchr(p, '/')+1;
	p++;
	e = p = strchr(p, '/');
	e = strchr(p+1, '/');
	if (e)
		return sa_strndup(sa, b, e - b);
	else 
		return sa_strdup(sa, b);
}
示例#16
0
const char *
mapiuri_table( const char *uri, sql_allocator *sa, const char *fallback)
{
	const char *p = uri, *b;

	p = strchr(p, '/')+1;
	p = strchr(p+1, '/');
	p = strchr(p+1, '/');
	if (!p)
		return fallback;
	p = strchr(p+1, '/');
	if (!p)
		return fallback;
 	b = ++p;
	return sa_strdup(sa, b);
}
示例#17
0
const char *
mapiuri_database( const char *uri, sql_allocator *sa)
{
	const char *p = uri, *b, *e;

	p = strchr(p, '/')+1;
	p++;
	b = p = strchr(p, '/')+1;
	e = strchr(p, '/');

	if (e) {
		return sa_strndup(sa, b, e - b);
	} else {
		return sa_strdup(sa, b);
	}
}
示例#18
0
文件: sql_mvc.c 项目: f7753/monetdb
sql_table *
mvc_create_remote(mvc *m, sql_schema *s, const char *name, int persistence, const char *loc)
{
	sql_table *t = NULL;

	if (mvc_debug)
		fprintf(stderr, "#mvc_create_remote %s %s %s\n", s->base.name, name, loc);

	if (persistence == SQL_DECLARED_TABLE) {
		t = create_sql_table(m->sa, name, tt_remote, 0, persistence, 0);
		t->s = s;
		t->query = sa_strdup(m->sa, loc);
	} else {
		t = sql_trans_create_table(m->session->tr, s, name, loc, tt_remote, 0, SQL_REMOTE, 0, 0);
	}
	return t;
}
示例#19
0
文件: sql_mvc.c 项目: f7753/monetdb
sql_table *
mvc_create_view(mvc *m, sql_schema *s, const char *name, int persistence, const char *sql, bit system)
{
	sql_table *t = NULL;

	if (mvc_debug)
		fprintf(stderr, "#mvc_create_view %s %s %s\n", s->base.name, name, sql);

	if (persistence == SQL_DECLARED_TABLE) {
		t = create_sql_table(m->sa, name, tt_view, system, persistence, 0);
		t->s = s;
		t->query = sa_strdup(m->sa, sql);
	} else {
		t = sql_trans_create_table(m->session->tr, s, name, sql, tt_view, system, SQL_PERSIST, 0, 0);
	}
	return t;
}
示例#20
0
const char *
mapiuri_schema( const char *uri, sql_allocator *sa, const char *fallback)
{
	const char *p = uri, *b, *e;

	p = strchr(p, '/')+1;
	p = strchr(p+1, '/');
	p = strchr(p+1, '/');
	if (!p)
		return fallback;
 	b = ++p;
	e = strchr(p, '/');

	if (e) {
		return sa_strndup(sa, b, e - b);
	} else {
		return sa_strdup(sa, b);
	}
}
示例#21
0
/* return val;
 */
static list * 
rel_psm_return( mvc *sql, sql_subtype *restype, list *restypelist, symbol *return_sym )
{
	exp_kind ek = {type_value, card_value, FALSE};
	sql_exp *res;
	sql_rel *rel = NULL;
	int is_last = 0;
	list *l = sa_list(sql->sa);

	if (restypelist)
		ek.card = card_relation;
	res = rel_value_exp2(sql, &rel, return_sym, sql_sel, ek, &is_last);
	if (!res)
		return NULL;
	if (ek.card != card_relation && (!res || 
           	(res = rel_check_type(sql, restype, res, type_equal)) == NULL))
		return NULL;
	else if (ek.card == card_relation && !rel)
		return NULL;
	
	if (rel && ek.card != card_relation)
		append(l, exp_rel(sql, rel));
	else if (rel && !is_ddl(rel->op)) {
		list *exps = sa_list(sql->sa);
		node *n, *m;
		int isproject = (rel->op == op_project);
		list *oexps = rel->exps;
		sql_rel *l = rel->l;

		if (is_topn(rel->op))
			oexps = l->exps;
		for (n = oexps->h, m = restypelist->h; n && m; n = n->next, m = m->next) {
			sql_exp *e = n->data;
			sql_arg *ce = m->data;
			char *cname = exp_name(e);
			char name[16];

			if (!cname)
				cname = sa_strdup(sql->sa, number2name(name, 16, ++sql->label));
			if (!isproject) 
				e = exp_column(sql->sa, exp_relname(e), cname, exp_subtype(e), exp_card(e), has_nil(e), is_intern(e));
			e = rel_check_type(sql, &ce->type, e, type_equal);
			if (!e)
				return NULL;
			append(exps, e);
		}
		if (isproject)
			rel -> exps = exps;
		else
			rel = rel_project(sql->sa, rel, exps);
		res = exp_rel(sql, rel);
	} else if (rel && restypelist){ /* handle return table-var */
		list *exps = sa_list(sql->sa);
		sql_table *t = rel_ddl_table_get(rel);
		node *n, *m;
		char *tname = t->base.name;

		if (cs_size(&t->columns) != list_length(restypelist))
			return sql_error(sql, 02, "RETURN: number of columns do not match");
		for (n = t->columns.set->h, m = restypelist->h; n && m; n = n->next, m = m->next) {
			sql_column *c = n->data;
			sql_arg *ce = m->data;
			sql_exp *e = exp_alias(sql->sa, tname, c->base.name, tname, c->base.name, &c->type, CARD_MULTI, c->null, 0);

			e = rel_check_type(sql, &ce->type, e, type_equal);
			if (!e)
				return NULL;
			append(exps, e);
		}
		rel = rel_project(sql->sa, rel, exps);
		res = exp_rel(sql, rel);
	}
	append(l, exp_return(sql->sa, res, stack_nr_of_declared_tables(sql)));
	return l;
}
示例#22
0
char *
atom2string(sql_allocator *sa, atom *a)
{
	char buf[BUFSIZ], *p = NULL;
	void *v;

	if (a->isnull)
		return sa_strdup(sa, "NULL");
	switch (a->data.vtype) { 
#ifdef HAVE_HGE
	case TYPE_hge:
	{	char *_buf = buf;
		int _bufsiz = BUFSIZ;
		hgeToStr(&_buf, &_bufsiz, &a->data.val.hval);
		break;
	}
#endif
	case TYPE_lng:
		sprintf(buf, LLFMT, a->data.val.lval);
		break;
	case TYPE_wrd:
		sprintf(buf, SSZFMT, a->data.val.wval);
		break;
	case TYPE_oid:
		sprintf(buf, OIDFMT "@0", a->data.val.oval);
		break;
	case TYPE_int:
		sprintf(buf, "%d", a->data.val.ival);
		break;
	case TYPE_sht:
		sprintf(buf, "%d", a->data.val.shval);
		break;
	case TYPE_bte:
		sprintf(buf, "%d", a->data.val.btval);
		break;
	case TYPE_bit:
		if (a->data.val.btval)
			return sa_strdup(sa, "true");
		return sa_strdup(sa, "false");
	case TYPE_flt:
		sprintf(buf, "%f", a->data.val.fval);
		break;
	case TYPE_dbl:
		sprintf(buf, "%f", a->data.val.dval);
		break;
	case TYPE_str:
		if (a->data.val.sval)
			return sa_strdup(sa, a->data.val.sval);
		else
			sprintf(buf, "NULL");
		break;
        default:  
		v = &a->data.val.ival;
		if (ATOMvarsized(a->data.vtype))
			v = a->data.val.pval;
		if (ATOMformat(a->data.vtype, v, &p) < 0) {
                	snprintf(buf, BUFSIZ, "atom2string(TYPE_%d) not implemented", a->data.vtype);
		} else {
			 char *r = sa_strdup(sa, p);
			 _DELETE(p);
			 return r;
		}
	}
	return sa_strdup(sa, buf);
}
示例#23
0
文件: rel_exp.c 项目: lajus/monetinr
sql_exp *
exp_atom_str(sql_allocator *sa, str s, sql_subtype *st) 
{
	return exp_atom(sa, atom_string(sa, st, s?sa_strdup(sa, s):NULL));
}
示例#24
0
文件: termtree.c 项目: elipp/calc
struct term_t term_create(const char* str, int reparse) {
	struct term_t term = term_construct();
	term.string = sa_strdup(str);
	term.reparse = reparse;
	return term;
}
示例#25
0
文件: rel_psm.c 项目: MonetDB/MonetDB
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);
}