Vagrant : Mise en place d’une box prête à l’emploi

Dans l’article précédent  (Veewee : La creation d’une boite Vagrant), nous avons vu comment créer une machine virtuelle prête pour Vagrant.

Considérons que nous avons avons ajouter la box à l’environnement Vagrant avec la commande :

vagrant box add 'myubuntubox' 'pathto/myubuntubox.box'
Si vous le souhaitez, je peux vous fournir une box Ubuntu 12.04 server X64.
Une fois, cette dernière ajouter à votre environnement, il convient de créer votre machine virtuelle en utilisant les commandes suivantes :
vagrant init 'myubuntubox'
vagrant up
vagrant ssh
Vous vous trouverez alors dans la machine virtuelle, sur laquelle vous pourrez installer vos outils de développement.
Le principe de Vagrant est similaire à celui du Cloud, vous avez soit un environnement vierge que vous vous paramétrez, soit un environnement prêt à l’emploi qui vous permet de fournir le même environnement à toute une équipe.
Pour ce dernier point, il convient d’utiliser un outil de provisionning, pour ma part, j’ai choisi Chef, mais il y en a d’autres comme Puppet .etc..

Dans le cas de Chef, on trouve de nombreuses recettes sur Github permettant d’installer à peu près tout, avec par exemple le repository officiel d’Opscode (https://github.com/opscode-cookbooks).

Afin de simplifier, un peu la vie de ceux qui veulent se lancer, j’ai préparer un petit projet qui vous permet de vous lancer : https://github.com/gpsnail/VagrantBox
Suivez les instructions du README pour commencer.

N’hésitez à me faire part de vos commentaires.

tip pentaho/déploiements: rafraîchir le repository

Le problème est très vite arrivé quand on veut déployer de nouveaux rapports sur plusieurs serveurs différents de façon automatique.
imaginons que ayez un nouveau rapport de type CDE ( kesako ?)que vous avez fabriqué sur votre serveur local.

Vous avez copié les fichiers physiques du rapports  sur le serveur de production grâce à  un script shell par exemple.
Si vous vous connectez sur votre console utilisateur (https://monserveur:8080/pentaho/Home), vous ne voyez pas le nouveau rapport !!
L’explication est simple, tant que vous n’avez pas rafraîchi la solution , les nouveaux fichiers ne sont pas pris en compte par le moteur Pentaho.
Sous le capot, Pentaho utilise un indexage des fichiers qu’il enregistre dans la base de données ( tables PRO_FILES  et PRO_ACLS_LIST dans la base de données hibernate).
Tant que l’on a pas commandé à  pentaho de rafraîchir le repository, les nouveaux objets qui ont été copiés n’ont pas été enregistrés dans l’index pentaho.
Comment on peut piloter ce rafraîchissement, par exemple par script shell ?
La seule façon que j’ai trouvé est de créer une page jsp que je vais installer dans le contexte d’exécution de pentaho.
Je vais l’appeler RefreshRepository.jsp et voici le code :

<%@ page language= »java »
import= »org.pentaho.platform.engine.core.system.PentahoSystem,
org.pentaho.platform.api.engine.IPentahoSession,
org.pentaho.platform.web.jsp.messages.Messages,
org.pentaho.platform.api.engine.IUITemplater,
org.pentaho.platform.web.http.WebTemplateHelper,
org.pentaho.platform.util.messages.LocaleHelper,
org.pentaho.platform.api.repository.ISolutionRepository,
org.pentaho.platform.repository.solution.dbbased.DbBasedSolutionRepository,
org.pentaho.platform.web.http.PentahoHttpSessionHelper » %>
<%
response.setCharacterEncoding(LocaleHelper.getSystemEncoding());
IPentahoSession userSession = PentahoHttpSessionHelper.getPentahoSession( request );
String content = «  »;
ISolutionRepository solutionRepository = PentahoSystem.get(ISolutionRepository.class, userSession);
solutionRepository.reloadSolutionRepository(userSession, userSession.getLoggingLevel());
content = « OK refresh »;
%>
<%= content %>

Je n’ai plus qu’à  déployer cette page dans le répertoire suivant :

biserver-ce/tomcat/webapps/pentaho/jsp/

Une fois fait, je peux maintenant piloter le refresh  en faisant  :

https://monserveur:8080/pentaho/RefreshRepository?userid=totologin&password=XXXX

Du coup je peux piloter le refresh  par script Shell :

 wget  –quiet  -O – « https://monserveur:8080/pentaho/RefreshRepository?userid=totologin&password=XXXX »

tip trac/ldap : usage de ldap-filter

Il y a quelques temps j’ai dû ouvrir à des personnes externes un site de gestion d’incidents ( trac). Il se trouve que nous gérons les clients comme des contacts dans notre système openldap.
En gros un client a type a comme structure dans ldap :

dn: cn=jean Filemonpul,ou=clients,ou=Users,dc=masociete,dc=com
cn: jean Filemonpul
givenname: jeanfil
mail: jean.filemonpul@parlespieds.com
mobile: +33473000011
objectclass: inetOrgPerson
objectclass: extensibleObject
objectclass: person
objectclass: mailAccount
objectclass: top
ou: client
sn: filmonpul
uid: jfil
userpassword: {MD5}9×2+54ef34zeLOL4OneqsqsrSUgXUlsdsg==se

Par opposition, un utilisateur interne a cette structure:

dn: cn=pikki@masociete.com,ou=Users,dc=masociete,dc=com
cn: pikki@masociete.com
givenname: pikki
mail: pikki@masociete.com
mailbox: /home/vmail/masociete.com/pikki
mailenable: OK
mailuserquota: 1048576
mobile: +336XXXXXXXX
objectclass: inetOrgPerson
objectclass: extensibleObject
objectclass: person
objectclass: mailAccount
objectclass: top
ou: masociete
sn: pikki
uid: pikki
userpassword: {MD5}q09j+fqgfg4645refgzereza33454==

 La grosse différence est donc l’unité organisationnelle ( ou)  qui est soit « masociete » soit « client ».
On veut donc autoriser l’accès au gestionnaire d’incident ( trac) à ces deux profils.
Pour cela, dans le fichier de configuration dans /etc/apache2/sites-enabled on va utiliser l’instruction Require ldap-filter dont la doc est à  cette adresse .

Le truc est de savoir si la requête ldap va fonctionner ou pas. pour cela j’ai testé cette requete: 

ldapsearch -W -x -D « cn=moimeme,dc=masociete,dc=com » '(|(ou=masociete)(ou=client))'

qui veut dire: << cherche toutes les entrées du ldap ayant comme "ou" soit "masociete", soit "client" >> .Nickel, il me renvoie bien des entrées. Du coup, je me dis, je vais mettre ça dans mon fichier de config apache : 

Require ldap-filter (|(ou=client) (ou=masociete))

katastrof, en rechargeant apache( service apache2 reload)  , impossible de se connecter ni en tant que client , ni en tant qu’utilisateur.

Il suffit juste d’enlever les parenthèses les plus excentrées pour que ça marche ( va comprendre..) .


Voici mon fichier de configuration: 

 ServerAdmin admin-system@masociete.com
 ServerName tickets.masociete.com
 DocumentRoot /var/www/tickets
 
  Options FollowSymLinks MultiViews
   AllowOverride AuthConfig
 

 
  Options +SymLinksIfOwnerMatch
  AllowOverride All
  Order allow,deny
  Allow from all
 

 ErrorLog /var/log/apache2/trac/error.log
 LogLevel warn
 CustomLog /var/log/apache2/trac/access.log combined
 ServerSignature On
  #set up Trac handling
  SetHandler mod_python
  PythonHandler trac.web.modpython_frontend
  PythonOption TracEnv /var/www/tickets
  PythonOption TracUriRoot /
  PythonPath « sys.path + [‘/var/www/tickets’] »
 

 
  AuthType Basic
  AuthName « LDAP auth »
  AuthBasicProvider ldap
  AuthLDAPUrl ldap://127.0.0.1/ou=Users,dc=masociete,dc=com?uid?sub
  AuthLDAPBindDN « cn=rechercheuser,dc=masociete,dc=com »
  AuthLDAPBindPassword XXXXXXX
  Require ldap-filter |(ou=client) (ou=masociete)
 

Veewee : La creation d’une boite Vagrant

Comme je l’abordais dans mon précédent article, l’utilisation de Vagrant pour le développement a été pour moi un gros plus et une superbe découverte.

Mais, vous allez me dire comment créer sa propre Box en effet, il est pas évident de faire confiance à celle que l’on peut trouver sur internet surtout dans le cadre d’une équipe de projet.

C’est à ce titre, que je conseille l’utilisation de Veewee (https://github.com/jedi4ever/veewee) qui permet de créer toutes sortes de Box et qui est surtout d’une simplicité d’utilisation déconcertante.

Le pré-requis pour l’utilisation de veewee est une plate-forme ruby 1.9.2 et la dernière version de VirtualBox (https://www.virtualbox.org), là, il faut impérativement installer RVM sur la machine qui va vous servir à créer votre box et cela afin d’avoir la meilleur version possible de ruby à savoir la 1.9.2p290.

Une fois, les pré-requis en place, la meilleure façon de procéder est de cloner veewee à partir de Github, le procédure d’installation est très bien faite : https://github.com/jedi4ever/veewee/blob/master/doc/installation.md

Ensuite, il y a juste à utiliser veewee (il faut se positionner à la racine du répertoire veewee) et voici la procédure à suivre pour créer une boite directement sans trop de changement :

Ce processus crée une nouvelle définition de boîte dans le répertoire veewee/definitions. Vous pouvez si vous vous en sentez le courage modifier les fichiers mais à titre d’exemple nous le ferons pas. La prochaine étape est de créer la Box :

Cette étape prend pas mal de temps à cause essentiellement des téléchargements d’images ISO nécessaire à l’installation. Vous pourrez suivre de manière simple la procédure.

Une fois, cette étape terminée, vous aurez une boite en place :

Une fois, la box créée, vous pourrez l’exporter dans une fichier « .box » à distribuer à l’ensemble de votre équipe de développement avec la commande suivante :
Nous venons de voir comment créer une Box vide, cependant, maintenant le problème se pose de la mise en place celle-ci dans un environnement réel avec les outils nécessaires comme mysql, postgres, php .etc.. Nous allons pour cela utiliser le système de « Provision » permettant à partir d’un script de mettre en place l’environnement et de l’utiliser ensuite au quotidien. Nous aborderons cela dans un prochain article en attendant, je ne saurait que trop vous conseiller de tester.

Vagrant : Le développement sur VM

Nous nous sommes tous heurter à la difficulté de mettre en place son environnement de développement, surtout dans le cadre de la mise en place d’une plateforme homogène entre plusieurs postes sans ajout de logiciels tiers et le plus proche possible de l’environnement de production.

– Exemple : une plateforme PHP, MySQL, Postgres dans le cadre de la migration d’un application PHP de MySQL vers Postgres.

Au fil de mes recherches sur le net et surement avec beaucoup de retard je suis tombé sur Vagrant. (https://vagrantup.com)

Vagrant a pour but de rendre plus simple l’utilisation de machine virtuelle dans le cadre de l’environnement de développement. On peut le dire le but est atteint pour la facilité de développement entre la machine hôte et la VM.

Le plus compliqué avec Vagrant va être de créer sa propre machine proche des habitudes de développement de l’équipe. Car Vagrant n’est pas là pour cela, il est juste là pour le montage de la machine et son utilisation au quotidien.

Heureusement, la communauté est très active sur le sujet et des outils sont là pour simplifier la création de sa propre Box avec quelques connaissances. Je pense notamment à Veewee (https://github.com/jedi4ever/veewee) qui est vraiment un outil à s’accaparer pour la création de sa propre Box, n’hésitez pas à dupliquer le projet et pusher vos modifications pour mettre à disposition vos Box, c’est d’ailleurs ce que je vais faire.

Mais, ne vous inquiétez pas, je vous prépare un petit tutoriel pour l’utilisation de Veewee avec une Box en français.

Et, important à savoir tout cela, c’est en Ruby.

Tip SQL: pourquoi Migrer de MySQL vers PostgreSQL?

Comment dire….
quand on a fini de jouer avec MySQL et que l’on veut passer en production, on cherche un moteur SQL de pros.
C’est un peu comme quand tu as cassé ta perceuse achetée chez Lidl (en promo !) et que tu bave devant la bosh dans le rayon chez casto…
Moi, mon vendeur, il m’a fait l’article et je viens tout juste de déballer le paquet:  PostgreSQL 9.
Avec ça, j’ai bien envie de percer des trous partout dans mes serveurs…
Bon, je m’emporte:

  1. MySQL c’est quand même bien!
  2. je fais toujours des courses chez lidl
  3. même facebook utilise la perceuse pas cher de chez Lidl ( MySQL)
C’est quoi les avantages de MySQL ?
  • d’abord le moteur est facilement configurable
  • l’outil de requêtage MysqlWorkBench est pas mal –  je dirais même , il s’approche de ce que fait Microsoft.
  • la doc en ligne est ok
  • la communauté est active
Mais quand on se penche un peu sur le bestiau, il y a des trucs qui me gênent : 
  1. la sauvegarde incrémentale InnoDB => pas disponible en mode gratos. Vas donc sauvegarder 400 Go d’un serveur sur-sollicité….
  2. le mode mono-thread sur les requêtes : Fais donc une auto-jointure sur une table de 25 millions d’enregistrements; ben, tu peux pas Mr patate !! en tout cas pas avec ton kimsuffi à  trois euros six sous. 
  3. pas de sharding (répartition de données)  sauf à  l’implémenter côté applicatif; Bref, réinventer ce foutu fil à couper le beurre que j’ai eu tant de mal à réinventer les 50 dernières fois.
  4. et puis j’ai aussi envie de changer les rideaux , donc je veux ma nouvelle perceuse !
Alors quelle perceuse doit-je prendre ? en général, le vendeur vous demande ce que vous allez en faire.
Moi, je veux :
  1. une Bdd gratos
  2. facile à  administrer 
  3. grosse volumétrie
  4. qui va se comporter en entrepôt de données ( peu de transactions, beaucoup de lectures, beaucoup de calculs)
  5. compatible avec ce qui a déjà  été implémenté côté applicatif
  6. le plus proche possible de l’ANSI SQL 92 ( utilisation des instructions JOIN )
Vous savez maintenant ce que j’ai choisi comme Base de données….

Et vous, vous pensez quoi des avantages de l’un et de l’autre ?

Tip MySQL: restaurer une table à partir d’une sauvegarde complète

En tant qu’administrateur de base de données MySQL, vous avez surement mis en place une  politique de sauvegarde des bases de données qui permet de sauvegarder toutes les bases installées.
Pour ma part j’utilise automysqlbackup qui permet de faire une rotation des bases de données.
Or ce logiciel sauvegarde l’ensemble des bases dans un seul et même fichier.

Imaginons maintenant qu’un développeur vienne vous dire qu’il a détruit les données d’une table et qu’il faudrait restaurer uniquement cette table à  partir des données de la veille.

La première chose que vous faites et de croiser les doigts en allant regarder dans le répertoire de sauvegarde s’il y a bien un dump des bases.
Ensuite, vous essayez de localiser la table en question avec votre éditeur préféré pour faire un copier coller dans l’IHM MySQL Workbench.
Problème:  le fichier de dump fait 20 Go!
même vi a du mal à  ouvrir le fichier…
Vous devez donc vous pencher sur les capacité du programme sed dont voici une bonne introduction.

L’explication suivante s’appuie sur un exemple précis:
 restaurer la table comments qui appartient à  la base de donées facebook.

Identification des patterns

Si on regarde de plus près le type de sauvegarde qu’automysqlbackup effectue ( grâce au programme mysqldump), on remarque plusieurs choses :

  • avant  chaque création de base de données on retrouve un commentaire.Exemple : 


— Current Database: `facebook`

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `facebook` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `facebook`;

  • pour chaque table , la table est détruite ( commande DROP)

DROP TABLE IF EXISTS `comment`;

  • la table est crée, verrouillée, les données sont insérées puis enfin la table est déverrouillée : 

UNLOCK TABLES;

On peut donc en déduire une stratégie :

  1. d’abord extraire la base de données cherchée et la sauvegarder dans un fichier
  2. ensuite extraire la table  cherchée et la sauvegarder dans un fichier

Extraction de la Base  de données 

On va donc utiliser le pattern « Current Database » pour  extraire uniquement la base de données facebook:

sed -n -e ‘/Current Database: .facebook/,/Current Database/p’ mon_fichier_de_dump.sql > facebook.sql

cette commande va extraire à  partir du fichier mon_fichier_de_dump.sql tout ce qui se trouve entre le texte « Current Database: `facebook` » et le prochain texte « Current Database: »  et sauvegarder dans le fichier facebook.sql.

l’option -n avec l’option /p  permet à  sed de n’écrire que les lignes comprises entre les deux patterns.
l’option -e

Extraction de la table

Une fois que la base de données est extraite, on peut maintenant extraire la table comment :

sed -n -e ‘/DROP TABLE.*`comment`/,/UNLOCK TABLES/p’ facebook.sql > comment.sql

Restauration de la table

 Il suffit ensuite de restaurer la table comments dans votre serveur de base de données avec la commande mysql:

mysql -h myserver.mynetwork.com  -u root -pmyPassword -D facebook< facebook.sql

Evidemment, vous pourrez modifier

Tip SQL/MDX: chercher le top X pour chaque groupe

Une des demandes les plus récurrentes, lorsque l’on fait des tableaux de bord c’est de retrouver les « 10 meilleurs clients par zone commerciale », ou encore les « 10 plus gros contributeurs facebook par page » .

Aujourd’hui je vous propose 3 façons de résoudre cette problématique en SQL, selon le système  utilisé.
Imaginons la table suivante:

Create   TABLE Contribs (id_page int, page varchar(50), fan varchar(50) , contribs INT);

INSERT INTO Contribs VALUES (2, ‘françois Hollande’, ‘toto’ , 65);
INSERT INTO Contribs VALUES (2,’françois Hollande’, ‘titi’ , 50);
INSERT INTO Contribs VALUES  (2,’françois Hollande’, ‘tutu’ , 30);
INSERT INTO Contribs VALUES (2,’françois Hollande’, ‘tata’ , 20);
INSERT INTO Contribs VALUES  (8,’Nicolas Sarkozy’, ‘toto’ , 5);
INSERT INTO Contribs VALUES  (8,’Nicolas Sarkozy’, ‘titi’ , 41);
INSERT INTO Contribs VALUES   (8,’Nicolas Sarkozy’, ‘tutu’ , 35);
INSERT INTO Contribs VALUES  (8,’Nicolas Sarkozy’, ‘tata’ , 66);
INSERT INTO Contribs VALUES  (8,’Nicolas Sarkozy’, ‘tete’ , 67);
INSERT INTO Contribs VALUES  (24,’Marine Le Pen’, ‘toto’ , 35);
INSERT INTO Contribs VALUES  (24,’Marine Le Pen’, ‘tata’ , 15);
INSERT INTO Contribs VALUES  (24,’Marine Le Pen’, ‘titi’ , 5);
INSERT INTO Contribs VALUES  (24,’Marine Le Pen’, ‘tutu’ , 3);
INSERT INTO Contribs VALUES  (24,’Marine Le Pen’, ‘zozo’ , 2);
INSERT INTO Contribs VALUES  (8,’Nicolas Sarkozy’, ‘zizi’ , 69);
INSERT INTO Contribs VALUES  (8,’Nicolas Sarkozy’, ‘zaza’ , 100);
INSERT INTO Contribs VALUES  (8,’Nicolas Sarkozy’, ‘zuzu’ , 1230);

Cette table correspond à la liste des fans ( champ fan) de pages page facebook avec la liste

Sql Server:

Bon là c’est tellement simple que s’en est bête… on va utiliser la fonction RANK, introduite avec la version 2005
la fonction RANK() , permet de calculer un auto-incrément lors d’une requête.
Par exemple:

select *   from  ( select page, fan, contribs, RANK() over ( Partition by page order by contribs DESC)  as Rank
from  Contribs ) as TEMP
where Rank <=10;

MySql:

Bon, là  on va utiliser une fonctionnalité que j’appellerais « procédurale »de Mysql et non ensembliste.
Je m’explique:
au sein même de la requête, on utilise l’incrémentation au fur et à  mesure que le moteur lit et ordonne les lignes qu’il trouve.
On doit d’abord ordonner les contributeurs  par page:
select page, fans, contribs from Contribs  order by page, contribs DESC;

On introduit l’incrémentation au travers d’une variable : @count.
Dès que le moteur de requête change de  page, il est nécessaire de remettre à  zéro la variable @count.
L’indication du changement de page se fera avec la variable : @oldPage

select  @oldPage := 0 , @count := 0;
SELECT
    @count := IF(id_page <=> @oldPage, @count+1, 0) as mycount,
    @oldPage := id_page,
    page,
    fan,
    contribs
FROM Contribs
ORDER BY id_page, contribs DESC;

Il suffit ensuite de filtrer :

select fan,page, contribs  from (SELECT
    @count := IF(id_page <=> @oldPage, @count+1, 0) as mycount,
    @oldPage := id_page,
    page,
    fan,
    contribs
FROM Contribs
ORDER BY id_page, contribs DESC)  t
where mycount<=10;

ANSI SQL:

On doit toujours revenir aux bases…
Sachant que le langage SQL ne sait pas compter la position dans le résultat, il faut trouver autre chose.
On peut essayer d’imaginer d’extraire pour chaque contribution ( contribs)  le sous-ensemble des contributions supérieures et inférieures.

Pour chaque contribs, on peut extraire le sous ensemble des contribs supérieures:

select C2.contribs, C1.contribs
from  Contribs as C1
join Contribs as C2 on C1.contribs >= C2.contribs

On veut maintenant n’avoir que les contribs qui n’ont que trois contribs qui lui sont supérieurs. On va compter pour chaque sous ensemble le nombre distinct de contribs  :

select min(C1.contribs)
from  Contribs as C1
join Contribs as C2 on C1.contribs >= C2.contribs
group by C2.contribs
having count(DISTINCT C1.contribs) <=3;

Avec cette requête, on récupère ainsi les trois plus hautes contribs c’est à  dire 69,100 et 1230

Enfin, on veut faire le regroupement par page :

select min(C1.contribs) , C1.page
from  Contribs as C1
join Contribs as C2 on C1.contribs >= C2.contribs and C1.id_page = C2.id_page
group by C2.contribs, C1.page
having count(DISTINCT C1.contribs) <=3;

Il ne reste plus qu’à  injecter les noms des contributeurs :

select c.*  from  Contribs c
JOIN
(select min(C1.contribs) as contribs, C1.id_page
from  Contribs as C1
join Contribs as C2 on C1.contribs >= C2.contribs and C1.id_page = C2.id_page
group by C2.contribs, C1.id_page
having count(DISTINCT C1.contribs) <=3) t
on t.id_page = c.id_page and c.contribs = t.contribs;

Et voilà:  on récupère les trois meilleurs contributeurs par page!!
C’est d’ailleurs la requête la plus élégante et celle qui fonctionnera partout.

MDX:

Alors là, le système est très simple  avec l’instruction TopCount puisqu’il permet de faire le filtre pour chaque sous-ensemble.
Par exemple, on crée un « set » des clients à qui on a le plus vendu sur 2012, puis on peut l’utiliser  en dans une requête MDX:

with set [Top10cust] as ‘TopCount({[Client].[ClientName].Members}, 10.0, ([Time].[2012], [Measures].[sales]))’
member [Measures].[Ventes] as ‘[Measures].[sales]’
select {[Measures].[Ventes]} on COLUMNS,
 {[Top10cust]}  ON ROWS
from [Commercial]

Pentaho:calcul du pipe commercial en MDX avec Mondrian – partie 3

Dans mon précédent post j’avais résolu le problème du calcul du pipe pour le mois de janvier.

On avait introduit deux dimensions [TimeStart] et [TimeEnd] qui permettait de faire des filtres sur les dates de début et de fin des devis.
La formule initiale qui permet de savoir le pipe pour le mois de janvier 2011, est celle-ci :
with MEMBER Measures.x as ‘
SUM( NonEmptyCrossJoin(
OpeningPeriod([TimeStart].[Month],[TimeStart].firstchild):[TimeStart].[2011].[Q1].[January],
[TimeEnd].[2011].[Q1].[January]:Closingperiod([TimeEnd].[Month],[TimeEnd].lastchild ) )
, [Measures].[Montant] )’
Select Measures.x on 0
Le problème, maintenant est que l’on doit trouver un moyen pour faire cela pour tous les mois…
On sait que contrairement à MS OLAP, Mondrian n’implémente pas la fonction linkMember et donc ne peut pas lier les deux dimensions TimeStart et TimeEnd entre elles.
Imaginons que l’on ait d’une part la liste de tous les devis ouvert et d’autre part tous les devis fermés, on pourrait ainsi savoir pour chaque période la somme des devis qui ont été traités.
En SQL ça donne :
select T.DateTypeKey , T.TimeKey , T.TimeKeyStart,
T.TimeKeyEnd,
T.montant
from
(select distinct ‘Ouvert’ as DateTypeKey , TimeKeyStart as TimeKey, TimeKeyStart, TimeKeyEnd, montant from FactPipe
UNION ALL
select distinct ‘Cloturé’ as DateTypeKey , TimeKeyEnd as TimeKey, TimeKeyStart, TimeKeyEnd,montant from FactPipe
) T
Imaginons que cette requete soit sauvegardée entant que vue que l’on va appeler viewPipe
Si, en SQL je veux savoir le montant total des devis ouvert jusqu’au 1er janvier 2011, je dois faire cette requête:

select sum(montant) from viewPipe where TimeKey <= '2011/01/01' and DateTypeKey = 'Ouvert'

De même, je veux savoir la somme des devis clôturés jusqu’au 1er janvier 2011, la requête est sensiblement la même :

select sum(montant) from viewPipe where TimeKey <= '2011/01/01' and DateTypeKey = 'Cloturé'

Côté MDX- Mondrian, on va donc introduire une nouvelle dimension que je vais appeler [DateType] qui va permettre de gérer ce fameux status ouvert/clôturé
La particularité de cette nouvelle dimension est qu’elle

Lion : Upgrade vs Clean Install

Après deux mois d’utilisation de Lion, en upgrade, je viens de faire une clean install. 

 Pourquoi ?

Simple, le système me paraissait assez instable, et surtout lent par moment, voir extrêmement lent surtout au reboot environ 56s de boot. 

Pourquoi, pas avant ?

J’ai opté pour la facilité, en effet, l’upgrade est d’une simplicité et surtout vraiment rapide. 
De plus, j’avais un peu peur quand à la récupération de mes données, possédant une bibliothèque photo d’environ 90 Go, vous comprendrez ma crainte, mais bon time machine est là. 
Comment procéder ? 
D’abord, je conseille à tout le monde de se faire un clé USB en suivant le tutoriel de l’outil Lion Disk Maker : https://blog.gete.net/lion-diskmaker/.
Cet outil est très bien fait et permet de préparer la réinstallation de manière plus efficace que la clé de récupération Apple.
Une fois, la clé prête : 
  1. Une vérification du disque dur avec « Utilitaire de disque »
  2. Backup avec Time Machine sur un disque vierge (conseil la backup courante suffit)
  3. Redémarrage de l’ordinateur en utilisant la touche Alt afin de pouvoir choisir la clé USB qui doit évidement être inséré dans un port USB
  4. Choisir la clé pour le redémarrage 

Vous allez alors arriver sur l’écran suivant : 
Il va alors dans le but d’une installation propre falloir suivre les étapes suivantes : 
  1. Aller dans l’utilitaire de disque et effacer la partition principale, généralement « Macintosh HD »
  2. Surtout choisir en type fichier celui proposé : « MacOS etendu (journalisé) » 
  3. Une fois l’opération effectuée – fermer l’Utilitaire avec la croix rouge vous revenez alors sur l’écran ci-dessus
  4. A partir de là lancer l’installation en utilisant « Réinstaller Mac OS X »
  5. Suivez les instructions 
Pour la récupération des données, personnellement, j’ai utilisé Time Machine mais pas l’Utilitaire de migration.
J’ai raccordé le disque utilisé pour ma sauvegarde précédemment et je lui ai dit que c’était un disque time machine, j’ai alors arrêté la première sauvegarde et je suis entré dans Time Machine pour ne récupérer que mes fichiers de données et non les paramètres.
Résultat visible : 
  • Boot plus rapide 40s vs 56s (16s c’est toujours bon à prendre)
  • Fermeture plus rapide : 5s vs 15s
  • Application plus fluide surtout visible avec iTunes et iPhoto dont la bibliothèque pèse plus de 90Go.
  • Lancement des applications presque immédiatement.
Bref, aucun regret, si ce n’est un peu de temps, bien que l’ordinateur a travaillé tout seul la plupart du temps, début de la sauvegarde 9:30 fin vers 13:00.
Début de l’installation 13:15 fin vers 13:30
Début de la restauration incluant l’installation des mises à jour de l’OS 13:45 fin vers 16:30.
Il faut là l’admettre quelque soit l’OS une clean install prend du temps surtout à cause des opérations de sauvegarde et de restauration.