I.
Wprowadzenie do  języków zapytań (1)
II.
Wprowadzenie do  języków zapytań (2)
  Wstęp
  1. Niezgodność impedancji
  2. Schemat i organizacja danych - nieodłączne cechy języka zapytań
  3. Pomiędzy złożonością modelu danych a złożonością zapytań
  4. Architektura SZBD włączająca przetwarzanie zapytań
  Podsumowanie
  Zadania
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
XIV.
Procedury, procedury funkcyjne, metody, reguły zakresu
XV.
Parametry procedur i metod, procedury rekurencyjne, optymalizacja poprzez modyfikację zapytań

 

1. Niezgodność impedancji

Wykształcone w latach 70-tych koncepcje dotyczące języków zapytań z definicji zakładały brak algorytmicznej uniwersalności. Ponieważ taka uniwersalność jest jednak niezbędna do tworzenia aplikacji opartych na bazie danych, przyjęto założenie, że języki zapytań będą "podjęzykami" w środowisku wytwórczym oprogramowania, i co za tym idzie, to środowisko będzie oparte na normalnym języku programowania. To oznacza konieczność połączenia języka zapytań z językiem programowania w taki sposób, aby:

  • zapytania mogły być używane wewnątrz programów;

  • zapytania mogły być parametryzowane (dynamicznie, w praktycznie dowolny sposób) przez wartości zmiennych języka programowania;

  • wyniki zapytań mogły być przetwarzane przez programy.


Okazało się, że różnice w koncepcji języków spowodowały znaczne trudności techniczne w realizacji tego rodzaju połączenia. Nie one jednak były przyczyną negatywnego stosunku wielu specjalistów i programistów do tego pomysłu. Główną wadą była znaczna degradacja środowiska rozwoju oprogramowania, objawiająca się na różne sposoby, które kolektywnie ochrzczono mianem "niezgodności impedancji" (impedance mismatch). Terminem tym określa się zespół niekorzystnych cech towarzyszących formalnemu połączeniu języka zapytań (w szczególności SQL) z uniwersalnym językiem programowania, takim jak np. C, C++, Pascal lub Java. Objawia się niezgodnościami w zakresie:

  1. Składni. Programista musi w jednym tekście programu używać dwóch stylów językowych i przestrzegać reguł dwóch różnych gramatyk.

  2. Systemu typów. Język zapytań operuje na typach zdefiniowanych w schemacie bazy danych, m.in. relacjach, natomiast język programowania posiada zwykle odmienny system typów, w którym nie występuje typ relacja. Większość języków programowania ma wbudowaną statyczną kontrolę typów, podczas gdy SQL takiej kontroli nie przewiduje.

  3. Semantyki i paradygmatów języków. Koncepcja semantyki języków jest zasadniczo różna. Język zapytań bazuje na stylu deklaracyjnym (co wyszukać, a nie jak), podczas gdy języki programowania bazują na stylu imperatywnym (sekwencja instrukcji ustala jak wyszukać, skąd pośrednio wynika co).

  4. Poziomu abstrakcji. Język zapytań uwalnia programistę od wielu szczegółów organizacji i implementacji danych (np. organizacji zbiorów, obecności lub nieobecności indeksów itd.), podczas gdy w języku programowania te szczegóły muszą być oprogramowane explicite. Problem pojawia się wtedy, gdy dane zawarte w bazie danych muszą być dostępne nie tylko poprzez zapytania, ale też przez standardowe konstrukcje języka programowania. Odizolowanie programisty od tych szczegółów wymaga napisania szeregu generycznych modułów, bibliotek i procedur, które wymagają dodatkowych nakładów i zwykle nie są dostatecznie uniwersalne.

  5. Faz i mechanizmów wiązania. Języki zapytań są oparte na późnym wiązanieu (są interpretowane), podczas gdy języki programowania zakładają wczesne wiązanie (podczas kompilacji i konsolidacji). Stwarza to problemy m.in. dla mocnej kontroli typów, obrazu przestrzeni nazw, z którymi ma do czynienia programista, programów odpluskwiających itd.

  6. Przestrzeni nazw i reguł zakresu. Język zapytań i język programowania posiadają własne przestrzenie nazw, które mogą zawierać identyczne nazwy o różnych znaczeniach. Odwzorowania pomiędzy przestrzeniami nazw wymagają dodatkowych środków syntaktycznych i semantycznych. Przestrzeń nazw języka programowania jest zbudowana hierarchicznie i podlega regułom zakresu opartym na zasadzie stosu. Te reguły są ignorowane przez język zapytań, powodując wiele trudności.

  7. Traktowania wartości zerowych. Bazy danych i języki zapytań posiadają wyspecjalizowane środki dla przechowywania i przetwarzania wartości zerowych. Środki te nie występują w językach programowania.

  8. Schematów iteracyjnych. W języku zapytań iteracje są wtopione w semantykę operatorów, takich jak selekcja, projekcja i złączenie. W języku programowania iteracje muszą być organizowane explicite za pomocą pętli for, while, repeat lub innych. Przetwarzanie wyników zapytań za pomocą języka programowania wymaga specjalnych udogodnień, takich jak kursory i iteratory.

  9. Traktowania cechy trwałości danych. Języki zapytań przetwarzają wyłącznie trwałe dane (znajdujące się na dysku), podczas gdy języki programowania przetwarzają wyłącznie dane nietrwałe znajdujące się w pamięci operacyjnej. Połączenie obu języków wymaga od programisty użycia specjalnych środków językowych do parametryzacji zapytań przez zmienne języka programowania oraz środków językowych i architektonicznych służących do transmisji danych z dysku do pamięci operacyjnej i odwrotnie.

  10. Środków programowania ogólnego (generic). Środki te w języku zapytań są oparte na refleksji (patrz np. dynamiczny SQL). Użycie podobnego środka w języku programowania jest zazwyczaj niemożliwe z powodu wczesnego wiązania. Stosowane są inne środki, takie jak funkcje wyższego rzędu, casting, przejście na niższy poziom językowy, polimorfizm lub szablony.

Skutkiem niezgodności impedancji nie są wyłącznie wady estetyczne i ergonomiczne. Niezgodność impedancji powoduje konieczność istnienia dodatkowej warstwy oprogramowania pośredniczącego pomiędzy językiem zapytań a językiem programowania. Ta warstwa zwiększa długość kodu aplikacji, może być źródłem błędów, zwiększa czas uczenia się narzędzia, zwiększa czas wykonania oraz zmniejsza pielęgnacyjność oprogramowania.

Z doświadczenia autora wynika, że po stworzeniu wszystkich mechanizmów niezbędnych do implementacji i funkcjonowania języka zapytań, zaprojektowanie i zrealizowanie konstrukcji programistycznych, takich jak zdania imperatywne, zdania sterujące, procedury itd. wymaga stosunkowo niedużych nakładów, nieproporcjonalnie mniejszych niż realizacja samego języka zapytań. Z tego powodu obstawanie przy idei języka zapytań "zanurzonego" w język programowania i dorabiania do niego specjalnego mechanizmu mającego na celu sklejenie dwóch języków wydaje się mało rozsądne z technicznego punktu widzenia. (Może tu mieć jednak pewien sens marketingowy - umożliwia bowiem twierdzenia, że programowanie baz danych może odbywać się w ulubionym przez klienta języku programowania.) Tak też potoczył się rozwój SQL, który oprócz czystych zapytań wprowadził zdania imperatywne (create, update, insert, delete i inne), procedury zapamiętane w bazie danych, trygery itd., przenosząc w znacznym stopniu logikę budowanych aplikacji na stronę SQL i niwelując przez to niezgodność impedancji. Niektóre firmy, w tym CA, Oracle, Informix i Microsoft poszły dalej, tworząc rozbudowane wersje SQL będące w istocie nowymi językami programowania (np. Oracle PL/SQL). Standard SQL-99 jest już specyfikacją kompletnego języka programowania (dramatycznie eklektycznego i w wielu miejscach redundantnego), chociaż zachowuje jeszcze  tzw. interfejs wołający (Call-Level Interface, CLI), umożliwiający wołanie programów napisanych w SQL z innych języków programowania. Niestety, dokładnie odwrotne stanowisko zajęli twórcy standardu ODMG, gdzie język OQL ma być zanurzany w języki C++, Java i Smalltalk. Twierdzenia, że mimo to standard unika niezgodności impedancji są - w świetle podanych wyżej rodzajów niezgodności - całkowicie bezpodstawne, są raczej elementem pewnej gry reklamowej (dzisiaj już można powiedzieć, że nieudanej). Krytykę tego rozwiązania można znaleźć w [Subi97]

W niniejszym wykładzie nie będziemy zakładać ani też opisywać metod "zanurzenia" języka zapytań w języki programowania. Przyjmujemy więc estetyczny punkt widzenia, przy którym zapytania będą pełniły rolę wyrażeń kompletnego języka programowania, zbudowanego od podstaw na bazie języka zapytań.


Rys.1. Zależności pomiędzy pojęciami systemu przetwarzania zapytań

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