LAB: Integracja z RDBMS
Celem laboratorium jest pokazanie możlwości integracji maszyny wnioskującej SWI Prolog z systemami zarządzania relacyjnymi bazami danych (RDBMS).
Interackja taka jest możliwa z wykorzystaniem ODBC.
1 Konfiguracja ODBC
Aby móc skorzystać z tzw. źródła danych ODBC, należy w domowym katalogu utworzyć plik o nazwie .odbc.ini
oraz umieścić w nim poniższą treść:
[prolog]
Description = PostgreSQL Unicode
Driver = PostgreSQL Unicode
Trace = No
TraceFile =
Database = prolog
Servername = borg.ia.agh.edu.pl
Username =
Password =
Port = 5432
Protocol = 6.4
ReadOnly = No
RowVersioning = No
ShowSystemTables = No
ShowOidColumn = No
FakeOidIndex = No
ConnSettings =
Uwaga:
Wartości pól Username
oraz Password
będą podane przez prowadzącego na zajęciach.
Prawa dostępu do pliku .odbc.ini
powinny być ustawione na 600.
Powyższe działania konfigurują źródło danych ODBC o nazwie prolog
([prolog]
).
Źródło to jest skojarzone z systemem zarządzania relacyjnymi bazami danych PostgreSQL działającym na serwerze borg.ia.agh.edu.pl
, a konkretnie z bazą danych o nazwie prolog
(Database
).
Ćwiczenie
Sprawdź, czy źródło danych jest poprawnie skonfigurowane. W tym celu uruchom narzędzie isql
umożlwiające wykonywanie zapytań w języku SQL na źródle ODBC:
isql prolog
Jeżeli połączenie powiodło się zostanie wyświetlony stosowny komunikat:
~$ isql prolog
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL>
Następnie wykonaj proste zapytanie np. SELECT nazwa FROM kompozycje;
. Rezultat powinien być zbliżony do tego poniżej:
SQL> SELECT nazwa FROM kompozycje;
+-----------------------------------------+
| nazwa |
+-----------------------------------------+
| Bukiet 1 |
| Bukiet 2 |
| Bukiet 3 |
| Kosz 1 |
| Kosz rozyczek |
| Kosz mix |
| Kompozycja suszona |
| Koszyk gozdzikowy |
| Hiacynty w koszyku |
| Biala azalia |
| Rozowa azalia |
| Orchidea rozowa |
| Kosz z azalia |
| Wiazanka czerwona |
| Bukiecik serc |
| Ikebana z rozami |
| Kwitnacy kosz |
| Sloneczniki z lilia |
| Strelicje |
| Anturium latem |
+-----------------------------------------+
SQLRowCount returns 20
20 rows fetched
SQL>
2 ODBC w SWI-Prolog
SWI Prolog umożliwia wykonywanie zapytań na źródłach ODBC.
Rezultaty zapytania (pojedynczy wiersz) uzgodniane są ze wskazanymi szukanymi.
Wartości kolejnych kolejnych wierszy dostępne są poprzez mechanizm nawrotów.
Przed wykonaniem zapytania należy nawiązać połączenie ze skonfigurowanym źródłem ODBC.
Dokumentacja dotycząca predykatów obsługujących połączenia ODBC z bazami danych.
3 Połączenia
Do nawiązaywania połączenia ze źródłem danych ODBC służy predykat odbc_connect/3
.
Pierwszym argumentem jest nazwa źródła danych ODBC (w poniższym przykładzie prolog
), drugim jest identyfikator połączenia, trzecim opcje połączenia, np.
odbc_connect('prolog', Polaczenie,
[open(once)
]).
Przed zakończeniem korzystania z połączenia ze źródłem danych należy wywołać predykat
odbc_disconnect/1
, którego argumentem musi być identyfikator połączenia (zakładając, że szukana Polaczenie
jest uzgodniona z wartością będącą identyfikatorem połączenia utworzonym za pomocą odbc_connect/3
):
odbc_disconnect(Polaczenie).
Zamiast identyfikatora połączenia można użyć synonimu połączenia, korzystając z opcji alias
:
?- odbc_connect('prolog', _,
[ alias(prolog),
open(once)
]).
Tak otwarte połączenie można zakończyć:
?- odbc_disconnect(prolog).
4 Schemat Bazy Danych
Schemat bazy danych, dostępnej jako źródło danych prolog
przedstawiony jest poniżej.
CREATE TABLE klienci (
idklienta VARCHAR(10) NOT NULL,
haslo VARCHAR(10) NOT NULL,
nazwa VARCHAR(40) NOT NULL,
miasto VARCHAR(40) NOT NULL,
kod CHAR(6) NOT NULL,
adres VARCHAR(40) NOT NULL,
email VARCHAR(40),
telefon VARCHAR(16) NOT NULL,
fax VARCHAR(16),
nip CHAR(13),
regon CHAR(9)
);
CREATE TABLE kompozycje (
idkompozycji CHAR(5) NOT NULL,
nazwa VARCHAR(40) NOT NULL,
opis VARCHAR(100),
cena NUMERIC(7,2),
minimum INTEGER,
stan INTEGER
);
CREATE TABLE odbiorcy (
idodbiorcy INTEGER NOT NULL,
nazwa VARCHAR(40) NOT NULL,
miasto VARCHAR(40) NOT NULL,
kod CHAR(6) NOT NULL,
adres VARCHAR(60) NOT NULL
);
CREATE TABLE zamowienia (
idzamowienia INTEGER NOT NULL,
idklienta VARCHAR(10) NOT NULL,
idodbiorcy INTEGER NOT NULL,
idkompozycji CHAR(5) NOT NULL,
termin DATE NOT NULL,
cena NUMERIC(7,2),
zaplacone BOOLEAN,
uwagi VARCHAR(200)
);
CREATE TABLE historia (
idzamowienia INTEGER NOT NULL,
idklienta VARCHAR(10),
idkompozycji CHAR(5),
wartosc NUMERIC(7,2),
termin DATE
);
Kompletny skrypt z schematem i danymi.
5 Wykonywanie zapytań
Zapytania można realizować korzystając z predykatu odbc_query/4
(albo odbc_query/3
, patrz dokumentacja).
Pierwszym argumentem jest identyfikator połączenia, drugim zapytanie w języku SQL, trzecim rezultat zapytania w postaci termu row/n
(argumenty predykatu row/n
będą uzgodnione z wartościami w kolejnych kolumnach zwaracanych przez zapytanie), czwartym lista dodatkowych opcji.
Przykładowe zapytanie zwracające jako wartości szukanych Nazwa
, Email
wartości kolumn nazwa
i email
tabeli klienci
będzi wyglądało następująco:
?- odbc_query(prolog, 'SELECT nazwa, email FROM klienci' ,row(Nazwa, Email), []).
Ostatni argument odbc_query/4
umożliwia przekazanie dodatkowych opcji, m.in. konwersje typów pomiędzy SQL a Prologiem (patrz dokumentacja).
Ćwiczenie
Otwórz połączenie do bazy danych korzystając ze źródła danych prolog
.
Wykonaj następujące zapytanie SQL: SELECT SUM(cena), miasto FROM zamowienia JOIN odbiorcy USING (idodbiorcy) GROUP BY miasto;
, przeglądnij wyniki.
Zamknij połączenie.
6 Proste zapytania
Ćwiczenie
Zaimplementuj:
predykat op/0
otwierający połączenie ze źródłem danych prolog
,
predykat cl/0
zamykający w/w połączenie,
predykat
kompozycje/2
udostępniający informacje o kompozycji tj. identyfikator oraz cenę.
Uwaga: może być konieczne zastosowanie konwersji typów, użyteczny predykat:
atom_number/2
(patrz
dokumentacja).
Przetestuj działanie w/w predykatów.
7 Złożone przetwarzanie
Częstą rozterką kupojącego jest: mam określoną sumę pieniędzy, ale co moge za to kupić np.:
Takie zapytanie jest trudne lub wręcz niemożliwe do zaimplementowania za pomocą SQL.
Ćwiczenie
Zaimplementuj predykat jakieza/2
, tak aby zapytanie:
?- jakieza(200,X).
uzgadniało X z listą nazw identyfikatorów kompozycji kwiatowych, które można kupić mając do dyspozyji 200 zł. Uwaga: predykat winien być niedeternistyczny, umożliwiać znalezienie alternatywnych rozwiązań.
8 Samodzielny program
Wykorzystaj kod z poprzedniego ćwiczenia.
Ćwiczenie
Zmodyfikuj kod programu z poprzedniego ćwiczenia, tak aby stanowił samodzielną aplikację.
Program po skonsultowaniu, powinien zapytać o kwotę i wyświetlić wszystkie możlwie kombinacje kompozycji kwiatowych, które można za podaną kwotę kupić, podając: identyfikator kompozycji, nazwę oraz cenę.
Uwagi, komentarze, propozycje
Laboratorium jest za krótkie. Zostaje ok. 30 minut wolnego czasu.
— Szymon Świerkosz