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)
  Wstęp
  1. Składnia SBQL
  2. Stos rezultatów (QRES)
  3. Ogólna architektura mechanizmu przetwarzania zapytań
  4. Procedura ewaluacji zapytań eval
  5. Operatory algebraiczne
  Podsumowanie
  Zadania
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
XIV.
Procedury, procedury funkcyjne, metody, reguły zakresu
XV.
Parametry procedur i metod, procedury rekurencyjne, optymalizacja poprzez modyfikację zapytań

 

1. Składnia SBQL

Dla zdefiniowania składni SBQL 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 i metody itd. nie posiada reprezentacji zewnętrznej; może istnieć więc wyłącznie wewnątrz składu obiektów lub jest zwracane jako rezultat zapytania. Zwykle zewnętrzny reprezentant elementu zbioru V jest zwany w językach programowania literałem; nazwa ta została użyta w innym (niewłaściwym) znaczeniu w terminologii standardu ODMG. Można użyć terminu stała, ale następuje tu kolizja znaczeniowa z nazwanym elementem składu obiektów, którego nie można modyfikować. Aby nie doprowadzać do nieporozumień, przywrócimy właściwe znaczenie terminu literał, znane z języków programowania na oznaczenie zewnętrznego, leksykalnego reprezentanta pewnej wartości zbioru V. Zbiór literałów będziemy oznaczać L. Będziemy zakładać, że istnieje prosta i jednoznaczna funkcja odwzorowująca element zbioru L w element zbioru V. Zgodnie z powszechną konwencją, funkcji tej nie będziemy specjalnie oznaczać. Np. literał "Kowalski" może pojawić się w zapytaniu oraz "Kowalski" jest wartością (stringiem) przechowywaną w składzie obiektów lub zwracaną jako rezultat zapytania. Subtelne różnice semantyczne będziemy najczęściej zaniedbywać, przyjmując, że rozróżnienie wynika z kontekstu, w którym taki ciąg znaków się pojawia. Zwrócimy uwagę, że pierwszy string "Kowalski" będzie elementem definiowanego przez nas języka zapytań, zaś drugi - elementem metajęzyka, który służy jako podstawa opisu języka, m.in. tekstu tej książki. Precyzyjne rozróżnienie pomiędzy jednym i drugim może wydawać się przesadą, ale naszym zdaniem brak tego rodzaju rozróżnienia doprowadził do zasadniczych błędów koncepcyjnych i matematycznych w innych podejściach do semantyki języków zapytań.

Przyjmiemy także, że wprowadzone poprzednio identyfikatory należące do zbioru I nie mają leksykalnych reprezentantów, czyli nie mogą być zapisane w postaci literałów. Programista lub użytkownik nie ma możliwości użycia w zapytaniu reprezentacji znakowej wewnętrznego identyfikatora w taki sposób, że jej znaczeniem będzie ten wewnętrzny identyfikator. Oczywiście, z jakichś powodów, np. w celu przetestowania programu, będzie mógł skorzystać z funkcji, która wydrukuje identyfikator w postaci ciągu znaków. Takiego ciągu znaków nie będzie jednak można bezpośrednio odwzorować w zapytaniu w odpowiadający mu identyfikator.

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 element zbioru L 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 za pomocą 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 LV. Np. element leksykalny sum jest ciągiem trzech znaków, który oznacza zaimplementowaną funkcję agregowaną sumującą wartości ze zbioru będącego jej argumentem. Rozróżnienie to może okazać się istotne dla precyzyjnej definicji semantyki, m.in. ze względu na własności określane jak przeciążanie operatorów oraz polimorfizm.

Z syntaktycznego punktu widzenia operatory będą podzielone na unarne i binarne. Operatory będą ponadto podzielone na algebraiczneniealgebraiczne; podział ten zostanie wyjaśniony nieco dalej.

  • Jeżeli D jest oznaczeniem operatora algebraicznego unarnego, zaś q jest zapytaniem, wówczas D( 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.

  • Jeżeli D jest oznaczeniem operatora algebraicznego binarnego, zaś q1q2 są zapytaniami, wówczas q1 D q2 jest zapytaniem. Przykładami operatorów algebraicznych binarnych są: =, +, -, *, /, <. >, and, or, union itd.

  • Jeżeli q jest oznaczeniem operatora niealgebraicznego, zaś q1q2 są zapytaniami, wówczas q1 q q2 jest zapytaniem. Przykładami operatorów niealgebraicznych są: selekcja (where), projekcja lub nawigacja (.), zależne złączenie (join), 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.

  • 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, w szczególności jako zmienne "korelacyjne" (tzw. "synonimy" nazw tabel) w SQL, jako zmienne związane kwantyfikatorami, jako kursory w iteratorach itd. Pojęcia zmiennej nie będziemy jednak wprowadzać, jest ono dla definicji naszego języka zapytań zbędne, gdyż zastępujemy je znacznie bardziej precyzyjnymi konstrukcjami semantycznymi.

  • Jeżeli q jest zapytaniem, zaś n Î N, wówczas  q group as n  jest zapytaniem. Operator group as jest unarnym operatorem algebraicznym parametryzowanym nazwą n. Jego semantyka jest nieco inna od semantyki operatora as.

  • Jeżeli q jest zapytaniem, to (q) jest zapytaniem. Ta reguła składniowa pozwala na dowolne używanie nawiasów. Większość nawiasów będziemy pomijać przyjmując powszechne reguły priorytetu operatorów lub kolejność wykonywania operatorów od lewej do prawej.

  • 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. W większości przypadków będziemy przyjmować, że takie zapytania są równoważne.

  • Jeżeli q1, q2, q3 są zapytaniami, to if q1 then q2 else q3 jest zapytaniem. Zapytanie to na podstawie warunku określonego przez q1 wybiera q2 lub q3.

  • Konstrukcje zapytań będą podlegać ograniczeniom typologicznym, które w tym wykładzie będą zakładane implicite. Poza tymi ograniczeniami wszelkie kombinacje zapytań i operatorów będą dozwolone.


Oprócz podanych wyżej konstrukcji dla pewnych szczególnych celów będziemy w miarę potrzeby wprowadzać pewne konstrukcje specjalne.

Przykładowe zapytania zgodne z powyższą składnią są następujące:

P8.1.

2000

zarobek

Osoba

2+2

zarobek > 2000

Osoba where (zarobek > 2000)

(Osoba where (wiek() > 30)) . (zarobek + x + 2000/y)

((Osoba as p) join (p.pracuje_w.Dział as d)) . (p.nazwisko, d.nazwa)

" Osoba (wiek < 65)

Dział where ($(zatrudnia.Osoba) as p (p.wiek < 17))

Na Rys.40 podsumowaliśmy zdefiniowaną przez nas składnię. Nie jest to ostateczna składnia SBQL - w miarę potrzeb będziemy dodawać dalsze konstrukcje.

Zwrócimy uwagę, że wśród algebraicznych operatorów binarnych mogą znaleźć się operatory sumy bagów (È), konkatenacji ciągów elementów oraz iloczynu kartezjańskiego ´. Operatory te są jednak na tyle ważnie, że warto stworzyć dla nich specjalną składnię. Zastosujemy tu składnię ze słowami kluczowymi struct, bagsequence dla oznaczenia tych operatorów, przy czym będą one n-arne zaś ich argumenty będą oddzielone przecinkami, tj. zapytaniami będą następujące konstrukcje:

struct( q1, q2, q3, ...)
bag(q1, q2, q3, ...)
sequence(q1, q2, q3, ...)

Przyjmiemy, że w struct( q1, q2, q3, ...) można pominąć słowo kluczowe struct. Konstrukcja struct( q1, q2, q3, ...) oznacza specyficzny "iloczyn kartezjański" bagów, bag(q1, q2, q3, ...) oznacza sumę bagów, zaś sequence(q1, q2, q3, ...) oznacza konkatenację sekwencji. Semantyka tych operatorów jest dość oczywista, ale posiadająca niuansy; zostaną one objaśnione dalej.

40
Rys.40. Składnia SBQL (podstawowa)

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