コード例 #1
0
ファイル: rel_psm.c プロジェクト: MonetDB/MonetDB
static sql_exp * 
rel_psm_if_then_else( mvc *sql, sql_subtype *res, list *restypelist, dnode *elseif, int is_func)
{
	if (!elseif)
		return NULL;
	if (elseif->next && elseif->type == type_symbol) { /* if or elseif */
		sql_exp *cond;
		list *ifstmts, *elsestmts;
		dnode *n = elseif;
		sql_rel *rel = NULL;

		cond = rel_logical_value_exp(sql, &rel, n->data.sym, sql_sel); 
		n = n->next;
		ifstmts = sequential_block(sql, res, restypelist, n->data.lval, NULL, is_func);
		n = n->next;
		elsestmts = psm_if_then_else( sql, res, restypelist, n, is_func);
		if (sql->session->status || !cond || !ifstmts) 
			return NULL;
		if (rel) {
			sql_exp *er = exp_rel(sql, rel);
			list *b = sa_list(sql->sa);

			append(b, er);
			append(b, exp_if(sql->sa, cond, ifstmts, elsestmts));
			return exp_rel(sql, rel_psm_block(sql->sa, b));
		}
		return exp_if( sql->sa, cond, ifstmts, elsestmts);
	}
	return NULL;
}
コード例 #2
0
ファイル: rel_psm.c プロジェクト: MonetDB/MonetDB
/* [ label: ]
   while (cond) do 
	statement_list
   end [ label ]
   currently we only parse the labels, they cannot be used as there is no

   support for LEAVE and ITERATE (sql multi-level break and continue)
 */
static sql_exp * 
rel_psm_while_do( mvc *sql, sql_subtype *res, list *restypelist, dnode *w, int is_func )
{
	if (!w)
		return NULL;
	if (w->type == type_symbol) { 
		sql_exp *cond;
		list *whilestmts;
		dnode *n = w;
		sql_rel *rel = NULL;

		cond = rel_logical_value_exp(sql, &rel, n->data.sym, sql_sel); 
		n = n->next;
		whilestmts = sequential_block(sql, res, restypelist, n->data.lval, n->next->data.sval, is_func);

		if (sql->session->status || !cond || !whilestmts) 
			return NULL;
		if (rel) {
			sql_exp *er = exp_rel(sql, rel);
			list *b = sa_list(sql->sa);

			append(b, er);
			append(b, exp_while( sql->sa, cond, whilestmts ));
			return exp_rel(sql, rel_psm_block(sql->sa, b));
		}
		return exp_while( sql->sa, cond, whilestmts );
	}
	return NULL;
}
コード例 #3
0
ファイル: rel_psm.c プロジェクト: jaiminpan/Monetdb
/* SET variable = value */
static sql_exp *
psm_set_exp(mvc *sql, dnode *n)
{
	exp_kind ek = {type_value, card_value, FALSE};
	char *name = n->data.sval;
	symbol *val = n->next->data.sym;
	sql_exp *e = NULL;
	int level = 0, is_last = 0;
	sql_subtype *tpe = NULL;
	sql_rel *rel = NULL;
	sql_exp *res = NULL;

	/* name can be 
		'parameter of the function' (ie in the param list)
		or a local or global variable, declared earlier
	*/

	/* check if variable is known from the stack */
	if (!stack_find_var(sql, name)) {
		sql_arg *a = sql_bind_param(sql, name);

		if (!a) /* not parameter, ie local var ? */
			return sql_error(sql, 01, "Variable %s unknown", name);
		tpe = &a->type;
	} else { 
		tpe = stack_find_type(sql, name);
	}

	e = rel_value_exp2(sql, &rel, val, sql_sel, ek, &is_last);
	if (!e || (rel && e->card > CARD_AGGR))
		return NULL;

	level = stack_find_frame(sql, name);
	e = rel_check_type(sql, tpe, e, type_cast); 
	if (!e)
		return NULL;
	if (rel) {
		sql_exp *er = exp_rel(sql, rel);
		list *b = sa_list(sql->sa);

		append(b, er);
		append(b, exp_set(sql->sa, name, e, level));
		res = exp_rel(sql, rel_psm_block(sql->sa, b));
	} else {
		res = exp_set(sql->sa, name, e, level);
	}
	return res;
}
コード例 #4
0
ファイル: rel_psm.c プロジェクト: jaiminpan/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, "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;
}
コード例 #5
0
ファイル: rel_psm.c プロジェクト: MonetDB/MonetDB
/* if (cond) then statement_list
   [ elseif (cond) then statement_list ]*
   [ else statement_list ]
   end if
 */
static list * 
psm_if_then_else( mvc *sql, sql_subtype *res, list *restypelist, dnode *elseif, int is_func)
{
	if (!elseif)
		return NULL;
	assert(elseif->type == type_symbol); 
	if (elseif->data.sym && elseif->data.sym->token == SQL_IF) {
		sql_exp *cond;
		list *ifstmts, *elsestmts;
		dnode *n = elseif->data.sym->data.lval->h;
		sql_rel *rel = NULL;

		cond = rel_logical_value_exp(sql, &rel, n->data.sym, sql_sel); 
		n = n->next;
		ifstmts = sequential_block(sql, res, restypelist, n->data.lval, NULL, is_func);
		n = n->next;
		elsestmts = psm_if_then_else( sql, res, restypelist, n, is_func);

		if (sql->session->status || !cond || !ifstmts) 
			return NULL;
		if (rel) {
			sql_exp *er = exp_rel(sql, rel);
			list *b = sa_list(sql->sa);

			append(b, er);
			append(b, exp_if(sql->sa, cond, ifstmts, elsestmts));
			return b;
		}
		return append(sa_list(sql->sa), exp_if( sql->sa, cond, ifstmts, elsestmts));
	} else { /* else */
		symbol *e = elseif->data.sym;

		if (e==NULL || (e->token != SQL_ELSE))
			return NULL;
		return sequential_block( sql, res, restypelist, e->data.lval, NULL, is_func);
	}
}
コード例 #6
0
ファイル: rel_psm.c プロジェクト: jaiminpan/Monetdb
static list *
sequential_block (mvc *sql, sql_subtype *restype, list *restypelist, dlist *blk, char *opt_label, int is_func) 
{
	list *l=0;
	dnode *n;

	assert(!restype || !restypelist);

 	if (THRhighwater())
		return sql_error(sql, 10, "SELECT: too many nested operators");

	if (blk->h)
 		l = sa_list(sql->sa);
	stack_push_frame(sql, opt_label);
	for (n = blk->h; n; n = n->next ) {
		sql_exp *res = NULL;
		list *reslist = NULL;
		symbol *s = n->data.sym;

		switch (s->token) {
		case SQL_SET:
			res = psm_set_exp(sql, s->data.lval->h);
			break;
		case SQL_DECLARE:
			reslist = rel_psm_declare(sql, s->data.lval->h);
			break;
		case SQL_CREATE_TABLE: 
			res = rel_psm_declare_table(sql, s->data.lval->h);
			break;
		case SQL_WHILE:
			res = rel_psm_while_do(sql, restype, s->data.lval->h, is_func);
			break;
		case SQL_IF:
			res = rel_psm_if_then_else(sql, restype, s->data.lval->h, is_func);
			break;
		case SQL_CASE:
			reslist = rel_psm_case(sql, restype, s->data.lval->h, is_func);
			break;
		case SQL_CALL:
			res = rel_psm_call(sql, s->data.sym);
			break;
		case SQL_RETURN:
			/*If it is not a function it cannot have a return statement*/
			if (!is_func)
				res = sql_error(sql, 01, 
					"Return statement in the procedure body");
			else {
				/* should be last statement of a sequential_block */
				if (n->next) { 
					res = sql_error(sql, 01, 
						"Statement after return");
				} else {
					reslist = rel_psm_return(sql, restype, restypelist, s->data.sym);
				}
			}
			break;
		case SQL_SELECT: { /* row selections (into variables) */
			exp_kind ek = {type_value, card_row, TRUE};
			reslist = rel_select_into(sql, s, ek);
		}	break;
		case SQL_COPYFROM:
		case SQL_BINCOPYFROM:
		case SQL_INSERT:
		case SQL_UPDATE:
		case SQL_DELETE: {
			sql_rel *r = rel_updates(sql, s);
			if (!r)
				return NULL;
			res = exp_rel(sql, r);
		}	break;
		default:
			res = sql_error(sql, 01, 
			 "Statement '%s' is not a valid flow control statement",
			 token2string(s->token));
		}
		if (!res && !reslist) {
			l = NULL;
			break;
		}
		if (res)
			list_append(l, res);
		else
			list_merge(l, reslist, NULL);
	}
	stack_pop_frame(sql);
	return l;
}
コード例 #7
0
ファイル: rel_psm.c プロジェクト: jaiminpan/Monetdb
/* 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;
}
コード例 #8
0
ファイル: rel_psm.c プロジェクト: MonetDB/MonetDB
/* SET variable = value and set (variable1, .., variableN) = (query) */
static sql_exp *
psm_set_exp(mvc *sql, dnode *n)
{
	symbol *val = n->next->data.sym;
	sql_exp *e = NULL;
	int level = 0, is_last = 0;
	sql_subtype *tpe = NULL;
	sql_rel *rel = NULL;
	sql_exp *res = NULL;
	int single = (n->type == type_string);


	if (single) {
		exp_kind ek = {type_value, card_value, FALSE};
		const char *name = n->data.sval;
		/* name can be 
			'parameter of the function' (ie in the param list)
			or a local or global variable, declared earlier
		*/

		/* check if variable is known from the stack */
		if (!stack_find_var(sql, name)) {
			sql_arg *a = sql_bind_param(sql, name);

			if (!a) /* not parameter, ie local var ? */
				return sql_error(sql, 01, SQLSTATE(42000) "Variable %s unknown", name);
			tpe = &a->type;
		} else { 
			tpe = stack_find_type(sql, name);
		}

		e = rel_value_exp2(sql, &rel, val, sql_sel, ek, &is_last);
		if (!e || (rel && e->card > CARD_AGGR))
			return NULL;

		level = stack_find_frame(sql, name);
		e = rel_check_type(sql, tpe, e, type_cast); 
		if (!e)
			return NULL;
		if (rel) {
			sql_exp *er = exp_rel(sql, rel);
			list *b = sa_list(sql->sa);

			append(b, er);
			append(b, exp_set(sql->sa, name, e, level));
			res = exp_rel(sql, rel_psm_block(sql->sa, b));
		} else {
			res = exp_set(sql->sa, name, e, level);
		}
	} else { /* multi assignment */
		exp_kind ek = {type_value, (single)?card_column:card_relation, FALSE};
		sql_rel *rel_val = rel_subquery(sql, NULL, val, ek, APPLY_JOIN);
		dlist *vars = n->data.lval;
		dnode *m;
		node *n;
		list *b;

		if (!rel_val || !is_project(rel_val->op) ||
			    dlist_length(vars) != list_length(rel_val->exps)) {
			return sql_error(sql, 02, SQLSTATE(42000) "SET: Number of variables not equal to number of supplied values");
		}

	       	b = sa_list(sql->sa);
		if (rel_val) {
			sql_exp *er = exp_rel(sql, rel_val);

			append(b, er);
		}

		for(m = vars->h, n = rel_val->exps->h; n && m; n = n->next, m = m->next) {
			char *vname = m->data.sval;
			sql_exp *v = n->data;

			if (!stack_find_var(sql, vname)) {
				sql_arg *a = sql_bind_param(sql, vname);

				if (!a) /* not parameter, ie local var ? */
					return sql_error(sql, 01, SQLSTATE(42000) "Variable %s unknown", vname);
				tpe = &a->type;
			} else { 
				tpe = stack_find_type(sql, vname);
			}

			if (!exp_name(v))
				exp_label(sql->sa, v, ++sql->label);
			v = exp_column(sql->sa, exp_relname(v), exp_name(v), exp_subtype(v), v->card, has_nil(v), is_intern(v));

			level = stack_find_frame(sql, vname);
			v = rel_check_type(sql, tpe, v, type_cast); 
			if (!v)
				return NULL;
			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);
			}
			append(b, exp_set(sql->sa, vname, v, level));
		}
		res = exp_rel(sql, rel_psm_block(sql->sa, b));
	}
	return res;
}
コード例 #9
0
ファイル: rel_psm.c プロジェクト: MonetDB/MonetDB
sql_rel *
rel_psm(mvc *sql, symbol *s)
{
	sql_rel *ret = NULL;

	switch (s->token) {
	case SQL_CREATE_FUNC:
	{
		dlist *l = s->data.lval;
		int type = l->h->next->next->next->next->next->data.i_val;
		int lang = l->h->next->next->next->next->next->next->data.i_val;
		int repl = l->h->next->next->next->next->next->next->next->data.i_val;

		ret = rel_create_func(sql, l->h->data.lval, l->h->next->data.lval, l->h->next->next->data.sym, l->h->next->next->next->data.lval, l->h->next->next->next->next->data.lval, type, lang, repl);
		sql->type = Q_SCHEMA;
	} 	break;
	case SQL_DROP_FUNC:
	{
		dlist *l = s->data.lval;
		dlist *qname = l->h->data.lval;
		dlist *typelist = l->h->next->data.lval;
		int type = l->h->next->next->data.i_val;
		int if_exists = l->h->next->next->next->data.i_val;
		int all = l->h->next->next->next->next->data.i_val;
		int drop_action = l->h->next->next->next->next->next->data.i_val;

		if (STORE_READONLY) 
			return sql_error(sql, 06, SQLSTATE(42000) "Schema statements cannot be executed on a readonly database.");
			
		if (all)
			ret = rel_drop_all_func(sql, qname, drop_action, type);
		else {
			ret = rel_drop_func(sql, qname, typelist, drop_action, type, if_exists);
		}

		sql->type = Q_SCHEMA;
	}	break;
	case SQL_SET:
		ret = rel_psm_stmt(sql->sa, psm_set_exp(sql, s->data.lval->h));
		sql->type = Q_SCHEMA;
		break;
	case SQL_DECLARE:
		ret = rel_psm_block(sql->sa, rel_psm_declare(sql, s->data.lval->h));
		sql->type = Q_SCHEMA;
		break;
	case SQL_CALL:
		ret = rel_psm_stmt(sql->sa, rel_psm_call(sql, s->data.sym));
		sql->type = Q_UPDATE;
		break;
	case SQL_CREATE_TABLE_LOADER:
	{
	    dlist *l = s->data.lval;
	    dlist *qname = l->h->data.lval;
	    symbol *sym = l->h->next->data.sym;

	    ret = create_table_from_loader(sql, qname, sym);
	    if (ret == NULL)
		    return NULL;
	    ret = rel_psm_stmt(sql->sa, exp_rel(sql, ret));
	    sql->type = Q_SCHEMA;
	}	break;
	case SQL_CREATE_TRIGGER:
	{
		dlist *l = s->data.lval;

		assert(l->h->next->type == type_int);
		ret = create_trigger(sql, l->h->data.lval, l->h->next->data.i_val, l->h->next->next->data.sym, l->h->next->next->next->data.lval, l->h->next->next->next->next->data.lval, l->h->next->next->next->next->next->data.lval, l->h->next->next->next->next->next->next->data.i_val);
		sql->type = Q_SCHEMA;
	}
		break;

	case SQL_DROP_TRIGGER:
	{
		dlist *l = s->data.lval;
		dlist *qname = l->h->data.lval;
		int if_exists = l->h->next->data.i_val;

		ret = drop_trigger(sql, qname, if_exists);
		sql->type = Q_SCHEMA;
	}
		break;

	case SQL_ANALYZE: {
		dlist *l = s->data.lval;

		ret = psm_analyze(sql, "analyze", l->h->data.lval /* qualified table name */, l->h->next->data.lval /* opt list of column */, l->h->next->next->data.sym /* opt_sample_size */, l->h->next->next->next->data.i_val);
		sql->type = Q_UPDATE;
	} 	break;
	default:
		return sql_error(sql, 01, SQLSTATE(42000) "Schema statement unknown symbol(%p)->token = %s", s, token2string(s->token));
	}
	return ret;
}