I.
Wprowadzenie do  języków zapytań (1)
II.
Wprowadzenie do  języków zapytań (2)
III.
Pojęcia obiektowości w bazach danych (1)
IV.
Pojęcia obiektowości w bazach danych (2)
V.
Podstawy semantyczne języków zapytań
VI.
Modele składu obiektów
VII.
Stos środowisk, rezultaty zapytań, funkcja nested
VIII.
Język SBQL (Stack-Based Query Language) (1)
IX.
  Wstęp
  1. Operatory niealgebraiczne
  2. SBQL - przykłady zapytań i porównania
  Podsumowanie
  Zadania
X.
Dalsze własności SBQL
XI.
Operatory order by i group by
XII.
Przetwarzanie struktur nieregularnych
XIII.
Rozszerzenie języków zapytań o konstrukcje imperatywne
XIV.
Procedury, procedury funkcyjne, metody, reguły zakresu
XV.
Parametry procedur i metod, procedury rekurencyjne, optymalizacja poprzez modyfikację zapytań

 

1. Operatory niealgebraiczne

Istotą podejścia stosowego są operatory niealgebraiczne. Do nich należą: operator where, operator kropki, kwantyfikatory, zależne złączenie i inne. Wszystkie wprowadzone przez nas operatory są binarne. Mimo podobieństwa do operatorów algebraicznych, semantyka operatorów niealgebraicznych nie da się w prosty sposób sprowadzić do algebry. To zdanie może wydawać się niejasne i obrazoburcze dla Czytelnika przyzwyczajonego do tego, że w całej epoce relacyjnej operatory selekcji (operator where), projekcji (operator kropki) oraz złączenia były traktowane jako operatory algebry relacji. Takie traktowanie było jednak możliwe wyłącznie przy założeniu silnie ograniczonej funkcjonalności tych operatorów oraz po przyjęciu pewnego (niezbyt rzetelnego) triku formalnego. Trik polega na tym, że część informacji o semantyce tych operatorów jest przeniesiona na poziom metajęzykowy: każdy operator jest dodatkowo kwalifikowany wyrażeniem metajęzykowym. Rozważmy wyrażenie algebry relacyjnej

P9.1.

sZar>1000( Prac )

gdzie występuje operator selekcji s kwalifikowany wyrażeniem metajęzykowym  Zar > 1000. Mówiąc ściśle, operator selekcji nie jest pojedynczym operatorem, lecz nieskończoną rodziną zawierającą tyle operatorów, ile jest możliwych warunków selekcji. Wyrażenie Zar > 1000 nie należy do języka tej algebry; jest to wyrażenie metajęzykowe ustalające, który z operatorów z tej rodziny należy wybrać. To wyrażenie nie jest formalne, jest poza-matematyczne; w istocie jest wyłącznie nieformalnym komentarzem zastosowanym w celu objaśnienia znaczenia tego operatora. Podobna sytuacja zachodzi dla innych operatorów algebry relacji.

Poziom metajęzykowy jest nieformalny, poza sytuacjami w matematyce, gdy jest on formalizowany explicite. 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, w matematyce nic nie jest oczywiste, lecz musi wynikać z aksjomatów. Operator selekcji może mieć bardziej złożony warunek selekcji, np.

P9.2.

sZarobekNetto( Zar + 100 )>1000( Prac )


Warunek selekcji zawiera operator + oraz wywołuje pewną funkcję ZarobekNetto. Wyrażenie metajęzykowe posiada nietrywialną wewnętrzną semantykę. Ponieważ to wyrażenie jest nieformalne (jest komentarzem), trudno mówić o w pełni formalnej semantyce operatora selekcji i innych tego rodzaju operatorów.

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 komentarzem, jest "drugiej kategorii". 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 modeli i języków obiektowych oraz dla języków dla XML, gdyż obiekty mogą mieć strukturę hierarchiczną o dowolnej liczbie zagnieżdżeń, zaś nazwy mogą oznaczać dane na dowolnym poziomie hierarchii obiektów.

Podobny problem dotyczy operatorów wprowadzanych w algebrze relacyjnej. Operator selekcji s jest elementem języka tej algebry, jest "pierwszej kategorii", podczas gdy operator < występuje w metajęzyku, jest komentarzem, bytem "drugiej kategorii". Powyższa językowo/metajęzykowa schizofrenia jest bardzo poważną wadą definicji semantyki, w szczególności rodzi zasadnicze pytania w rodzaju: "dlaczego skomplikowany operator złączenia należy do algebry relacyjnej, zaś banalny operator + do niej nie należy?".

Powyższe obserwacje dotyczą coraz to nowych "algebr obiektowych" (ponad setka artykułów), które wzorzec algebry relacji próbują zastosować do modelu obiektowego. Istnieją propozycje, w których operatory selekcji, projekcji itd. mogą pojawić się w wyrażeniu metajęzykowym definiującym te właśnie operatory selekcji, projekcji, złączenia itd., co jest błędem znanym w logice jako "ignotum per ignotum" (definiowanie pojęć nieznanych przez pojęcia nieznane). W kilku propozycjach tego rodzaju algebr kwantyfikatory również są "operatorami algebraicznymi". Operatory takie jak +, -, *, / niefrasobliwie dołącza się do języka takiej algebry, mimo że powinny one występować raczej w warstwie metajęzykowej. Co więcej, operatory działające na stanie, takie jak aktualizacja obiektu, są również wrzucone do zestawu "operatorów algebry obiektowej". Tego rodzaju propozycje dowodzą matematycznego i informatycznego analfabetyzmu, braku jakiejkolwiek istotnej koncepcji, powielania i dowolnego rozszerzania zastanych wzorców bez troski o koncepcyjną i formalną spójność. Paradoksalnie, autorzy tego rodzaju pseudo-koncepcji motywują to troską o "solidne podstawy matematyczne" obiektowych języków zapytań. Dokładniejszą analizę koncepcyjnej i formalnej wadliwości obiektowych algebr można znaleźć w [Subi95b].

Podsumowując, obecny stan sztuki w zakresie teorii obiektowych języków zapytań nie jest zadowalający. Istnieją poprawne koncepcyjnie i formalnie teorie, ale o bardzo ograniczonej funkcjonalności, która jest w stanie przykryć nikłą część praktycznych języków, takich jak SQL lub OQL. Z drugiej strony, istnieją propozycje uniwersalne, ale wykazujące wady koncepcji i wady formalne. Czy można wyrwać się z tych skrajności i zbudować całkowicie uniwersalną teorię obiektowych języków zapytań, poprawną w sensie koncepcyjnym i formalnym? Omawiane w tym wykładzie podejście stosowe jest naszym zdaniem jak dotąd jedyną pozytywną odpowiedzią na to pytanie.

W podejściu stosowym dowolne operatory języka zapytań nie są indeksowane wyrażeniami metajęzykowymi.

Jest to fundamentalna różnica w stosunku do algebry relacji i algebr obiektowych. Nie występuje więc semantyczna schizofrenia nazw dzieląca je na "językowe" i "metajęzykowe". Nie ma nazw "pierwszej kategorii" i "drugiej kategorii": każda nazwa, niezależnie od poziomu hierarchii i tego, co aktualnie oznacza, ma dokładnie taką samą semantykę i podlega dokładnie tym samym regułom wiązania i zakresu, które omówiliśmy wcześniej. Podobnie z operatorami: nie występuje semantyczne zróżnicowanie operatorów: operator + występuje na tym samym poziomie semantycznym jak operator where (oczywiście, pierwszy z nich jest algebraiczny, drugi zaś niealgebraiczny).

Podana przez nas dalej koncepcja operatorów niealgebraicznych jest w gruncie rzeczy bardzo prosta, posiada dobrze ugruntowane korzenie w semantyce języków programowania oraz może podlegać rozszerzeniom (m.in. w celu zdefiniowania takich własności jak klasy, dziedziczenie i hermetyzacja). Definicja operatorów niealgebraicznych 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ą jednak bazowały na podanej niżej podstawowej definicji dla modelu M0.

tmp2

W bardziej matematycznym (denotacyjnym) sformułowaniu powyższy fragment procedury eval możemy zapisać w postaci wzoru:

tmp1

Podane wyrażenie jest parametryzowane stanem składu obiektów poprzez funkcję nested. Jest to zapis denotacyjny, w którym stos QRES nie występuje.

Nieformalny opis powyższej procedury oraz wzoru jest następujący. Aby dokonać ewaluacji zapytania q1 q  q2, należy wykonać następujące czynności:

  • Dokonaj ewaluacji zapytania q1. Zapytanie to zwraca kolekcję (bag) 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 środowisk.

    • Dokonaj ewaluacji zapytania q2 w tym nowym środowisku.

    • Oblicz wynik pośredni dla danego elementu e poprzez połączenie e z wynikiem zwróconym przez q2. Funkcja łącząca połącz zależy od rodzaju operatora q.

    • Usuń nowo wstawioną sekcję ze stosu środowisk.

  • Zsumuj wszystkie wyniki pośrednie w wynik końcowy. Sposób sumowania sumuj ( U ) zależy od rodzaju operatora q.


Jak można wywnioskować z podanych procedur i wzorów, stan stosu środowisk zmienia się podczas ewaluacji zapytania, ale po jej zakończeniu jest taki sam jak przed rozpoczęciem ewaluacji (dla zapytań bez efektów ubocznych).

Podana procedura obowiązuje dla operatorów selekcji (where), projekcji i nawigacji (kropka), zależnego złączenia (join), kwantyfikatorów i innych. Jak się okazało, mimo wydawałoby się dużych różnic koncepcyjnych, operatory te różnią się między sobą wyłącznie sposobem obliczania wyniku pośredniego oraz sposobem sumowania wyników pośrednich w wynik końcowy. Definicje poszczególnych operatorów są następujące:

Operator where:

Składnia: q1 where q2,
Ograniczenie: podzapytanie q2 zwraca wartość prawda (true) lub fałsz (false).
Funkcja połącz: dla danego e należącego do wyniku q1 zwraca jednoelementowy bag{e} w przypadku, gdy dla tego e podzapytanie q2 zwróciło prawda, lub pusty bag { }, jeżeli podzapytanie q2 zwróciło fałsz.
Funkcja sumuj: sumuje (mnogościowo) wszystkie wyniki pośrednie.
P9.3.

Prac where ( Zar > 1000 )

Operator kropki

Składnia: q1 . q2
Funkcja połącz: ignoruje e; zwraca wynik podzapytania q2.
Funkcja sumuj: sumuje (mnogościowo) wszystkie wyniki pośrednie.
P9.4.

Prac . Zar

Operator zależnego złączenia

Składnia: q1 join q2
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.
P9.5.

Prac join Zar

Kwantyfikator egzystencjalny
Składnia: $ q1 (q2) lub q1 $ q2
Ograniczenie: podzapytanie q2  zwraca wartość prawda (true) lub fałsz (false).
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 przypadku zwraca fałsz.
P9.6.

$ Prac ( Zar > 1000 )

Kwantyfikator uniwersalny
Składnia: " q1 (q2) lub q1 " q2
Ograniczenie: podzapytanie q2 zwraca wartość prawda (true) lub fałsz (false).
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 przypadku zwraca prawda.
P9.7.

"Prac ( Zar > 1000 )

 


Działanie tych operatorów prześledzimy na maleńkiej bazie danych (odpowiadającej modelowi składu M0) z Rys.23 i Rys.24. Przyjmijmy, że ta baza danych jest jedynym środowiskiem, w którym wykonują się zapytania. Na początku ewaluacji zapytań stos środowisk posiada jedyną sekcję zawierającą bindery:

P9.8.

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

Rys.50 przedstawia kolejne kroki ewaluacji prostego zapytania z operatorem where. Analogicznie, Rys.51 przedstawia kroki dla zapytania z operatorem kropki, Rys.52 przedstawia kroki dla zapytania z operatorem zależnego złączenia, Rys.53 przedstawia zapytanie z kwantyfikatorem, zaś Rys.54 przedstawia kroki ewaluacji dla prostego przykładu zastosowania pomocniczej nazwy.

W ostatnim przypadku końcowy wynik zapytania jest różny od wyniku zapytania   Prac where Zar > 1000, mianowicie, elementy wyniku są opatrzone nazwą x. Elementy takie można uważać za struktury (w sensie języków C/C++), których jedynym polem jest pole o nazwie x. Wracając do podanej wcześniej niejasności w specyfikacji standardu ODMG, gdzie nazwa "zmiennej" została potraktowana jako etykieta składowej struktury, widzimy, że tak jest w istocie w naszym przykładzie. Zjawiska tego nie można jednak wyjaśnić na gruncie "algebry obiektowej" lub "dziedzinowego rachunku obiektowego", ale wyłącznie na gruncie omawianego przez nas podejścia stosowego, ponieważ tylko to podejście zajmuje się zagadnieniami związanymi z nazwami bytów programistycznych, wiązaniem nazw i semantyką tych nazw.


Rys.50. Kroki ewaluacji zapytania    Prac where ( Zar > 1000 )

 


Rys.51. Kroki ewaluacji zapytania    Prac . Zar

 


Rys.52. Kroki ewaluacji zapytania    Prac join Zar

 


Rys.53. Kroki ewaluacji zapytania    "Prac ( Zar > 1000)

 


Rys.54. Kroki ewaluacji zapytania   (Prac as x) where ((x.Zar) > 1000

Copyrights © 2006 PJWSTK
Materiały zostały opracowane w PJWSTK w projekcie współfinansowanym ze środków EFS.