Licence Science et Technologies - INF245 Examen session 1 - mai 2012 Durée : 2 heures Documents non autorisés Le barème est donné à titre indicatif 1 Position du problème Le Club Universitaire de Vélo dans les Cailloux et dans la Boue désire implanter une application web pour la gestion des sorties qu il organise. Les randonneurs : un randonneur, dont on connaît le prénom et le niveau technique (débutant, moyen, bon, ou expert) est identifié par un numéro. Tout randonneur a un parrain (et un seul) pris parmi les autres randonneurs. Chaque randonneur peut être parrain de 0, 1 ou plusieurs autres randonneurs. Les groupes : les randonneurs s inscrivent à zéro ou plusieurs groupes (chaque groupe comporte au moins un randonneur). Chaque groupe a un nom qui l identifie. Dans tous les groupes auxquels il participe, chaque randonneur tient un rôle : chef de randonnée ou participant. Dans chaque groupe, il y a exactement un randonneur avec le rôle chef de randonnée. Les itinéraires : un itinéraire est identifié par un numéro, il a un titre, un point de départ (n importe quel lieu-dit dont on connaît le nom), un type (aller-retour ou circuit), une difficulté technique (vert, bleu, rouge ou noir), une durée estimée (en minutes) pour réaliser l itinéraire et une longueur donnée en kilomètres. Les sorties : une sortie est la prévision, par un groupe, d effectuer un itinéraire à une certaine date (un jour). Un groupe peut prévoir plusieurs sorties (au moins une), mais chaque jour, un groupe effectue zéro ou une sortie. Lorsqu un groupe prévoit une sortie alors tous les membres du groupe prévoient la sortie. Pour chaque randonneur, on conserve le pourcentage réalisé de l itinéraire de chaque sortie qu il a effectué : 100 signifie qu il a fait tout l itinéraire, 50 signifie qu il s est arrêté à mi-chemin, etc. 2 Schéma de la base de données LesItinéraires (noiti, titre, pointdépart, type, difficulté, durée, long) /* <n, i, d, t, di, du, k> LesItinéraires l itinéraire identifié par le numéro n, de titre i part du point de nom d. Cet itinéraire est de type t et de difficulté di. du est la durée estimée en minutes pour réaliser cet itinéraire, et k est sa longueur en km. */ LesRandonneurs (nord, prénom, niveautech, noparrain) /* <r, n, t, p> LesRandonneurs le randonneur de prénom n est identifié par le numéro r. Son niveau technique est t et p est le numéro de son parrain. */ LesGroupes (nomgr, nord, role) /* <g, rd, ro> LesGroupes le randonneur de numéro rd appartient au groupe g. Il tient dans ce groupe le rôle ro. */ LesSorties (nomgr, datesr, noiti) /* <g, d, i> LesSorties le groupe de nom g prévoit, ou a prévu de réaliser l itinéraire i à la date d. */ LesHistoires (nord, datesr, TxSucces) /* <r, d, t> LesHistoires le randonneur de numéro r a réalisé t pour cent de l itinéraire de la sortie effectuée à la date d. */ c C. Parent-Vigouroux 2012/13 page 1
Les domaines associés sont : domaine (nord) = domaine (noparrain) = domaine (noiti) = entier domaine (nomgr) = domaine (titre) = domaine (prénom) = domaine (pointarrivée) = chaîne de caractères domaine (datesr) = date(jour) Les restrictions de domaine : domaine (niveautech) = [ débutant, moyen, bon, expert ] domaine (role) = [ chef de randonnée, participant ] domaine (type) = [ aller-retour, circuit ] domaine (difficulté) = [ vert, bleu, rouge, noir ] domaine (long) = réel > 0 domaine (durée) = entier > O domaine (TxSucces) = entier sur ]0..100] Les contraintes d intégrité référentielles sont : LesRandonneurs[noParrain] LesRandonneurs[noRd] LesGroupes[noRd] LesRandonneurs[noRd] LesSorties[nomGr] = LesGroupes[nomGr] LesSorties[noIti] LesItinéraires[noIti] LesHistoires[noRd,dateSr] (LesSorties * LesGroupes)[noRd,dateSr] /* L opérateur * dénote le produit naturel. */ Contraintes de valuation obligatoire : - noparrain dans LesRandonneurs - role dans LesGroupes - noiti dans LesSorties Autre contrainte : - Dans chaque groupe, exactement un randonneur a le rôle chef de randonnée - Dans la relation LesRandonneurs, chaque nuplet soit <r, n, t, p> est tel que r p. 3 Expression de requêtes Question 1 (5 points) : Exprimer en SQL les requêtes ci-dessous. Les requêtes devront construire des résultats sans répétition de valeurs, la clause distinct ne sera utilisée que lorsque nécessaire. Les produits de relation seront exprimés dans la clause from des requêtes. Toute sous-requête sera soigneusement spécifiée. Les réponses ne respectant pas ces indications seront considérées comme incorrectes. 1. Parmi les randonneurs ayant effectué au moins une sortie (c est-à-dire présents dans la relation LesHistoires), donner le numéro et le niveau technique de ceux qui n ont jamais réalisé d itinéraire à 100%. Donner deux versions : une qui utilise l opérateur in ou sa négation not in et une autre qui n utilise ni l opérateur in ni sa négation not in. 2. Donner les numéros et les prénoms des parrains des chefs 1 des groupes qui ont prévu d effectuer une sortie dont l itinéraire est le plus long parmi tous les itinéraires associés à au moins une sortie. 1 Le chef d un groupe est le randonneur dont le rôle est chef de randonnée dans ce groupe. c C. Parent-Vigouroux 2012/13 page 2
4 Création de la base de données Ci-dessous est donné le code SQL, supporté par le SGBD Oracle vu en cours, pour la création des relations LesItinéraires, LesRandonneurs et LesGroupes. create table LesItineraires ( noiti number(5), titre varchar(30), pointdepart varchar(30), type varchar(12), difficulte varchar(5), duree number(5), long number(5,2), constraint iti_pk primary key (noiti), constraint iti_ck1 check (type in ( aller-retour, circuit, traversee )), constraint iti_ck2 check (difficulte in ( vert, bleu, rouge, noir )), constraint iti_ck3 check (duree > 0), constraint iti_ck4 check (long > 0) ); create table LesRandonneurs ( nord number(5), prenom varchar(30), niveautech varchar(9), noparrain number(5) constraint rand_ob not null, constraint rand_pk primary key (nord), constraint rand_ck1 check (niveautech in ( debutant, moyen, bon, expert )), constraint rand_ck2 check (nord <> noparrain), constraint rand_fk1 foreign key (noparrain) references LesRandonneurs(noRd) ); create table LesGroupes ( nomgr varchar(30), nord number(5), role varchar(18) constraint groupes_ob not null, constraint gr_pk primary key (nomgr, nord), constraint gr_ck1 check (role in ( chef de randonnee, participant )), constraint gr_fk1 foreign key (nord) references LesRandonneurs(noRd) ); Remarque : la valeur de la relation LesRandonneurs a été initialisée alors que les contraintes rand fk1 et rand ck2 étaient désactivées. Lorsque la base de données a été mise en production, ces contraintes ont été ré-activées. Question 2 (3 points) : Donner le code SQL, supporté par le SGBD Oracle vu en cours, pour la création des relations LesSorties et LesHistoires. Question 3 (3 points) : Considérant toutes les relations de la base de données, quelles sont les contraintes d intégrité spécifiées dans l énoncé (Section 2) et qui, ne pouvant pas être exprimées en SQL, restent à la charge des applications? 5 Programmes Php Question 4 (4 points) : Compléter le programme AjoutItineraire-action.php donné en annexe du sujet et permettant d implanter l ajout d un nouvel itinéraire comme décrit ci-dessous (utiliser la page fournie avec le sujet et la joindre à la copie). Indication : la fonction LaContrainte spécifiée ci-dessous est fournie. programmer. Il n est pas demandé de la LaContrainte : chaîne de caractères chaîne de caractères /* si m est le message d une erreur Oracle e, alors LaContrainte(m) est la sous-chaîne de m qui fournit l identifiant de la contrainte dont le non respect a provoqué e. */ Par exemple, LaContrainte( check constraint (FAUVET.RAND CK1) violated ) = RAND CK1. c C. Parent-Vigouroux 2012/13 page 3
L utilisateur fournit les informations nécessaires par le biais de formulaires HTML (non étudiés ici) : Le numéro de l itinéraire, son titre, son point de départ, sa durée et la longueur sont saisis dans des champs textes. Le type de l itinéraire est choisi en cochant le bouton radio aller-retour ou le bouton radio circuit. La difficulté de l itinéraire est choisie en sélectionnant dans une liste déroulante à choix unique une des valeurs parmi [ vert, bleu, rouge, noir ]. A l issue de la transaction, un message est retourné à l utilisateur indiquant soit que le nouvel itinéraire a pu être ajouté, soit qu une incohérence a été détectée. Dans ce dernier cas, le message explicite la nature de l incohérence. Question 5 (5 points) : Compléter le programme Desinscrire-action.php donné en annexe du sujet et permettant d implanter la suppression dans un groupe, d un des randonneurs du groupe. Ce programme ne doit pas modifier la relation LesHistoires car cette dernière décrit les sorties passées. L utilisateur fournit les informations nécessaires par le biais de formulaires HTML (non étudiés ici) : Le nom du groupe est choisi dans une liste déroulante à choix unique contenant les noms de groupe de la base de données dont aucune sortie n est passée. Le numéro du randonneur à désinscrire est ensuite choisi dans la liste déroulante à choix unique des randonneurs du groupe sélectionné précédemment. Seuls les randonneurs dont le rôle dans le groupe est différent de chef de randonnée sont proposés. A l issue de la transaction, un message est retourné à l utilisateur indiquant soit que le randonneur a pu être désinscrit du groupe, soit qu une incohérence a été détectée. Dans ce dernier cas, le message explicite la nature de l incohérence. c C. Parent-Vigouroux 2012/13 page 4
Programme à compléter (rendre la feuille avec la copie) Numéro d anonymat : //===== AjoutItineraire-action.php ================ // $lien est une connexion valide // $noiti est le numéro de l itinéraire, $titre son titre, $depart son point de départ // $duree sa durée, $long sa longueur, $type son type ( aller-retour ou circuit ). // $diff sa difficulté une valeur parmi [ vert, bleu, rouge, noir ] $requete = "insert into LesItineraires values (:noiti,:titre,:dep,:type,:diff,:duree,:long)"; $curs = oci_parse ($lien, $requete); oci_bind_by_name($curs, ":noiti", $noiti); oci_bind_by_name($curs, ":titre", $titre); $res = oci_execute($curs, OCI_NO_AUTO_COMMIT); if ($res) { "Itinéraire ajouté avec succès"; else { $e = oci_error($curs); $cont = LaContrainte ($e[ message ]); // Voir indication dans l énoncé. if ($cont=="iti_pk") { elseif ($cont="iti_ck1") { elseif ($cont="iti_ck2") { elseif ($cont="iti_ck3") { elseif ($cont="iti_ck4") { else { "Erreur : ".$e[ message ]; echo $message; c C. Parent-Vigouroux 2012/13 page 5
Programme à compléter (rendre la feuille avec la copie) Numéro d anonymat : //===== Desinscrire-action.php ================ // $lien est une connexion valide, $nord est le numéro du randonneur à // désinscrire du groupe $nomgr $req = // $req retourne 1 si $nord est le chef de randonnée dans le groupe $nomgr, // sinon $req retourne 0 $curs = oci_parse ($lien, $req); oci_bind_by_name ($curs,...,...); oci_bind_by_name ($curs,...,...); $res = oci_execute($curs, OCI_DEFAULT); if ($res) { // $req a été exécutée correctement oci_fetch ($curs); if (oci_result($curs, 1) == 1) { // le randonneur est le chef de randonnée dans le groupe...; else { // le randonneur n est pas le chef de randonnée dans le groupe oci_free_statement ($curs); else { // L exécution de $req a généré une erreur "Désincription impossible, erreur : ".$e[ message ]; echo $message; c C. Parent-Vigouroux 2012/13 page 6