static void add_sql(MidgardGroupConstraint *group, GString *sql) 
{
	g_assert(group != NULL);
        g_assert(sql != NULL);

	GSList *list = NULL;
	GSList *jlist = NULL;
	GSList *glist = NULL;
	guint i = 0;

	if(g_slist_length(group->constraints) == 0
			&& g_slist_length(group->nested) == 0) {
		
		g_string_append(sql, "1=1");
		return;
	}

	if(g_slist_length(group->constraints) == 1
			&& g_slist_length(group->nested) == 0) {
	
		g_string_append(sql,
				MIDGARD_CORE_QUERY_CONSTRAINT(group->constraints->data)->priv->condition);
		return;
	}

	g_string_append_c(sql, '(');
		
	for(list = group->constraints; list != NULL;
			list = list->next) {
		
		if(i > 0)
			g_string_append_printf(sql, " %s ", group->type);
		
		g_string_append(sql,
				MIDGARD_CORE_QUERY_CONSTRAINT(list->data)->priv->condition);
		i++;
	}

	for(glist = group->nested; glist != NULL;
			glist = glist->next) {
		
		if(i > 0)
			g_string_append_printf(sql, " %s ", group->type);
		
		MidgardGroupConstraint *ngroup = MIDGARD_GROUP_CONSTRAINT(glist->data);
		MidgardGroupConstraintClass *klass = MIDGARD_GROUP_CONSTRAINT_GET_CLASS(ngroup);
		
		klass->add_sql(ngroup, sql);

		i++;
	}

	g_string_append_c(sql, ')');

	list = NULL;

	for(list = group->constraints; list != NULL;
			list = list->next) {
		
		for(jlist = ((MidgardCoreQueryConstraint*)list->data)->priv->joins;
				jlist != NULL; jlist = jlist->next) {
			
			g_string_append(sql, " AND ");
			g_string_append(sql,
					((MidgardCoreQueryConstraintPrivate*)jlist->data)->condition);
		}
	}
}
gchar *midgard_core_qb_get_sql(
		MidgardQueryBuilder *builder, guint mode, gchar *select)
{
	g_assert (builder != NULL);
        g_assert (builder->priv->schema->table);    

        /* FIXME, error reporting needed */
        if (builder->priv->error != 0) {
		g_warning("Can not create query");
		return NULL;
        }	

	/* SELECT */
        GString *sql = g_string_new ("SELECT ");
	
	if (builder->priv->select_distinct)
		g_string_append (sql, "DISTINCT ");
	
	g_string_append (sql, select);
	g_free (select);

	/* FROM */
        g_string_append (sql, " FROM ");
	GSList *tlist = NULL;
	g_hash_table_foreach (builder->priv->tables, _add_table_foreach, &tlist);

	GString *tables = g_string_new ("");

	guint l = 0;
	GSList *nlist; 
	for (nlist = tlist; nlist != NULL; nlist = nlist->next) {
	
		if(l < 1)
			g_string_append(tables, (gchar *) nlist->data);
		else 
			g_string_append_printf(tables, 
					", %s", (gchar *) nlist->data);
		l++;
	}
	if(tlist)
		g_slist_free(tlist);

	g_string_append(sql, tables->str);

	/* WHERE */
        g_string_append(sql, " WHERE ");
	
	__sql_add_constraints(sql, builder);

	g_string_free(tables, TRUE);

	/* OR&AND groupings */
	guint i = 0;
	builder->priv->groups = g_slist_reverse(builder->priv->groups);
	
	if(builder->priv->groups != NULL) {
		
		if(builder->priv->constraints)
			g_string_append(sql, " AND ");
		
		GSList *glist = NULL;
		MidgardGroupConstraintClass *klass;
		
		for(glist = builder->priv->groups;
				glist != NULL; glist = glist->next) {
			
			if(i > 0)
				g_string_append(sql, " AND ");
			
			klass = MIDGARD_GROUP_CONSTRAINT_GET_CLASS(
					MIDGARD_GROUP_CONSTRAINT(glist->data));
			klass->add_sql(MIDGARD_GROUP_CONSTRAINT(glist->data), sql);
			
			i++;
		}
	}

	/* Join tables from ORDER BY */
	GSList *olist = NULL;
	GSList *jlist = NULL;
	if(builder->priv->orders != NULL) {

		for(olist = builder->priv->orders;
				olist != NULL; olist = olist->next) {
		
			for(jlist = ((MidgardQueryOrder*)olist->data)->constraint->priv->joins;
					jlist != NULL; jlist = jlist->next) {
				
				g_string_append(sql, " AND ");				
				g_string_append(sql,
						((MidgardCoreQueryConstraintPrivate*)jlist->data)->condition);                
			}
		}
	}

	/* Add joins */
	if(builder->priv->joins != NULL) {
		
		for(jlist = builder->priv->joins;
				jlist != NULL; jlist = jlist->next) {
		
			g_string_append(sql, " AND ");                          
			g_string_append(sql,
					((MidgardCoreQueryConstraintPrivate*)jlist->data)->condition);                
		}
	}

	MidgardDBObjectClass *dbklass = g_type_class_peek(builder->priv->type);

	if(!builder->priv->include_deleted) {

		const gchar *deleted_field = midgard_core_object_get_deleted_field (dbklass);	
		if (deleted_field) {
			g_string_append(sql, " AND ");
			g_string_append_printf(sql,
					" %s.%s = FALSE",
					builder->priv->schema->table, 
					deleted_field);
		}
	}

	/* ORDER BY */
	olist = NULL;
	i = 0;
	if(builder->priv->orders != NULL) {
		
		g_string_append(sql, " ORDER BY ");

		for(olist = builder->priv->orders; 
				olist != NULL; olist = olist->next) {

			if(i > 0)
				g_string_append(sql, ", ");
		
			MidgardQueryOrder *order = 
				(MidgardQueryOrder *)olist->data;
			g_string_append(sql,
					midgard_core_query_order_get_sql(order));

			i++;
		}
	}

        if (mode < MQB_SELECT_COUNT && builder->priv->limit != G_MAXUINT) 
		g_string_append_printf(sql, " LIMIT %u", builder->priv->limit);

	if (builder->priv->offset != 0) 
		g_string_append_printf(sql, " OFFSET %u", builder->priv->offset);

        return g_string_free(sql, FALSE);
}