Αντικειμενοστρεφείς βάσεις δεδομένων

Οι αντικειμενοστρεφείς βάσεις δεδομένων είναι συστήματα βάσεων δεδομένων που κρατούν τα δεδομένα τους σαν αντικείμενα, κατά τις αρχές του αντικειμενοστρεφούς προγραμματισμού.

## Βάσεις δεδομένων και αντικειμενοστρεφής προγραμματισμός
Γύρω στα 1986, η προσπάθεια συσχετισμού αντικειμένων και βάσεων δεδομένων, ήταν συναρπαστική. Από την πλευρά των βάσεων δεδομένων υπήρχε η τάση επέκτασης του σχεσιακού μοντέλου, που μόλις πριν από λίγο καιρό είχε καθιερωθεί. Από την πλευρά των γλωσσών προγραμματισμού υπήρχε η τάση πρόσθεσης χαρακτηριστικών όπως διάρκεια στα δεδομένα. Από τη συνάντηση των δύο τάσεων προέκυψε μια ποικιλία απόψεων: κάποιοι πίστευαν ότι ο συνδυασμός χαρακτηριστικών από τις αντικειμενοστρεφείς γλώσσες προγραμματισμού και τις βάσεις δεδομένων θα δημιουργούσε ένα νέο είδος συστημάτων βάσεων δεδομένων. Την ίδια στιγμή, κάποιοι άλλοι πίστευαν ότι, με τη βοήθεια των αντικειμένων, ο κόσμος θα έπρεπε να προσανατολιστεί σε εργαλεία (toolkits) που θα βοηθούσαν τους προγραμματιστές να κατασκευάσουν εξειδικευμένα συστήματα διαχείρισης βάσεων δεδομένων. Στη συνέχεια του κεφαλαίου αυτού, θα παρουσιάσουμε το πώς οι
διαφορετικές αυτές προσεγγίσεις κατέληξαν στη δημιουργία των αντικειμενοστρεφών συστημάτων βάσεων δεδομένων. Προηγουμένως, όμως,θα κάνουμε μια μικρή εισαγωγή στις έννοιες του προσανατολισμού στα αντικείμενα. Προσανατολισμός στ' Αντικείμενα (Object Orientation) σημαίνει μια "μοντελοποίηση του λογισμικού και κάποιες αρχές ανάπτυξης που διευκολύνουν την κατασκευή
σύνθετων συστημάτων από ξεχωριστά συστατικά" [Kh93]. Τι είναι "Αντικείμενο" (Object); "Αντικείμενο είναι μια ξεχωριστή οντότητα, που προσπαθεί να μοντελοποιήσει και να προσεγγίσει όσον το δυνατό καλύτερα, το φυσικό κόσμο." [CK86]. Ένα αντικείμενο μπορεί να διενεργήσει ένα σύνολο δραστηριοτήτων. Το σύνολο, αυτό, των δραστηριοτήτων του, καθορίζει και τη συμπεριφορά του (object's behaviour). Ο ορισμός της συμπεριφοράς ενός αντικειμένου αποτελείται από τρία μέρη:

* τη διαπροσωπεία (interface)
* τον κώδικα (code)
* τα δεδομένα (data)

Η διαπροσωπεία ενός αντικειμένου αποτελείται από ένα σύνολο εντολών που κάθε μία επιτελεί μία συγκεκριμένη εργασία. Ένα αντικείμενο ζητά από ένα άλλο να εκτελέσει μία εντολή στέλνοντάς του ένα μήνυμα. Ο έλεγχος μεταβιβάζεται από το αντικείμενο αποστολέα (sender) στο αντικείμενο παραλήπτη (receiver), μέχρι το δεύτερο να ολοκληρώσει την ζητηθείσα εντολή. Στη συνέχεια, ο έλεγχος επιστρέφει στον αποστολέα. Ένα μήνυμα μπορεί να περιέχει πληροφορία για τον αποστολέα, με τη μορφή ορισμάτων. Το αντικείμενο παραλήπτης, από την πλευρά του, μπορεί να επιστρέψει μια τιμή πίσω στο αιτούν αντικείμενο. Κάθε μήνυμα λαμβάνει ένα όνομα το οποίο ονομάζεται επιλογέας (selector), και είναι το όνομα αυτό που αποστέλλεται στο αντικείμενο παραλήπτη.

Ένα άλλο σύνηθες φαινόμενο είναι το αντικείμενο που λαμβάνει ένα μήνυμα να στέλνει με
τη σειρά του ένα άλλο μήνυμα σε ένα τρίτο αντικείμενο κ.ο.κ..

Ο κώδικας του κάθε μηνύματος εκτελείται κάθε φορά που ένα αντικείμενο λαμβάνει το εν λόγω μήνυμα. Ο κώδικας που σχετίζεται με κάθε μήνυμα ονομάζεται μέθοδος. Όταν ένα αντικείμενο λαμβάνει ένα μήνυμα, καθορίζει ποια μέθοδος πρέπει να εκτελεστεί και της περνάει τον έλεγχο. Ένα αντικείμενο έχει τόσες μεθόδους, όσα και μηνύματα. Εν γένει, το όνομα της μεθόδου είναι το ίδιο με το όνομα του μηνύματος. Τα δεδομένα ενός αντικειμένου χρησιμοποιούνται για να διατηρούν την πληροφορία γύρω από αυτό. Τα αντικείμενα διατηρούν μεταβλητές, οι οποίες υλοποιούν τα δεδομένα και ονομάζονται μεταβλητές στιγμιότυπου (instance variables). Είναι σαφές ότι αυτού του είδους οι μεταβλητές ζουν όσο και το αντικείμενο.

Ένα από τα χαρακτηριστικά του αντικειμενοστρεφούς προγραμματισμού είναι και το γεγονός, ότι ένα αντικείμενο μπορεί να έρθει σε επικοινωνία με ένα άλλο, μόνο μέσω του interface του δεύτερου. Η λογική και τα δεδομένα κάθε αντικειμένου αποκρύπτονται. Το interface ενθυλακώνει τον κώδικα και τα δεδομένα κάθε αντικειμένου, γι' αυτό και το χαρακτηριστικό αυτό, του αντικειμενοστρεφούς προγραμματισμού, ονομάζεται ενθυλάκωση (encapsulation)

Είναι χαρακτηριστικό φαινόμενο, το γεγονός ότι πολλά αντικείμενα επιδεικνύουν την ίδια ακριβώς συμπεριφορά και διαφέρουν μόνο στην τιμή των μεταβλητών στιγμιοτύπου. Για να μην επαναλαμβάνουμε τη συγγραφή του κώδικα για τις μεθόδους, τα δεδομένα και το interface, φροντίζουμε να ομαδοποιήσουμε τα αντικείμενα σε κλάσεις. Κλάση είναι μια ομάδα από αντικείμενα με παρόμοια σημασιολογία και, εν γένει, παρόμοια δομή και λειτουργίες. Είναι χαρακτηριστικό, ότι στον αντικειμενοστρεφή προγραμματισμό, δεν ορίζουμε αντικείμενα,αλλά τις κλάσεις στις οποίες ανήκουν. Ένα στιγμιότυπο (instance) είναι ένα αντικείμενο που ανήκει στην κλάση αυτή, και έχει τα δικά του δεδομένα. Δομούμε τις κλάσεις σε ιεραρχίες κλάσεων, έτσι ώστε να κατασκευαστεί ένα δέντρο από κλάσεις. Κάθε κλάση κληρονομεί από την πατρική της όλα τα χαρακτηριστικά της δεύτερης,στα οποία, αν υπάρχει ανάγκη, προσθέτει και τα ιδιαίτερα δικά της. Το φαινόμενο αυτό ονομάζεται κληρονομικότητα. Με τον τρόπο αυτό, μπορούμε να ομαδοποιούμε αλλά και να εξειδικεύουμε τα αντικείμενα με μια δενδρική δομή εύκολα αντιληπτή σημασιολογικά, η οποία ταυτοχρόνως μας επιτρέπει να εξοικονομούμε σημαντικό τμήμα κώδικα (αφού δε χρειάζεται να ορίσουμε ξανά τις λειτουργίες και τη δομή μιας θυγατρικής κλάσης -αρκεί να έχει περιγραφεί ο πατέρας της).

Τέλος, άλλο ένα χαρακτηριστικό του αντικειμενοστρεφούς προγραμματισμού είναι το γεγονός ότι διαφορετικά αντικείμενα αντιδρούν με διαφορετικό τρόπο στο ίδιο μήνυμα. (Έχουν, δηλαδή, διαφορετική υλοποίηση της μεθόδου για το ίδιο μήνυμα). Το φαινόμενο ονομάζεται πολυμορφισμός (polymorphism). Τα βασικά χαρακτηριστικά του αντικειμενοστρεφή προγραμματισμού, είναι:

* Ένα αντικείμενο αποτελείται από δεδομένα, λογική και το interface που τα ενθυλακώνει και που καθορίζει τη συμπεριφορά του αντικειμένου.
* Τα αντικείμενα επικοινωνούν με μηνύματα.
* Μια μέθοδος είναι η υλοποίηση ενός μηνύματος.
* Αντικείμενα ομοειδή ανήκουν στην ίδια κλάση.
* Ο μόνος τρόπος για να υπάρξει επικοινωνία με ένα αντικείμενο είναι μέσω του interface του.
* Δύο αντικείμενα μπορεί να υλοποιούν το ίδιο μήνυμα μέσω διαφορετικών μεθόδων.

## Βασικές αρχές ενός αντικειμενοστρεφούς μοντέλου δεδομένων
Σύμφωνα με το [Mai89] η έννοια μοντέλο δεδομένων (data model) έχει διττή σημασία:
σημαίνει αφενός ένα συγκεκριμένο σχήμα ή γενικά, περιγραφή των μεταδεδομένων (metadata) σε μια εφαρμογή,
και αφετέρου σημαίνει τον τρόπο με τον οποίο σχήματα ή περιγραφές δεδομένων εκφράζονται
σε ένα σύστημα. Για τη δεύτερη ερμηνεία, προς την οποία και εμείς θα προσανατολιστούμε
στη συνέχεια, υπάρχουν επίσης, διάφορες παραλλαγές -εμείς θα υιοθετήσουμε τον ορισμό που
δίνεται στο [Di93]:

"Ένα μοντέλο δεδομένων είναι ένα σύνολο από λογικά εργαλεία για την περιγραφή της
αναπαράστασης της πληροφορίας σε δεδομένα. Περιλαμβάνει δε, ζητήματα σχετικά με:

* τύπους και δομές δεδομένων (types and data structures)
* λειτουργίες (operations)
* περιορισμούς ακεραιότητας (integrity constraints)

Η ενότητα αυτή αφορά ζητήματα του αντικειμενοστρεφούς μοντέλου δεδομένων. Κυρίως θα βασιστούμε στο μοντέλο που προτείνεται στο [Di93], το οποίο με τη σειρά του βασίζεται στο μοντέλο που διαφαίνεται να υπάρχει στο [At+89]. Επιπλέον,όπου κρίνεται αναγκαίο, θα αναφέρουμε τις ενστάσεις και τους προβληματισμούς άλλων επιστημόνων.

Η γενική ιδέα είναι ότι ένα αντικειμενοστρεφές μοντέλο δεδομένων προσπαθεί να ενώσει ιδέες που διέπουν αντικειμενοστρεφή συστήματα, με καθιερωμένες ιδέες από ισχύοντα μοντέλα δεδομένων.

### Δομή των Δεδομένων
Ένα αντικειμενοστρεφές μοντέλο δεδομένων βασίζεται στη γενική ιδέα του αντικειμένου (object) και της κλάσης (class).
Σύμφωνα με το [Di93], ένα αντικείμενο μπορεί να θεωρηθεί σαν μία τετράδα: **<OID, τιμή, κατάσταση, κλάση>** και μια κλάση σαν μία εντεκάδα:

* 

#### OID - Ταυτότητα αντικειμένου (Object identity)
Σαφής ορισμός για την έννοια της ταυτότητας αντικειμένου (OID - object identifier ή object
identity), δεν υπάρχει. Θα μπορούσε να αναφέρει κανείς τον ορισμό που δίνουν οι Copeland
και Khoshafian [CK86]:

Για να υλοποιηθεί η έννοια της ταυτότητας αντικειμένου, κάνουμε την παραδοχή, ότι
υπάρχει ένας (θεωρητικά άπειρος) αριθμός αναγνωριστικών (identifiers), τα οποία ικανοποιούν
τις παρακάτω συνθήκες:

* ένα αναγνωριστικό σxετίζεται με κάθε μη βασικό αντικείμενο (nonbase object).
* το αναγνωριστικό σχετίζεται με το αντικείμενο κατά τη διάρκεια της δημιουργίας του αντικειμένου, και παραμένει συσχετισμένο με το αντικείμενο, ανεξάρτητα από τις αλλαγές στην κατάσταση του αντικειμένου.
* η αντιστοιχία μεταξύ αναγνωριστικών και αντικειμένων στη Βάση Δεδομένων πρέπει να είναι ένα προς ένα. Η ιδιότητα αυτή ονομάζεται συνέπεια (consistency). Το αναγνωριστικό καθορίζει μονοσήμαντα το αντικείμενο, το οποίο με τη σειρά του παραμένει άρρηκτα συνδεδεμένο μαζί του, καθ' όλη τη διάρκεια της ύπαρξής του.

Θα μπορούσε κανείς να πει, ότι η έννοια της ταυτότητας αντικειμένου είναι μια σύλληψη,
ώστε το κάθε αντικείμενο να έχει μια οντότητα ανεξάρτητη της τιμής του. Έτσι, η ταύτιση και
η ισότητα αντικειμένων είναι έννοιες ξέχωρες μεταξύ τους.

Ο τρόπος με τον οποίο η ταυτότητα καθορίζει μονοσήμαντα ένα αντικείμενο, φαίνεται
ολοκάθαρα σε δύο ιδιότητες των αντικειμένων: το μοίρασμα αντικειμένων (object sharing) και
τις ενημερώσεις αντικειμένων (object updates) [At+89].

* Μοίρασμα Αντικειμένων: δύο αντικείμενα μπορούν να μοιράζονται ένα συστατικό. Έστω
ότι η κλάση Person έχει ως χαρακτηριστικά όνομα, ηλικία και ένα σύνολο από παιδιά. 
Ας υποθέσουμε ότι ο Πέτρος και η Μαρία έχουν από ένα παιδί με όνομα Γιάννη και ηλικία 15
χρονών. Έχουμε δηλαδή τα εξής αντικείμενα:

 *( Πέτρος, 40, { ( Γιάννης, 15, { } ) } )*
 *( Μαρία, 41, { ( Γιάννης, 15, { } ) } )*

Είναι δυνατόν, ο Πέτρος και η Μαρία να έχουν το ίδιο παιδί, ή να πρόκειται για δύο διαφορετικά παιδιά. Η παραπάνω περιγραφή είναι ικανή να αποδώσει την πραγματικότητα, από μόνη της, και στις δύο περιπτώσεις. Στην πρώτη περίπτωση, αρκεί τα δύο αντικείμενα να μοιράζονται το κοινό στοιχείο {( Γιάννης, 15, { } )}, ενώ στη δεύτερη, αρκεί να έχουμε δύο ίσα αλλά μη ταυτοτικά αντίγραφα του αντικειμένου {( Γιάννης, 15, { } )}.

* Ενημερώσεις Αντικειμένων: αν υποθέσουμε ότι ο Πέτρος και η Μαρία έχουν το ίδιο παιδί, τότε όλες οι αλλαγές στο παιδί της Μαρίας θα πρέπει να εφαρμόζονται και στο παιδί του Πέτρου.

Είναι βασικό να επισημανθεί, ότι από άποψη υλοποίησης, η ταυτότητα ενός αντικειμένου είναι μια έννοια που έχει να κάνει κυρίως με το σύστημα, παρά με το χρήστη. Τα αναγνωριστικά που εκχωρούνται είναι συνήθως αόρατα στους χρήστες, και πάντως σίγουρα μη διαχειρίσιμα, καθώς ο χρήστης δεν μπορεί να τα αλλάξει. Για να μπορεί ο χρήστης να διαχειριστεί τα αντικείμενα, τα συστήματα εισάγουν την έννοια του ονόματος (name) του αντικειμένου. Ένας χρήστης, αν θέλει, μπορεί να αναθέσει ένα όνομα σε ένα αντικείμενο, και να το διαχειρίζεται μέσω αυτού. Το όνομα του αντικειμένου μπορεί να ζει μαζί με το αντικείμενο -σε κάποιες υλοποιήσεις- και σε κάποιες άλλες μπορεί να είναι μια "προσωρινή μεταβλητή" -πράγμα που σημαίνει ότι μπορούμε ακόμα και να μεταφέρουμε ένα όνομα από ένα αντικείμενο σε ένα άλλο (κάτι που προφανώς δεν μπορεί να γίνει με την ταυτότητα σε καμία περίπτωση).

### Ενθυλάκωση (encapsulation)
Η ιδέα της ενθυλάκωσης προκύπτει από την ανάγκη διάκρισης μεταξύ καθορισμού και υλοποίησης μιας εφαρμογής καθώς και από την ανάγκη για δομή κατά ενότητες (modularity).

Η έννοια της ενθυλάκωσης στις γλώσσες προγραμματισμού προκύπτει από τους αφηρημένους τύπους δεδομένων (abstract data types). Κάθε αντικείμενο έχει ένα τμήμα διαπροσωπείας (interface part) και ένα τμήμα υλοποίησης (implementation part). Το τμήμα διαπροσωπείας είναι ο ορισμός των λειτουργιών που μπορεί να επιτελέσει το αντικείμενο. Το τμήμα υλοποίησης έχει ένα τμήμα δεδομένων (data part) και ένα συναρτησιακό τμήμα
(procedural part). Το τμήμα δεδομένων παριστάνει την κατάσταση (state) των δεδομένων και το συναρτησιακό τμήμα την υλοποίηση των διαφόρων λειτουργιών. Δηλαδή:

 αντικείμενο = τμήμα διαπροσωπείας + τμήμα υλοποίησης

όπου:

 τμήμα υλοποίησης = τμήμα δεδομένων + συναρτησιακό τμήμα

Η μεταφορά της έννοιας της ενθυλάκωσης στις Βάσεις Δεδομένων καθορίζει ότι ένα αντικείμενο ενσωματώνει πρόγραμμα και δεδομένα. Στις σχεσιακές βάσεις, κάθε οντότητα παριστάνεται με μια πλειάδα (tuple), ενώ οι εφαρμογές τρέχουν χρησιμοποιώντας κάποια προστακτική γλώσσα με ενσωματωμένες DML εντολές (ή μια γλώσσα τέταρτης γενεάς). Οι εφαρμογές είναι αποθηκευμένες σε ένα σύστημα αρχείων, ανεξάρτητο της βάσης.

Σε ένα αντικειμενοστρεφές σύστημα κάθε οντότητα καθορίζεται σαν ένα τμήμα δεδομένων και ένα τμήμα υλοποίησης, όπου υλοποιούνται οι διάφορες εφαρμογές που έχουν σχέση με την οντότητα.

Ένα καλό παράδειγμα, για τη διαφορά ανάμεσα στο σχεσιακό και το αντικειμενοστρεφές μοντέλο, είναι η οντότητα "Εργοστάσιο_Αυτοκινήτων" και η υλοποίηση της εφαρμογής "*Αύξησε_Παραγωγή_Φορτηγών*". Σε μια σχεσιακή βάση, η εφαρμογή "*Αύξησε_Παραγωγή_Φορτηγών*" θα ήταν ένα εξωτερικό πρόγραμμα. Αντίθετα, σε μια αντικειμενοστρεφή βάση, η οντότητα "Εργοστάσιο_Αυτοκινήτων" θα αποτελούνταν από το τμήμα διαπροσωπείας (το μέσο επικοινωνίας με το χρήστη), το τμήμα δεδομένων (το οποίο θα έμοιαζε αρκετά με την υλοποίηση της οντότητας στο σχεσιακό μοντέλο) και το συναρτησιακό τμήμα, που ανάμεσα στα άλλα, θα είχε και την εφαρμογή "*Αύξησε_Παραγωγή_Φορτηγών*". Καμιά λειτουργία, πέραν αυτών που καθορίστηκαν στο τμήμα διαπροσωπείας δεν μπορεί να επιτελεστεί. Η παραπάνω θέση αποτελεί ένα από τα πιο σημαντικά στοιχεία για την έννοια της
ενθυλάκωσης. Ο μόνος τρόπος για να αποταθούμε στα διάφορα αντικείμενα, και στις μεταβλητές στιγμιοτύπου τους, είναι μέσω των μηνυμάτων που δηλώθηκαν στο τμήμα διαπροσωπείας.

Αν υποθέσουμε ότι έχουμε μια κλάση "*Άνθρωπος*", με μια μέθοδο "*Παρουσιάσου*", και ότι για το αντικείμενο "*Γιώργος*", που τυχαίνει να είναι στιγμιότυπο της κλάσεως "*Άνθρωπος*", υπάρχει κάπου η κλήση:

 ***Γιώργος Παρουσιάσου***

Όταν το αντικείμενο "*Γιώργος*" λάβει το παραπάνω μήνυμα αναλαμβάνει την εκτέλεση της μεθόδου "*Παρουσιάσου*".

Η ενθυλάκωση ενθαρρύνει ιδιαίτερα την ιδέα της "λογικής ανεξαρτησίας δεδομένων": μπορούμε να αλλάξουμε την υλοποίηση ενός τύπου, χωρίς να φανεί αυτό, στη διαπροσωπεία.

Έτσι, οι διάφορες εφαρμογές προστατεύονται από τις αλλαγές στα χαμηλότερα επίπεδα υλοποίησης.

Συμπερασματικά, η ενθυλάκωση συγκεντρώνει τα εξής χαρακτηριστικά:

* ενσωματώνει δεδομένα και λειτουργίες σ' αυτά,
* αποκρύπτει τον τρόπο υλοποίησης των μεθόδων, οπότε απεξαρτά τη διαχείριση του αντικειμένου από τη δομή του,
* επιβάλει τη διαχείριση του κάθε αντικειμένου, αυστηρά και μόνο από τις δικές του μεθόδους, μέσω των αντίστοιχων μηνυμάτων.

### Περιορισμοί Ακεραιότητας
Οι περιορισμοί σκοπό έχουν να εξασφαλίσουν την ακεραιότητα των δεδομένων. Στις αντικειμενοστρεφείς βάσεις δεδομένων οι περιορισμοί ακεραιότητας που συνήθως μπορούν να οριστούν είναι οι ακόλουθοι:

* Περιορισμοί ακεραιότητας κλειδιού (Key constraints).
* Υπαρξιακός περιορισμός ακεραιότητας (Existential constraint) (όταν σε κάποιο σύνθετο αντικείμενο, υπάρχει αναφορά σε κάποιο άλλο αντικείμενο, τότε το αντικείμενο στο οποίο γίνεται η αναφορά, υπάρχει).
* Περιορισμοί ακεραιότητας μη κενού χαρακτηριστικού (NOT NULL constraints).
* Περιορισμός δομικής συνέπειας (structural consistency) (το σχήμα μιας αντικειμενοστρεφούς βάσης δεδομένων είναι δομικά συνεπές αν η ιεραρχία των κλάσεων είναι ένας κατευθυνόμενος ακυκλικός γράφος (DAG), αν δεν υπάρχουν συγκρούσεις στον ορισμό χαρακτηριστικών (attributes) και μεθόδων και αν οι τύποι και οι υπογραφές των μεθόδων είναι συμβατοί. Ένα αντικείμενο, δε, είναι δομικά συνεπές, αν η τιμή του ανταποκρίνεται στον τύπο της κλάσης του).
* Περιορισμός συνέπειας συμπεριφοράς (Behavioral consistency) (μια βάση είναι συνεπής στη συμπεριφορά της αν κάθε μέθοδος σέβεται την υπογραφή της και αν ο κώδικάς της δεν παράγει λάθη στο χρόνο εκτέλεσης (run-time errors) ή ανεπιθύμητα αποτελέσματα).
* Περιορισμός διατήρησης της συνέπειας του αντίστροφου δείκτη (Inverse link consistency).
* Περιορισμός διαχωρισιμότητας (Disjointness Constraint) (ένα αντικείμενο δε μπορεί να ανήκει σε περισσότερες από μία κλάσεις).
* Περιορισμός επικάλυψης (Covering constraint) (δεν είναι δυνατό, μια κλάση να έχει στιγμιότυπα, τα οποία να μην ανήκουν σε κάποια από τις υποκλάσεις της).

## ODMG-93
Η επιτυχία των σχεσιακών συστημάτων διαχείρισης βάσεων δεδομένων βασίστηκε αφενός στην απλότητα του σχεσιακού μοντέλου δεδομένων και στην ανεξαρτησία των δεδομένων από τις εφαρμογές, και αφετέρου στην τυποποίηση. Η αποδοχή του SQL standard, το οποίο βασίστηκε στο μοντέλο δεδομένων και τη γλώσσα που πρότεινε η ΙΒΜ (η μεγαλύτερη εταιρεία που αναμίχθηκε από νωρίς στην ανάπτυξη τέτοιων συστημάτων), πρόσφερε μεταφερσιμότητα των δεδομένων και των εφαρμογών, γεγονός που έκανε το σχεσιακό μοντέλο δεδομένων και την SQL τόσο δημοφιλή.

Στην περίπτωση των αντικειμενοστρεφών συστημάτων δεδομένων, η κατάσταση είναι διαφορετική, καθώς η "παιδική τους ηλικία" συνοδεύτηκε από το βασικό πρόβλημα της ανυπαρξίας ενός καλά ορισμένου μοντέλου δεδομένων. Κάθε σύστημα προσέφερε το δικό του μοντέλο δεδομένων. Τα μοντέλα δεδομένων αυτά έμοιαζαν σημαντικά μεταξύ τους, όμως η ομοιότητα δεν είναι αρκετή: στο επίπεδο του μοντέλου δεδομένων χρειάζεται ταύτιση, και όχι απλή ομοιότητα στα βασικά στοιχεία. Το ίδιο συμβαίνει και στο επίπεδο των γλωσσών προγραμματισμού και των ερωτήσεων. Κάθε σύστημα, βασιζόμενο στο δικό του μοντέλο δεδομένων, προσέφερε και τη δική του γλώσσα. Αν και οι γλώσσες προγραμματισμού της βάσης δεδομένων βασίζονταν στις ίδιες κλασικές γλώσσες τρίτης γενιάς (C++, Smalltalk, κλπ.) δεν υπήρχε ταύτιση στα επιπλέον στοιχεία που χρειάζονται για τη διαχείριση των αντικειμένων μιας βάσης δεδομένων.

Με βάση τα παραπάνω, ήταν φανερή η ανάγκη για την ύπαρξη τουλάχιστον ενός κοινού παρονομαστή, που να επιτρέπει τη μεταφερσιμότητα εφαρμογών και δεδομένων. Το Object Database Management Group (ODMG) είναι μια επιτροπή που, στις αρχές της δεκαετίας του 1990, πρότεινε ένα κοινό interface (ODMG-93) στους διάφορους κατασκευαστές αντικειμενοστρεφών συστημάτων βάσεων δεδομένων, με βάση το οποίο να συγγράφονται μεταφέρσιμες εφαρμογές από το ένα σύστημα στο άλλο. Η μεταφερσιμότητα (portability) των εφαρμογών συνίσταται στη μεταφερσιμότητα του σχήματος της βάσης, του binding της γλώσσας προγραμματισμού, της γλώσσας διαχείρισης δεδομένων και της γλώσσας ερωτήσεων.

Το ODMG δεν είναι μια επίσημη επιτροπή τυποποίησης. Συμμετέχουν όμως, σ’ αυτήν, εταιρείες που κατέχουν το 80% της αγοράς των αντικειμενοστρεφών συστημάτων βάσεων δεδομένων. Επιπλέον, οι εταιρείες αυτές έχουν δεσμευτεί να παρέχουν το κοινό αυτό interface από τις αρχές του 1995. Κομμάτια του standard αποτελούν στοιχεία ήδη υλοποιημένα σε κάποια από τα υπάρχοντα αντικειμενοστρεφή συστήματα βάσεων δεδομένων (π.χ. η γλώσσα ερωτήσεων βασίζεται στη γλώσσα ερωτήσεων του Ο2).

Το 1993, τα επτά μέλη του ODMG με δικαίωμα ψήφου ήταν οι εταιρείες Object Design (ObjectStore), Objectivity, ONTOS, O2 Technology, POET Software, Servio Corporation (GemStone), και Versant Technology. Επιπλέον όλες οι εταιρείες που συμμετέχουν ως Reviewer Members έχουν δεσμευτεί να υλοποιήσουν το ODMG-93. Σήμερα, στα 1997, οι εταιρείες αυτές έχουν παραμείνει σχεδόν οι ίδιες (αν και πολλές έχουν αλλάξει τα ονόματά τους) και είναι οι εξής: GemStone Systems, IBEX Computing, O2 Technology, Object Design, Objectivity, POET Software, UniSQL, Versant Object Technology. Πρακτικά, αποχώρησε η Ontos και προσχώρησε η IBEX Computing (που διακινεί το Itasca) και η UniSQL. Στην παρουσίαση του ODMG-93 standard θα βασιστούμε κυρίως στο [Ca95] και κατά δεύτερο λόγο στα [Ki94], [ODMG94]. Όλα τα σχήματα και τα παραδείγματα είναι από το [Ca94] και το [Ca95].

### Αρχιτεκτονική του ODMG-93
Τα βασικά στοιχεία της αρχιτεκτονικής του ODMG-93 είναι τα εξής:
* Μοντέλο Αντικειμένων (Object Model)
* Γλώσσα Ορισμού Αντικειμένων (Object Definition Language - ODL)
* Γλώσσα Ερωταποκρίσεων Αντικειμένων (Object Query Language - OQL)
* Language Bindings (C++, Smalltalk)

Η περιγραφή του ODMG-93 περιλαμβάνει ένα μοντέλο αντικειμένων που είναι μια επέκταση στο μοντέλο αντικειμένων του OMG [OMG97], μια γλώσσα ορισμού αντικειμένων (ODL) που παρέχει ένα μηχανισμό ανεξάρτητο από τις γλώσσες προγραμματισμού για να εκφράσει κανείς το σχήμα μιας βάσης, μια γλώσσα ερωταποκρίσεων αντικειμένων (OQL) που παρέχει ένα δηλωτικό τρόπο προσπέλασης των δεδομένων, σαν μια επέκταση της SQL, και δυο επεκτάσεις αντικειμενοστρεφών γλωσσών προγραμματισμού. Η μια επέκταση είναι αυτή για τη C++ και η άλλη για τη Smalltalk.

Στην παρακάτω εικόνα φαίνεται ο τρόπος, με βάση τον οποίο θα χρησιμοποιείται ένα αντικειμενοστρεφές σύστημα βάσεων δεδομένων, στα πλαίσια της προδιαγραφής του ODMG-93. Ένας διαχειριστής της βάσης γράφει δηλώσεις για το σχήμα της, οι οποίες συγγράφονται στην ODL, ή σε μια επέκταση της γλώσσας προγραμματισμού (PL ODL). Ο προγραμματιστής εφαρμογών γράφει και ένα πρόγραμμα που υλοποιεί την εφαρμογή. Ο κώδικας του προγράμματος αυτού γράφεται σε μια γλώσσα προγραμματισμού (PL), όπως για παράδειγμα, η C++, η οποία επεκτείνεται για να αποτελέσει την γλώσσα προγραμματισμού μιας βάσης δεδομένων. Οι δηλώσεις περνούν από κάποιο προεπεξεργαστή (preprocessor), ο οποίος αφενός παράγει το σχήμα της βάσης και αφετέρου φτιάχνει μια περιγραφή του σχήματος στη γλώσσα προγραμματισμού της εφαρμογής. Ο κώδικας της εφαρμογής και η περιγραφή αυτή
μεταφράζονται, δημιουργείται ένα εκτελέσιμο αρχείο της εφαρμογής, το οποίο αφού συνδυαστεί με τη μηχανή του αντικειμενοστρεφούς συστήματος βάσεων δεδομένων (μέσα από ένα πρόγραμμα σύνδεσης - linker) δημιουργεί την τελική εφαρμογή, η οποία και επεξεργάζεται τα δεδομένα της βάσης δεδομένων.

### Το Μοντέλο Αντικειμένων του ODMG
Το μοντέλο δεδομένων του ODMG συνοψίζεται ως εξής:
* Η βασικές οντότητες είναι το αντικείμενο (object) και η βασική τιμή (literal). Κάθε αντικείμενο έχει ένα μοναδικό αναγνωριστικό. Μια βασική τιμή δεν έχει αναγνωριστικό.
* Η κατάσταση (state) των αντικειμένων χαρακτηρίζεται από τις τιμές που έχουν αυτά για κάποιες ιδιότητες (properties). Οι ιδιότητες μπορεί να είναι είτε χαρακτηριστικά (attributes) του αντικειμένου, είτε αναφορές (relationships) ανάμεσα στο αντικείμενο και τα άλλα αντικείμενα. Γενικά, οι τιμές των ιδιοτήτων ενός αντικειμένου μπορούν να αλλάξουν στο χρόνο.
* Η συμπεριφορά των αντικειμένων χαρακτηρίζεται από μια ομάδα λειτουργιών (operations) που μπορεί να επιτελεσθεί από (ή σε) ένα αντικείμενο.
* Τα αντικείμενα και οι βασικές τιμές κατηγοριοποιούνται σε τύπους (types). Όλα τα στοιχεία ενός δεδομένου τύπου έχουν ένα κοινό ενεργό πεδίο καταστάσεων (δηλαδή, το ίδιο σύνολο ιδιοτήτων) και κοινή συμπεριφορά (δηλαδή, το ίδιο σύνολο λειτουργιών). Ένα αντικείμενο αποτελεί στιγμιότυπο (instance) του τύπου του.
* Μια βάση δεδομένων αποθηκεύει αντικείμενα τα οποία μπορούν να μοιράζονται πολλοί χρήστες και πολλές εφαρμογές. Η βάση δεδομένων στηρίζεται σε ένα σχήμα που δηλώνεται σε ODL και περιέχει στιγμιότυπα των τύπων που δηλώθηκαν στο σχήμα.

Η ορολογία που χρησιμοποιεί το ODMG δε συμβαδίζει απόλυτα με την ορολογία που έχουμε χρησιμοποιήσει μέχρι εδώ. Η "κατάσταση" ενός αντικειμένου στο ODMG είναι ο όρος για την "τιμή" του αντικειμένου, όπως τον έχουμε χρησιμοποιήσει μέχρι τώρα.

### Γλώσσα Ορισμού Αντικειμένων (Object Definition Language - ODL)
Η ODL είναι μια γλώσσα που χρησιμοποιείται για να δηλώσει διαπροσωπείες (interfaces) σε τύπους αντικειμένων που ακολουθούν το μοντέλο αντικειμένων του ODMG-93 και έχει σκοπό να παρέχει μεταφερσιμότητα των σχημάτων των βάσεων δεδομένων. Η ODL αποτελεί την DDL για τύπους αντικειμένων. Καθορίζει τα χαρακτηριστικά των τύπων και τις υπογραφές των μεθόδων. Για τη διαχείριση των στιγμιότυπων των τύπων, και την υλοποίηση των μεθόδων, υπάρχουν οι γλώσσες διαχείρισης αντικειμένων (Object Manipulation Languages - OMLs). Το ODMG-93 δεν καθορίζει κάποια συγκεκριμένη OML. Περιγράφει, όμως, δύο interfaces για τη σύνδεση των αντικειμενοστρεφών συστημάτων βάσεων δεδομένων με C++ και Smalltalk.

Δεδομένου ότι δεν είναι σαφές που θα υλοποιηθεί το σχήμα που θα καθοριστεί στην ODL, η ODL πρέπει να είναι ανεξάρτητη από την οποιαδήποτε γλώσσα προγραμματισμού. Επιπλέον, πρέπει να μπορεί να ενσωματωθεί με ομαλό τρόπο σε γλώσσες όπως η Smalltalk και η C++, πράγμα που καθορίζεται στα αντίστοιχα bindings. Ακολουθεί το παράδειγμα ενός υποτυπώδους σχήματος σε ODL (με έντονα γράμματα φαίνονται οι δεσμευμένες λέξεις της ODL):

  **interface** Person
  (   **extent** People)
  {
    **attribute** String name;
    **attribute** Struct Address { Unsigned Short number, String
        Street, String city_name} address;
    **relationship** Person spouse **inverse** Person::spouse;
    **relationship** Set children **inverse** Person::parents
        {order by birth date }
    **relationship** List parents **inverse** Person::children;
    **void** birth (in String name);
    **Boolean** marriage (in String person_name) raises
        (no_such_person);
    **Unsigned Short** ancestors (out Set all_ancestors)
        raises (no_such_person);
    **void** move (in String new_address);
  };

  **interface** Employee: Person
  (    **extent** employees
    **key**(name, id))
  {
    **attribute** Short id;
    **attribute** Unsigned Short annual_salary;
  };

  **interface** City
  (    **extent** cities
    **key** city_code)
  {
    **attribute** Unsigned Short city_code;
    **attribute** String name;
    **attribute** Set population;
  };

Στο παραπάνω παράδειγμα, ορίσαμε την κλάση Person που μοντελοποιεί ένα άνθρωπο. Τα χαρακτηριστικά της εν λόγω κλάσης είναι το όνομα (name), η διεύθυνση (Address) που αποτελεί μια σύνθετη τιμή, η/ο σύζυγος (spouse) που αποτελεί ένας αντίστροφος δείκτης (inverse) και οι αντίστροφοι δείκτες children και parents, που μοντελοποιούν τα παιδιά και τους γονείς αντίστοιχα. Ακόμα υπάρχουν οι συναρτήσεις birth (ημερομηνία γεννήσεως), marriage (αν κάποιος είναι παντρεμένος ή όχι), ancestors (που επιστρέφει όλους τους προγόνους κάποιου) και move (που αλλάζει τη διεύθυνση κάποιου. Η κλάση Employee κληρονομεί την κλάση Person και την εξειδικεύει προσθέτοντας ένα κωδικό (id) και ένα ετήσιο εισόδημα (annual_salary). Τέλος, η κλάση City έχει τα χαρακτηριστικά city_code (κωδικός), name (όνομα) και population, που είναι ο πληθυσμός της και είναι ένα σύνολο από αντικείμενα της κλάσης Person.

### Object Query Language - OQL
Η OQL βασίστηκε στην ήδη υλοποιημένη γλώσσα ερωταποκρίσεων του συστήματος Ο2. Η OQL μπορεί να χρησιμοποιηθεί και σαν ανεξάρτητη γλώσσα, αλλά και σαν υποσύνολο μιας από τις OML. Στη δεύτερη περίπτωση, υπάρχει μια συνάρτηση που εκτελεί την ερώτηση.

Ας υποθέσουμε ότι έχουμε τον τύπο Person με τα χαρακτηριστικά name, birthdate, salary και τη μέθοδο age και τον τύπο Employee που κληρονομεί τον τύπο Person και τον εξειδικεύει με την αναφορά (relationship) subordinates και τη μέθοδο seniority. Επίσης, κάποιο πρόσωπο είναι ο Chairman και μάλιστα υπάρχει κάποιο entry-point για αυτό το αντικείμενο. Τέλος, οι δύο τύποι έχουν τα extents Persons και Employees. Έστω επίσης, ότι υπάρχει και ο τύπος Department, με το χαρακτηριστικό name και την αναφορά employees, η οποία τυχαίνει να είναι και αντίστροφη (στον τύπο Employee υπάρχει η αντίστροφη αναφορά department). Έστω η ερώτηση:

 select distinct struct(name: x.name, hps:
    (select y
	 from x.subordinates as y
	 where y.age > 30))
 from Employees x

η οποία επιστρέφει, για κάθε υπάλληλο, το όνομά του και τους υφιστάμενούς του που έχουν ηλικία πάνω από 30. Η παραπάνω ερώτηση έχει αποτέλεσμα του τύπουQ

 **set**)>

Παρατηρούμε τα εξής:
* Μπορούμε να ονομάζουμε τα χαρακτηριστικά του αποτελέσματος της ερώτησης.
* Στο from clause μπορούμε να χρησιμοποιήσουμε πολλούς φορμαλισμούς. Μπορούμε να πούμε from Employees x, ή from Employees as x, ή ακόμα και from x in Employees.
* Μπορούμε να έχουμε φώλιασμα ερωτήσεων και μεταβλητών.
* Μπορούμε να χρησιμοποιούμε εκφράσεις μονοπατιών μέσα σε μια ερώτηση.
* Μπορούμε να χρησιμοποιούμε μεθόδους οπουδήποτε μέσα σε μια ερώτηση.

Η ερώτηση:

  Chairman

αν και δεν υπακούει στο γνωστό SELECT-FROM-WHERE φίλτρο της SQL, είναι έγκυρη και επιστρέφει το αντικείμενο Chairman.

Η ερώτηση:

  **Employee**(name: "Pat", id: 0, annual_salary: 100,000)

δημιουργεί ένα αντικείμενο της κλάσης Employee.

Πρέπει να επισημάνουμε ότι το αποτέλεσμα μιας ερώτησης μπορεί να έχει ή να μην έχει ταυτότητα αντικειμένου, ανάλογα με τον τύπο του.

Ας υποθέσουμε και μία κλάση Flowers με το χαρακτηριστικό name.

 select p
 from Persons p, Flowers f
 where p.name = f.name

Η παραπάνω ερώτηση που βρίσκει όλους τους ανθρώπους που το όνομά τους είναι και το όνομα ενός άνθους, υλοποιεί μια σύνδεση, όπως θα γινόταν και στα σχεσιακά συστήματα.

Στην ερώτηση:

 select department, avg_salary: avg(select e.salary from partition x)
 from Employees e
 group by department: e.department
 having count(select * from partition x) > 5
 order by department.name

μπορούμε να παρατηρήσουμε ότι διατηρούνται τα group by, having και order by clauses της SQL, τα οποία χαρακτηρίζονται από τα εξής:

* Το clause group by χωρίζει τους υπαλλήλους σε ομάδες (partitions). Κάθε ομάδα χαρακτηρίζεται από το γεγονός ότι όλοι οι υπάλληλοι που ανήκουν σ' αυτό δουλεύουν στο ίδιο τμήμα και ονομάζεται partition (που είναι δεσμευμένη λέξη στην OQL). Επιπλέον το clause having περιορίζει τα τμήματα με τα οποία θα ασχοληθεί η ερώτηση, σ' αυτά που έχουν αριθμό υπαλλήλων πάνω από 5.
* Η συντόμευση * διατηρείται και στην OQL (όπως και στην SQL).
* Το order by λειτουργεί όπως και στην SQL.

Τέλος, στην OQL υπάρχουν και διάφορα άλλα χαρακτηριστικά, τα οποία δεν κρίνεται σκόπιμο να αναφερθούν.[Ca95]

### C++ Binding
Στη συνέχεια, θα παρουσιάσουμε ένα από τα χρησιμοποιούμενα bindings, το C++ binding, το οποίο είναι και το πλέον χρησιμοποιούμενο. Όταν αναφερόμαστε στο C++ binding για ODL/OML πρέπει να έχουμε υπόψη μας δύο πράγματα: το C++ binding για ODL είναι μια βιβλιοθήκη κλάσεων και μια επέκταση στη γραμματική της C++. Η βιβλιοθήκη των κλάσεων παρέχει κλάσεις για να υλοποιηθεί το μοντέλο αντικειμένων του ODMG-93. Η επέκταση του συντακτικού της γλώσσας έχει να κάνει με την υποστήριξη αναφορών (relationships) μεταξύ των κλάσεων. Η OML χρησιμοποιείται για την ανάκτηση και την επεξεργασία δεδομένων από τη βάση, και ακολουθεί το συντακτικό της C++. Οι ODL/OML δεν ασχολούνται με τη φυσική αποθήκευση των αντικειμένων, αλλά μόνο με τα λογικά χαρακτηριστικά τους. Ένα πρόσθετο σύνολο δομών, με όνομα physical pragmas, έχει καθοριστεί για να αναλάβει να δώσει στον προγραμματιστή κάποιο έλεγχο πάνω σε αυτά τα ζητήματα.

Τα bindings για τις διάφορες γλώσσες προγραμματισμού καθορίστηκαν με βάση την αρχή ότι ο προγραμματιστής πρέπει να έχει να κάνει με μόνο μία γλώσσα. Αποτελέσματα της αρχής αυτής είναι, ότι υπάρχει μόνο ένα σύστημα τύπων και για τη γλώσσα και για τη βάση δεδομένων, και ότι η ενσωμάτωση των χαρακτηριστικών που οφείλονται στο μοντέλο αντικειμένων της βάσης δεδομένων γίνεται ομαλά.

Για να δηλωθούν τα διαρκή (persistent) δεδομένα στη C++, μια κλάση πρέπει να είναι υποκλάση της κλάσης Persistent_Object. Αυτό σημαίνει, ότι η κλάση αυτή μπορεί να έχει και διαρκή (persistent) και μεταβατικά (transient) -μέσω κάποιων συναρτήσεων- αντικείμενα. Στο παρακάτω παράδειγμα, ακολουθεί η δήλωση ενός στιγμιότυπου (profP) μιας κλάσεως (Professor), το οποίο είναι διαρκές:

 **Ref** profP;

Στην παραπάνω εικόνα φαίνεται ο τρόπος με τον οποίο παράγεται μια εφαρμογή, χρησιμοποιώντας το C++ binding για ODL/OML. Ένας διαχειριστής της βάσης γράφει δηλώσεις για το σχήμα της, οι οποίες συγγράφονται στην C++ ODL, η οποία είναι μια επέκταση της C++. Ο προγραμματιστής εφαρμογών γράφει και ένα πρόγραμμα που υλοποιεί την εφαρμογή σε C++, η οποία επεκτείνεται για να αποτελέσει την γλώσσα προγραμματισμού μιας βάσης δεδομένων. Οι δηλώσεις περνούν από κάποιο προεπεξεργαστή (preprocessor), ο οποίος αφενός παράγει το σχήμα της βάσης και αφετέρου φτιάχνει μια περιγραφή του σχήματος στη C++. Ο κώδικας της εφαρμογής και η περιγραφή αυτή μεταφράζονται, δημιουργείται ένα εκτελέσιμο αρχείο της εφαρμογής, το οποίο αφού συνδυαστεί με τη μηχανή του αντικειμενοστρεφούς συστήματος βάσεων δεδομένων (μέσα από ένα πρόγραμμα σύνδεσης -linker) δημιουργεί την τελική εφαρμογή, η οποία και επεξεργάζεται τα δεδομένα της βάσης δεδομένων.

Όπως προαναφέρθηκε, η ODL καθορίζει το σχήμα μιας βάσης, ενώ η OML καθορίζει τη διαχείριση των αντικειμένων, των σχέσεων μεταξύ των κλάσεων, καθώς και των συλλογών (set, bag, list, array). Σε ότι αφορά τις δοσοληψίες ή συναλλαγές (transactions), είναι υποχρεωτικό, κάθε λειτουργία διαχείρισης αντικειμένων να γίνεται μέσα από μια δοσοληψία. Οι δοσοληψίες αποτελούν στιγμιότυπα της ομώνυμης κλάσης και διαθέτουν λειτουργίες commit, abort και checkpoint. Δεν υποστηρίζονται μακρές συναλλαγές, υποστηρίζονται όμως, εμφωλευμένες. Επιπλέον, η OML είναι υπεύθυνη και για τις λειτουργίες σύνδεσης και αποσύνδεσης με μία βάση.

Υπάρχει και μια απεικόνιση της OQL για C++. Οι ερωτήσεις μπορούν να δηλωθούν μέσα σε ένα πρόγραμμα μέσω μιας συναρτήσεως για ερωτήσεις, η οποία παίρνει συμβολοσειρές για ορίσματα. Τα ορίσματα αυτά πρέπει να είναι έγκυρες ερωτήσεις, οι οποίες μεταφράζονται και εκτελούνται στο run-time. Το αποτέλεσμα επιστρέφεται στην παράμετρο "result".

## Αντικειμενοστρεφείς επεκτάσεις των Σχεσιακών Συστημάτων (SQL/Object, SQL/Foundation)
Εδώ θα εξετάσουμε τον τρόπο με τον οποίο οι παρουσία των
αντικειμενοστρεφών βάσεων δεδομένων επηρέασε την εξέλιξη των κλασικών, σχεσιακών
συστημάτων. Διάφορα σχεσιακά ΣΔΒΔ (Oracle, Informix κλπ.) άρχισαν σιγά σιγά, στα μέσα
της δεκαετίας του '90 να παρέχουν αντικειμενοστρεφείς επεκτάσεις στη μηχανή τους. Η πιο
βασική, όμως, έκφανση της επίδρασης που είχε η ύπαρξη των αντικειμενοστρεφών συστημάτων
ήταν η υιοθέτηση αντικειμενοστρεφών επεκτάσεων στο καινούριο στάνταρτ της SQL, το SQL-3. Πιο συγκεκριμένα, υπάρχουν τέσσερις κύριοι τομείς στους οποίους συνοψίζεται αδρά, ηεπίδραση αυτή. Οι τομείς αυτοί είναι:
* Εισαγωγή τύπων που ορίζονται από το χρήστη -UDTs
* Κατηγορήματα για την κατασκευή τους -Type Predicate
* Συναρτήσεις που μπορούν να οριστούν από το χρήστη - User Defined Functions & Procedures
* Κατάργηση της πρώτης κανονικής μορφής (1NF) - Collection Types

Θα στηριχθούμε στα [ΚΜΝ97], [ΜΜ96] για την παρουσίαση αυτή.

### Τύποι Ορισμένοι από τον Χρήστη
Οι τύποι που μπορούν να οριστούν από το χρήστη (User Defined Types -UDTs) διαιρούνται
με τη σειρά τους σε διάφορες κατηγορίες:
* Διακριτοί τύποι - Distinct Types
* Αφηρημένοι τύποι - Abstract Data Types (ADTs)
* Τύποι γραμμών / Τύποι αναφοράς - Row Types / Reference Types

#### Διακριτοί Τύποι
Οι διακριτοί τύποι (distinct types) αποτελούν την πιο βασική έκφραση των ορισμένων από τον χρήστη τύπων. Ουσιαστικά, αποτελούν μετονομασία ενός βασικού τύπου πηγή (π.χ. *DECIMAL, REAL, INTEGER*). Στην συνέχεια, θα αναφερόμαστε στον τύπο βάσει του οποίου ορίζεται ένας διακριτός τύπος, ως πηγαίο τύπο (*source type*) ή βασικό τύπο αναφοράς του διακριτού τύπου. Ο διακριτός τύπος με τον πηγαίο τύπο έχουν την ίδια εσωτερική δομή αλλά παρουσιάζουν εν γένει διαφορετική συμπεριφορά.

Για παράδειγμα, μπορούμε να δηλώσουμε δύο διακριτούς τύπους, παράγωγα του DECIMAL, που θα αναπαριστούν το αμερικάνικο (*US_DOLLAR*) και το καναδικό δολάριο (*CND_DOLLAR*).

 CREATE DISTINCT TYPE US_DOLLAR AS DECIMAL (9.2)
 CREATE DISTINCT TYPE CDN_DOLLAR AS DECIMAL (9.2)

Οι διακριτοί τύποι είναι εφοδιασμένοι από το σύστημα με τελεστές σύγκρισης. Ο ορισμός των τελεστών βασίζεται στους αντιστοίχους ορισμούς του πηγαίου τύπου.

Παρόλο που οι διακριτοί τύποι παρουσιάζουν την ίδια εσωτερική δομή με τον πηγαίο τύπο, δεν είναι άμεσα συγκρίσιμοι μαζί του (strongly typed). Για να μπορέσουμε να συγκρίνουμε ένα διακριτό τύπο με τον πηγαίο του, καθώς και διακριτούς τύπους μεταξύ τους (που έχουν βέβαια κοινή πηγή) χρησιμοποιούμε συναρτήσεις μετατροπής (casting).

Με χρήση των διακριτών τύπων μπορούμε να ορίζουμε σχέσεις. Για παράδειγμα:

 CREATE TABLE SALES
   (ID INTEGER, US US_DOLLAR, CDN CDN_DOLLAR)

Οι μεταβλητές US, CND βασίζονται στον ίδιο πηγαίο τύπο αλλά ανήκουν σε διαφορετικούς διακριτούς τύπους. Ως εκ τούτου η ακόλουθη έκφραση είναι λανθασμένη.

 SELECT * FROM SALES WHERE CDN > US

Για να πετύχουμε την σύγκριση χρησιμοποιούμε την συνάρτηση μετατροπής CND_DOLLAR η οποία μετατρέπει το όρισμα της σε καναδικά δολάρια.

 SELECT * FROM SALES WHERE CDN > CDN_DOLLAR(US)

Αντίστοιχα, θα μπορούσαμε να χρησιμοποιήσουμε την συνάρτηση μετατροπής US_DOLLAR.

Οι διακριτοί τύποι δεν υποστηρίζουν κληρονομικότητα ούτε είναι δυνατό να ορίσουμε ένα διακριτό τύπο με πηγαίο έναν άλλο διακριτό τύπο.

#### Αφηρημένοι τύποι δεδομένων
Έκτος από τους διακριτούς τύπους δεδομένων μπορούμε να ορίσουμε και αφηρημένους τύπους δεδομένων (Abstract Data Types, ADTs). Οι αφηρημένοι τύποι δεδομένων αποτελούν οντότητες με συμπεριφορά και ενθυλακωμένη εσωτερική δομή. Ο ορισμός της δομής ενός ATD γίνεται σε SQL. Για παράδειγμα ορίζουμε τον ακόλουθο τύπο:

 CREATE TYPE address
   (street char (30),
   city char (20),
   state char (2),
   zip integer);*

==== Ενθυλάκωση (Encapsulation) ====
Όπως έχουμε ήδη αναφέρει, η εσωτερική δομή των αφηρημένων τύπων είναι ενθυλακωμένη. Η πρόσβαση στα πεδία του τύπου περιορίζεται σε συναρτήσεις που ορίζονται στο ορατό μέρος του κάθε αφηρημένου τύπου. Παράλληλα, δεν υπάρχει διάκριση μεταξύ συναρτήσεων, αποθηκευμένων συναρτήσεων (stored functions) και ιδεατών πεδίων (virtual attributes).

Οι συναρτήσεις με τις οποίες μας επιστρέφεται η τιμή ενός πεδίου (observer functions) ή με τις οποίες αναθέτουμε μια τιμή σε κάποιο πεδίο (mutator functions) δημιουργούνται αυτόματα. Για παράδειγμα:

 street(address) -> char(30)
 city(address) -> char(20)
 state(address) -> char(2)
 zip(address) -> integer
 street(address, char(30)) -> address
 city(address, char(20)) -> address
 state(address, char(2)) -> address
 zip(address, integer) -> address

Η κλήση της street(address) θα επιστρέψει ένα πεδίο char(30) που αντιστοιχεί στο πεδίο street του τύπου address. Αντίστοιχα, η κλήση της συνάρτησης street(address, char(30)) θα δημιουργήσει ένα στιγμιότυπο του τύπου address με τιμή πεδίου address την τιμή του char(30).

==== Δημιουργία Στιγμιότυπων ====
Για να δημιουργήσουμε ένα νέο στιγμιότυπο χρησιμοποιούμε την κατασκευαστική συνάρτηση (constructor function). Κάθε φόρα που ορίζουμε ένα ADT δημιουργείται αυτόματα και μια κατασκευαστική συνάρτηση.

 address() -> address

Με την κλήση της παραπάνω συνάρτησης κατασκευάζουμε ένα νέο στιγμιότυπο του τύπου address με κάθε πεδίο του αρχικοποιήμενο στην εξ’ ορισμού τιμή.

==== Κληρονομικότητα ====
Σε αντίθεση με τους διακριτούς τύπους, οι αφηρημένοι τύποι μπορούν να οριστούν με βάση έναν ή περισσότερους διαφορετικούς αφηρημένους τύπους (subtyping). Έτσι ο νέος τύπος (υποτύπος) κληρονομεί τα αντίστοιχα πεδία, την συμπεριφορά και τις συναρτήσεις των τύπων ορισμού του (υπερτύποι). Τονίζουμε ότι υποστηρίζεται και πολλαπλή κληρονομικότητα.

 CREATE TYPE shape …
 CREATE TYPE point UNDER shape …
 CREATE TYPE line UNDER shape …

 CREATE TYPE polygon UNDER shape …

Στο παράδειγμα μας ο υπερτύπος είναι ο τύπος shape και οι υποτύποι είναι οι τύποι point, line και polygon.

==== Χρήση ====
Οι αφηρημένοι τύποι δεδομένων μπορούν να χρησιμοποιηθούν όπως και οι βασικοί τύποι της SQL. Έστω ότι ορίζουμε ένα ADT με όνομα shape ως εξής:

 CREATE TYPE shape
   (refercing_system INTEGER,
   tolerance DECIMAL(8.2),
   geometry BLOB(1M));

Με βάση τον παραπάνω τύπο μπορούμε να ορίσουμε και την σχέση:

 CREATE TABLE real_estate_info
   (address address,
   price money,
   owner char(40),
   property shape);

Η διαχείριση των στιγμιότυπων γίνεται με την κλήση των αντιστοίχων συναρτήσεων ορισμού. Χρησιμοποιούμε σαν διαχωριστή πεδίου τις δύο τελείες (dot notation). Για παράδειγμα:

 INSERT real_estate_info
 VALUES (US_DOLLAR(30000),‘Joe Doe’,spatial(10,12,15,20))
 SELECT D_mark(price), owner
 FROM real_estate_info
 WHERE overlaps(property..geometry, square (5, 5, 25, 25))

==== Δυνατότητα Αντικατάστασης (Substitutability) ====
Για να κατανοήσουμε την έννοια της δυνατότητας αντικατάστασης θα χρησιμοποιήσουμε ένα παράδειγμα. Ας υποθέσουμε την ύπαρξη της ακόλουθης σχέσης:

 CREATE TABLE real_estate_info
   (price money,
   owner CHAR (40),
   property shape);

Ακόμα, ας υποθέσουμε ότι κάνουμε τις ακόλουθες εισαγωγές:

 INSERT INTO real_estate_info VALUES 
 (US_DOLLAR(100000),‘Mr. S. White’,point(4, 4))
 INSERT INTO real_estate_info VALUES
 (CDN_DOLLAR(400000),‘Mr. W. Green’,
 poly(point(4, 4), point(10, 10), point(12, 14)))
 INSERT INTO SALES VALUES
 (S_FRANK(150000),‘Mrs. D. Black’,line(5, 5, 7, 8))

Τα δεδομένα φυλάσσονται ως εξής:

Παρατηρούμε ότι στην στήλη price εκτός από τις τιμές φυλάσσουμε και πληροφορία σχετική με την μονάδα μέτρησης. Ακόμα, αν έχουμε δηλώσει ένα πεδίο σαν τύπο Α, η τιμή του πεδίου αυτού μπορεί να είναι οποιαδήποτε στιγμιότυπο του τύπου Α ή κάποιου από τους υποτύπους του. Έτσι στο πεδίο property του τύπου shape μπορούμε να αναθέσουμε στιγμιότυπα των υποτύπων point, poly και line. Τα στοιχεία του υποτύπου βρίσκονται κατά τον χρόνο εκτέλεσης, γεγονός που απαιτεί καθυστέρηση στην αποτίμηση (late binding).

Το βασικό χαρακτηριστικό της καθυστέρησης στην αποτίμηση είναι η αυτόματη κλήση των συναρτήσεων μετατροπής κατά την εκτέλεση μιας ερώτησης.
 
Για παράδειγμα, κατά την εκτέλεση της ερώτησης

 SELECT owner, dollar_amount(price)
 FROM real_estate_info
 WHERE dollar_amount(price)<US_DOLLAR(500000);

θα κληθούν αυτόματα οι συναρτήσεις μετατροπής *US_DOLLAR, CND_DOLLAR* και
*SWISS_FRANK* ανάλογα με τον τύπο των δεδομένων της στήλης price.

==== Επώνυμοι Τύποι Γραμμής (Named Row Types) ====
Οι τύποι που έχουμε μέχρι τώρα εξετάσει αναφέρονται στον ορισμό νέων πεδίων. Υπάρχουν όμως και τύποι για την αναπαράσταση μιας ολόκληρης πλειάδας μια σχέσης -ενός συνόλου δηλαδή πεδίων. Οι τύποι αυτοί ονομάζονται επώνυμοι τύποι γραμμής (named row types). Γενικά, οι επώνυμοι τύποι γραμμής αποτελούν τύπους ορισμένους από τον χρήστη χωρίς ενθυλακωμένη εσωτερική δομή. Για παράδειγμα:

 CREATE ROW TYPE account_t
   (acctno INTEGER,
   cust REF(customer_t),
   type CHAR (1),
   opened DATE,
   rate DOUBLE PRECISION,
   balance DOUBLE PRECISION);

Χρησιμοποιώντας τους επώνυμους τύπους γραμμής μπορούμε να ορίσουμε σχέσεις. Για παράδειγμα:

 CREATE TABLE account OF account_t
   (PRIMARY KEY acctno);

==== Τύποι Αναφοράς (Reference types) ====
Οι επώνυμοι τύποι γραμμής μπορούν να συνδυαστούν με αναφορές, όπως στο πεδίο cust του τύπου γραμμής account_t. Οι τύποι αναφοράς παραπέμπουν σε δηλώσεις τύπων (στην συγκεκριμένη περίπτωση του τύπου customer_t) και χρησιμοποιούνται κυρίως για να μοντελοποιήσουν σχέσεις μεταξύ επώνυμων τύπων γραμμών.

Οι αναφορές μπορούν να έχουν εμβέλεια (scope).

 CREATE TABLE account OF account_t
   (PRIMARY KEY acctno,
   SCOPE FOR cust IS customer);

Σε μια σχέση μπορούμε να ορίσουμε αναφορές μόνο σε μεταβλητές που βρίσκονται στο πρώτο επίπεδο (π.χ. cust). Επιπλέον μπορούμε να χρησιμοποιούμε τους τύπους αναφοράς για να εκφράσουμε ερωτήσεις:

 SELECT a.acctno, a.cust->name
 FROM account a
 WHERE a.cust->address..city = “Hollywood”
 AND a.balance > 1000000;

==== Υποτύποι και κληρονομικότητα ====
Ένας επώνυμος τύπος γραμμής μπορεί να δηλωθεί σαν υπερτύπος από έναν ή περισσότερους επώνυμους τύπους γραμμής. Οι υποτύποι κληρονομούν τις μεταβλητές και τις συναρτήσεις από τους υπερτύπους τους.

Έστω ότι ορίζουμε ένα τύπο γραμμής για να αναπαραστήσουμε εργαζόμενους.

 CREATE TYPE empoloyee
   (name CHAR (20), salary DECIMAL (10,2))

Βασισμένοι στον τύπο αυτό ορίζουμε δυο νέους για τους προϊστάμενους και τους φοιτητές που εργάζονται το καλοκαίρι.

 CREATE TYPE manager UNDER employee
   (bonus DECIMAL (10,2));
 CREATE TYPE summer_stundent UNDER employee
   (school VARCHAR (30));

Χρησιμοποιώντας τύπους και υποτύπους μπορούμε να ορίσουμε ιεραρχίες σε σχέσεις.

Έστω:

 CREATE TABLE employees OF employee;
 CREATE TABLE managers OF manager UNDER employees;
 CREATE TABLE summer_students OF summer_student
   UNDER employees;

Πρακτικά, ιεραρχία στις σχέσεις σημαίνει ότι αν εκφράσουμε ερώτηση που αφορά μια δεδομένη σχέση, θα αναζητηθούν απαντήσεις και σε όλες τις σχέσεις που κληρονομούν από αυτήν. Έτσι, απευθύνοντας ερώτηση στην σχέση employees αυτόματα εξετάζονται και δεδομένα από τις σχέσεις *managers* και *summer_students*.

=== Τύποι Κατηγορημάτων (Type Predicate) ===
Ας ξαναδούμε την σχέση real_estate_info.

 CREATE TABLE real_estate_info
   (price money,
   owner CHAR(40),
   property real_estate);

Είναι δυνατό μια ερώτηση, κατά τον χρόνο εκτέλεσης, να ελέγχει το είδος του τύπου που έχει ορίσει ο χρήστης:

 SELECT price, owner, property
 FROM real_estate_info
 WHERE TYPE(price) IN US_DOLLAR;

Επίσης είναι δυνατό μια ερώτηση να μετατρέψει ένα τύπο σε ένα άλλο υποτύπο του (subtype specification):

 SELECT TREAT (price AS US_DOLLAR), owner, property
 FROM real_estate_info
 WHERE TYPE (price) IN (US_DOLLAR);

=== Συναρτήσεις και Μέθοδοι ορισμένοι από τον χρήστη (User Defined Functions-Methods) ===
Ο χρήστης είναι δυνατό να ορίζει συναρτήσεις, μεθόδους και αποθηκευμένες διαδικασίες (stored procedures) βασισμένες σε κάποιο τύπο (ADTs, row types, κλπ.). Οι δηλώσεις τους γίνονται είτε σε SQL/PSM, είτε σε γλώσσες τρίτης ή τέταρτης γενιάς (3GLs ή 4GLs).

Διαχωρίζουμε τις συναρτήσεις που μπορεί ο χρήστης να ορίσει σε εξωτερικές (external) και σε εσωτερικές (internal). Οι εξωτερικές συναρτήσεις γράφονται και δηλώνονται σε μια από τις καθιερωμένες γλώσσες προγραμματισμού (ADA, C κλπ.). Οι συναρτήσεις αυτές προφανώς υπόκεινται στους περιορισμούς αλλά και εκμεταλλεύονται τις βιβλιοθήκες και την λειτουργικότητα της γλώσσας στην οποία ορίζονται. Παράλληλα, μπορούν να περιέχουν και ενσωματωμένη SQL. Αντίθετα, οι εσωτερικές συναρτήσεις είναι δηλωμένες εξ ολοκλήρου σε SQL, εφοδιασμένη με συναρτήσεις ροής (loop, case, if, for, repeat, return κτλ.) και [[Προστακτικός προγραμματισμός|ανάθεσης]] (set).

=== Συγκεντρωτικοί Τύποι (Collection Types) ===
Οι συγκεντρωτικοί τύποι αποτελούν δομές όπως σύνολα (sets), λίστες (lists), πίνακες (arrays) και πολυσύνολα (bags).

 CREATE ROW TYPE employee
   (id INTEGER,
   name VARCHAR(30),
   address address,
   manager REF (employee),
   projects SET (REF (project)),
   children LIST (REF (PERSON)),
   hobbies SET (VARCHAR (20)))*

Στις ερωτήσεις τα στιγμιότυπα των συγκεντρωτικών τύπων συμπεριφέρονται σαν σχέσεις.

 SELECT e.name
 FROM employees e
 WHERE ‘travel’ IN (SELECT *
 FROM TABLE (e.hobbies) c)
 AND 5 > (SELECT count(*) FROM TABLE (e.children) d)

Επιπρόσθετα οι πίνακες και οι λίστες υποστηρίζουν και δεικτοδότηση για πιο γρήγορη πρόσβαση.

Ας εξετάσουμε μερικά παραδείγματα. Ας υποθέσουμε ότι έχουμε ορίσει δυο σχέσεις που αφορούν εργαζόμενους και τμήματα (employees και departments αντίστοιχα) ως εξής:

 CREATE TABLE employees
   (id INTEGER PRIMARY KEY,
   name VARCHAR (30),
   address ROW (street VARCHAR (40),
   city CHAR(20),
   state CHAR (2)
   zip INTEGER,
   country VARCHAR(30),
   salary DECIMAL(10,2),
   deptno INTEGER REFERENCES departments,
   manager INTEGER RFEFERENCES employees,
   projects SET (INTEGERS),
   children LIST (person),
   hobbies SET (VARCHAR(20)));

 CREATE TABLE departments
   (deptno INTEGER PRIMARY KEY,
   manager INTEGER REFERENCES employees,
   projects TABLE (projno INTEGER),
   projname CHAR (30),
   budget DECIMAL (10,2));

#### Μετασχηματισμός συγκεντρωτικών τύπων σε πίνακες
Ερώτηση: Βρείτε όλους τους εργαζόμενους που δουλεύουν σε περισσότερα από δύο έργα.

 SELECT name
 FROM employees e
 WHERE 2 100000)
 FROM departments as d

Στο εν λόγω παράδειγμα, βλέπουμε πώς μπορούμε να έχουμε αποτέλεσμα τύπου MULTISET, αντί για τύπου SET.

Ερώτηση: Βρείτε ποια από τις διευθύνσεις addr.1_v, addr.2_v, addr.3_v είναι πιο κοντά στη διεύθυνση 123, University Avenue, Palo Alto, CA, 94301 (δεδομένης μιας Boolean συνάρτησης κοντά, (NEAR)).

 SELECT row addr
 FROM (values (addr1_v, addr2_v, addr3_v)) as addr
 WHERE near
 (row addr, row(123 University Avenue, Palo Alto, CA, 94301))

ή όμοια

 SELECT row addr
 FROM (multiset ( addr1_v, addr2_v, addr3_v)) as addr
 WHERE near
 (row addr, row(123 University Avenue, Palo Alto, CA, 94301))

Στο συγκεκριμένο παράδειγμα, μπορούμε να δούμε αφενός τη χρήση συναρτήσεων που έχει φτιάξει ο χρήστης και αφετέρου ένα φορμαλισμό για την κατασκευή συνόλων από συγκεκριμένες τιμές (μέσω της έκφρασης (values addr1_v, addr2_v, addr3_v) as addr).

## Παραπομπές


## Δείτε επίσης
* Βάση δεδομένων Zope

## Αναφορές-Βιβλιογραφία
* [At+89] M. Atkinson, F. Bancilhon, D. DeWitt, K. Dittrich, D. Maier, S. Zdonik, "The Object-Oriented Database System Manifesto", In Banchilhon et. al. (eds), Building an Object-Oriented Database System: The Story of O2,Morgan Kaufmann, 1992. Also in Proc. Int. Conf. Deductive Object Oriented Databases, Kyoto, Japan, Dec. 1989.
* [BBKV87] F. Bancilhon, T. Briggs, S. Khoshafian, P. Valduriez, "FAD, a Powerful and Simple Database Language", Proceedings of the 13th VLDB Conference, Brighton 1987.
* [Ca94] R. G. G. Cattell (edt), "The Object Database Standard: ODMG-93, Release 1.1", Morgan Kaufmann Publishers, Inc., 1994.
* [Ca95] R. G. G. Cattell (edt), "The Object Database Standard: ODMG-93, Release 1.2", Morgan Kaufmann Publishers, Inc., 1995.
* [CK86] G. Copeland, S. Khoshafian, "Identity and Versions for Complex Objects", "1986 International Workshop on Object-Oriented Database Systems", September 1986, Pacific Grove, California.
* [Di93] K. Dittrich, "Object-Oriented Data Model Concepts", NATA ASI OODBS 1993.
* [Kh93] S. Khoshafian, "Object-Oriented Databases", John Willey and Sons, 1993.
* [Ki91] M. Kifer, "A First Order Formalization of Object-Oriented Languages", IEEE Data Engineering Bulletin, June 1991, Vol. 14, No. 2.
* [Ki94] W. Kim, “Observations on the ODMG-93 Proposal for an Object-Oriented Database Language”, SIGMOD RECORD, Vol 23, No. 3, March 1994.
* [KMN97] K. Kulkarni, N. Mattos, A. K. Nori, “Object-Relational Database Systems - Principles, Products and Challenges” Tutorials of 23rd Int’l VLDB Conference, Athens, Greece, 1997
* [Mai89] D. Maier, "Why Isn't There an Object-Oriented Data Model?", Technical Report CS/E-89-002, 2 May 1989, Computer Science and Enginnering, Oregon Graduate Center.
* [MM96] J. Melton, N. Mattos, “An overview of SQL3 - the Emerging New Generation of the SQL Standard”, Tutorials of 22nd Int’l VLDB Conference, Mumbai, India, 1996
* [ODMG94] Object Database Management Group, "Response to the ODMG-93 Commentary Written by Dr. Won Kim of UniSQL, Inc.", SIGMOD RECORD, Vol 23, No. 3, September 1994

Κατηγορία:Βάσεις δεδομένων
Κατηγορία:Αντικειμενοστρεφής προγραμματισμός