On Thu, 15 Nov 2001, Julien Escario wrote:
> On m'a dit que Marc ne jurait que par postgre/Perl, j'aimerais savoir pkoi.
Précisons:
quand j'ai fait mes études en informatique, j'ai eu un cours sur les
Systèmes de gestion de base de données (SGBD), assez théorique et assez
barbant je précise. Mais ce cours m'a donné une vue d'ensemble sur la
théorie de la modélisation, sur les divers types de SGBD, comme p.ex. le
cas particulier des SBGD/R (relationels), objets, etc, ainsi que des
caractéristiques d'implantations. On a aussi traité assez en profondeur
(du moins pour un cours général) des problèmes de garanties d'intégrité,
de protocoles à trois phases, etc.
Ensuite je n'ai plus jamais fait de bases de données, pendant 4-5 ans.
En 1998, vu que tout le monde parlait alors d'interfaçage de bases de
données avec WWW, j'ai pris une voie étrange:
- j'ai pris Perl (et C) comme langages
(raison: je connaissais bien C, et Perl de nom.
Perl est un langage UNIX par excellence que j'ai
rencontré déjà il y a de nombreuses années, sans vraiment
utiliser tout son potentiel là. Une des raisons qui m'ont
fait choisir Perl, ce sont les tableaux associatifs,
qui me manquaient depuis que j'avais goûté au langage
expérimental Newton).
- j'ai pris pour Perl: DBI comme interface (pas de mysql_connect() ou
autres bêtises, tout se passe de la même façon pour toutes les bases
de données/systèmes de gestion de table, grâce à une couche
d'abstraction)
- j'ai un peu regardé et à l'époque, la seule base de données libre
ou open source qui supportait au moins certaines caractéristiques
ACID était PostgreSQL.
En 2001, ce double-choix Perl + PostgreSQL est à mon avis pleinement
justifié:
- Perl n'est pas forcément toujours aussi efficace que d'autres langages
(en temps de développement et en temps d'exécution), mais il a l'avantage
de permettre *certaines* vérifications (use strict; -w), et de permettre
un style de programmation sûr. De plus c'est un langage universel, non
confiné au WWW. Son apprentissage permet ensuite de développer sur
plusieurs plateformes (y compris non UNIX), en particulier des scripts
pour l'automatisation de tâches.
- PostgreSQL supporte désormais la totalité des règles ACID et possède une
performance meilleure que MySQL notamment pour les cas complexes, ceux que
j'implémente vu que je designe mes systèmes en fonction de ça.
Rappelons les règles ACID: (j'espère ne pas dire trop de bêtises, le cours
est loin)
Atomicity
Consistency
Isolation
Durability
Je ne parlerai pas des transactions ici, car ce concept est recouvert par
ACID.
Ajoutons que PostgreSQL supporte les triggers et les fonctions. Par
exemple:
CREATE TABLE exercice (id SERIAL NOT NULL, -- interne à la base de données
societe INT4 REFERENCES societe NOT NULL,
debut DATE DEFAULT CURRENT_DATE NOT NULL,
fin DATE NOT NULL,
cloture BOOLEAN DEFAULT 'f' NOT NULL,
devise VARCHAR(3) DEFAULT 'CHF' NOT NULL,
libelle TEXT NOT NULL, -- libellé
UNIQUE(libelle, societe),
UNIQUE(id), PRIMARY KEY(id));
CREATE FUNCTION f_exercice_cloture ()
RETURNS opaque
AS 'BEGIN
IF OLD.cloture THEN
RAISE EXCEPTION ''exercice is CLOTURE, you cannot change it.'';
END IF;
RETURN new;
END;'
LANGUAGE 'plpgsql';
CREATE TRIGGER t_exercice_cloture
BEFORE DELETE OR UPDATE
ON exercice
FOR EACH ROW
EXECUTE PROCEDURE f_exercice_cloture ();
Grâce à ce trigger/cette fonction (qui sont stockées dans la base de
données, ie qui tournent sur le serveur) on peut détecter à temps des bugs
dans les scripts en Perl/PHP/C/lisp/etc qui tenteraient par erreur de
modifier/supprimer un exercice qui serait clôturé.
De plus, grâce aux références, il est impossible (par défaut) de supprimer
une societe encore référencée par un exercice.
Dans cet exemple il n'y a pas de contraintes d'intégrité complexes, mais
en voici un exemple:
CREATE TABLE file (id SERIAL NOT NULL,
creation_time TIMESTAMP
NOT NULL DEFAULT CURRENT_TIMESTAMP,
last_access_time TIMESTAMP, -- read some data
file_name VARCHAR(100) NOT NULL, -- see servers_defs.h
client_name VARCHAR(30) NOT NULL, -- from auth
server_name VARCHAR(30) NOT NULL, -- from auth
complete BOOL NOT NULL DEFAULT 'f',
part_count INT4,
UNIQUE(client_name, server_name, file_name),
UNIQUE(id), PRIMARY KEY(id),
CHECK ((complete AND (part_count IS NOT NULL))
OR (NOT complete)));
Il es