Bonsoir,
Petit sujet coup de gueule en ce vendredi soir. Vous me savez critique envers la gestion de l'accès aux données de PCSoft que je qualifie souvent de buggée, approximative ou mensongère.
Me voici avec un nouvel exemple sous la main. Je plante le décor avec un besoin courant, gérer des périodes, une base Oracle (accès natif) et l'envie d'utiliser les outils fournis dans les règles de l'art.
Pour ça je créée une simple table dans l'analyse (chère analyse ...) :
Les deux bornes étant indexées indépendamment (je voulais voir après pour les optimisations)IDPeriode Entier
DateDebut DateHeure
DateFin DateHeure
Je demande la création des scripts, cette fois ci ça se passe bien :
Pour le fun, je teste un HCreationSiInexistant, idem, ça sort bien.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 CREATE TABLE TestDate ( IDTestDate NUMERIC(10,0) PRIMARY KEY , DateDebut DATE , DateFin DATE ); CREATE INDEX WDIDX_TestDate_DateDebut ON TestDate (DateDebut); CREATE INDEX WDIDX_TestDate_DateFin ON TestDate (DateFin);
L'utilisation maintenant. Je mets de côté mes convictions et fais une requête dans l'éditeur de requêtes qui donne ça :
pdh car je compte fournir un paramètre de type DateHeure et éviter ainsi toute méprise de type aux yeux du moteur de requêtes.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 SELECT TestDate.IDTestDate AS IDTestDate, TestDate.DateDebut AS DateTest FROM TestDate WHERE TestDate.DateDebut = {pdhDateHeure}
Je jette quelques données dans la table avec deux périodes (02/07/2010 00:00:00 à 03/07/2010 00:00:00, 02/08/2010 00:00:00 à 04/08/2010 00:00:00):
Je me lance avec le code suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 INSERT INTO TESTDATE (IDTESTDATE, DATEDEBUT, DATEFIN) VALUES (1, TO_DATE('2010-07-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), TO_DATE('2010-07-03 00:00:00', 'YYYY-MM-DD HH24:MI:SS')) ; INSERT INTO TESTDATE (IDTESTDATE, DATEDEBUT, DATEFIN) VALUES (2, TO_DATE('2010-08-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), TO_DATE('2010-08-04 00:00:00', 'YYYY-MM-DD HH24:MI:SS')) ;
La trace affiche ... Roulement de tambour ...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 dhDateHeure est un DateHeure dhDateHeure..Année = 2010 dhDateHeure..Mois = 7 dhDateHeure..Jour = 25 dhDateHeure..Heure = 0 dhDateHeure..Minute = 0 dhDateHeure..Seconde = 0 dhDateHeure..Milliseconde = 0 ReqDate.pdhDateHeure = dhDateHeure HExécuteRequête(ReqDate) POUR TOUT ReqDate Trace(ReqDate.IDTestDate, ReqDate.DateDebut) FIN HAnnuleDéclaration(ReqDate)
Bon ça fonctionne . Alors quel est mon problème si ça retourne le bon résultat ? Pour ça il faut regarder le log de requêtes d'Oracle pour voir ce que Webdev a envoyé à mon cher SGBD, et voici le résultat :
Code : Sélectionner tout - Visualiser dans une fenêtre à part 1 20100702000000000
Pour ceux qui ne seraient pas habitués, le :1 est un paramètre Oracle qui reçoit "20100702000000000". Je ne compare pas ma colonne DateDebut mais un TO_CHAR(TestDate.DateDebut). Les conséquences sont désastreuses car tout index posé sur la rubrique DateDebut ne sera jamais utilisé car la comparaison n'est pas faite directement avec la colonne. Pour information, la bonne pratique SQL est de comparer la colonne à un TO_DATE de la chaîne qui représente la date que je cherche.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 SELECT TestDate.IDTestDate AS IDTestDate , TestDate.DateDebut AS DateTest FROM TestDate WHERE ( TO_CHAR(TestDate.DateDebut,'YYYYMMDDHH24MISS') = :1 )
Le comble, le clou du spectacle, appelez ça comme vous voulez, c'est que si je supprime l'index dans l'analyse, l'optimiseur de requête (ahem !) me dit que je gagnerai en performance avec un index sur DateDebut . Mais très cher, si tu savais t'en servir, peut être qu'on gagnerait en performance.
Cet exemple parmi d'autres est une preuve flagrante de l'amateurisme quelquefois constaté quand on regarde en détail comment l'accès au données a été développé. Et je persiste, "Amateurisme" car la personne qui a développé le moteur de conversion SQL Windev -> SQL Oracle a sciemment traité la conversion de la colonne plutôt que la conversion du paramètre. Quelle question s'est il posé à ce moment là ? Je me le demande. Soit il ne sait pas comment travaille une base de données avec les indexes ; très grave quand on est en charge de traiter le moteur de conversion SQL. Soit il le sait mais n'en a pas tenu rigueur ; encore plus grave.
Alors vous me direz, c'est un bug, il suffit de le soumettre à PCSoft. Je suis las de remonter des bugs très précis à PCSoft pour lesquels je suis capable de fournir moi même un correctif. Cet exemple était destiné à être envoyé au ST mais il n'ira pas. J'ai déjà soumis des bugs bloquants du même genre sur l'accès aux données. Les réponses du ST : "Utilisez HRequêteSansCorrection". Sauf que dans la documentation, PCSoft mentionne "Performant ! Compatible toutes bases ! Epargnez vous les spécificités des bases de données ! Accès Natif Oracle ultra rapide xxxx € !". PCSoft ne fournira jamais de correctif pour la V14 alors qu'on frise la publicité mensongère (je suis gentil quand je dis "frise"). Je travaille sur un projet où les décideurs ont cru à ce discours et les pertes (temps et argent) occasionnées par ce type de problème sont grandes.
Pour conclure, je vais me répéter. N'utilisez JAMAIS l'accès aux données de Windev si vous travaillez sur un projet sérieux (exit l'analyse, les ordres H, les requêtes Windev). Personne n'a aujourd'hui produit de couche d'accès aux données à la fois simple à utiliser, performante et multi bases. L'utilisation correcte d'une base de données est tout sauf de l'approximation.
A bon entendeur
ps : sur ce je retourne à mon SQL pur
ps2 : note aux modérateurs, avant de faire quoi que ce soit avec ce sujet d'intérêt public, merci d'en discuter au préalable. J'ai bien choisi mes termes et mes exemples, il n'y a aucune calomnie.
Partager