Vous êtes sur la page 1sur 18

LANGAGES DE MANIPULATION D'OBJETS

1 Introduction
Pour les bases de données, quelque soit leur modèle, il existe trois types de langages de
manipulation de données (LMD) possibles: navigationnel, déclaratif et graphique.

• Langages navigationnels
Une interface navigationnelle d'un SGBD est constituée d'un ensemble d'instructions élémentaires
qui permettent à l'utilisateur de parcourir la base pas à pas: chaque instruction fournit en résultat à
l'utilisateur un objet unique (o) et positionne un pointeur système sur cet objet, permettant ainsi à
l'instruction suivante de chercher l'objet suivant de o ou l'objet (un des objets) lié à o selon tel lien.
Pour poser une requête, l'utilisateur écrit un programme à l'aide d'un langage de programmation et
des instructions de l'interface du SGBD. Les systèmes de fichiers et les SGBD réseaux et
hiérarchiques offrent des interfaces de type navigationnel.

Les SGBDO offrent tous une interface procédurale, constituée d'un langage de programmation (qui
en général est orienté-objets), des méthodes standard des classes prédéfinies de la racine de la
hiérarchie de généralisation, et des méthodes des classes définies dans le schéma de la base. Le jeu
de classes et de méthodes prédéfinies varie beaucoup d'un système à l'autre. Il contient au minimum
des méthodes permettant de naviguer dans la base d'objets en suivant les liens de composition.

Avantages des interfaces navigationnelles: leur puissance; les problèmes d'incompatibilité entre le
langage de programmation et l'interface du SGBDO sont minimisés.
Inconvénient : l'utilisateur doit écrire des programmes ... efficaces, ce qui est beaucoup plus long
qu'écrire des requêtes dans un langage déclaratif.

• Langages déclaratifs
Dans le cas d'un langage déclaratif, l'utilisateur écrit des requêtes qui spécifient uniquement ce qu'il
veut en résultat et non comment y accéder. Le résultat est un ensemble d'objets: l'ensemble des
objets qui satisfont la requête. SQL, QUEL sont des exemples de langages déclaratifs pour les
SGBD relationnels.
Avantage des langages déclaratifs: rapidité pour écrire des requêtes, l'optimisation est effectuée
par le SGBD.
Il existe encore peu de langages déclaratifs complets et formellement définis pour les SGBDO,
comme par exemple OQL proposé par ODMG et SQL3 proposé par l'ISO. Deux propositions
s'affrontent: OQL d'ODMG qui est issu du LMD de O2 et qui n'est pas compatible avec SQL, et
SQL3 qui est une vraie extension de SQL. En effet, pour passer d'un SQL (ou QUEL) relationnel à
un SQL orienté-objets (que nous appelerons SQLOO par la suite), les problèmes sont nombreux,
dus aux nouveaux concepts des modèles orenté-objets (OO). Par exemple, comment manipuler des
attributs complexes et multivalués à plusieurs niveaux, les liens de composition, les méthodes ?...
Ces problèmes et l'étude de leurs solutions font l'objet de ce chapitre.

1
• Langages graphiques ou visuels
Les SQLOO sont compliqués du fait que le modèle OO est complexe, et les utilisateurs ont du mal
à les maîtriser. Il faudra offrir aux utilisateurs des aides pour écrire leurs requêtes, tels des éditeurs
syntaxiques, ou mieux des langages visuels qui déchargent l'utilisateur du besoin de maîtriser un
langage. L'ancêtre des langages visuels est QBE en relationnel. L'idée de base de QBE est que
l'utilisateur "dessine" un exemple du résultat qu'il veut obtenir. Des valeurs exemples sont
employées pour montrer les liens entre relations (jointures).

Pour les langages visuels, le modèle OO a un avantage important sur le relationnel, car les liens
(liens de composition et de généralisation) existent dans le modèle et sont représentés
graphiquement dans les diagrammes des schémas.
Employer un langage visuel consiste à:
1/ désigner sur le diagramme (grâce à la souris) les types d'objets concernés et les liens à suivre,
2/ préciser les prédicats,
3/ désigner quels sont les types d'objets résultats.
Il existe deux types de langages visuels:
- langage visuel navigationnel : "browser", appelé parcoureur en français,
- langage visuel déclaratif: langage visuel de requêtes.

Avantage de ces langages visuels: l'utilisateur n'a plus à apprendre un langage. Il peut se consacrer
entièrement aux problèmes de son application.

• Langages de manipulation des données pour bases de données OO


Tout LMD OO quelque soit son type doit prendre en compte les nouveaux concepts des modèles de
base de données OO:
• encapsulation
• méthodes
• objets, valeurs, oids: quel est le type du résultat d'une requête?
• structure complexe des objets : attributs complexes, multivalués
• liens de composition: lors des manipulations, un objet comprend-il ses objets composants ?
• hiérarchie de généralisation: une requête doit-elle manipuler uniquement les objets propres à sa
classe ou aussi ceux de ses sous-classes?
• oids et plusieurs égalités: faut-il une nouvelle notion de "doubles", ce qui affecte les opérateurs
ensemblistes (union, différence et intersection) et la projection.
Ces différents points sont traités par la suite.

2 Méthodes et encapsulation
Les SGBD classiques ont pour principe d'offrir à tous un libre accès à toutes les données. A
l'inverse, l'approche OO encapsule les données par des méthodes afin de rendre les programmes
utilisateurs indépendants des choix d'implémentation des objets. Les LMD OO de type déclaratif
suivent généralement l'approche des SGBD classiques et permettent l'accès direct aux données, ne
respectant pas l'encapsulation. Pour les LMD interactifs où les requêtes sont éphémères, ce choix se
justifie puisqu'il n'y a pas lieu de rendre indépendantes des requêtes qui ne sont pas conservées. Par
exemple dans le SGBD O2, l'encapsulation n'est pas respectée dans le mode interactif (mode
"query"), mais elle l'est dans le mode programmation.
2
Les méthodes de type fonction qui fournissent en résultat une valeur peuvent être utilisées dans les
requêtes partout où peut être cité un attribut ou une valeur. Par exemple, les deux requêtes:
Select p•age From p in Personne Where p•nom = "Dupont"
Select p•nom From p in Personne Where p•age <18
sont valables que age soit un attribut ou une fonction. Avoir la même syntaxe pour l'emploi des
attributs et des méthodes de type fonction est important. Cela permet de changer l'implantation des
attributs et fonctions sans affecter les requêtes et programmes utilisateurs existants. Par exemple,
l'attribut age peut être remplacé par un attribut date-de-naissance et par une méthode age, et vice-
versa.

Mais l'emploi de méthodes dans les requêtes pose deux problèmes:


- certaines méthodes peuvent avoir des effets de bord. Pour certaines requêtes on ne peut plus
définir exactement leur résultat, alors que c'est une caractéristique fondamentale des LMD
relationnels;
- on ne sait pas encore optimiser des requêtes comportant des méthodes.

3 Quel est le type du résultat d'une requête?


En relationnel il n'y a que deux concepts: la relation et l'attribut. Le résultat d'une requête
quelconque est toujours une nouvelle relation (avec ses attributs). Les LMDs relationnels sont donc
fermés, ce qui permet de réutiliser le résultat d'une requête dans une autre requête (expressions
d'algèbre), d'utiliser le LMD pour créer des "instantanés" (snapshot) ou des vues. C'est une
propriété très importante.

En orienté objets il y a plus de concepts: objets, valeurs, oids, méthodes. Il faut choisir entre eux,
celui (ceux) qui sera le type du résultat: objets, valeur, oids ? Les requêtes portent sur des
collections d'objets de la base de données. Il faudrait donc, pour la fermeture du langage, avoir pour
résultat des collections d'objets (avec oid, valeur et méthodes associées). Ces objets doivent être,
comme les objets de la base, liés à d'autres objets par les graphes de composition et de
généralisation.

Soit, par exemple, la requête suivante (se reporter au schéma de la base FormaPerm en annexe):
Cbd: = sélection [nomC = "BD"] Cours
Si les objets du résultat (les cours de BD), contrairement aux cours de la base, ne sont pas composés
d'enseignants et d'étudiants, on ne peut pas se resservir de Cbd pour continuer une autre requête, par
exemple: chercher les professeurs qui donnent des cours Cbd (i.e. des cours de BD).

Le choix pour le résultat des requêtes, des collections d'objets est simple dans son principe, mais sa
mise en oeuvre est compliquée (voir § 6.2). Ce qui fait que peu de SGBDO ont actuellement une
solution complète.
En Orion le résultat est une collection d'objets ou une collection de tuples d'oids. En O2 le résultat
est une collection d'objets de la base ou une collection de valeurs complexes.

3
4 Structure complexe des objets
Le problème principal est comment manipuler les attributs complexes et multivalués à un ou
plusieurs niveaux. Il y a eu de nombreuses recherches: sur les modèles relationnels en non première
forme normale (NF2) et sur les modèles d'objets complexes. Des modèles ont été proposés avec des
algèbres et des calculs associés.

Exemple: soit le type d'objet complexe suivant:

Personne

nom prénoms enfants date adr

j m a n° rue ville codepostal


prénoms dateN sexe vaccins

j m a type rappels

j m a

Figure 1: type d'objet complexe Personne

Exemple de représentation d'une occurrence d'objet complexe Personne (les attributs date et adr ont
été omis). L'étoile (*) dans l'entête du tableau indique un attribut multivalué.

nom prénoms* enfants*


prénoms* dateN sexe vaccins*
j m a type rappels*
j m a
Dupont Alfred Annie 1 2 80 F polio 1 6 80
Jean Marinette 1 7 80
7 7 81
coqueluche 10 5 80
22 6 80
Marc 3 5 84 M polio 5 10 84
André 27 11 84

Tableau 1: représentation tabulaire d'un objet complexe

4.1 Comment atteindre les attributs composants du i è m e niveau ?


Solution 1:
- une notation pointée pour descendre les niveaux des attributs complexes, par exemple:
personne.enfants.prénoms
- pour chaque attribut multivalué une variable avec un quantificateur existentiel ou universel (une
alternative moins puissante est l'emploi des opérateurs ensemblistes (∈ , ⊆ , = )).

Exemple: Personnes qui ont transmis leurs prénoms à leurs enfants.

4
Cette requête est ambiguë: les personnes qui ont transmis un (ou tous ?) de leurs prénoms à un (ou
tous ?) de leurs enfants. La requête suivante donne les personnes qui ont transmis au moins un de
leurs prénoms à au moins un de leurs enfants.
En algèbre OO:
sélection [∃prénoms (∃enfants (∃enfants•prénoms (prénoms = enfants•prénoms)))] Personne
En SQL de O2:
Select p From p in Personne
Where exists p1 in p•prénoms: exists e in p•enfant: exists p2 in e•prénoms: p1 = p2

Solution 2: Considérer les attributs complexes et/ou multivalués comme des types d'objets à part
entière, et écrire des expressions emboîtées: sur ces attributs complexes et multivalués on réutilise
les mêmes opérateurs que pour les types d'objets.

Exemple en algèbre OO: Personnes qui ont au moins une fille


Solution 1: sélection [∃ enfants (enfants•sexe = "F")] Personne
Solution 2: sélection [sélection (sexe = "F") enfants ≠ Ø] Personne

Même chose pour les autres opérateurs, par exemple la projection:


Pour chaque personne donner son nom, ses prénoms et les prénoms de ses enfants
Solution 1: projection [nom, prénoms, enfants•prénoms]Personne
Solution 2: projection [nom, prénoms, projection [prénoms] enfants]Personne
Ce qui fournit le résultat suivant:

Résultat

nom prénoms enfants

prénoms

4.2 Restructurer les objets ?


Dans le résultat de l'exemple précédent, l'attribut enfants•prénoms est un attribut multivalué de
multivalué: sa valeur est un ensemble d'ensembles. Ce qui est justifié puisque les prénoms sont
regroupés enfant par enfant. Mais pour certaines requêtes, ce n'est pas le résultat voulu. Par
exemple, pour chaque personne, on veut son nom et la liste (sans double) des types de vaccins
qu'elle a fait faire à ses enfants. La requête algébrique:
projection [nom, enfants•vaccins•type] Personne
fournira aussi un ensemble d'ensembles pour les types de vaccin. Mais ici, il faudrait pouvoir
"aplatir" cet ensemble d'ensembles et y supprimer les doubles.

Il y a deux types de restructuration: avec ou sans perte de sémantique. Par exemple dans la figure 1,
supprimer le noeud adr (n°, rue, ville et codepostal deviennent attributs directs de Personne), ne
change rien à la sémantique des objets Personne. Par contre, supprimer le noeud enfants (prénoms,
dateN, sexe et vaccins deviennent attributs directs de Personne) change la sémantique des objets. Si
l'on ne veut pas perdre d'information (i.e. le fait que tel ensemble de prénoms, telle dateN, tel sexe
et tels vaccins représentent le même enfant), il faut multiplier les occurrences du résultat: créer un
objet résultat par personne et par enfant). Si l'on veut ensuite revenir aux objets initiaux (les

5
personnes) il faut regrouper les nouvelles occurrences, ce qui ne peut se faire que s'il existe un (des)
attribut(s) identifiant de Personne. S'il n'en existe pas la sémantique initiale est perdue: il y a perte
de sémantique.
Plus généralement, l'utilisateur peut vouloir, pour les besoins de son application, changer la
structure d'un objet, créer de nouvelles structures. Afin de permettre de structurer les résultats
comme le veut l'utilisateur des opérateurs ont été proposés pour effectuer ces
regroupements/dégroupements d'attributs.

Les deux opérateurs les plus fréquents sont Nest et Unnest. Nest crée un attribut complexe et
multivalué en regroupant plusieurs attributs. Il permet de passer d'une structure en première forme
normale (1NF) à une structure en NF2, ou de complexifier plus une structure déjà en NF2.

Définition :
Soit S une structure de type tuple (type d'objet complexe ou attribut complexe), d'attributs
composants A1, A2, ... Ap, alors l'opération:
nest [nom: A1, A2, ... Ai] S avec i<p
crée un nouvel attribut complexe multivalué de nom "nom", sous S, et d'attributs A1 ... Ai.
Les attributs Ai+1 ... A p deviennent la "clé" de S selon laquelle sont regroupées les valeurs de
A1 ... Ai.

Unnest effectue l'opération "inverse". Unnest supprime un attribut (éventuellement complexe)


multivalué en multipliant les occurrences du noeud supérieur. Unnest permet de normaliser (en
1NF) un objet de structure complexe.

Exemple: soit le type d'objet complexe Personne du tableau 1 sans les attributs date, adr et vaccins.
L'unnest de tous les attributs multivalués sera fait par l'expression suivante:
Personne1 := unnest[prénoms](unnest[enfants](unnest[enfants.prénoms]Personne))
Son résultat est donné ci-dessous (l'attribut prénoms de enfants a été renommé en
prénomE).

Personne1:
nom prénoms prénomE j m a sexe
Dupont Jean Annie 1 2 80 F
Dupont Jean Marinette 1 2 80 F
Dupont Alfred Annie 1 2 80 F
Dupont Alfred Marinette 1 2 80 F
Dupont Jean Marc 3 5 84 M
Dupont Jean André 3 5 84 M
Dupont Alfred Marc 3 5 84 M
Dupont Alfred André 3 5 84 M

Pour obtenir à nouveau le résultat initial, il faut regrouper les attributs de la façon suivante:
nest [enfants•prénoms:enfants•prénomE] nest [enfants: prénomE, j, m, a, sexe]
(nest [prénoms: prénoms] Personne1)

Attention:
Nest suivi de Unnest = identité

6
Unnest suivi de Nest ≠ identité
Par exemple, s'il existait deux objets complexes Personne de même nom mais de prénoms et
d'enfants différents, on ne retrouverait qu'un seul objet après le "renestage".

Exemple: O2 propose deux opérations, flatten et group, qui sont proches de unnest et nest.
flatten <collection de collections>
L'instruction flatten ne travaille pas sur un attribut d'un objet structuré comme nest mais sur une
collection de collections, qu'elle "aplatit" en supprimant un niveau. Le résultat est une collection à
un seul niveau.
group variable in <collection> by variable.attribut
De même l'instruction group travaille sur une collection, et non pas sur des attributs à un niveau
quelconque d'un objet structuré. L'instruction group regroupe les éléments d'une collection selon les
valeurs prises par un attribut.

4.3 Comment structurer le résultat des opérations (produit et


jointure) qui agrègent plusieurs objets?
En relationnel, le produit (ou la jointure) de deux relations, R1xR2, crée une nouvelle relation de
schéma: celui de R1 plus celui de R2, et dont les tuples sont la concaténation d'un tuple de R1 et
d'un tuple de R2.
En objets complexes deux problèmes se posent:
- A quel niveau va-t-on faire les produits et jointures: au niveau des objets ou au niveau d'un attribut
composant quelconque ?
- Va-t-on faire un produit (jointure) plat ou emboîté ?

• A quel niveau effectuer l'opération ?


Exemple: on voudrait, dans le type d'objets complexes Personne de la figure 1, rajouter pour les
vaccins des enfants des renseignements sur le vaccin qui sont dans un autre type d'objet Vaccin.

Vaccin

type durée contreindications

Pour faire ce type d'opération, des algèbres emboîtées avec produit et jointure à tout niveau ont été
proposées. L'exemple précédent s'écrirait:
projection [nom, prénoms, projection [prénoms, vaccins jointure Vaccin] enfants] Personne

• Produits et jointures plats ou emboîtés ?


La structure créée par un produit (ou une jointure) doit-elle être plate comme en relationnel
(concaténation de deux occurrences), ou emboîtée (création d'un attribut complexe multivalué
regroupant les occurrences du second opérande) ?

7
Exemple: supposons qu'il y ait dans la base, deux types d'objets, Personne de la figure 1 et
Entreprise décrit ci-dessous:
Entreprise

nomE type adr

rue ville codepostal

Si l'utilisateur demande les personnes avec les entreprises qui sont dans la même ville, veut-il/elle:
- des couples (une personne, une entreprise),
- des objets structurés (une personne, les entreprises de la ville) ?
En général, l'application a besoin d'une structure emboîtée. Pour cela, il faut des opérations de type
jointure et produit avec un objet de tête qui définit les occurrences du résultat et dans lequel sont
regroupés les objets du second opérande.

Définition: La jointure orientée de deux types d'objet, O1*O2, crée un nouveau type d'objet
complexe O, d'attributs: ceux de O1, plus un attribut complexe multivalué de nom "O2" et
d'attributs composants ceux de O2. La population de O est en bijection avec celle de O1. La valeur
des occurrences de O est composée de:
- la valeur de l'occurrence de O1 correspondante
- pour l'attribut complexe "O2": de l'ensemble des valeurs des occurrences de O2 qui satisfont le
prédicat avec l'objet de O1.

attributs de O1 O2

attributs de O2

Exemple: La réponse à la requête : "liste des personnes, avec pour chaque personne la liste des
entreprises de sa ville", sera obtenue par la jointure orientée:
Personne * [adr.ville = adr.ville] Entreprise
Attention: les opérateurs de produit et jointure orientés ne sont pas symétriques.
La jointure orientée:
Entreprise * [adr.ville = adr.ville] Personne
fournirait une liste des entreprises avec pour chacune d'elles les personnes de la ville de
l'entreprise.

5 Liens de composition
Le problème essentiel est ici de savoir si les objets composants font partie de l'objet composite. La
réponse dépend de ce qu'on veut faire de l'objet composite.

5.1 Le résultat est un objet composite


Soit une requête dont le résultat est un objet composite, comme par exemple, sur la base
FormaPerm, la requête: "liste des cours". Le résultat peut être:

8
- soit constitué uniquement des attributs propres de la classe (uniquement les attributs de Cours);
- soit constitué des attributs propres de la classe et récursivement de ceux de ses classes
composantes (les attributs de cours et récursivement ceux de Enseignant, Etudiant, Cours,
…).
Le problème est de savoir où s'arrêter, car le graphe de composition est souvent très dense et
peut être cyclique.
La solution est de fournir en résultat uniquement les attributs propres de la classe (ici les attributs de
Cours). Si l'utilisateur veut aussi les attributs des objets composants, il doit le préciser explicitement
dans sa requête. Par exemple, en SQLOO, la requête "liste des cours":
Select c•All From c in Cours
fournit uniquement les attributs de Cours. La requête "liste des cours avec leurs enseignants"
s'écrirait:
Select c•All, c•prof•All From c in Cours

5.2 Accès aux objets composants


Certaines requêtes ont besoin d'accéder à un objet composite et à ses objets composants, car l'objet
composite et ses objets composants participent tous au résultat et/ou à la condition de la requête. Par
exemple sur la base FormaPerm, les requêtes:
1) enseignants du cours BD
2) étudiants des cours du professeur Duval
Pour la première requête le résultat est un ensemble d'enseignants, et la condition porte sur les cours
de ces enseignants. Pour la seconde requête le résultat est un ensemble d'étudiants, et la condition
porte sur leurs cours et les professeurs de ces cours.

La solution retenue est alors de considérer que les objets composants font partie de l'objet
composite, comme des attributs complexes. On utilise, comme vu ci-dessus pour les objets à
structure complexe, une notation pointée pour descendre dans les attributs complexes, ou pour
passer par un attribut référence, avec des quantificateurs chaque fois que le lien (attribut valeur ou
attribut référence) est multivalué.

Exemple: les requêtes ci-dessus s'écrivent en SQL O2:


1) Select e From e in Enseignant Where exists c in e•cours-assurés: c•nomc = "BD"
2) Select e From e in Etudiant Where exists c in e•cours-suivis: c•prof•nom = "Duval"

6 Hiérarchie de généralisation
La présence de la hiérarchie de généralisation génère deux problèmes:
- Quand une requête cite une classe d'objets, est-ce la population propre (sans celle de ses sous-
classes) ou la population globale (avec les sous classes) qui doit intervenir ?
- Le résultat d'une requête est une classe d'objets. Où la mettre dans la hiérarchie de
généralisation ?

6.1 Population propre ou globale ?


Exemple sur la base FormaPerm:
sélection [adr•ville = "Lausanne"] Personne
Le résultat est-il:

9
1. pris dans la population propre de la classe: uniquement les personnes qui ne sont ni
enseignante ni étudiante et qui habitent à Lausanne ?
2. pris dans la population globale de la classe: toutes les personnes de Lausanne (enseignantes,
étudiantes et autres) ?
Dans ce dernier cas, sous quel format obtient-on ces personnes ?
2.1 sous leur format spécialisé (d'Etudiant, d'Enseignant ou de Personne). On obtient alors en
résultat un ensemble hétérogène. Le résultat constitue un arbre de classes.
2.2 sous leur format de Personne.

Selon les requêtes les utilisateurs peuvent vouloir obtenir l'un ou l'autre de ces résultats. Le système
Orion par exemple, offre les deux possibilités. Il permet à l'utilisateur de préciser explicitement
dans sa requête s'il/elle veut la population propre ou globale. La requête:
Select p From p in Personne Where p.adr.ville="Lausanne"
fournit la population propre de la classe Personne.
La requête:
Select p From p in Personne* Where p.adr.ville="Lausanne"
fournit la population globale; le résultat est une collection d'objets hétérogènes.

6.2 Où placer le résultat d'une requête dans la hiérarchie de


généralisation ?
Dans le cas des SGBDO qui fournissent en résultat une collection d'objets, si l'utilisateur veut
sauvegarder ces objets dans la base (pour en faire une vue ou un instantané), cette collection
d'objets doit devenir une classe d'objets et être insérée dans la hiérarchie de généralisation. Le
problème est: où dans la hiérarchie ? Il y a deux types de solutions:
1. le résultat d'une requête décrit de nouveaux objets. C'est une classe d'objets avec de nouveaux
oids. Elle est placée au sommet de la hiérarchie de généralisation;
2. le résultat d'une requête décrit un nouveau point de vue sur des objets qui existaient déjà dans
la base. C'est une classe dont les oids existent déjà: c'est une sous-classe (ou une classe
dérivée) d'une classe existante de l'application.

• Les langages du premier type sont dits "générateurs d'objets". Les propriétés de la nouvelle classe
sont déduites de celles des opérandes de la requête.
Exemple: pour la requête suivante qui cherche la personne Dupont:
d: = sélection [nom = "Dupont"] Personne
la nouvelle classe d a les mêmes attributs et méthodes que la classe Personne. Cependant l'objet (ou
les objets) de d ne sont pas des objets de la classe Personne. L'objet Dupont de d a un oid différent
de l'objet correspondant, Dupont, dans Personne.

Root Class

Personne d

NP nom … NP nom …
Exemple: Orion

10
Certains langages générateurs d'objets, pour pallier à cet inconvénient de duplication des objets,
créent leurs classes résultat comme des renvois sur la classe opérande. Pour l'exemple précédent, la
classe d ne contiendra qu'un seul attribut: un attribut référence pointant l'objet correspondant de la
classe Personne.
Root Class

Personne d

NP nom … personne

Avantage des langages générateurs d'objets: solution simple à implémenter.


Inconvénients: la duplication d'objets est une solution aux possibilités limitées, notamment pour les
requêtes cycliques. L'indirection est lourde pour les utilisateurs.

• Les langages du second type sont dits "à conservation d'objets". Les propriétés de la classe
résultat sont dérivées de celles des opérandes par le mécanisme d'héritage. Par exemple, pour la
requête précédente, sélection de la (les) personne(s) Dupont, le résultat est une sous-classe de
Personne.

Root Class

Personne

select (Personne)

L'opération de différence crée aussi une sous-classe (du premier opérande). Cependant tous les
opérateurs ne créent pas tous aussi naturellement une sous-classe de l'opérande.

L'opération de projection crée plutôt une surclasse, de même que l'union. Par exemple, la requête
"liste des noms des personnes":
projection [nom] Personne
crée en résultat une classe ayant le même ensemble d'oids que la classe Personne, mais avec moins
d'attributs.

11
Root Class

nom proj[nom](Personne)

Personne

NP …
Quant aux produits et jointures, cela dépend de leur type:
- produits et jointures orientés peuvent créer des sous-classes (couvrantes) de l'opérande
principal;
- produits et jointures plats qui multiplient les objets, créent forcément de nouveaux objets dont
l'identité est différente de celle de tous les objets existants dans la base. Ce dernier type
d'opération ne peut pas faire partie d'un pur langage à conservation d'objets.

Le fait que l'emplacement de la classe résultat dépende de l'opérateur, interdit de traiter de manière
uniforme toutes les requêtes, notamment les expressions comprenant plusieurs opérateurs.
Par exemple, où placer le résultat de la requête suivante qui recherche l'adresse de Dupont:
projection[adr] sélection[nom="Dupont"] Personne
Cette classe résultat a moins d'oids et moins d'attributs que la classe Personne. Ce n'est ni une sur-
classe, ni une sous-classe de Personne:

Root Class

Personne ? proj.select(Personne)

select (Personne)
Solutions:
− Séparer la notion d'héritage de la notion d'inclusion de population (solution qui a été adoptée
dans quelques prototypes tels que COCOON et DUAL)
− Assouplir les règles d'héritage: non toujours automatique
− Avoir un autre type de lien: lien de dérivation.
Solution mixte
Les opérateurs créent des sous-classes de l'opérande, sauf le produit et la jointure plate qui créent
une nouvelle classe sous la racine et génèrent de nouveaux oids.

7 Plusieurs égalités
L'introduction des oids a donné naissance à plusieurs égalités:
- le test d'identité (même oid)
- le test d'égalité de valeur au premier niveau (égalité de surface)
- le test d'égalité de valeur au niveau des feuilles (égalité en profondeur)
Pour les prédicats, les LMDs proposent en général les deux premiers comparateurs.
12
7.1 Impact sur la gestion des doubles
En relationnel, un opérateur "crée" des doubles, c'est la projection. Dans la théorie relationnelle ces
doubles sont aussitôt éliminés, car une relation est un ensemble de tuples. Par contre, en OO on
gère des collections qui permettent en général les doubles (multi-ensemble, liste, tableau,…).

En OO, qu'est-ce qu'un double: deux occurrences de la même classe avec même valeur, ou deux
références au même objet ? Orion, par exemple, a deux mots-clés différents pour permettre à
l'utilisateur de supprimer les doubles d'une collection:
Select UNIQUE p From p in <collection>
qui signifie ne garder qu'une fois chaque objet
Select UNIQUE VALUE p From p in <collection>
qui signifie supprimer les objets qui ont même valeur au premier niveau: n'en garder qu'un (au
hasard).

7.2 Impact sur les opérateurs ensemblistes


Pour pouvoir effectuer l'union, la différence ou l'intersection de deux classes, il faut choisir une
sémantique pour la comparaison des objets des classes: au niveau oid ou au niveau valeur (comme
en relationnel)? Par cohérence avec le modèle, ce sont les oids qui servent pour les comparaisons
des opérateurs ensemblistes. Faire l'union (ou la différence, l'intersection) de deux classes signifie
faire l'union (ou la différence, intersection) de leurs objets. Si le même objet est représenté dans les
deux classes (même oid), il apparaît une fois (et une seule) dans la classe union, il ne fait pas partie
de la classe différence, et il fait partie de la classe intersection.

La comparaison portant sur les oids, les valeurs de deux représentations du même objet dans les
deux classes peuvent être différentes, quelle est alors la valeur de l'objet résultat? Quel est sont
type?

Pour la différence,
C1 différence C2
le résultat est défini comme étant l'ensemble des objets de C1 qui ne sont pas dans C2. Le type du
résultat est donc celui de C1, et les objets ont pour valeur, leur valeur dans C1.

Pour l'union,
C1 union C2
le type résultat doit permettre de décrire les objets provenant de C1 et C2. La solution la plus
fréquente est de créer une sur-classe commune à C1 et C2, ayant pour propriétés celles communes à
C1 et C2. Cela pose le problème des objets de même oid qui ont pour le même attribut (même nom
et même domaine) des valeurs différentes.

Pour l'intersection,
C1 intersection C2
le résultat est une sous-classe commune à C1 et C2. Il faut alors gérer dynamiquement les conflits
d'héritage qui peuvent ainsi avoir été créés.

8. Mises à jour

13
Pour les mises à jour les problèmes sont semblables à ceux rencontrés pour les requêtes
d'interrogation:
- mises à jour d'objets de structure complexe: comment accéder aux attributs composants pour
les modifier ?
- mise à jour d'objet appartenant à une hiérarchie de généralisation: mises à jour induites par les
insertions et suppressions d'objets, migrations d'objets d'une classe à une autre;
- mise à jour d'objets composites ou composants: manipulation des attributs référence en
SQLOO, maintient de l'intégrité référentielle.

8.1 Structure complexe


Pour pouvoir mettre à jour un attribut composant de niveau quelconque, les solutions sont les
mêmes que pour les requêtes (instructions emboîtées ou notation pointée, variables et
quantificateurs). On manipule aussi des constantes complexes.

Exemple format d'instruction de mise à jour d'attribut avec notation pointée et variables implicites:

Update c in nom-classe
[ Where <prédicat sur c> ] /* choix des occurrences c de la classe à mettre à jour */
 < valeur > (si att n monovalué)
< ensemble de valeurs > (si att multivalué) 
 n 
Set att1•att2• ... • attn =  
 add < valeur > (si att n multivalué) 
 delete (si att n multivalué) 

[Where <prédicat sur att1 • ...• attn>] /*choix de la/les valeurs de attn à mettre à jour */

Cette instruction permet de mettre à jour la valeur de l'attribut composant attn.


Si l'attribut attn est monovalué:
Set tt1 • att2 • ...• attn = <valeur> [where < prédicat sur tt1 • att2 • ...• attn-1>]
permet, pour les valeurs de att n-1 qui satisfont le prédicat, de modifier la valeur de attn.
Si l'attribut attn est multivalué:
Set tt1 • att2 • ...• attn = <ensemble de valeurs> [where < prédicat sur tt1 • att2 • ...• attn-1>]
permet, pour les valeurs de attn-1 qui satisfont le prédicat, de modifier l'ensemble de valeurs de
attn.
Set att1 • att2 • ...• attn = delete [where <prédicat sur att1 • att2 • ...• attn>]
permet de supprimer les valeurs de att n qui satisfont le prédicat,
Set tt1 • att2 • ...• attn = add <valeur> [where <prédicat sur tt1 • att2 • ...• attn-1>]
permet d'ajouter une valeur à attn, dans les valeurs de attn-1 qui satisfont le prédicat.

14
Exemple:
Personne

N° nom prénoms enfant

prénom sexe vaccin dateN

type dates j m a

Exemples: ajout d'un enfant à la personne de numéro 136.


Update p in Personne Where N° = 136
Set enfant = add (prénom={Anne, Lucie}, sexe=F, vaccin=Ø, dateN=15.12.93)

Ajout d'un vaccin à l'enfant Anne Lucie de la personne de numéro 136.


Update p in Personne Where N°= 136
Set enfant•vaccin = (type=oreillons, dates={1.3.94}) Where enfant•prénoms ={Anne, Lucie}

8.2 Hiérarchie de généralisation/spécialisation


En présence d'une hiérarchie de généralisation/spécialisation, créer un objet dans une classe peut
avoir deux significations:
- créer un objet qui n'existe pas encore dans la base: et donc créer un oid,
- créer une nouvelle représentation (point de vue) pour un objet qui existait déjà dans la base:
l'oid existe déjà, il est déjà dans une (des) classe(s) avec sa valeur, on veut le mettre dans une
autre classe, par exemple pour le spécialiser.

De même supprimer un objet peut signifier soit supprimer complètement l'objet de la base, soit en
supprimer une représentation (son appartenance à telle classe).

Exemple; soit la hiérarchie de généralisation suivante:

Personne

Etudiant Enseignant

Etudt1 Etudt2 Etudt3

Une même personne, par exemple Annie, peut au cours de sa vie changer plusieurs fois de classe, et
conduire au cycle de vie suivant pour l'objet Annie:

15
Personne
Etudiant
Etudt1
Etudt2
Etudt3
temps
Enseignant

Créer Annie Annie Annie retraite


étudiante passe passe Annie thèse d'Annie
en 1er cycle en 2e cycle en 3e cycle donne des cours d'Annie nettoyage de la base:
et devient
on supprime Annie
enseignante

Il y a donc deux opérations (ou méthodes) distinctes de création:


- créer un objet
o : = nomclasse•newobject (où o est fourni en réponse et est l'oid créé)
- créer une représentation supplémentaire pour un objet o qui existe déja
o•newrepr (nomclasse)
et deux opérations de suppression:
- supprimer complètement un objet
o•deleteobjet
- ôter une représentation d'un objet
o•deleterepr (nomclasse)

Attention: La plupart des SGBO actuels ne permettent pas encore ces changements de classe
(newrepr, deleterepr) car ils peuvent impliquer de changer le format de l'enregistrement décrivant
l'objet et de le changer de place physiquement.

• Mises à jour induites par la hiérarchie de généralisation


La création (d'un objet ou d'une représentation) implique sa création dans toutes les sur-classes (s'il
n'y est pas déjà). La destruction (d'un objet ou d'une représentation) implique sa destruction dans
toutes les sous-classes.

8.3 Liens de composition et intégrité référentielle


L'intégrité référentielle est la propriété qui assure que toute référence (oid) existant dans la base est
valide, i.e. qu'il existe un objet ayant cet oid. Les SGBD devraient toujours assurer ce type
d'intégrité; ce qui n'est pas le cas. Par exemple, la plupart des systèmes relationnels n'ont pas le
concept d'identifiant (ou clé) externe, et donc n'assurent pas l'intégrité référentielle. Par contre, les
SGBDO l'assurent généralement.

Pratiquement pour un SGBDO, cela consiste à vérifier lors des mises à jour de la base que les
attributs référence pointent toujours des objets existants :

16
Lors de l'affectation d'un attribut référence, le mécanisme de typage du système effectuera
automatiquement la vérification que la "valeur" affectée soit bien du bon type, i.e. un oid de la
classe (ou d'une sous-classe) qui est le domaine déclaré pour cet attribut - ou la valeur nulle -.

Lors de la suppression d'un objet composant, le système doit (devrait) rechercher dans la base tous
les attributs référence pointant cet objet, pour les mettre à "nul". La réalisation de cette dernière
fonction est coûteuse. Une solution est que le système conserve en interne les références inverses
(aux objets composites pointant l'objet composant). C'est la solution d'ONTOS. Une alternative est
de ne pas offrir d'instruction de destruction d'objet dans l'interface utilisateur. Un objet est
implicitement détruit quand il n'est plus référencé. C'est la solution d'O2.

• Mises à jour induites par les liens de composition


Dans le cas de références croisées inverses, par exemple pour la base FormaPerm Enseignant•cours-
assurés et Cours•prof, si elles sont connues du SGBDO (déclarées dans le schéma), alors leur
cohérence est automatiquement maintenue par le système. A chaque mise à jour d'un des deux
attributs référence, le SGBDO effectue la mise à jour correspondante de la référence inverse.

Un autre type de mise à jour induite par les liens de composition arrive lors de la destruction d'un
objet composite dont un (des) composant a été déclaré dépendant pour son existence. Par exemple,
la classe composite Immeuble a pour classe dépendante Appartement. Lors de la destruction d'un
objet composite (d'un immeuble), les objets composants dépendants (les appartements de
l'immeuble) sont détruits automatiquement par le SGBDO. Cette destruction induite est récursive.

Le cas inverse est celui de la création d'un objet composite dont un attribut référence est obligatoire
(valeur nulle interdite), par exemple dans la classe Cours de FormaPerm, l'attribut référence prof.
Dans ce cas l'utilisateur ne peut créer un objet composite (un cours) qu'après avoir créé son (ses
objets composants (son prof).

• Manipulation des attributs référence dans les langages déclaratifs


Initialiser ou mettre à jour un attribut référence dans un LMD navigationnel ne pose pas de
problème. Les variables de domaine classe (variable-oid) peuvent être affectées comme toute autre
variable.
Pour les LMD OO déclaratifs, il faut pouvoir sélectionner un oid et l'affecter à un attribut référence.
Par exemple, la mise à jour "le cours BD est assuré par le professeur Annie" s'écrira en SQL
d'Orion:
Update c In Cours Where c•nomC = "BD"
Set c•prof = ( Select e From Enseignant Where e•nom = "Annie" ) ;
Le résultat du Select interne est un oid d'un Enseignant.

9 Conclusion
Ces nouveaux SQLOO ont a leur actif d'être très puissants (en quelques lignes l'utilisateur peut
écrire une requête très complexe) et d'être compatibles (presque complètement) avec les langages
de programmation hôtes. Mais il reste des problèmes ouverts qui sont essentiellement:
- ces langages n'utilisent que partiellement les méthodes. Notamment les méthodes associées au
type résultat sont très rarement définies;

17
- ces langages ne permettent pas toutes les utilisations qui sont possibles en relationnel,
notamment la définition de vues ou la modification de schéma;
- il y a actuellement une forte bataille pour la définition d'un SQLOO standard, et pas encore de
consensus.

18

Vous aimerez peut-être aussi