gboolean __query_select_add_orders (MidgardQueryExecutor *self, GError **error)
{
	if (!self->priv->orders)
		return TRUE;

	GSList *l = NULL;

	MidgardQueryExecutor *executor = MIDGARD_QUERY_EXECUTOR (self);
	GdaSqlStatement *sql_stm = executor->priv->stmt;
	GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) sql_stm->contents;	
	GdaSqlSelectOrder *order; 
	
	for (l = MIDGARD_QUERY_EXECUTOR (self)->priv->orders; l != NULL; l = l->next) {

		/* Proper asc type is set during validation phase */
		qso *_so = (qso*) l->data;

		/* Create new order */
		order = gda_sql_select_order_new (GDA_SQL_ANY_PART (select));
		order->asc = _so->asc;
		MidgardQueryProperty *property = _so->property;
		MidgardQueryStorage *storage = NULL;
		
		if (property->priv && property->priv->storage)
			storage = property->priv->storage;

		/* Compute table.colname for given property name */
		GValue rval = {0, };
		midgard_query_holder_get_value (MIDGARD_QUERY_HOLDER (property), &rval);
		GError *err = NULL;
		gchar *table_field = midgard_core_query_compute_constraint_property (executor, storage, g_value_get_string (&rval), &err);
		if (err) {
			g_propagate_error (error, err);
			g_free (table_field);
			gda_sql_select_order_free (order);
			return FALSE;
		}

		if (!table_field) {
			g_set_error (error, MIDGARD_VALIDATION_ERROR, MIDGARD_VALIDATION_ERROR_LOCATION_INVALID,
					"Can not find table and column name for given '%s' property name", g_value_get_string (&rval));
			g_value_unset (&rval);
			return FALSE;	
		}

		g_value_unset (&rval);

		GValue *value = g_new0 (GValue, 1);
		g_value_init (value, G_TYPE_STRING);
		g_value_take_string (value, table_field);

		/* Set order's expression and add new one to statement orders list */
		GdaSqlExpr *expr = gda_sql_expr_new (GDA_SQL_ANY_PART (order));
		expr->value = value;
		order->expr = expr;
		select->order_by = g_slist_append (select->order_by, order);
	}

	return TRUE;
}
static PHP_METHOD(midgard_sql_query_constraint, __construct)
{
	zval *z_column = NULL;
	char *operator = NULL;
	int op_length = 0;
	zval *z_holder = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO",
				&z_column, php_midgard_sql_query_column_class,
				&operator, &op_length, 
				&z_holder, php_midgard_query_holder_class
				) == FAILURE
	   ) {
		return;
	}

	MidgardSqlQueryColumn *column = MIDGARD_SQL_QUERY_COLUMN(__php_gobject_ptr(z_column));
	MidgardQueryHolder *holder = MIDGARD_QUERY_HOLDER(__php_gobject_ptr(z_holder));
	MidgardSqlQueryConstraint *constraint = midgard_sql_query_constraint_new(column, operator, holder);
	if (!column) {
		zend_throw_exception_ex(ce_midgard_error_exception, 0 TSRMLS_CC, "Failed to create SqlQueryColumn");
		return;
	}
	MGD_PHP_SET_GOBJECT(getThis(), constraint);
}
// midgard_query_constraint
static PHP_METHOD(midgard_query_constraint, __construct)
{
	char *operator = NULL;
	int operator_len = 0;
	zval *z_property = NULL;
	zval *z_holder = NULL;
	zval *z_storage = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|O",
			&z_property, php_midgard_query_property_class,
			&operator, &operator_len,
			&z_holder, php_midgard_query_holder_class,
			&z_storage, php_midgard_query_storage_class
			) == FAILURE
	) {
		return;
	}

	MidgardQueryProperty *property = MIDGARD_QUERY_PROPERTY(__php_gobject_ptr(z_property));
	MidgardQueryHolder   *holder   = MIDGARD_QUERY_HOLDER(__php_gobject_ptr(z_holder));
	MidgardQueryStorage  *storage  = NULL; 

	if (z_storage) {
		storage = MIDGARD_QUERY_STORAGE(__php_gobject_ptr(z_storage));
	}

	MidgardQueryConstraint *constraint = midgard_query_constraint_new(property, operator, holder, storage);

	if (!constraint) {
		zend_throw_exception_ex(ce_midgard_error_exception, 0 TSRMLS_CC, "Failed to create constraint");
		return;
	}

	MGD_PHP_SET_GOBJECT(getThis(), constraint);
}
void 
_midgard_sql_query_constraint_add_conditions_to_statement (MidgardQueryExecutor *executor, MidgardQueryConstraintSimple *constraint_simple, GdaSqlStatement *stmt, GdaSqlExpr *where_expr_node, GError **error)
{	
	MidgardSqlQueryConstraint *self = MIDGARD_SQL_QUERY_CONSTRAINT (constraint_simple);
	MidgardConnection *mgd = executor->priv->mgd;
	GdaConnection *cnc = mgd->priv->connection;

	GdaSqlStatementSelect *select = stmt->contents;
	GdaSqlExpr *top_where, *where, *expr;
	GdaSqlOperation *top_operation, *cond;
	GValue *value;

	/* Create table_alias.field name */
	MidgardSqlQueryColumn *column = midgard_sql_query_constraint_get_column (self);
	gchar *table_alias_field = get_real_table_field (executor, column);
	g_object_unref (column);

	if (!table_alias_field) {
		/* TODO */
		/* Handle error */
	}

	if (where_expr_node) {
		top_where = where_expr_node;
		top_operation = top_where->cond;
	} else {
		top_where = select->where_cond;
		top_operation = top_where->cond;
	}

	where = gda_sql_expr_new (GDA_SQL_ANY_PART (top_operation));
	top_operation->operands = g_slist_append (top_operation->operands, where);

	cond = gda_sql_operation_new (GDA_SQL_ANY_PART (where));
	where->cond = cond;	
	cond->operator_type = self->priv->op_type;

	expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
	g_value_take_string ((value = gda_value_new (G_TYPE_STRING)), table_alias_field);
	expr->value = value;
	cond->operands = g_slist_append (cond->operands, expr);
	expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));	

	/* Create value */
	GValue val = {0, };
	midgard_query_holder_get_value (MIDGARD_QUERY_HOLDER (self->priv->holder), &val);
	//FIXME, create parameter name::type */
	expr->value = gda_value_new (G_TYPE_STRING);
	GString *str = g_string_new ("");
	__get_expression_value (cnc, &val, str);
	g_value_take_string (expr->value, g_string_free (str, FALSE));
	g_value_unset (&val);
	cond->operands = g_slist_append (cond->operands, expr);

	/* increase executor's constraints number */
	executor->priv->n_constraints++;
}
static void
__midgard_query_property_get_property (GObject *object, guint property_id,
		GValue *value, GParamSpec *pspec)
{
	MidgardQueryProperty *self = (MidgardQueryProperty *) object;

	switch (property_id) {
		
		case MIDGARD_QUERY_PROPERTY_PROPNAME:
			__get_value (MIDGARD_QUERY_HOLDER (object), value);
			break;

		case MIDGARD_QUERY_PROPERTY_STORAGE:
			g_value_set_object (value, self->priv->storage);
			break;

		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
			break;
	}
}
void 
_midgard_query_constraint_add_conditions_to_statement (MidgardQueryExecutor *executor, MidgardQueryConstraintSimple *constraint_simple, GdaSqlStatement *stmt, GdaSqlExpr *where_expr_node)
{	
	MidgardQueryConstraint *self = MIDGARD_QUERY_CONSTRAINT (constraint_simple);
	//GdaConnection *cnc = executor->priv->mgd->priv->connection;
	MidgardDBObjectClass *dbklass = NULL;	
       	if (self->priv->storage && (self->priv->storage != MIDGARD_QUERY_EXECUTOR (executor)->priv->storage)) {
	       dbklass = self->priv->storage->priv->klass;
	       MQE_SET_TABLE_ALIAS (executor, self->priv->storage);
	}
	if (!dbklass)
		dbklass = executor->priv->storage->priv->klass;
	g_return_if_fail (dbklass != NULL);

	/* Get table */
	//const gchar *table = midgard_core_class_get_table (dbklass);	

	/* Get field name */
	GValue field_value = {0, };
	midgard_query_holder_get_value (MIDGARD_QUERY_HOLDER (MIDGARD_QUERY_CONSTRAINT (constraint_simple)->priv->property_value), &field_value);

	GdaSqlStatementSelect *select = stmt->contents;
	GdaSqlExpr *top_where, *where, *expr;
	GdaSqlOperation *top_operation, *cond;
	GValue *value;

	if (where_expr_node) {
		top_where = where_expr_node;
		top_operation = top_where->cond;
	} else {
		top_where = select->where_cond;
		top_operation = top_where->cond;
	}

	where = gda_sql_expr_new (GDA_SQL_ANY_PART (top_operation));
	top_operation->operands = g_slist_append (top_operation->operands, where);

	cond = gda_sql_operation_new (GDA_SQL_ANY_PART (where));
	where->cond = cond;	
	cond->operator_type = self->priv->op_type;

	/* Create table_alias.field name */
	gchar *table_alias_field;
	expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));
	table_alias_field = midgard_core_query_compute_constraint_property (executor, 
			MIDGARD_QUERY_CONSTRAINT (constraint_simple)->priv->storage, g_value_get_string (&field_value));
	if (!table_alias_field)
		g_warning ("Null table.field alias for given '%s'", g_value_get_string (&field_value));
	/* TODO, handle error case when table_alias_field is NULL */
	g_value_take_string ((value = gda_value_new (G_TYPE_STRING)), table_alias_field);
	expr->value = value;
	cond->operands = g_slist_append (cond->operands, expr);
	expr = gda_sql_expr_new (GDA_SQL_ANY_PART (cond));

	/* Create value */
	GValue val = {0, };
	midgard_query_holder_get_value (MIDGARD_QUERY_CONSTRAINT (constraint_simple)->priv->holder, &val);
	/*GType v_type = G_VALUE_TYPE (&val);
	//FIXME, create parameter name::type */
	//GValue *dval = gda_value_new (G_TYPE_STRING);
	//g_value_transform (&val, dval);
	//expr->param_spec = gda_sql_param_spec_new (dval);
	//expr->param_spec->g_type = v_type;
	expr->value = gda_value_new (G_TYPE_STRING);
	__set_expression_value (expr->value, &val);
	g_value_unset (&val);
	cond->operands = g_slist_append (cond->operands, expr);

	/* increase executor's constraints number */
	executor->priv->n_constraints++;
}
gboolean __query_select_add_joins (MidgardQuerySelect *self, GdaSqlOperation *operation, GError **error)
{
	__add_implicit_workspace_join (self, operation);

	if (!MIDGARD_QUERY_EXECUTOR (self)->priv->joins)
		return TRUE;

	GSList *l = NULL;

	MidgardQueryExecutor *executor = MIDGARD_QUERY_EXECUTOR (self);
	GdaSqlStatement *sql_stm = executor->priv->stmt;
	GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) sql_stm->contents;	
	GdaSqlSelectFrom *from = select->from;
	GdaSqlSelectJoin *join; 
	
	for (l = MIDGARD_QUERY_EXECUTOR (self)->priv->joins; l != NULL; l = l->next) {

		qsj *_sj = (qsj*) l->data;

		join = gda_sql_select_join_new (GDA_SQL_ANY_PART (from));
		join->type = _sj->join_type;

		MidgardQueryStorage *left_storage = _sj->left_property->priv->storage;
		MidgardQueryStorage *right_storage = _sj->right_property->priv->storage;

		GError *err = NULL;
		GValue lval = {0, };
		midgard_query_holder_get_value (MIDGARD_QUERY_HOLDER (_sj->left_property), &lval);
		gchar *left_table_field = 
			midgard_core_query_compute_constraint_property (executor, left_storage, g_value_get_string (&lval), &err);
		if (err) {
			g_propagate_error (error, err);
			g_free (left_table_field);
		}

		GValue rval = {0, };
		midgard_query_holder_get_value (MIDGARD_QUERY_HOLDER (_sj->right_property), &rval);
		gchar *right_table_field = 
			midgard_core_query_compute_constraint_property (executor, right_storage, g_value_get_string (&rval), &err);
		if (err) {
			g_propagate_error (error, err);
			g_free (right_table_field);
		}

		GdaSqlExpr *expr = gda_sql_expr_new (GDA_SQL_ANY_PART (join));
		expr->value = gda_value_new (G_TYPE_STRING);
		g_value_take_string (expr->value, g_strdup_printf ("%s = %s", left_table_field, right_table_field));

		join->expr = expr;
		join->position = ++executor->priv->joinid;

		/* Add right storage to targets */
		MQE_SET_TABLE_ALIAS (executor, right_storage);
		gda_sql_select_from_take_new_join (from , join);
		GdaSqlSelectTarget *s_target = gda_sql_select_target_new (GDA_SQL_ANY_PART (from));
		s_target->table_name = g_strdup (right_storage->priv->table);
		s_target->as = g_strdup (right_storage->priv->table_alias);
		gda_sql_select_from_take_new_target (from, s_target);
	
		// Set target expression 
		GdaSqlExpr *texpr = gda_sql_expr_new (GDA_SQL_ANY_PART (s_target));
		GValue *tval = g_new0 (GValue, 1);
		g_value_init (tval, G_TYPE_STRING);
		g_value_set_string (tval, right_storage->priv->table);
		texpr->value = tval;
		s_target->expr = texpr;
	}

	return TRUE;
}