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.
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
  Wstęp
  1. Konstrukcje deklaratywne i imperatywne
  2. Zasada korespondencji
  3. Elementarne konstrukcje językowe w językach imperatywnych
  Podsumowanie
  Zadania
XIV.
Procedury, procedury funkcyjne, metody, reguły zakresu
XV.
Parametry procedur i metod, procedury rekurencyjne, optymalizacja poprzez modyfikację zapytań

 

Wstęp

W poprzednim rozdziale ustaliśmy, że w naszym podejściu zapytania będą pełnić rolę wyrażeń znanych z języków programowania. Ponieważ jednocześnie przyjęliśmy zasadę ortogonalnej trwałości, która nie różnicuje sposobów dostępu do trwałych i nietrwałych danych, wobec tego nasze zapytania będą również stosowane do nietrwałych danych. Inaczej mówiąc, przyjęliśmy, że w naszym (jak dotąd hipotetycznym) języku programowania nie będzie innych wyrażeń niż zapytania. Zapytaniami będą więc także klasyczne wyrażenia, takie jak 2+2, sin(x), A[i+1] itd.

To założenie jest pewną rewolucją w odniesieniu do języków zapytań. Tradycyjnie, np. w języku SQL zapytania (zagnieżdżone w język programowania) mogły odwoływać się do zmiennych języka programowania poprzez specjalną składnię. Z powodu różnej przestrzeni nazw, nazwy zmiennych były w zapytaniach SQL poprzedzane znakiem dwukropka i specyficznie wiązane, tak aby zatrzeć różnicę pomiędzy wczesnym wiązaniem zmiennych a późnym wiązaniem charakterystycznym dla języka SQL.

Postępem w tym zakresie był system DBPL [Matt92, Schm94] bazujący na języku Modula-2. Przyjęto tam zasadę ortogonalnej trwałości, ale pozostawiono tradycyjne wyrażenia języka Modula-2 operujące na zmiennych nietrwałych. Zapytania natomiast mogły operować na trwałych i nietrwałych kolekcjach. Mogły też używać zmiennych nie będących kolekcjami, ale z ograniczeniami. Uzasadnione to było w ten sposób, że przetwarzanie zapytań nie może obejść się bez optymalizacji, zaś pełna moc obliczeniowa języka zapytań zredukuje możliwość zastosowania metod optymalizacyjnych. Konsekwencją tego był syntaktyczny i semantyczny podział na wyrażenia i zapytania w ramach jednego zintegrowanego języka programowania. Argument o konieczności zredukowania mocy języka ze względu na optymalizację jest powierzchowny i kontrowersyjny. Jeżeli nie dopuścimy pewnej funkcjonalności w języku zapytań, to programista będzie musiał ją zrealizować inaczej, prawdopodobnie również bez optymalizacji. Przypomina to sytuację, w której w nowoczesnej kuchence elektrycznej ograniczono temperaturę do 50 stopni, ponieważ ktoś mógłby się poparzyć. Ponieważ większość zastosowań kuchennych wymaga i tak temperatury co najmniej 100 stopni, zmusza to kucharza do rozpalania paleniska, gdzie oczywiście też może się poparzyć, ale już w inny, mniej nowoczesny sposób, za który nowoczesna maszynka nie odpowiada.

Podobną filozofię przyjmują języki określane jako języki czwartej generacji (4GL), gdzie występują zarówno wyrażenia odnoszące się do nietrwałych, lokalnych danych, jak i zapytania w SQL odwołujące się do tabel zapamiętanych w bazie danych. Również PL/SQL systemu Oracle, pierwszy komercyjny język programowania w pełni zintegrowany z językiem SQL wprowadza podział na wyrażenia i zapytania. Wydaje się, że w tym przypadku powodem są ograniczenia i narzuty składniowe języka SQL, w którym nie da się zapisać tak prostych wyrażeń jak 2+2.

Najbardziej znany obiektowy język zapytań OQL (standard ODMG) nie różnicuje sposobu wiązania obiektów/atrybutów indywidualnych oraz obiektów/atrybutów będących kolekcjami. Standard ODMG nie zakłada jednak ortogonalnej trwałości. Zapytania w OQL dotyczą więc wyłącznie bazy danych. OQL nie jest zintegrowany z językiem programowania (w stylu PL/SQL). Zatem zapytania w OQL nie pełnią roli wyrażeń, odwołują się wyłącznie do trwałych danych ignorując nietrwałe, jakkolwiek zapytania takie jak 2+2 są w nim wyrażalne.

Połączenie OQL z obiektowym językiem programowania nieuchronnie prowadzi do niekorzystnych zjawisk określanych jako "niezgodność impedancji". Mimo że manifest obiektowych baz danych [Atki89] postulował brak niezgodności impedancji, OQL powiązany z językiem Java wykazuje tę niezgodność w najbardziej "nieretuszowanej" formie. Taki "retusz" zastosowano w zagnieżdżonym SQL, gdzie nazwy zmiennych języka programowania są zintegrowane składniowo z zapytaniami. Zapytania OQL są stringami znaków komunikowanymi jako parametry specjalnych metod języka Java, co implikuje, że z semantycznego punktu widzenia są bytami różnymi od wyrażeń języka Java. Wartości zmiennych języka programowania można tam komunikować do zapytań poprzez specjalne parametry tych zapytań, w dość niewygodnej (i prawdopodobnie błędogennej) formie. ODMG uzasadnia te rozwiązania trudnością wypromowania całkowicie nowego języka programowania. Stąd oparcie koncepcji na językach o ugruntowanej pozycji, takich jak C++, Smalltalk i Java. Nieuchronną konsekwencją tego podejścia jest istnienie dwóch odrębnych systemów składni, semantyki i  mechanizmów wiązania dla wyrażeń i dla zapytań, a to powoduje, że niezgodności impedancji nie da się uniknąć.

Dodatkową okolicznością większości języków zapytań, która ogranicza ich rolę jako wyrażeń, jest to, że zapytanie może zwrócić wartość, ale nie może zwrócić referencji do pewnej danej zapamiętanej w składzie. Uniemożliwia to wykorzystanie zapytań jako składowych zdań imperatywnych, takich jak podstawienie (update w SQL) lub usuwanie (delete w SQL).

Loqis jest prawdopodobnie pierwszym w historii systemem, w którym zrealizowano pełny język programowania oparty na wczesnej wersji omawianego w poprzednim rozdziale języka zapytań SBQL. Loqis nie wprowadza wyrażeń innych niż zapytania. Język programowania systemu Loqis posiada zestaw cech, których pełna kombinacja nie występuje w innym języku programowania:

  • Pełna ortogonalna trwałość, czyli brak jakichkolwiek różnic syntaktycznych i semantycznych w dostępie i operacjach na nietrwałych i trwałych danych.

  • Pełny relatywizm obiektów w powiązaniu z relatywizmem wyrażeń języka. Umożliwia przetwarzanie obiektów o dowolnej liczbie poziomów hierarchii przy zachowaniu identyczności konstrukcji języka dla dowolnego poziomu hierarchii.

  • Identyczne mechanizmy zakresu i wiązania dla obiektów indywidualnych i dla kolekcji. Odwołania do kolekcji i do obiektów indywidualnych mogą być dowolnie ze sobą kombinowane w ramach jednego zapytania.

  • Brak podziału na zapytania i wyrażenia. Dowolne wyrażenie jest także zapytaniem. Wszelkie operatory występujące tradycyjnie w wyrażeniach mogą występować także w zapytaniach.

  • Zapytania mogą zwracać zarówno wartości (dowolnie złożone), jak i referencje do obiektów. Jak widzieliśmy w poprzednim rozdziale, wyniki zapytań w SBQL mogą być specyficznymi strukturami zbudowanymi z wartości, referencji i nazw.


Zapytania jako wyrażenia języka programowania będą w związku z tym używane we wszystkich kontekstach, w których używane są wyrażenia, w szczególności w następujących sytuacjach:

  • Jako składowa zdań imperatywnych, np. instrukcji podstawienia, usuwania, tworzenia i wstawiania.

  • Jako parametry procedur, funkcji lub metod, przy zachowaniu klasycznych metod przekazywania parametrów znanych jako wołanie przez wartość (call-by-value) oraz wołanie przez referencję (call-by-reference).

  • Jako składnik zdania określającego wynik procedury lub metody funkcyjnej.

  • Jako składnik iteratora znanego jako "for each ... do ...", określający liczbę pętli iteratora oraz element przetwarzany w każdym jego cyklu.


Czy tego rodzaju język nie jest utopią? System Loqis jest tylko akademickim prototypem, a pomysły akademickie często okazują się mało wartościowe dla praktyki. Powstaje pytanie, jakiego rodzaju zagrożenia można wiązać z realizacją języka zapytań i programowania o podanych własnościach. Najważniejsze z nich są następujące:

  • Niska wydajność. Głównym celem metod optymalizacji zapytań jest zminimalizowanie liczby odwołań do dysku. Metody optymalizacyjne są tradycyjnie wiązane z modelem relacyjnym, ale wiele z nich ma bezpośrednie odpowiedniki dla modelu obiektowego. Dla SBQL zostały odkryte nieznane wcześniej mocne metody optymalizacyjne [Plod00a, Plod00b, Plod01a, Plod01b, Plod01c, Plod99a, Plod99b].

  • Konieczność wypromowania nowego języka programowania. Na tym tle panuje w środowiskach informatyki komercyjnej pewna histeria, nie mająca jednak pełnego uzasadnienia w praktyce. Język Java stał się bardzo szybko popularny, mimo, że praktycznie nie występują w nim cechy nieznane w innych językach. Język PHP w ciągu dwóch lat zdobył miliony zwolenników. Wiele rynkowych systemów jest wyposażanych w języki o bardzo specyficznych nazwach i rozwiązaniach; użytkownicy traktują je normalnie  i efektywnie ich używają.


Zadaniem świata akademickiego jest więc proponowanie dobrych rozwiązań, a nie zastanawianie się, czy dadzą się one wypromować. Jesteśmy zdania, że mimo podanych zagrożeń warto rozwijać pomysł nowego języka programowania opartego na podanych wyżej własnościach.

W dalszym ciągu tego rozdziału przedstawimy konstrukcje imperatywne, które można byłoby rozwijać na bazie języka zapytań oraz abstrakcje programistyczne, takie jak procedury, procedury funkcyjne i metody.

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