Utilisation de l'API MySQL avec Visual Basic

Ce tutoriel est une adaptation d'un document écrit par LFE pour Borland C++ Builder. Il a pour but de montrer comment exploiter une connexion à une base de données MySQL, en utilisant uniquement l'API fournie avec MySQL. Le code a été écrit et testé avec Visual Basic 6 et MySQL version 3.23.49.

Pour une description des fonctions de l'API, je vous renvoie à la documentation fournie avec MySQL.

Article lu   fois.

L'auteur

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Préparation

Vous devez tout d'abord recopier le fichier libmySQL.dll dans le répertoire windows. Ensuite il vous faut les déclarations des fonctions de l'API MySQL. Vous pouvez télécharger ma traduction des fichiers entêtes ici. Une fois le fichier .zip téléchargé, il vous suffit d'ajouter à votre projet les 3 modules contenus dans l'archive.

II. Manipulation des pointeurs en Visual Basic

Les fonctions de l'API Windows sont assez faciles à utiliser avec Visual Basic, car elles ne renvoient pas de pointeurs.
Mais la grande majorité des fonctions de l'API MySQL renvoient un pointeur, sur une structure ou sur une chaîne de caractères. VB ne permet pas de déclarer un pointeur sur une variable. Donc si nous avons besoin des champs de la structure renvoyée, ou de la chaîne de caractères, nous devons recopier la zone mémoire qui est pointée, dans une variable. Afin d'y parvenir, nous pouvons utiliser ces deux fonctions de l'API windows :

 
Sélectionnez

Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As Any, _
    ByVal lpString2 As Any) As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, _
    Source As Any, ByVal Length As Long)

lstrcpy (lpString1, lpString2) recopie la chaîne qui est à l'adresse lpString2 dans la chaîne lpString1.

CopyMemory() recopie une zone mémoire dans une autre. Les paramètres sont :
  • l'adresse de la zone mémoire de destination
  • l'adresse de la zone mémoire à recopier
  • le nombre d'octets à recopier

Voyons comment récupérer une chaîne de caractères qui se trouve à une adresse donnée, à l'aide de lstrcpy() :

 
Sélectionnez

Private Function CopieChaine(ByVal adresse As Long) As String

Dim ret As String

If adresse > 0 Then
    ret = Space(256)
    lstrcpy ret, adresse
    ret = Trim(ret)
    If ret <> "" Then CopieChaine = left(ret, Len(ret) - 1)
End If

End Function

III. Initialiser la connexion à MySQL

Avant tout chose il est nécessaire d'initialiser l'accès à la DLL.

 
Sélectionnez

Dim pMySQL As Long

pMySQL = mysql_init(0)

Au retour, pMySQL contient l'adresse de la structure permettant l'interfaçage avec mySQL, ou 0 en cas d'erreur. Il est tout à fait possible d'avoir plusieurs connexions dans le même programme.

IV. Fermer la connexion

 
Sélectionnez

Dim pMySQL As Long

mysql_close (pMySQL)

mysql_close() ferme la connexion à la base de données et libère les ressources allouées lors de la création de la connexion.

V. Se connecter à la base de données

 
Sélectionnez

Dim pMySQL As Long

If mysql_real_connect(pMySQL, "127.0.0.1", "", "", "test", 0, "", 0) = 0 Then
    ' ...
    ' la connexion a échoué
    ' ...
Else
    ' la connexion a réussi
mysql_real_connect() ouvre la connexion à la base de données. Les paramètres sont :
  1. le handle de connexion
  2. l'adresse du serveur où mySQL est installé
  3. le nom de user
  4. le mot de passe
  5. le nom de la base de données
  6. le n° de port (0 indique que l'on utilise le port par défaut)
  7. le nom du pipe ou le socket qui sera utilisé (habituellement 0)
  8. des statuts permettant de configurer la connexion (habituellement 0)

Une valeur de retour nulle indique qu'une erreur s'est produite. Une valeur autre indique que la connexion est ouverte.

VI. Lister les tables dans la base de données

 
Sélectionnez

Private Sub EnumTables(pMySQL As Long)

Dim pMyROW As Long, myROW As Long, pMyRES As Long, i As Long

pMyRES = mysql_list_tables(pMySQL, "")

If (pMyRES <> 0) Then
    For i = 0 To mysql_num_rows(pMyRES) - 1
        pMyROW = mysql_fetch_row(pMyRES)
        CopyMemory myROW, ByVal pMyROW, 4
        ListBox1.AddItem CopieChaine(myROW)
    Next
    mysql_free_result (pMyRES)
End If

End Sub
mysql_list_tables() permet de lire le nom de toutes les tables de la base de données. Ses paramètres sont :
  • le handle de connexion
  • un masque permettant de filtrer les noms des tables à lire

La valeur de retour est un handle vers le résultat de la requête, qui est un pointeur vers une structure MYSQL_RES. Si la requête échoue, la valeur de retour est nulle.

mysql_num_rows() renvoie le nombre d'enregistrements contenus dans le résultat.

mysql_fetch_row() permet d'accéder aux champs de l'enregistrement courant, et passe automatiquement à l'enregistrement suivant. En langage C, elle renvoie un tableau de chaînes de caractères, dont chaque élèment contient la valeur d'un champ. Jetons un coup d'oeil sur la déclaration de cette fonction en langage C :

 
Sélectionnez

typedef char **MYSQL_ROW;

MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result);

En C, un tableau de chaînes de caractères est un pointeur vers un pointeur sur une chaîne de caractères. Le tableau est en fait une chaîne unique, contenant les différentes chaînes juxtaposées, chaque chaîne se terminant par un caractère nul.

En VB, nous récupèrons avec CopyMemory() le pointeur sur la chaîne de caractères, et enfin la chaîne de caractères elle-même avec la fonction CopieChaine(), que nous avons écrite précédemment. Ici chaque enregistrement ne contient qu'un seul champ.

Une fois que l'on n'a plus besoin du résultat de la requête, il ne faut pas oublier de libérer les ressources en appelant la fonction mysql_free_result().

VII. Accéder aux données de la table

 
Sélectionnez

Private Sub LitEnregistrements(pMySQL As Long)

Dim pMyROW As Long, myROW As Long, pLengths As Long, pMyRES As Long
Dim i As Long, j As Long, nbFields As Long, lengths() As Long, texte As String

If (mysql_query(pMySQL, "select * from tTest") = 0) Then

    pMyRES = mysql_store_result(pMySQL)

    If (pMyRES <> 0) Then

        nbFields = mysql_num_fields(pMyRES)
        If nbFields > 0 Then

            ReDim lengths(0 To nbFields - 1)
            For i = 0 To mysql_num_rows(pMyRES) - 1

                pMyROW = mysql_fetch_row(pMyRES)
                CopyMemory myROW, ByVal pMyROW, 4

                pLengths = mysql_fetch_lengths(pMyRES)
                CopyMemory lengths(0), ByVal pLengths, 4 * nbFields

                For j = 0 To nbFields - 1
                    texte = Space(lengths(j))
                    lstrcpy texte, myROW
                    myROW = myROW + lengths(j) + 1
                    ListBox1.AddItem texte
                Next
            Next
        End If
    End If
    mysql_free_result (pMyRES)
End If

End Sub

La fonction mysql_query() exécute une requête, et renvoie 0 si la requête a abouti.
Pour accéder au résultat de la requête, il est nécessaire d'appeler la fonction mysql_store_result(). Celle-ci renvoie un handle vers le résultat de la requête, qui est un pointeur vers une structure MYSQL_RES, ou 0 en cas d'erreur.

Nous pouvons ensuite lire les données. Vous voyez que la boucle qui est chargée de parcourir les enregistrements est ici plus complexe. Ceci vient du fait que nous avons plusieurs champs. mysql_fetch_row() nous renvoie la valeur des champs, juxtaposés dans une chaîne de caractères unique. Nous ne pouvons pas lire toute la chaîne de caractères en une seule fois. Car avec lstrcpy(), nous récupèrerons que le premier élèment. Et avec CopyMemory(), nous devons connaître le nombre d'octets à lire.

La solution à notre problème est la fonction mysql_fetch_lengths(), qui renvoie un tableau contenant la longueur des différents champs.
Nous pouvons alors lire la valeur de chaque champ, un par un, en nous déplaçant dans la chaîne de caractères unique, et en copiant le nombre d'octets nécessaire à chaque fois. Le schéma ci-dessous montre un exemple de ce que l'on peut obtenir.

Image non disponible

VIII. Lire la structure d'une table

 
Sélectionnez

Private Sub LitStructure(pMySQL As Long)

Dim pMyROW As Long, pMyRES As Long, pMyFields As Long, myFields() As MYSQL_FIELD
Dim aStr As String, CountFields As Integer, i As Integer

If (mysql_query(pMySQL, "select * from pet") = 0) Then

    pMyRES = mysql_store_result(pMySQL)

    If (pMyRES <> 0) Then

        CountFields = mysql_num_fields(pMyRES)

        If (CountFields > 0) Then

            pMyFields = mysql_fetch_fields(pMyRES)
            ReDim myFields(0 To CountFields - 1)
            CopyMemory myFields(0), ByVal pMyFields, Len(myFields(0)) * CountFields

            For i = 0 To CountFields - 1
                aStr = "Le champ " & CopieChaine(myFields(i).name) & " est du type " & _
                        myFields(i).type
                ListBox1.AddItem (aStr)
            Next
        End If
        mysql_free_result (pMyRES)
    End If
End If

End Sub

La fonction mysql_fetch_fields() renvoie un tableau de structures MYSQL_FIELD, dont chaque élèment représente un champ de la table.
Les attributs de la structure MYSQL_FIELD sont les informations relatives à un champ.

IX. Gestion des erreurs

IX-A. Obtenir le code d'erreur

 
Sélectionnez

Dim myErrorCode As Long

myErrorCode = mysql_errno(pMySQL)

mysql_errno() renvoie le n° de l'erreur survenue lors du dernier appel à l'API, pour la connexion donnée. Une valeur nulle indique qu'il n'y a pas eu d'erreur.

IX-B. Obtenir un message décrivant l'erreur

 
Sélectionnez

Dim pMyErrorMsg As Long, myErrorMsg As String

pMyErrorMsg = mysql_error(pMySQL)
myErrorMsg = CopieChaine(pMyErrorMsg)

mysql_error() renvoie un message décrivant l'erreur survenue lors du dernier appel à l'API, pour la connexion donnée. Un message vide indique qu'il n'y a pas eu d'erreur.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Articles sur Visual Basic 6
Exemple de création d'un contrôle : le splitter
Utilisation de l'API mySQL
Exemple d'architecture à 3 couches
Créer des dll en C compatibles avec Visual Basic 6
Mes contributions à la faq VB

Copyright (c) 2003 Romain Puyfoulhoux. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. Read the full license here : http://www.gnu.org/licenses/fdl.txt.