\documentclass[french]{article}

\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{a4}
\usepackage{times}
\usepackage{graphics}
\usepackage[dvips]{graphicx}

\title{\Huge Utilitaires pour modéliser des bases de données en XML}
\author{{\Large\bf PimenTech}\\
  {\tt http://www.pimentech.net}\\
  }

\begin{document}

\maketitle

\section{Introduction}

Afin de gagner un peu de temps et d'uniformiser les modèles de nos bases de données, nous avons développé 2 utilitaires
nous permettant de créer nos bases de données en XML (PGML). Le PGML est grossièrement l'équivalent d'un modèle EER 
(Extended Entity Relationship) qui peut d'ailleurs être généré en dot et visualisable grâce à Graphviz\footnote{http://www.research.att.com/sw/tools/graphviz/download.html}.

\section{Syntaxe du pgml}

Nous présentons ici brièvement la syntaxe utilisée pour construire le ``pgml'' notre utilisation du modèle EER (Extended Entity Relationship)
\subsection{Entité}

Dans notre cas, une entité (entity) représente une table dotée d'attributs. Par exemple :
\begin{verbatim}
  <table name='book'>
    <attribute name='title' type='text'/>
    <attribute name='author' type='text'/>
  </table>
\end{verbatim}

\subsection{Relation} 

Une relation (relationship) est utilisée pour relier des tables entre elles. 
Les relations sont dotées de {\bf participations}, qui définissent la nature du lien entre table et relation
\begin{itemize}
	\item la nature de leurs inter-connections
	\item la façon dont elles sont connectées
\end{itemize}

On peut voir sur le pgml ci dessous que chaque tag {\em participation} est dotée d'un {\em type} représenté par un triplet :

$$type = (nature\_participation, cardinalite, localisation)$$
\begin{itemize}
	\item[\bf Nature participation] :
	\begin{itemize}
		\item[0] - Partielle 
		\item[1] - Totale (obligatoire)
	\end{itemize}
	\item[\bf Cardinalité] : 
	\begin{itemize}
		\item[1] - Une
		\item[n] - Plus d'une
	\end{itemize}
	\item[\bf Localisation] :
	\begin{itemize}
		\item[1] - La référence sera placée de ce coté
		\item[0] - Localisation de la référence indéfinie
	\end{itemize}
\end{itemize}





\section{pgml2dot}

Afin d'illustrer l'utilisation de nos outils nous partirons d'un petit modèle de gestion de bibliothèques {\tt biblio.pgml}~:

\begin{verbatim}
<?xml version='1.0' encoding='ISO-8859-1' standalone="no" ?>
<!DOCTYPE template SYSTEM "/usr/share/doc/pimentech-dbutils/
pgml_2.0.dtd">

<schema>

  <table name='people'>
    <attribute name='name' type='text'/>
  </table>

  <table name='author'/>

  <table name='user' isa='people'>
    <attribute name='expiration' type='date' default='now'/>
  </table>

  <table name='manager' isa='people'>
    <attribute name='password' type='text'/>
  </table>

  <table name='book'>
    <attribute name='title' type='text'/>
    <attribute name='author' type='text'/>
  </table>

  <relation name='rent'>
    <attribute name='date' type='date' default='now'/>
    <participation table='book' type='0,1,1'/>
    <participation table='user' type='0,n,0'/>
  </relation>

  <relation name='write'>
    <participation table='book' type='0,n,0'/>
    <participation table='author' type='0,n,0'/>
  </relation>

</schema>
\end{verbatim}




Nous voyons sur le schéma \ref{biblio_dot} que {\tt pgml2dot} sans options ne fait que dessiner le modèle EER
correspondant, cependant sur le schéma \ref{sbiblio_dot} nous voyons le schéma après transformation par notre outil.
En effet, la relation {\tt write} ne peut être réalisé par une simple référence puisqu'un seul auteur peut écrire 
plusieurs livres et de même un livre peut être écrit par plusieurs auteurs. Ainsi notre outil génère la table nécessaire
à cet effet. Cette table porte le nom de la relation et un attribut d'héritage peut être ajouté comme pour la description
des tables ({\tt <relation name='write' isa='object'>...}). 
La relation {\tt rent} elle est des plus classique et la référence est mise du coté de la table {\tt book}
comme indiqué par le troisième élément du type de participation. 
Toute relation a, en effet, un type qui correspond pour les deux premiers éléments aux arguments de cardinalité 
du schéma EER et un troisième qui lui indique si on veut qu'une référence soit hébergé par la table désigné dans la 
participation. Nous voyons également les références calculés par notre outil.

\begin{figure}[htbp]
	\begin{center}
    \includegraphics[width=17cm,angle=270]{biblio}
    \caption{\em Schéma rendu par pgml2dot -f biblio.pgml -o biblio.dot}
    \label{biblio_dot}
	\end{center}
\end{figure}

\begin{figure}[htbp]
	\begin{center}
    \includegraphics[width=14cm,angle=270]{sbiblio}
    \caption{\em Schéma rendu par pgml2dot -s -f biblio.pgml -o sbiblio.dot}
    \label{sbiblio_dot}
	\end{center}
\end{figure}




\section{pgml2sql}

Le SQL peut être généré de différentes façon suivant les options passées à {\tt pgml2sql}. Voici d'abord la version la plus simple
qui n'utilise pas l'héritage PostgreSql et génère un identifiant par table~:

\begin{verbatim}
CREATE TABLE people (
        id_people SERIAL PRIMARY KEY,
        name text
);
CREATE TABLE author (
        id_author SERIAL PRIMARY KEY,
        ref_people int4
);
CREATE TABLE user (
        id_user SERIAL PRIMARY KEY,
        ref_people int4,
        expiration date DEFAULT 'now'
);
CREATE TABLE book (
        id_book SERIAL PRIMARY KEY,
        title text,
        author text,
        ref_user int4,
        date date DEFAULT 'now'
);
CREATE TABLE manager (
        id_manager SERIAL PRIMARY KEY,
        password text,
        ref_people int4
);
CREATE TABLE write (
        id_write SERIAL PRIMARY KEY,
        ref_book int4,
        ref_author int4
);
\end{verbatim}

Nous lui préférons cependant celui généré avec~:
\begin{verbatim}
ramon@cumin:~$ pgml2sql.py -f biblio.pgml -o biblio.sql -u 
-i "uid SERIAL PRIMARY KEY" -r '0' -x
ramon@cumin:~$
\end{verbatim}
qui génère également les indexes et utilise l'héritage PostgreSql ainsi qu'un identifiant commun à toutes les tables.

\begin{verbatim}
CREATE TABLE people (
        uid SERIAL PRIMARY KEY,
        name text
);
create index idx_people_uid on people (uid);
CREATE TABLE author (

) inherits (people);
create index idx_author_uid on author (uid);
CREATE TABLE user (
        expiration date DEFAULT 'now'
) inherits (people);
create index idx_user_uid on user (uid);
CREATE TABLE book (
        uid SERIAL PRIMARY KEY,
        title text,
        author text,
        ref_user int4 DEFAULT '0',
        date date DEFAULT 'now'
);
create index idx_book_uid on book (uid);
create index idx_book_ref_user on book (ref_user);
CREATE TABLE manager (
        password text
) inherits (people);
create index idx_manager_uid on manager (uid);
CREATE TABLE write (
        uid SERIAL PRIMARY KEY,
        ref_book int4 DEFAULT '0',
        ref_author int4 DEFAULT '0'
);
create index idx_write_uid on write (uid);
create index idx_write_ref_book on write (ref_book);
create index idx_write_ref_author on write (ref_author);
\end{verbatim}

Il est également à noter qu'une option existe pour générer des contraintes.

\section{les nouveautées}

\subsection{les multi indexes:}

\begin{verbatim}
	<table name="employe" isa="personne_physique">
	...
	..
	.
	  <multi-index names="nom, prenom" constraints="unique"/>
	</table>
\end{verbatim}

qui nous donnera

\begin{verbatim}
create unique index employe_nom_prenom_key on employe (nom, prenom);
\end{verbatim}

ou encore :

\begin{verbatim}
	<relation name="travaille_pour" isa="object" constraints="fin is null">
	  <attribute name="debut" type="date" default="now()"/>
	  <attribute name="fin" type="date"/>	
	  <participation type="0,n,0" table="personne_physique"/>
	  <participation type="0,n,0" table="societe"/>
	  <participation type="0,n,0" table="fonction"/>
	</relation>
\end{verbatim}

nous donnera

\begin{verbatim}
create unique index idx_ne_physique_ref_societe_key on travaille_pour \
(ref_fonction,ref_personne_physique,ref_societe) where fin is null;
\end{verbatim}

\subsection{django}

\begin{verbatim}
ramon@host:~$ pgml2django.py -f ~/src/dbutils/src/xml/biblio.pgml  
from django.db import models

class People(models.Model):
        id = models.AutoField('ID', primary_key=True)
        name = models.TextField()

        class Admin:
                pass
class Author(models.Model):
        id = models.AutoField('ID', primary_key=True)
        name = models.TextField()

        class Admin:
                pass
class User(models.Model):
        id = models.AutoField('ID', primary_key=True)
        name = models.TextField()
        expiration = models.DateField()

        class Admin:
                pass
class Book(models.Model):
        id = models.AutoField('ID', primary_key=True)
        date = models.DateField()
        title = models.TextField()
        user = models.ForeignKey(User)

        class Admin:
                pass
class Write(models.Model):
        id = models.AutoField('ID', primary_key=True)
        author = models.ForeignKey(Author)
        book = models.ForeignKey(Book)

        class Admin:
                pass
class Manager(models.Model):
        id = models.AutoField('ID', primary_key=True)
        name = models.TextField()
        password = models.TextField()

        class Admin:
                pass
\end{verbatim}

des options permettent de changer le style du rendu de pgml2sql afin de coller à django~:

\begin{verbatim}
ramon@host:~$ pgml2sql.py -f ~/src/dbutils/src/xml/biblio.pgml -s -n biblio -x -u
CREATE TABLE biblio_people (
        id SERIAL PRIMARY KEY,
        name text
);
create unique index idx_biblio_people_id on biblio_people (id);
CREATE TABLE biblio_manager (
        password text
) inherits (biblio_people);
create unique index idx_biblio_manager_id on biblio_manager (id);
CREATE TABLE biblio_author (

) inherits (biblio_people);
create unique index idx_biblio_author_id on biblio_author (id);
CREATE TABLE biblio_user (
        expiration date DEFAULT now
) inherits (biblio_people);
create unique index idx_biblio_user_id on biblio_user (id);
CREATE TABLE biblio_book (
        id SERIAL PRIMARY KEY,
        date date DEFAULT now,
        title text,
        user_id int4
);
create unique index idx_biblio_book_id on biblio_book (id);
create index idx_biblio_book_user_id on biblio_book (user_id);
CREATE TABLE biblio_write (
        id SERIAL PRIMARY KEY,
        author_id int4,
        book_id int4
);
create unique index idx_biblio_write_id on biblio_write (id);
create index idx_biblio_write_author_id on biblio_write (author_id);
create index idx_biblio_write_book_id on biblio_write (book_id);
create unique index idx_write_author_id_book_id_key on biblio_write \
(author_id,book_id);
\end{verbatim}

de plus si nous changeons le pgml avec :

\begin{verbatim}
<schema>

  <table name='people'>
    <attribute name='name' type='text' display='true' length='20'/>
  </table>

   ...
\end{verbatim}

nous obtenons :

\begin{verbatim}
class People(models.Model):
        id = models.AutoField('ID', primary_key=True)
        name = models.CharField(maxlength=20)

        class Admin:
                pass
        def __str__(self):
                return '%s' % (self.name)
\end{verbatim}

\section{qmlserv}
Qmlserv est un middleware xml permettant d'accéder à une base de données PostgreSQL. 
Qmlserv peut fonctionner en mode chiffré ou non. 
Il gère autant de clés que l'on veut selon les clients qui se connectent. Qmlserv utilise Pimencrypto.py
Qmlclient illustre la façon dont on se connecte à qmlserv.
Daemon.py permet de lancer qmlserv en mode daemon et ainsi de le lancer au démarrage de la machine.

\subsection{quelques requètes...}

\begin{verbatim}

user mdm
password xxx
database mdm
host localhost
 
<sequence>
    <transaction>
      <select table='reseau'>
        <attribute name='code' op='equal' value='202'/>
      </select>
      <select table='agence' default-op='view'>
        <attribute name='date_modification' op='greater' value='01/04/2003'/>
      </select>
    </transaction>
</sequence>

getselect 

<sequence>
    <transaction>  

      <select table='ville'>
        <attribute name='nom'>Paris</attribute>
        <attribute name='code_postal'>75020</attribute>
      </select>

      <update-or-insert table='appartement'>
        <attribute name='euid' op='equal'>2222</attribute>
        <attribute name='src_modification'>john</attribute>
      </update-or-insert>
        
    </transaction>
</sequence>

\end{verbatim}

\end{document}

