Esempio n. 1
0
var_t *
exp_eval_operation(exp_t *exp, var_t *mailspec)
{
	var_t *left = NULL, *right = NULL, *copy;
	exp_operation_t *eo = exp->ex_data;
	var_t *result = NULL;
	var_type_t type;

	/*
	 * Variable assigment
	 */
	if (eo->eo_operator == '=')
	{
		return exp_assign(eo->eo_operand[0], eo->eo_operand[1],
		    mailspec);
	}

	/*
	 * isset operator
	 */
	if (eo->eo_operator == IS_SET)
	{
		return exp_isset(mailspec, eo->eo_operand[0]);
	}

	/*
	 * Do not load unneccessary symbols in boolean operations
	 */
	if (eo->eo_operator == AND || eo->eo_operator == OR)
	{
		result = exp_bool(mailspec, eo->eo_operator, eo->eo_operand[0],
			eo->eo_operand[1]);
		goto exit;
	}

	/*
 	 * Load left operand
 	 */
	left = exp_eval(eo->eo_operand[0], mailspec);

	/*
	 * ! operator
	 */
	if (eo->eo_operator == '!')
	{
		return exp_not(left);
	}

	/*
	 * Hack: IS_NULL operator
	 */
	if (eo->eo_operator == IS_NULL)
	{
		result = exp_is_null(left);
		goto exit;
	}

	/*
 	 * Evaluate right operand
 	 */
	if (eo->eo_operand[1])
	{
		right = exp_eval(eo->eo_operand[1], mailspec);
	}

	switch(eo->eo_operator)
	{
	// Comparator
	case '<':
	case '>':
	case LE:
	case GE:
	case EQ:
	case NE:
		result = exp_compare(eo->eo_operator, left, right);
		goto exit;

	// Regex
	case '~':
	case NR:
		result = exp_eval_regex(eo->eo_operator, left, right);
		goto exit;

	// In
	case IN:
		result = exp_eval_in(left, right);
		goto exit;



	// Address prefix operator
	case '/':
		if (left == NULL || right == NULL)
		{
			break;
		}
		if (!(left->v_type == VT_ADDR && right->v_type == VT_INT))
		{
			break;
		}

		result = exp_addr_prefix(left, right);
		goto exit;

	default:
		break;
	}

	// Math operators need left and right to be set
	if (left == NULL || right ==  NULL)
	{
		result = EXP_EMPTY;
		goto exit;
	}

	// Make sure we work with the same types
	if (left->v_type != right->v_type)
	{
		/*
		 * The biggest type has precedence (see exp.h)
		 * STRING > FLOAT > INT
		 */
		type = VAR_MAX_TYPE(left, right);

		if (type == left->v_type)
		{
			copy = var_cast_copy(type, right);
		}
		else
		{
			copy = var_cast_copy(type, left);
		}

		if (copy == NULL)
		{
			log_error("exp_eval_operation: var_cast_copy "
			    "failed");
			goto exit;
		}

		if (type == left->v_type)
		{
			exp_free(right);
			right = copy;
			right->v_flags |= VF_EXP_FREE;
		}
		else
		{
			exp_free(left);
			left = copy;
			left->v_flags |= VF_EXP_FREE;
		}
	}

	switch (left->v_type)
	{
	case VT_INT:
		result = exp_math_int(eo->eo_operator, left, right);
		break;

	case VT_FLOAT:
		result = exp_math_float(eo->eo_operator, left, right);
		break;

	case VT_STRING:
		result = exp_math_string(eo->eo_operator, left, right);
		break;

	default:
		log_error("exp_eval_operation: bad type");
		goto exit;
	}

exit:
	if (left)
	{
		exp_free(left);
	}

	if (right)
	{
		exp_free(right);
	}

	return result;
}
Esempio n. 2
0
sql_exp *
exp_copy( sql_allocator *sa, sql_exp * e)
{
	sql_exp *l, *r, *r2, *ne = NULL;

	switch(e->type){
	case e_column:
		ne = exp_column(sa, e->l, e->r, exp_subtype(e), e->card, has_nil(e), is_intern(e));
		ne->flag = e->flag;
		break;
	case e_cmp:
		if (e->flag == cmp_or) {
			list *l = exps_copy(sa, e->l);
			list *r = exps_copy(sa, e->r);
			if (l && r)
				ne = exp_or(sa, l,r);
		} else if (e->flag == cmp_in || e->flag == cmp_notin || get_cmp(e) == cmp_filter) {
			sql_exp *l = exp_copy(sa, e->l);
			list *r = exps_copy(sa, e->r);

			if (l && r) {
				if (get_cmp(e) == cmp_filter)
					ne = exp_filter(sa, l, r, e->f, is_anti(e));
				else
					ne = exp_in(sa, l, r, e->flag);
			}
		} else {
			l = exp_copy(sa, e->l);
			r = exp_copy(sa, e->r);

			if (e->f) {
				r2 = exp_copy(sa, e->f);
				if (l && r && r2)
					ne = exp_compare2(sa, l, r, r2, e->flag);
			} else if (l && r) {
				ne = exp_compare(sa, l, r, e->flag);
			}
		}
		break;
	case e_convert:
		l = exp_copy(sa, e->l);
		if (l)
			ne = exp_convert(sa, l, exp_fromtype(e), exp_totype(e));
		break;
	case e_aggr:
	case e_func: {
		list *l = e->l, *nl = NULL;

		if (!l) {
			return e;
		} else {
			nl = exps_copy(sa, l);
			if (!nl)
				return NULL;
		}
		if (e->type == e_func)
			ne = exp_op(sa, nl, e->f);
		else 
			ne = exp_aggr(sa, nl, e->f, need_distinct(e), need_no_nil(e), e->card, has_nil(e));
		break;
	}	
	case e_atom:
		if (e->l)
			ne = exp_atom(sa, e->l);
		else if (!e->r)
			ne = exp_atom_ref(sa, e->flag, &e->tpe);
		else 
			ne = exp_param(sa, e->r, &e->tpe, e->flag);
		break;
	case e_psm:
		if (e->flag == PSM_SET) 
			ne = exp_set(sa, e->name, exp_copy(sa, e->l), GET_PSM_LEVEL(e->flag));
		break;
	}
	if (ne && e->p)
		ne->p = prop_copy(sa, e->p);
	if (e->name)
		exp_setname(sa, ne, exp_find_rel_name(e), exp_name(e));
	return ne;
}