// midgard_query_constraint_group
static PHP_METHOD(midgard_query_constraint_group, __construct)
{
	char *type = "AND";
	int type_len = 3, num_varargs = 0;
	zval ***varargs = NULL;

#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 2
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &type, &type_len) == FAILURE) {
		zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Failed to create constraint group");
	    return;
	}
#else
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s*", &type, &type_len, &varargs, &num_varargs) == FAILURE) {
		zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Failed to create constraint group");
	    return;
	}
#endif

	MidgardQueryConstraintGroup *constraint_group = NULL;

	if (num_varargs) {
		MidgardQueryConstraintSimple **constraints = ecalloc(num_varargs, sizeof(MidgardQueryConstraintSimple *));

		size_t i;
		for (i = 0; i < num_varargs; i++) {
			constraints[i] = MIDGARD_QUERY_CONSTRAINT_SIMPLE(__php_gobject_ptr(*varargs[i]));
		}
		efree(varargs);

		constraint_group = midgard_query_constraint_group_new_with_constraints(type, constraints, num_varargs);
		efree(constraints);

		if (!constraint_group) {
			zend_throw_exception_ex(ce_midgard_error_exception, 0 TSRMLS_CC, "Failed to create constraint group");
			return;
		}
	} else {
		constraint_group = midgard_query_constraint_group_new();

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

		zend_bool result = midgard_query_constraint_group_set_group_type(constraint_group, type);

		if (!result) {
			g_object_unref(constraint_group);
			zend_throw_exception_ex(ce_midgard_error_exception, 0 TSRMLS_CC, "Failed to create constraint group: couldn't set type");
			return;
		}
	}

	MGD_PHP_SET_GOBJECT(getThis(), constraint_group);
}
static PHP_METHOD(midgard_query_constraint_group, add_constraint)
{
	zval *z_constraint = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &z_constraint, php_midgard_query_constraint_simple_class) == FAILURE) {
		return;
	}

	MidgardQueryConstraintGroup *constraint_group = MIDGARD_QUERY_CONSTRAINT_GROUP(__php_gobject_ptr(getThis()));
	MidgardQueryConstraintSimple *constraint = MIDGARD_QUERY_CONSTRAINT_SIMPLE(__php_gobject_ptr(z_constraint));

	zend_bool result = midgard_query_constraint_group_add_constraint(constraint_group, constraint, NULL);

	RETURN_BOOL(result);
}
// midgard_query_constraint_simple
static PHP_METHOD(midgard_query_constraint_simple, list_constraints)
{
	if (zend_parse_parameters_none() == FAILURE)
		return;

	MidgardQueryConstraintSimple *object = MIDGARD_QUERY_CONSTRAINT_SIMPLE(__php_gobject_ptr(getThis()));

	guint n_objects;
	MidgardQueryConstraintSimple **constraints = midgard_query_constraint_simple_list_constraints(object, &n_objects);

	array_init(return_value);

	if (constraints) {
		php_midgard_array_from_constraints(constraints, n_objects, return_value TSRMLS_CC);
        g_free(constraints);
	}
}
void
_midgard_query_group_add_conditions_to_statement (MidgardQueryExecutor *executor, MidgardQueryConstraintSimple *self, 
		GdaSqlStatement *stmt, GdaSqlExpr *where_expr_node, GError **error)
{	
	guint n_objects;
	guint i;
	MidgardQueryConstraintSimple **constraints = 
		midgard_query_constraint_simple_list_constraints (MIDGARD_QUERY_CONSTRAINT_SIMPLE (self), &n_objects);
	if (!constraints)
		return;

	GdaSqlStatementSelect *select = stmt->contents;
	GdaSqlExpr *top_where = NULL, *where;
	GdaSqlOperation *top_operation, *operation;	
	
	/* Create base top expression and operation */
	if (!select->where_cond) {
		top_where = gda_sql_expr_new (GDA_SQL_ANY_PART (select));
		top_operation = gda_sql_operation_new (GDA_SQL_ANY_PART (top_where));
		top_operation->operator_type = MIDGARD_QUERY_CONSTRAINT_GROUP (self)->priv->op_type;
		top_where->cond = top_operation;
	     	gda_sql_statement_select_take_where_cond (stmt, top_where);	
	} else if (where_expr_node) {
		/* This is nested groups case: '... AND (f2=1 OR f2=2)...' */
		where = where_expr_node;
		operation = where->cond;
		top_where = gda_sql_expr_new (GDA_SQL_ANY_PART (operation));
		top_operation = gda_sql_operation_new (GDA_SQL_ANY_PART (where_expr_node));
		top_operation->operator_type = MIDGARD_QUERY_CONSTRAINT_GROUP (self)->priv->op_type;
		top_where->cond = top_operation;
		operation->operands = g_slist_append (operation->operands, top_where);
	}

	for (i = 0; i < n_objects; i++) {

		GError *err = NULL;
		MIDGARD_QUERY_CONSTRAINT_SIMPLE_GET_INTERFACE (constraints[i])->priv->add_conditions_to_statement (executor, MIDGARD_QUERY_CONSTRAINT_SIMPLE (constraints[i]), stmt, top_where, &err);
		if (err)
			g_propagate_error (error, err);
	}

	g_free (constraints);
}