示例#1
0
str
db_password_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	(void) mb;

	if (stk->stk[pci->argv[0]].vtype == TYPE_bat) {
		BAT *b = BATdescriptor(*getArgReference_bat(stk, pci, 1));
		if (b == NULL)
			throw(SQL, "sql.password", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
		BAT *bn = COLnew(b->hseqbase, TYPE_str, BATcount(b), TRANSIENT);
		if (bn == NULL) {
			BBPunfix(b->batCacheid);
			throw(SQL, "sql.password", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		}
		BATiter bi = bat_iterator(b);
		BUN p, q;
		BATloop(b, p, q) {
			char *hash, *msg;
			msg = AUTHgetPasswordHash(&hash, cntxt, BUNtvar(bi, p));
			if (msg != MAL_SUCCEED) {
				BBPunfix(b->batCacheid);
				BBPreclaim(bn);
				return msg;
			}
			if (BUNappend(bn, hash, false) != GDK_SUCCEED) {
				BBPunfix(b->batCacheid);
				BBPreclaim(bn);
				throw(SQL, "sql.password", SQLSTATE(HY001) MAL_MALLOC_FAIL);
			}
			GDKfree(hash);
		}
示例#2
0
str
CMDcalcavg(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	dbl avg;
	BUN vals;
	bat *bid;
	BAT *b, *s = NULL;
	gdk_return ret;

	(void) cntxt;
	(void) mb;

	bid = getArgReference_bat(stk, pci, pci->retc + 0);
	if ((b = BATdescriptor(*bid)) == NULL)
		throw(MAL, "aggr.avg", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
	if (pci->retc == pci->retc + 2) {
		bat *sid = getArgReference_bat(stk, pci, pci->retc + 1);
		if (*sid && (s = BATdescriptor(*sid)) == NULL) {
			BBPunfix(b->batCacheid);
			throw(MAL, "aggr.avg", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
		}
	}
	ret = BATcalcavg(b, s, &avg, &vals);
	BBPunfix(b->batCacheid);
	if (s)
		BBPunfix(s->batCacheid);
	if (ret != GDK_SUCCEED)
		return mythrow(MAL, "aggr.avg", OPERATION_FAILED);
	* getArgReference_dbl(stk, pci, 0) = avg;
	if (pci->retc == 2)
		* getArgReference_lng(stk, pci, 1) = vals;
	return MAL_SUCCEED;
}
示例#3
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);
}
示例#4
0
static str
CMDconvertbat(MalStkPtr stk, InstrPtr pci, int tp, int abort_on_error)
{
	bat *bid;
	BAT *b, *bn, *s = NULL;

	bid = getArgReference_bat(stk, pci, 1);
	if ((b = BATdescriptor(*bid)) == NULL)
		throw(MAL, "batcalc.convert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
	if (pci->argc == 3) {
		bat *sid = getArgReference_bat(stk, pci, 2);
		if (*sid && (s = BATdescriptor(*sid)) == NULL) {
			BBPunfix(b->batCacheid);
			throw(MAL, "batcalc.convert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
		}
	}

	bn = BATconvert(b, s, tp, abort_on_error);
	BBPunfix(b->batCacheid);
	if (s)
		BBPunfix(s->batCacheid);
	if (bn == NULL) {
		char buf[20];
		snprintf(buf, sizeof(buf), "batcalc.%s", ATOMname(tp));
		return mythrow(MAL, buf, OPERATION_FAILED);
	}
	bid = getArgReference_bat(stk, pci, 0);
	BBPkeepref(*bid = bn->batCacheid);
	return MAL_SUCCEED;
}
示例#5
0
static str
CMDbatUNARY1(MalStkPtr stk, InstrPtr pci, int abort_on_error,
			 BAT *(*batfunc)(BAT *, BAT *, int), const char *malfunc)
{
	bat *bid;
	BAT *bn, *b, *s = NULL;

	bid = getArgReference_bat(stk, pci, 1);
	if ((b = BATdescriptor(*bid)) == NULL)
		throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
	if (pci->argc == 3) {
		bat *sid = getArgReference_bat(stk, pci, 2);
		if (*sid && (s = BATdescriptor(*sid)) == NULL) {
			BBPunfix(b->batCacheid);
			throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
		}
	}

	bn = (*batfunc)(b, s, abort_on_error);
	BBPunfix(b->batCacheid);
	if (s)
		BBPunfix(s->batCacheid);
	if (bn == NULL) {
		return mythrow(MAL, malfunc, OPERATION_FAILED);
	}
	bid = getArgReference_bat(stk, pci, 0);
	BBPkeepref(*bid = bn->batCacheid);
	return MAL_SUCCEED;
}
示例#6
0
文件: rel_psm.c 项目: MonetDB/MonetDB
static sql_rel*
create_table_from_loader(mvc *sql, dlist *qname, symbol *fcall)
{
	sql_schema *s = NULL;
	char *sname = qname_schema(qname);
	char *tname = qname_table(qname);
	sql_subfunc *loader = NULL;
	sql_rel* rel = NULL;

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

	if (mvc_bind_table(sql, s, tname)) {
		return sql_error(sql, 02, SQLSTATE(42S01) "CREATE TABLE: name '%s' already in use", tname);
	} else if (!mvc_schema_privs(sql, s)){
		return sql_error(sql, 02, SQLSTATE(42000) "CREATE TABLE: insufficient privileges for user '%s' in schema '%s'", stack_get_string(sql, "current_user"), s->base.name);
	}

	rel = rel_loader_function(sql, fcall, new_exp_list(sql->sa), &loader);
	if (!rel || !loader) {
		return NULL;
	}
	loader->sname = sname ? sa_zalloc(sql->sa, strlen(sname) + 1) : NULL;
	loader->tname = tname ? sa_zalloc(sql->sa, strlen(tname) + 1) : NULL;

	if (sname) strcpy(loader->sname, sname);
	if (tname) strcpy(loader->tname, tname);

	return rel;
}
示例#7
0
文件: rel_psm.c 项目: MonetDB/MonetDB
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) {
			const 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,
					SQLSTATE(42000) "Variable '%s' already declared", name);
			}
			/* variables are put on stack, 
 			 * TODO make sure on plan/explain etc they only 
 			 * exist during plan phase */
			if(!stack_push_var(sql, name, ctype)) {
				return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
			}
			r = exp_var(sql->sa, sa_strdup(sql->sa, name), ctype, sql->frame);
			append(l, r);
			ids = ids->next;
		}
		n = n->next;
	}
	return l;
}
示例#8
0
文件: rel_psm.c 项目: MonetDB/MonetDB
static sql_rel* 
rel_drop_all_func(mvc *sql, dlist *qname, int drop_action, int type)
{
	const char *name = qname_table(qname);
	const 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, SQLSTATE(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, SQLSTATE(3F000) "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);
}
示例#9
0
PyObject *PyCodeObject_ParseString(char *string, char **msg)
{
	size_t length = strlen(string);
	PyObject *code_object, *tuple, *mystr;
	char *code_copy = GDKmalloc(length * sizeof(char));
	char hex[3];
	size_t i, j;
	hex[2] = '\0';
	if (code_copy == NULL) {
		*msg = createException(MAL, "pyapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		return NULL;
	}
	// decode hex codes (e.g. \x00) in the string to the actual numeric
	// representation
	for (i = 2, j = 0; i < length - 2; i++) {
		if (string[i] == '\\' && string[i + 1] == '\\')
			i++;
		if (string[i] == '\\' && string[i + 1] == 't') {
			code_copy[j++] = '\t';
			i++;
		} else if (string[i] == '\\' && string[i + 1] == 'n') {
			code_copy[j++] = '\n';
			i++;
		} else if (string[i] == '\\' && string[i + 1] == 'x') {
			hex[0] = string[i + 2];
			hex[1] = string[i + 3];
			code_copy[j++] = (char)strtol(hex, NULL, 16);
			i += 3;
		} else {
			code_copy[j++] = string[i];
		}
	}
	code_copy[j] = '\0';
	tuple = PyTuple_New(1);
	mystr = PyString_FromStringAndSize(
		code_copy,
		j); // use FromStringAndSize because the string is not null-terminated
	PyTuple_SetItem(tuple, 0, mystr);
	code_object = PyObject_CallObject(marshal_loads, tuple);
	Py_DECREF(tuple);
	GDKfree(code_copy);
	if (code_object == NULL) {
		PyErr_Print();
		*msg = createException(MAL, "pyapi.eval",
							   SQLSTATE(PY000) "Failed to marshal.loads() encoded object");
		return NULL;
	}
	*msg = MAL_SUCCEED;
	return code_object;
}
示例#10
0
str
malAtomDefinition(str name, int tpe)
{
	int i;

	if (strlen(name) >= IDLENGTH) {
		throw (SYNTAX, "atomDefinition", "Atom name '%s' too long", name);
	}
	if (ATOMindex(name) >= 0) {
#ifndef HAVE_EMBEDDED /* we can restart embedded MonetDB, making this an expected error */
		throw(TYPE, "atomDefinition", "Redefinition of atom '%s'", name);
#endif
	}
	if (tpe < 0 || tpe >= GDKatomcnt) {
		throw(TYPE, "atomDefinition", "Undefined atom inheritance '%s'", name);
	}
	if (strlen(name) >= sizeof(BATatoms[0].name))
		throw(TYPE, "atomDefinition", "Atom name too long '%s'", name);

	i = ATOMallocate(name);
	if (is_int_nil(i))
		throw(TYPE,"atomDefinition", SQLSTATE(HY001) MAL_MALLOC_FAIL);
	/* overload atom ? */
	if (tpe) {
		BATatoms[i] = BATatoms[tpe];
		strncpy(BATatoms[i].name, name, sizeof(BATatoms[i].name));
		BATatoms[i].name[sizeof(BATatoms[i].name) - 1] = 0; /* make coverity happy */
		BATatoms[i].storage = ATOMstorage(tpe);
	} else { /* cannot overload void atoms */
		BATatoms[i].storage = i;
		BATatoms[i].linear = false;
	}
	return MAL_SUCCEED;
}
示例#11
0
文件: rel_psm.c 项目: MonetDB/MonetDB
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;
}
示例#12
0
文件: alarm.c 项目: MonetDB/MonetDB
str
ALARMctime(str *res)
{
	time_t t = time(0);
	char *base;

#ifdef HAVE_CTIME_R3
	char buf[26];

	base = ctime_r(&t, buf, sizeof(buf));
#else
#ifdef HAVE_CTIME_R
	char buf[26];

	base = ctime_r(&t, buf);
#else
	base = ctime(&t);
#endif
#endif
	if (base == NULL)
		/* very unlikely to happen... */
		throw(MAL, "alarm.ctime", "failed to format time");

	base[24] = 0;				/* squash final newline */
	*res = GDKstrdup(base);
	if (*res == NULL)
		throw(MAL, "alarm.ctime", SQLSTATE(HY001) MAL_MALLOC_FAIL);
	return MAL_SUCCEED;
}
示例#13
0
文件: rel_psm.c 项目: MonetDB/MonetDB
static list *
result_type(mvc *sql, symbol *res) 
{
	if (res->token == SQL_TYPE) {
		sql_subtype *st = &res->data.lval->h->data.typeval;
		sql_arg *a = sql_create_arg(sql->sa, "result", st, ARG_OUT);

		return list_append(sa_list(sql->sa), a);
	} else if (res->token == SQL_TABLE) {
		sql_arg *a;
		dnode *n = res->data.lval->h;
		list *types = sa_list(sql->sa);

		for(;n; n = n->next->next) {
			sql_subtype *ct = &n->next->data.typeval;

			if (list_find(types, n->data.sval, &arg_cmp) != NULL)
				return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "CREATE FUNC: identifier '%s' ambiguous", n->data.sval);

		       	a = sql_create_arg(sql->sa, n->data.sval, ct, ARG_OUT);
			list_append(types, a);
		}
		return types;
	}
	return NULL;
}
示例#14
0
文件: rel_psm.c 项目: MonetDB/MonetDB
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);
}
示例#15
0
str
batnil_2_timestamp(bat *res, const bat *bid)
{
	BAT *b, *dst;
	BUN p, q;

	if ((b = BATdescriptor(*bid)) == NULL) {
		throw(SQL, "batcalc.nil_2_timestamp", SQLSTATE(HY005) "Cannot access column descriptor");
	}
	dst = COLnew(b->hseqbase, TYPE_timestamp, BATcount(b), TRANSIENT);
	if (dst == NULL) {
		BBPunfix(b->batCacheid);
		throw(SQL, "sql.2_timestamp", SQLSTATE(HY001) MAL_MALLOC_FAIL);
	}
	BATloop(b, p, q) {
		timestamp r = *timestamp_nil;
		if (BUNappend(dst, &r, FALSE) != GDK_SUCCEED) {
			BBPunfix(b->batCacheid);
			BBPreclaim(dst);
			throw(SQL, "sql.timestamp", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		}
	}
示例#16
0
文件: rel_psm.c 项目: MonetDB/MonetDB
static sql_exp*
rel_psm_call(mvc * sql, symbol *se)
{
	sql_subtype *t;
	sql_exp *res = NULL;
	exp_kind ek = {type_value, card_none, FALSE};
	sql_rel *rel = NULL;

	res = rel_value_exp(sql, &rel, se, sql_sel, ek);
	if (!res || rel || ((t=exp_subtype(res)) && t->type))  /* only procedures */
		return sql_error(sql, 01, SQLSTATE(42000) "Function calls are ignored");
	return res;
}
示例#17
0
str
CMDgetTrace(bat *res, str *ev)
{
	BAT *bn;

	(void) res;		/* fool compiler */
	bn = getTrace(*ev);
	if (bn) {
		BBPkeepref(*res = bn->batCacheid);
		return MAL_SUCCEED;
	}
	throw(MAL, "getTrace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING  "%s",*ev);
}
示例#18
0
文件: groupby.c 项目: MonetDB/MonetDB
str
GROUPmulticolumngroup(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	bat *grp = getArgReference_bat(stk, pci, 0);
	bat *ext = getArgReference_bat(stk, pci, 1);
	bat *hist = getArgReference_bat(stk, pci, 2);
	int i, j;
	bat oldgrp, oldext, oldhist;
	str msg = MAL_SUCCEED;
	BAT *b;
	BUN count = 0;
	AGGRtask *aggr;

	aggr = GROUPcollect(cntxt, mb, stk, pci);
	if( aggr == NULL)
		throw(MAL,"group.multicolumn", SQLSTATE(HY001) MAL_MALLOC_FAIL);
	GROUPcollectSort(aggr, 0, aggr->last);

	/* (grp,ext,hist) := group.group(..) */
	/* use the old pattern to perform the incremental grouping */
	*grp = 0;
	*ext = 0;
	*hist = 0;
	msg = GRPgroup1(grp, ext, hist, &aggr->bid[0]);
	i = 1;
	if (msg == MAL_SUCCEED && aggr->last > 1)
		do {
			/* early break when there are as many groups as entries */
			b = BATdescriptor(*hist);
			if (b) {
				j = BATcount(b) == count;
				BBPunfix(*hist);
				if (j)
					break;
			}

			/* (grp,ext,hist) := group.subgroup(arg,grp,ext,hist) */
			oldgrp = *grp;
			oldext = *ext;
			oldhist = *hist;
			*grp = 0;
			*ext = 0;
			*hist = 0;
			msg = GRPsubgroup5(grp, ext, hist, &aggr->bid[i], NULL, &oldgrp, &oldext, &oldhist);
			BBPrelease(oldgrp);
			BBPrelease(oldext);
			BBPrelease(oldhist);
		} while (msg == MAL_SUCCEED && ++i < aggr->last);
	GROUPdelete(aggr);
	return msg;
}
示例#19
0
str 
SQLdiff(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	(void)cntxt;
	if (isaBatType(getArgType(mb, pci, 1))) {
		bat *res = getArgReference_bat(stk, pci, 0);
		bat *bid = getArgReference_bat(stk, pci, 1);
		BAT *b = BATdescriptor(*bid), *c, *r;
		gdk_return gdk_code;

		if (!b)
			throw(SQL, "sql.diff", SQLSTATE(HY005) "Cannot access column descriptor");
		voidresultBAT(r, TYPE_bit, BATcount(b), b, "sql.diff");
		if (pci->argc > 2) {
			c = b;
			bid = getArgReference_bat(stk, pci, 2);
			b = BATdescriptor(*bid);
			if (!b) {
				BBPunfix(c->batCacheid);
				throw(SQL, "sql.diff", SQLSTATE(HY005) "Cannot access column descriptor");
			}
			gdk_code = GDKanalyticaldiff(r, b, c, b->ttype);
			BBPunfix(c->batCacheid);
		} else {
			gdk_code = GDKanalyticaldiff(r, b, NULL, b->ttype);
		}
		BBPunfix(b->batCacheid);
		if(gdk_code == GDK_SUCCEED)
			BBPkeepref(*res = r->batCacheid);
		else
			throw(SQL, "sql.diff", GDK_EXCEPTION);
	} else {
		bit *res = getArgReference_bit(stk, pci, 0);

		*res = FALSE;
	}
	return MAL_SUCCEED;
}
示例#20
0
str
yieldFactory(MalBlkPtr mb, InstrPtr p, int pc)
{
	Plant pl;
	int i;

	i = yieldResult(mb, p, pc);

	if (i>=0) {
		pl = plants+i;
		pl->pc = pc + 1;
		pl->client = NULL;
		pl->caller = NULL;
		pl->pci = NULL;
		pl->env = NULL;
		return MAL_SUCCEED;
	}
	throw(MAL, "factory.yield", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
}
示例#21
0
文件: rel_psm.c 项目: MonetDB/MonetDB
static list *
rel_select_into( mvc *sql, symbol *sq, exp_kind ek)
{
	SelectNode *sn = (SelectNode*)sq;
	dlist *into = sn->into;
	node *m;
	dnode *n;
	sql_rel *r;
	list *nl = NULL;

	/* SELECT ... INTO var_list */
	sn->into = NULL;
	r = rel_subquery(sql, NULL, sq, ek, APPLY_JOIN);
	if (!r) 
		return NULL;
	nl = sa_list(sql->sa);
	append(nl, exp_rel(sql, r));
	for (m = r->exps->h, n = into->h; m && n; m = m->next, n = n->next) {
		sql_subtype *tpe = NULL;
		char *nme = n->data.sval;
		sql_exp *v = m->data;
		int level;

		if (!stack_find_var(sql, nme)) 
			return sql_error(sql, 02, SQLSTATE(42000) "SELECT INTO: variable '%s' unknown", nme);
		/* dynamic check for single values */
		if (v->card > CARD_AGGR) {
			sql_subaggr *zero_or_one = sql_bind_aggr(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(v));
			assert(zero_or_one);
			v = exp_aggr1(sql->sa, v, zero_or_one, 0, 0, CARD_ATOM, 0);
		}
		tpe = stack_find_type(sql, nme);
		level = stack_find_frame(sql, nme);
		if (!v || !(v = rel_check_type(sql, tpe, v, type_equal))) 
			return NULL;
		v = exp_set(sql->sa, nme, v, level);
		list_append(nl, v);
	}
	return nl;
}
示例#22
0
/**
 * Returns an exception string for the given type of exception, function
 * and additional formatting parameters.  This function will crash the
 * system or return bogus when the malexception enum is not aligned with
 * the exceptionNames array.
 */
str
createException(enum malexception type, const char *fcn, const char *format, ...)
{
	va_list ap;
	str ret;

	if (GDKerrbuf &&
		(ret = strstr(format, MAL_MALLOC_FAIL)) != NULL &&
		ret[strlen(MAL_MALLOC_FAIL)] != ':' &&
		(strncmp(GDKerrbuf, "GDKmalloc", 9) == 0 ||
		 strncmp(GDKerrbuf, "GDKrealloc", 10) == 0 ||
		 strncmp(GDKerrbuf, "GDKzalloc", 9) == 0 ||
		 strncmp(GDKerrbuf, "GDKstrdup", 9) == 0 ||
		 strncmp(GDKerrbuf, "allocating too much virtual address space", 41) == 0)) {
		/* override errors when the underlying error is memory
		 * exhaustion, but include whatever it is that the GDK level
		 * reported */
		ret = createException(type, fcn, SQLSTATE(HY001) MAL_MALLOC_FAIL ": %s", GDKerrbuf);
		GDKclrerr();
		return ret;
	}
	if (strcmp(format, GDK_EXCEPTION) == 0 && GDKerrbuf[0]) {
		/* for GDK errors, report the underlying error */
		char *p = GDKerrbuf;
		if (strncmp(p, GDKERROR, strlen(GDKERROR)) == 0)
			p += strlen(GDKERROR);
		if (strlen(p) > 6 && p[5] == '!')
			ret = createException(type, fcn, "%s", p);
		else
			ret = createException(type, fcn, "GDK reported error: %s", p);
		GDKclrerr();
		return ret;
	}
	va_start(ap, format);
	ret = createExceptionInternal(type, fcn, format, ap);
	va_end(ap);
	GDKclrerr();

	return ret;
}
示例#23
0
str
QOToptimize(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	str modnme;
	str fcnnme;
	Symbol s;

	(void) stk;
	if (stk != 0) {
		modnme = *getArgReference_str(stk, pci, 1);
		fcnnme = *getArgReference_str(stk, pci, 2);
	} else {
		modnme = getArgDefault(mb, pci, 1);
		fcnnme = getArgDefault(mb, pci, 2);
	}
	s = findSymbol(cntxt->usermodule, putName(modnme), fcnnme);
	if (s == NULL)
		throw(MAL, "optimizer.optimize", SQLSTATE(HY002) SEMANTIC_OPERATION_MISSING);
	removeInstruction(mb, pci);
	addtoMalBlkHistory(s->def);
	return optimizeMALBlock(cntxt, s->def);
}
示例#24
0
str
str_2_timestamp(timestamp *res, const str *val)
{
	ptr p = NULL;
	size_t len = 0;
	ssize_t e;
	char buf[BUFSIZ];

	e = ATOMfromstr(TYPE_timestamp, &p, &len, *val);
	if (e < 0 || !p || (ATOMcmp(TYPE_timestamp, p, ATOMnilptr(TYPE_timestamp)) == 0 && ATOMcmp(TYPE_str, *val, ATOMnilptr(TYPE_str)) != 0)) {
		if (p)
			GDKfree(p);
		snprintf(buf, BUFSIZ, "Conversion of string '%s' failed", *val? *val:"");
		throw(SQL, "timestamp", SQLSTATE(42000) "%s", buf);
	}
	*res = *(timestamp *) p;
	if (!ATOMextern(TYPE_timestamp)) {
		if (p)
			GDKfree(p);
	}
	return MAL_SUCCEED;
}
示例#25
0
static str
monet5_create_user(ptr _mvc, str user, str passwd, char enc, str fullname, sqlid schema_id, sqlid grantorid)
{
	mvc *m = (mvc *) _mvc;
	oid uid = 0;
	bat bid = 0;
	str ret;
	sqlid user_id;
	str pwd;
	sql_schema *s = find_sql_schema(m->session->tr, "sys");
	sql_table *db_user_info, *auths;
	Client c = MCgetClient(m->clientid);

	if (!enc) {
		pwd = mcrypt_BackendSum(passwd, strlen(passwd));
		if (pwd == NULL) {
			BBPunfix(bid);
			throw(MAL, "sql.create_user", SQLSTATE(42000) "Crypt backend hash not found");
		}
	} else {
		pwd = passwd;
	}
	/* add the user to the M5 authorisation administration */
	ret = AUTHaddUser(&uid, c, user, pwd);
	if (!enc)
		free(pwd);
	if (ret != MAL_SUCCEED)
		return ret;

	user_id = store_next_oid();
	db_user_info = find_sql_table(s, "db_user_info");
	auths = find_sql_table(s, "auths");
	table_funcs.table_insert(m->session->tr, db_user_info, user, fullname, &schema_id);
	table_funcs.table_insert(m->session->tr, auths, &user_id, user, &grantorid);
	return NULL;
}
示例#26
0
文件: rapi.c 项目: MonetDB/MonetDB
str RAPIeval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, bit grouped) {
	sql_func * sqlfun = NULL;
	str exprStr = *getArgReference_str(stk, pci, pci->retc + 1);

	SEXP x, env, retval;
	SEXP varname = R_NilValue;
	SEXP varvalue = R_NilValue;
	ParseStatus status;
	int i = 0;
	char argbuf[64];
	char *argnames = NULL;
	size_t argnameslen;
	size_t pos;
	char* rcall = NULL;
	size_t rcalllen;
	int ret_cols = 0; /* int because pci->retc is int, too*/
	str *args;
	int evalErr;
	char *msg = MAL_SUCCEED;
	BAT *b;
	node * argnode;
	int seengrp = FALSE;

	rapiClient = cntxt;

	if (!RAPIEnabled()) {
		throw(MAL, "rapi.eval",
			  "Embedded R has not been enabled. Start server with --set %s=true",
			  rapi_enableflag);
	}
	if (!rapiInitialized) {
		throw(MAL, "rapi.eval",
			  "Embedded R initialization has failed");
	}

	if (!grouped) {
		sql_subfunc *sqlmorefun = (*(sql_subfunc**) getArgReference(stk, pci, pci->retc));
		if (sqlmorefun) sqlfun = (*(sql_subfunc**) getArgReference(stk, pci, pci->retc))->func;
	} else {
		sqlfun = *(sql_func**) getArgReference(stk, pci, pci->retc);
	}

	args = (str*) GDKzalloc(sizeof(str) * pci->argc);
	if (args == NULL) {
		throw(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
	}

	// get the lock even before initialization of the R interpreter, as this can take a second and must be done only once.
	MT_lock_set(&rapiLock);

	env = PROTECT(eval(lang1(install("new.env")), R_GlobalEnv));
	assert(env != NULL);

	// first argument after the return contains the pointer to the sql_func structure
	// NEW macro temporarily renamed to MNEW to allow including sql_catalog.h

	if (sqlfun != NULL && sqlfun->ops->cnt > 0) {
		int carg = pci->retc + 2;
		argnode = sqlfun->ops->h;
		while (argnode) {
			char* argname = ((sql_arg*) argnode->data)->name;
			args[carg] = GDKstrdup(argname);
			carg++;
			argnode = argnode->next;
		}
	}
	// the first unknown argument is the group, we don't really care for the rest.
	argnameslen = 2;
	for (i = pci->retc + 2; i < pci->argc; i++) {
		if (args[i] == NULL) {
			if (!seengrp && grouped) {
				args[i] = GDKstrdup("aggr_group");
				seengrp = TRUE;
			} else {
				snprintf(argbuf, sizeof(argbuf), "arg%i", i - pci->retc - 1);
				args[i] = GDKstrdup(argbuf);
			}
		}
		argnameslen += strlen(args[i]) + 2; /* extra for ", " */
	}

	// install the MAL variables into the R environment
	// we can basically map values to int ("INTEGER") or double ("REAL")
	for (i = pci->retc + 2; i < pci->argc; i++) {
		int bat_type = getBatType(getArgType(mb,pci,i));
		// check for BAT or scalar first, keep code left
		if (!isaBatType(getArgType(mb,pci,i))) {
			b = COLnew(0, getArgType(mb, pci, i), 0, TRANSIENT);
			if (b == NULL) {
				msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
				goto wrapup;
			}
			if ( getArgType(mb,pci,i) == TYPE_str) {
				if (BUNappend(b, *getArgReference_str(stk, pci, i), false) != GDK_SUCCEED) {
					BBPreclaim(b);
					b = NULL;
					msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
					goto wrapup;
				}
			} else {
				if (BUNappend(b, getArgReference(stk, pci, i), false) != GDK_SUCCEED) {
					BBPreclaim(b);
					b = NULL;
					msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
					goto wrapup;
				}
			}
		} else {
			b = BATdescriptor(*getArgReference_bat(stk, pci, i));
			if (b == NULL) {
				msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
				goto wrapup;
			}
		}

		// check the BAT count, if it is bigger than RAPI_MAX_TUPLES, fail
		if (BATcount(b) > RAPI_MAX_TUPLES) {
			msg = createException(MAL, "rapi.eval",
								  "Got "BUNFMT" rows, but can only handle "LLFMT". Sorry.",
								  BATcount(b), (lng) RAPI_MAX_TUPLES);
			BBPunfix(b->batCacheid);
			goto wrapup;
		}
		varname = PROTECT(Rf_install(args[i]));
		varvalue = bat_to_sexp(b, bat_type);
		if (varvalue == NULL) {
			msg = createException(MAL, "rapi.eval", "unknown argument type ");
			goto wrapup;
		}
		BBPunfix(b->batCacheid);

		// install vector into R environment
		Rf_defineVar(varname, varvalue, env);
		UNPROTECT(2);
	}

	/* we are going to evaluate the user function within an anonymous function call:
	 * ret <- (function(arg1){return(arg1*2)})(42)
	 * the user code is put inside the {}, this keeps our environment clean (TM) and gives
	 * a clear path for return values, namely using the builtin return() function
	 * this is also compatible with PL/R
	 */
	pos = 0;
	argnames = malloc(argnameslen);
	if (argnames == NULL) {
		msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		goto wrapup;
	}
	argnames[0] = '\0';
	for (i = pci->retc + 2; i < pci->argc; i++) {
		pos += snprintf(argnames + pos, argnameslen - pos, "%s%s",
						args[i], i < pci->argc - 1 ? ", " : "");
	}
	rcalllen = 2 * pos + strlen(exprStr) + 100;
	rcall = malloc(rcalllen);
	if (rcall == NULL) {
		msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		goto wrapup;
	}
	snprintf(rcall, rcalllen,
			 "ret <- as.data.frame((function(%s){%s})(%s), nm=NA, stringsAsFactors=F)\n",
			 argnames, exprStr, argnames);
	free(argnames);
	argnames = NULL;
#ifdef _RAPI_DEBUG_
	printf("# R call %s\n",rcall);
#endif

	x = R_ParseVector(mkString(rcall), 1, &status, R_NilValue);

	if (LENGTH(x) != 1 || status != PARSE_OK) {
		msg = createException(MAL, "rapi.eval",
							  "Error parsing R expression '%s'. ", exprStr);
		goto wrapup;
	}

	retval = R_tryEval(VECTOR_ELT(x, 0), env, &evalErr);
	if (evalErr != FALSE) {
		char* errormsg = strdup(R_curErrorBuf());
		size_t c;
		if (errormsg == NULL) {
			msg = createException(MAL, "rapi.eval", "Error running R expression.");
			goto wrapup;
		}
		// remove newlines from error message so it fits into a MAPI error (lol)
		for (c = 0; c < strlen(errormsg); c++) {
			if (errormsg[c] == '\r' || errormsg[c] == '\n') {
				errormsg[c] = ' ';
			}
		}
		msg = createException(MAL, "rapi.eval",
							  "Error running R expression: %s", errormsg);
		free(errormsg);
		goto wrapup;
	}

	// ret should be a data frame with exactly as many columns as we need from retc
	ret_cols = LENGTH(retval);
	if (ret_cols != pci->retc) {
		msg = createException(MAL, "rapi.eval",
							  "Expected result of %d columns, got %d", pci->retc, ret_cols);
		goto wrapup;
	}

	// collect the return values
	for (i = 0; i < pci->retc; i++) {
		SEXP ret_col = VECTOR_ELT(retval, i);
		int bat_type = getBatType(getArgType(mb,pci,i));
		if (bat_type == TYPE_any || bat_type == TYPE_void) {
			getArgType(mb,pci,i) = bat_type;
			msg = createException(MAL, "rapi.eval",
								  "Unknown return value, possibly projecting with no parameters.");
			goto wrapup;
		}

		// hand over the vector into a BAT
		b = sexp_to_bat(ret_col, bat_type);
		if (b == NULL) {
			msg = createException(MAL, "rapi.eval",
								  "Failed to convert column %i", i);
			goto wrapup;
		}
		// bat return
		if (isaBatType(getArgType(mb,pci,i))) {
			*getArgReference_bat(stk, pci, i) = b->batCacheid;
		} else { // single value return, only for non-grouped aggregations
			BATiter li = bat_iterator(b);
			if (VALinit(&stk->stk[pci->argv[i]], bat_type,
						BUNtail(li, 0)) == NULL) { // TODO BUNtail here
				msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
				goto wrapup;
			}
		}
		msg = MAL_SUCCEED;
	}
	/* unprotect environment, so it will be eaten by the GC. */
	UNPROTECT(1);
  wrapup:
	MT_lock_unset(&rapiLock);
	if (argnames)
		free(argnames);
	if (rcall)
		free(rcall);
	for (i = 0; i < pci->argc; i++)
		GDKfree(args[i]);
	GDKfree(args);

	return msg;
}
示例#27
0
/*
 * The shortcut operator for factory calls assumes that the user is
 * not interested in the results produced.
 */
str
callFactory(Client cntxt, MalBlkPtr mb, ValPtr argv[], char flag){
	Plant pl;
	InstrPtr psig = getInstrPtr(mb, 0);
	int i;
	ValPtr lhs,rhs;
	MalStkPtr stk;
	str ret;

	i= findPlant(mb);
	if( i< 0) {
		/* first call? prepare the factory */
		pl = newPlant(mb);
		if (pl == NULL)
			throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		/* remember context, which does not exist. */
		pl->client = cntxt;
		pl->caller = 0;
		pl->env = 0;
		pl->pci = 0;
		pl->inuse = 1;
		stk = pl->stk;
		/* initialize the stack */
		stk->stktop= mb->vtop;
		stk->stksize= mb->vsize;
		stk->blk= mb;
		stk->up = 0;
		stk->cmd= flag;
		/* initialize the stack */
		for(i= psig->argc; i< mb->vtop; i++)
		if( isVarConstant(mb,i) > 0 ){
			lhs = &stk->stk[i];
			rhs = &getVarConstant(mb,i);
			if (VALcopy(lhs,rhs) == NULL)
				throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		} else {
			lhs = &stk->stk[i];
			lhs->vtype = getVarGDKType(mb,i);
		}
		pl->stk= stk;
	} else  {
		pl= plants+i;
		/*
		 * When you re-enter the factory the old arguments should be
		 * released to make room for the new ones.
		 */
		for (i = psig->retc; i < psig->argc; i++) {
			lhs = &pl->stk->stk[psig->argv[i]];
			if( lhs->vtype == TYPE_bat )
				BBPrelease(lhs->val.bval);
		}
	}
	/* copy the calling arguments onto the stack of the factory */
	i = psig->retc;
	for (i = psig->retc; i < psig->argc; i++) {
		lhs = &pl->stk->stk[psig->argv[i]];
		if (VALcopy(lhs, argv[i]) == NULL)
			throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		if( lhs->vtype == TYPE_bat )
			BBPretain(lhs->val.bval);
	}
	ret=  reenterMAL(cntxt, mb, pl->pc, -1, pl->stk);
	/* garbage collect the string arguments, these positions
	   will simply be overwritten the next time.
	for (i = psig->retc; i < psig->argc; i++)
		garbageElement(lhs = &pl->stk->stk[psig->argv[i]]);
	*/
	return ret;
}
示例#28
0
str
runFactory(Client cntxt, MalBlkPtr mb, MalBlkPtr mbcaller, MalStkPtr stk, InstrPtr pci)
{
	Plant pl=0;
	int firstcall= TRUE, i, k;
	InstrPtr psig = getInstrPtr(mb, 0);
	ValPtr lhs, rhs;
	char cmd;
	str msg;

#ifdef DEBUG_MAL_FACTORY
	fprintf(stderr, "#factoryMgr called\n");
#endif
	/* the lookup can be largely avoided by handing out the index
	   upon factory definition. todo
		Alternative is to move them to the front
	 */
	for(i=0; i< lastPlant; i++)
	if( plants[i].factory == mb){
		if(i > 0 && i< lastPlant ){
			PlantRecord prec= plants[i-1];
			plants[i-1] = plants[i];
			plants[i]= prec;
			i--;
		}
		pl= plants+i;
		firstcall= FALSE;
		break;
	}
	if (pl == 0) {
		/* compress the plant table*/
		for(k=i=0;i<=lastPlant; i++)
		if( plants[i].inuse)
			plants[k++]= plants[i];
		lastPlant = k;
		/* initialize a new plant using the owner policy */
		pl = newPlant(mb);
		if (pl == NULL)
			throw(MAL, "factory.new", SQLSTATE(HY001) MAL_MALLOC_FAIL);
	}
	/*
	 * We have found a factory to process the request.
	 * Let's call it as a synchronous action, without concern on parallelism.
	 */
	/* remember context */
	pl->client = cntxt;
	pl->caller = mbcaller;
	pl->env = stk;
	pl->pci = pci;
	pl->inuse = 1;
	/* inherit debugging */
	cmd = stk->cmd;
	if ( pl->stk == NULL)
		throw(MAL, "factory.new", "internal error, stack frame missing");

	/* copy the calling arguments onto the stack
	   of the factory */
	i = psig->retc;
	for (k = pci->retc; i < pci->argc; i++, k++) {
		lhs = &pl->stk->stk[psig->argv[k]];
		/* variable arguments ? */
		if (k == psig->argc - 1)
			k--;

		rhs = &pl->env->stk[getArg(pci, i)];
		if (VALcopy(lhs, rhs) == NULL)
			throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		if( lhs->vtype == TYPE_bat )
			BBPretain(lhs->val.bval);
	}
	if (mb->errors)
		throw(MAL, "factory.call", PROGRAM_GENERAL);
	if (firstcall ){
		/* initialize the stack */
		for(i= psig->argc; i< mb->vtop; i++) {
			lhs = &pl->stk->stk[i];
			if( isVarConstant(mb,i) > 0 ){
				if( !isVarDisabled(mb,i)){
					rhs = &getVarConstant(mb,i);
					if (VALcopy(lhs,rhs) == NULL)
						throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
				}
			} else{
				lhs->vtype = getVarGDKType(mb,i);
				lhs->val.pval = 0;
				lhs->len = 0;
			}
		}
		pl->stk->stkbot= mb->vtop;	/* stack already initialized */
		msg = runMAL(cntxt, mb, 0, pl->stk);
	 } else {
		msg = reenterMAL(cntxt, mb, pl->pc, -1, pl->stk);
	}
	/* propagate change in debugging status */
	if (cmd && pl->stk && pl->stk->cmd != cmd && cmd != 'x')
		for (; stk; stk = stk->up)
			stk->cmd = pl->stk->cmd;
	return msg;
}
示例#29
0
str
OPTevaluateImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	InstrPtr p;
	int i, k, limit, *alias = 0, barrier;
	MalStkPtr env = NULL;
	int profiler;
	int debugstate = cntxt->itrace, actions = 0, constantblock = 0;
	int *assigned = 0, use; 
	char buf[256];
	lng usec = GDKusec();
	str msg = MAL_SUCCEED;

	(void)stk;
	(void)pci;

	if ( mb->inlineProp )
		return MAL_SUCCEED;

	cntxt->itrace = 0;

#ifdef DEBUG_OPT_EVALUATE
	fprintf(stderr, "Constant expression optimizer started\n");
#endif

	assigned = (int*) GDKzalloc(sizeof(int) * mb->vtop);
	if (assigned == NULL)
		throw(MAL,"optimzier.evaluate", SQLSTATE(HY001) MAL_MALLOC_FAIL);

	alias = (int*)GDKzalloc(mb->vsize * sizeof(int) * 2); /* we introduce more */
	if (alias == NULL){
		GDKfree(assigned);
		throw(MAL,"optimzier.evaluate", SQLSTATE(HY001) MAL_MALLOC_FAIL);
	}

	// arguments are implicitly assigned by context
	p = getInstrPtr(mb, 0);
	for ( k =p->retc;  k < p->argc; k++)
		assigned[getArg(p,k)]++;
	limit = mb->stop;
	for (i = 1; i < limit; i++) {
		p = getInstrPtr(mb, i);
		// The double count emerging from a barrier exit is ignored.
		if (! blockExit(p) || (blockExit(p) && p->retc != p->argc))
		for ( k =0;  k < p->retc; k++)
		if ( p->retc != p->argc || p->token != ASSIGNsymbol )
			assigned[getArg(p,k)]++;
	}

	for (i = 1; i < limit && cntxt->mode != FINISHCLIENT; i++) {
		p = getInstrPtr(mb, i);
		// to avoid management of duplicate assignments over multiple blocks
		// we limit ourselves to evaluation of the first assignment only.
		use = assigned[getArg(p,0)] == 1 && !(p->argc == p->retc && blockExit(p));
		for (k = p->retc; k < p->argc; k++)
			if (alias[getArg(p, k)])
				getArg(p, k) = alias[getArg(p, k)];
#ifdef DEBUG_OPT_EVALUATE
		fprintInstruction(stderr , mb, 0, p, LIST_MAL_ALL);
#endif
		/* be aware that you only assign once to a variable */
		if (use && p->retc == 1 && OPTallConstant(cntxt, mb, p) && !isUnsafeFunction(p)) {
			barrier = p->barrier;
			p->barrier = 0;
			profiler = malProfileMode;	/* we don't trace it */
			malProfileMode = 0;
			if ( env == NULL) {
				env = prepareMALstack(mb,  2 * mb->vsize);
				if (!env) {
					msg = createException(MAL,"optimizer.evaluate", SQLSTATE(HY001) MAL_MALLOC_FAIL);
					goto wrapup;
				}
				env->keepAlive = TRUE;
			}
			msg = reenterMAL(cntxt, mb, i, i + 1, env);
			malProfileMode= profiler;
			p->barrier = barrier;
#ifdef DEBUG_OPT_EVALUATE
			fprintf(stderr, "#retc var %s\n", getVarName(mb, getArg(p, 0)));
			fprintf(stderr, "#result:%s\n", msg == MAL_SUCCEED ? "ok" : msg);
#endif
			if (msg == MAL_SUCCEED) {
				int nvar;
				ValRecord cst;

				actions++;
				cst.vtype = 0;
				VALcopy(&cst, &env->stk[getArg(p, 0)]);
				/* You may not overwrite constants.  They may be used by
				 * other instructions */
				nvar = getArg(p, 1) = defConstant(mb, getArgType(mb, p, 0), &cst);
				if (nvar >= env->stktop) {
					VALcopy(&env->stk[getArg(p, 1)], &getVarConstant(mb, getArg(p, 1)));
					env->stktop = getArg(p, 1) + 1;
				}
				alias[getArg(p, 0)] = getArg(p, 1);
				p->argc = 2;
				p->token = ASSIGNsymbol;
				clrFunction(p);
				p->barrier = barrier;
				/* freeze the type */
				setVarFixed(mb,getArg(p,1));
				setVarUDFtype(mb,getArg(p,1));
#ifdef DEBUG_OPT_EVALUATE
				{str tpename;
				fprintf(stderr, "Evaluated new constant=%d -> %d:%s\n",
					getArg(p, 0), getArg(p, 1), tpename = getTypeName(getArgType(mb, p, 1)));
				GDKfree(tpename);
				}
#endif
			} else {
				/* if there is an error, we should postpone message handling,
					as the actual error (eg. division by zero ) may not happen) */
#ifdef DEBUG_OPT_EVALUATE
				fprintf(stderr, "Evaluated %s\n", msg);
#endif
				freeException(msg);
				msg= MAL_SUCCEED;
				mb->errors = 0;
			}
		}
		constantblock +=  blockStart(p) && OPTallConstant(cntxt, mb, p);	/* default */
	}
	// produces errors in SQL when enabled
	if ( constantblock)
		msg = OPTremoveUnusedBlocks(cntxt, mb);
	cntxt->itrace = debugstate;

    /* Defense line against incorrect plans */
	/* Plan is unaffected */
	chkTypes(cntxt->usermodule, mb, FALSE);
	chkFlow(mb);
	chkDeclarations(mb);
    
    /* keep all actions taken as a post block comment */
	usec = GDKusec()- usec;
    snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","evaluate",actions,usec);
    newComment(mb,buf);
	if( actions >= 0)
		addtoMalBlkHistory(mb);

wrapup:
	if ( env) freeStack(env);
	if(assigned) GDKfree(assigned);
	if(alias)	GDKfree(alias);
	return msg;
}
示例#30
0
char *FormatCode(char *code, char **args, size_t argcount, size_t tabwidth,
				 PyObject **code_object, char **msg, char **additional_args,
				 size_t additional_argcount)
{
	// Format the python code by fixing the indentation levels
	// We do two passes, first we get the length of the resulting formatted code
	// and then we actually create the resulting code
	size_t i = 0, j = 0, k = 0;
	size_t length = strlen(code);
	size_t size = 0;
	size_t spaces_per_level = 2;

	size_t code_location = 0;
	char *newcode = NULL;

	size_t indentation_count = 0;
	size_t max_indentation = 100;
	// This keeps track of the different indentation levels
	// indentation_levels is a sorted array with how many spaces of indentation
	// that specific array has
	// so indentation_levels[0] = 4 means that the first level (level 0) has 4
	// spaces in the source code
	// after this array is constructed we can count the amount of spaces before
	// a statement and look in this
	// array to immediately find the indentation level of the statement
	size_t *indentation_levels;
	// statements_per_level keeps track of how many statements are at the
	// specified indentation level
	// this is needed to compute the size of the resulting formatted code
	// for every indentation level i, we add statements_per_level[i] * (i + 1) *
	// spaces_per_level spaces
	size_t *statements_per_level;

	size_t initial_spaces = 0;
	size_t statement_size = 0;
	bool seen_statement = false;
	bool multiline_statement = false;
	int multiline_quotes = 0;

	char base_start[] = "def pyfun(";
	char base_end[] = "):\n";
	*msg = NULL;
#ifndef IS_PY3K
	if (code[1] == '@') {
		*code_object = PyCodeObject_ParseString(code, msg);
		return NULL;
	}
#else
	(void)code_object;
#endif

	indentation_levels = (size_t *)GDKzalloc(max_indentation * sizeof(size_t));
	statements_per_level =
		(size_t *)GDKzalloc(max_indentation * sizeof(size_t));
	if (indentation_levels == NULL || statements_per_level == NULL) {
		*msg = createException(MAL, "pyapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		goto finally;
	}

	// Base function definition size
	// For every argument, add a comma, and add another entry for the '\0'
	size += strlen(base_start) + strlen(base_end) + argcount + 1;
	for (i = 0; i < argcount; i++) {
		if (args[i] != NULL) {
			size += strlen(args[i]) + 1;
		}
	}
	// Additional parameters
	for (i = 0; i < additional_argcount; i++)
		size += strlen(additional_args[i]) + 1;

	// First remove the "{" at the start and the "};" at the end of the
	// function, this is added when we have a function created through SQL and
	// python doesn't like them
	// We need to be careful to only remove ones at the start/end, otherwise we
	// might invalidate some otherwise valid python code containing them
	for (i = length - 1, j = 0; i > 0; i--) {
		if (code[i] != '\n' && code[i] != ' ' && code[i] != '\t' &&
			code[i] != ';' && code[i] != '}')
			break;
		if (j == 0) {
			if (code[i] == ';') {
				code[i] = ' ';
				j = 1;
			}
		} else if (j == 1) {
			if (code[i] == '}') {
				code[i] = ' ';
				break;
			}
		}
	}
	for (i = 0; i < length; i++) {
		if (code[i] != '\n' && code[i] != ' ' && code[i] != '\t' &&
			code[i] != '{')
			break;
		if (code[i] == '{') {
			code[i] = ' ';
		}
	}
	// We indent using spaces, four spaces per level
	// We also erase empty lines
	for (i = 0; i < length; i++) {
		// handle multiline strings (strings that start with """)
		if (code[i] == '\"') {
			if (!multiline_statement) {
				multiline_quotes++;
				multiline_statement = multiline_quotes == 3;
			} else {
				multiline_quotes--;
				multiline_statement = multiline_quotes != 0;
			}
		} else {
			multiline_quotes = multiline_statement ? 3 : 0;
		}

		if (!seen_statement) {
			// We have not seen a statement on this line yet
			if (code[i] == '\n') {
				// Empty line, skip to the next one
				initial_spaces = 0;
			} else if (code[i] == ' ') {
				initial_spaces++;
			} else if (code[i] == '\t') {
				initial_spaces += tabwidth;
			} else {
				// Statement starts here
				seen_statement = true;
			}
		}
		if (seen_statement) {
			// We have seen a statement on this line, check the indentation
			// level
			statement_size++;

			if (code[i] == '\n' || i == length - 1) {
				// Statement ends here
				bool placed = false;
				size_t level = 0;

				if (multiline_statement) {
					// if we are in a multiline statement, we don't want to mess
					// with the indentation
					size += statement_size;
					initial_spaces = 0;
					statement_size = 0;
					continue;
				}
				// First put the indentation in the indentation table
				if (indentation_count >= max_indentation) {
					// If there is no room in the indentation arrays we will
					// extend them
					// This probably will never happen unless in really extreme
					// code (or if max_indentation is set very low)
					size_t *new_indentation =
						GDKzalloc(2 * max_indentation * sizeof(size_t));
					size_t *new_statements_per_level;
					if (new_indentation == NULL) {
						*msg =
							createException(MAL, "pyapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
						goto finally;
					}
					new_statements_per_level =
						GDKzalloc(2 * max_indentation * sizeof(size_t));
					if (new_statements_per_level == NULL) {
						*msg =
							createException(MAL, "pyapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
						goto finally;
					}

					for (i = 0; i < max_indentation; i++) {
						new_indentation[i] = indentation_levels[i];
						new_statements_per_level[i] = statements_per_level[i];
					}
					GDKfree(indentation_levels);
					GDKfree(statements_per_level);
					indentation_levels = new_indentation;
					statements_per_level = new_statements_per_level;
					max_indentation *= 2;
				}

				for (j = 0; j < indentation_count; j++) {
					if (initial_spaces == indentation_levels[j]) {
						// The exact space count is already in the array, so we
						// can stop
						level = j;
						placed = true;
						break;
					}

					if (initial_spaces < indentation_levels[j]) {
						// The indentation level is smaller than this level (but
						// bigger than the previous level)
						// So the indentation level belongs here, so we move
						// every level past this one upward one level
						// and put the indentation level here
						for (k = indentation_count; k > j; k--) {
							indentation_levels[k] = indentation_levels[k - 1];
							statements_per_level[k] =
								statements_per_level[k - 1];
						}
						indentation_count++;
						statements_per_level[j] = 0;
						indentation_levels[j] = initial_spaces;
						level = j;
						placed = true;
						break;
					}
				}
				if (!placed) {
					// The space count is the biggest we have seen, so we add it
					// to the end of the array
					level = indentation_count;
					indentation_levels[indentation_count++] = initial_spaces;
				}
				statements_per_level[level]++;
				size += statement_size;
				seen_statement = false;
				initial_spaces = 0;
				statement_size = 0;
			}
		}
	}
	// Add the amount of spaces we will add to the size
	for (i = 0; i < indentation_count; i++) {
		size += (i + 1) * spaces_per_level * statements_per_level[i];
	}

	// Allocate space for the function
	newcode = GDKzalloc(size);
	if (newcode == NULL) {
		*msg = createException(MAL, "pyapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		goto finally;
	}
	initial_spaces = 0;
	seen_statement = false;

	// First print in the function definition and arguments
	for (i = 0; i < strlen(base_start); i++) {
		newcode[code_location++] = base_start[i];
	}
	// Add user-defined parameters
	for (i = 0; i < argcount; i++) {
		if (args[i] != NULL) {
			for (j = 0; j < strlen(args[i]); j++) {
				newcode[code_location++] = args[i][j];
			}
			if (i != argcount - 1 || additional_argcount > 0) {
				newcode[code_location++] = ',';
			}
		}
	}
	// Add additional parameters
	for (i = 0; i < additional_argcount; i++) {
		if (additional_args[i] != NULL) {
			for (j = 0; j < strlen(additional_args[i]); j++) {
				newcode[code_location++] = additional_args[i][j];
			}
			if (i != additional_argcount - 1) {
				newcode[code_location++] = ',';
			}
		}
	}
	for (i = 0; i < strlen(base_end); i++) {
		newcode[code_location++] = base_end[i];
	}

	// Now the second pass, actually construct the code
	for (i = 0; i < length; i++) {
		// handle multiline statements
		if (code[i] == '\"') {
			if (!multiline_statement) {
				multiline_quotes++;
				multiline_statement = multiline_quotes == 3;
			} else {
				multiline_quotes--;
				multiline_statement = multiline_quotes != 0;
			}
		} else {
			multiline_quotes = multiline_statement ? 3 : 0;
		}

		if (!seen_statement) {
			if (multiline_statement)
				seen_statement = true; // if we are in a multiline string, we
									   // simply want to copy everything
									   // (including indentation)
			// We have not seen a statement on this line yet
			else if (code[i] == '\n') {
				// Empty line, skip to the next one
				initial_spaces = 0;
			} else if (code[i] == ' ') {
				initial_spaces++;
			} else if (code[i] == '\t') {
				initial_spaces += tabwidth;
			} else {
				// Look through the indentation_levels array to find the level
				// of the statement
				// from the amount of initial spaces
				bool placed = false;
				size_t level = 0;
				// Statement starts here
				seen_statement = true;
				for (j = 0; j < indentation_count; j++) {
					if (initial_spaces == indentation_levels[j]) {
						level = j;
						placed = true;
						break;
					}
				}
				if (!placed) {
					// This should never happen, because it means the initial
					// spaces was not present in the array
					// When we just did exactly the same loop over the array, we
					// should have encountered this statement
					// This means that something happened to either the
					// indentation_levels array or something happened to the
					// code
					*msg = createException(MAL, "pyapi.eval",
										   SQLSTATE(PY000) "If you see this error something "
										   "went wrong in the code. Sorry.");
					goto finally;
				}
				for (j = 0; j < (level + 1) * spaces_per_level; j++) {
					// Add spaces to the code
					newcode[code_location++] = ' ';
				}
			}
		}
		if (seen_statement) {
			// We have seen a statement on this line, copy it
			newcode[code_location++] = code[i];
			if (code[i] == '\n') {
				// The statement has ended, move on to the next line
				seen_statement = false;
				initial_spaces = 0;
				statement_size = 0;
			}
		}
	}
	newcode[code_location] = '\0';
	if (code_location >= size) {
		// Something went wrong with our size computation, this also should
		// never happen
		*msg = createException(MAL, "pyapi.eval",
							   SQLSTATE(PY000) "If you see this error something went wrong in "
							   "the code (size computation). Sorry.");
		goto finally;
	}
finally:
	GDKfree(indentation_levels);
	GDKfree(statements_per_level);
	return newcode;
}