Record collection (JavaScript) Création d'une petite base de données pour trier votre discothèque Projet de Documentation GNOME gnome-doc-list@gnome.org Johannes Schmid jhs@gnome.org Marta Maria Casetti mmcasettii@gmail.com 2013 Luc Rebert, traduc@rebert.name 2011 Alain Lojewski, allomervan@gmail.com 2011-2012 Luc Pionchon pionchon.luc@gmail.com 2011 Bruno Brouard annoa.b@gmail.com 2011-12 Luis Menina liberforce@freeside.fr 2014 Record collection

Dans ce tutoriel, vous allez apprendre :

comment vous connecter à une base de données en utilisant « libgda »

comment insérer et parcourir des enregistrements dans une table de base de données

Introduction

Cet exemple utilise le langage Javascript. Nous allons vous montrer comment vous connecter à une base de données et l'utiliser à partir d'un programme GTK en utilisant la bibliothèque GDA (GNOME Data Access). Vous devez bien sûr avoir déjà installé cette dernière.

La bibliothèque GDA (GNOME Data Access) vous permet d'accéder de manière universelle à différentes sortes et types de sources de données, depuis les plus traditionnels systèmes de bases de données relationnelles, jusqu'à des sources aussi diverses qu'un serveur de messagerie, un répertoire LDAP, etc. Pour de plus amples informations et pour une documentation et l'API complète, consultez le Site Web de GDA.

Bien que la plus grosse partie du programme se réfère à l'interface utilisateur (GUI), nous allons orienter notre tutoriel sur les fonctions bases de données (avec des explications sur certaines autres fonctions que nous jugeons pertinentes). Pour de plus amples informations sur les programmes GNOME en Javascript, consultez le tutoriel Programme visionneur d'images.

Création d'un projet dans Anjuta

Avant de commencer à programmer, vous devez ouvrir un nouveau projet dans Anjuta. Ceci crée tous les fichiers qui vous sont nécessaires pour construire et exécuter votre programme plus tard. C'est aussi utile pour tout regrouper en un seul endroit.

Lancez Anjuta et cliquez sur FichierNouveauProjet pour ouvrir l'assistant de création de projet.

Cliquez sur l'onglet JS, choisissez JavaScript générique, cliquez sur Continuer et renseignez les champs requis avec vos informations. Mettez discotheque (sans accent) comme nom du projet et répertoire.

Cliquez sur Appliquer et votre projet est créé. Ouvrez src/main.js depuis l'onglet Projet ou l'onglet Fichiers. Il contient un exemple de programme très basique.

Structure du programme

Cet exemple est une application GTK simple (avec une seule fenêtre) pouvant insérer des enregistrements dans une table de base de données et également consulter tous les enregistrements de cette table. Cette table possède deux champs : id, un entier et name, une variable de type caractère. La première section de l'application (en haut) vous permet d'insérer un enregistrement dans la table. La dernière (en bas) vous permet d'afficher tous les enregistrements de cette table. Son contenu est mis à jour à chaque fois qu'un nouvel enregistrement est inséré et au démarrage de l'application.

Début du plaisir

Commençons par examiner le squelette du programme :

Lignes 1‒4 : importations initiales. Faites surtout attention à la ligne 3, qui commande à Javascript l'importation de la bibliothèque GDA, la cible de ce tutoriel.

Lignes 6‒17 : définition de la classe Demo. Faites surtout attention aux lignes 13‒15, où nous appelons 3 méthodes qui font tout le travail. Elles sont détaillées plus bas.

Lignes 19‒23 : lancement de l'application.

Conception de l'application

Examinons la méthode setupWindow. C'est elle qui crée l'interface utilisateur. Comme l'interface utilisateur n'est pas notre sujet, nous en expliquons seulement les parties pertinentes.

Insert a record", xalign: 0, use_markup: true}); main_box.pack_start (info1, false, false, 5); // "insert a record" horizontal box var insert_box = new Gtk.Box ({orientation: Gtk.Orientation.HORIZONTAL, spacing: 5}); main_box.pack_start (insert_box, false, false, 5); // ID field insert_box.pack_start (new Gtk.Label ({label: "ID:"}), false, false, 5); this.id_entry = new Gtk.Entry (); insert_box.pack_start (this.id_entry, false, false, 5); // Name field insert_box.pack_start (new Gtk.Label ({label: "Name:"}), false, false, 5); this.name_entry = new Gtk.Entry ({activates_default: true}); insert_box.pack_start (this.name_entry, true, true, 5); // Insert button var insert_button = new Gtk.Button ({label: "Insert", can_default: true}); insert_button.connect ("clicked", Lang.bind (this, this._insertClicked)); insert_box.pack_start (insert_button, false, false, 5); insert_button.grab_default (); // Browse textview var info2 = new Gtk.Label ({label: "Browse the table", xalign: 0, use_markup: true}); main_box.pack_start (info2, false, false, 5); this.text = new Gtk.TextView ({editable: false}); var sw = new Gtk.ScrolledWindow ({shadow_type:Gtk.ShadowType.IN}); sw.add (this.text); main_box.pack_start (sw, true, true, 5); this.count_label = new Gtk.Label ({label: "", xalign: 0, use_markup: true}); main_box.pack_start (this.count_label, false, false, 0); this.window.show_all (); },]]>

Lignes 22 et 27 : création des 2 entrées (pour les 2 champs) dans lesquelles l'utilisateur saisit les choses à insérer dans la base de données.

Lignes 31‒34 : création du bouton « Insert ». Le signal clicked de ce bouton est connecté à la méthode privée _insertClicked de la classe. Cette méthode est décrite ci-dessous.

Ligne 39 : création de l'élément graphique (TextView) où nous affichons le contenu de la table.

Ligne 44 : création de l'étiquette où nous affichons le nombre d'enregistrements dans la table. Au début, elle est vide et est mise à jour ultérieurement.

Connexion à la base de données et initialisation

Le code permettant de se connecter à la base de données est dans la méthode setupDatabase ci-dessous :

Lignes 2‒3 : création de l'objet Connection de GDA. Il faut transmettre quelques propriétés à son constructeur :

provider : l'un des fournisseurs reconnus par GDA. GDA prend en charge SQLite, MySQL, PostgreSQL, Oracle et beaucoup d'autres. Pour les besoins de l'exemple, nous utilisons une base de données SQLite car elle est déjà incluse par défaut dans la plupart des distributions et elle est facile à utiliser (elle n'a besoin que d'un fichier comme base de données).

cnc_string : la chaîne de connexion. Elle peut être différente en fonction du fournisseur. La syntaxe pour SQLite est : DB_DIR=CHEMIN;DB_NAME=NOM2FICHIER. Dans cet exemple, nous accédons à une base de données nommée gnome_demo dans le dossier personnel de l'utilisateur (notez l'appel à la fonction get_home_dir de GLib).

Si le fournisseur n'est pas reconnu par GDA, ou si la chaîne de connexion n'est pas complète, la ligne 2 provoque une exception. Donc, en pratique, il faut gérer cette exception grâce à l'instruction JavaScript try...catch.

Ligne 4 : ouverture de la connexion. Pour le fournisseur SQLite, si la base de donnée n'existe pas, elle est créée à cette étape.

Lignes 6‒10 : tentative de faire une simple instruction « select » pour vérifier que la table existe (ligne 7). Si elle n'existe pas (parce que la base de données vient juste d'être créée), cette instruction provoque une exception qu'il faut gérer grâce au bloc try...catch. Dans ce cas, il faut exécuter l'instruction « create table » pour créer la table (ligne 9).

In order to run the SQL commands above we are using the GDA connection methods execute_select_command and execute_non_select_command. They are simple to use, and just require two arguments: The Connection object and the SQL command to be parsed.

À ce niveau, nous avons configuré la base de données et cette dernière est fonctionnelle.

Sélection

Après connexion à la base de données, le constructeur de notre exemple appelle la méthode selectData. C'est elle qui récupère tous les enregistrements de la table et qui les affiche dans l'élément graphique TextView. Regardons à quoi elle ressemble :

\t" + name_field + '\n'; } this.text.buffer.text = text; this.count_label.label = "" + dm.get_n_rows () + " record(s)"; },]]>

Line 2: The SELECT command. We are using the GDA connection's execute_select_command method for that. It returns a DataModel object, which is later used to retrieve the rows.

Ligne 3 : création d'un objet Iter qui sert à itérer sur les enregistrements de DataModel.

Ligne 7 : Itération sur tous les enregistrements en les récupérant à l'aide de l'objet Iter. À cet endroit, la variable Iter contient les informations trouvées. La méthode move_next retourne le message false quand elle atteint le dernier enregistrement.

Lignes 8‒9 : nous faisons deux choses dans chaque ligne :

Utilisez la méthode get_value_at d'Iter qui n'a besoin que d'un argument : le numéro de colonne à récupérer, en commençant par 0. Comme notre commande SELECT ne retourne que deux colonnes, nous récupérons donc les colonnes 0 et 1.

La méthode get_value_at retourne l'information sur les champs au format GValue de GLib. Pour convertir ce format en chaîne de caractères, utilisez simplement la fonction globale value_stringify de GDA. C'est ce que nous faisons ici puis nous enregistrons les résultats dans les variables id_field et name_field.

Ligne 11 : concaténation des deux chaînes pour former une seule ligne de texte en les séparant par "=>" et enregistrement dans la variable text.

Ligne 14 : à la fin de la boucle, tous les enregistrements sont formatés dans la variable text. À cette ligne, nous attribuons le contenu de cette variable au TextView.

Ligne 15 : affichage du nombre d'enregistrements dans la table avec la fonction get_n_rows de DataModel.

Insertion

Bien, nous savons comment nous connecter à une base de données et comment sélectionner des lignes dans une table. Il est temps maintenant d'apprendre à faire une insertion à l'aide de la commande INSERT dans la table. Souvenez-vous, dans la méthode setupWindow, nous avions relié le signal clicked du bouton Insert à la méthode _insertClicked. Voyons la mise en place de cette méthode.

We have learned how to use the GDA connection's methods execute_select_command and execute_non_select_command to quickly execute SQL commands on the database. GDA allows one to build a SQL statement indirectly, by using its SqlBuilder object. What are the benefits of this? GDA will generate the SQL statement dynamically, and it will be valid for the connection provider used (it will use the same SQL dialect the provider uses). Let's study the code:

Lignes 2‒3 : vérification du bon renseignement par l'utilisateur de tous les champs. Le code de la méthode privée _validateFields est vraiment simple et vous pouvez le consulter dans le programme source complet de l'exemple.

Ligne 5 : la façon la plus rapide pour faire l'insertion à l'aide de la commande INSERT. Celle-ci est mise en commentaire car nous voulons vous montrer comment utiliser l'objet SqlBuilder pour construire une instruction SQL qui soit indépendante de la base de données.

Ligne 7 : création de l'objet SqlBuilder. Nous devons transmettre le type d'instruction que nous voulons construire. Cela peut être SELECT, UPDATE, INSERT ou DELETE.

Ligne 8 : détermination du nom de la table sur laquelle l'instruction construite va agir (le code INSERT INTO demo est généré)

Lignes 9‒10 : détermination des champs et de leurs valeurs qui font partie de l'instruction. Le premier argument est le nom du champ (comme dans la table). Le second est la valeur pour ce champ.

Ligne 11 : fabrication de l'objet Statement généré dynamiquement et qui représente une instruction SQL.

Ligne 12 : enfin, exécution de l'instruction SQL (INSERT).

Ligne 14 : effacement des champs « id » et « name » à l'écran. Le code de la méthode privée _clearFields est vraiment simple et vous pouvez le consulter dans le programme source complet de l'exemple.

Ligne 15 : mise à jour de l'affichage à l'écran en faisant un nouveau SELECT.

Vous pouvez aussi faire usage de paramètres pour construire l'instruction. En utilisant les objets SqlBuilder et des paramètres, vous êtes moins exposé à des attaques du type injection SQL. Consultez la documentation GDA pour plus d'informations sur les paramètres.

Exécution de l'application

Tout le programme nécessaire doit maintenant être en place, donc essayez de l'exécuter. Vous disposez maintenant d'une base de donnée pour votre discothèque !

Implémentation de référence

Si vous rencontrez des difficultés avec ce tutoriel, comparez votre programme à ce programme de référence.