Ressources informatiques

Ressources informatiques

Ressources informatiques

Accéder à une base de données MariaDB en langage C

Documentation : MariaDB Connector/C API Functions

Prenons pour sujet d'étude la base meubleFournisseur qui a été créée dans l'article Requêtes SQL. Le serveur MariaDB a été installé et un utilisateur créé dans l'article : Installer et utiliser un serveur MariaDB.

Installer le connecteur C - MariaDB

adminX@serveurWebX:~$ su - root
Mot de passe :
root@debian:~# apt install libmariadbd-dev

Effectuer des requêtes sur la base

Insertion

Programme source
/**
 * @file insertEnCMysql.c
 * @brief
 * compilation: gcc -o insertEnCMysql insertEnCMysql.c `mariadb_config --cflags --libs`
 * exécution : ./insertEnCMysql -u <user> -p <password>
 * Ce programme insère des données dans la table fournisseur de la base de données meubleFournisseur.
 * Il utilise les fonctions de la bibliothèque MySQL C API pour se connecter à la base de données,
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <mysql.h>

#define HOTE "localhost"
#define NOM_BASE "meubleFournisseur"

/* Fonction pour afficher l'usage du programme */
void usage(const char *prog_name) {
    fprintf(stderr, "Usage: %s -u <user> -p <password> \n", prog_name);
    exit(1);
}

int main(int argc, char *argv[]) {
    MYSQL *pMysql;
    MYSQL_STMT *stmt;
    MYSQL_BIND param[2];
    const char *sql = "INSERT INTO fournisseur (fou_nom, fou_ville) VALUES (?, ?)";

    char *user = NULL, *password = NULL;
    int opt;

    // Analyser les arguments avec getopt
    while ((opt = getopt(argc, argv, "u:p:")) != -1) {
        switch (opt) {
            case 'u':
                user = optarg;  // Utilisateur de la base de données
                break;
            case 'p':
                password = optarg;  // Mot de passe
                break;
            default:
                usage(argv[0]);  // Afficher l'usage si un argument invalide est passé
        }
    }

    // Vérifier que tous les arguments nécessaires sont fournis
    if (user == NULL || password == NULL ) {
        usage(argv[0]);
    }

    /* Initialiser la structure MySQL */
    if ((pMysql = mysql_init(NULL)) == NULL) {
        fprintf(stderr, "mysql_init() échoué : %s\n", mysql_error(pMysql));
        return -1;
    }

    /* Se connecter à la base de données */
    if (mysql_real_connect(pMysql, HOTE, user, password, NOM_BASE, 0, NULL, 0) == NULL) {
        fprintf(stderr, "mysql_real_connect() échoué : %s\n", mysql_error(pMysql));
        mysql_close(pMysql);
        return -1;
    }

    /* Préparer la requête SQL */
    stmt = mysql_stmt_init(pMysql);
    if (mysql_stmt_prepare(stmt, sql, strlen(sql)) != 0) {
        fprintf(stderr, "mysql_stmt_prepare() échoué : %s\n", mysql_error(pMysql));
        mysql_close(pMysql);
        return -1;
    }

    /* Lier les paramètres */
    memset(param, 0, sizeof(param));
    param[0].buffer_type = MYSQL_TYPE_STRING;
    param[0].buffer = "B Meubles";
    param[0].buffer_length = strlen(param[0].buffer);

    param[1].buffer_type = MYSQL_TYPE_STRING;
    param[1].buffer = "Brétigny";
    param[1].buffer_length = strlen(param[1].buffer);

    if (mysql_stmt_bind_param(stmt, param) != 0) {
        fprintf(stderr, "mysql_stmt_bind_param() échoué : %s\n", mysql_error(pMysql));
        mysql_stmt_close(stmt);
        mysql_close(pMysql);
        return -1;
    }

    /* Exécuter la requête */
    if (mysql_stmt_execute(stmt) != 0) {
        fprintf(stderr, "mysql_stmt_execute() échoué : %s\n", mysql_error(pMysql));
        mysql_stmt_close(stmt);
        mysql_close(pMysql);
        return -1;
    }

    /* Fermer la requête préparée et la connexion à la base */
    mysql_stmt_close(stmt);
    mysql_close(pMysql);

    printf("Insertion réussie dans la base de données.\n");
    return 0;
}
Compilation

Pour pouvoir compiler, il est nécessaire d'utiliser les fichiers d'en-tête .h et la librairie lib*.so de la bibliothèque MySQL.
La commande mariadb_config --cflags --libs fournit les informations nécessaires à la compilation.
Remarque : il peut être nécessaire de remplacer mariadb_config par mysql_config

adminX@serveurWebX:~$ gcc -o insertEnCMysql insertEnCMysql.c `mariadb_config --cflags --libs`
Exécution
adminX@serveurWebX:~$ ./insertEnCMysql
Usage: ./insertEnCMysql -u  -p 

adminX@serveurWebX:~$ ./insertEnCMysql -u adminBasemeuble1
Usage: ./insertEnCMysql -u  -p 

adminX@serveurWebX:~$ ./insertEnCMysql -u adminBaseMeuble1 -p bonjour
Insertion réussie dans la base de données.
Vérification
adminX@serveurWebX:~$ mysql -u adminBaseMeuble1 -p meubleFournisseur
Enter password:
mysql>  SELECT * from fournisseur;
+--------+-----------+-----------+
| fou_id | fou_nom   | fou_ville |
+--------+-----------+-----------+
|      1 | A Meubles | Arpajon   |
|      2 | E Meubles | Etampes   |
|      3 | D Meubles | Dourdan   |
|      7 | B Meubles | Brétigny  |
+--------+-----------+-----------+

Affichage sans contraintes : affichage de tous les fournisseurs

Dans ce cas, il n'est pas nécessaire d'utiliser les requêtes préparées

Programme source
/**
 * @file selectEnCMysql.c
 * Compilation: gcc -o selectEnCMysql selectEnCMysql.c `mariadb_config --cflags --libs`
 * Exécution : ./selectEnCMysql -u <user> -p <password>
 * Ce programme affiche les données de la table fournisseur de la base de données meubleFournisseur
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <mysql.h>

#define HOTE "localhost"
#define NOM_BASE "meubleFournisseur"

/* Fonction pour afficher l'usage du programme */
void usage(const char *prog_name) {
    fprintf(stderr, "Usage: %s -u <user> -p <password>\n", prog_name);
    exit(1);
}

int main(int argc, char *argv[]) {
    MYSQL *pMysql;
    MYSQL_STMT *stmt;
    MYSQL_BIND param[2];

    char *user = NULL, *password = NULL;
    int opt;

    // Analyser les arguments avec getopt
    while ((opt = getopt(argc, argv, "u:p:")) != -1) {
        switch (opt) {
            case 'u':
                user = optarg;
                break;
            case 'p':
                password = optarg;
                break;
            default:
                usage(argv[0]);
        }
    }

    if (user == NULL || password == NULL ) {
        usage(argv[0]);
    }

    /* Initialiser la structure MySQL */
    if ((pMysql = mysql_init(NULL)) == NULL) {
        fprintf(stderr, "mysql_init() échoué : %s\n", mysql_error(pMysql));
        return -1;
    }

    /* Se connecter à la base de données */
    if (mysql_real_connect(pMysql, HOTE, user, password, NOM_BASE, 0, NULL, 0) == NULL) {
        fprintf(stderr, "mysql_real_connect() échoué : %s\n", mysql_error(pMysql));
        mysql_close(pMysql);
        return -1;
    }

    printf("Contenu de la table fournisseur :\n");

    /* Afficher le contenu de la table fournisseur */
    if (mysql_query(pMysql, "SELECT fou_nom, fou_ville FROM fournisseur") != 0) {
        fprintf(stderr, "Erreur SELECT : %s\n", mysql_error(pMysql));
        mysql_close(pMysql);
        return -1;
    }

    MYSQL_RES *result = mysql_store_result(pMysql);
    if (result == NULL) {
        fprintf(stderr, "Erreur mysql_store_result : %s\n", mysql_error(pMysql));
        mysql_close(pMysql);
        return -1;
    }

    int num_fields = mysql_num_fields(result);
    MYSQL_ROW row;
    MYSQL_FIELD *fields = mysql_fetch_fields(result);

    // Afficher les noms de colonnes
    for (int i = 0; i < num_fields; i++) {
        printf("%s\t", fields[i].name);
    }
    printf("\n");

    // Afficher les lignes
    while ((row = mysql_fetch_row(result))) {
        for (int i = 0; i < num_fields; i++) {
            printf("%s\t", row[i] ? row[i] : "NULL");
        }
        printf("\n");
    }

    mysql_free_result(result);
    mysql_close(pMysql);

    return 0;
}
Compilation
adminX@serveurWebX:~$ gcc -o selectEnCMysql selectEnCMysql.c `mariadb_config --cflags --libs`

Remarque : il peut être nécessaire de remplacer mariadb_config par mysql_config

Exécution
adminX@serveurWebX:~$ ./selectEnCMysql -u adminBaseMeuble1 -p bonjour
Contenu de la table fournisseur :
fou_nom fou_ville
A Meubles       Arpajon
E Meubles       Etampes
D Meubles       Dourdan
B Meubles       Brétigny

Affichage avec contraintes : affichage des fournisseurs de la ville de Brétigny

Dans ce cas, il est ipmératif d'utiliser les requêtes préparées

Programme source
/**
 * @file selectEnCMysql.c
 * Compilation: gcc -o selectEnCMysql selectEnCMysql.c `mariadb_config --cflags --libs`
 * Exécution : ./selectEnCMysql -u <user> -p <password>
 * Ce programme affiche les fournisseurs de la ville de Brétigny
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <mysql.h>

#define HOTE "localhost"
#define NOM_BASE "meubleFournisseur"

void usage(const char *prog_name) {
    fprintf(stderr, "Usage: %s -u <user> -p <password>\n", prog_name);
    exit(1);
}

int main(int argc, char *argv[]) {
    MYSQL *pMysql;
    MYSQL_STMT *stmt;

    char *user = NULL, *password = NULL;
    int opt;

    while ((opt = getopt(argc, argv, "u:p:")) != -1) {
        switch (opt) {
            case 'u':
                user = optarg;
                break;
            case 'p':
                password = optarg;
                break;
            default:
                usage(argv[0]);
        }
    }

    if (user == NULL || password == NULL ) {
        usage(argv[0]);
    }

    if ((pMysql = mysql_init(NULL)) == NULL) {
        fprintf(stderr, "mysql_init() échoué : %s\n", mysql_error(pMysql));
        return -1;
    }

    if (mysql_real_connect(pMysql, HOTE, user, password, NOM_BASE, 0, NULL, 0) == NULL) {
        fprintf(stderr, "mysql_real_connect() échoué : %s\n", mysql_error(pMysql));
        mysql_close(pMysql);
        return -1;
    }

    // Préparer la requête avec un paramètre
    const char *sql = "SELECT fou_nom, fou_ville FROM fournisseur WHERE fou_ville = ?";
    stmt = mysql_stmt_init(pMysql);
    if (!stmt) {
        fprintf(stderr, "mysql_stmt_init() échoué\n");
        mysql_close(pMysql);
        return -1;
    }
    if (mysql_stmt_prepare(stmt, sql, strlen(sql)) != 0) {
        fprintf(stderr, "mysql_stmt_prepare() échoué : %s\n", mysql_stmt_error(stmt));
        mysql_stmt_close(stmt);
        mysql_close(pMysql);
        return -1;
    }

    // Lier le paramètre (ville)
    MYSQL_BIND bind_param[1];
    memset(bind_param, 0, sizeof(bind_param));
    char ville[] = "Brétigny";
    bind_param[0].buffer_type = MYSQL_TYPE_STRING;
    bind_param[0].buffer = ville;
    bind_param[0].buffer_length = strlen(ville);

    if (mysql_stmt_bind_param(stmt, bind_param) != 0) {
        fprintf(stderr, "mysql_stmt_bind_param() échoué : %s\n", mysql_stmt_error(stmt));
        mysql_stmt_close(stmt);
        mysql_close(pMysql);
        return -1;
    }

    // Préparer les buffers de sortie
    MYSQL_BIND result_bind[2];
    memset(result_bind, 0, sizeof(result_bind));
    char fou_nom[100];
    unsigned long fou_nom_length;
    my_bool fou_nom_is_null;

    char fou_ville[100];
    unsigned long fou_ville_length;
    my_bool fou_ville_is_null;

    result_bind[0].buffer_type = MYSQL_TYPE_STRING;
    result_bind[0].buffer = fou_nom;
    result_bind[0].buffer_length = sizeof(fou_nom);
    result_bind[0].length = &fou_nom_length;
    result_bind[0].is_null = &fou_nom_is_null;

    result_bind[1].buffer_type = MYSQL_TYPE_STRING;
    result_bind[1].buffer = fou_ville;
    result_bind[1].buffer_length = sizeof(fou_ville);
    result_bind[1].length = &fou_ville_length;
    result_bind[1].is_null = &fou_ville_is_null;

    if (mysql_stmt_bind_result(stmt, result_bind) != 0) {
        fprintf(stderr, "mysql_stmt_bind_result() échoué : %s\n", mysql_stmt_error(stmt));
        mysql_stmt_close(stmt);
        mysql_close(pMysql);
        return -1;
    }

    // Exécuter la requête
    if (mysql_stmt_execute(stmt) != 0) {
        fprintf(stderr, "mysql_stmt_execute() échoué : %s\n", mysql_stmt_error(stmt));
        mysql_stmt_close(stmt);
        mysql_close(pMysql);
        return -1;
    }

    // Afficher les résultats
    printf("fou_nom\t\tfou_ville\n");
    printf("-----------------------------\n");
    while (mysql_stmt_fetch(stmt) == 0) {
        printf("%s\t\t%s\n",
            fou_nom_is_null ? "NULL" : fou_nom,
            fou_ville_is_null ? "NULL" : fou_ville
        );
    }

    mysql_stmt_close(stmt);
    mysql_close(pMysql);

    return 0;
}
Compilation
adminX@serveurWebX:~$ gcc -o selectEnCMysql selectEnCMysql.c `mariadb_config --cflags --libs`

Remarque : il peut être nécessaire de remplacer mariadb_config par mysql_config

Exécution
adminX@serveurWebX:~$ ./selectEnCMysql -u adminBaseMeuble1 -p bonjour
fou_nom         fou_ville
-----------------------------
B Meubles               Brétigny