• Aucun résultat trouvé

A.5 Une nouvelle solution : BOLDR

A.5.2 Description détaillée

Le déroulement général de l'évaluation de requêtes avec BOLDR est décrit dans la Figure A.6. Durant l'exécution 1 d'un programme hôte, les requêtes sont traduites en QIR puis évaluées par QIR 2 . Ces deux étapes n'ont pas à être contiguës. Souvent, les requêtes sont traduites à leur création, mais évaluées seule-ment quand le programme a besoin des résultats. Le système d'évaluation de QIR prend alors le relais et essaie de typer les requêtes QIR. S'il réussit, il normalise 3 les termes QIR pour les défragmenter en utilisant une stratégie qui est garantie de réussir. Cette étape est essentielle pour permettre aux traductions vers les langages de bases de données de fonctionner de manière optimale. Si le typage

Database query  + L Term Database value QIR value Host Language (L) Host Language (L) program L value Database  evaluation Type system + typed normalization 3        L evaluation 1 QIR+L+database Term QIR evaluation 7 QIR Database Embedded L QIR + L Term 8

Application code evaluation Typed path (safe)

Translation to QIR 2 QIR (normalized) + L Term        Translation to L12 Type system + translation 5 Translation to QIR 11 L evaluation 10 9 Syntactic normalization 4

Syntactic path (may fail)

Syntactic translation 6 syntactic syntactic typed typed syntactic typed

Figure A.6  Évaluation d'un programme avec BOLDR

échoue, une stratégie basée sur la structure syntaxique des expressions QIR est utilisée pour la normalisation 4 qui pourrait échouer. Les termes QIR sont en-suite typés de nouveau 5 pour obtenir des informations utiles à la traduction sur l'endroit où les sous-requêtes doivent être exécutées, mais aussi pour détecter des erreurs avant exécution et obtenir d'autres propriétés formelles intéressantes. Si cela réussit, BOLDR traduit les termes QIR dans de nouveaux termes QIR qui contiennent des requêtes écrites dans des langages de bases de données (par exemple SQL) en utilisant une stratégie de traduction également garantie de réus-sir. Sinon, une fois encore, c'est une stratégie syntaxique qui est utilisée 6 et qui pourrait échouer. Ensuite, les diérentes parties de ces termes sont évaluées où elles doivent l'être, soit dans l'application 7 ou dans une base de données 8 . Les expressions du langage hôte se trouvant dans ces termes sont évaluées soit par le système d'évaluation du langage hôte qui a appelé le QIR 9 , ou dans le système d'évaluation intégré dans une base de données cible 10 . Les résultats sont alors traduits de la base de données vers QIR 11 , puis de QIR vers le langage hôte 12 .

Example A.5.

1 # Taux de change entre rfrom et rto 2 getRate = function(rfrom, rto) {

3 # La table change a trois colonnes: cfrom, cto, rate 4 change = tableRef("change", "PostgreSQL")

5 if (rfrom == rto) 1

6 else subset(change, cfrom == rfrom && cto == rto, c(rate))

7 }

8

9 # Employees gagnant au moins min dans la monnaie cur 10 atLeast = function(min, cur) {

11 # La table employee a deux colonnes: name, salary 12 emp = tableRef("employee", "PostgreSQL")

13 subset(emp, salary >= min * getRate("USD", cur), c(name))

14 }

15

16 richUSPeople = atLeast(2500, "USD")

17 richEURPeople = atLeast(2500, "EUR")

18 print(executeQuery(richUSPeople))

19 print(executeQuery(richEURPeople))

Notre Exemple A.5 est un programme R standard avec deux exceptions : la fonctiontableRefqui renvoie une référence vers une table d'une source externe ; et la fonctionexecuteQueryqui évalue une requête. Pour rappel, en R, la fonction

c crée un vecteur, la fonction subset ltre une table en utilisant un prédicat, et optionnellement ne conserve que les colonnes spéciées. La première fonction getRate prend le code de deux monnaies et envoie une requête en utilisantsubset

pour obtenir leur taux de change. La seconde fonction atLeast prend un salaire minimum et un code de monnaie et récupère les noms des employés gagnant au moins le salaire minimum. Puisque le salaire est stocké en dollars dans la base de données, la fonction getRate est utilisée pour faire la conversion.

Avec BOLDR, subset est surchargée pour fabriquer une requête QIR si elle est appliquée sur une référence de source externe. L'évaluation du premier appel à la fonction atLeast (atLeast(2500, "USD") à la Ligne 16) a pour résultat la création d'une requête obtenue par traduction de l'expression R vers QIR. Quand

executeQueryest appelée sur la requête, alors (i) les valeurs de l'environnement d'exécution liées aux variables libres de la requête sont traduites en QIR, puis liées à ces variables dans la requête, créant ainsi une requête QIR close ; (ii) la requête est normalisée, procédé qui, en particulier, remplace les variables liées par leurs valeurs ; (iii) la requête normalisée est traduite vers le langage de base de données cible (ici SQL) ; et (iv) la requête résultante est évaluée dans la base

de données et les résultats sont récupérés. Après normalisation et traduction, la requête générée pour l'exécution de richUSPeople est :

SELECT name FROM employee WHERE sal >= 2500 * 1

ce qui est optimal, dans le sens où une seule requête SQL est générée. Le code généré pour richEURPeople est également optimal grâce à la combinaison entre la construction paresseuse de la requête et la normalisation :

SELECT name FROM employee WHERE sal >= 2500 *

(SELECT rate FROM change WHERE rfrom = "USD" AND rto = "EUR") Dans ce cas, BOLDR combine les sous-requêtes ensemble pour créer des requêtes moins nombreuses et plus larges, bénéciant ainsi des optimisations des bases de données autant que possible et évitant le phénomène d'avalanche de requê-tes [GRS10].

Les fonctions dénies par l'utilisateur qui ne peuvent pas être traduites sont également supportées par BOLDR. Par exemple, regardons l'Exemple A.6.

Example A.6.

getRate = function(rfrom, rto) { print(rto)

change = tableRef("change", "PostgreSQL") if (rfrom == rto) 1

else subset(change, cfrom == rfrom && cto == rto, c(rate)) }

Cette version de la fonction getRate appelle la fonction print qui ne peut pas être traduite en QIR, donc BOLDR génère la requête suivante :

SELECT name FROM employee

WHERE sal >= 2500 * R.eval("@...", array("USD", "EUR"))

où la chaîne de caractères "@..." est une référence à une clôture pour getRate. Mélanger diérentes sources de données est supporté, mais moins ecacement. Par exemple, nous pourrions faire référence à une table d'une base HBase [Apaa] dans la fonction getRate. BOLDR serait toujours capable d'évaluer la requête en envoyant une sous-requête aux deux bases HBase et PostgreSQL, et en exécutant dans l'application ce qui ne peut pas être traduit.

Documents relatifs