Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 1 kwiecień 2002 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła.

Podobne prezentacje


Prezentacja na temat: "© K.Subieta. Obiektowe języki zapytań 6..10, Folia 1 kwiecień 2002 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła."— Zapis prezentacji:

1 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 1 kwiecień 2002 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa Instytut Podstaw Informatyki PAN, Warszawa Wykłady 6..10

2 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 2 kwiecień 2002 Plan wykładów SBQL - składnia SBQL - stos rezultatów SBQL - procedura eval, zapytania elementarne i operatory algebraiczne SBQL - operatory nie-algebraiczne Rozszerzenie SBQL dla modeli M1, M2 i M3 (klas i dziedziczenia, dynamicznych ról, list eksportowych) Konstrukcje imperatywne bazujące na SBQL Perspektywy bazujące na SBQL

3 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 3 kwiecień 2002 Wykład 6

4 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 4 kwiecień 2002 Język SBQL (Stack-Based Query Language)

5 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 5 kwiecień 2002 Generalne własności SBQL Język SBQL jest sformalizowanym obiektowym językiem zapytań w stylu SQL lub OQL. Posiada semantyczne odpowiedniki podstawowych konstrukcji tych języków. Może być zdefiniowany (uściślony) dla wielu modeli składu, w szczególności dla modeli M0 - M3. W odróżnieniu od relacyjnych i obiektowych algebr, rachunków, logik i innych tego rodzaju koncepcji, definicja SBQL bazuje na pojęciu stanu, którego składnikami są skład obiektów oraz stos środowisk. SBQL będziemy uważać za wzorzec teoretyczny podobny do algebry relacji (stanowiącej podstawę wielu rozważań dotyczących modelu relacyjnego). SBQL jest jednak nieporównywalnie bardziej uniwersalny i konsekwentny niż dowolna tego rodzaju algebra, włączając tzw. algebry obiektowe. Będziemy starali się wykazać, że: Języki zapytań mogą zawierać operatory nie-algebraiczne, których odwzorowanie w dowolną algebrę jest niemożliwe bez wprowadzenia poważnych ograniczeń koncepcyjnych.

6 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 6 kwiecień 2002 Składnia SBQL (1) Przyjmiemy, że niektóre elementy wprowadzonego poprzednio zbioru V mają reprezentację zewnętrzną, która pozwala zapisać ten element w zapytaniu w postaci ciągu bajtów. Wiele elementów zbioru V, takich jak grafika, skompilowane procedury, itd. nie posiada reprezentacji zewnętrznej. Zwykle zewnętrzny reprezentant elementu zbioru V jest zwany w językach programowania literalem; nazwa ta została użyta w niewłaściwym znaczeniu w standardzie ODMG. Niedobrym terminem jest stała, gdyż następuje tu kolizja znaczeniowa z niemodyfikowalnym elementem składu obiektów. Wracamy do właściwych znaczeń terminów literal i stała. Terminologię ODMG odrzucamy. Zbiór literali będziemy oznaczać L. Będziemy zakładać, że istnieje prosta i jednoznaczna funkcja odwzorowująca element zbioru L w element zbioru V. Identyfikatory należące do zbioru I nie mają odpowiadających im literali.

7 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 7 kwiecień 2002 Składnia SBQL (2) Jedyną możliwością odwołania się do obiektów znajdujących się w składzie obiektów będzie użycie ich zewnętrznej nazwy należącej do zbioru N. Przyjmiemy, że każdy element zbioru N może być użyty w zapytaniu. Dowolny literal jest zapytaniem; np. 2, 3.14, Kowalski Dowolny element zbioru N jest zapytaniem; np. Osoba, Student, zarobek, wiek. Zapytania można łączyć w większe zapytania przy pomocy operatorów. Wykorzystamy tu typowy zestaw operatorów występujących w znanych językach zapytań, np. w SQL. Musimy przy tym rozróżniać leksykalną reprezentację operatora i sam operator, podobnie jak w przypadku rozróżnienia pomiędzy zbiorami L i V. Np. element leksykalny sum jest ciągiem trzech znaków, który oznacza sumującą funkcję zagregowaną. Operatory będą podzielone na unarne i binarne, oraz algebraiczne i nie-algebraiczne.

8 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 8 kwiecień 2002 Składnia SBQL (3) Jeżeli jest oznaczeniem operatora algebraicznego unarnego, zaś q jest zapytaniem, wówczas ( q ) jest zapytaniem. Przykładami operatorów algebraicznych unarnych są: count, sum, avg, log, -, sin, sqrt, not, itd. W niektórych sytuacjach, np. dla operatorów - oraz not, będziemy pomijać nawiasy, o ile nie doprowadzi to do niejednoznaczności. Jeżeli jest oznaczeniem operatora algebraicznego binarnego, zaś q 1 i q 2 są zapytaniami, wówczas q 1 q 2 jest zapytaniem. Przykładami operatorów algebraicznych binarnych są: =, +, -, *, /,, and, or, union, itd. Przecinek jest operatorem algebraicznym - konstruktorem struktur i kolekcji. Jeżeli jest oznaczeniem operatora nie-algebraicznego, zaś q 1 i q 2 są zapytaniami, wówczas q 1 q 2 jest zapytaniem. Przykładami operatorów nie-algebraicznych są: selekcja (where), projekcja lub nawigacja (.), zależne złączenie ( ), kwantyfikatory, itd. Dla kwantyfikatorów zastosujemy tradycyjną składnię q 1 ( q 2 ) oraz q 1 ( q 2 ); jest ona równoważna podanej wyżej uniwersalnej składni q 1 q 2 i q 1 q 2

9 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 9 kwiecień 2002 Składnia SBQL (4) Jeżeli q jest zapytaniem, zaś n N, wówczas q as n jest zapytaniem. Operator as jest unarnym operatorem algebraicznym parametryzowanym nazwą n. Operator ten będziemy wykorzystywać w większości sytuacji wymagających zdefiniowania pomocniczej nazwy. Jeżeli q jest zapytaniem, zaś n N, wówczas q group as n jest zapytaniem. Operator group as jest podobny do as, o nieco innej semantyce. Jeżeli q jest zapytaniem, to (q) jest zapytaniem. Jeżeli n N jest nazwą procedury, funkcji, lub metody posiadającej k parametrów, zaś q 1, q 2,..., q k są zapytaniami, wówczas n(q 1 ; q 2 ;..., q k ) jest zapytaniem. Jeżeli n N jest nazwą procedury, funkcji, lub metody nie posiadającej parametrów, wówczas n() oraz n są zapytaniami. Zapytania będą podlegać ograniczeniom typologicznym, które najczęściej będą tutaj zakładane implicite.

10 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 10 kwiecień 2002 Przykładowe zapytania 2000 "Kowalski" zarobek Osoba 2+2 zarobek > 2000 Osoba where (zarobek > 2000) (Osoba where (wiek() > 30)). (zarobek + x /y) ((Osoba as p) (p.pracuje_w.Dział as d)). (p.nazwisko, d.nazwa) Osoba (wiek < 65) Dział where ( (zatrudnia.Osoba) as p (p.wiek() < 17)) (((Osoba as p) (p.pracuje_w.Dział as d)) where (p.Nazwisko = "Nowak" and d.Nazwa = "Kontrola")). (p.nazwisko, d.nazwa)

11 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 11 kwiecień 2002 Podsumowanie składni SBQL zapytanie ::= L zapytanie ::= N zapytanie ::= operUna zapytanie zapytanie ::= operUna ( zapytanie ) zapytanie ::= zapytanie operBin zapytanie zapytanie ::= zapytanie operNieAlg zapytanie operNieAlg ::= where |.| | | zapytanie ::= zapytanie ( zapytanie ) zapytanie ::= zapytanie as N zapytanie ::= zapytanie group as N zapytanie ::= ( zapytanie ) zapytanie ::= N ( ) zapytanie ::= N ( parametr {; parametr} ) parametr ::= zapytanie L V jest zbiorem literali N jest zbiorem nazw operUna jest operatorem algebraicznym unarnym operBin jest operatorem algebraicznym binarnym operNieAlg jest operatorem nie-algebraicznym Możliwe są dalsze operatory nie-algebraiczne Meta-nawiasy {} oznaczają iterację od 0

12 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 12 kwiecień 2002 Drzewa syntaktyczne zapytań Jest to struktura danych, która powstaje jako rezultat rozbioru gramatycznego zapytania. Jest podstawą działania procedury eval wyznaczania rezultatu zapytania. Może być przedtem poddane przekształceniom mającym na celu optymalizację zapytania. Np. drzewo syntaktyczne zapytania: Osoba where Nazwisko = Nowak Zapytanie Operator algebraiczny = Nazwa Osoba Nazwa Nazwisko Reprezentant Nowak Operator nie-algebraiczny where Zapytanie

13 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 13 kwiecień 2002 Stos rezultatów zapytań (QRES) Wszelkie pośrednie i końcowe rezultaty zapytań (wyrażeń) będą odkładane na stosie rezultatów QRES (Query REsult Stack). Stos rezultatów jest uogólnieniem stosu arytmetycznego spotykanego w implementacji języków programowania. Dość często osoby mało wyrobione w semantyce języków programowania plączą stos środowisk ze stosem rezultatów. Są to różne stosy, o odmiennej budowie, operacjach i przeznaczeniu. W SBA zajmujemy się obydwoma stosami. Elementami stosu będą rezultaty zapytań (elementy zbioru Rezultat) zdefiniowane poprzednio; Stos będzie przechowywał także wszelkie pomocnicze elementy niezbędne do obliczania zapytań; w szczególności, liczniki pętli iteracyjnych implikowanych przez operatory działające na kolekcjach. Elementy te nie będą uwzględniane w opisie formalnej semantyki. Stos rezultatów jest strukturą danych przechowywaną w pamięci operacyjnej. Zmienia się w trakcie obliczeń.

14 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 14 kwiecień 2002 Przykład działania stosu rezultatów (2 *((5 + 3 ) / 4)) / * 1 - WyrażenieOdwrotna notacja polska pusty / * -

15 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 15 kwiecień 2002 Dlaczego wprowadzamy stos QRES? QRES nie będzie przez nas uważany za składową pojęcia stanu. Dla sformułowania semantyki stos QRES ma znaczenie drugorzędne. W niektórych sformułowaniach tej semantyki (np. w semantyce denotacyjnej) QRES jest w ogóle zbędny. Jest również zbędny, jeżeli semantykę zaimplementujemy poprzez zestaw rekurencyjnych procedur. Stos QRES jest wygodny przy podejściu operacyjnym do semantyki. Doświadczenie pokazuje, że inne podejścia (np. denotacyjne) są za trudne; Stos ten uzupełnia koncepcję abstrakcyjnej implementacji, która jest zaletą podejścia stosowego. Dzięki temu nasze rozważania teoretyczne można dość łatwo zaimplementować; Stos rezultatów jest skojarzony z jego statycznym odpowiednikiem funkcjonującym podczas statycznej analizy zapytania (kompilacji). Statyczny stos rezultatów jest niezbędnym elementem optymalizatora zapytań.

16 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 16 kwiecień 2002 Operatory działające na stosie QRES Stos QRES jest abstrakcyjną strukturą danych obsługiwaną przez cztery operatory: push (włóż nowy element na wierzchołek stosu), pop (zdejmij jeden element z wierzchołka stosu), top (odczytaj wierzchołek stosu), empty (sprawdź czy stos jest pusty). Operacje na stosie odbywają się zawsze na jego wierzchołku (uwzględniają jeden lub dwa wierzchołkowe elementy). Pozostałe elementy stosu staną się widoczne dopiero wtedy, gdy zdejmiemy odpowiednią liczbę elementów z jego wierzchołka.

17 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 17 kwiecień i 17 struct{ x(i 61 ), y(i 93 ) } bag{ struct{ n("Nowak"), s(i 9 )}, struct{ n("Stec"), s(i 14 )}, struct{ n("Mikuła" ), s(i 18 )}} Przykład zawartości stosu QRES dół stosu wierzchołek stosu - jedyny widoczny element niewidoczne elementy stosu

18 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 18 kwiecień 2002 Ogólna architektura elementów semantyki Skład obiektów Obiekty trwałe Obiekty ulotne Stos środowisk ENVS Stos rezultatów QRES Ewaluacja zapytań Operatory niealgebraiczne referencje do obiektów referencje do obiektów

19 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 19 kwiecień 2002 Procedura ewaluacji zapytań eval ( eval uation) Semantyka SBQL będzie zdefiniowana poprzez procedurę eval. Argumentem procedury eval jest dowolne zapytanie, zaś wynikiem procedury jest rezultat tego zapytania włożony na wierzchołek QRES. Procedura eval jest realizacją omawianej wcześniej zasady modularności lub kompozycyjności języka. Jest rekurencyjna, wywołuje sama siebie dla podzapytań danego zapytania. Procedura eval będzie korzystać ze składu obiektów, ENVS oraz QRES. Dla zapytań bez efektów ubocznych przyjmiemy następujące założenia: Procedura eval nie zmienia stanu składu obiektów; Procedura eval w trakcie ewaluacji zapytania q może zmieniać stan ENVS, ale po zakończeniu ewaluacji q stan ten będzie taki sam, jak na początku. Procedura eval w trakcie ewaluacji zapytania q nie zmienia tej części QRES, którą zastała w momencie rozpoczęcia ewaluacji. Semantyka będzie sterowana abstrakcyjną składnią. Procedura eval jest wspomagana przez analizator gramatyczny (parser).

20 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 20 kwiecień 2002 poprzedni stan QRES eval( q ) rezultat zapytania q poprzedni stan QRES Działanie procedury eval Rezultaty zapytań zapisane na QRES są konsumowane przez operatory języka, dla których zapytania były parametrami. Takim operatorem może być print lub operator SQL delete oznaczający usunięcie danych, np.: delete Osoba where Nazwisko = Nowak; Wykonanie tego polecenia oznacza ewaluację przez procedurę eval zapytania Osoba where Nazwisko = Nowak, w wyniku czego na wierzchołku QRES pojawi się referencja do obiektu Nowaka. Ten rezultat zostanie skonsumowany przez operator delete, który następnie usunie go ze stosu QRES. Po zakończeniu kompletu operacji QRES pozostanie taki sam, jak na początku. Na koniec wszystkich obliczeń QRES będzie pusty.

21 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 21 kwiecień 2002 Wynik procedury eval dla elementarnych zapytań Jeżeli zapytanie jest literalem l L, to procedura eval wkłada odpowiadającą mu wartość atomową l V na wierzchołek QRES. Jeżeli zapytanie jest nazwą n N, to procedura eval dokonuje wiązania tej nazwy na ENVS (funkcja bind), a następnie wynik tego wiązania wkłada na wierzchołek stosu QRES. procedure eval( q : zapytanie ) begin parse( q ); (* rozbiór gramatyczny *) case q jest rozpoznane jako l L : push( QRES, l ); case q jest rozpoznane jako n N : push( QRES, bind( n ) ); case end;

22 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 22 kwiecień 2002 Operatory algebraiczne i nie-algebraiczne Operatory łączące zapytania będziemy dzielić na algebraiczne i nie- algebraiczne. Istotą podejścia stosowego są operatory nie-algebraiczne. Fundamentalna różnica pomiędzy operatorami algebraicznymi i nie- algebraicznymi polega na ich stosunku do stosu środowisk ENVS. Operatory algebraiczne nie używają ENVS: działanie takiego operatora dotyczy wyłącznie stosu QRES (z reguły jednego lub dwóch wierzchołkowych elementów). Operatory nie-algebraiczne, oprócz działań na QRES, bezpośrednio odwołują się do konstrukcji i operacji zachodzących na ENVS.

23 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 23 kwiecień 2002 SBQL - operatory algebraiczne

24 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 24 kwiecień 2002 Operatory algebraiczne Cechą dowolnej algebry jest m.in. to, że w wyrażeniu x 1 x 2 (gdzie jest operatorem algebry) kolejność ewaluacji argumentów x 1 oraz x 2 tego operatora nie ma znaczenia. Jest to zasadnicza różnica w stosunku do operatorów nie-algebraicznych. W matematycznym (denotacyjnym) sformułowaniu wynik zapytań ( q 1 ) oraz q 1 q 2 można zapisać jako: wynik( ( q 1 ) ) = ( wynik( q 1 ) ) jest implementacją wynik( q 1 q 2 ) = wynik( q 1 ) wynik( q 2 ) Funkcja wynik jest parametryzowana stanem, ale jej definicja nie odwołuje się do tego stanu bezpośrednio.

25 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 25 kwiecień 2002 Funkcja eval dla operatorów algebraicznych procedure eval( q : zapytanie ) begin..... case q jest rozpoznane jako ( q 1 ) lub q 1 : begin wynik_q1: Rezultat; (* lokalna zmienna typu Rezultat *) eval( q 1 ); (* rezultat q 1 na wierzchołku stosu QRES *) wynik_q1 := top( QRES ); pop( QRES ); push( QRES, wynik_q1 ); end; case q jest rozpoznane jako q 1 q 2 : begin wynik_q1, wynik_q2: Rezultat; (* lokalne zmienne *) eval( q 1 ); (* rezultat q 1 na wierzchołku stosu QRES *) eval( q 2 ); (* rezultat q 2 na wierzchołku stosu QRES *) wynik_q2 := top( QRES ); pop( QRES ); wynik_q1 := top( QRES ); pop( QRES ); push( QRES, wynik_q1 wynik_q2 ); end; case end;

26 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 26 kwiecień 2002 Rodzaje operatorów algebraicznych - ogólnie Języki zapytań wprowadzają wiele operatorów algebraicznych. Granica pomiędzy operatorami wbudowanymi w dany język, a operatorami dobudowanymi na wierzchołku języka jest rozmyta. Liczba operatorów wbudowanych powinna być minimalna. Prawie wszystkie powinny wchodzić w skład bibliotek, które nie należą do definicji języka, ale raczej uzupełniają pewien jego aspekt lub dziedzinę zastosowań. Może być duża liczba operatorów bibliotecznych przywiązanych do specyficznych dziedzin zastosowań, np. operatory obsługujące hurtownie danych, systemy geograficzne, systemy temporalne, systemy przestrzenne, systemy oparte o XML, systemy przetwarzania języka naturalnego, itd. Nas będą interesować głównie operatory generyczne, niezależne od dziedziny zastosowań. Nie będziemy jednak przesądzać, które operatory algebraiczne należą do SBQL, a które nie należą. Przyjmiemy, że do SBQL teoretycznie należy dowolny operator algebraiczny, który jest potrzebny i implementowalny. Jeżeli zaimplementowano 100 operatorów algebraicznych, to implementacja 101-szego jest zazwyczaj bardzo prosta.

27 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 27 kwiecień 2002 Rodzaje operatorów algebraicznych (1) Generyczny operator porównania na równość, oznaczany zwykle =, i operator odwrotny oznaczany. Np. Nazwisko = Kowalski, x = y, Zarobek 2000, itd. Operatory te są zwykle zdefiniowane dla wszystkich typów wprowadzanych w danym języku. Porównania i operatory dotyczące liczba całkowitych i rzeczywistych:,, +, -, *, /. Np. Zarobek < 3000, 2+2, -(głebokosc + x), itd. Funkcje liczbowe: część całkowita liczby, zaokrąglenie liczby, wartość bezwzględna liczby, sinus, kosinus, tangens, cotangens, logarytm dziesiętny, logarytm naturalny, funkcja wykładnicza, pierwiastek kwadratowy, itd.; Np. sqrt( x 2 + y 2), sin(x+45), itd; Porównania, operatory i funkcje na stringach znaków: porównanie na porządek leksykograficzny stringów, zawieranie się stringów, obcięcie stringów, konkatenacja stringów, zamiana wszystkich liter na wersaliki i odwrotnie, określenie długości stringu, itd. Porównanie, operatory i funkcje na datach i czasie godzinowym: porównanie dat, porównanie czasu, zmiana czasu na liczbę sekund, itd.

28 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 28 kwiecień 2002 Rodzaje operatorów algebraicznych (2) Funkcje arytmetyczne zagregowane: sum (suma liczb), avg (średnia), min (liczba minimalna), max (liczba maksymalna), itd. Argumentem takiej funkcji jest kolekcja liczb, zaś wynikiem - pojedyncza liczba. W SQL funkcje te nie są ortogonalne (niezależne), gdyż są związane z operatorem group by. Jest to konsekwencja wadliwej koncepcji. W naszym ujęcie takie związanie jest zbędne. Przykłady: sum( Pracownik.zarobek ), avg( bag(25, 43, 47, 11) ). Funkcja zliczająca liczbę elementów w kolekcji (w SQL - count), funkcja usuwająca duplikaty z kolekcji (w SQL - distinct), funkcja sprawdzająca, czy kolekcja nie jest pusta (w SQL - exists). W SQL funkcje te nie są składniowo ortogonalne. Będziemy tego unikać. Przykłady: count(Pracownik), distinct(Pracownik.zawód), exists(Pracownik where zawód = analityk). Funkcja dereferencji; zwykle występuje implicite. Jest wywoływana wtedy, gdy pewną referencję trzeba zamienić na wartość. Np. w zapytaniu Pracownik where Zarobek > 2000 nazwa Zarobek zwróci referencję do danej Zarobek. Funkcja dereferencji jest wymuszona przez operator >. Funkcję dereferencji będziemy oznaczać dereferencja i przyjmować, że dla wartości v nie będącej referencją zwróci v.

29 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 29 kwiecień 2002 Rodzaje operatorów algebraicznych (3) Operatory działające na multizbiorach: suma, przecięcie, iloczyn kartezjański, różnica, równość, zawieranie się, itd. Przykłady: (Prac.Nazwisko) (Emeryt.Nazwisko) (Pracownik.Zawód) bag(analityk) Analogiczne do powyższych, operatory na sekwencjach: konkatenacja sekwencji, obcięcie sekwencji poprzez usunięcie elementów z przodu lub z tyłu, porównanie sekwencji na równość, zawieranie się sekwencji, pobranie i- tego elementu sekwencji itd. Operatory zmiany typu i/lub reprezentacji, czyli tzw. koercje: zmiana liczby rzeczywistej na string (i odwrotnie), zmiana liczby całkowitej na rzeczywistą (i odwrotnie), zmiana sekwencji na wielozbiór (i odwrotnie), itd. W zależności od liczby typów wprowadzonych do języka liczba tych operatorów może być znaczna. Konstruktory wartość złożonych: zmiana wartości na strukturę z etykietowanymi polami, zmiana wartości na wielozbiór lub sekwencję, itd itd.

30 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 30 kwiecień 2002 Konstruktor struktur Składnia: ( q 1, q 2, q 3,...) gdzie q 1, q 2, q 3,... są zapytaniami zwracającymi pojedyncze elementy - wartości atomowe, referencje lub bindery. Jeżeli q i zwraca r i, to wyrażenie ( q 1, q 2, q 3,...) zwraca struct{ r 1, r 2, r 3,...} Np.: (2, 3, 5), (Nazwisko, Zar), (Nazwisko as n, (Zar+100) as z, "p" as r) Konstruktor ten uogólnimy do specyficznego "iloczynu Kartezjańskiego": Jeżeli dowolny argument konstruktora struktury jest wielozbiorem, to pozostałe też muszą być wielozbiorami. Jeżeli wśród nich są pojedyncze elementy to automatycznie są one traktowane jako jedno-elementowe wielozbiory. Np. jeżeli Prac zwraca bag{i 1, i 5, i 9 }, Dział zwraca bag{i 17, i 22 }, to (Prac, Dział, 3) zwraca bag{ struct{i 1, i 17, 3}, struct{i 5, i 17, 3}, struct{i 9, i 17, 3}, struct{i 1, i 22, 3}, struct{i 5, i 22, 3}, struct{i 9, i 22, 3} } Możliwe jest uogólnienie typu "outer join": jeżeli w (.., q i-1, q i, q i+1,..) q i zwraca pusty wynik, to zapytanie jest równoważne (..., q i-1, q i+1,...).

31 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 31 kwiecień 2002 Konstruktor wielozbiorów Składnia: bag( q 1, q 2, q 3,...) gdzie q 1, q 2, q 3,... są zapytaniami zwracającymi pojedyncze elementy - wartości atomowe, referencje lub bindery. Jeżeli q i zwraca r i, to wyrażenie bag( q 1, q 2, q 3,...) zwraca bag{ r 1, r 2, r 3,...} Np.: bag(2, 3, 5), bag(Nazwisko, Nazwa), bag("x" as r, "y" as r, "z" as r) Konstruktor ten uogólnimy dla argumentów będących wielozbiorami: Jeżeli wśród argumentów konstruktora są pojedyncze elementy to automatycznie są one traktowane jako jedno-elementowe wielozbiory. Np. jeżeli zapytanie Lokacja zwraca bag{ "Kielce", "Krosno" }, to zapytanie bag(Lokacja, "Radom", "Płock" ) zwraca bag{"Kielce", "Krosno", "Radom", "Płock" } W innej terminologii konstruktor bag jest sumą wielozbiorów: bag( q 1, q 2, q 3,...) jest równoważne q 1 union q 2 union q 3 union... przy czym jeżeli q i zwraca element r i, to jest on traktowany jak bag{r i }.

32 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 32 kwiecień 2002 Operator definiowania pomocniczej nazwy Wiele zapytań wymaga zdefiniowania pomocniczych nazw. Są one istotnym środkiem konceptualizacji zapytań lub programów. Zwiększają moc języka: bez nich niektóre zapytania nie dadzą się wyrazić. Występują również jako "zmienne związane kwantyfikatorami", lub "jako zmienne iteracyjne" w konstrukcjach for each... do... W SBA występują również jako etykiety struktur. SBQL, podobnie jak SQL, i w odróżnieniu od OQL, nie zmusza do używania pomocniczych nazw. Generalnie, inne podejścia nie radzą sobie z tym pojęciem, w związku z tym rozwiązania są niespójne. W SBA i SBQL semantyka pomocniczych nazw jest potraktowana ogólnie i precyzyjnie, dzięki temu że: Każda nazwa występująca w zapytaniu lub programie podlega tym samym regułom zakresu i wiązania, które zostały zrealizowane w postaci mechanizmu stosu środowisk. Dotyczy to także wszelkich pomocniczych nazw definiowanych wewnątrz zapytań.

33 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 33 kwiecień 2002 Definicja nazwy jako operator algebraiczny Operator definiowania pomocniczej nazwy as jest unarnym operatorem algebraicznym parametryzowanym nazwą. Niech q będzie zapytaniem, które zwraca kolekcję bag{x 1, x 2, x 3,...}. Wówczas zapytanie q as n zwróci kolekcję binderów bag{ n(x 1 ), n(x 2 ), n(x 3 ),...}. Operator as etykietuje określoną nazwą każdą wartość zwróconą przez zapytanie będące jego argumentem. Operator ten nie zmienia charakteru kolekcji: w szczególności, jeżeli q zwraca sequence{x 1, x 2,...}, to q as n zwraca sequence{ n(x 1 ), n(x 2 ),...}. Operator as może być zagnieżdżany: np. jeżeli q zwraca bag{x 1, x 2, x 3,...}, to (q as n 1 ) as n 2 zwraca bag{ n 2 ( n 1 (x 1 ) ), n 2 ( n 1 (x 2 ) ), n 2 ( n 1 (x 3 ) ),...} Powyższa definicja wydaje się banalna, ale okazuje się uniwersalna i precyzyjna, zwiększająca znacznie potencjał dla optymalizacji zapytań.

34 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 34 kwiecień 2002 Przykład działania operatora as i 1 i 6 i 11 Prac p( i 1 ) p( i 6 ) p( i 11 ) Prac as p Zapytanie Wynik

35 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 35 kwiecień 2002 Zastosowania operatora as create view BogatyProjektant { return (Prac where Stan = projektant and Zar > 10000). (Nazwisko as N, PracujeW as NrD) }; Zmienne (krotkowe, dziedzinowe, itd.) definiowane w ramach klauzulami from w językach takich jak SQL i OQL; np. Prac as p. Pokażemy, że operator zależnego złączenia znany z OQL i SQL3 jest ortogonalny w stosunku do operatora as, wobec czego nie zachodzi potrzeba definiowania go w tym szczególnym kontekście; Zmienna związana kwantyfikatorem, np. Prac as p (p.Zar > 10000); Etykiety składników struktur zwracanych przez zapytanie, np. Prac.( Nazwisko as n, Zar as z ) ; Kursor w zdaniu for each; np. for each Prac as p do p.Zar := p.Zar +100; Definicja nowych nazw atrybutów dla wirtualnej perspektywy (view); np:

36 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 36 kwiecień 2002 Operator group as Podobny do operatora as. Jeżeli q zwraca pewną wartość r (w szczególności, kolekcję), to q group as n zwraca pojedynczy binder n( r ). W odróżnieniu od operatora as, operator group as przypisuje nazwę n do rezultatu całości zapytania, a nie do poszczególnych elementów kolekcji zwracanej przez to zapytanie. Operator group as powstał w wyniku prób sformalizowania mętnej semantycznie klauzuli group by języka OQL. Głównym motywem była "ortogonalizacja" tej klauzuli. I to się udało. bag{ i 1, i 6, i 11 } PracZapytanie Wynik Prac group as p p( bag{ i 1, i 6, i 11 } )

37 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 37 kwiecień 2002 Wykład 7

38 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 38 kwiecień 2002 SBQL - operatory nie-algebraiczne

39 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 39 kwiecień 2002 Dlaczego "nie-algebraiczne"? (1) Do nich należą operator where, operator kropki, kwantyfikatory, zależne złączenie, sortowanie (order by), i inne. Wszystkie są binarne. Mimo podobieństwa do operatorów algebraicznych, semantyka operatorów nie-algebraicznych nie da się prosto sprowadzić do algebry. To zdanie może wydawać się niejasne. W modelu relacyjnym operatory selekcji (operator where), projekcji (operator kropki) oraz złączenia są przecież traktowane jako operatory algebraiczne algebry relacji. Tu właśnie jest nieporozumienie. Takie traktowanie jest możliwe wyłącznie przy ograniczonej funkcjonalności, oraz po przyjęciu triku formalnego. Trik polega na tym, że część semantyki jest przenoszona na poziom metajęzykowy. Operatory te są dodatkowo kwalifikowane wyrażeniem metajęzykowym. Np. w wyrażeniu algebry relacyjnej: Zar>1000 ( Prac ) operator selekcji jest kwalifikowany wyrażeniem metajęzykowym Zar >1000. Operator selekcji nie jest pojedynczym operatorem, lecz nieskończoną rodziną zawierającą tyle operatorów, ile jest warunków selekcji.

40 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 40 kwiecień 2002 Dlaczego "nie-algebraiczne"? (2) Powyższy trik można uważać za uzasadniony w przypadku, gdy wyrażenie metajęzykowe parametryzujące operator jest proste, a jego semantyka jest oczywista. Nie zawsze to jest prawda. Operator selekcji może mieć bardziej złożony warunek selekcji, np. ZarobekNetto( Zar ) >1000 ( Prac ) Warunek selekcji zawiera operator + oraz wywołuje pewną funkcję ZarobekNetto. Wyrażenie metajęzykowe posiada nietrywialną wewnętrzną semantykę, która jest nieformalna. Jeżeli jakikolwiek składnik języka nie ma formalnej semantyki, to cały język również nie ma formalnej semantyki. Mimo podobieństwa wizualnego, w powyższych wyrażeniach nazwy Prac oraz Zar są ulokowane w dwóch różnych światach. Pierwsza nazwa należy do języka algebry relacji, jest pierwszej kategorii, podlega formalnemu traktowaniu. Natomiast druga nazwa należy do metajęzyka algebry relacji, jest drugiej kategorii, nie podlega formalnemu traktowaniu.

41 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 41 kwiecień 2002 Dlaczego "nie-algebraiczne"? (3) W ten sposób złamana została zasada relatywizmu, zgodnie z którą nazwy nie mogą posiadać fundamentalnie różnej semantyki w zależności od tego, jakiego rodzaju dane oznaczają. Ta zasada staje się szczególnie istotna dla języków obiektowych, gdyż obiekty mogą mieć strukturę hierarchiczną, zaś nazwy mogą oznaczać dane na dowolnym poziomie hierarchii obiektów. Podobny problem dotyczy operatorów. Operator selekcji jest elementem języka tej algebry, należy do pierwszej kategorii, podczas gdy operator < występuje w metajęzyku, jest drugiej kategorii. Powyższa językowo-meta-językowa schizofrenia podważa poprawność definicji semantyki. Podane argumenty są wystarczające aby twierdzić, że tzw. algebry obiektowe są pseudo-matematyczną bzdurą (włączając algebry dla XML). Paradoksalnie, są one motywowane koniecznością zbudowania solidnych podstaw matematycznych obiektowych języków zapytań.

42 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 42 kwiecień 2002 Dlaczego "nie-algebraiczne"? (4) W podejściu stosowym dowolne operatory nie są indeksowane wyrażeniami meta-językowymi. Nie występuje więc semantyczna schizofrenia nazw dzieląca je na językowe i meta-językowe. Nie ma podziału na nazwy pierwszej kategorii i drugiej kategorii. Każda nazwa ma dokładnie taką samą semantykę i podlega dokładnie tym samym regułom wiązania i zakresu Podobnie z operatorami: nie występuje semantyczne zróżnicowanie operatorów: operator < występuje na tym samym poziomie semantycznym jak operator selekcji where. Koncepcja operatorów nie-algebraicznych jest bardzo prosta oraz ma dobrze ugruntowane korzenie w semantyce języków programowania. Definicja operatorów nie-algebraicznych będzie się nieco różniła w zależności od tego, który modelu składu (M0 - M3) będzie rozpatrywany. Wszystkie te definicje będą bazowały na podanej niżej podstawowej definicji dla modelu M0.

43 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 43 kwiecień 2002 Opis procedury eval dla operatora nie-algebr. Aby dokonać ewaluacji zapytania q 1 q 2 wykonaj następujące czynności: Dokonaj ewaluacji zapytania q 1. Zapytanie to zwraca wielozbiór elementów. Dla każdego elementu e należącego do wyniku q 1 wykonaj następujące czynności: Oblicz wartość funkcji nested( e ). Wynik jest zbiorem binderów. Włóż obliczony zbiór binderów jako nową sekcje na wierzchołek stosu ENVS. Dokonaj ewaluacji zapytania q 2 w tym nowym środowisku. Oblicz wynik cząstkowy dla danego elementu e poprzez połączenie e z wynikiem zwróconym przez q 2. Funkcja łącząca zależy od operatora. Usuń nowo wstawioną górną sekcję ze stosu ENVS. Zsumuj wszystkie wyniki cząstkowe w wynik końcowy. Sposób sumowania sumuj ( U ) zależy od rodzaju operatora. Stan stosu środowisk ENVS po zakończeniu ewaluacji jest taki sam, jak przez rozpoczęciem ewaluacji.

44 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 44 kwiecień 2002 Formalny zapis procedury eval dla oper. niealgebr. procedure eval( q : zapytanie ) begin case q jest rozpoznane jako q 1 q 2 : (* q 1, q 2 są zapytaniami, jest operatorem nie-algebraicznym *) begin wyniki_pośr: bag of Rezultat; (* lokalna kolekcja wyników pośrednich *) wynik_pośredni: Rezultat; (* lokalna zmienna na wynik pośredni *) wynik_końcowy: Rezultat; (* lokalna zmienna na wynik końcowy *) e: Rezultat; (* lokalna zmienna na element kolekcji zwracanej przez q 1 *) wyniki_pośr := ; (* zerowanie kolekcji wyników pośrednich *) eval( q 1 ); (*q 1 zwraca kolekcję elementów; wynik q 1 na czubku stosu QRES *) for each e in top( QRES ) do (* iteracja po wszystkich elementach wyniku q 1 *) begin push( ENVS, nested( e ) ); (* nowa sekcja na stosie środowisk *) eval( q 2 ); (* wynik q 2 na czubku stosu QRES *) wynik_pośredni := połącz ( e, top( QRES ) ); (* połączenie e z wynikiem q 2 ; zależne od *) wyniki_pośr := wyniki_pośr U { wynik_pośredni }; (* akumulacja wyniku pośredniego *) pop( QRES ); (* usuniecie z QRES wyniku q 2 *) pop( ENVS ); (* usuniecie z ENVS nowej sekcji *) end; wynik_końcowy := sumuj ( wyniki_pośr ); (* zsumowanie wyników pośrednich; zależne od *) pop( QRES ); (* usuniecie z QRES wyniku q 1 *) push( QRES, wynik_końcowy ); (* włożenie na QRES końcowego wyniku *) end; end;

45 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 45 kwiecień 2002 Poglądowy obraz małej bazy danych i 1 Prac i 2 Nazwisko Nowak i 3 Zar 2500 i 4 PracujeW i 5 Prac i 6 Nazwisko Kowalski i 7 Zar 2000 i 8 PracujeW i 9 Prac i 10 Nazwisko Barski i 11 Zar 900 i 16 PracujeW i 13 Miasto Radom i 14 Ulica Wolska i 15 NrDomu 12 i 12 Adres i 17 Dział i 18 Nazwa Produkcja i 19 Lokacja Kielce i 21 Zatrudnia i 20 Lokacja Kraków i 22 Dział i 23 Nazwa Sprzedaż i 24 Lokacja Radom i 25 Zatrudnia i 26 Zatrudnia

46 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 46 kwiecień 2002 Operator where (selekcja) Składnia: q 1 where q 2 Ograniczenie: podzapytanie q 2 zwraca wartość prawda lub fałsz. Semantyka Dla każdego elementu e zwróconego przez q 1, ENVS jest podwyższany o nested(e) Następnie ewaluowane jest q 2 Po ewaluacji q 2 stos ENVS wraca do poprzedniego stanu e należy do ostatecznego wyniku wyłącznie wtedy, gdy q 2 zwróciło prawda. Objaśnienie funkcji eval Funkcja połącz: dla danego e należącego do wyniku q 1 zwraca jednoelementowy wielozbiór { e } w przypadku, gdy dla tego e podzapytanie q 2 zwróciło prawda, lub pusty wielozbiór { }, jeżeli podzapytanie q 2 zwróciło fałsz. Funkcja sumuj: sumuje (mnogościowo) wszystkie wyniki pośrednie. Przykład: Prac where ( Zar > 1000 )

47 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 47 kwiecień 2002 Operator where - ilustracja działania Prac where ( Zar > 1000 ) i1i5i9i1i5i9 Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) i3i3 i7i7 i 11 i1i5i1i5 Stan stosu ENVS przed ewaluacją Rezultat zwracany przez zapytanie Prac (wiązanie Prac) Rezultat zwracany przez zapytanie Zar (wiązanie Zar) Iteracja po elementach e poprzedniego rezultatu: na ENVS wkłada się nested(e) Nazwisko(i 2 ) Zar(i 3 ) PracujeW(i 4 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 6 ) Zar(i 7 ) PracujeW(i 8 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 10 ) Zar(i 11 ) Adres(i 12 ) PracujeW(i 16 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Rezultat dereferencji wymuszanej przez operator > Rezultat zwracany przez zapytanie prawda fałsz Rezultat zwracany przez zapytanie Zar>1000 Końcowy rezultat zapytania

48 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 48 kwiecień 2002 Operator kropki (projekcja, nawigacja) Składnia: q 1. q 2 Semantyka Dla każdego elementu e zwróconego przez q 1, ENVS jest podwyższany o nested(e) Następnie ewaluowane jest q 2 Po ewaluacji q 2 stos ENVS wraca do poprzedniego stanu Ostateczny wynik jest sumą mnogościową wyników q 2 Objaśnienie funkcji eval Funkcja połącz: ignoruje e; zwraca wynik podzapytania q 2. Funkcja sumuj: sumuje (mnogościowo) wszystkie wyniki pośrednie. Przykład: Prac. Zar Operator kropki przykrywa tzw. wyrażenia ścieżkowe (path expressions) w najbardziej uniwersalnej postaci, pozwalając je jednocześnie dowolnie kombinować z innymi operatorami.

49 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 49 kwiecień 2002 Operator kropki - ilustracja działania Prac. Zar i1i5i9i1i5i9 i3i3 i7i7 i 11 Stan stosu ENVS przed ewaluacją Rezultat zwracany przez zapytanie Prac (wiązanie Prac) Rezultat zwracany przez zapytanie Zar (wiązanie Zar) Iteracja po elementach e poprzedniego rezultatu: na ENVS wkłada się nested(e) Końcowy rezultat zapytania i 3 i 7 i 11 Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 2 ) Zar(i 3 ) PracujeW(i 4 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 6 ) Zar(i 7 ) PracujeW(i 8 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 10 ) Zar(i 11 ) Adres(i 12 ) PracujeW(i 16 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 )

50 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 50 kwiecień 2002 Operator zależnego złączenia Składnia: q 1 q 2 Semantyka Dla każdego e zwróconego przez q 1, ENVS jest podwyższany o nested(e) Następnie ewaluowane jest q 2 Po ewaluacji q 2 stos ENVS wraca do poprzedniego stanu Ostateczny wynik jest sumą mnogościową wszystkich struktur, w których na początku jest e, zaś dalej jest element wyniku q 2 zwrócony dla tego e. Objaśnienie funkcji eval Funkcja połącz: zarówno e jak i każdy element e 2 zwracany przez q 2 traktuje jako struktury (jednoelementowe lub wieloelementowe). Dla każdego e 2 zwracanego przez q 2 tworzy strukturę poprzez połączenie e oraz e 2. Wynikiem pośrednim jest kolekcja wszystkich takich struktur. Funkcja sumuj: sumuje (mnogościowo) wszystkie wyniki pośrednie. Przykład: Prac Zar Zależne złączenie jest zdefiniowane w ODMG OQL (klauzula from) w znacznie ograniczonej postaci w stosunku do powyższej definicji.

51 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 51 kwiecień 2002 Operator zależnego złączenia - ilustracja działania Prac Zar i1i5i9i1i5i9 i3i3 i7i7 i 11 Stan stosu ENVS przed ewaluacją Rezultat zwracany przez zapytanie Prac (wiązanie Prac) Rezultat zwracany przez zapytanie Zar (wiązanie Zar) Iteracja po elementach e poprzedniego rezultatu: na ENVS wkłada się nested(e) Końcowy rezultat zapytania struct(i 1, i 3 ) struct(i 5, i 7 ) struct(i 9, i 11 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 2 ) Zar(i 3 ) PracujeW(i 4 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 6 ) Zar(i 7 ) PracujeW(i 8 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 10 ) Zar(i 11 ) Adres(i 12 ) PracujeW(i 16 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 )

52 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 52 kwiecień 2002 Operator sortowania Składnia: q 1 order by q 2 Semantyka Wykonywane jest zapytanie: q 1 dereferencja( q 2 ) Wynik (bag) jest sortowany według części struktur zwróconej przez q 2. Po posortowaniu wynik jest sekwencją. Końcowy wynik uzyskuje się poprzez projekcję tej sekwencji (bez zmiany kolejności elementów na części struktur zwrócone przez q 1. Np. Prac order by Nazwisko Prac order by ((PracujeW.Dział.Nazwa), Zarobek) Operator ten można dodatkowo wyposażyć w kwalifikatory asc (wzrastająco) i desc (malejąco) przy każdej składowej q 2. Np. Prac order by ((PracujeW.Dział.Nazwa) asc, Zarobek desc) Operator asc jest komentarzem, operator desc jest odwrotnością wartości: np. 5 desc oznacza -5, "abceg" desc oznacza "zyxvt", itd. Operator ten należy parametryzować (najlepiej konfiguracyjnie) funkcją porównania elementów ( zależną od języka: angielski, polski, niemiecki,.. ).

53 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 53 kwiecień 2002 Kwantyfikator egzystencjalny Składnia: q 1 ( q 2 ) lub q 1 q 2 Ograniczenie: podzapytanie q 2 zwraca wartość prawda lub fałsz. Semantyka Dla każdego e zwróconego przez q 1, ENVS jest podwyższany o nested(e) Następnie ewaluowane jest q 2 Po ewaluacji q 2 stos ENVS wraca do poprzedniego stanu Ostateczny wynik jest prawda wtedy i tylko wtedy, jeżeli dla co najmniej jednego e podzapytanie q 2 zwróciło prawda. Objaśnienie funkcji eval Funkcja połącz: ignoruje e; zwraca wynik podzapytania q 2. Funkcja sumuj: Zwraca prawda jeżeli co najmniej jeden wynik pośredni zwrócony przez q 2 jest prawda; w przeciwnym wypadku zwraca fałsz. Przykład: Prac ( Zar > 1000 )

54 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 54 kwiecień 2002 Kwantyfikator uniwersalny Składnia: q 1 ( q 2 ) lub q 1 q 2 Ograniczenie: podzapytanie q 2 zwraca wartość prawda lub fałsz. Semantyka Dla każdego e zwróconego przez q 1, ENVS jest podwyższany o nested(e) Następnie ewaluowane jest q 2 Po ewaluacji q 2 stos ENVS wraca do poprzedniego stanu Ostateczny wynik jest prawda wtedy i tylko wtedy, jeżeli dla wszystkich e podzapytanie q 2 zwróciło prawda. Jeżeli q 1 zwróciło pusty wielozbiór, to wynik także jest prawda. Objaśnienie funkcji eval Funkcja połącz: ignoruje e; zwraca wynik podzapytania q 2. Funkcja sumuj: Zwraca fałsz jeżeli co najmniej jeden wynik pośredni zwrócony przez q 2 jest fałsz ; w przeciwnym wypadku zwraca prawda. Przykład: Prac ( Zar > 1000 )

55 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 55 kwiecień 2002 Kwantyfikator uniwersalny - ilustracja działania Prac ( Zar > 1000 ) i1i5i9i1i5i9 i3i3 i7i7 i 11 Stan stosu ENVS przed ewaluacją Rezultat zwracany przez zapytanie Prac (wiązanie Prac) Rezultat zwracany przez zapytanie Zar (wiązanie Zar) Iteracja po elementach e poprzedniego rezultatu: na ENVS wkłada się nested(e) Rezultat dereferencji wymuszanej przez operator > Rezultat zwracany przez zapytanie prawda fałsz Rezultat zwracany przez zapytanie Zar>1000 Końcowy rezultat zapytania fałsz Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 2 ) Zar(i 3 ) PracujeW(i 4 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 6 ) Zar(i 7 ) PracujeW(i 8 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 10 ) Zar(i 11 ) Adres(i 12 ) PracujeW(i 16 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 )

56 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 56 kwiecień 2002 Kroki ewaluacji zapytania z pomocniczą nazwą (Prac as x) where ( ( x. Zar ) > 1000 ) i1i5i9i1i5i9 i3i3 i7i7 i 11 x(i 1 ) x(i 5 ) Rezultat zwracany przez zapytanie Prac Rezultat zwracany przez zapytanie x (wiązanie x) Iteracja po elementach e poprzedniego rezultatu: na ENVS wkłada się nested(e) Rezultat dereferencji wymuszanej przez operator > Rezultat zwracany przez zapytanie prawda fałsz Rezultat zwracany przez zapytanie Zar>1000 Końcowy rezultat zapytania Rezultat zwracany przez zapytanie Prac as x x(i 1 ) x(i 5 ) x(i 9 ) i1i1 i5i5 i9i9 Rezultat zwracany przez zapytanie Zar x(i 1 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) x(i 5 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) x(i 9 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 2 ) Zar(i 3 ) PracujeW(i 4 ) x(i 1 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 6 ) Zar(i 7 ) PracujeW(i 8 ) x(i 5 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Nazwisko(i 10 ) Zar(i 11 ) Adres(i 12 ) PracujeW(i 16 ) x(i 9 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Iteracja po elementach e poprzedniego rezultatu: na ENVS wkłada się nested(e)

57 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 57 kwiecień 2002 Zamiana "zmiennej" na etykietę struktury Dla zapytania (Prac as x) where (( x. Zar ) > 1000 ) końcowy wynik jest różny od wyniku zapytania Prac where Zar > 1000, mianowicie, elementy wyniku są opatrzone nazwą x. Elementy takie można uważać za proste struktury (w sensie języków C/C++), których jedynym polem jest pole o nazwie x. W standardzie ODMG są "tajemnicze" miejsca, w których zmienna dziedzinowa zmienia się w etykietę struktury. Standard tego nie wyjaśnia. Dopiero na gruncie SBA widać jasno, dlaczego tak się dzieje. Wymagało to jednak bardzo istotnych założeń odnośnie semantyki. Standard ODMG jest semantycznie nieprecyzyjny, więc nie jest w stanie tego wyjaśnić. Tego efektu nie można także wyjaśnić na gruncie algebry obiektowej, dziedzinowego rachunku obiektowego, lub innego tradycyjnego formalizmu. Można pokazać, że zapytanie Prac where Zar > 1000 jest równoważne zapytaniu ((Prac as x) where (( x. Zar ) > 1000 )). x

58 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 58 kwiecień 2002 SBQL - schematy BD dla przykładów zapytań Dział [0..*] NrD Nazwa Lokacja[1..*] Schemat obiektowy (diagram klas) PracujeW Zatrudnia [1..*] Prac[0..*] NrP Nazwisko Stan Zar Adres [0..1] Miasto Ulica NrDomu Prac NrP Nazwisko Stan Zar PracujeW Dział NrD Nazwa Szef Lokacje NrD Lokacja Adres NrP Miasto Ulica NrDomu Schemat relacyjny Kieruje [0..1] Szef Asocjacje są zrealizowane jako (bliźniacze) obiekty pointerowe Strzałki modelują asocjacje; prowadzą od klucza obcego do głównego

59 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 59 kwiecień 2002 Podaj pełną informację o pracownikach: Prac Jest to odpowiednik zapytania SQL: select * from Prac. Wbrew popularnym opiniom, lukier select... from... będziemy uważać za szkodliwy. Różnice semantyczne: zapytanie SQL zwraca tabelę Prac, podczas gdy Prac zwraca referencje do obiektów Prac. Zapytania SBQL nigdy nie zwracają obiektów. SBQL - przykłady zapytań (1) Podaj nazwiska wszystkich pracowników: Prac. Nazwisko Zapytanie jest odpowiednikiem zapytania SQL: select Nazwisko from Prac. Zapytanie SQL zwraca jedno-kolumnową tablicę stringów będących nazwiskami, natomiast zapytanie SBQL zwraca tablicę referencji do pod-obiektów Nazwisko w obiektach Prac. Do tej tablicy można oczywiście zastosować operator dereferencji, który referencje na stringi, ale automatyczna dereferencja prowadzi do straty informacji. Referencje są bardziej uniwersalne niż stringi, gdyż. np. mogą być użyte po lewej stronie operacji podstawienia.

60 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 60 kwiecień 2002 SBQL - przykłady zapytań (2) Podaj pełną informację o Kowalskim: Prac where (Nazwisko = Kowalski) SQL: select * from Prac where Nazwisko = Kowalski. W odróżnieniu od SQL, zapytanie w SBQL zwróci referencję do obiektu Kowalskiego. Referencję tę można następnie skonsumować zdaniem imperatywnym; np. można usunąć obiekt Kowalskiego zdaniem delete Prac where (Nazwisko = Kowalski); W dalszych przykładach będziemy często rezygnować z nawiasów. Podaj zarobek Kowalskiego: (Prac where Nazwisko = Kowalski). Zar SQL: select Zar from Prac where Nazwisko = Kowalski. W odróżnieniu od SQL, zapytanie w SBQL zwróci referencję do zarobku Kowalskiego. Referencję tę można następnie skonsumować zdaniem imperatywnym; np. można zmienić zarobek Kowalskiego zdaniem: ((Prac where Nazwisko = Kowalski). Zar) := 5000; Odpowiada to zdaniu aktualizacyjnemu SQL: update Prac set Zar = 5000 where Nazwisko = Kowalski;

61 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 61 kwiecień 2002 SBQL - przykłady zapytań (3) Podaj numery i nazwiska pracowników zarabiających więcej niż (Prac where Zar > 1000). (NrP, Nazwisko) Wynikiem zapytania jest wielozbiór struktur struct{i NrP, i Nazwisko }, gdzie w każdej strukturze pierwsza referencja dotyczy atrybutu NrP, zaś druga - atrybutu Nazwisko. Przecinek oznacza operator algebraiczny konstruktora struktury. Zwróć referencję do danej pointerowej PracujeW dla pracownika Kowalskiego: (Prac where Nazwisko = Kowalski). PracujeW Zapytanie nie ma odpowiednika w SQL i OQL. Zapytanie takie ma jednak sens, gdyż może być podzapytaniem szerszego zapytania. Ma również sens z powodu operacji aktualizacyjnych. Przykładowo, jeżeli chcielibyśmy przenieść Kowalskiego do działu Sprzedaż, wówczas takie zdanie może mieć postać: (Prac where Nazwisko=Kowalski).PracujeW := &(Dział where Nazwa=Sprzedaż) Z lewej strony podstawienia obliczana jest l-wartość (l-value), czyli referencja do danej pointerowej PracujeW w obiekcie Kowalskiego. Z prawej strony podstawienia mamy r-wartość (r-value), która jest referencją do działu Sprzedaż.

62 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 62 kwiecień 2002 SBQL - przykłady zapytań (4) Podaj pełne dane o dziale, w którym pracuje Kowalski: ((Prac where Nazwisko = Kowalski). PracujeW ). Dział Zapytanie to zwraca referencję do obiektu działu, w którym pracuje Kowalski. OQL: select d from Prac as p, p.PracujeW as d where p.Nazwisko = Kowalski OQL unika nazwy Dział. Jest to niewłaściwe z dwóch powodów. (1) Jak pokazuje poprzedni przykład, istnieje potrzeba rozróżnienia pomiędzy referencją do pointera prowadzącego do obiektu, a referencją do samego obiektu. (2) Zapytanie w SBQL jest bardziej czytelne, gdyż explicite używa nazwy Dział, oznaczającej końcowy efekt ewaluacji. Podaj nazwę działu, w którym pracuje Kowalski: (Prac where Nazwisko = Kowalski). PracujeW. Dział. Nazwa Zapytanie to zwraca referencję do nazwy działu, w którym pracuje Kowalski. OQL: select p.PracujeW.Nazwa from Prac as p where p.Nazwisko = Kowalski Przykład ilustruje tzw. wyrażenia ścieżkowe (path expressions), czyli nawigację wzdłuż ścieżki wyznaczonej powiązaniami pointerowymi lub w dół hierarchii obiektów. W SBQL takie wyrażenia są efektem definicji kropki - wyrażenie czytamy jako (((Prac where Nazwisko = Kowalski). PracujeW). Dział). Nazwa

63 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 63 kwiecień 2002 SBQL - przykłady zapytań (5) Wyrażenia ścieżkowe mogą być dowolnie długie. Np. nazwisko szefa Kowalskiego: (Prac where Nazwisko = Kowalski). PracujeW. Dział. Szef. Prac. Nazwisko Nie definiujemy specjalnych wyrażeń ścieżkowych, lecz wykorzystujemy operator kropki. Uzyskujemy przez to możliwość dowolnego kombinowania wyrażeń ścieżkowych z innymi operatorami. Przykładowo, poniższe wyrażenie SBQL (Prac where budynek D (PracujeW.Dział.Lokacja)).(Nazwisko, (Adres.Miasto)) specyfikuje nazwisko i miasto pracownika pracującego w budynku D. ODMG OQL ogranicza możliwość używania wygodnych wyrażeń ścieżkowych poprzez niezbyt mądry w tym kontekście lukier select...from...where... oraz poprzez przyjęcie (również niezbyt mądrego) założenia, że operator kropki może się pojawić tylko wtedy, jeżeli wyrażenie przed kropką zwraca dokładnie jedną wartość. Obydwa te założenia są implicite odrzucone przy definiowaniu operatorów niealgebraicznych.

64 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 64 kwiecień 2002 SBQL - przykłady zapytań (6) Podaj wszystkie informacje o pracownikach zarabiających więcej od Kowalskiego: Prac where Zar > ((Prac where Nazwisko = Kowalski).Zar) SQL: select * from Prac where Zar > select Zar from Prac where Nazwisko = Kowalski W zapytaniu tym występuje dwa razy nazwa Zar, ale dzięki stosowej semantyce każde z tych wystąpień jest inaczej wiązane: pierwsze Zar jest wiązane na stosie posiadającym 2 sekcje, drugie Zar na stosie posiadającym 3 sekcje. Dla każdego pracownika zwróć pełną informację o pracowniku i jego dziale. Prac (PracujeW. Dział) Skorzystaliśmy z operatora zależnego złączenia. Wynikiem jest wielozbiór struktur struct{ i Prac, i Dział }, gdzie pierwszy składnik każdej struktury jest referencją do obiektu pracownika, zaś drugi jest referencją do obiektu jego działu. Zapytanie to ma odpowiednik w OQL: select struct(pr: p, dz: d) from Prac as p, p.PracujeW as d Nie jest to dokładny odpowiednik, ponieważ w OQL struktury muszą mieć etykiety (tutaj pr i dz), a ponadto OQL nie wprowadza referencji.

65 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 65 kwiecień 2002 SBQL - przykłady zapytań (7) Dla każdego pracownika zwróć pełną informację o pracowniku i jego dziale. Analogiczne zapytanie odnoszące się do struktury relacyjnej ma postać: Prac (Dział where PracujeW = NrD) lub (z użyciem produktu kartezjańskiego) (Prac Dział ) where PracujeW = NrD To ostatnie zapytanie ma odpowiednik w SQL: select * from Prac, Dział where PracujeW = NrD Nie jest to dokładny odpowiednik, ponieważ wynikiem nie jest wielozbiór z parami referencji (jak w przypadku SBQL), lecz zbiorcza tabela zawierająca zarówno atrybuty tabeli Prac jak i tabeli Dział.

66 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 66 kwiecień 2002 SBQL - przykłady zapytań (8) Podaj informację o działach i średnich zarobkach pracowników w działach: Dział avg(Zatrudnia.Prac.Zar) Wynikiem zapytania jest wielozbiór struktur struct{ i Dział, średni_zar }, gdzie pierwszy składnik każdej struktury jest referencją do obiektu Dział, zaś drugi jest liczbą będącą średnią zarobków w tym dziale. Następny slajd przedstawia stany stosu środowisk przy wiązaniu poszczególnych nazw występujących w tym zapytaniu. W OQL zapytanie to wymaga użycia opcji group by, która została wyspecyfikowana nieprecyzyjnie, toteż nie ma pewności jak jej użyć. Podobne zapytanie można sformułować przy pomocy następującego zdania SQL: select d.*, avg(p.Zar) from Dział d, Prac p where d.NrD = p.PracujeW group by d.NrD Wadą jest konieczność użycia operatora group by, który jest nieortogonalny, prowadzi do nowego jakościowo warunku (having), ma rafy semantyczne, oraz sprawia trudności z optymalizacją zapytań. W SBQL unikamy tego wątpliwego operatora, również dla struktur relacyjnych: Dział avg((Prac where PracujeW = NrD ). Zar)

67 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 67 kwiecień 2002 SBQL - przykłady zapytań (9) ( Dział avg((Zatrudnia. Prac ). Zar ) ) Prac(..) Prac(..),... Dział(..) Dział(..)... Nrd(..), Nazwa(..) Lokacja(..) Lokacja(..)... Zatrudnia(..) Zatrudnia(..)... Szef(..) Prac(..) Prac(..),... Dział(..) Dział(..)... NrP (..) Nazwisko (..) Stan (..) Zar (..) Adres(..) PracujeW(..) Kieruje(..) Nrd(..), Nazwa(..) Lokacja(..) Lokacja(..)... Zatrudnia(..) Zatrudnia(..)... Szef(..) Prac(..) Prac(..),... Dział(..) Dział(..)... Prac(..) Nrd(..), Nazwa(..) Lokacja(..) Lokacja(..)... Zatrudnia(..) Zatrudnia(..)... Szef(..) Prac(..) Prac(..),... Dział(..) Dział(..)... Nrd(..), Nazwa(..) Lokacja(..) Lokacja(..)... Zatrudnia(..) Zatrudnia(..)... Szef(..) Prac(..) Prac(..),... Dział(..) Dział(..)... Nrd(..), Nazwa(..) Lokacja(..) Lokacja(..)... Zatrudnia(..) Zatrudnia(..)... Szef(..) Prac(..) Prac(..),... Dział(..) Dział(..)... Prac(..) Prac(..),... Dział(..) Dział(..)... Stany stosu środowisk przy wiązaniu nazw występujących w zapytaniu Dział avg(Zatrudnia.Prac.Zar)

68 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 68 kwiecień 2002 SBQL - przykłady zapytań (10) Podaj średnią liczbę pracowników w działach. Dla schematu obiektowego: avg( Dział. count(Zatrudnia)) Dla schematu relacyjnego: avg( Dział. count(Prac where NrD = PracujeW)) Analogiczne zdanie w standardzie SQL-89 nie istnieje; zapytanie można wyrazić z pomocą dodatkowej perspektywy. W standardzie SQL-92 zdanie to można sformułować przy pomocy opcji group by. Opcja ta prowadzi do znanej rafy semantycznej, polegającej na tym, że jeżeli pewien dział nie będzie miał ani jednego pracownika, wówczas nie zostanie uwzględniony przy obliczaniu średniej. W SBQL ta rafa nie występuje.

69 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 69 kwiecień 2002 SBQL - przykłady zapytań (11) Dla pracowników zarabiających więcej niż 2000 i pracujących w budynku A podaj nazwisko, stanowisko, nazwę działu i nazwisko szefa działu. ((Prac where Zar > 2000) (PracujeW. (Dział where "budynek A" Lokacja ))). (Nazwisko, Stan, Nazwa, (Szef.Prac.Nazwisko)) Wynikiem będzie kolekcja struktur struct{i Nazwisko1, i Stan, i Nazwa, i Nazwisko2 }, gdzie każda struktura zawiera cztery referencje. Czy w każdym dziale jest pracownik zarabiający więcej od swojego szefa? Dział ( Zatrudnia.Prac ( Zar > Szef.Prac.Zar)) Wynikiem zapytania jest wartość boolowska prawda lub fałsz. Kwantyfikatory są operatorami niealgebraicznymi, wobec czego (jak w całym SBQL), użycie nazw pomocniczych (czyli zmiennych związanych kwantyfikatorami) nie jest konieczne. Jeżeli zachodziłaby potrzeba, wówczas takie zmienne można byłoby powołać w postaci pomocniczych nazw: Dział as x ( x.Zatrudnia.Prac as y ( y.Zar > x.Szef.Prac.Zar)) Zmuszanie użytkowników do obowiązku stosowania pomocniczych nazw, jak w OQL, jest konsekwencją pseudo-matematycznych koncepcji semantyki.

70 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 70 kwiecień 2002 SBQL - przykłady zapytań (12) Podaj pracowników którzy na pewno mieszkają w Olsztynie. Zgodnie ze schematem, adres pracownika jest daną opcyjną i złożoną. W terminologii modelu relacyjnego, brak adresu dla pracownika oznacza, ze w tym miejscu jest zapisana wartość zerowa (null). Wartości te wymagają w SQL specjalnych opcji, które są niespójne oraz komplikują semantykę i pragmatykę języka. W naszym podejściu będziemy ich unikać. Zamiast operacji na wartościach zerowych można zastosować kwantyfikatory. Prac where Adres (Miasto = Olsztyn) Podaj pracowników którzy albo na pewno mieszkają w Olsztynie albo być może mieszkają w Olsztynie, ponieważ ich adres jest nieznany: Prac where Adres (Miasto = Olsztyn) Pamiętać: kwantyfikator działający na pustym zbiorze zwraca true.

71 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 71 kwiecień 2002 SBQL - przykłady zapytań (13) Podaj nazwiska i zarobki projektantów zarabiających więcej od swoich szefów: Zilustrujemy kilka stylów tworzenia zapytań, które są konsekwencją przyjętych przez nas definicji: Styl SQL (schemat relacyjny): (((Prac as x) (Dział as y) (Prac as z)) where x.Stan = projektant and x.PracujeW = y.NrD and y.Szef = z.NrP and x.Zar > z.Zar). (x.Nazwisko, x.Zar) Styl OQL (schemat obiektowy): ((Prac as x) (x.PracujeW.Dział as y) (y.Szef.Prac as z) where x.Stan =projektant and x.Zar > z.Zar). (x.Nazwisko, x.Zar) Wariant minimalny SBQL (schemat obiektowy ): (Prac where Stan = projektant and Zar > (PracujeW.Dział.Szef.Prac.Zar)). (Nazwisko,Zar) Styl rachunku dziedzinowego zapisanego w SBQL (schemat relacyjny): (((Prac.(Nazwisko as np, Zar as zp, Stan as sp, PracujeW as dp)) (Dział.( Nrd as nd, Szef as sd)) (Prac.(Zar as zs, NrP as ns))) where sp = projektant and dp = nd and sd = ns and zp > zs). (np, zp)

72 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 72 kwiecień 2002 SBQL - podsumowanie przykładów Poprzez przykłady, szczególnie z poprzedniego slajdu, pokazujemy, że debaty o wyższości formalizmu A nad formalizmem B oraz obecne spory o języki zapytań można pogodzić na gruncie podejścia stosowego. Istotne jest, jakie struktury danych dopuszczamy w systemie zarządzania bazą danych. Z chwilą precyzyjnej definicji tych struktur dla dowolnych z nich można zbudować język zapytań na gruncie podejścia stosowego. Teza M.Stonebrakera o tym, że dla modeli obiektowych nie można zbudować języka zapytań, jest nonsensem; próbą zbudowania fałszywego stereotypu. Struktury relacyjne nie mają w tym względzie jakiejkolwiek przewagi nad strukturami obiektowymi, i odwrotnie. Gorąca debata ideologów świata komercyjnego odnośnie tego, który paradygmat struktur danych i języków zapytań jest lepszy, na gruncie SBA staje się jałową demagogiczną retoryką, pustosłowiem pozbawionym merytorycznych argumentów. Szczególnie wtedy, gdy powołuje się na "podstawy matematyczne".

73 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 73 kwiecień 2002 Wykład 8

74 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 74 kwiecień 2002 Rozszerzenie SBQL dla modeli M1, M2 i M3 (klas i dziedziczenia, dynamicznych ról, list eksportowych)

75 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 75 kwiecień 2002 Rozszerzenie SBQL w modelu M1 W modelu M1 należy zmodyfikować regułę wiązania nazw. Chodzi o zachowanie zasady zamienialności (substitutability). Przykładowo, obiekt Prac jest jednocześnie obiektem Osoba. Informacja o tej zależności jest przechowywana w modelu M1 w dwóch miejscach: (1) klasy, które przechowują nazwy należących do nich obiektów; (2) relacje KK i OK. W terminach operacji na ENVS zmieniona reguła wiązania oznacza, że o ile w pewnej sekcji stosu znajduje się binder o nazwie Prac, zaś wiązana jest nazwa Osoba, to binder ten uczestniczy w procesie wiązania tak samo, jakby był to binder o nazwie Osoba. M1 wprowadza nową zasadę otwierania i usuwania sekcji na ENVS. Jeżeli operator niealgebraiczny przetwarza obiekt posiadający identyfikator i, to na wierzchołek stosu środowisk wkładane są nie tylko bindery nested(i), ale poniżej wierzchołka stosu są ulokowane sekcje z binderami do własności klas tego obiektu w odpowiedniej kolejności,

76 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 76 kwiecień 2002 Graficzna reprezentacja przykładu modelu M1 i 40 KlasaOsoba i 41 Wiek (...kod...) i 50 KlasaPrac i 51 ZmieńZar (...kod...) i 52 ZarNetto (...kod...) i 4 Prac i 5 Nazwisko Nowak i 7 Zar 2500 i 8 PracujeW i 6 RokUr 1944 i 127 i 1 Osoba i 2 Nazwisko Wilski i 3 RokUr 1950 i 128 i 9 Prac i 10 Nazwisko Kowalski i 12 Zar 2000 i 13 PracujeW i 11 RokUr 1940 Osoba Nazwisko RokUr Wiek Prac Zar ZmieńZar ZarNetto PracujeW

77 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 77 kwiecień 2002 Bindery do własności przechowywanych wewnątrz obiektu O, czyli nested( i O ) Bindery do własności przechowywanych wewnątrz K1 Bindery do własności przechowywanych wewnątrz K2 Bindery do własności przechowywanych wewnątrz K Bindery z identyfikatorami startowymi składu obiektów Kolejność przeszukiwania stosu Sekcje wkładane na stos środowiskowy przy przetwarzaniu obiektu O przez operator niealgebraiczny Obiekt Klasa K1 Klasa K2 Klasa K3 Sytuacja na ENVS dla modelu M1 Zakładamy, że operator nie-algebraiczny przetwarza obiekt O z identyfikatorem i O.

78 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 78 kwiecień 2002 Zmiany w modelu M1 Podana koncepcja automatycznie uwzględnia własność przesłaniania (overriding). Jeżeli np. klasa K1 zawiera pewną metodę m, która przesłania metodę m zawartą w klasie K2, to zgodnie z przedstawioną kolejnością przeszukiwania stosu przy wiązaniu nazwy m związana zostanie metoda m z klasy K1; metoda m z klasy K2 będzie niewidoczna. Poprzedni slajd przedstawia stan stosu od strony koncepcji semantyki języka zapytań. Przy przetwarzaniu obiektu O na stos są wkładane cztery sekcje, a po przetworzeniu obiektu - zdejmowane. Ogólnie wkładanych jest n+1 sekcji, gdzie n jest liczbą poziomów w hierarchii klas Wizja ta może być bezpośrednio zaimplementowana, ale jest ona dość rozrzutna jeżeli chodzi o zużycie zasobów, gdyż może przy okazji przetwarzania każdego obiektu wkładać na stos i zdejmować wiele sekcji. Możliwe są proste optymalizacje.

79 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 79 kwiecień 2002 Przetwarzanie obiektu Prac w M1 Nazwisko (i 5 ) RokUr (i 6 ) Zar (i 7 ) PracujeW (i 8 ) ZmieńZar(i 51 ) ZarNetto(i 52 )... Wiek(i 51 ) Prac(i 4 ) Prac(i 9 ),... Osoba(i 1 ) Osoba(i 4 ) Osoba(i 9 ),... Sekcja zawierająca nested(i 4 ) - własności aktualnie przetwarzanego obiektu i 4 Bindery do własności klasy KlasaPrac (połączonej z i 4 związkiem OK). Bindery do własności klasy KlasaOsoba (połączonej z KlasaPrac związkiem KK).... inne sekcje... Bindery do obiektów bazy danych, zdublowane dla różnych nazw. Kolejność przeszukiwania stosu Operator niealgebraiczny, np. where w zapytaniu Prac where Wiek > avg(Prac.Wiek) przetwarza obiekt Nowaka (z identyfikatorem i 4 ) dla bazy danych przedstawionej poprzednio.

80 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 80 kwiecień 2002 Zdublowane bindery w M1 Sekcja binderów do obiektów bazy danych zawiera bindery do obiektów i 4 oraz i 9 opatrzone zarówno nazwą Prac, jak i nazwą Osoba. Jest to jeden z wariantów uwzględnienia zasady zamienialności. Dodatkowe bindery Osoba pojawiają się na podstawie nazw obiektów będących inwariantami klas oraz związku KK. Zakładamy tu, że jeżeli wiązana była nazwa Osoba, to kontrola typologiczna ograniczy możliwość użycia własności obiektu Prac nie będących atrybutami obiektów Osoba. Dla języków pozbawionych mocnej kontroli typów ta metoda może prowadzić do anomalii; np. wiążąc nazwę Osoba mamy dostęp do takich własności jak Zar i ZarNetto. Jest to sprzeczne z zasadami obiektowości. W klasycznych modelach obiektowych problem nie występuje, gdyż: typy lub klasy nie przesądzają nazw obiektów, zasada zamienialności jest konsekwencją hierarchii dziedziczenia klas lub typów.

81 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 81 kwiecień 2002 Przetwarzanie metod Dotychczas przyjmowaliśmy, że wiązanie polega wyłącznie na tym, że nazwę występującą w zapytaniu zamienia się np. na referencję obiektu na podstawie bindera wyszukanego na stosie ENVS. Dla metod ta zasada jest rozszerzona. Jeżeli wiązana nazwa jest nazwą metody, to: Następuje wiązanie jej nazwy jak zwykle na stosie ENVS; Po związaniu, metoda jest wywoływana; Wywołanie metody powoduje utworzenie nowej sekcji na stosie ENVS - zapisu aktywacji, zawierającego bindery do lokalnego środowiska metody, tj. jej parametrów i lokalnych obiektów, następnie wejście sterowania w kod. Zapis aktywacji zawiera także ślad powrotu z metody. Aktualne parametry metody są pobierane ze stosu rezultatów QRES i następnie wstawiane do lokalnego środowiska. Niekiedy może nam zależeć na pobraniu identyfikatora metody, a nie na jej wywołaniu, np. celem przekazania metody jako parametru. W tym celu potrzebna jest specjalna składnia, np. ref Wiek.

82 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 82 kwiecień 2002 Kroki przetwarzania dla r 1 : Co się dzieje, gdy wołana jest metoda? method met( p 1 : T1, p 2 : T2 ): T (*sygnatura*) begin x 1 : T11, x 2 : T12; (* lokalne obiekty *).... end met; Implementacja metody w ramach klasy K Poprzedni stan ENVS q... met(q 1, q 2 )... Niech eval(q) zwróci bag{r 1, r 2,....}, gdzie są referencjami do obiektów będących członkami klasy K. Wiązanie i wywołanie metody met Użycie metody w zapytaniu gdzie jest operatorem niealgebraicznym nested(r 1 ) Bindery do publicznych własności K Poprzedni stan ENVS Rezultat q Poprzedni stan QRES Operator Obliczenie q Rezultat q 2 Rezultat q 1 Rezultat q Poprzedni stan QRES Obliczenie parametrów q 1, q 2 Sekcja lokalna metody met p 1 (Rezultat q 1 ) p 2 (Rezultat q 2 ) x 1 (..) x 2 (..) Bindery do prywatnych własności K nested(r 1 ) Bindery do publicznych własności K Poprzedni stan ENVS Rezultat q Poprzedni stan QRES Usunięcie rezultatów q 1, q 2 Przetwarzanie ciała metody met p 1 (Rezultat q 1 ) p 2 (Rezultat q 2 ) x 1 (..) x 2 (..) Bindery do prywatnych własności K nested(r 1 ) Bindery do publicznych własności K Poprzedni stan ENVS

83 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 83 kwiecień 2002 Podsumowanie zmian semantycznych w M1 Zmiany w globalnych sekcjach binderów (m.in. do bazy danych): dowolny binder n(i) wynikający ze zbioru R identyfikatorów startowych jest uzupełniany poprzez bindery n1(i), n2(i),..., gdzie n1, n2,... są nazwami ustalonymi jako inwarianty klas nadrzędnych w stosunku do klasy do której należy obiekt i. Jeżeli operator niealgebraiczny przetwarza obiekt z identyfikatorem i należący do klasy K1, która ma kolejne superklasy K2, K3,..., wówczas na wierzchołek stosu środowiskowego wkłada się po kolei, poczynając od wierzchołka: nested(i), bindery do własności K1, bindery do własności K2, bindery do własności K3, itd. Dla metod wiązanie nazw jest skojarzone z wywołaniem. Wywołanie oznacza obliczenie parametrów metody, założenie nowej sekcji (zapisu aktywacji) na czubku ENVS, i następnie, przekazanie sterowania do kodu metody. Nowa sekcja zawiera bindery parametrów, bindery lokalnych obiektów, oraz ślad powrotu.

84 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 84 kwiecień 2002 Klasa K1 Klasa K2 Klasa K4 metoda m Klasa K5 Klasa K3 metoda m Bindery do własności obiektu O Bindery do własności K1 Bindery do własności K2 Bindery do własności K3: m (...) Bindery do własności K4: m (...) Bindery do własności K Bindery danych globalnych Skład obiektów Stos środowisk przy przetwarzaniu obiektu O Wielodziedziczenie w M1 i fałszywe przesłanianie Metoda m z klasy K4 jest przesłonięta przez metodę m z klasy K3, przez co metoda m z klasy K4 nie ma szansy na to, aby była użyta. Jest to złamanie zasady zamienialności (substitutability) Kierunek przeszukiwania stosu Obiekt

85 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 85 kwiecień 2002 Wielokrotne dziedziczenie w M1 Jeżeli pewna klasa dziedziczy z większej liczby klas, to możliwe są dwa przypadki: Nie występuje konflikt nazw pomiędzy własnościami dziedziczonymi z poszczególnych klas. W tym przypadku kolejność klas na stosie powinna uwzględniać hierarchię klas, ale kolejność klas na tym samym poziomie hierarchii nie ma znaczenia. Jeżeli występuje konflikt pomiędzy własnościami dziedziczonymi z poszczególnych klas, to nie istnieje dobry porządek ustawienia klas na stosie. Każdy porządek łamie zasadę zamienialności. Jest to inherentna wada modelu M1, która jest wyeliminowana w modelu M2. Nie ma sposobu uniknięcia anomalii wielodziedziczenia w modelu M1. Jeżeli zabronimy użycia identycznych nazw metod w nadklasach, to łamiemy zasadę "klasa otwarta dla specjalizacji, zamknięta dla zmian". Jeżeli dopuścimy zmianę nazwy metody w podklasie, to łamiemy zarówno zasadę zamienialności, jak i zasadę koncepcyjnej kontynuacji.

86 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 86 kwiecień 2002 Skąd problemy wielodziedziczenia w M1? Wynikają one z faktu zmieszania w jednym środowisku własności różnych klas, często niekompatybilnych. Jest to przyczyna tego, że w niektórych językach i systemach zrezygnowano z wielokrotnego dziedziczenia. Nie usuwa to problemu, ponieważ w ten sposób zwiększa się dystans pomiędzy modelowaniem pojęciowym a modelem implementacyjnym. Brak wielodziedziczenia łamie zasadę otwarte-zamknięte (open-close principle), podstawowej dla ponownego użycia (reuse). Model a la M1 jest stosowany w większości języków i systemów obiektowych (z różnymi nazwami, mutacjami i własnościami). Niezależnie od tego, czy zezwala on na wielodziedziczenie (C++, OMG CORBA, standard ODMG, standardy SQL3 i SQL1999), czy też nie (Smalltalk, Java), zawsze pojawią się w nim pewne wady bądź w zakresie modelowania pojęciowego, bądź też w postaci anomalii technicznych tworzących rafy dla programistów. Sposobem usunięcia tych wad jest przyjęcie modelu M2 (i modeli pochodnych), zakładających koncepcję dynamicznych ról obiektów.

87 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 87 kwiecień 2002 Przykłady zapytań w modelu M1 Schemat obiektowy (diagram klas) Osoba[0..*] Nazwisko RokUr Wiek() Prac[0..*] NrP Zawód[1..*] Zar ZmieńZar(nowy) ZarNetto( ) Dział [0..*] NrD Nazwa Lokacja[1..*] BudżetRoczny() Kieruje [0..1] Szef PracujeW Zatrudnia [1..*] Nazwa działu i średni wiek jego pracowników: Dział. ( Nazwa, avg(Zatrudnia.Prac.Wiek()) as Średnia) Dziedziczenie metody Wiek przez klasę Prac. Podaj nazwiska, zarobek netto i nazwisko szefa dla programistów pracujących w Radomiu. (Dział where Lokacja as x (x = "Radom" )) (Zatrudnia.Prac where "programista" Zawód ). (Nazwisko, ZarNetto() as netto, (Szef.Prac.Nazwisko) as boss) Dziedziczenie atrybutu Nazwisko przez klasę Prac. Dla każdego pracownika podaj nazwisko oraz procent budżetu przeznaczony na jego uposażenie. Prac. (Nazwisko as NazwiskoPracownika, (Zar * 12 * 100 / (PracujeW.Dział.BudżetRoczny())) as ProcentBudżetu)

88 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 88 kwiecień 2002 Rozszerzenie SBQL w modelu M2 Jak dotąd, tylko podejście stosowe jest przystosowane do koncepcji obiektowości zakładającej dynamiczne role obiektów, określanej przez nas jako model M2. Pozostałe podejścia, takie jak obiektowe algebry, nie tylko nie rozważają takiej koncepcji, ale są niespójne w stosunku do prostszego modelu M1. Zmiana w stosunku do modeli M0 i M1 polega na sposobie zapełniania bazowych sekcji stosu. W tym przypadku sekcja bazowa ENVS musi zawierać bindery do wszystkich ról obiektów, gdyż identyfikatory startowe (zbiór R) obejmują wszystkie aktualne role wszystkich obiektów. W modelu M2 obiekt występuje wyłącznie jako konglomerat ról, z jedną wyróżnioną rolą główną.

89 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 89 kwiecień 2002 Graficzna reprezentacja przykładu modelu M2 i 1 Osoba i 2 Nazwisko Wilski i 3 RokUr 1950 i 40 KlasaOsoba i 41 Wiek (...kod...) i 50 KlasaPrac i 51 ZmieńZar (...kod...) i 52 ZarNetto (...kod...) i 60 KlasaStudent i 61 ŚredniaOcen (...kod...) i 13 Prac i 14 Zar 2500 i 15 PracujeW i 127 i 4 Osoba i 5 Nazwisko Nowak i 6 RokUr 1944 i 7 Osoba i 8 Nazwisko Kowalski i 9 RokUr 1940 i 128 i 16 Prac i 17 Zar 2000 i 18 PracujeW i 19 Student i 20 NrIndeksu i 21 Wydział fizyka

90 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 90 kwiecień 2002 Dolne sekcje ENVS w modelu M Bindery do obiektów/zmiennych nietrwałych aktualnej sesji użytkownika Osoba( i 1 ) Osoba( i 4 ) Osoba( i 8 ) Prac( i 13 ) Prac( i 16 ) Student( i 19 )... Bindery do globalnych funkcji bibliotecznych Bindery do zmiennych i funkcji środowiska komputerowego Sekcje danych globalnych Sekcja bazy danych

91 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 91 kwiecień 2002 Przykład stanu stosu ENVS dla M2 Zapytanie ma postać Prac where... n... Przetwarzana jest rola z identyfikatorem i 16, wiązana jest nazwa n Bindery do własności aktualnie przetwarzanej roli Prac Bindery do własności klasy KlasaPrac Bindery do własności roli Osoba będącej super-rolą aktualnie przetwarzanej roli Prac Bindery do własności klasy KlasaOsoba Sekcja bazy danych Kolejność przeszukiwania stosu Zar( i 17 ) PracujeW( i 18 ) ZmieńZar( i 51 ) ZarNetto( i 52 )... Nazwisko( i 8 ) RokUr( i 9 ) Wiek( i 41 ) Osoba( i 1 ) Osoba( i 4 ) Osoba( i 8 ) Prac( i 13 ) Prac( i 16 ) Student( i 19 )

92 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 92 kwiecień 2002 i K1R1 K1R1 i K2R1 K2R1 i K3R1 K3R1 i K1R2 K1R2 i K2R2 K2R2 i K3R2 K3R2 i K1R3 K1R3 i K2R3 K2R3 i K3R3 C3R3 i R2 R2 i R1 R1 i R3 R3 Obiekt z rolami Klasy Obiekty i role Uogólnienie: skład z rolami w M2 Klasy KjRi (j = 1,2,...) nie muszą być unikalne; mogą tworzyć graf dziedziczenia.

93 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 93 kwiecień 2002 Organizacja i kolejność przeszukiwania ENVS Operator nie-algebraiczny przetwarza rolę R1 nested(i R1 ) nested(i K1R1 ) nested(i K2R1 )... nested(i R2 ) nested(i K1R2 ) nested(i K2R2 )... nested(i R3 ) nested(i K1R3 )... sekcje roli R1 sekcje roli R2 sekcje roli R3 Kolejność przeszukiwania stosu

94 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 94 kwiecień 2002 Uwagi do poprzedniego rysunku Może się zdarzyć, że pewne sekcje klas wkładanych na stos będą się powtarzać. Poza koncepcyjną redundancją (którą można łatwo wyeliminować w implementacji) w niczym to nie przeszkadza, ponieważ istotna będzie tylko ta sekcja, która jest najbliższa wierzchołka stosu. Duplikaty sekcji znajdujące się poniżej w stosie nie będą uczestniczyć w wiązaniu nazw. Po ewaluacji zapytania q 2 wszystkie te sekcje będą zdjęte ze stosu. Reguły wiązania nazw są takie same jak w przypadku modelu M0. Nie występują tu anomalie przy wiązaniu nazw, które były omawiane przy okazji modelu M1.

95 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 95 kwiecień 2002 Operatory rzutowania w modelu M2 Model M2 implikuje operator algebraicznego znany z innych języków pod nazwą rzutowanie (casting). Chodzi o możliwość przełączenia się z danej roli obiektu do innej roli tego samego obiektu. Syntaktycznie, operator ten będzie zapisywany w postaci: (nazwa) zapytanie gdzie nazwa jest nazwą roli, zapytanie zwraca wielozbiór identyfikatorów ról. Operator ten dla danego identyfikatora roli zwróconego przez zapytanie wyszukuje w ramach tego samego obiektu role nazwa. Operator zwraca identyfikatory ról. Końcowy wynik jest sumą mnogościową wyników dla wszystkich identyfikatorów zwróconych przez zapytanie. Przykład. Podaj pracowników, którzy są jednocześnie studentami. (Prac) Student Ewaluacja zapytania Student zwróci identyfikatory wszystkich ról Student. Operator rzutowania (Prac) zmieni niektóre z nich na identyfikatory ról Prac (jeżeli obiekt ma jednocześnie role Student i Prac), zaś inne na wartość pustą.

96 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 96 kwiecień 2002 Przykład operatora rzutowania Załóżmy, że role Student mają atrybut Stypendium. Dla każdej osoby należy zwrócić Nazwisko oraz dochody, które wynoszą 0, jeżeli dana osoba nie jest ani pracownikiem ani studentem, Zar jeżeli osoba jest pracownikiem, Stypendium jeżeli osoba jest studentem, lub Zar+Stypendium, jeżeli osoba jest jednocześnie pracownikiem i studentem. (Osoba as p). (p.Nazwisko, sum( bag( 0, ((Student)p).Stypendium, ((Prac)p).Zar ) ) sum jest funkcją agregowaną znaną z SQL. Pomocnicza nazwa p obiega wszystkie role Osoba. Po pierwszej kropce następuje wyliczenie wyniku dla pojedynczej wartości p. Na wynik ten składa się Nazwisko danej osoby oraz suma dochodów. Dla wyliczenie tej sumy tworzy się wielozbiór składając się z jednego, dwóch lub trzech elementów. Jeżeli p posiada rolę Student, to p jest rzutowane na tę rolę, z tej roli pobiera się Stypendium; podobnie dla roli Prac i atrybutu Zar. Podane zapytanie automatycznie uwzględni fakt, że dana osoba jest kilkakrotnie pracownikiem i/lub kilkakrotnie studentem.

97 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 97 kwiecień 2002 Rozszerzenie SBQL w modelu M3 Model M3 rozszerza M1 i M2 o listę eksportową, która dzieli własności klasy oraz własności obiektów tej klasy na publiczne i prywatne. Własności prywatne zarówno klasy K, jak i obiektów klasy K, są dostępne wyłącznie z wnętrza ciała metod (publicznych i prywatnych) klasy K. Można to prosto zrealizować poprzez odpowiednie ustawienie sekcji stosu oraz poprawkę do funkcji nested. Niech i K będzie identyfikatorem obiektu klasy K posiadającej listę eksportową export K nested_private( i K ) = {n(x) : n nested( i K ) and n export K } nested_public( i K ) = {n(x) : n nested( i K ) and n export K } Dla pozostałych argumentów funkcje te nie ulegają zmianie. Funkcje te w sposób naturalny (czyli podobnie jak poprzednio) rozszerzamy na dowolne struktury: nested_private( struct{ x 1, x 2,...}) = nested_private( x 1 ) nested_private( x 2 )... nested_public ( struct{ x 1, x 2,...}) = nested_public ( x 1 ) nested_public ( x 2 )...

98 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 98 kwiecień 2002 Poprzedni stan ENVS Operator Przetwarzanie obiektów w M3 Zapytanie q 1 q 2, gdzie jest operatorem niealgebraicznym. Niech eval(q) zwróci bag{r 1, r 2,....}, gdzie r 1, r 2,.... są referencjami do obiektów będących członkami klasy K1, która jest podklasą K2, która jest podklasą K3. Niech wiązana będzie pewna nazwa m występująca w q 2 ; m nie jest nazwą metody. Kroki przetwarzania dla r i : Poprzedni stan ENVS nested_public(r i ) nested_public(i K1 ) nested_public(i K2 ) nested_public(i K3 ) Poprzedni stan ENVS Sekcje wkładane przy przetwarzaniu r i Koniec przetwarzania r i przez q 2

99 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 99 kwiecień 2002 Przetwarzanie metod w M3 Założenia jak poprzednio. Niech wiązana będzie pewna nazwa n występująca w q 2 ; m jest nazwą metody, która znajduje się w klasie K2. Kroki przetwarzania dla r i : Poprzedni stan ENVS nested_public(r i ) nested_public(i K1 ) nested_public(i K2 ) nested_public(i K3 ) Poprzedni stan ENVS nested_public(r i ) nested_public(i K1 ) nested_public(i K2 ) nested_public(i K3 ) Poprzedni stan ENVS Lokalne środowisko metody m nested_private(i K2 ) nested_ private(r i ) nested_public(r i ) nested_public(i K1 ) nested_public(i K2 ) nested_public(i K3 ) Poprzedni stan ENVS Wywołanie metody m Prywatne własności klasy K2 Prywatne własności obiektu z OID = r i Środowisko indukowane przez wywołanie m Środowisko indukowane przez

100 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 100 kwiecień 2002 Reguły zakresu dla M3 Załóżmy, że dla rozpatrywanego zapytania q 1 q 2 zachodzi: aktualnie wykonywana jest metoda m 1 występująca w q 2 i przetwarzająca r i zapytanie występuje wewnątrz ciała metody m 2 m 2 została wywołana z metody m 3 Kolejność wiązania nazw występujących w ciele m 1 Środowisko indukowane przez wywołanie m 1 dla r i Środowisko indukowane przez q 2, w którym zanurzone jest wołanie metody m 1 Środowisko indukowane przez dla r i Środowisko indukowane przez wywołanie m 2 Środowisko indukowane przez wywołanie m 3... Sekcje bazowe ENVS Lexical scoping: programista piszący m 1 nie znał tych środowisk. Wobec tego nazwy występujące w m 1 nie mogą być w nich wiązane.

101 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 101 kwiecień 2002 Przykłady poprawnych i błędnych zapytań w M3 + PracujeW Osoba + Nazwisko - RokUr + Wiek Prac - Zar + ZmieńZar + ZarNetto Osoba where Nazwisko = "Nowak" Dział + Nazwa + Budżet + Zatrudnia Poprawne Błędne (Osoba where Nazwisko = "Nowak").RokUr (Prac where Nazwisko = "Nowak").Wiek Poprawne (Prac where Nazwisko = "Nowak").Zar Błędne method Wiek() { return BieżącyRok - RokUr } Poprawne method ZmieńZar( nowy ) { Zar := nowy } Poprawne Błędne method ZarNetto( ) { if RokUr > 1955 then return 0.9 * Zar else return 0.8 * Zar } Prac where Dział (Budżet > 100 * ZarNetto).... method ZarNetto( ) { if Nazwa = "Marketing" then return 0.9 * Zar else return 0.8 * Zar } Błędne

102 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 102 kwiecień 2002 Wykład 9

103 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 103 kwiecień 2002 Konstrukcje imperatywne oparte na SBQL

104 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 104 kwiecień 2002 Zapytania jako wyrażenia języka programowania W SBA zapytania pełnią rolę wyrażeń języka programowania. Zapytania będą również stosowane do nietrwałych danych. Inaczej mówiąc przyjęliśmy, że w naszym (hipotetycznym) języku programowania nie będzie innych wyrażeń niż zapytania. To założenie jest rewolucją w odniesieniu do języków zapytań. W SQL zapytania zagnieżdżone w język programowania mogły odwoływać się do zmiennych języka programowania poprzez specjalną składnię. Podział na wyrażenia i zapytania przyjmują języki czwartej generacji (4GL). PL/SQL system Oracle, pierwszy komercyjny język programowania w pełni zintegrowany z językiem SQL, również wprowadza podział na wyrażenia i zapytania. Powodem są ograniczenia i narzuty składniowe języka SQL, w którym nie da się zapisać są tak prostych wyrażeń jak 2+2. Jest jednak oczywiste, że wyrażenia i zapytania muszą mieć niepuste przecięcie, co stawia pod znakiem zapytania ten podział.

105 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 105 kwiecień 2002 Zastosowania zapytań w jęz. programowania Zapytania, jako wyrażenia języka programowania, będą używane we wszystkich kontekstach w których używane są wyrażenia, w szczególności w następujących: Jako składowa zdań imperatywnych, np. instrukcji podstawienia, usuwania, tworzenia i wstawiania. Jako parametry procedur, funkcji lub metod, przy zachowaniu klasycznych metod przekazywania parametrów znanych jako wołanie przez wartość (call- by-value) oraz wołanie przez referencję (call-by-reference). Jako składnik zdania return określającego wynik procedury lub metody funkcyjnej. Jako składnik iteratora znanego jako for each... do..., określający ilość pętli iteratora oraz element przetwarzany w każdym jego cyklu.

106 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 106 kwiecień 2002 Czy taki język nie jest utopią? Jakiego rodzaju zagrożenia można wiązać z realizacją języka programowania o podanych własnościach? Są one następujące: Niska wydajność. Ale: Wiele metod optymalizacyjnych wiązanych z modelem relacyjnym ma bezpośrednie odpowiedniki dla modeli obiektowych. Np. indeksy. Dla SBQL zostały odkryte nieznane wcześniej bardzo mocne metody optymalizacyjne oparte na przepisywaniu. Trudności z wypromowaniem nowego języka programowania. Ale: Java stała się szybko popularna, mimo że nie występują w niej cechy nieznane w poprzednich językach. (Jest nową kombinacją popularnych cech.) PHP w ciągu dwóch lat zdobył miliony zwolenników. Wiele rynkowych systemów jest wyposażana w języki o bardzo specyficznych nazwach i rozwiązaniach. Użytkownikom to nie przeszkadza. Świat badawczo-rozwojowy nie może zastopować badań i rozwoju z powodu potencjalnych trudności z powszechnym wdrożeniem.

107 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 107 kwiecień 2002 Konstrukcje deklaratywne i imperatywne Założeniem języków zapytań jest deklaratywność, czyli wyrażanie bezpośrednio celu wyszukiwania. Deklaratywność jest wiązana z programowaniem w logice, np. językami Prolog lub Datalog. Zwolennicy tego podejścia twierdzą niekiedy, że tylko wyrażenia logiki matematycznej (i pochodne) są deklaratywne. Są to próby zbudowania fałszywego stereotypu. Pseudo-naukowe bzdury. Deklaratywność wynika z psychologii, odczuć użytkownika języka, a nie z jakichkolwiek tworów formalnych. Zarówno algebra relacji jak i SQL są uważane za języki deklaracyjne, mimo że ich semantyka jest objaśniana w sposób operacyjny. Deklaratywność nie jest celem samym w sobie - ma o tyle znaczenie, o ile skraca czas tworzenia programu, czyni go bardziej zrozumiałym, oraz zapewnia łatwiejszą i mniej kosztowną jego pielęgnację. Kluczem do deklaratywności jest uzyskanie jak najprostszego odwzorowania pojęciowego pomiędzy rzeczywistym problemem w dziedzinie przedmiotowej, a zapisem bądź rozwiązaniem tego problemu w środowisku komputerowym.

108 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 108 kwiecień 2002 Konstrukcje deklaratywne a zmiany stanu Konstrukcje deklaratywne nie mogą (nie powinny) zmieniać stanu. Stan jest pojęciem związanym z czasem i następstwem czynności. Zmiany stanu wymagają wprowadzenia konstrukcji imperatywnych. Twórcy koncepcji opartych na programowaniu w logice starają się retuszować ten oczywisty fakt poprzez różnorodne konstrukcje. Np. w systemie LDL zastosowano "mimikrę syntaktyczną" w postaci symbolu -, który przypomina negację, ale w istocie jest konstrukcją imperatywną, której semantyką jest usunięcie pewnej danej. Obecność tego rodzaju sztuczek stawia pytanie, czy w misji zbudowania fałszywego stereotypu programowania deklaracyjnego niektórzy naukowcy nie posuwają się zbyt daleko, poza granicę etyki naukowej, która zabrania oszukiwania czytelników, użytkowników (i samych siebie). Z reguły, zmiany stanu są przemycane w tego rodzaju koncepcjach i językach poprzez różnorodne efekty uboczne. Te "efekty uboczne" podkopują formalną podstawę programowania w logice; powodują, że tysiące twierdzeń i wniosków udowodnionych przez armię akademickich "teoretyków" można a priori skierować do składu śmieci.

109 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 109 kwiecień 2002 SBQL a konstrukcje imperatywne Przy rozszerzeniach SBQL będziemy starali się trzymać czystości rozdzielenia tej części języka, która nie może zmienić stanu obiektów (czyli deklaratywnych zapytań), oraz części, która będzie zajmować się zmianami stanu (czyli części imperatywnej). Efekty uboczne w zapytaniach będziemy uważać za niewskazane. Poprzez efekty uboczne wyrażenia stają się mniej czytelne, błędogenne oraz bardziej kłopotliwe podczas zmian oprogramowania; Efekty uboczne mogą zakłócić lub uniemożliwić optymalizację zapytań. Nie możemy też zabronić użycia efektów ubocznych w zapytaniach. Programista może wewnątrz zapytania wywołać funkcję lub metodę. Nie będziemy dzielić funkcji i metod w zależności od posiadania efektów ubocznych. Wprowadziłoby to zbytnią komplikację do języka i jego użycia. Efekty uboczne w zapytaniach powinny być stosowane w sytuacji pewności, że nie zakłóci to optymalizacji i nie doprowadzi do złego wyniku.

110 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 110 kwiecień 2002 Zasada korespondencji Podstawowy drogowskaz przy konstruowaniu języka programowania. Zasada korespondencji mówi, że wraz z wprowadzeniem do języka pewnej cechy X należy precyzyjnie określić inne cechy języka w taki sposób, aby cecha X współdziałała z już istniejącymi konstrukcjami, została wtopiona w istniejące lub zmodyfikowane mechanizmy nazywania, typowania, zakresu i wiązania, oraz miała zapewnioną uniwersalną obsługę. Przykładowo, jeżeli cecha X jest dynamiczną tablicą, to odpowiednimi pytaniami są: czy może ona być składową zapisu (struktury, obiektu), czy może być parametrem procedury, czy może być zwrócona przez procedurę funkcyjną, jakie środki będą przewidziane do typizacji, wyszukiwania, aktualizacji, usuwania, dostawiania elementów; itd. Oddolny rozwój niektórych języków (np. SQL) jest przyczyną wielu przypadków łamania zasady korespondencji, co objawia się m.in. tym, że nowo dodawane cechy nie są gładko połączone ze starymi cechami. correspondence principle

111 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 111 kwiecień 2002 Przegląd operatorów imperatywnych

112 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 112 kwiecień 2002 Operator tworzenia obiektu Może to być deklarowanie obiektu, czyli utworzeniem obiektu w momencie inicjacji pewnej abstrakcji programistycznej (np. metody). Może to być dynamiczne utworzenie obiektu na polecenie wydane explicite przez programistę - operator musi być dodatkowo parametryzowany miejscem składu i statusem trwałości. Operator powinien być makroskopowy. Operator powinien dawać możliwość utworzenia nowej danej elementarnej oraz nowej danej pointerowej wewnątrz określonego obiektu. Operator powinien dawać możliwość utworzenia nowego modułu, klasy, metody, perspektywy, procedury, ograniczenia, trygera, itd. Generalnie, dla dowolnego elementu składu obiektów powinna istnieć odmiana tego operatora pozwalająca na utworzenie tego elementu w określonym środowisku.

113 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 113 kwiecień 2002 Operator podstawienia i wstawiania Operator podstawienia powinien umożliwiać podstawienie makroskopowe, w stylu klauzuli update języka SQL. Podstawienie może dotyczyć wartości atomowych oraz wartości złożonych. Musi istnieć odmiana operatora podstawienia pozwalająca na aktualizację danej pointerowej oraz dowolnego innego elementu składu obiektów, o którym zakłada się, że może podlegać aktualizacji. Operator wstawiania obiektu powinien umożliwiać wstawianie makroskopowe, w stylu klauzuli insert języka SQL. Ma on za zadanie wstawić pewien obiekt (obiekty) jako podobiekt (podobiekty) innego obiektu. Wybrany obiekt jest przesuwany z dotychczasowego środowiska do określonego środowiska. Powinien on działać na wszystkich typach obiektów, włączając obiekty złożone, klasy, metody, perspektywy, itd. Dla modelu M2 powinna istnieć odmiana tego operatora pozwalająca podłączyć do istniejącej roli nową rolę.

114 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 114 kwiecień 2002 Operator usuwania Operator usuwania powinien umożliwiać usuwanie makroskopowe, w stylu klauzuli delete języka SQL. Dotyczy obiektów tworzonych (nie deklarowanych) przez programistę i oznacza usunięcie obiektu z określonego środowiska. Operator usuwania powinien dotyczyć wszystkich rodzajów obiektów, w tym obiektów atomowych, pointerowych, złożonych., klas, metod, perspektyw, itd. Niektórzy lansują pogląd, że operator usuwania nie powinien być dostępny programiście, gdyż może prowadzić do tzw. zwisających pointerów. Programista usuwa pointery do obiektu, natomiast usunięcie samego obiektu załatwia automatyczny odśmiecacz (garbage collector). Ten pogląd jest powierzchowny, wynikający z niezrozumienia problemu. Pozostawienie obiektu, który już nie powinien istnieć, jest tak samo błędogenne jak zwisający pointer. Należy usuwać obiekty z automatycznym usunięciem/wyzerowaniem prowadzących do nich pointerów.

115 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 115 kwiecień 2002 Inne operatory elementarne Operator deklaracji stałej lub makrosa. Można go uważać za operator tworzenia obiektu niemodyfikowalnego. Istotą tego operatora jest to, że wszelkie operacje związane z tym operatorem są wykonywane podczas kompilacji. Deklaracja ma np. postać: constant = ; gdzie jest w zasadzie dowolnym tekstem (tzw. makrosem) który zastąpi po kompilacji każde użycie. Operator zmiany nazwy obiektu lub utworzenia nowego aliasu dla obiektu. Dotyczy raczej szczególnych sytuacji i jest możliwy wyłącznie w przypadku gdy nazwy obiektów są pierwszej kategorii programistycznej. Operator zmiany nazwy powinien być makroskopowy. Operatory dotyczące zdarzeń: wygenerowanie zdarzenia, przechwycenie zaistniałego zdarzenia.

116 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 116 kwiecień 2002 Operatory warunkowe i przełączania Operator warunkowy: if then else if then Wariant dla wyrażeń: if then else Operator przełączania: posiada wiele wariantów, np. case do :,... : else Semantycznie, obliczane jest ; jeżeli wyrażenie zwróci wartość wówczas wykonywany jest. Jeżeli nie zwróciło wartości równej jakiejkolwiek etykiecie, wówczas wykonywany jest. Fraza else jest zwykle opcyjna.

117 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 117 kwiecień 2002 Operatory pętli while do Operator powtarza wyliczenie wyrażenia i wykonanie bloku aż do momentu, kiedy będzie nieprawdziwy. Jeżeli jest na samym początku nieprawdziwy, wówczas nie jest wykonywany ani razu. repeat until Najpierw następuje wykonanie bloku, następnie wyliczenie wyrażenia ; jeżeli jest prawdziwy, to sterowanie jest przekazywane dalej, w przeciwnym przypadku powtarzane jest wykonanie bloku, z ponownym wyliczeniem wyrażenia. Modyfikacja tych operatorów polega na wprowadzeniu specjalnej instrukcji break, której wykonanie wewnątrz powoduje przekazanie sterowania do instrukcji znajdującego się za tą konstrukcją. loop przerwanie pętli wymaga użycia instrukcji break.

118 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 118 kwiecień 2002 Operator for Intencją tego operatora jest powtórzenie wykonania pewnego programu dla kolejnych wartości tzw. zmiennej iteracyjnej, przyjmującej wartości z zadanego przedziału numerycznego, np. ze składnią: for = until do Początkowa i końcowa wartość zmiennej iteracyjnej jest określona z góry przez programistę, zaś przyrost tej zmiennej w poszczególnych cyklach iteracyjnych wynosi 1. Składnia ta została uogólniona na przypadek, kiedy początkowa i końcowa wartość zmiennej oraz przyrost są określone przez dowolne wyrażenie: np.C: for( = ; ; ) Dodatkowo jest możliwe zakończenie cyklu iteracyjnego poprzez wydanie w dowolnym miejscu instrukcji break.

119 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 119 kwiecień 2002 Operator for each Intencja tego operatora jest nieco różna od operatora for. Chodzi tu o iterację obiegającą po kolei wszystkie elementy pewnej kolekcji, zapamiętanej lub wyliczonej przez zapytanie. Składnia jest zwykle następująca: for each in do Operator ten jest bardzo użyteczny dla programowania baz danych, zajmiemy się więc nim dokładniej nieco dalej.

120 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 120 kwiecień 2002 Iteratory niższego poziomu Występują w postaci spójnej rodziny operatorów lub metod, niekiedy hermetyzowanej w postaci klasy lub szablonu. Służą do sekwencyjnego przetwarzania elementów kolekcji. Typowym przykładem są kursory znane z języka SQL lub iteratory. Klasyczny zestaw takich operatorów jest następujący (z dokładnością do nazw operatorów): getFirst, getNext, getPrior, wyjątek NoMoreElements Zwykle takie metody zwracają referencję do bieżącego elementu, która dalej jest przetwarzana przy pomocy standardowych metod (nie dotyczy to SQL). Iteratory niższego poziomu można zastąpić konstrukcją for each. Istnieją zadania, których nie można zrealizować przy pomocy for each; klasycznym przykładem jest algorytm zlania (merging) dwóch posortowanych zbiorów w jeden posortowany zbiór. Problem z iteratorami niższego poziomu polega na tym, że wymagają one wprowadzenia pojęcia elementu bieżącego. To prowadzi do trudności z zagnieżdżonym wywoływaniem iteratorów, w szczególności z rekurencją.

121 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 121 kwiecień 2002 Procedury Imperatywne języki programowania, w tym języki obiektowe, są wyposażone w procedury. Są to najważniejsze jak dotąd mechanizmy abstrakcji i hermetyzacji. Istotą procedur to, że hermetyzują one dowolnie złożony i długi kod. Wewnątrz kodu mogą być zadeklarowane lokalne zmienne lub obiekty, które są całkowicie niedostępne z zewnątrz procedury. Procedury mogą być wywoływane z wielu miejsc. Mogą być rekurencyjne. Ich przystosowanie do konkretnego celu następuje poprzez parametry. Procedury mogą mieć tzw. efekty uboczne. Pasywne efekty uboczne: kod wewnątrz procedury odwołuje się do pewnych danych/obiektów spoza ciała danej procedury. Aktywne efekty uboczne: kod wewnątrz procedury może zmieniać dane, obiekty spoza ciała danej procedury. Może także zmieniać stan środowiska komputerowego, np. stan ekranu lub plików. procedures

122 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 122 kwiecień 2002 Klasyfikacje procedur W zależności od pewnych dodatkowych własności procedury mogą być dalej podzielone wg następującej klasyfikacji: Procedury właściwe i procedury funkcyjne (zwane też funkcjami). Pierwsze nie zwracają wyniku, nie mogą więc być użyte jako składniki wyrażeń, drugie zaś zwracają wynik i przez to ich wywołania są wyrażeniami. Procedury i metody. Różnica dotyczy miejsca logicznego ulokowania kodu procedur oraz sposobu ich wywołania. Procedury są zwykle ulokowane w określonych jednostkach programu, np. w modułach, natomiast metody są ulokowane w klasach. Dodatkowo, niejawnym (pośrednim) parametrem metody jest obiekt, na którym ta metoda działa. Procedury znajdujące się po stronie programu aplikacyjnego i procedury przechowywane w bazie danych. W SZBD pojawił się typ procedury, zwany zapamiętaną procedurą (stored procedure) lub procedurą bazy danych (database procedure). Są to byty pierwszej kategorii programistycznej wiązane dynamicznie. Można je dynamicznie wstawiać i usuwać. Występują różne kombinacje tych aspektów klasyfikacyjnych.

123 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 123 kwiecień 2002 Parametry procedur Istnieje wiele semantycznie różnych sposobów komunikowania parametrów do procedur. Najbardziej popularne: Call-by-value. Do wnętrza procedury przekazywana jest wartość parametru obliczona przed przekazaniem sterowania do wnętrza procedury. Wewnątrz procedury tworzy się lokalną zmienną zawierającą tę wartość. Call-by-reference. Do wnętrza procedury przekazywana jest referencja do zmiennej/obiektu. Dzięki temu wewnątrz procedury można dokonać zmiany stanu (aktualizacji) obiektu zewnętrznego w stosunku do tej procedury. Call-by-name. Parametr przekazuje się w postaci kodu wyrażenia będącego parametrem aktualnym. Tekst ten zastępuje (na zasadzie makro) wszystkie wystąpienia parametru formalnego w ciele procedury. Razem z parametrem "przekazuje się" środowisko zewnętrzne procedury. Technika jest "brudna". Call-by-need. Technika przekazywania parametrów określana także jako leniwa ewaluacja (lazy evaluation). Oznacza opóźnienie wyliczania wartości parametru aktualnego do momentu, kiedy będzie on rzeczywiście potrzebny wewnątrz ciała procedury. Technika jest "brudna". Niektóre z tych metod będą uogólnione dla parametrów - zapytań.

124 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 124 kwiecień 2002 Dalsze cechy języka programowania Przy konstrukcji języka programowania uwzględnia się dalsze cechy: System kontroli typologicznej: bardzo istotny dla podwyższenia niezawodności programowania. Polega na przypisywanie typów wszystkim bytom występującym w programie (obiektom, funkcjom, procedurom, metodom, itd.), oraz sprawdzanie zgodności użycia danego bytu w programie z jego zadeklarowanym typem. Hermetyzowane abstrakcje: moduły, klasy, interfejsy, bloki programu. Zdarzenia, wyjątki, aktywne reguły (tryggery), obsługa zdarzeń/wyjątków. Asercje, reguły bezpieczeństwa i inne środki podwyższenia niezawodności. Zarządzanie transakcjami, procesy, wątki i inne środki synchronizacji równolegle działających programów. Programowanie generyczne: metamodel i środki dostępu do metamodelu, refleksja lingwistyczna.

125 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 125 kwiecień 2002 Wybrane operatory imperatywne bazujące na SBQL

126 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 126 kwiecień 2002 Operator for each Składnia: for each do Semantyka: przyjmujemy zasadę operatorów nie-algebraicznych Dla każdego e zwróconego przez, ENVS jest podwyższany o nested(e). W modelach M1, M2, M3, jeżeli e zawiera referencje do obiektów, to na ENVST są wkładane sekcje z binderami do wnętrza odpowiednich klas. Następnie wykonywany jest. Po zakończeniu wykonania ENVS wraca do poprzedniego stanu. Cykl ten jest powtarzany dla wszystkich elementów zwróconych przez. Tak jak w operatorach nie-algebraicznych, "zmienna iteracyjna" jest definiowana przez operator as i nie musi wystąpić. Przykłady: for each Prac where Stan = "asystent" do Zar := Zar + 100; for each (Prac where Stan = "asystent") as p do { p.Zar := p.Zar + 100; p.Stan := "starszy asystent"};

127 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 127 kwiecień 2002 Operator podstawienia W oryginale ten operator ma postać :=. zwraca referencję czyli id.obiektu (l-value), zwraca wartość (r-value), którą należy zapisać do obiektu wskazanego przez referencję. Jeżeli zwraca referencję, to przed podstawieniem należy zastosować operator dereferencji. Jak zmienić ten operator aby stał się makroskopowy? Jeżeli zastosowalibyśmy składnię :=, gdzie zwraca referencje, zaś zwraca wartości, to powstaje problem: którą wartość dopasować do danej referencji? Kolekcja bag nie zawiera informacji o kolejności elementów. Są dwa sposoby: 1. Operator nie jest makroskopowy. Makroskopowe podstawienie można osiągnąć poprzez for each - przykłady na poprzednim slajdzie. 2. Wprowadzić specjalny operator podstawienia (nazwijmy go assign), który będzie działać na kolekcji par, gdzie pierwszym elementem będzie referencja zaś drugim - wartość.

128 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 128 kwiecień 2002 Operator assign Składnia: assign musi zwrócić kolekcje par. Przykład: Podwyższ wszystkim pracownikom zarobek o 100. assign Prac.(Zar, Zar+100); Przykład: Niech dla działów mających lokację w Radomiu nazwa będzie identyczna z nazwiskiem ich szefów. assign ((Dział where "Radom" in Lokacja) as d) ((d.Szef.Prac) as s). (d.Nazwa, s.Nazwisko); Podstawienie nie-makroskopowe (z ewentualnym użyciem operatora for each) jest bardziej intuicyjne dla użytkowników niż operator assign. Główną zaletą koncepcji wprowadzającej operator assign jest podwyższenie mocy i generyczności języka poprzez umożliwienie zakomunikowania danych do makroskopowego podstawienia jako parametru procedury.

129 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 129 kwiecień 2002 Podstawienie na obiekt pointerowy Z zasady korespondencji wynika, że jeżeli wprowadziliśmy obiekty pointerowe, to musimy zapewnić ich aktualizację. Specjalny operator podstawienia :=& różni się od operatora := tym, że po obliczeniu prawej strony (r-value) nie wykonywana jest dereferencja. Operator ten można wprowadzić w wersji nie-makroskopowej (z użyciem for each) oraz w wersji makroskopowej, z użyciem specjalnego operatora (nazwijmy go assign pointer). Przykład: Niech wszyscy programiści przejdą do działu Produkcja. for each Prac where Stan = "programista" do PracujeW :=& (Dział where Nazwa = "Produkcja"); assign pointer (Prac where Stan = "programista"). (PracujeW, (Dział where Nazwa = "Produkcja")); Jeżeli skład zawiera informację o bliźniaczych pointerach, to aktualizacja pointera (pointerów) powinna automatycznie wyzwalać spójną aktualizację jego bliźniaka (bliźniaków). Tak jak w wiązaniu do C++ standardu ODMG.

130 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 130 kwiecień 2002 Procedury w SBQL Składnia: procedure ( ) { }; Nie będziemy różnicować procedur i procedur funkcyjnych. Procedura funkcyjna musi kończyć swoje działanie instrukcją return, gdzie określa wynik działania procedury. może być konstruowane na podstawie lokalnego środowiska procedury oraz środowiska globalnego (np. bazy danych), ale nie powinno zwracać referencji do obiektu znajdującego się w jego lokalnym środowisku. Po zakończeniu działania procedury obiekty te przestaną istnieć. Parametry aktualne procedur są zapytaniami. Parametry mogą być wejściowe (call-by-value) lub wyjściowe (call-by- reference). Rozróżnienie jest np. poprzez słowo kluczowe var. Semantyka: procedura podwyższa stos ENVS wkładając na jego wierzchołek nowa sekcję (zapis aktywacyjny). Zawiera ona: bindery do lokalnych obiektów procedury, bindery do wartości parametrów aktualnych procedury, ślad powrotu z procedury.

131 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 131 kwiecień 2002 Przykład procedury Deklaracja: procedura zmienia dział dla pracowników. Referencje do pracowników i ich nowego działu są jej parametrami. Wywołanie procedury: Przenieść wszystkich analityków do działu kierowanego przez Nowaka: Wersja procedury z automatyczną aktualizacją bliźniaczych pointerów Zatrudnia i PracujeW: procedure ZmieńDział( var P; var D ) { delete Dział.Zatrudnia where Prac in P; for each P as p do { p.PracujeW :=&D create local pointer Zatrudnia( &p ); insert Zatrudnia into D;}; }; ZmieńDział( Prac where Stan = "analityk"; Dział where (Szef.Prac.Nazwisko) = "Nowak" ); procedure ZmieńDział( var P; var D ) { for each P do PracujeW :=&D };

132 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 132 kwiecień 2002 Przykład procedury funkcyjnej Procedura MałoZarabiający zwraca nazwisko, zarobek i nazwę działu dla mało zarabiających pracowników określonych zawodów. Mało zarabiający zarabia mniej niż średnia zarobków. Wynik jest strukturą z nazwami N, Z, D. Przykład: Podaj nazwiska i zarobek dla mało zarabiających piekarzy i stolarzy z działu produkcji. Przykład: Podwyższ o 100 zarobek wszystkim mało zarabiającym programistom z działu konserwacji. procedure MałoZarabiający ( Stanowiska ) { create local Średnia( avg( Prac.Zar ) ); create local pointer Mało( & (Prac where Stan in Stanowiska and Zar < Średnia) ); return Mało.Prac.( Nazwisko as N, Zar as Z, (PracujeW.Dział.Nazwa) as D) }; (MałoZarabiający ( bag("piekarz", "stolarz") ) where D = "produkcja"). (N, Z) for each MałoZarabiający ( bag("programista") ) where D = "Konserwacja" do Z := Z+100;

133 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 133 kwiecień 2002 Wykład 10

134 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 134 kwiecień 2002 Metody w SBQL Są procedurami umieszczonymi w ramach klas w modelach M1, M2 i M3. Istotą ich jest to, ze działają na środowisku obiektu, w stosunku do których są wywoływane. Implikuje to określone reguły zakresu, czyli omijanie lub nie omijanie sekcji ENVS przy wiązaniu. Przykład: metoda ZarobekNetto umieszczona w klasie KlasaPrac: Predefiniowana nazwa self - czy jest potrzebna? Przy podejściu stosowym jest zbędna. Jest jednak istotna dla modelowania pojęciowego, ponieważ explicite odwołuje się do obiektu, na którym działa metoda. method ZarobekNetto ( ) { if self.Zar <500 then return self.Zar else if self.Zar < 1000 then return 0.8 * (self.Zar - 500) else return 0.7 * (self.Zar ) };

135 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 135 kwiecień 2002 Makroskopowe parametry procedur i metod (1) Identyczne techniki transmisji parametrów dotyczą procedur i metod. Rodzaj techniki transmisji parametrów jest określony przez składnię. Wołanie przez wartość (call-by-value) - wariant Pascala: Składnia deklaracji: procedure NazwaProcedury(..., NazwaParam,...){...ciało...}; Składnia wywołania: NazwaProcedury(..., zapytanie,...) Niech zapytanie zwróci bag{ v 1,v 2,... }, gdzie v 1, v 2,... Rezultat Po wywołaniu procedury zapis aktywacyjny procedury/metody (na wierzchołku ENVS) będzie zawierał bindery:..., NazwaParam( dereferencja( v 1 ) ), NazwaParam( dereferencja( v 2 ) ),... Dzięki temu wewnątrz ciała procedury do parametru można będzie odwołać się poprzez NazwaParam, zaś wynikiem tego odwołania będzie bag{dereferencja( v 1 ), dereferencja( v 2 ),... }. Wewnątrz ciała nie można dokonać podstawienia na NazwaParam, gdyż wiązanie nazwy NazwaParam nie zwraca referencji.

136 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 136 kwiecień 2002 Makroskopowe parametry procedur i metod (2) Wołanie przez wartość (call-by-value) - wariant C (różnica semantyczna): Składnia deklaracji - jak poprzednio: procedure NazwaProcedury(..., NazwaParam,...){...ciało...}; Składnia wywołania - jak poprzednio: NazwaProcedury(..., zapytanie,...) Niech zapytanie zwróci bag{ v 1,v 2,... }, gdzie v 1, v 2,... Rezultat Po wywołaniu procedury następuje utworzenie obiektów lokalnych:,,... Zapis aktywacyjny procedury/metody (na wierzchołku ENVS) będzie zawierał bindery:..., NazwaParam( i p1 ), NazwaParam( i p2 ),... Dzięki temu wewnątrz ciała procedury do parametru można będzie odwołać się poprzez NazwaParam (jak poprzednio), ale wynikiem tego odwołania będzie bag{i p1, i p2,... }. Wewnątrz ciała można zatem dokonać podstawienia na NazwaParam - są to zwyczajne obiekty lokalne. Jeżeli parametry nie są makroskopowe, to (podobnie j.w.) tworzy się na ENVS jeden binder (+ewentualnie jeden obiekt).

137 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 137 kwiecień 2002 Przykład parametru wołanego przez wartość Parametrem procedury jest kolekcja nazwisk, wynikiem jest kolekcja par, w której pierwszym elementem referencja do pracownika posiadającego nazwisko znajdujące się w kolekcji będącej parametrem, drugim zaś jest referencja do jego kierownika. procedure PracSzef( Naz ) { return (Prac where (Nazwisko in Naz)) (PracujeW.Dział.Szef.Prac); }; Wywołanie procedury: PracSzef( bag( "Kowal", "Nowak" ) ) W wariancie Pascala, po wywołaniu procedury na wierzchołku ENVS umieszczona będzie sekcja zawierająca bindery: Naz("Kowal"), Naz("Nowak") W wariancie C, po wywołaniu procedury utworzone będą lokalne obiekty,, zaś sekcja na wierzchołku ENVS będzie zawierać bindery Naz(i p1 ), Naz(i p2 ). Po zakończeniu procedury obiekty, muszą być usunięte.

138 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 138 kwiecień 2002 Makroskopowe wołanie przez referencję Składnia deklaracji: procedure NazwaProcedury(..., var NazwaParam,...){...ciało...}; Składnia wywołania: NazwaProcedury(..., zapytanie,...) zapytanie musi zwrócić kolekcję referencji bag{i 1,i 2,... }. Nie jest wykonywana dereferencja. Po wywołaniu procedury zapis aktywacyjny procedury/metody (na wierzchołku ENVS) będzie zawierał bindery:..., NazwaParam(i 1 ), NazwaParam(i 2 ),... Wewnątrz ciała procedury do parametru można będzie odwołać się poprzez NazwaParam, zaś wynikiem tego odwołania będzie bag{i 1, i 2,... }. Wewnątrz ciała można dokonać podstawienia na NazwaParam, co oznacza, że w istocie podstawienie jest dokonywane na obiekcie, którego referencja została zakomunikowana jako parametr. Podobnie dla przypadku, kiedy zapytanie zwróci pojedynczą referencję. call-by-reference

139 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 139 kwiecień 2002 Przykład parametru wołanego przez referencję Parametrem procedury jest kolekcja referencji do pracowników, wynikiem jest podwyższenie ich uposażenia o zadaną wielkość. procedure Podwyżka ( var dlaPrac; Ile ) { for each dlaPrac do Zar := Zar + Ile; }; Wywołanie procedury: Podwyżka( Prac where Stan = "pielęgniarka"; 202 ); Niech zapytanie Prac where Stan = "pielęgniarka" zwróci bag{i 11, i 13, i 55 }. Po wywołaniu procedury na wierzchołku ENVS będzie umieszczona sekcja z binderami: dlaPrac(i 11 ), dlaPrac(i 13 ), dlaPrac(i 55 ), Ile(202).

140 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 140 kwiecień 2002 Makroskopowe wołanie strict-call-by-value Wynik zapytania bez jakichkolwiek zmian przekazuje się jako parametr do wnętrza procedury. Nie jest wykonywana dereferencja. Dla parametru formalnego p, dla którego parametr aktualny - zapytanie - zwrócił wynik r na wierzchołku ENVS tworzy się pojedynczy binder p(r). Ta metoda łączy call-by-value z call-by-referencje. procedure WydatkiDziałów( któreDziały ) { return któreDziały.(Nazwa, sum(Zatrudnia.Prac.Zar)); }; Wywołanie procedury: WydatkiDziałów(Dział where Lokacja bag("Radom", "Kalisz")) Jeżeli zapytanie Dział where Lokacja bag("Radom", "Kalisz") zwróci bag{i 15, i 35, i 59 }, to na wierzchołek ENVS wkłada się pojedynczy binder któreDziały( bag{i 15, i 35, i 59 }).

141 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 141 kwiecień 2002 Perspektywy w SBQL

142 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 142 kwiecień 2002 Perspektywy w SBQL są procedurami funkcyjnymi Taka procedura jest składową bazy danych: może być do niej dynamicznie wstawiona i usunięta. Procedura taka na ogół zwraca kolekcję elementów, które są interpretowane jako "obiekty wirtualne". Może też zwrócić pojedynczy element ("obiekt wirtualny"). Nazwa procedury funkcyjnej staje się nazwą "obiektów wirtualnych". Pamiętamy jednak, że w SBQL zapytania, a więc i procedury, nigdy nie zwracają obiektów, lecz kombinację wartości, referencji i nazw. Procedury takie, podobnie do danych, podlegają ochronie dostępu. Np. pewien użytkownik nie ma dostępu do obiektów, ale może wywołać taką procedurę, co oznacza, że ma dostęp do "obiektów wirtualnych". W zależności od tego gdzie taka procedura jest umieszczona w strukturze obiektowej możemy mieć: wirtualne obiekty (procedura jest na czubku struktury obiektowej); wirtualne atrybuty (procedura jest umieszczona wewnątrz klasy). Procedura może mieć lokalne środowisko (obiekty), może mieć parametry, może być rekurencyjna. Jak poprzednio.

143 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 143 kwiecień 2002 Osoba Nazwisko Płeć RokUrodz Wiek Rodzina Zatrudnia * 1 PracujeW Szef Kieruje Dziecko Mama 0..1 * Dziecko Tata 0..1 * Przykład struktury danych Powiązania rodzinne - drzewo genealogiczne - dla ilustracji procedur rekurencyjnych. Perspektywy są koncepcyjnie równoważne tzw. "regułom dedukcyjnym" w tzw. "dedukcyjnych bazach wiedzy" (Datalog). Rekurencyjne perspektywy z pełną mocą obliczeniową dają znacznie więcej niż "reguły dedukcyjne". Przede wszystkim są manipulowalne jako hermetyzowane byty i są zintegrowane z całością środowiska programistycznego. Dział Dnr Nazwa Lokacja * Prac Pnr Stan Zar ZarNetto

144 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 144 kwiecień 2002 Przykład perspektywy Zwraca wirtualne obiekty BogatyPrac dla takich pracowników, który zarabiają brutto co najmniej W ramach tych obiektów zwraca nazwisko pracownika jako Nazwisko, nazwisko jego szefa jako Szef oraz zarobek netto jako Zarobek. procedure BogatyPrac { return (Prac where Zar >= 3000). ( Nazwisko as Nazwisko, (PracujeW.Dział.Szef.Prac.Nazwisko) as Szef, ZarNetto() as Zarobek); }; Wirtualne obiekty: Nazwiska i zarobki netto bogatych pracowników pracujących dla Wilickiego. (BogatyPrac where Szef = "Wilicki"). (Nazwisko, Zarobek) BogatyPrac Nazwisko Szef Zarobek

145 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 145 kwiecień 2002 Przykład - perspektywa z parametrem Procedura MłodyPrac zwraca wirtualne obiekty o postaci MłodyPrac (Nazw, Wiek, Firma) dla osób o podanym zawodzie, których wiek jest mniejszy o co najmniej 10 lat od średniej wieku. procedure MłodyPrac( Zawód ) { create local GranicaWieku( avg( Prac.Wiek) - 10); (* lokalny obiekt *) return (Prac where Stan = Zawód and Wiek < GranicaWieku ). ( Nazwisko as Nazw, Wiek as Wiek, (PracujeW.Dział.Nazwa) as Firma ); }; Zapytanie: Podaj wszystkie stanowiska oraz średnią wieku młodych pracowników pracujących na tych stanowiskach, jeżeli istnieją; w przeciwnym wypadku podaj informację "Nie ma młodych". (distinct(Prac.Stan) as z) (( MłodyPrac (z) group as m). (if count(m) > 0 then avg(m.Wiek) else "Nie ma młodych" ))

146 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 146 kwiecień 2002 Co zwraca wywołanie procedury MłodyPrac ? Zgodnie z semantyką SBQL, zwracany jest bag zawierający 3-elementowe struktury binderów: bag{struct{ Nazw(i Nazwisko 1), Wiek(w1), Firma(i Nazwa 1) }, struct{ Nazw(i Nazwisko 2), Wiek(w2), Firma(i Nazwa 2) }, struct{ Nazw(i Nazwisko 3), Wiek(w3), Firma(i Nazwa 3) },... } gdzie i Atrybut j jest referencją do odpowiedniego atrybutu. Jest to równoważne sytuacji, jak gdyby nasz diagram obiektowy został uzupełniony o klasę wirtualnych obiektów MłodyPrac. Możliwa jest aktualizacja zapamiętanych danych poprzez atrybuty Nazw i Firma, gdyż zwracają one referencje. Nie wprowadzamy specjalnej składni dla nazywania atrybutów wirtualnych obiektów (jak w SQL). Jest to zaleta dla optymalizacji zapytań. Wynik procedury będącej perspektywą MłodyPrac Nazw Wiek Firma

147 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 147 kwiecień 2002 Perspektywy rekurencyjne Podejście stosowe jest przygotowane do dowolnej rekurencji. Np. należy zdefiniować obiekty wirtualne Genealogia z atrybutami Człowiek, JegoPrzodkowie, która zwraca wielozbiór par, gdzie pierwszym elementem jest referencja do osoby, zaś drugim - kolekcja referencji do jej przodków. Najpierw definiujemy procedurę rekurencyjną z parametrem w postaci wielozbioru referencji do osób. procedure Przodkowie( os ) { return ((os.(Mama union Tata).Osoba) as rodzic). (rodzic union Przodkowie(rodzic))}; procedure Genealogia { return (Osoba as Człowiek) (Przodkowie(Człowiek) group as JegoPrzodkowie);}; Podaj przodków Malinowskiego urodzonych przed 20-tym wiekiem: (Genealogia where (Człowiek.Nazwisko) = "Malinowski"). (JegoPrzodkowie where RokUrodz < 1900)

148 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 148 kwiecień 2002 Perspektywy rekurencyjne a dedukcyjne reguły W obecnym sformułowaniu perspektywy koncepcyjnie przykrywają tzw. "reguły dedukcyjne" (i tzw. "dedukcyjne bazy danych"). Są jednak w stanie zaoferować znacznie, znacznie więcej. Klasyczne trudne zadanie dedukcyjnych baz danych - reguła CousinsSameGeneration: dla danej osoby podaj wszystkich kuzynów tej samej generacji. Jedno z wielu rozwiązań: Procedura Ancestors dla referencji os (do osoby) z poziomem generacji gen zwraca referencje do jej przodków z poziomem generacji odpowiednio wyższym. procedure Ancestors( os, gen ) { return (os.(Mama union Tata).Osoba) as p, (gen+1) as g). ((p, g) union Ancestors( p, g ))}; procedure CousinsSameGeneration( person ) { return ((Osoba as s) where Ancestors(s, 0) as x ( x in Ancestors(person, 0) ) };

149 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 149 kwiecień 2002 Aktualizacja perspektyw - przykłady procedure MałoZarabiający ( Stanowiska ) { return (Prac where Stan in Stanowiska and Zar < avg( Prac.Zar ) ). ( Nazwisko as N, Zar as Z, (PracujeW.Dział.Nazwa) as D) }; Podnieś o 100 zarobki mało zarabiającym asystentom i analitykom z działu informatyki: for each MałoZarabiający( bag( asystent, analityk ) ) where D = Informatyka do Z := Z + 100; Po wykonaniu tego zlecenia niektórzy mało zarabiający mogą przestać być mało zarabiającymi, zaś inni staną się mało zarabiającymi. Niektóre wirtualne obiekty znikną z naszej perspektywy, zaś pojawią się nowe. Dla mało zarabiającego asystenta Nowaka zmień dział na Marketing: for each MałoZarabiający( bag{ asystent} ) where N = Nowak do D := Marketing ; Zlecenie można wykonać, lecz jego intencja jest zakłócona. Zmieniona będzie nazwa działu, w którym dotychczas pracował Nowak, a nie o to chodziło. (Analogia do aktualizacji po stronie klucza głównego w Oracle.) Z przykładów widać, że nasze podejście daje duże możliwości w zakresie aktualizacji perspektyw. Nie rozwiązuje jednak wszystkich problemów.

150 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 150 kwiecień 2002 Najprostszy zabieg - ograniczyć aktualizację Specjalna składnia dla perspektyw umożliwiające ograniczenie operacji wykonywanych na elementach zwracanych przez perspektywę: view MałoZarabiający ( Stanowiska ) { updateable N, Z; return (Prac where Stan in Stanowiska and Zar < avg( Prac.Zar ) ). ( Nazwisko as N, Zar as Z, (PracujeW.Dział.Nazwa) as D) }; Semantyka nie jest problemem: po materializacji perspektywy każda nieaktualizowalna referencja (w tym przypadku D) zwracana przez perspektywę zostaje wyposażona we flagę "Nie podlega aktualizacji". Zastosować dereferencję dla tych referencji, poprzez które aktualizacja ma być zabroniona: procedure MałoZarabiający ( Stanowiska ) { return (Prac where Stan in Stanowiska and Zar < avg( Prac.Zar ) ). ( Nazwisko as N, Zar as Z, deref(PracujeW.Dział.Nazwa) as D) }; Jest to równoważne ustawieniu flagi "Nie podlega aktualizacji".

151 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 151 kwiecień 2002 Obiekty wirtualne vs. "klasa wirtualna" Nie wprowadzamy pojęcia "klasy wirtualnej". Nie wiadomo co miałoby ono znaczyć. Obiekty wirtualne są wartościami, które "symulują" obiekty. Nie ma sensu mówić o identyfikatorach (OID) takich obiektów wirtualnych. Jeżeli procedura zwraca referencje do obiektów, wówczas z definicji są one podłączone do swoich klas (co wynika ze stosowej semantyki). Np. wywołanie procedury procedure Kobieta { return Osoba where Płeć = K }; zwraca referencje (identyfikatory) obiektów Osoba, które dziedziczą z klasy Osoba. Poprawne jest więc zapytanie z użyciem metody Wiek znajdującej się w klasie Osoba: Kobieta where Wiek > 25 Niepoprawne jest zapytanie: MałoZarabiający( bag( asystent) ) where Wiek > 25; ponieważ wynik procedury MałoZarabiający nie jest podłączony do jakiejkolwiek klasy.

152 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 152 kwiecień 2002 Klasa dla obiektów wirtualnych Powinna to być normalna klasa, w której będą znajdowały się inwarianty (np. nowe metody) obiektów wirtualnych. Definicji perspektywy powinna uwzględniać podłączenie obiektów wirtualnych do takiej klasy. Np. Klasa jest zdefiniowana jak zwykle: Można teraz używać metody LiczbaDzieci w stosunku do obiektów wirtualnych: Wartość zwrócona przez perspektywę Kobieta będzie wyposażona we flagę informującą, która perspektywa te wartość zwróciła. Dzięki niej operator niealgebraiczny przetwarzający tę wartość włoży odpowiednio sekcję z binderami do cech tej klasy na stos ENVS. view Kobieta() { connect to own class KlasaKobiet; return Osoba where Płeć = K; }; class KlasaKobiet inherits from Osoba { method LiczbaDzieci { return count( Dziecko ) }}; (Kobieta where LiczbaDzieci > 3). Nazwisko

153 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 153 kwiecień 2002 Można uwzględnić w definicji perspektywy: Uniemożliwienie dostępu do pewnych atrybutów/metod obiektów rzeczywistych widzianych poprzez obiekty wirtualne. Dodatkowa klauzula visible i/lub invisible. Uniemożliwienie aktualizacji pewnych atrybutów wirtualnych. Dodatkowa klauzula updateable i/lub non updateable. Odłączenia obiektów wirtualnych od klas obiektów rzeczywistych widzianych poprzez obiekty wirtualne. Dodatkowa klauzula not a member of. Podłączenie obiektów wirtualnych do istniejących klas. Dodatkowa klauzula is a member of. Podłączenie obiektów wirtualnych do nowo powołanych klas. Dodatkowa klauzula connect to own class. Klasa ta należy do definicji perspektywy, jest usuwana razem z perspektywą. Własności te można osiągnąć poprzez flagę skojarzoną z wartością zwracaną przez perspektywę i modyfikację mechanizmu ENVS.

154 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 154 kwiecień 2002 Wirtualne atrybuty Inaczej metody funkcyjne. Załóżmy, że wewnątrz klasy Dział umieszczamy następującą procedurę: Procedura będzie wykonywana w środowisku wnętrza obiektu Dział. Zawiera ono atrybuty Dnr, Nazwa, Lokacja oraz pointery Zatrudnia i Szef. Z tego powodu zapytanie wewnątrz ciała procedury zaczyna się od Zatrudnia. Można byłoby użyć self.Zatrudnia, co niekiedy zwiększyłoby czytelność. Podaj lokację działów, w których średni zarobek jest większy od 1500: W zależności od miejsca ulokowania i środowiska na którym działa procedura może ona być perspektywą lub wirtualnym atrybutem. Podejście stosowe zunifikowało te sytuacje. Dla większości obecnych systemów klasy są obywatelami drugiej kategorii, w związku z czym nie można do nich nic dynamicznie wstawiać ani usuwać. To ogranicza dynamizm wstawiania/usuwania wirtualnych atrybutów. procedure ŚredniaZarobków { return avg( Zatrudnia.Prac.Zar ); }; (Dział where ŚredniaZarobków > 1500). Lokacja

155 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 155 kwiecień 2002 Wirtualne powiązania Podobnie jak poprzednio, są to metody funkcyjne. Różnicą jest jedynie to, że wirtualne powiązanie zwraca referencje do obiektów. Utwórz wirtualny związek Podwładny w klasie Prac prowadzący od pracownika będącego szefem do wszystkich jego podwładnych. Podaj nazwiska ludzi, których szefem jest Abacki. Podane rozwiązanie nie jest "przezroczyste": powinno być: Dla uzyskania całkowitej zgodności i przezroczystości wirtualnych powiązań należałoby zastosować dodatkowe zabiegi, np. jak poprzednio, flagę skojarzoną z referencją zwracaną przez metodę oraz prostą modyfikację mechanizmu ENVS związaną z tą flagą. Wirtualne związki nie są symetryczne, ale można (na ogół) uczynić je symetrycznymi. Np. umieszczamy w klasie Prac następującą metodę: procedure Podwładny { return Kieruje.Dział.Zatrudnia.Prac }; (Prac where Nazwisko = "Abacki"). Podwładny. Nazwisko (Prac where Nazwisko = "Abacki"). Podwładny. Prac. Nazwisko procedure Przełożony { return PracujeW.Dział.Szef.Prac };

156 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 156 kwiecień 2002 Modyfikacja zapytań Modyfikacja zapytań jest podstawową metoda optymalizacji zapytań używających perspektyw. Jest stosowana we wszystkich systemach relacyjnych. Oryginalnie została sformułowana przez M.Stonebrakera w 1975 roku, ale wskutek braku ortogonalności ówczesnych języków zapytań (w szczególności QUEL i SQL) sformułowanie jest bardzo złożone (i mętne). Przy pełnej ortogonalności języka (cecha SBQL) metoda ta staje się banalna i sprowadza się do następującego stwierdzenia: Metoda modyfikacji zapytań polega na tym, że definicję perspektywy traktuje się jako makro-definicję. Wszędzie tam, gdzie w zapytaniach występuje nazwa perspektywy, zastępuje się tę nazwę poprzez tekst będący definicją tej nazwy (pomijając nieistotne elementy leksykalne). Po tym zabiegu uzyskuje się zapytanie bez odwołań do perspektyw. Poddaje się go następnie standardowym metodom optymalizacyjnych, np. przesuwaniem operatorów, usunięciu martwych podzapytań, wykorzystaniu indeksów, itd.

157 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 157 kwiecień 2002 Przykład modyfikacji zapytań (1) Załóżmy, że mamy perspektywę: Załóżmy, że mamy zapytanie: Zmaterializowanie wyniku procedury będzie bardzo kosztowne. Atrybut Nazwisko ma indeks, który zapewnia szybki dostęp do obiektów wg nazwisk. W powyższym zapytaniu indeksu nie można wykorzystać. Wyliczenie nazwy działów dla wszystkich mało zarabiających jest niepotrzebne, bo tej danej zapytanie nie wykorzystuje. Modyfikacja zapytań usuwa te problemy. Dzięki niej w ogóle nie trzeba będzie liczyć tej perspektywy, w szczególności jej niepotrzebnych członów. Można będzie wykorzystać indeks. procedure MałoZarabiający { return (Prac where Zar < 0.5 * avg( Prac.Zar ) ). ( Nazwisko as N, Zar as Z, (PracujeW.Dział.Nazwa) as D) }; (MałoZarabiający where N = "Bilski"). Z

158 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 158 kwiecień 2002 Przykład modyfikacji zapytań (2) Dokonujemy makro-substytucji: zastępujemy nazwę perspektywy przez treść jej definicji: Dokonujemy optymalizacji tekstu zapytania przez przepisywanie: Człon (PracujeW.Dział.Nazwa) as D) nie jest używany (jest martwym podzapytaniem); może być usunięty. Człon 0.5 * avg( Prac.Zar ) może być "wyciągnięty przed nawias" i policzony tylko raz: (( Prac where Zar < 0.5 * avg( Prac.Zar )). (Nazwisko as N, Zar as Z, (PracujeW.Dział.Nazwa) as D)) where N = "Bilski"). Z (( Prac where Zar < 0.5 * avg( Prac.Zar )). (Nazwisko as N, Zar as Z)) where N = "Bilski"). Z (( 0.5 * avg( Prac.Zar )) as x ). ((( Prac where Zar < x). (Nazwisko as N, Zar as Z)) w here N = "Bilski"). Z )

159 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 159 kwiecień 2002 Przykład modyfikacji zapytań (3) Definicje pomocniczych nazw N i Z stają się zbędne; można je usunąć, zastępując oryginalnymi nazwami Nazwisko i Zar: Dwa następujące po sobie operatory where łączymy w jeden: Wykorzystujemy dostęp przez IndeksPracNazwisko( N ), który na podstawie stringu N będącego nazwiskiem zwraca referencje do obiektów Prac: Zapytanie jest ostatecznie zoptymalizowane. Optymalizacja odbywała się na podstawie reguł, które można dość łatwo sformalizować i zaimplementować. (( 0.5 * avg( Prac.Zar )) as x ). ((( Prac where Zar < x) w here Nazwisko = "Bilski"). Zar ) (( 0.5 * avg( Prac.Zar )) as x ). (( Prac where Zar < x and Nazwisko = "Bilski"). Zar ) (( 0.5 * avg( Prac.Zar )) as x ). ((IndeksPracNazwisko( "Bilski" ) where Zar < x ). Zar )

160 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 160 kwiecień 2002 Warunki poprawności modyfikacji zapytań Modyfikacja zapytań oznacza potraktowania perspektywy jako makro- definicji. Pytanie: czy i kiedy to jest semantycznie równoważne? Warunki: Procedura definiująca perspektywę nie ma własnego środowiska. Nie występuje rekurencja w wywoływaniu perspektyw. Środowisko w którym wywoływana jest procedura jest takie samo jak środowisko, w którym ewaluowane jest zapytanie wewnątrz tej procedury. Dla większości przypadków wykorzystania perspektyw nie są to warunki mocne. Mogą być w niektórych sytuacjach osłabione. Jeżeli perspektywa ma parametry, wówczas makrosubstytucja wymaga potraktowania każdego parametru również jako makro. To sugeruje metodę transmisji parametrów znaną jako call-by-name. Powstaje pytanie, kiedy call-by-name jest semantycznie równoważne przyjętej w danym języku metodzie transmisji parametrów, np. call-by-value.

161 © K.Subieta. Obiektowe języki zapytań 6..10, Folia 161 kwiecień 2002 Na zakończenie... Podstawowe tematy związane z obiektowymi językami zapytań zostały omówione, ale pozostały jeszcze inne. Wiele z nich stanowi pole działalności badawczej, m.in. następujące tematy: Języki schematu dla obiektowych baz danych (a la ODMG ODL), metamodele dla obiektowych baz danych. Mocna kontrola typów dla języków zapytań i języków programowania opartych na językach zapytań; polimorficzny system typów. Tranzytywne domknięcia i równania stało-punktowe w językach zapytań. Modele składu i konstrukcje języków uwzględniające sekwencje, sortowanie i operacje zależne od kolejności elementów. Języki zapytań uwzględniające dane nieregularne i półstrukturalne. Aktualizacja wirtualnych perspektyw z uwzględnieniem możliwości sterowania przez definiującego intencją tej aktualizacji. Programowanie generyczne z refleksją. Przetwarzanie zapytań w rozproszonych obiektowych bazach danych. Metody optymalizacji obiektowych zapytań.


Pobierz ppt "© K.Subieta. Obiektowe języki zapytań 6..10, Folia 1 kwiecień 2002 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła."

Podobne prezentacje


Reklamy Google