Obiektowe języki zapytań

161
© 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 [email protected] Instytut Podstaw Informatyki PAN, Warszawa [email protected] Wykłady 6..10

description

Obiektowe języki zapytań. Wykładowca : Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa [email protected] Instytut Podstaw Informatyki PAN, Warszawa [email protected]. Wykłady 6..10. Plan wykładów 6..10. SBQL - składnia SBQL - stos rezultatów - PowerPoint PPT Presentation

Transcript of Obiektowe języki zapytań

© 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łaTechnik Komputerowych, [email protected]

Instytut Podstaw Informatyki PAN, [email protected]

Wykłady 6..10

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 2 kwiecień 2002

Plan wykładów 6..10

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

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

Wykład 6

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 4 kwiecień 2002

Język SBQL (Stack-Based Query Language)

© 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.

© 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.

© 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.

© 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ś q1 i q2 są zapytaniami, wówczas q1 q2 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ś q1 i q2 są zapytaniami, wówczas q1 q2 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ę q1( q2 ) oraz q1( q2 ); jest ona równoważna podanej wyżej uniwersalnej składni q1q2 i q1q2

© 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ś q1, q2, ... , qk są zapytaniami, wówczas n(q1; q2; ... , qk) 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.

© 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 + 2000/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)

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 11 kwiecień 2002

Podsumowanie składni SBQL

zapytanie ::= L zapytanie ::= Nzapytanie ::= operUna zapytaniezapytanie ::= operUna ( zapytanie )zapytanie ::= zapytanie operBin zapytaniezapytanie ::= zapytanie operNieAlg zapytanieoperNieAlg ::= where | .| | | zapytanie ::= zapytanie ( zapytanie )zapytanie ::= zapytanie ( zapytanie )zapytanie ::= zapytanie as N zapytanie ::= zapytanie group as Nzapytanie ::= ( zapytanie )zapytanie ::= N ( )zapytanie ::= N ( parametr {; parametr} )parametr ::= zapytanie

L V jest zbiorem literaliN jest zbiorem nazwoperUna jest operatorem algebraicznym unarnymoperBin jest operatorem algebraicznym binarnymoperNieAlg jest operatorem nie-algebraicznymMożliwe są dalsze operatory nie-algebraiczne

Meta-nawiasy {} oznaczają iterację od 0

© 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

Zapytanie ZapytanieOperator algebraiczny

=NazwaOsoba

NazwaNazwisko

Reprezentant”Nowak”

Operator nie-algebraicznywhere

Zapytanie Zapytanie

© 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ń.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 14 kwiecień 2002

Przykład działania stosu rezultatów

(2 *((5 + 3 ) / 4)) - 1 2 5 3 + 4 / * 1 -

Wyrażenie Odwrotna notacja polska

2 25

253

284

22

41

4 3pusty 28+ /

* -

© 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ń.

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 17 kwiecień 2002

15

i17

struct{ x(i61), y(i93) }

bag{ struct{ n("Nowak"), s(i9)}, struct{ n("Stec"), s(i14)},

struct{ n("Mikuła" ), s(i18)}}

Przykład zawartości stosu QRES

dół stosu

wierzchołek stosu - jedyny widoczny element

niewidoczne elementy stosu

© 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 środowiskENVS Stos rezultatów

QRESEwaluacjazapytań

Operatoryniealgebraiczne

referencjedo obiektów

referencjedo obiektów

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 19 kwiecień 2002

Procedura ewaluacji zapytań eval (evaluation)

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).

© 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.

© 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;

© 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.

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

SBQL - operatory algebraiczne

© 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 x1 x2 (gdzie jest operatorem algebry) kolejność ewaluacji argumentów x1 oraz x2 tego operatora nie ma znaczenia. Jest to zasadnicza różnica w stosunku do operatorów nie-algebraicznych.

W matematycznym (denotacyjnym) sformułowaniu wynik zapytań ( q1 ) oraz q1 q2 można zapisać jako:

wynik( ( q1 ) ) = ( wynik( q1 ) ) jest implementacją wynik( q1 q2 ) = wynik( q1 ) wynik( q2 )

Funkcja wynik jest parametryzowana stanem, ale jej definicja nie odwołuje się do tego stanu bezpośrednio.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 25 kwiecień 2002

Funkcja eval dla operatorów algebraicznychprocedure eval( q : zapytanie )begin ..... case q jest rozpoznane jako ( q1 ) lub q1: begin wynik_q1: Rezultat; (* lokalna zmienna typu Rezultat *) eval( q1 ); (* rezultat q1 na wierzchołku stosu QRES *) wynik_q1 := top( QRES ); pop( QRES ); push( QRES, wynik_q1 ); end;

case q jest rozpoznane jako q1 q2 : begin wynik_q1, wynik_q2: Rezultat; (* lokalne zmienne *) eval( q1 ); (* rezultat q1 na wierzchołku stosu QRES *) eval( q2 ); (* rezultat q2 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;

© 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.

© 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( x2 + y2) , 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.

© 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.

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 30 kwiecień 2002

Konstruktor struktur

Składnia: ( q1, q2, q3,...)

• gdzie q1, q2, q3,... są zapytaniami zwracającymi pojedyncze elementy - wartości atomowe, referencje lub bindery.

• Jeżeli qi zwraca ri, to wyrażenie ( q1, q2, q3,...) zwraca struct{ r1, r2, r3,...}

• 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{i1, i5, i9}, Dział zwraca bag{i17, i22}, to (Prac, Dział, 3) zwraca

bag{ struct{i1, i17, 3}, struct{i5, i17, 3}, struct{i9, i17, 3},

struct{i1, i22, 3}, struct{i5, i22, 3}, struct{i9, i22, 3} }

Możliwe jest uogólnienie typu "outer join": jeżeli w (.., qi-1, qi, qi+1,..) qi zwraca pusty wynik, to zapytanie jest równoważne (..., qi-1, qi+1,...) .

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 31 kwiecień 2002

Konstruktor wielozbiorów

Składnia: bag( q1, q2, q3,...)

• gdzie q1, q2, q3,... są zapytaniami zwracającymi pojedyncze elementy - wartości atomowe, referencje lub bindery.

• Jeżeli qi zwraca ri, to wyrażenie bag( q1, q2, q3,...) zwraca bag{ r1, r2, r3,...}

• 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( q1, q2, q3,...) jest równoważne q1 union q2 union q3 union ...

• przy czym jeżeli qi zwraca element ri , to jest on traktowany jak bag{ri}.

© 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ń.

© 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{x1, x2, x3, ...}. Wówczas zapytanie

q as n

zwróci kolekcję binderów bag{ n(x1), n(x2), n(x3), ...}.

• 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{x1, x2,...}, to q as n zwraca sequence{ n(x1), n(x2),...}.

• Operator as może być zagnieżdżany: np. jeżeli q zwraca bag{x1, x2, x3, ...}, to (q as n1) as n2 zwraca bag{ n2( n1(x1) ), n2( n1(x2) ), n2( n1(x3) ), ...}

Powyższa definicja wydaje się banalna, ale okazuje się uniwersalna i precyzyjna, zwiększająca znacznie potencjał dla optymalizacji zapytań.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 34 kwiecień 2002

Przykład działania operatora as

i1

i6

i11

Prac

p( i1 )p( i6 )p( i11 )

Prac as pZapytanie

Wynik

© 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:

© 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{ i1, i6, i11 }

PracZapytanie

Wynik

Prac group as p

p( bag{ i1, i6, i11 } )

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

Wykład 7

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 38 kwiecień 2002

SBQL - operatory nie-algebraiczne

© 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.

© 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 + 100 ) >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.

© 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ń.

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 43 kwiecień 2002

Opis procedury eval dla operatora nie-algebr. Aby dokonać ewaluacji zapytania q1 q2 wykonaj następujące czynności:

• Dokonaj ewaluacji zapytania q1. Zapytanie to zwraca wielozbiór elementów.

• Dla każdego elementu e należącego do wyniku q1 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 q2 w tym nowym środowisku.

• Oblicz wynik cząstkowy dla danego elementu e poprzez połączenie e z wynikiem zwróconym przez q2. 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.

© 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 q1 q2 : (* q1 , q2 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 q1 *) wyniki_pośr := ; (* zerowanie kolekcji wyników pośrednich *) eval( q1 ); (*q1 zwraca kolekcję elementów; wynik q1 na czubku stosu QRES *) for each e in top( QRES ) do (* iteracja po wszystkich elementach wyniku q1 *) begin

push( ENVS, nested( e ) ); (* nowa sekcja na stosie środowisk *)eval( q2 ); (* wynik q2 na czubku stosu QRES *)wynik_pośredni := połącz ( e, top( QRES ) ); (* połączenie e z wynikiem q2; zależne od *)wyniki_pośr := wyniki_pośr U { wynik_pośredni }; (* akumulacja wyniku pośredniego *)pop( QRES ); (* usuniecie z QRES wyniku q2 *)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 q1 *) push( QRES, wynik_końcowy ); (* włożenie na QRES końcowego wyniku *) end; .......end;

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 45 kwiecień 2002

Poglądowy obraz małej bazy danych

i1 Prac

i2 Nazwisko ”Nowak”

i3 Zar 2500

i4 PracujeW

i5 Prac

i6 Nazwisko ”Kowalski”

i7 Zar 2000

i8 PracujeW

i9 Prac

i10 Nazwisko ”Barski”

i11 Zar 900

i16 PracujeW

i13 Miasto ”Radom”

i14 Ulica ”Wolska”

i15 NrDomu 12

i12 Adres

i17 Dział

i18 Nazwa ”Produkcja”

i19 Lokacja ”Kielce”

i21 Zatrudnia

i20 Lokacja ”Kraków”

i22 Dział

i23 Nazwa ”Sprzedaż”

i24 Lokacja ”Radom”

i25 Zatrudnia

i26 Zatrudnia

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 46 kwiecień 2002

Operator where (selekcja)

Składnia: q1 where q2

• Ograniczenie: podzapytanie q2 zwraca wartość prawda lub fałsz.

Semantyka• Dla każdego elementu e zwróconego przez q1, ENVS jest podwyższany o

nested(e)

• Następnie ewaluowane jest q2

• Po ewaluacji q2 stos ENVS wraca do poprzedniego stanu

• e należy do ostatecznego wyniku wyłącznie wtedy, gdy q2 zwróciło prawda.

Objaśnienie funkcji eval• Funkcja połącz: dla danego e należącego do wyniku q1 zwraca

jednoelementowy wielozbiór { e } w przypadku, gdy dla tego e podzapytanie q2 zwróciło prawda, lub pusty wielozbiór { }, jeżeli podzapytanie q2 zwróciło fałsz.

• Funkcja sumuj: sumuje (mnogościowo) wszystkie wyniki pośrednie.

Przykład: Prac where ( Zar > 1000 )

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 47 kwiecień 2002

Operator where - ilustracja działania

Prac where ( Zar > 1000 )

i1

i5

i9Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

i3

i7

i11

i1

i5

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(i2) Zar(i3) PracujeW(i4)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i6) Zar(i7) PracujeW(i8)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i10) Zar(i11) Adres(i12) PracujeW(i16)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Rezultat dereferencji wymuszanej przez operator >

2500

2000

900

Rezultat zwracany przez zapytanie 1000

1000

1000

1000

prawda

prawda

fałsz

Rezultat zwracany przez zapytanie Zar>1000

Końcowy rezultat zapytania

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 48 kwiecień 2002

Operator kropki (projekcja, nawigacja)

Składnia: q1 . q2

Semantyka• Dla każdego elementu e zwróconego przez q1, ENVS jest podwyższany o

nested(e)

• Następnie ewaluowane jest q2

• Po ewaluacji q2 stos ENVS wraca do poprzedniego stanu

• Ostateczny wynik jest sumą mnogościową wyników q2

Objaśnienie funkcji eval• Funkcja połącz: ignoruje e; zwraca wynik podzapytania q2.

• 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 49 kwiecień 2002

Operator kropki - ilustracja działania

Prac . Zar

i1

i5

i9

i3

i7

i11

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

i3

i7

i11Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i2) Zar(i3) PracujeW(i4)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i6) Zar(i7) PracujeW(i8)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i10) Zar(i11) Adres(i12) PracujeW(i16)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 50 kwiecień 2002

Operator zależnego złączenia

Składnia: q1 q2

Semantyka• Dla każdego e zwróconego przez q1, ENVS jest podwyższany o nested(e)

• Następnie ewaluowane jest q2

• Po ewaluacji q2 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 q2 zwrócony dla tego e.

Objaśnienie funkcji eval• Funkcja połącz: zarówno e jak i każdy element e2 zwracany przez q2 traktuje jako

struktury (jednoelementowe lub wieloelementowe). Dla każdego e2 zwracanego przez q2 tworzy strukturę poprzez połączenie e oraz e2. 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 51 kwiecień 2002

Operator zależnego złączenia - ilustracja działania

Prac Zar

i1

i5

i9

i3

i7

i11

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(i1, i3)

struct(i5, i7)

struct(i9, i11 )Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i2) Zar(i3) PracujeW(i4)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i6) Zar(i7) PracujeW(i8)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i10) Zar(i11) Adres(i12) PracujeW(i16)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 52 kwiecień 2002

Operator sortowania

Składnia: q1 order by q2

Semantyka• Wykonywane jest zapytanie: q1 dereferencja( q2 )

• Wynik (bag) jest sortowany według części struktur zwróconej przez q2 . 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 q1 .

• 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 q2.

• 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,.. ).

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 53 kwiecień 2002

Kwantyfikator egzystencjalny

Składnia: q1 ( q2 ) lub q1 q2

• Ograniczenie: podzapytanie q2 zwraca wartość prawda lub fałsz.

Semantyka• Dla każdego e zwróconego przez q1, ENVS jest podwyższany o nested(e)

• Następnie ewaluowane jest q2

• Po ewaluacji q2 stos ENVS wraca do poprzedniego stanu

• Ostateczny wynik jest prawda wtedy i tylko wtedy, jeżeli dla co najmniej jednego e podzapytanie q2 zwróciło prawda.

Objaśnienie funkcji eval• Funkcja połącz: ignoruje e; zwraca wynik podzapytania q2.

• Funkcja sumuj: Zwraca prawda jeżeli co najmniej jeden wynik pośredni zwrócony przez q2 jest prawda; w przeciwnym wypadku zwraca fałsz.

Przykład: Prac ( Zar > 1000 )

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 54 kwiecień 2002

Kwantyfikator uniwersalny

Składnia: q1 ( q2 ) lub q1 q2

• Ograniczenie: podzapytanie q2 zwraca wartość prawda lub fałsz.

Semantyka• Dla każdego e zwróconego przez q1, ENVS jest podwyższany o nested(e)

• Następnie ewaluowane jest q2

• Po ewaluacji q2 stos ENVS wraca do poprzedniego stanu

• Ostateczny wynik jest prawda wtedy i tylko wtedy, jeżeli dla wszystkich e podzapytanie q2 zwróciło prawda. Jeżeli q1 zwróciło pusty wielozbiór, to wynik także jest prawda.

Objaśnienie funkcji eval• Funkcja połącz: ignoruje e; zwraca wynik podzapytania q2.

• Funkcja sumuj: Zwraca fałsz jeżeli co najmniej jeden wynik pośredni zwrócony przez q2 jest fałsz ; w przeciwnym wypadku zwraca prawda.

Przykład: Prac ( Zar > 1000 )

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 55 kwiecień 2002

Kwantyfikator uniwersalny - ilustracja działania

Prac ( Zar > 1000 )

i1

i5

i9

i3

i7

i11

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 >

2500

2000

900

Rezultat zwracany przez zapytanie 1000

1000

1000

1000

prawda

prawda

fałsz

Rezultat zwracany przez zapytanie Zar>1000

Końcowy rezultat zapytania

fałsz

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i2) Zar(i3) PracujeW(i4)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i6) Zar(i7) PracujeW(i8)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i10) Zar(i11) Adres(i12) PracujeW(i16)

Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

© 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 )

i1

i5

i9

i3

i7

i11

x(i1)

x(i5 )

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 >

2500

2000

900

Rezultat zwracany przez zapytanie 1000

1000

1000

1000

prawda

prawda

fałsz

Rezultat zwracany przez zapytanie Zar>1000

Końcowy rezultat zapytania

Rezultat zwracany przez zapytanie Prac as x

x(i1)

x(i5 )

x(i9)

i1

i5

i9

Rezultat zwracany przez zapytanie Zar

x(i1)Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

x(i5 )Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

x(i9)Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i2) Zar(i3) PracujeW(i4)x(i1)Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i6) Zar(i7) PracujeW(i8)x(i5 )Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Nazwisko(i10) Zar(i11) Adres(i12) PracujeW(i16)x(i9)Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22)

Iteracja po elementach e poprzedniego rezultatu: na ENVS wkłada się nested(e)

© 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

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 58 kwiecień 2002

SBQL - schematy BD dla przykładów zapytań

Dział [0..*]NrDNazwaLokacja[1..*]

Schemat obiektowy (diagram klas)

PracujeW Zatrudnia[1..*]Prac[0..*]NrPNazwiskoStanZar

Adres [0..1]MiastoUlicaNrDomu

PracNrPNazwiskoStanZarPracujeW

DziałNrDNazwaSzef

LokacjeNrDLokacja

AdresNrPMiastoUlicaNrDomu

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

© 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.

© 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’;

© 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ż 1000.

(Prac where Zar > 1000) . (NrP, Nazwisko)

Wynikiem zapytania jest wielozbiór struktur struct{iNrP, iNazwisko}, 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ż.

© 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

© 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.

© 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{ iPrac, iDział }, 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.

© 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ł.

© 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{ iDział, ś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)

© 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)

© 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.

© 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{iNazwisko1, iStan, iNazwa, iNazwisko2 }, 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.

© 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.

© 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)

© 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".

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

Wykład 8

© 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)

© 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,

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 76 kwiecień 2002

Graficzna reprezentacja przykładu modelu M1

i40 KlasaOsoba

i41 Wiek (...kod...)

................

i50 KlasaPrac

i51 ZmieńZar (...kod...)

................

i52 ZarNetto (...kod...)

i4 Prac

i5 Nazwisko ”Nowak”

i7 Zar 2500

i8 PracujeW

i6 RokUr 1944

i127

i1 Osoba

i2 Nazwisko ”Wilski”

i3 RokUr 1950

i128

i9 Prac

i10 Nazwisko ”Kowalski”

i12 Zar 2000

i13 PracujeW

i11 RokUr 1940

OsobaNazwiskoRokUrWiek

PracZarZmieńZarZarNetto

PracujeW

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 77 kwiecień 2002

Bindery do własności przechowywanych wewnątrz obiektu O, czyli nested(iO)

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 K3

............................

...........................

Bindery z identyfikatorami startowymi składu obiektów

Kolejność przeszukiwania stosu

Sekcje wkładane na stos środowiskowy przy przetwarzaniu obiektu O przez operator niealgebraiczny

ObiektObiekt Obiekt

Klasa K1

Klasa K2

Klasa K3

Sytuacja na ENVS dla modelu M1

Zakładamy, że operator nie-algebraiczny przetwarza obiekt O z identyfikatorem iO.

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 79 kwiecień 2002

Przetwarzanie obiektu Prac w M1

Nazwisko(i5) RokUr (i6) Zar (i7) PracujeW (i8)

ZmieńZar(i51) ZarNetto(i52) ...

Wiek(i51) ...

.........

Prac(i4) Prac(i9), ... Osoba(i1) Osoba(i4) Osoba(i9), ...

Sekcja zawierająca nested(i4) - własności aktualnie przetwarzanego obiektu i4

Bindery do własności klasy KlasaPrac (połączonej z i4 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 i4 ) dla bazy danych przedstawionej poprzednio.

© 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 i4 oraz i9 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.

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 82 kwiecień 2002

Kroki przetwarzania dla r1 :

Co się dzieje, gdy wołana jest metoda?

method met( p1: T1, p2: T2 ): T (*sygnatura*) begin x1: T11, x2: T12; (* lokalne obiekty *) .... end met;

Implementacja metody w ramach klasy K

Poprzedni stan ENVS

q ... met(q1, q2)...

Niech eval(q) zwróci bag{r1, r2, ....}, 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(r1)

Bindery do publicznych własności K

Poprzedni stan ENVS

Rezultat q

Poprzedni stan QRES

Operator

Obliczenie qRezultat q2

Rezultat q1

Rezultat q

Poprzedni stan QRES

Obliczenie parametrów

q1, q2

Sekcja lokalnametody met

p1 (Rezultat q1)

p2(Rezultat q2)

x1(..) x2(..)

Bindery do prywatnych własności K

nested(r1)

Bindery do publicznych własności K

Poprzedni stan ENVS

Rezultat q

Poprzedni stan QRES

Usunięcie rezultatów

q1, q2

Przetwarzanie ciała metody met

p1 (Rezultat q1)

p2(Rezultat q2)

x1(..) x2(..)

Bindery do prywatnych własności K

nested(r1)

Bindery do publicznych własności K

Poprzedni stan ENVS

Poprzedni stan ENVS

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 84 kwiecień 2002

Klasa K1

Klasa K2

Klasa K4metoda m

Klasa K5

Klasa K3metoda 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 K5

.....

Bindery danych globalnych

Skład obiektówStos ś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

ObiektObiekt Obiekt

© 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.

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 87 kwiecień 2002

Przykłady zapytań w modelu M1Schemat obiektowy

(diagram klas)

Osoba[0..*]NazwiskoRokUrWiek()

Prac[0..*]NrPZawód[1..*]ZarZmieńZar(nowy)ZarNetto( )

Dział [0..*]NrDNazwaLokacja[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)

© 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ą.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 89 kwiecień 2002

Graficzna reprezentacja przykładu modelu M2

i1 Osoba

i2 Nazwisko ”Wilski”

i3 RokUr 1950

i40 KlasaOsoba

i41 Wiek (...kod...)

.............

i50 KlasaPrac

i51 ZmieńZar (...kod...)

................

i52 ZarNetto (...kod...)

i60 KlasaStudent

i61 ŚredniaOcen (...kod...)

................

i13 Prac

i14 Zar 2500

i15 PracujeW

i127

i4 Osoba

i5 Nazwisko ”Nowak”

i6 RokUr 1944

i7 Osoba

i8 Nazwisko ”Kowalski”

i9 RokUr 1940

i128

i16 Prac

i17 Zar 2000

i18 PracujeW

i19 Student

i20 NrIndeksu 76943

i21 Wydział ”fizyka”

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 90 kwiecień 2002

Dolne sekcje ENVS w modelu M2

....................

Bindery do obiektów/zmiennych nietrwałych aktualnej sesji

użytkownika

Osoba( i1 ) Osoba( i4 ) Osoba( i8 ) Prac( i13 ) Prac( i16) Student( i19) ...

Bindery do globalnych funkcji bibliotecznych

Bindery do zmiennych i funkcji środowiska komputerowego

Sekcje danych globalnych

Sekcja bazy danych

© 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 i16 , 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( i17 ) PracujeW( i18 )

ZmieńZar( i51 ) ZarNetto( i52 ) ...

Nazwisko( i8 ) RokUr( i9 )

Wiek( i41 ) ...

.........

Osoba( i1 ) Osoba( i4 ) Osoba( i8 ) Prac( i13 ) Prac( i16) Student( i19) ...

.........

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 92 kwiecień 2002

iK1R1 K1R1

iK2R1 K2R1

iK3R1 K3R1

iK1R2 K1R2

iK2R2 K2R2

iK3R2 K3R2

iK1R3 K1R3

iK2R3 K2R3

iK3R3 C3R3

iR2 R2

iR1 R1

iR3 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 93 kwiecień 2002

Organizacja i kolejność przeszukiwania ENVS

Operator nie-algebraiczny przetwarza rolę R1

nested(iR1)nested(iK1R1)nested(iK2R1)...nested(iR2)nested(iK1R2)nested(iK2R2)...nested(iR3)nested(iK1R3)......

sekcjeroli R1

sekcjeroli R2

sekcjeroli R3

Kolejność przeszukiwania stosu

© 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 q2 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.

© 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ą.

© 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.

© 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 iK będzie identyfikatorem obiektu klasy K posiadającej listę eksportową exportK

• nested_private( iK ) = {n(x) : n nested( iK ) and n exportK}

• nested_public( iK ) = {n(x) : n nested( iK ) and n exportK}

• 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{ x1, x2, ...}) = nested_private( x1 ) nested_private( x2 ) ...

nested_public( struct{ x1, x2, ...}) = nested_public( x1 ) nested_public( x2 ) ...

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 98 kwiecień 2002

Poprzedni stan ENVS

Operator

Przetwarzanie obiektów w M3

Zapytanie q1 q2, gdzie jest operatorem niealgebraicznym.

Niech eval(q) zwróci bag{r1, r2, ....}, gdzie r1, r2, .... 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 q2 ; m nie jest nazwą metody.

Kroki przetwarzania dla ri :

Poprzedni stan ENVS

nested_public(ri)

nested_public(iK1)

nested_public(iK2)

nested_public(iK3)

Poprzedni stan ENVS

Sekcje wkładane przy przetwarzaniu

ri

Koniec przetwarzania ri

przez q2

© 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 q2 ; m jest nazwą metody, która znajduje się w klasie K2.

Kroki przetwarzania dla ri :

Poprzedni stan ENVS

nested_public(ri)

nested_public(iK1)

nested_public(iK2)

nested_public(iK3)

Poprzedni stan ENVS

Poprzedni stan ENVS

nested_public(ri)

nested_public(iK1)

nested_public(iK2)

nested_public(iK3)

Poprzedni stan ENVS

Lokalne środowisko metody m

nested_private(iK2)

nested_ private(ri)

nested_public(ri)

nested_public(iK1)

nested_public(iK2)

nested_public(iK3)

Poprzedni stan ENVS

Wywołanie metody m Prywatne własności klasy K2

Prywatne własności obiektu z OID = ri Środowisko indukowane

przez wywołanie m

Środowisko indukowane przez

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 100 kwiecień 2002

Reguły zakresu dla M3

Załóżmy, że dla rozpatrywanego zapytania q1 q2 zachodzi:

• aktualnie wykonywana jest metoda m1 występująca w q2 i przetwarzająca ri

• zapytanie występuje wewnątrz ciała metody m2

• m2 została wywołana z metody m3

Kolejność wiązania nazw występujących w ciele m1

Środowisko indukowane przez wywołanie m1 dla ri

Środowisko indukowane przez q2 , w którym zanurzone jest wołanie metody m1

Środowisko indukowane przez dla ri

Środowisko indukowane przez wywołanie m2

Środowisko indukowane przez wywołanie m3

...

Sekcje bazowe ENVS

Lexical scoping: programista piszący m1 nie znał tych środowisk. Wobec tego nazwy występujące w m1

nie mogą być w nich wiązane.

© 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łędnemethod 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

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

Wykład 9

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 103 kwiecień 2002

Konstrukcje imperatywne oparte na SBQL

© 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ł.

© 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.

© 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.

© 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.

© 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.

© 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.

© 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

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 111 kwiecień 2002

Przegląd operatorów imperatywnych

© 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.

© 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ę.

© 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.

© 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 <nazwa> = <tekst>; gdzie <tekst> jest w zasadzie dowolnym tekstem (tzw. makrosem) który zastąpi po kompilacji każde użycie <nazwa>.

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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 116 kwiecień 2002

Operatory warunkowe i przełączania

Operator warunkowy:• if <warunek> then <program1> else <program2>

• if <warunek> then <program>

• Wariant dla wyrażeń: if <warunek> then <zapytanie1> else <zapytanie2>

Operator przełączania: posiada wiele wariantów, np. case <wyrażenie> do

<etykieta 1>: <program 1>,<etykieta 2>: <program 2>,...<etykieta n>: <program n>

else <program n+1>

• Semantycznie, obliczane jest <wyrażenie>; jeżeli wyrażenie zwróci wartość <etykieta i> wówczas wykonywany jest <program i>.

• Jeżeli <wyrażenie> nie zwróciło wartości równej jakiejkolwiek etykiecie, wówczas wykonywany jest <program n+1>.

• Fraza else jest zwykle opcyjna.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 117 kwiecień 2002

Operatory pętli

while <warunek> do <program>

• Operator powtarza wyliczenie wyrażenia <warunek> i wykonanie bloku <program> aż do momentu, kiedy <warunek> będzie nieprawdziwy. Jeżeli <warunek> jest na samym początku nieprawdziwy, wówczas <program> nie jest wykonywany ani razu.

repeat <program> until <warunek>

• Najpierw następuje wykonanie bloku <program>, następnie wyliczenie wyrażenia <warunek>; jeżeli jest prawdziwy, to sterowanie jest przekazywane dalej, w przeciwnym przypadku powtarzane jest wykonanie bloku <program>, z ponownym wyliczeniem wyrażenia <warunek>.

• Modyfikacja tych operatorów polega na wprowadzeniu specjalnej instrukcji break, której wykonanie wewnątrz <program> powoduje przekazanie sterowania do instrukcji znajdującego się za tą konstrukcją.

loop <program>• przerwanie pętli wymaga użycia instrukcji break.

© 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 <zmienna> = <wartość początkowa> until <wartość końcowa> do <program>

• 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( <zmienna iteracyjna> = <wyrażenie początkowe>;<warunek zakończenia pętli>;<instrukcja przyrostu zmiennej iteracyjnej> ) <program>

• Dodatkowo jest możliwe zakończenie cyklu iteracyjnego poprzez wydanie w dowolnym miejscu <program> instrukcji break.

© 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 <zmienna iteracyjna> in <kolekcja> do <program>

Operator ten jest bardzo użyteczny dla programowania baz danych, zajmiemy się więc nim dokładniej nieco dalej.

© 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ą.

© 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

© 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.

© 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ń.

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 125 kwiecień 2002

Wybrane operatory imperatywne bazujące na SBQL

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 126 kwiecień 2002

Operator for each

Składnia: for each <zapytanie> do <program> Semantyka: przyjmujemy zasadę operatorów nie-algebraicznych

• Dla każdego e zwróconego przez <zapytanie>, 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 <program>.

• Po zakończeniu wykonania <program> ENVS wraca do poprzedniego stanu.

• Cykl ten jest powtarzany dla wszystkich elementów zwróconych przez <zapytanie>.

• 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"};

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 127 kwiecień 2002

Operator podstawienia

W oryginale ten operator ma postać <wyrażenie1> := < wyrażenie2>.• <wyrażenie1> zwraca referencję czyli id.obiektu (l-value), • <wyrażenie2> zwraca wartość (r-value), którą należy zapisać do obiektu

wskazanego przez referencję. • Jeżeli <wyrażenie2> zwraca referencję, to przed podstawieniem należy

zastosować operator dereferencji. Jak zmienić ten operator aby stał się makroskopowy?

• Jeżeli zastosowalibyśmy składnię <zapytanie1> := <zapytanie2>, gdzie <zapytanie1> zwraca referencje, zaś <zapytanie2> 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ść.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 128 kwiecień 2002

Operator assign

Składnia: assign <zapytanie>• <zapytanie> musi zwrócić kolekcje par <referencja, wartość>.

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.

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 130 kwiecień 2002

Procedury w SBQL

Składnia: procedure <nazwa> (<parametry formalne>) {<program>};• Nie będziemy różnicować procedur i procedur funkcyjnych. • Procedura funkcyjna musi kończyć swoje działanie instrukcją

return <zapytanie>, gdzie <zapytanie> określa wynik działania procedury.

• <zapytanie> 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.

© 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 };

© 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;

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

Wykład 10

© 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) + 500 else return 0.7 * (self.Zar - 1000) + 900 };

© 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{ v1,v2, ... }, gdzie v1, v2, ... Rezultat

• Po wywołaniu procedury zapis aktywacyjny procedury/metody (na wierzchołku ENVS) będzie zawierał bindery:

..., NazwaParam( dereferencja( v1 ) ), NazwaParam( dereferencja( v2 ) ), ...

• 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( v1 ), dereferencja( v2 ), ... }.

• Wewnątrz ciała nie można dokonać podstawienia na NazwaParam, gdyż wiązanie nazwy NazwaParam nie zwraca referencji.

© 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{ v1,v2, ... }, gdzie v1, v2, ... Rezultat

• Po wywołaniu procedury następuje utworzenie obiektów lokalnych:

<ip1, NazwaParam, dereferencja( v1 )>, <ip2, NazwaParam, dereferencja( v2 )>,...

Zapis aktywacyjny procedury/metody (na wierzchołku ENVS) będzie zawierał bindery: ..., NazwaParam( ip1 ), NazwaParam( ip2 ), ...

• 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{ip1, ip2 , ... }.

• 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).

© 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

<ip1,Naz,"Kowal">, <ip2,Naz,"Nowak">, zaś sekcja na wierzchołku ENVS będzie zawierać bindery Naz(ip1), Naz(ip2). Po zakończeniu procedury obiekty <ip1,Naz,"Kowal">, <ip2,Naz,"Nowak"> muszą być usunięte.

© 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{i1,i2, ... }. Nie jest wykonywana dereferencja.

• Po wywołaniu procedury zapis aktywacyjny procedury/metody (na wierzchołku ENVS) będzie zawierał bindery:

..., NazwaParam(i1), NazwaParam(i2 ), ...

• Wewnątrz ciała procedury do parametru można będzie odwołać się poprzez NazwaParam, zaś wynikiem tego odwołania będzie bag{i1 , i2, ... }.

• 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

© 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{i11, i13, i55}. Po wywołaniu procedury na wierzchołku ENVS będzie umieszczona sekcja z binderami: dlaPrac(i11), dlaPrac(i13), dlaPrac(i55), Ile(202).

© 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{i15, i35, i59}, to na wierzchołek ENVS wkłada się pojedynczy binder któreDziały( bag{i15, i35, i59}).

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

Perspektywy w SBQL

© 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.

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 143 kwiecień 2002

OsobaNazwiskoPłećRokUrodzWiekRodzina

Zatrudnia *1 PracujeW

Szef 10..1 Kieruje

Dziecko

Mama0..1

*

Dziecko

Tata0..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łDnrNazwaLokacja *

PracPnrStanZarZarNetto

© 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 3000. 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)

BogatyPracNazwiskoSzefZarobek

© 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" ))

© 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(iNazwisko1), Wiek(w1), Firma(iNazwa1) },

struct{ Nazw(iNazwisko2), Wiek(w2), Firma(iNazwa2) },

struct{ Nazw(iNazwisko3), Wiek(w3), Firma(iNazwa3) }, ... }

gdzie iAtrybutj 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łodyPracNazwWiekFirma

© 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)

© 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) ) };

© K.Subieta. Obiektowe języki zapytań 6..10, Folia 149 kwiecień 2002

Aktualizacja perspektyw - przykładyprocedure 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.

© 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".

© 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.

© 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

© 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.

© 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

© 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 };

© 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.

© 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

© 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)) where N = "Bilski") . Z )

© 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) where 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 )

© 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.

© 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ń.