Obiektowe języki zapytań 6..10

Download Report

Transcript Obiektowe języki zapytań 6..10

Obiektowe języki zapytań
Wykładowca: Kazimierz Subieta
Polsko-Japońska Wyższa Szkoła
Technik Komputerowych, Warszawa
[email protected]
Wykłady 6..10
Instytut Podstaw Informatyki PAN,
Warszawa
[email protected]
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 1
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 2
kwiecień 2002
Wykład 6
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 3
kwiecień 2002
Język SBQL (Stack-Based Query Language)
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 4
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 5
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 6
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 7
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 q1q2 i q1q2
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 8
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 9
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 10
kwiecień 2002
Podsumowanie składni SBQL
zapytanie ::= L
zapytanie ::= N
zapytanie ::= operUna zapytanie
zapytanie ::= operUna ( zapytanie )
zapytanie ::= zapytanie operBin zapytanie
zapytanie ::= zapytanie operNieAlg zapytanie
operNieAlg ::= where | .|  |  | 
zapytanie ::= zapytanie ( zapytanie )
zapytanie ::=  zapytanie ( zapytanie )
zapytanie ::= zapytanie as N
zapytanie ::= zapytanie group as N
zapytanie ::= ( zapytanie )
zapytanie ::= N ( )
zapytanie ::= N ( parametr {; parametr} )
parametr ::= zapytanie
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 11
L  V jest zbiorem literali
N jest zbiorem nazw
operUna jest operatorem
algebraicznym unarnym
operBin jest operatorem
algebraicznym binarnym
operNieAlg jest operatorem
nie-algebraicznym
Możliwe są dalsze
operatory nie-algebraiczne
Meta-nawiasy {}
oznaczają iterację od 0
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
Nazwa
Osoba
Operator nie-algebraiczny
where
Zapytanie
Nazwa
Nazwisko
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 12
Zapytanie
Operator algebraiczny
=
Zapytanie
Reprezentant
”Nowak”
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 13
kwiecień 2002
Przykład działania stosu rezultatów
Wyrażenie
Odwrotna notacja polska
(2 *((5 + 3 ) / 4)) - 1
pusty
2
5
2
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 14
3
5 +
2
253+4/*1-
8
2
4
8
2
/
2
2
* 4
1
4
-
3
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 15
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 16
kwiecień 2002
Przykład zawartości stosu QRES
15
wierzchołek stosu jedyny widoczny element
i17
struct{ x(i61), y(i93) }
bag{
struct{ n("Nowak"), s(i9)},
struct{ n("Stec"),
s(i14)},
struct{ n("Mikuła" ), s(i18)}}
niewidoczne
elementy stosu
dół stosu
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 17
kwiecień 2002
Ogólna architektura elementów semantyki
Stos środowisk
ENVS
Operatory
niealgebraiczne
referencje
do obiektów
Skład obiektów
Ewaluacja
zapytań
Obiekty trwałe
Stos rezultatów
QRES
referencje
do obiektów
Obiekty ulotne
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 18
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 19
kwiecień 2002
Działanie procedury eval
rezultat zapytania q
poprzedni stan
QRES
eval( q )
poprzedni stan
QRES
 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 20
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 21
kwiecień 2002
Operatory algebraiczne i nie-algebraiczne
 Operatory łączące zapytania będziemy dzielić na algebraiczne i niealgebraiczne.
• Istotą podejścia stosowego są operatory nie-algebraiczne.
 Fundamentalna różnica pomiędzy operatorami algebraicznymi i niealgebraicznymi 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 22
kwiecień 2002
SBQL - operatory algebraiczne
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 23
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 24
kwiecień 2002
Funkcja eval dla operatorów algebraicznych
procedure 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 25
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 26
kwiecień 2002
Rodzaje operatorów algebraicznych (1)
• Generyczny operator porównania na równość, oznaczany zwykle =, i operator
odwrotny oznaczany  . Np. Nazwisko = ”Kowalski” , x = y ,
Zarobek
 2000 , itd. Operatory te są zwykle zdefiniowane dla wszystkich typów
wprowadzanych w danym języku.
• Porównania i operatory dotyczące liczba całkowitych i rzeczywistych: <, , >,
, +, - , *, /. Np. Zarobek < 3000 , 2+2 , -(głebokosc + x) , itd.
• Funkcje liczbowe: część całkowita liczby, zaokrąglenie liczby, wartość
bezwzględna liczby, sinus, kosinus, tangens, cotangens, logarytm dziesiętny,
logarytm naturalny, funkcja wykładnicza, pierwiastek kwadratowy, itd.;
Np. sqrt( x2 + y2) , sin(x+45) , itd;
• Porównania, operatory i funkcje na stringach znaków: porównanie na
porządek leksykograficzny stringów, zawieranie się stringów, obcięcie
stringów, konkatenacja stringów, zamiana wszystkich liter na wersaliki i
odwrotnie, określenie długości stringu, itd.
• Porównanie, operatory i funkcje na datach i czasie godzinowym: porównanie
dat, porównanie czasu, zmiana czasu na liczbę sekund, itd.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 27
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 28
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 itego 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 29
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 30
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 31
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 32
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 33
kwiecień 2002
Przykład działania operatora as
Zapytanie
Prac
Prac as p
Wynik
i1
i6
i11
p( i1 )
p( i6 )
p( i11 )
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 34
kwiecień 2002
Zastosowania operatora as
 „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
Prac.( Nazwisko as n, Zar as z ) ;
przez
zapytanie,
np.
 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:
create view BogatyProjektant
{ return (Prac where Stan = ”projektant” and Zar > 10000).
(Nazwisko as N, PracujeW as NrD) };
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 35
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.
Zapytanie
Wynik
Prac
bag{ i1, i6, i11 }
Prac group as p
p( bag{ i1, i6, i11 } )
 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.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 36
kwiecień 2002
Wykład 7
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 37
kwiecień 2002
SBQL - operatory nie-algebraiczne
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 38
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 39
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 40
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 41
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 42
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 43
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 44
kwiecień 2002
Poglądowy obraz małej bazy danych
i1
Prac
i2 Nazwisko ”Nowak”
i3 Zar 2500
i4 PracujeW
i5
Prac
i9
i6 Nazwisko ”Kowalski”
Prac
i10 Nazwisko ”Barski”
i7 Zar 2000
i11 Zar 900
i12 Adres
i8 PracujeW
i13 Miasto ”Radom”
i14 Ulica ”Wolska”
i15 NrDomu 12
i16 PracujeW
i17
Dział
i22
Dział
i18 Nazwa ”Produkcja”
i23 Nazwa ”Sprzedaż”
i19 Lokacja ”Kielce”
i24 Lokacja ”Radom”
i20 Lokacja ”Kraków”
i25 Zatrudnia
i21 Zatrudnia
i26 Zatrudnia
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 45
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 46
kwiecień 2002
Operator where - ilustracja działania
Rezultat
zwracany przez
zapytanie Prac
(wiązanie Prac)
i1
i5
Stan stosu ENVS
przed ewaluacją
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
i9
Iteracja po
elementach e
poprzedniego
rezultatu: na ENVS
wkłada się nested(e)
Rezultat
zwracany
przez
zapytanie Zar
(wiązanie Zar)
Nazwisko(i2) Zar(i3)
PracujeW(i4)
Rezultat Końcowy
zwracany rezultat
przez
zapytania
zapytanie
Zar>1000
Rezultat
dereferencji
wymuszanej
przez
operator >
Rezultat
zwracany
przez
zapytanie
1000
i3
2500
1000
prawda
i1
i7
2000
1000
prawda
i5
i11
900
1000
fałsz
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)
Prac
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 47
where
(
Zar
> 1000 )
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 48
kwiecień 2002
Operator kropki - ilustracja działania
Rezultat
zwracany przez
zapytanie Prac
(wiązanie Prac)
i1
Iteracja po
elementach e
poprzedniego
rezultatu: na ENVS
wkłada się nested(e)
Nazwisko(i2) Zar(i3)
PracujeW(i4)
Rezultat
zwracany
przez
zapytanie Zar
(wiązanie Zar)
Końcowy
rezultat
zapytania
i3
i3
i7
i7
i11
i11
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
i5
Nazwisko(i6) Zar(i7)
PracujeW(i8)
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
Stan stosu ENVS
przed ewaluacją
i9
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)
Prac
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 49
.
Zar
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 50
kwiecień 2002
Operator zależnego złączenia - ilustracja działania
Rezultat
zwracany przez
zapytanie Prac
(wiązanie Prac)
i1
Iteracja po
elementach e
poprzedniego
rezultatu: na ENVS
wkłada się nested(e)
Nazwisko(i2) Zar(i3)
PracujeW(i4)
Rezultat
zwracany
przez
zapytanie Zar
(wiązanie Zar)
Końcowy
rezultat
zapytania
i3
struct(i1, i3)
i7
struct(i5, i7)
i11
struct(i9, i11 )
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
i5
Nazwisko(i6) Zar(i7)
PracujeW(i8)
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
Stan stosu ENVS
przed ewaluacją
i9
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)
Prac
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 51

Zar
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 52
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 53
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 54
kwiecień 2002
Kwantyfikator uniwersalny - ilustracja działania
Rezultat
zwracany przez
zapytanie Prac
(wiązanie Prac)
i1
i5
Stan stosu ENVS
przed ewaluacją
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
i9
Iteracja po
elementach e
poprzedniego
rezultatu: na ENVS
wkłada się nested(e)
Rezultat
zwracany
przez
zapytanie Zar
(wiązanie Zar)
Nazwisko(i2) Zar(i3)
PracujeW(i4)
Rezultat
dereferencji
wymuszanej
przez
operator >
Rezultat
zwracany
przez
zapytanie
1000
Rezultat
zwracany
przez
zapytanie
Zar>1000
i3
2500
1000
prawda
i7
2000
1000
prawda
i11
900
1000
fałsz
Końcowy
rezultat
zapytania
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
Nazwisko(i6) Zar(i7)
PracujeW(i8)
fałsz
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)
Prac
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 55

(
Zar
> 1000 )
kwiecień 2002
Kroki ewaluacji zapytania z pomocniczą nazwą
Rezultat
zwracany
przez
zapytanie
Prac
i1
i5
i9
(Prac
Rezultat
zwracany
przez
zapytanie
Prac as x
x(i1)
x(i5 )
x(i9)
as x)
Iteracja po
elementach e
poprzedniego
rezultatu: na
ENVS wkłada
się nested(e)
Rezultat
zwracany
przez
zapytanie x
(wiązanie x)
Iteracja po
elementach e
poprzedniego
rezultatu: na
ENVS wkłada
się nested(e)
Rezultat
zwracany
przez
zapytanie
Zar
Rezultat
dereferencji
wymuszanej
przez operator
>
Rezultat
zwracany
przez
zapytanie
1000
Końcowy
rezultat
zapytania
Rezultat
zwracany
przez
zapytanie
Zar>1000
Nazwisko(i2) Zar(i3)
PracujeW(i4)
x(i1)
i3
2500
1000
prawda
x(i1)
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
Prac(i1) Prac(i5) Prac(i9) Dział(i17)
Dział(i22)
x(i5 )
i5
Nazwisko(i6) Zar(i7)
PracujeW(i8)
x(i5 )
2000
1000
prawda
x(i5 )
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
Prac(i1) Prac(i5) Prac(i9) Dział(i17)
Dział(i22)
i7
x(i9)
i9
Nazwisko(i10) Zar(i11)
Adres(i12) PracujeW(i16)
x(i9)
i11
900
1000
fałsz
i1
x(i1)
Prac(i1) Prac(i5) Prac(i9)
Dział(i17) Dział(i22)
where
( ( x
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 56
Prac(i1) Prac(i5) Prac(i9) Dział(i17)
Dział(i22)
.
Zar )
> 1000 )
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 57
kwiecień 2002
SBQL - schematy BD dla przykładów zapytań
Schemat relacyjny
Adres
NrP
Miasto
Ulica
NrDomu
Dział
NrD
Nazwa
Szef
Prac
NrP
Nazwisko
Stan
Zar
PracujeW
Lokacje
NrD
Lokacja
Strzałki modelują asocjacje;
prowadzą od klucza obcego
do głównego
Schemat obiektowy (diagram klas)
Prac[0..*]
NrP
Nazwisko
Stan
Zar
Adres [0..1]
Miasto
Ulica
NrDomu
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 58
PracujeW
Kieruje[0..1]
Zatrudnia[1..*]
Szef
Dział [0..*]
NrD
Nazwa
Lokacja[1..*]
Asocjacje są zrealizowane jako
(bliźniacze) obiekty pointerowe
kwiecień 2002
SBQL - przykłady zapytań (1)
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.
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 59
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 60
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 61
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 62
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 63
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 64
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 65
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 66
kwiecień 2002
SBQL - przykłady zapytań (9)
Stany stosu środowisk przy wiązaniu nazw występujących w zapytaniu
Dział  avg(Zatrudnia.Prac.Zar)
( Dział  avg((Zatrudnia .
Prac(..)
Prac(..), ...
Dział(..)
Dział(..) ...
Nrd(..),
Nazwa(..)
Lokacja(..)
Lokacja(..) ...
Zatrudnia(..)
Zatrudnia(..) ...
Szef(..)
Prac(..)
Prac(..), ...
Dział(..)
Dział(..) ...
Prac
Prac(..)
Nrd(..),
Nazwa(..)
Lokacja(..)
Lokacja(..) ...
Zatrudnia(..)
Zatrudnia(..) ...
Szef(..)
Prac(..)
Prac(..), ...
Dział(..)
Dział(..) ...
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 67
)
Nrd(..),
Nazwa(..)
Lokacja(..)
Lokacja(..) ...
Zatrudnia(..)
Zatrudnia(..) ...
Szef(..)
Prac(..)
Prac(..), ...
Dział(..)
Dział(..) ...
.
Zar
NrP (..)
Nazwisko(..)
Stan(..) Zar(..)
Adres(..)
PracujeW(..)
Kieruje(..)
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ł(..) ...
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 68
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 69
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 70
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 71
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 72
kwiecień 2002
Wykład 8
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 73
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 74
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 75
kwiecień 2002
Graficzna reprezentacja przykładu modelu M1
Osoba
Nazwisko
RokUr
Wiek
i40 KlasaOsoba
i41 Wiek (...kod...)
................
i1 Osoba
i2 Nazwisko ”Wilski”
PracujeW
i3 RokUr 1950
Prac
Zar
ZmieńZar
ZarNetto
i50 KlasaPrac
i51 ZmieńZar (...kod...)
i52 ZarNetto (...kod...)
................
i4 Prac
i9 Prac
i5 Nazwisko ”Nowak”
i10 Nazwisko ”Kowalski”
i6 RokUr 1944
i11 RokUr 1940
i7 Zar 2500
i12 Zar 2000
i8 PracujeW
i13 PracujeW
i127
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 76
i128
kwiecień 2002
Sytuacja na ENVS dla modelu M1
 Zakładamy, że operator nie-algebraiczny przetwarza obiekt O z
identyfikatorem iO.
Kolejność przeszukiwania stosu
Klasa K3
Klasa K2
Klasa K1
Obiekt Obiekt
Obiekt
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 77
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
Sekcje wkładane na stos
środowiskowy przy
przetwarzaniu obiektu O
przez operator
niealgebraiczny
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 78
kwiecień 2002
Przetwarzanie obiektu Prac w M1
Operator niealgebraiczny, np. where w zapytaniu
Prac where Wiek > avg(Prac.Wiek)
przetwarza obiekt Nowaka (z identyfikatorem i4 ) dla bazy danych
przedstawionej poprzednio.
Kolejność przeszukiwania stosu
Nazwisko(i5) RokUr (i6) Zar (i7)
PracujeW (i8)
Sekcja zawierająca nested(i4) - własności
aktualnie przetwarzanego obiektu i4
ZmieńZar(i51) ZarNetto(i52) ...
Bindery do własności klasy KlasaPrac
(połączonej z i4 związkiem OK).
Wiek(i51) ...
Bindery do własności klasy KlasaOsoba
(połączonej z KlasaPrac związkiem KK).
.........
Prac(i4) Prac(i9), ...
Osoba(i1) Osoba(i4) Osoba(i9), ...
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 79
... inne sekcje ...
Bindery do obiektów bazy danych, zdublowane
dla różnych nazw.
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 80
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 81
kwiecień 2002
Co się dzieje, gdy wołana jest metoda?
Implementacja metody w ramach klasy K
Użycie metody w zapytaniu
method met( p1: T1, p2: T2 ): T (*sygnatura*)
begin
x1: T11, x2: T12; (* lokalne obiekty *)
....
end met;
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
Kroki
metody met
przetwarzania
Obliczenie
Operator 
dla r1 :
parametrów
q1, q2
nested(r1)
Rezultat q2
Bindery do
Obliczenie q
Rezultat q1
publicznych
Rezultat q
Rezultat q
własności K
Poprzedni
Poprzedni
Poprzedni
Poprzedni
stan QRES
stan QRES
stan ENVS
stan ENVS
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 82
gdzie  jest operatorem
niealgebraicznym
Przetwarzanie ciała
metody met
Sekcja lokalna
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
Usunięcie
rezultatów
q1, q2
Rezultat q
Poprzedni
stan QRES
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
stan
Poprzedni
ENVS
ENVS
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 83
kwiecień 2002
Wielodziedziczenie w M1 i fałszywe przesłanianie
Klasa K4
metoda m
Klasa K5
Bindery do własności obiektu O
Bindery do własności K1
Klasa K2
Klasa K3
metoda m
Bindery do własności K2
Kierunek
przeszukiwania
stosu
Bindery do własności K3: m (...)
Bindery do własności K4: m (...)
Klasa K1
Bindery do własności K5
.....
Bindery danych globalnych
Obiekt
Obiekt
Obiekt
Skład obiektów
Stos środowisk przy
przetwarzaniu obiektu O
 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)
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 84
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 85
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 86
kwiecień 2002
Przykłady zapytań w modelu M1
Schemat obiektowy
(diagram klas)
Dział . ( Nazwa, avg(Zatrudnia.Prac.Wiek()) as Średnia)
Osoba[0..*]
Nazwisko
RokUr
Wiek()
Dziedziczenie metody Wiek przez klasę Prac.
Podaj nazwiska, zarobek netto i nazwisko szefa dla
programistów pracujących w Radomiu.
Prac[0..*]
NrP
Zawód[1..*]
Zar
ZmieńZar(nowy)
ZarNetto( )
PracujeW
Kieruje[0..1]
Zatrudnia[1..*]
Dział [0..*]
NrD
Nazwa
Lokacja[1..*]
BudżetRoczny()
Nazwa działu i średni wiek jego pracowników:
Szef
(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 87
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 88
kwiecień 2002
Graficzna reprezentacja przykładu modelu M2
i40 KlasaOsoba
i41 Wiek (...kod...)
.............
i1 Osoba
i60 KlasaStudent
i2 Nazwisko ”Wilski”
i61 ŚredniaOcen (...kod...)
i3 RokUr 1950
................
i50 KlasaPrac
i51 ZmieńZar (...kod...)
i52 ZarNetto (...kod...)
................
i4 Osoba
i5 Nazwisko ”Nowak”
i7 Osoba
i8 Nazwisko ”Kowalski”
i6 RokUr 1944
i9 RokUr 1940
i13 Prac
i16 Prac
i14 Zar 2500
i17 Zar 2000
i15 PracujeW
i19 Student
i20 NrIndeksu 76943
i21 Wydział ”fizyka”
i18 PracujeW
i127
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 89
i128
kwiecień 2002
Dolne sekcje ENVS w modelu M2
....................
Bindery do obiektów/zmiennych
nietrwałych aktualnej sesji
użytkownika
Sekcje danych
globalnych
Osoba( i1 ) Osoba( i4 ) Osoba( i8 )
Prac( i13 ) Prac( i16) Student( i19)
...
Sekcja bazy danych
Bindery do globalnych funkcji
bibliotecznych
Bindery do zmiennych i funkcji
środowiska komputerowego
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 90
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
Kolejność
przeszukiwania
stosu
Zar( i17 ) PracujeW( i18 )
Bindery do własności aktualnie
przetwarzanej roli Prac
ZmieńZar( i51 ) ZarNetto( i52 ) ...
Bindery do własności klasy
KlasaPrac
Nazwisko( i8 ) RokUr( i9 )
Bindery do własności roli Osoba
będącej super-rolą aktualnie
przetwarzanej roli Prac
Wiek( i41 ) ...
Bindery do własności klasy
KlasaOsoba
.........
Osoba( i1 ) Osoba( i4 ) Osoba( i8 )
Prac( i13 ) Prac( i16) Student( i19) ...
Sekcja bazy danych
.........
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 91
kwiecień 2002
Uogólnienie: skład z rolami w M2
Klasy
iK3R1 K3R1
iK3R2 K3R2
iK3R3 C3R3
iK2R1 K2R1
iK2R2 K2R2
iK2R3 K2R3
iK1R1 K1R1
iK1R2 K1R2
iK1R3 K1R3
iR3 R3
Obiekty
i role
iR2 R2
iR1 R1
 Klasy KjRi (j = 1,2,...) nie muszą być unikalne; mogą tworzyć graf dziedziczenia.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 92
kwiecień 2002
Organizacja i kolejność przeszukiwania ENVS
 Operator nie-algebraiczny przetwarza rolę R1
Kolejność
przeszukiwania
stosu
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 93
nested(iR1)
nested(iK1R1)
nested(iK2R1)
...
nested(iR2)
nested(iK1R2)
nested(iK2R2)
...
nested(iR3)
nested(iK1R3)
...
...
sekcje
roli R1
sekcje
roli R2
sekcje
roli R3
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 94
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 95
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 96
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 97
kwiecień 2002
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 :
Koniec
przetwarzania ri
przez q2
Operator 
Sekcje
wkładane przy
przetwarzaniu
ri
Poprzedni stan
ENVS
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 98
nested_public(ri)
nested_public(iK1)
nested_public(iK2)
nested_public(iK3)
Poprzedni stan
ENVS
Poprzedni stan
ENVS
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 :
Wywołanie metody m
Środowisko indukowane
przez wywołanie m
Środowisko
indukowane
przez 
Poprzedni
stan ENVS
nested_public(ri)
nested_public(iK1)
nested_public(iK2)
nested_public(iK3)
Poprzedni stan
ENVS
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 99
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
Prywatne własności
klasy K2
Prywatne własności
obiektu z OID = ri
nested_public(ri)
nested_public(iK1)
nested_public(iK2)
nested_public(iK3)
Poprzedni stan
ENVS
Poprzedni
stan ENVS
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
Kolejność
• m2 została wywołana z metody m3
Środowisko indukowane przez wywołanie m1 dla ri
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.
wiązania nazw
występujących
w ciele m1
Ś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
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 100
kwiecień 2002
Przykłady poprawnych i błędnych zapytań w M3
Osoba
+ Nazwisko
- RokUr
+ Wiek
Prac
- Zar
+ ZmieńZar
+ ZarNetto
+ PracujeW
+ Zatrudnia
Dział
+ Nazwa
+ Budżet
Osoba where Nazwisko = "Nowak"
Poprawne
(Osoba where Nazwisko = "Nowak").RokUr
Błędne
(Prac where Nazwisko = "Nowak").Wiek
Poprawne
method Wiek() { return BieżącyRok - RokUr }
Poprawne
(Prac where Nazwisko = "Nowak").Zar
Błędne
method ZmieńZar( nowy ) { Zar := nowy }
Poprawne
method ZarNetto( ) { if RokUr > 1955 then
return 0.9 * Zar else return 0.8 * Zar }
Błędne
Prac where Dział (Budżet > 100 * ZarNetto)
....
method ZarNetto( ) { if Nazwa = "Marketing" then
return 0.9 * Zar else return 0.8 * Zar }
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 101
Błędne
kwiecień 2002
Wykład 9
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 102
kwiecień 2002
Konstrukcje imperatywne oparte na SBQL
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 103
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 104
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ść (callby-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 105
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 106
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 107
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 108
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 109
kwiecień 2002
Zasada korespondencji
correspondence principle
• 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.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 110
kwiecień 2002
Przegląd operatorów imperatywnych
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 111
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 112
kwiecień 2002
Operator podstawienia i wstawiania
 Operator
podstawienia
powinien
umożliwiać
makroskopowe, w stylu klauzuli update języka SQL.
podstawienie
• 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ć
makroskopowe, w stylu klauzuli insert języka SQL.
wstawianie
• 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 113
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 114
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ń:
przechwycenie zaistniałego zdarzenia.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 115
wygenerowanie
zdarzenia,
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 116
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 117
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 118
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 119
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 120
kwiecień 2002
Procedury
procedures
 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.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 121
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 122
kwiecień 2002
Parametry procedur
 Istnieje wiele semantycznie różnych sposobów
parametrów do procedur. Najbardziej popularne:
komunikowania
• 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 123
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 124
kwiecień 2002
Wybrane operatory imperatywne bazujące na
SBQL
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 125
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 126
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 127
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 128
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 129
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-byreference). 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 130
kwiecień 2002
Przykład procedury
• Deklaracja: procedura zmienia dział dla pracowników. Referencje do
pracowników i ich nowego działu są jej parametrami.
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;};
};
• Wywołanie procedury: Przenieść wszystkich analityków do działu
kierowanego przez Nowaka:
ZmieńDział( Prac where Stan = "analityk";
Dział where (Szef.Prac.Nazwisko) = "Nowak" );
• Wersja procedury z automatyczną aktualizacją bliźniaczych pointerów Zatrudnia i
PracujeW:
procedure ZmieńDział( var P; var D ) {
for each P do PracujeW :=&D };
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 131
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.
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)
};
• Przykład: Podaj nazwiska i zarobek dla mało zarabiających piekarzy i stolarzy
z działu produkcji.
(MałoZarabiający ( bag("piekarz", "stolarz") ) where D = "produkcja") . (N, Z)
• Przykład: Podwyższ o 100 zarobek wszystkim mało zarabiającym
programistom z działu konserwacji.
for each MałoZarabiający ( bag("programista") ) where D = "Konserwacja" do
Z := Z+100;
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 132
kwiecień 2002
Wykład 10
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 133
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:
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
};
 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.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 134
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 135
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 136
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 137
kwiecień 2002
Makroskopowe wołanie przez referencję
call-by-reference
• 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ę.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 138
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 139
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 140
kwiecień 2002
Perspektywy w SBQL
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 141
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 142
kwiecień 2002
Przykład struktury danych
Zatrudnia
*
Dział
1
PracujeW
Dnr
Nazwa
Lokacja *
1
Szef
0..1
Kieruje
Prac
Pnr
Stan
Zar
ZarNetto
Mama
0..1
Osoba
Nazwisko Dziecko
Płeć
*
RokUrodz Tata
Wiek
0..1
Rodzina
Dziecko
*
 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.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 143
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:
BogatyPrac
Nazwisko
Szef
Zarobek
• Nazwiska i zarobki netto bogatych pracowników pracujących dla Wilickiego.
(BogatyPrac where Szef = "Wilicki") . (Nazwisko, Zarobek)
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 144
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 145
kwiecień 2002
Wynik procedury będącej perspektywą
 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),
struct{ Nazw(iNazwisko2), Wiek(w2),
struct{ Nazw(iNazwisko3), Wiek(w3),
Firma(iNazwa1) },
Firma(iNazwa2) },
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.
MłodyPrac
Nazw
Wiek
Firma
• 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ń.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 146
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 147
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 148
kwiecień 2002
Aktualizacja perspektyw - przykłady
procedure MałoZarabiający ( Stanowiska ) {
return (Prac where Stan in Stanowiska and Zar < avg( Prac.Zar ) ) .
( Nazwisko as N, Zar as Z, (PracujeW.Dział.Nazwa) as D) };
• Podnieś o 100 zarobki mało zarabiającym asystentom i analitykom z działu
informatyki:
for each MałoZarabiający( bag( “asystent”, “analityk” ) ) where D = “Informatyka”
do Z := Z + 100;
• Po wykonaniu tego zlecenia niektórzy mało zarabiający mogą przestać być
mało zarabiającymi, zaś inni staną się mało zarabiającymi. Niektóre wirtualne
obiekty znikną z naszej perspektywy, zaś pojawią się nowe.
• Dla mało zarabiającego asystenta Nowaka zmień dział na Marketing:
for each MałoZarabiający( bag{ “asystent”} ) where N = “Nowak” do D := “Marketing”;
• Zlecenie można wykonać, lecz jego intencja jest zakłócona. Zmieniona będzie
nazwa działu, w którym dotychczas pracował Nowak, a nie o to chodziło.
(Analogia do aktualizacji po stronie klucza głównego w Oracle.)
 Z przykładów widać, że nasze podejście daje duże możliwości w zakresie
aktualizacji perspektyw. Nie rozwiązuje jednak wszystkich problemów.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 149
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 150
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 151
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.
view Kobieta() { connect to own class KlasaKobiet;
return Osoba where Płeć = “K”; };
• Klasa jest zdefiniowana jak zwykle:
class KlasaKobiet inherits from Osoba {
method LiczbaDzieci { return count( Dziecko ) }};
• Można teraz używać metody LiczbaDzieci w stosunku do obiektów
wirtualnych:
(Kobieta where LiczbaDzieci > 3). Nazwisko
• 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.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 152
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 153
kwiecień 2002
Wirtualne atrybuty
 Inaczej metody funkcyjne.
• Załóżmy, że wewnątrz klasy Dział umieszczamy następującą procedurę:
procedure ŚredniaZarobków {
return avg( Zatrudnia.Prac.Zar ); };
• 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:
(Dział where ŚredniaZarobków > 1500). Lokacja
 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.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 154
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.
procedure Podwładny { return Kieruje.Dział.Zatrudnia.Prac };
• Podaj nazwiska ludzi, których szefem jest Abacki.
(Prac where Nazwisko = "Abacki"). Podwładny. Nazwisko
• Podane rozwiązanie nie jest "przezroczyste": powinno być:
(Prac where Nazwisko = "Abacki"). Podwładny. Prac. Nazwisko
• 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 Przełożony { return PracujeW.Dział.Szef.Prac };
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 155
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 156
kwiecień 2002
Przykład modyfikacji zapytań (1)
 Załóżmy, że mamy perspektywę:
procedure MałoZarabiający {
return (Prac where Zar < 0.5 * avg( Prac.Zar ) ) .
( Nazwisko as N, Zar as Z, (PracujeW.Dział.Nazwa) as D) };
 Załóżmy, że mamy zapytanie:
(MałoZarabiający where N = "Bilski") . Z
• 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.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 157
kwiecień 2002
Przykład modyfikacji zapytań (2)
 Dokonujemy makro-substytucji:
• zastępujemy nazwę perspektywy przez treść jej definicji:
((Prac where Zar < 0.5 * avg( Prac.Zar )).
(Nazwisko as N, Zar as Z, (PracujeW.Dział.Nazwa) as D)) where N = "Bilski") . Z
 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.
((Prac where Zar < 0.5 * avg( Prac.Zar )).
(Nazwisko as N, Zar as Z)) where N = "Bilski") . Z
• Człon 0.5 * avg( Prac.Zar ) może być "wyciągnięty przed nawias" i
policzony tylko raz:
((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 158
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:
((0.5 * avg( Prac.Zar )) as x ) .
(((Prac where Zar < x) where Nazwisko = "Bilski"). Zar )
• Dwa następujące po sobie operatory where łączymy w jeden:
((0.5 * avg( Prac.Zar )) as x ) .
((Prac where Zar < x and Nazwisko = "Bilski"). Zar )
• Wykorzystujemy dostęp przez IndeksPracNazwisko( N ), który na podstawie
stringu N będącego nazwiskiem zwraca referencje do obiektów Prac:
((0.5 * avg( Prac.Zar )) as x ) .
((IndeksPracNazwisko( "Bilski" ) where Zar < x ). Zar )
• Zapytanie jest ostatecznie zoptymalizowane. Optymalizacja odbywała się na
podstawie reguł, które można dość łatwo sformalizować i zaimplementować.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 159
kwiecień 2002
Warunki poprawności modyfikacji zapytań
 Modyfikacja zapytań oznacza potraktowania perspektywy jako makrodefinicji. 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 160
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ń.
© K.Subieta. Obiektowe języki zapytań 6..10, Folia 161
kwiecień 2002