lundi 21 juin 2010

Agrégation de strings

Comment avoir dans son result set un groupement de string qui serait agrégé et séparé par des virgules? Nous allons prendre comme cas d'utilisation la table des pays du schéma HR fournit par Oracle (HR.COUNTRIES). Nous voulons avoir pour chaque lettre de l'alphabet la liste des pays séparé par des virgules correspondant à cette lettre.

Il existe diverses solutions en Oracle pour arriver à cette fin. La plus récente (Oracle 11.2g) consiste à utiliser la fonction LISTAGG et de réaliser un group by. La requete suivante donne le résultat attendu :
La clause WITHIN GROUP(...) permet de réaliser un tri au sein de l'agrégation et ainsi avoir les pays triés par ligne du result set.

Pour les malchanceux(comme moi) qui n'ont pas la chance d'utiliser Oracle 11.2g, quelles sont les solutions à notre disposition pour réaliser la tâche demandée ? Après quelques recherches sur le Web, j'ai pu trouver la fonction wm_concat du package wmsys. La requete utilisant cette fonction est la suivante :
Cependant, cette solution n'est pas géniale. Premièrement, le result set n'est pas trié par ligne et la clause WITHIN GROUP n'est pas applicable sur cette fonction. La solution serait alors d'utiliser un PARTITION BY dans le select et d'ensuite filtrer pour n'avoir que les résultats qui contiennent l'ensemble des pays :

Le second problème lié à cette solution vient de sa non-documentation. En effet, cette fonction est undocumented et vous ne pourrez donc pas bénéficier du support d'Oracle en cas de problème avec cette fonction. De plus, la version exacte de la solution est assez lourde.

Quelles sont les solutions si on utilise une version d'Oracle un peu moins récente et qu'on ne veut pas utiliser une fonction non documentée ? Il existe sans doute plusieurs solutions à ce problème, les unes les plus originales et farfelues que les autres. Celle que j'ai dernièrement utilisée est la suivante :
 Cette solution utilise tout d'abord la fonction d'agrégation RANK pour mettre un ranking sur les noms de pays portant la même première lettre. Ensuite, nous utilisons les clauses connect by et la fonction sys_connect_by_path pour agréger les pays qui porte la même première lettre et de réaliser le tri a au sein de chaque résultat.

Enfin, il est bien évidemment possible de réaliser sa propre fonction qui permet de réaliser cette agrégation de strings. Plusieurs sites présentent leurs implémentations(voir sources)

Sources :

mardi 15 juin 2010

Enum Java-like en C#

Si vous avez l'habitude de programmer en Java et que vous passez dans le monde de Microsoft avec le C#, vous vous êtes peut-être déja demandé pourquoi les Enums C# sont aussi primitif que les enums en C. En effet, contrairement à Java(à partir de la version 5), il n'est pas possible d'ajouter des propriétés sur les Enums C#. Serait-ce une fonctionnalité propre et uniquement valable pour les développeurs Java ?

En effectuant plusieurs recherches sur internet, j'ai trouvé une solution qui permet de simuler le fonctionnement des enum java sur le .NET framework en C#.

La solution que je vais vous présenter consiste à utiliser les attributs sur les valeurs de l'énumération et d'utiliser la reflection pour récupérer les valeurs des attributs.

L'exemple le plus fréquent en Java est l'énumération des planètes du système solaire sur lesquelles il est possible de récupérer des informations complémentaires tel que le diamètre ou le poids de la planète, par exemple.

Alors en pratique comment faire ?

Premièrement, il est nécessaire de définir les attributs à utiliser, par exemple l'attribut MassAttribute:
L'attribut hérite de la classe Attribute, on lui définit un constructeur prenant un paramètre de type double et une propriété Mass avec un getteur qui retourne la valeur de la masse. Une fois définie, il est possible d'ajouter les attributs sur les valeurs de l'enum :
Maintenant que notre énumération de planètes est décorée de ses attributs, il est possible de récupérer les valeurs stockées dans ces attributs via la réflection. La méthode GetCustomAttributes de la classe FieldInfo permet de récupérer les attributs de la classe. Cette méthode prend en paramètre le type de l'attribut ainsi qu'un booléen qui détermine si il faut aller chercher les attributs dans les classes héritées ou non(Il existe également une signature de cette méthode qui ne prend pas le type de l'attribut mais cette dernière retourne, évidemment, tous les attributs liés au Type). Si vous avez défini que votre attribut Mass est unique pour chaque élement de l'énum, il suffit de récupérer l'élement d'index 0 de la liste des attributs retourné par la fonction. Ce qui donne :
Enfin, pour avoir le meme comportement que les enums Java, il est nécessaire de pouvoir récuperer la valeur de l'attribut en appelant une méthode directement sur l'objet de l'énumération. Pour ce faire nous allons définir une classe static avec des méthode pour étendre l'énum. Nous allons donc utiliser le fait que le C# permet d'étendre des classes en leur rajoutant de nouvelles méthodes avec les Extension methods(http://msdn.microsoft.com/en-us/library/bb383977.aspx) :
Ainsi, il est donc possible de faire appel à la méthode GetMass sur une valeur de l'énumération Planets que nous avons précédemment créé et d'avoir un fonctionnement similaire aux enums Java meme si la mise en oeuvre de ce système est beaucoup plus lourde que ce qui est mis à disposition des développeurs Java.
Une fois de plus, le langage C# de Microsoft se montre sans limite...

mercredi 9 juin 2010

Des couleurs dans la console

Le  blanc sur fond noir c'est parfois un peu lassant. Il est possible avec la console du framework .NET de mettre un peu de gaieté dans sa console. Les couleurs disponibles se trouvent dans l'énumeration System.ConsoleColor qui contient les couleurs suivante:

évidemment le noir(Black) sur fond noir ne se voit pas très bien. Il est également possible de changer la couleur de fond de votre console ce qui donne selon les couleurs :
Cette fois-ci, vous noterez que c'est le gris(Gray) sur fond gris qui ne passe pas très bien.

Bon passons à la pratique. Comment afficher du texte coloré ou avoir un fond coloré sur son texte ? Voici un petit bout de code manipulant les couleurs de la console :
 Ce code modifie la couleur du texte écrit dans la console (Console.ForegroundColor) ainsi que la couleur de fond du texte écrit (Console.BackgroundColor). Après avoir joué avec les couleurs, il est possible de revenir aux couleurs par défaut en effectuant un appel à la méthode ResetColor. Voici l'exemple généré par ce code : 
Afin d'avoir le fond coloré sur toute la ligne, il est nécessaire de réaliser un padding sur votre chaîne de caractères à afficher. Heureusement pour nous, la classe string dispose d'une méthode RightPadding permettant de completer la ligne... La propriété statique WindowWidth de la classe Console permet d'obtenir la largeur actuelle de la console en nombre de caractères. Ainsi, meme si votre utilisateur a défini une taille différente, il est possible de connaitre le nombre de  caractères que vous pouvez écrire sur une ligne de la console avant de devoir faire un retour à la ligne.

Voila, maintenant vous n'avez plus d'excuses pour avoir des jolies consoles pleines de couleur. Je pense qu'avoir du texte rouge en cas de problème et du vert lorsque tout est ok permet de faire ressortir des messages importants dans une application console. Donc n'hésitez surtout pas à en faire (bon) usage. 

Ca y est je me lance

Depuis quelques temps je me dis que ca serait bien si je notais tous les trucs cools que je faisais lorsque je suis au boulot. Il m'arrive fréquemment de me dire :"J'ai déja fait ca... mmmh comment on le faisait déjà ?"

Donc voila, mes notes de geeks je vais les noter sur ce blog afin que d'autres puissent éventuellement s'en servir et le jour ou je devrai faire quelque chose que j'ai déja fait... Allez hop sur mes notes de g33k.

Ce blog me permettra de récupérer tous mes trucs et astuces, mes diverses notes et autres petites choses que je rencontre dans mes tâches journalières en informatique. Travaillant actuellement en ASP.NET/C# 3.5 et sur Oracle 10g mes notes seront principalement sur ces 2 technologies.

Réunir toutes ces notes sur ce blog me permettra ainsi de centraliser mes informations et cela me forcera également à les noter de manière propre et réutilisable.