170 likes | 282 Views
Bazy danych i inżynieria oprogramowania. Wykład 12: Wprowadzenie do standardu ODMG, część 6: Wiązanie do C++. Kazimierz Subieta Instytut Podstaw Informatyki PAN, Warszawa Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa. ODMG 2.0: Wiązanie do C++ - charakterystyka.
E N D
Bazy danych i inżynieria oprogramowania Wykład 12: Wprowadzenie do standardu ODMG, część 6: Wiązanie do C++ Kazimierz Subieta Instytut Podstaw Informatyki PAN, Warszawa Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa
ODMG 2.0: Wiązanie do C++ - charakterystyka Standardowy język C++, + ODL/OML (Object Manipulation Language) • Zunifikowany system typów zarówno dla C++ jak i dla bazy danych • Rozszerza C++ poprzez przeładowywanie operatorów • ODL/OML respektuje składnię i semantykę języka bazowego • Rozszerza system klas języka C++ o klasy obiektów trwałych Koncepcja “sprytnych” wskaźników (smart pointers): każda klasa trwała T ma podporządkowaną klasę d_Ref<T> zawierającą wskaźniki do obiektów klasy T , które działają jak normalne wskaźniki C++. OML: zestaw metod do tworzenia, usuwania, modyfikacji, tworzenia referencji , obsługi związków, itp. Identyczne traktowanie trwałych i tymczasowych obiektów (ale zapytania i transakcje stosuje się tylko do obiektów trwałych). OML: zestaw metod do obsługi kolekcji (zbiorów, wielo-zbiorów, list, tablic), dość niskiego poziomu w porównaniu z językami zapytań Luźne powiązanie OQL z C++ (takie samo jak SQL z językiem programowania); zapytania są traktowane jako ciągi znaków w programie C++, ze wszystkimi znanymi wadami tego rozwiązania (impedance mismatch)
Co to jest “niezgodność impedancji”? Zespół chorobowo-paranoidalny powstający w wyniku eklektycznego, formalnego połaczenia języka zapytań z językiem programowania, np. SQL+C. Świat komercyjny godzi się z tą paranoją; ba, uważa ją za “osiągnięcie” technologii relacyjnej. Typowe objawy: • Niezgodność składni: programista ma do czynienia z dwoma stylami • Niezgodność paradygmatów języków i ich semantyki • Niezgodność pragmatyki użycia i stylu myślenia programisty • Niezgodność faz i mechanizmów wiązania (wczesne vs. późne) • Niezgodność przestrzeni nazw i reguł zakresu (m.in. trudności z rekursją) • Niezgodność schematów iteracyjnych • Niezgodność systemu typów (SQL nie podlega statycznej kontroli typów) • Niezgodność w zakresie traktowania cechy trwałości danych • Niezgodność w zakresie środków programowania ogólnego (generic) • Niezgodność w zakresie metod transmisji parametrów Leczenie: • Odrzucenie fałszywych hura-optymistycznych komercyjnych stereotypów • Budowa pełnego języka programowania bezszwowo zintegrowanego z językiem zapytań • Budowa bramek z języka zapytań do języka programowania (a nie odwrotnie) Mimo ideologicznych deklaracji, ODMG nie rusza tego problemu...
Założenia projektowe wiązania do C++ Zunifikowany system typów dla trwałych i ulotnych danych. (K.S. Niestety, w przypadku ODL i C++ pełna unifikacja jest niemożliwa, np. ze względu na kolekcje i związki.) Wiązanie do specyficznego języka programowania uwzględnia jego składnię i semantykę. (K.S. Bzdurna tautologia, w języku programowania nie da się zapisać nic, co wykracza poza jego składnię i semantykę.) Specjalne klasy, których wystąpienia mogą być zarówno trwałe jak i ulotne. Koncepcja “sprytnych wskaźników”(smart pointers) , które można deklarować dla każdej takiej klasy: dla klasy/typu T, typ sprytnego wskaźnika jest d_Ref<T> d_Ref<Profesor> profWsk; d_Ref<Wydział> wydzRef; ... profWsk -> promuje(“Maciej Kret”); wydzRef = profWsk ->pracuje_na;
Podstawowa architektura wiązania Preprocesor C++ ODL (rozwinięcie makrosów) Deklaracje w ODL Wygenerowane pliki nagłówkowe C++ (.h) i inne pliki źródłowe Pliki źródłowe w C++ i pliki nagłówkowe napisane przez użytkownika z użyciem OML Metadane ODBMS Kompilator C++ Pliki runtime OSZBD Pliki do konsolidacji (object code) Baza danych Konsolidator (linker) Wykonywalna aplikacja Runtime OSZBD
Odwzorowanie elementów modelu ODMG na C++ Typy obiektów i literali odwzorowują się na klasy C++. Zagnieżdżony obiekt jest traktowany jako literal. Struktura ODMG odwzorowuje się na struct lub class w C++ Generatory typów kolekcji (set, bag, list,...) są odwzorowane jako klasy szablonowe (template classes) w C++. Typy kolekcji są reprezentowane jako klasy kolekcji; podobnie dla wystąpień. template <class T> class <d_Set> : public d_Collection<T> {...}; class Statek{...} d_Set<d_Ref<Statek>> Linia_Indyjska; d_Set<T> jest klasą szablonową dla zbiorów d_Set<d_Ref<Statek>> jest klasa dla zbioru statków Linia_Indyjska jest konkretną kolekcją (referencji). Tylko maniak C++ może twierdzić, że podane notacje są prościutkie...
Odwzorowanie elementów modelu ODMG na C++ Nazwane operacje modelu obiektowego są odwzorowane na funkcje członkowskie C++ Dla pewnych operacji wiązanie do C++ daje alternatywne formy, z nazwą funkcji i z operatorem infixowym; np. d_Set::union_with ma również formę +=. Operacje zwracające wartości boolowskie są odwzorowane w funkcje zwracajace int. Operacje create i delete są odwzorowane jako konstruktory i destruktory C++. Listy i tablice sa odwzorowane na d_Varray (tablicę o zmiennej długości). Związki nie są bezpośrednio podtrzymywane przez C++. Zamiast tego, ODMG przewiduje specyficzne klasy szblonowe pozwalające na podwzorowanie związków. Związek jest zaimplementowany poprzez wskaźniki. Ekstensje i klucze nie są odwzorowywane. Nie można używać wielu nazw dla obiektu. Nie są odwzorowane funkcje administracyjne takie jak tworzenie BD lub indeksu. Wyjątki są obsługiwane poprzez standardowy mechanizm wyjątków C++.
C++ ODL ODL zapisany w skladni C++ extern const char _profesorowie[ ]; extern const char _opiekun[ ]; class Profesor : public d_Object { public: //własności: d_UShort wiek; d_UShort nr_ident; d_String nr_pokoju; d_String nazwisko; d_Rel_Ref<Wydział, _profesorowie> wydz; d_Rel_Set<Student, _opiekun> doradza; //operacje: void promuje(); void ustala_Kurs( Kurs & ); private: ... }; const char _profesorowie [ ] = “profesorowie”; const char _opiekun[ ] = “opiekun”; Nazwa, zapisana jako ciąg znaków, ustalająca powiązanie odwrotne. Przesunięcie nazwy do pierwszej kategorii obywatelstwa, z fatalnymi skutkami dla mocnego typowania. d_Rel_Ref - pojedynczy wskaźnik d_Rel_Set - zbiór wskaźników d_Rel_List - lista wskaźników
Jednokierunkowe związki Możliwe jest zadeklarowanie związku “zdegenerowanego”, prowadzącego tylko w jednym kierunku. Związek taki niczym nie różni się od wskaźnika. K.S. Aplikacja jest odpowiedzialna za spójne traktowanie takiego związku, tj. nie przewiduje się środków obrony przed zwisającymi wskaźnikami. struct Odpowiedzialny { d_String dział; d_Ref<Pracownik> p; d_Date od_kiedy; }; Wskaźnik/referencja do obiektu Pracownik class Zamówienie { public: d_Set<d_Ref<Klient>> kto; d_String co; Odpowiedzialnykontakt; }; Zbiór wskaźnikow/referencji do obiektów Klient
C++ OML (1) Object Manipulation Language Założenie: o ile to możliwe, składnia operacji na trwałych obiektach powinna być taka sama, jak składnia operacji na obiektach ulotnych. K.S. Jak przyznaja sami autorzy ODMG, to załozenie “na razie” nie jest spełnione. A przecież wszyscy wiedzą, najbardziej trwałe są prowizorki... Obiekty mogą być tworzone (operator new), usuwane i modyfikowane. 1. 2. 3. void * operator new(size_t size); void * operator new(size_t size, const d_Ref_Any &clustering, const char * typename ); void * operator new(size_t size, d_Database *database, const char * typename ); 2 i 3 tworzą trwałe obiekty. Parametr “clustering”: obiekt jest tworzony “blisko” innego obiektu. Parametr “size”: przewidywany rozmiar reprezentacji obiektu (automatycznie wyznaczany z deklaracji klasy przez specjalna funkcję). Parametr “typename”: określa typ tworzonego obiektu (K.S. poprzez nazwę typu przekazywaną jako string, ze wszystkimi negatwnymi skutkami dla mocnego typowania) obj_ref . delete_object(); Usunięcie obiektu o zadanej referencji obj_ref.
C++ OML (2) obj-ref . mark_modified(); Zaznaczenie, że dany obiekt był zmodyfikowany. Pominięcie tej operacji spowoduje, że modyfikacje nie zostaną zapisane do bazy danych. W wielu przypadkach uzycie tej instrukcji nie jest potrzebne, ale czasami jest konieczne. K.S. Okropne... tryumf przesadnej troski o wydajność nad koncepcją i niezawodnością. Nazwy obiektów w bazie danych tworzą jedną płaska przestrzeń. Specjalne funkcje C++ do wyszukiwania obiektów zgodnie z ich nazwami. Operacje na atrybutach - standardowe C++. profesor -> nr_ident = następny_id; Podstawienie; konieczne jest mark_modified. Zgodnie z konwencja ODMG, zagnieżdżone obiekty są traktowane jak atrybuty.
Związki extern const char _ra[ ], _rb[ ]; class A {... d_Rel_Ref<B, _ra> rb; ...}; class B {... d_rel_Ref<A, _rb> ra; ...}; const char _ra[] = “ra”; const char _rb[] = “rb”; a b rb ra Na razie obiekty a i b nie są powiązane. a b Po takim podstawieniu powstaje związek oraz jego “bliźniak” a.rb = &b; rb ra bb Referencja z a prowadzi do bb, ale automatycznie przestawiony zostaje także “bliźniak” ra a.rb = &bb; a b rb ra Obydwie referencje znikają, sytuacja wraca do poczatkowej. a.rb.clear(); Sprawa się nieco komplikuje dla powiązań 1:n i m:n
Klasy do obsługi kolekcji Szereg operatorów, zapisanych wojskowym szyfrem C++, których przeznaczeniem jest umożliwienie dowolnych zleceń dotyczących kolekcji. Przykłady: template <class T> class d_Collection : public d_Object { public ... friend int operator ==( const d_Collection<T> &cL, const d_Collection<T> &cR ); ... unsigned long cardinality() const; int is_empty() const; ... void insert_element( const T &elem); void remove_element( const T &elem); .... const T & select_element(const char *OQL_predicate) const; ... };
C++ OQL Generalna zasada: zapytania w OQL sa traktowane jako stringi przez pewien zestaw funkcji C++. K.S. Tego rodzaju załozenie musi implikować niezgodność impedancji. Optymalizacja zapytań jest niemożliwa podczas kompilacji; musi być przesunięta do fazy wykonania. template <class T> voidd_oql_execute(d_OQL_Query &query, T &result ); Funkcja umożliwiająca wykonanie zapytania komunikowanego jako string. Ciąg znaków reprezentuający zapytanie w OQL może byc parametryzowany; parametry są poprzedzane znakiem $: d_OQL_Query q1( “select p.nazwisko from Pracownik as p where p.zarobek > $1 and p.zawód = $2”); ... q1 << 10000 << “referent”; d_oql_execute(q1, BogaciReferenci); W nieco bardziej skomplikowanych sytuacjach sformułowanie zapytania z parametrami staje się bardzo skomplikowane.
ODMG 2.0: przykład w C++ d_Long, d_String, d_Ref,... typy trwałe z bazy danych class Profesor : Pracownik { d_Long pesel; d_String nazwisko; d_Short wiek; d_Ref <Wydział> pracuje_w; d_Rel_Ref<Wykład> prowadzi; .... void wystawia_ocene(...); void odwołuje_wykład(...); } .... d_Ref <Profesor> prof; .... prof -> nazwisko = “Nowak“; prof->wiek = 41; prof->wiek = prof->wiek + 1; prof->wystawia_ocene(...); d_Rel_Ref zbiór wskaźników trwałych
ODMG-93 C++: Schowek aplikacji Środowisko bazy danych deaktywacja deaktywacja aktywacja aktywacja Schowek aplikacji (pamięć operacyjna) mark_modified() konstruktor destruktor Czas
Związki ze środowiskiem OMG ORB Klient Klient Istniejące dokumenty OMG nie przesądzają, jak obiektowe bazy danych mają być uwzględnione w środowisku OMG. ORB (Object Request Broker) (pośrednik w dostarczniu obiektów ) • Kluczowe tematy: • Wydajność • Rozproszenie i heterogeniczność • OSZDB jako zarządca obiektów • Wspólny skład obiektów • OSZBD jako użytkownik ORB-a ODA (Object Database Adaptor) BOA (BasicObject Adaptor) LOA (Library Object Adaptor) OSZBD RPC dla dowolnego odwołania do obiektu (wolne) RPC dla pierwszego odwołania, utworzenie bezpośredniego wiązania do obiektu (szybkie)