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?)