Un wrapping de l'api Mysql en C++
	
	
		Bonjour à tous et à toutes,
J'ai décidé de faire un wrapping de l'api mysql en c++ afin de m'entraîner un peu et également l'utiliser pour après.
J'aimerais que vous me donniez des conseils car je trouve que mon code est un peu beaucoup crado :D
C'est plus le principe du code qui me gène que la façon dont je l'ai disposé dans les fichiers.
Voici mon fichier h qui regroupe plusieurs classes pour éviter d'avoir 60 fichiers à inclure :
	Code:
	
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
   | #ifndef DEF_MYSQL
#define DEF_MYSQL
 
#include <winsock.h>
#include <MYSQL/mysql.h>
#include <string>
#include <vector>
using namespace std;
 
struct MySqlDonnes
{
    string name;
    string value;
};
 
class MySqlResultArray
{
    public:
        MySqlResultArray(){};
        MySqlResultArray(const vector<MySqlDonnes>& row);
        string operator>>(const string& str) const;
 
    protected:
        vector<MySqlDonnes> m_row;
};
 
class MySqlResult
{
    public:
        MySqlResult(const MYSQL_RES *results);
        void getResults() const;
        bool mysql_fetch_array(MySqlResultArray *array);
 
    private:
        vector<vector<MySqlDonnes> > m_results;
        int m_curseur;
};
 
class MySql
{
    public:
        // constructeur / destructeur
        MySql(const string& host = "localhost", const string& username = "root",
                    const string& password = "", const string &bd_name = "");
        ~MySql();
 
        // membres publiques
        MySqlResult search(const string& request);
        void query(const string& request);
 
        void setBd(const string& new_bd);
 
 
    private:
        MYSQL *m_mysql;
};
 
#endif | 
 Voici le fichier .cpp :
	Code:
	
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
   | #include <mysql.h>
#include <iostream>
 
// Constructeur par défaut
MySql::MySql(const string& host, const string& username, const string& password,
                     const string &bd_name)
{
    // initialisation de mysql
    m_mysql = new MYSQL();
    mysql_init(m_mysql);
    mysql_options(m_mysql, MYSQL_READ_DEFAULT_GROUP, "");
 
    // connexion à la BDD
    if(!mysql_real_connect(m_mysql, host.c_str(), username.c_str(), password.c_str(),
            bd_name.c_str(), 0, NULL, 0))
        throw string("Une erreur s'est produite lors de la connexion à la BDD");
}
 
// Destructeur
MySql::~MySql()
{
    mysql_close(m_mysql);
    delete m_mysql;
}
 
// ---------------------------------------------------------
 
// Change la BDD
void MySql::setBd(const string& new_bd)
{
    if(mysql_select_db(m_mysql, new_bd.c_str()))
        throw string("Le changement de la BDD ("+ new_bd +") s'est mal déroulé !");
}
 
// ---------------------------------------------------------
 
// Execute une requête n'attendant pas un jeu de résultat
void MySql::query(const string& request)
{
    mysql_query(m_mysql, request.c_str());
}
 
// Execute une requete attendant un jeu de résultat
MySqlResult MySql::search(const string& request)
{
 
    // déclaration des pointeurs et variables et gestion
    MYSQL_RES *result = NULL;
    mysql_query(m_mysql, request.c_str());
    result = mysql_use_result(m_mysql);
 
    MySqlResult retour(result);
 
    // libération du jeu de résultat
    mysql_free_result(result);
 
    return retour;
}
 
 
// ---------------------------------------------------------
// ---------------------------------------------------------
// ---------------------------------------------------------
 
MySqlResult::MySqlResult(const MYSQL_RES* results)
{
    // création des variables
    MYSQL_ROW row;
    MYSQL_FIELD *field;
    int row_num = 0;
    unsigned int num_champs = mysql_num_fields(const_cast<MYSQL_RES*>(results));
    m_curseur = 0;
 
    // on lit les lignes
    while((row = mysql_fetch_row(const_cast<MYSQL_RES*>(results)) ))
    {
        // on rajoute une ligne au vector
        m_results.push_back(vector<MySqlDonnes>(num_champs));
 
        // on lit les colonnes
        for(unsigned int i = 0 ; i < num_champs ; ++i)
        {
            if(row[i] != NULL)
            {
                // lecture des données du champ
                mysql_field_seek(const_cast<MYSQL_RES*>(results),
                                static_cast<MYSQL_FIELD_OFFSET>(i));
                field = mysql_fetch_field(const_cast<MYSQL_RES*>(results));
 
                // remplissage du vector
                MySqlDonnes new_donnes = {field->name, row[i]};
                m_results[row_num].push_back(new_donnes);
            }
        }
 
        ++row_num;
    }
}
 
bool MySqlResult::mysql_fetch_array(MySqlResultArray *array)
{
    // on récupère et on envoie l'array de resultat
    *array = MySqlResultArray(m_results[m_curseur]);
 
    // on incremente le curseur virtuelle
    ++m_curseur;
    if(m_curseur > static_cast<int>(m_results.size()) )
    {
        m_curseur = 0;
        return false;
    }
 
    // on retourne true
    return true;
}
 
 
 
// ---------------------------------------------------------
// ---------------------------------------------------------
// ---------------------------------------------------------
 
MySqlResultArray::MySqlResultArray(const vector<MySqlDonnes>& row)
{
    m_row = row;
}
 
string MySqlResultArray::operator>>(const string& str) const
{
    string retour = "";
 
    // lecture de la ligne
    for(int i = 0 ; static_cast<int>(m_row.size()) ; ++i)
    {
        if(m_row[i].name == str)
        {
            retour = m_row[i].value;
            break;
        }
    }
 
    return retour;
} | 
 Et enfin, un petit exemple pour voir si mes classes fonctionnent correctement (c'est le cas ;) ) :
	Code:
	
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | #include <iostream>
#include "mysql.h"
 
using namespace std;
 
int main()
{
    cout << "Hello world!" << endl;
    try{
        MySql test;
        test.setBd("site");
 
        MySqlResult result = test.search("SELECT * FROM actions");
        MySqlResultArray result_array;
 
        while(result.mysql_fetch_array(&result_array))
        {
            string temp("id");
            string temp2 = result_array >>temp;
            cout << temp2 << endl;
        }
 
    }
    catch(string error){
        cout << error <<endl;
    }
 
    system("PAUSE");
    return 0;
} | 
 Et cela m'affiche bien le résultat que j'attendais et ce, sans chargement !
Mais évidemment, il existe une façon quelquonque de mieux "coder" ou organiser ces classes ?
Merci d'avance pour TOUS les commentaires que vous fairez, qu'ils soient positives ou négatives afin que cela puisse me faire avancer pour un code toujours meilleures :lol:
PS : j'ai utiliser le flux >> pour obtenir la valeur, mais j'aurais préféré utiliser l'operator[] avec un string, mais cela ne marche pas (pour faire comme en PHP, vous comprenez?)