Ne pas oublier que WinDev est un outil et que comme tout outil il a ses us et coutumes... Pourquoi demander à WinDev de savoir dériver une fenêtre ? Perso j'ai pas la réponse
Ne pas oublier que WinDev est un outil et que comme tout outil il a ses us et coutumes... Pourquoi demander à WinDev de savoir dériver une fenêtre ? Perso j'ai pas la réponse
Emmanuel Lecoester
=> joomla addict.
Il est vrai qu'avec les modèles, pcsoft a trouvé une manière intuitive (et visuelle !) de gérer la dérivation de fenêtres et de champs.
Je trouve que c'est une réussite.
MAIS cela ne permet pas de se passer de l'accès aux classes dans tous les cas, d'autant plus que les modèles ont quand même des limitations notamment :
- pas de constructeurs possibles (ex : modèle de fenêtre : pas de prototype autorisé dans le modèle, qu'on pourrait surcharger)
- impossible de supprimer un champ dans le modèle
Cette impossibilité d'accéder aux classes, et donc d'instancier des composants graphiques autrement que par l'IDE, entraîne également une contrainte pénalisante : l'impossibilité de créer dynamiquement des fenêtres et des champs par programmation, hormis par la commande ChampClone() en ce qui concerne les champs.
Inconvénients :
- ChampClone() a besoin d'un champ existant et est lent en exécution
- rien n'existe pour les fenêtres.
Donc je fais comment avec windev si j'ai besoin de générer dynamiquement une fenêtre standard, qui peut m'afficher le contenu de n'importe quel fichier dans une table ?
- je suis obligé de créer une fenêtre avec une table, contenant au moins tous les types de colonnes (texte, combo, interrupteurs)
- je créer une classe qui manipule cette fenêtre (et cette table) par indirection
- selon les rubriques du fichier, je clone les colonnes dont j'ai besoin
- je définis les liaisons par programmation
Hé bien ça marche... mais c'est lourd (à concevoir) et c'est lent à l'exécution
Autre conséquence indirecte de cette philosophie :
de nombreuses propriétés sont accessibles uniquement par l'interface de l'IDE et pas programmation (quelques exemples pêle-mêle : liaisons des ruptures de table, GUID d'une rubrique, certaines propriétés des fenêtres...).
Interessante ta remarque Arnaud concernant une fenetre pouvant afficher n'importe quel fichier.
Pourquoi interessante ? parce que la méthode en vogue (dev web autour de joomla par exemple) actuellement est basée sur le MVC et que donc tu as au final autant de fenetres que de besoins en affichage... Peut-on dire que WinDev était précurseur avec son générateur RAD ?
Emmanuel Lecoester
=> joomla addict.
Bien vu, c'est vrai que ConstruitTableFichier() est assez puissant.
Bon je ne me souviens plus exactement ce qui m'avais gêné à l'époque, mais je me souviens l'avoir utilisé, puis l'avoir abandonné à cause de certaines limitations (désolé ma mémoire me fait défaut).
Prenons alors un autre exemple, qui serait de générer un formulaire de saisie dynamiquement (et non pas une table).
Autre chose que je trouve mal conçue dans wd : c'est la portée du contexte Hyperfile.
En gros, on a le choix entre :
- un contexte global à tout le projet
- mais pas à certaines fenêtres si on coche "contexte HF indépendant" dans la description de la fenêtre.
Plusieurs problèmes à mon avis :
- le fait que par défaut, un contexte soit global
- pourquoi un contexte de données serait lié à la fenêtre ?? Faire l'équation fenêtre=contexte de données c'est simplificateur dans une application.
- on ne peut pas déclarer de nouveau contexte par programmation
Le plus logique serait de devoir explicitement déclarer un contexte. Par exemple, avec une commande HDéclareContexteHF().
Je tombe souvent sur des applications qui ont été développées avec un contexte HF commun à toutes les fenêtres, et parfois des HSauvePosition() pour faire des lectures séparées. C'est en général une catastrophe, et on toujours des cas d'écrasement des données.
On sent d'ailleurs une évolution depuis la v17 avec la possibilité d'avoir un contexte HF indépendant pour une classe.
Des fois PC Soft laisse des traces de développements inachevés :
Ca fait vraiment pas sérieux.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 Trace(TypeVar(0n42), wlNumérique) // OK Trace(TypeVar(0m42), wlMonétaire) // OK Trace(0n41 + 0n1) // 42 Trace(0m41 + 0m1) // 0 !
Testé dans dans WD17 et WD18.
Autre chose que je trouve mal conçue dans Windev : les paramètres des requêtes (requêtes créées sous l'éditeur).
Avec HF, on a le droit d'avoir des paramètres dans la clause Where, mais pas dans la clause From !
Ex :
ne fonctionne pas
Code : Sélectionner tout - Visualiser dans une fenêtre à part FROM T1 LEFT OUTER JOIN T2 ON (T1.ID = T2.ID AND T2.RUB = {parametre})
Dans la clause Select non plus :
ne fonctionne pas
Code : Sélectionner tout - Visualiser dans une fenêtre à part SELECT (CASE T1.RUB WHEN {Parametre} THEN 'OK' ELSE 'KO' END) ...
Autre limite : impossible de passer la valeur Null à un paramètre,
car
conduit à ignorer le paramètre, et non pas à sélectionner les valeurs égales à Null.
Code : Sélectionner tout - Visualiser dans une fenêtre à part requete.parametre = Null
En fait, on ne peut pas paramétrer IS NULL avec les requêtes de HF.
Compte tenu de ces limitations, on est très vite obligé en pratique d'utiliser des requêtes SQL dont on définit le code en fonction des critères voulus.
euh...
1 - les join c'est pour les jointures pas pour les clauses de restriction where (je regarde dans la journée la norme SQL)
2 - tester un case sur un paramètre c'est vrai que çà peut être utile
3- tester dans une clause where une colonne = un paramètre null c'est chaud... surtout que chez sgbd a sa fonction pour tester une colonne nulle (is_null(), null()) donc pas choquant en soi
au final j'ai du mal à comprendre pourquoi passer par des paramètres pour tes 2 derniers cas. d'autant plus que çà "casse" un peu les stats de tes requetes
Emmanuel Lecoester
=> joomla addict.
Je ne suis pas d'accord. Dans le cas d'une jointure externe, la restriction doit être mise dans la jointure, sous peine de transformer celle-ci en jointure interne:
Revient en fait à ceci:
Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 select 1 from Table1 left outer join table2 on table1.col1 = table2.col1 where table2.col3 = XXX
Puisque dans le cas de ligne de Table1 qui "n'ont pas d'équivalent" dans Table2, Table2.col3 vaut null et ne vérifie pas le test table2.col3 = XXX. Pour que la jointure fonctionne il faut mettre le test sur table2.col3 dans la jointure.
Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 select 1 from Table1 INNER join table2 on table1.col1 = table2.col1 where table2.col3 = XXX
Pas d'accord non plus. IfNull, Coalesce... ne servent qu'à transformer un null dans le select. Pour le test de null dans la clause Where, la norme est Table.Colonne is null. D'ailleurs la syntaxe d'Arnaud B. ne doit pas non plus fonctionner car null ne vérifie aucune égalité.
Pour moi la seule façon de s'en sortir ici est de se passer de l'éditeur de requête, et d'utiliser le couple ChaineConstruit + (hExecuteRequeteSQL/SqlExec).
Et puis c'est une bonne raison de se former au SQL
Tatayo.
Je ne comprends pas le problème. Si on veut que table2.col3 = XXX alors il est normal d'exclure tout ce qui n'a pas de table2.col3, sinon on ajoute OR table2.col3 IS NULL ou un COALESCE.
Personnellement, j'ai souvent utilisé des valeurs dans mes conditions de jointures en SQL Server, notamment quand c'est juste plus logique (jointure sur une clé composée notamment), donc je suis d'accord sur le fond. Mais là, quelle requête auriez-vous voulu écrire ?
Sinon, pour tous ces points, je ne pense pas qu'on puisse appeler ça des fautes de conception, l'éditeur de requêtes n'a pas vocation à remplacer définitivement le SQL.
tatayo tu m'as devancé
OK pour le filtre en plus dans une jointure ouverte.
Pour le "is null" on en revient à ce que je dis : faire colonne = parametre null çà fait désordre.
et au final on se rejoint sur le sujet : apprenez le SQL
@Hibernatus : j'apprécie ta remarque "je ne pense pas qu'on puisse appeler ça des fautes de conception"
Emmanuel Lecoester
=> joomla addict.
Hibernatus34: Par rapport à ce que veut faire Arnaud B., il faut bien ajouter le test sur le paramètre dans la jointure, puisqu'il s'agit d'une jointure externe. Or il semble que WinDev ne permette pas de mettre un tel test dans la jointure.
Or je pointait du doigt le fait que déporter ce test dans la clause Where transforme la jointure externe en jointure interne.
Ces deux requêtes ne sont pas équivalentes:
Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 SELECT 1 FROM Table1 LEFT OUTER JOIN table2 ON table1.col1 = table2.col1 WHERE table2.col3 = XXX
Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 SELECT 1 FROM Table1 LEFT OUTER JOIN table2 ON table1.col1 = table2.col1 AND table2.col3 = XXX
Maintenant je suis d'accord avec toi, on peut tout à fait écrire la requête ainsi:
Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 SELECT 1 FROM Table1 LEFT OUTER JOIN table2 ON table1.col1 = table2.col1 WHERE (table2.col3 = XXX or table2.col3 is null)
mais je me demande comment réagit WinDev si XXX est un paramètre, et qu'il n'est pas renseigné. A tester !
Tatayo.
Pour moi, le résultat sera le même pour les 2 premières.
Et la troisième n'est pas équivalente à la deuxième.
Me trompé-je ?
Désolé, je devais être dans la Lune.
Vous avez parfaitement raison.
Dans la norme SQL, ça s'appelle une condition de sélection dans le prédicat de jointure et c'est très utile.
Par exemple, si je veux :
- tous les clients qui n'ont pas de facture
- et aussi les clients qui ont une facture en 2013
... je ferai :
C'est LA syntaxe définie par la norme SQL pour écrire ce type de requêtes. C'est comme ça. Cette norme existe, elle est universellement connue et reconnue, validée par l'ISO (sous le nom ISO/CEI 9075) qui regroupe 164 pays , donc ça me parait logique de l'utiliser.
Code : Sélectionner tout - Visualiser dans une fenêtre à part SELECT * FROM CLIENT LEFT OUTER JOIN FACTURE ON (CLIENT.IDCLIENT = FACTURE.IDCLIENT AND FACTURE.ANNEE = '2013')
Bien entendu, je peux aussi écrire
qui est aussi admise par la norme SQL (puis IS NULL est prévu par la norme).
Code : Sélectionner tout - Visualiser dans une fenêtre à part SELECT * FROM CLIENT LEFT OUTER JOIN FACTURE ON (CLIENT.IDCLIENT = FACTURE.IDCLIENT) WHERE FACTURE.ANNEE = '2013' OR FACTURE.ANNEE IS NULL
Personnellement, je ne connais pas les intentions de pc soft.
Quelque soit la vocation de l'éditeur de requêtes, je trouve incohérent :
- de ne pouvoir utiliser des paramètres que dans certains clauses
- de ne pas pouvoir paramétrer le IS NULL (le fait d'affectuer Null à un paramètre = ignorer le paramètre -> moi je ne trouve pas ça très logique ! je suis persuadé que pc soft non plus, mais c'est probablement l'héritage de l'époque ou HF ne gérait pas du tout le null).
Bien sûr, il est toujours plus profitable d'apprendre le SQL (d'ailleurs tout développeur devrait en apprendre les bases).
MAIS si l'on passe par des requêtes SQL avec du code SQL construit dynamiquement dans Windev (chose que je pratique quasi-systématiquement) :
- on perd l'avantage de l'autocomplétion sur les rubriques
- on perd la possibilité de définir les liaisons (par exemple dans un champ table) entre les colonnes et cette requete.
Donc ce n'est pas tout à fait équivalent aux requêtes de windev...
L'éditeur de requête n'utilise pas JOIN pour faire les jointures, il les fait dans le WHERE...
Par contre quand on rentre dans la description de jointure et qu'on coche qu'il faut inclure des enregistrement même quand ils ne sont pas dans les deux fichiers en relations, là il utilise les LEFT JOIN, RIGHT JOIN et autre FULL OUTER JOIN...
Pour ce qui est de placer des clauses de restriction au niveau du JOIN plutôt que du WHERE c'est mieux surtout s'il y a plusieurs jointures en cascades.
En effet ça limite le nombre d'enregistrement pour les quels la jointure est cherchée.
Quand les fichiers sont gros ça peut faire gagner beaucoup de temps...
Enfin pour les requêtes complexes je rejoint Tatayo, pour lever les contraintes je préfère utiliser ChaineConstruit + hExecuteRequeteSQL que l'éditeur de requête...
Bon dev
Laurent
- C’est génial.
- Non c’est bizarre.
- Justement quand c’est simple y’a des milliers de réponses et quand c’est bizarre y’en a aucune.
Le 1er point est un peu lié au 2ème, puisqu'un paramètre de requête n'est pas qu'un simple remplacement d'un tag par une valeur.
Je pense que le choix de PC Soft a été de traiter le cas le plus usuel : on définit un filtre sur les données, et on veut le faire avec une seule requête pour plusieurs critères optionnels.
J'avoue cependant ne pas aimer non plus ce système et ne pas m'en servir.
C'est vrai.
Ces choses sont pour moi un lointain souvenir, mais c'est vrai que ça serait pratique.
J'aimerais voir un jour un nouveau type "requête", un peu comme le type "source de données", mais dans lequel on définit le code (avec coloration syntaxique) et des paramètres typés et qui permet la complétion sur les noms de colonnes (en déclarant à la main ces noms dans le cas où WinDev serait incapable de parser la requête). Ce type règlerait au passage le problème de portée des sources de données.
Exemple :
Le Toto.param2 = monTableau je le gère déjà avec les sources de données en OLE DB, c'est bien pratique.
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
17
18
19
20 Toto est une requête(param1 est entier, param2 est tableau de Variants, param3) [ SELECT Bob, COALESCE(John.Jen, {param1}) AS Jen FROM Bill LEFT JOIN John ON John.Bob = Bill.Bob WHERE Ben IN {param2} OR Burt = {param3} ] colonnes (Bob, Jen) // Optionnel, mais nécessaire pour certaines requêtes sur d'autres SGBD que HF Toto.param1 = "42" // Ne fera pas '42' (chaîne) mais 42 (entier) Toto.param2 = monTableau Toto.param3 = "51" // Là on garde le type d'entrée (chaîne) HExécuteRequête(Toto) Trace(HNbEnr(Toto)) // Type requête accepté partout où les sources de données l'étaient POUR TOUT Toto ... FIN
Absolument, j'en rêve aussi.
Un peu l'équivalent de ce qu'à fait Microsoft avec LINQ dans .NET ? (je n'utilise pas, mais il parait que c'est bien).
Sinon personnellement j'utilise une méthode de contournement :
- je créé dans l'éditeur de requêtes une requete avec dans la clause SELECT les colonnes dont j'ai besoin (peu importe les autres clauses du moment que c'est correctement reconnu par Windev)
- comme ça j'ai l'autocomplétion, je peux relier cette requête aux tables, combos, colonnes... avec l'interface.
- MAIS je rédéfinis le code SQL de cette requete par programmation, pour avoir plus de souplesse/puissance (donc j'exécute la requête avec HExecuteRequeteSQL(marequete, sCodeSQL))
Exactement. Je reste persuadé que si une syntaxe existe dans la norme SQL, c'est parce qu'elle est censée être optimisée par les SGBD.
Si on a inventé le INNER JOIN et le OUTER JOIN, ce n'est pas pour faire joli, c'est pour que les SGBD puissent savoir comment traiter la requête et l'optimiser.
Donc jusqu'à preuve du contraire, il est préférable d'utiliser ces syntaxes.
Très intéressant. Je ne savais pas que c'était possible.
On peut quand même avoir peur qu'un jour ça ne fonctionne plus, car c'est probablement pas une fonctionnalité désirée.
L'autre problème c'est qu'on perd la suppression automatique de la requête (comme avec une source de données déclarée localement).
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager