web view1.1.paplašinājuma izstrāde ms visual studio vidē5. ... valodu prolog, funkcionālo...
TRANSCRIPT
Rīgas Tehniskā universitāte
DATORZINĀTNES UN INFORMĀCIJAS TEHNOLOĢIJAS FAKULTĀTE
Lielu datu bāzu administrēšana
3. darbs – Deduktīvās datu bāzes
Izstrādāja: Dmitrijs Vecgailis
I kurss 3. grupa
St. apl. nr: 061RDB156
Pārbaudīja: asoc. prof. Jānis Eiduks
Rīga – 2010
SATURS
UZDEVUMA NOSTADNE....................................................................................................3
1. DEDUKTĪVĀS DATU BĀZES PROJEKTĒŠANA UN IMPLEMENTĒŠANA.....4
1.1. PAPLAŠINĀJUMA IZSTRĀDE MS VISUAL STUDIO VIDĒ...............................................51.2. TABULU RULES UN FACTS IZVEIDOŠANA.................................................................111.3. FAKTU TABULU VEIDOŠANA.....................................................................................12
2. TABULU AIZPILDĪŠANA..........................................................................................17
2.1. TABULU DATI............................................................................................................172.2. DATU IEVADE AR RĪKU BCP......................................................................................182.3. FAKTU IZGŪŠANA.....................................................................................................20
3. KONCEPTUĀLIE VAICĀJUMI................................................................................24
4. LIKUMU DEFINĒŠANA.............................................................................................25
4.1. CEĻU MEKLĒŠANA STARP DIVĀM PILSĒTĀM.............................................................254.2. ĪSĀKĀ MEKLĒŠANA STARP DIVĀM PILSĒTĀM............................................................254.3. BRAUKŠANAS LAIKA IZSKAITĻOŠANA......................................................................264.4. RULES TABULAS AIZPILDĪŠANA AR LIKUMIEM.........................................................27
5. DEDUKTĪVIE VAICĀJUMI......................................................................................28
SECINĀJUMI.......................................................................................................................35
PIELIKUMS..........................................................................................................................37
2
UZDEVUMA NOSTADNE
Praktiskā darba ietvaros ir jāizstrādā deduktīvā datu bāze, kas ļauj izpildīt sarežģītus
vaicājumus izmantojot kādas deklaratīvās programmēšanas valodas elementus (piemēram,
predikātu loģiku – valodu Prolog, funkcionālo valodu – LISP, datu bāzes paplašinājumu –
DATALOG utt.).
Deduktīvajā datu bāzē jānodrošina iespējas:
izpildīt rekursīvus vaicājumus;
papildināt zināšanu bāzi ar jauniem faktiem;
papildināt zināšanu bāzi ar jauniem izveduma likumiem;
uzglābāt faktu un likumus kā datu bāzes objektus.
3
DLL bibliotēka (paplašinājums) ar CS-PROLOGu un tabulāru funkciju SQLPROLOG
tabula Facts
tabula Rules
faktu tabula 1 faktu tabula 2 faktu tabula n…
MS SQL Server 2008datu bāze
1. DEDUKTĪVĀS DATU BĀZES PROJEKTĒŠANA UN IMPLEMENTĒŠANA
Deduktīvās datu bāzes projektēšanai tika izmantoti šādi līdzekļi:
DBVS Microsoft SQL Server 2008;
IDE Microsoft Visual Studio 2008;
brīvi pieejams (GPL licence) interpretators CS-Prolog1.
Izstrādātas deduktīvās datu bāzes arhitektūra ir parādīta . attēlā.
1. attēls. Izstrādātas deduktīvās datu bāzes arhitektūra
. attēlā ir redzams, ka sistēma sastāv no šādiem objektiem:
tabula Facts – tabulā ir ierakstītas tabulu nosaukumi, kuros glabājas fakti;
tabula Rules – tabulā atrodas lietotāja definēti izveduma likumi
formātā kolona1:-kolona2.;
faktu tabulas – relāciju tabulas, kuru ieraksti tiek uzskatīti par faktiem
formātā tabulas_nosaukums(kolona1, kolona2, kolona3, …, kolona3);
1 Interpretatora pirmkods pieejams pēc adreses http://sourceforge.net/projects/cs-prolog/
4
DLL bibliotēka ar izveduma mehānismu – bibliotēkā ir iekapsulēts
interpretators CS-Polog, kurš adaptēts (papildināts ar vienu klasi un tabulāru
funkciju) darbam ar datu bāzi.
Pirms izstrādāt deduktīvo datu bāzi ir jāveic šādi pasākumi:
Jāizveido lietotājs ar tiesībām papildināt datu bāzi ar CLR (Common
Language Runtime) struktūrām (t.i. procedūrām, funkcijām, trigeriem utt.,
kas ir veidoti C# vai kādā citā .NET valodā). Ir iespējams izmantot
administratora kontu;
Ir jānomaina savietojamības režīms, tā lai vērtība būtu 100 (t.i. būs aktivizētas
visas 2008 versijas iespējas, bet nebūs pilnas savietojamības ar iepriekšējām
versijām).
2. attēls. Savietojamības labošanas komanda (rīks SQLCMD)
1.1. Paplašinājuma izstrāde MS Visual Studio vidē
Sākumā tika izveidots jauns SQL Server tipa projekts (sk. . attēlu) ar nosaukumu
SQLProlog.
3. Jauna SQL Server projekta veidošana
5
Projektā bija jānorāda arī datu bāze, kurā tiks izmantotas izstrādājamās komponentes
(sk. . attēlu)
4. attēls. Savienojama izvēles vai veidošanas logs
Tika izmantots jauns pieslēgums iepriekšizveidotai (pagaidām tukšai) datu bāzei
SQLPROLOG (sk. . attēlu).
Autorizācijai tika izmantots administratora konts SA (administrators ir arī datu bāzes
īpašnieks), jo šī tipa lietotājam ir visas nepieciešamas tiesības papildināt datu bāzi ar CLR
tipa objektiem.
5. attēls. Savienojuma veidošanas logs
6
Tad projektā tika importētas visas CS-Prologa pirmkoda klases (sk. . attēlu). Šīs
klases izpildīs visas darbības Prolog vaicājumu apstrādei.
6. attēls. Projektā importētas CS-Prolog klases
Importētas klases nodrošina iespēju strādāt ar CS-Prologu interaktīvajā (konsoles)
režīmā, kad lietotājs ievada faktus un likumus no tastatūras vai ielāde no faila. Skaidrs, ka
deduktīvajā datu bāze faktus un likumus ir “jāņem” no tabulām un nav jānodrošina dialogs
ar lietotāju. Šo iemeslu dēļ, projekts tika papildināts vēl ar vienu klasi SQLProlog.cs
(sk. . attēlu), kurā tika aprakstītas visas metodes, kas ļauj strādāt gan ar datu bāzi, gan ar
Prologu (sk. . attēlu). Pilnais klases pirmkods ir pieejams pielikumā.
Klasē tika izveidotas šādas metodes:
ExecuteQuery(string query) – metode, kas apstrādā Prolog vaicājumu query
un atgriež rezultātu kā sarakstu;
AssertData – metode, kas ielāde faktus no tabulām;
LoadRules – metode, kas ielāde likumus no tabulas.
Metodes AssertData un LoadRules nav speciāli jāizsauc, tās nostrādā metodes
ExecuteQuery laikā.
7
7. attēls. Klases SQLProlog pievienošana
…namespace Prolog{ class SQLProlog { // engine - CS-Prologa interperatora eksemplars private static PrologEngine engine = new PrologEngine(); // Si funkcija atgriez sarakstu ar atbildem uz uzdoto vaicajumu public ArrayList ExecuteQuery(string query) {
… return list; } // Si funkcija pievieno faktus no datu bazes public void AssertData() { … } // Si funkcija pievieno likumus no datu bazes public void LoadRules() { … }}
8. attēls. Klases SQLProlg karkass
Projekts tika papildināts ar speciālo klasi, kas realizē datu bāzes funkciju, kura
atgriež tabulu (sk. . attēlu).
8
9. attēls. Lietotāja tabulārās funkcijas pievienošana
Klases ķermenis tika papildināts ar metodēm, kā paradīts . attēlā. Metode Prolog
(string query) kā argumentu saņem Prolog vaicājumu, bet kā rezultātu atgriež tabulu ar
piecām kolonām (TableDefinicion). Pati metode ir statiskā, un tabulas veidošanai netieši
izmanto papildus statisko metodi FillRow (šo metodi izsauc DBVS MS SQL Server
funkcijas Prolog izsaukšanas laikā).
Redzams, ka metode Prolog atgriež sarakstu, savukārt, metode FillRow apstrādā
atgriezta saraksta elementus un atgriež apstrādes rezultātus caur izejas argumentiem
(column_1, column_2, … , column_5), kuru definējums un secība sakrīt ar tabulas
definējumu.
9
Ņemot vērā to, ka dažiem vaicājumiem pieci elementi (piecas kolonas) izejas tabulā
dažreiz nemaz nav vajadzīgi, metodes sākumā nevajadzīgas kolonas tiek aizpildītas ar
tukšām vērtībām.
using System;using System.Collections;using System.Data;using System.Data.SqlClient;using System.Data.SqlTypes;using Microsoft.SqlServer.Server;using System.Diagnostics;namespace Prolog{ public partial class UDF //StoredProcedures { [SqlFunction(FillRowMethodName = "FillRow", TableDefinition = "column_1 nvarchar(4000), column_2 nvarchar(4000),column_3 nvarchar(4000), column_4 nvarchar(4000), column_5 nvarchar(4000)", DataAccess=DataAccessKind.Read)] public static IEnumerable Prolog(string query) { SQLProlog prolog = new SQLProlog(); ArrayList saraksts; prolog.AssertData(); prolog.LoadRules(); query = query.Replace('"', '\''); saraksts= prolog.ExecuteQuery(query); return saraksts; } private static void FillRow(Object obj, out string column_1, out string column_2, out string column_3, out string column_4, out string col-umn_5) { string[] row = (string[])obj; for (int i = 0; i < row.Length; i++) { row[i] = row[i].Replace("'", ""); } column_1 = ""; column_2 = ""; column_3 = ""; column_4 = ""; column_5 = ""; int j = row.Length; if (j-->0) column_1 = row[0]; if (j-->0) column_2 = row[1]; if (j-->0) column_3 = row[2]; if (j-->0) column_4 = row[3]; if (j-->0) column_5 = row[4];
} }};
10. attēls. Tabulārās funkcijas Prolog un papildus funkcijas FillRow pirmkodi
Izstrādāta funkcija atgriež tabulu ar neinicializēto mainīgo vērtībām. Tā, piemēram,
izsauc funkcija ar šādu vecaki (“Koks”, X), funkcija atgriezis vienu kolonu ar ierakstiem par
Koka vecākiem. Savukārt, ja funkciju izsaukt ar parametru vecaki (X,Y), funkcija atgriezis
10
divas kolonas – viena par kādu cilvēku, otra – par cilvēka vecākiem (patiesībā, funkcija
vienmēr atgriež piecas kolonas, bet informāciju satur tikai pirmās N kolonas, kur N -
neinicializēto mainīgo skaits predikātā (-os)).
Pēc aprakstīto darbību izpildes, projekta uzstādījumu logā tika norādīts (sk. . attēlu),
ka izstrādāto komponenti ir jālieto neaizsargāta režīmā (Unsafe). Tas izskaidrojams ar to, ka
PS-Prolog savā realizācijā satur “nedrošas” konstrukcijas (piemēram, destruktorus).
11. attēls. Projekta uzstādījumu mainīšana
Pēc aprakstīto darbību izpildes, projekts tika nokompilēts un datu bāzei automātiski
pievienojas jauna CLR tabulārā funkcija Prolog (query). Šī funkcija nav darbspējīga, kamēr
datu bāzē nav tabulu Rules un Fatcs.
1.2. Tabulu Rules un Facts izveidošana
Tabulu Rules un Facts izveidošanai tika izmantoti atbilstoši CREATE vaicājumi.
Tabulā Rules tika izveidota ar diviem laukiem:
Predicate – predikāta definējums (piemēram, max(X,Y,Z)).
Body – predikāta ķermenis ar realizāciju (piemēram, X>Y,Z is X,!;Z is Y);
Tādējādi, likums sastāv no divām daļām. Apvienojot divas daļās rodas Prolog
likums: max(X,Y,Z):-X>Y, Z is X,!; Z is Y).
Tabulā Facts sastāv no viena lauka – FactName – tabulas nosaukums, kurā glabājas
fakti.
Vaicājumi, kas veido šādas tabulas ir parādīti . un . attēlos.
11
12. attēls. Tabulas Rules veidošanas vaicājums
13. attēls. Tabulas Facts veidošanas vaicājums
Lai atvieglotu darbu, tika izveidota arī viena glabājamā procedūra, kuru izmanto
klase SQLProlog (sk. pielikumu), ar nosaukumu GetTable. Procedūra atgriež tabulu, kuras
nosaukums ir nodots kā parametrs. Lai realizētu šo procedūru, tika izmantota dinamiskā
konstrukcija EXEC (šī funkcija ir līdzīga Oracle funkcija EXECUTE IMMEDIATE).
Procedūras veidošanas vaicājums ir parādīts . attēlā.
14. attēls. Procedūras GetTable veidošanas vaicājums
1.3. Faktu tabulu veidošana
Lai nodrošinātu iespēju deduktīvai datu bāzei strādāt ar faktiem, tika izveidotas
vairākas tabulas, kurās glabāsies fakti.
Tabulai Pilsetas ir divi lauki – Pilsetas_ID un Pilseta. Pirmais (Pilsetas_ID) – ir
pilsētas unikālais numurs, otrais (Pilseta) – ir pilsētas nosaukums. Tādējādi, tabulā glābās
fakti par pilsētām. Tabulas veidošanas vaicājums ir parādīts . attēlā.
15 attēls. Tabulas Pilsetas veidošanas vaicājums
12
Tabulā Apskates_objekti ir apkopota informācija par apskates objektiem, ko var
redzēt noteiktajā pilsētā. Tabula sastāv no diviem laukiem: viens – Pilsetas_ID – pilsētas
numurs, otrs – Objekts – objekta nosaukums, kas atrodas attiecīgajā pilsēta. Vaicājums, kas
izveido tabulu ir parādīts . attēlā. Redzams, ka tabula ir saistīta ar tabulu Pilsētas.
16 attēls. Tabulas Apskates_objekti veidošanas vaicājums
Tabula Attalumi ir domāta, lai uzglabātu informāciju par attālumiem starp pilsētām, kuras pa tiešo ir saistītas ar ceļu. Tabulā ir trīs lauki. Pirmais un otrais (Pilseta_ID1 un Pilseta_ID2) norāda pilsētas, starp kuram ir ceļš, trešais lauks (Attalums) norāda attālumu starp pilsētām (pie tām, abas pilsētas ir saistītas ar ceļu). Vaicājums, kas izveido šo tabulu ir parādīts . attēlā.
17. attēls. Tabulas Attalumi veidošanas vaicājums
13
Tabula Celi satur informāciju par vidējo pārvietošanas ātrumu uz ceļiem. Ceļš tabulā
tiek uzdots kā trīs elementu kombinācija – ceļa sākumpunkts (lauks Pilseta_ID1), ceļa beigu
punkts (lauks Pilseta_ID2) un vidējais ātrums ar kuru var pārvietoties pa ceļu (lauks
Atrums). Uzdotais vidējais braukšanas ātrums attiecas uz visiem posmiem, kas atrodas starp
sākumu un beigām (piemēram, ja vidējais ātrums uz ceļa no pilsētas A līdz pilsētai C ir 80
km/st, un pilsēta A ir saistīta ar pilsētu B, bet pilsēta B ar pilsētu C (dati no tabulas
Attalumi), tad vidējais pārvietošanas ātrums starp pilsētām A un B (vai/un B un C) arī būs
80 km/st). Jāņem vērā, ka ceļš vienmēr ir mazākais attālums starp divām (gadījumos, ja ir
iespējami vairāki varianti). Vaicājums, kas izveido šo tabulu ir parādīts . attēlā.
Iegūtā datu bāzes tabulu struktūra ir parādīta . attēlā.
18.attēls. Tabulas Celi veidošanas vaicājums
14
19. attēls. Datu bāzes tabulu struktūra
. attēlā ir parādīta deduktīvas datu bāzes SQLProlog paplašinājuma darbības shēma.
Redzams, ka pēc funkcijas Prolog izsaukšanas notiek faktu un likumu ielāde atmiņā. Tad
notiek sākotnēja vaicājuma izpilde. Vaicājuma izpildes rezultāts tiek transformēts tabulā un
atgriezts kā funkcijas vērtība.
15
PROLOG (‘Vaicājums Prologā’)
klases SQLProlog eksemplāra veidošana
Metožu LoadRules un LoadFacts izsaukšana (faktu ielādē atmiņā)
Vaicājuma izpilde CS-Prologā
Rezultāts:X = Vērtība1,Y = Vērtība2;X = Vērtība3,Y = Vērtība4;true.
column_1 column_2 column_3 column_4 column_5
Vērtība1 Vērtība_2
Vērtība3 Vērtība4
Tabulas atgriešana
Rezultātu transformēšana tabulā
tabula Rules tabula Facts
tabulas ar faktiem
20. attēls. Deduktīvās datu bāzes SQLProlog paplašinājuma darbības shēma
16
Rīga
Sigulda
Salaspils
Jēkabpils
Jūrmala
Liepāja
Kuldīga
Ventspils
215 km91 km
58 km
166 km
119 km51 km
19 km
124 km
23km
Jelgava
47 km
137 km
Cēsis
39 km
2. TABULU AIZPILDĪŠANA
2.1. Tabulu dati
Tabulas tika aizpildītas ar datiem, kas satur informāciju par pilsētām, attālumiem
starp pilsētām, vidējo braukšanas ātrumu konkrētajā ceļā un informāciju par apskates
objektiem, kas atrodas noteiktajā pilsētā.
. attēlā ir parādīts ceļu tīkls (ar attālumiem starp pilsētām), kas tika izmantots tabulas
Attalumi aizpildīšanai.
21. attēls. Pilsētas, attālumi un ceļi.
. attēlā ir uzskaitīti ceļi starp pilsētām ar vidējo pārvietošanas ātrumu.
Pilsēta Pilsēta Ātrums (km/st)Rīga Cēsis 90Rīga Jēkabpils 85Rīga Jelgava 100
RīgaVentspils 95
Rīga Liepāja 85
LiepājaVentspils 75
Liepāja Jūrmala 85
KuldīgaVentspils 85
22. attēls. Informācija par vidējo ātrumu uz ceļiem
. attēlā ir uzskaitītas visas pilsētas un pilsētās esošās apskates objekti.
17
Pilsēta Apskates objekti objekti
Rīga Brīvdabas muzejsRīga Botāniskais dārzsRīga ZoodārzsRīga VecpilsētaRīga Dabas muzejsRīga PilsRīga PludmaleJēkabpils PilsJēkabpils Strausu fermaJēkabpils Brīvdabas muzejsCēsis PilsCēsis VējdzirnavaCēsis AlaCēsis Dabas parks
Salaspils Botāniskais dārzsSalaspils VecpilsētaSalaspils Doles salaJelgava PilsJelgava Mīlestības alejaJelgava VecpilsētaJelgava Dabas parksJūrmala PludmaleJūrmala AkvaparksJūrmala Bērnu parksLiepāja CietumsLiepāja PludmaleLiepāja KarostaLiepāja Izgriežamais tiltsKuldīga ŪdenskritumsKuldīga Vecpilsēta
Kuldīga Vecais tiltsKuldīga ŪdensdzirnavasKuldīga PilsVentspils Bērnu parksVentspils AkvaparksVentspils PludmaleVentspils GovsVentspils MazbānītisSigulda AlaSigulda PludmaleSigulda PilsSigulda PilsdrupasSigulda Dabas parksSigulda ŪdenskritumsSigulda Vagoniņš
23. attēls. Apskates objekti
2.2. Datu ievade ar rīku bcp
Rīks bcp ļauj ievadīt datus no teksta failiem (līdzīgs Oracle rīkam SQL*Loader).
Tabulas Pilsetas aizpildīšanai tika izmantots fails Pilsetas.txt (sk. . attēlu) un bcp
komanda, kas parādīta . attēlā.
1 Rīga2 Jēkabpils3 Cēsis4 Salaspils5 Jelgava6 Jūrmala7 Liepāja8 Kuldīga9 Ventspils10 Sigulda
24. attēls. Faila Pilsetas.txt saturs
25. attēls. Tabulas Pilsetas aizpildīšanas komanda
18
Tabulas Apskates_objekti aizpildīšanai tika izmantots fails Objekti.txt (sk. . attēlu)
un bcp komanda, kas parādīta . attēlā.
1 Brīvdabas muzejs1 Botāniskais dārzs1 Zoodārzs1 Vecpilsēta1 Dabas muzejs1 Pils1 Pludmale2 Pils2 Strausu ferma2 Brīvdabas muzejs3 Pils3 Vējdzirnavas3 Ala3 Dabas parks4 Botāniskais dārzs
4 Vecpilsēta4 Doles sala5 Pils5 Mīlestības aleja5 Vecpilsēta5 Dabas parks6 Pludmale6 Akvaparks6 Bērnu parks7 Cietums7 Pludmale7 Karosta7 Izgriežamais tilts8 Ūdenskritums8 Vecpilsēta
8 Vecais tilts8 Ūdensdzirnavas8 Pils9 Bērnu parks9 Akvaparks9 Pludmale9 Govs9 Mazbānītis10 Ala10 Pludmale10 Pils10 Pilsdrupas10 Dabas parks10 Ūdenskritums10 Vagoniņš
26. attēls. Faila Objekti.txt saturs
27 attēls. Tabulas Apskates_objekti aizpildīšanas komanda
Tabulas Attalumi aizpildīšanai tika izmantots fails Attalumi.txt (sk. . attēlu) un bcp
komanda, kas parādīta . attēlā.
1 10 511 4 191 5 471 6 231 7 2157 9 1197 8 918 9 588 6 1376 9 16610 3 394 2 124
28. attēls. Faila Attalumi.txt saturs
19
29 attēls. Tabulas Attalumi aizpildīšanas komanda
Tabulas Celi aizpildīšanai tika izmantots fails Celi.txt (sk. . attēlu) un bcp komanda,
kas parādīta . attēlā.
1 3 901 2 851 5 1001 9 951 7 857 9 757 6 858 9 85
30 attēls. Faila Celi.txt saturs
31. attēls. Tabulas Celi aizpildīšanas komanda
Lai Prolog paplašinājums zinātu, kur atrodas fakti, ko jāizmanto izvedumos, tabula
Facts tika papildināta ar ierakstiem, kas norāda uz vajadzīgām tabulām (sk. . attēlu).
32. attēls. Tabulas Facts aizpildīšanas vaicājums
2.3. Faktu izgūšana
Lai pārliecinātos, ka visas tabulas bija aizpildītas pareizi, tika izmantoti vairāki
SELECT vaicājumi. Nodāļā ir apskatīti gan parastie SQL vaicājumi, gan deduktīvie
vaicājumi, kas griežas pie tabulām kā pie faktiem.
Reālajās situācijās, gadījumos, kad ir iespējams iegūt vienu un to pašu rezultātu
izmantojot gan “tīro” SQL, gan deduktīvo paplašinājumu, datu izgūšanai ir jāizmanto
parastais SQL, jo tas vaicājumus izpilda ātrāk.
Vaicājumi, kas izgūst datus par attālumiem starp pilsētām ir parādīti . ,. attēlos.
20
33. attēls. Informācija par attālumiem starp pilsētām (SQL vaicājums)
34. attēls. Informācija par attālumiem starp pilsētām (deduktīvais vaicājums)
Vaicājumi, kas izgūst datus par pilsētas apskates objektiem ir parādīti ., . attēlos (ir
parādīts tikai izgūto datu fragments, jo tabulā ir liels ierakstu skaits).
21
35. attēls. Informācija par pilsētas apskates objektiem (SQL vaicājums)
36. attēls. Informācija par pilsētas apskates objektiem (deduktīvais vaicājums)
22
Vaicājumi, kas izgūst datus par vidējo pārvietošanas ātrumu ir parādīti . ,. attēlos.
37. attēls. Informācija par vidējām ātrumiem uz ceļiem (SQL vaicājums)
38. attēls. Informācija par vidējām ātrumiem uz ceļiem (deduktīvais vaicājums)
23
3. KONCEPTUĀLIE VAICĀJUMI
1. Kā nokļūt no pilsētas A līdz pilsētai B?
Vaicājumam ir jāatgriež visi iespējamie varianti kā var nokļūt no pilsētas A līdz
pilsētai B. Tā, piemēram, no Rīgas līdz Jūrmalai var nokļūt pa šādiem maršrutiem:
Rīga,JūrmalaRīga,Liepāja,Kuldīga,JūrmalaRīga,Liepāja,Kuldīga,Ventspils,JūrmalaRīga,Liepāja,Ventspils,JūrmalaRīga,Liepāja,Ventspils,Kuldīga,Jūrmala
Papildus vaicājumi (izmantojot arī SQL konstrukcijas):
1.1. Cik daudz variantu, kā var nokļūt no pilsētas A uz B?
1.2. Kāds ir garākais maršruts no pilsētas A līdz B, tā, lai pilsētas neatkārtotos un
nebūtu ciklu?
1.3. Kādi ir maršruti, ja braucot no pilsētas A līdz pilsētai B ir jāapmeklē pilsēta C.
1.4. Kur un pa kādiem ceļiem var aizbraukt no pilsētas A?
2. Kāds ir īsākais ceļš starp pilsētām A un B?
Vaicājumam ir jāatgriež īsākais ceļš kā var nokļūt no vienas pilsētas līdz otai,
piemēram, īsākais ceļš no Rīgas līdz Ventspils būs šāds:
Rīga, Jūrmala, Ventspils – 189 km
3. Kādā pilsētā atrodas noteiktais apskates objekts? Piemēram, ja uzdots jautājums,
kur atrodas ala, atbilde būs šāda:
Sigulda, Cēsis
Papildus vaicājumi (izmantojot arī SQL konstrukcijas):
3.1. Kādi apskates objekti atrodas noteiktajā pilsēta?
3.2. Kurā pilsēta, kas atrodas vistuvāk pilsēta A, atrodas noteikts objekts?
4. Cik ilgi jābrauc no pilsētas A līdz pilsētai B? Piemēram, no Rīgas līdz Jūrmalai
atbilde būs šāda:
Rīga – Jūrmala 16 minūtes
Papildus vaicājumi (izmantojot arī SQL konstrukcijas):
4.1. Cik ilgi jābrauc līdz pilsētai, kurā atrodas noteikts apskates objekts?
24
4. LIKUMU DEFINĒŠANA
4.1. Ceļu meklēšana starp divām pilsētām
Izstrādātais algoritms ļauj atrast visus ceļus starp divām grafa virsotnēm (izslēdzot
ciklus). Algoritma pirmkods Prolog valodā ir parādīts . attēlā.
39. attēls. Pirmkods ceļu meklēšanai grafā
Programmas izsaukšanai ir jāizmanto predikāts path(A, B, Path, Length), kur A -
sākuma pilsēta, B – beigu pilsēta, Path – atrastie ceļi, Length – atrasta ceļa garums.
4.2. Īsākā meklēšana starp divām pilsētām
Īsākais ceļš starp divām pilsētām ir viens no ceļiem, kura garums ir mazākais.
Tādējādi, īsākā ceļa meklēšanai var izmantot iepriekšdefinēto predikātu path atlasot īsāko
ceļu. Pirmkods, kas atrod īsāko ceļu ir parādīts . attēlā.
25
40. attēls. Īsākā ceļa meklēšanas algoritms
4.3. Braukšanas laika izskaitļošana
. attēlā piedāvātais algoritms izskaitļo laiku, ko jāpavada ceļā braucot pilsētas A līdz
pilsētai B. Rezultātā tiek atgriezts stundu skaits.
41. attēls. Braukšanas laika izskaitļošanas algoritms
26
4.4. Rules tabulas aizpildīšana ar likumiem
. attēlā ir parādīts faila Rules saturs. Failā ir iekļauti dati par deduktīvajā datu bāzē
izmantotājiem likumiem. . attēlā ir parādīts tabulas Rules aizpildīšanas rezultāts.
42. attēls. Faila Rules.txt saturs
43. attēls. Tabulas Rules aizpildīšana
27
Rīga
Sigulda
Salaspils
Jēkabpils
Jūrmala
Liepāja
Kuldīga
Ventspils
4,5,63 5
2
1,6
3,4
1,2,3,4,5,6
1,2,3
Jelgava1,2,3,4,5,6
2,3 6
Cēsis
5. DEDUKTĪVIE VAICĀJUMI
1. Kā nokļūt no pilsētas “Jēkabpils” līdz pilsētai “Ventspils” ?
Vaicājuma izpildes ilustrācija ir parādīta . attēla, deduktīvais vaicājums ir parādīts .
attēlā.
44. attēls. Vaicājuma ilustrācija
45. attēls. Deduktīvais vaicājums
1.1. Cik daudz variantu, kā var nokļūt no pilsētas Rīgas uz Ventspili?
Vaicājuma izpildes ilustrācija ir parādīta . attēla, deduktīvais vaicājums ir parādīts .
attēlā.
28
Rīga
Sigulda
Salaspils
Jēkabpils
Jūrmala
Liepāja
Kuldīga
Ventspils
4,5,63 5
2
1,6
3,4
1,2,3
Jelgava
2,3 6
Cēsis
Rīga
Sigulda
Salaspils
Jēkabpils
Jūrmala
Liepāja
Kuldīga
Ventspils
215 km91 km
58 km
166 km
119 km 51 km
19 km
124 km
23km
Jelgava
47 km
137 km
Cēsis
39 km
46. attēls. Vaicājuma ilustrācija
47. attēls. Deduktīvais vaicājums
1.2. Kāds ir garākais maršruts no Cēsis līdz Jēkabpils, tā, lai pilsētas neatkārtotos un
nebūtu ciklu?
Vaicājuma izpildei tika izmantots predikāts path ,SELECT konstrukcija ORDER BY
lai sakārtotu ierakstus pēc attālumiem un konstrukcija TOP 1, lai izvadītu tikai pirmo
ierakstu. Vaicājuma izpildes ilustrācija ir parādīta . attēla, deduktīvais vaicājums ir parādīts .
attēlā.
48. attēls. Vaicājuma ilustrācija
29
Rīga
Sigulda
Salaspils
Jēkabpils
Jūrmala
Liepāja
Kuldīga
Ventspils
1,2
2 4
2,3
3,4 1,2,3,4
1,2,3,4
Jelgava
1,4
Cēsis
49. attēls. Deduktīvais vaicājums
1.3. Kādi ir maršruti, ja braucot no Liepājas līdz Siguldai ir jāapmeklē Jūrmala.
Vaicājuma izpildes ilustrācija ir parādīta . attēla, deduktīvais vaicājums ir parādīts .
attēlā. Deduktīvais vaicājums atrod visus ceļus no Liepājas līdz Siguldai ar predikātu path un
tad atlasa maršrutus, kuros ir pilsēta Jūrmala.
50. attēls. Vaicājuma ilustrācija
51. attēls. Deduktīvais vaicājums
30
1.4. Kur un pa kādiem ceļiem var aizbraukt no Rīgas?
Šajā vaicājumā atšķirībā no iepriekšējiem vaicājumiem, otrais predikāta arguments
tika izmantots nevis kā ieejas parametrs, bet kā izejas. Vaicājuma izpildes rezultāts ir
parādīts . attēlā.
52. attēls. Deduktīvais vaicājums
Nav parādīti visi varianti, jo pavisam ir 78 ieraksti.
2. Kāds ir īsākais ceļš starp pilsētām Cēsis un Ventspils ?
Vaicājuma izpildes ilustrācija ir parādīta . attēla, deduktīvais vaicājums ir parādīts .
attēlā.
31
Rīga
Sigulda
Salaspils
Jēkabpils
Jūrmala
Liepāja
Kuldīga
Ventspils
215 km91 km
58 km
166 km
119 km 51 km
19 km
124 km
23km
Jelgava
47 km
137 km
Cēsis
39 km
53. attēls. Vaicājuma ilustrācija
54. attēls. Deduktīvais vaicājums
3. Kādās pilsētās atrodas akvaparks?
Vaicājuma izpildes rezultāts ir parādīts . attēlā. Analoģisko rezultātu var iegūt
izmantojot “parasto” SQL (piemēram, SELECT P.Pilseta FROM Pilsetas P,
Apskates_objekti A WHERE P.Pilsetas_ID=A.Pilsetas_ID AND
A.Objekts='Akvaparks').
55. attēls. Deduktīvais vaicājums
3.1. Kādi apskates objekti atrodas Rīgā?
Vaicājuma izpildes rezultāts ir parādīts . attēlā. Analoģisko rezultātu var iegūt
izmantojot “parasto” SQL (piemēram, SELECT A.Objekts FROM Pilsetas P,
32
Apskates_objekti A WHERE P.Pilsetas_ID=A.Pilsetas_ID AND
P.Pilseta='Rīga').
56. attēls. Deduktīvais vaicājums
3.2. Kurā pilsēta, kas atrodas vistuvāk Rīgai, ir ūdenskritums?
Vaicājuma izpildes rezultāts ir parādīts . attēlā. Sākumā deduktīvajā daļā notiek īsākā
ceļa atrāšana līdz pilsētai, kur atrodas ūdenskritums, tad ar ORDER BY un TOP 1 no visiem
ierakstiem tiek atlasīts tikai viens ieraksts – tuvākā līdz Rīgai pilsēta, kur ir ūdenskritums.
57. attēls. Deduktīvais vaicājums
4. Cik ilgi jābrauc no pilsētas Jēkabpils līdz Cēsīm?
Vaicājuma izpildes rezultāts ir parādīts . attēlā. Vaicājumā pamatdaļā notiek lauka
column_2 transformēšana (pārveidošana) uz skaitli (jo visi tabulārās funkcijas tabulas lauki
ir teksta rindas – nvarchar) un reizināšana ar 60, lai iegūtu minūtes.
33
58. attēls. Deduktīvais vaicājums
Papildus vaicājumi (izmantojot arī SQL konstrukcijas):
4.1. Cik ilgi jābrauc no Liepājas līdz pilsētai, kurā atrodas botāniskais dārzs?
Vaicājuma izpildes rezultāts ir parādīts . attēlā.
59. attēls. Deduktīvais vaicājums
34
SECINĀJUMI
Laboratorijas darba gaitā tika izstrādāts speciālais paplašinājums priekš DBVS
Mircosoft SQL Server 2008. Paplašinājums ļauj lietotājam izpildīt deduktīvos vaicājumus
izmantojot faktus un likumus no tabulām.
Darbs sastāv no piecām nodaļām. Pirmajā nodaļā ir sniegti paskaidrojumi par
paplašinājuma izstrādi. Paplašinājuma izstrādei tika izmantoti brīvi pieejami Prolog
interpretatora CS-Prolog pirmkodi. Nodaļā ir aprakstīts lietotāja funkcijas definēšanas
process valodā C#. Nodaļā ir arī uzskaitītas visas tabulas, kas tika izmantotas paplašinājuma
darbības pārbaudei un uzrakstīti visi vaicājumi šo tabulu izveidošanai.
Otrajā nodaļā ir aprakstīta procedūra, kas tika izmantota tabulu aizpildīšanai ar rīku
BCP. Ir parādīti faili, kas tika izmantoti tabulu aizpildīšanai, un komandas tabulu
aizpildīšanai.
Trešajā nodaļā ir nodefinēti konceptuālie vaicājumu izpildei ar paplašinājuma
palīdzību.
Ceturtajā nodaļā ir parādīti visi pirmkodi valodā Prolog trešajā nodaļā definēto
vaicājumu izpildei. Ir sniegti paskaidrojumi par algoritmu darbības principiem, kā arī
parādīts, ka tika aizpildīta tabula Rules
Piektajā nodaļā ir parādīti deduktīvi vaicājumi un šo vaicājumu izpildes rezultāti.
Sava ķermenī vaicājumi satur gan ceturtajā nodaļā nodefinētu likumus, gan tos predikātus,
kas jau ir iebūvēti CS-Prologā (piemēram, member).
Izstrādātām paplašinājumam ir šādas priekšrocības:
nav redundantā informācija t.i. nav jāglabā tie fakti, ko var izvest (izsecināt)
no citiem faktiem. Piemēram, lai uzglabātu informāciju par visiem
iespējamiem maršrutiem no jebkuras pilsētas līdz jebkurai citai, ar darbā
piedāvātu ceļu karti, būtu jāveido tabula ar 924 ierakstiem (reālajās dzīvēs
situācijās šīs skaitlis būtu vairākas reizes lielāks);
viegli izmantot rekursiju un maksimālais rekursijas dziļums ir lielāks nekā
izmantojot MS SQL Server 2008 glabājamās procedūras, kur rekursijas
dziļums nevar būt lielāks par 32 līmeņiem;
tā iemesla dēļ, ka dati tiek atgriezt tabulārajā struktūrā, izgūto informāciju var
apstrādāt ar SQL konstrukcijām (WHERE, funkcijas un apakšvaicājumi) un
savienot ar datus citām tabulām;
likumu definēšanai jāizmanto Prolog sintakse, kas ievērojami atvieglo likumu
definēšanu.
35
Risinājumam piemīt arī vairāki trūkumi:
zemā ātrdarbība – vaicājumi lēni apstrādājas, jo CS-Prolog ir interpretators un
pirms vaicājuma izpildes notiek faktu un likumu ielādēšana atmiņā. Šī
iemesla dēļ, deduktīvo paplašinājumu ir jāizmanto tikai tad, kad līdzīgo
darbību nav iespējams izpildīt ar parasto SELECT vaicājumu;
atrieztajā tabulā kolonu skaits vienmēr ir pieci, kaut arī mēdz būt gadījumi,
kad ir nepieciešams atgriezt lielākais kolonu skaits (kolonu skaitu var mainīt
funkcijas definējumā, bet to nav iespējams mainīt dinamiski izpildes laikā);
Salīdzinājumā ar Oracle MS SQL Server 2008 ir daži trūkumi. Pirmkārt, funkciju,
procedūru, trigeru definēšanai ir vēlams izmantot ārējās bibliotēkas (t.i. rakstīt tās C# vai
VB.NET valodās), jo šādu funkciju ātrdarbība ir lielāka nekā līdzīgajai konstrukcijai T-SQL
valodā (izņemot gadījumos, kad ir jāveic tikai datu izgūšana), kā arī valoda T-SQL nav tik
elastīga (un nesatur tik pat daudz konstrukciju) kā Oracle PL/SQL. Otrkārt, dažas
konstrukcijās var izveidot izmantojot tikai CLR komponentes, tā, piemēram, agrēgējošo
funkciju un tipu definēšanai (darbā šādas konstrukcijas nav apskatītas) jāizmanto C# vai
VB.NET valoda. Kā arī, salīdzinājumā ar Oracle, MS SQL Server tipi nevar būt kolekcijas
vai masīvi – tie var būt tikai no pamattipiem veidotie saliktie tipi.
Deduktīvās datu bāzes ir ļoti jaudīgs mehānisms, kas ļauj izpildīt sarežģītus
vaicājumus situācijās, kad nav nepieciešamus faktus, tos var iegūt ar izvedumu. Diemžēl, par
mehānisma jaudu ir “jāmaksā” ar ātrdarbību, tāpēc, reālajās dzīves situācijās, datu bāzes
deduktīvo paplašinājumu ir lietderīgi veidot atsevišķajā lietojumserverā (var, piemēram,
izmantot serviss-orientēto arhitektūru), lai datu bāze nebūtu pārslogota ar sarežģītu operāciju
izpildi.
Darba gaitā izdevās nostiprināt lekcijās iegūtas zināšanas un arī iegūt jaunas
zināšanas lasot grāmatas un interneta avotus.
36
PIELIKUMSusing System;using System.Collections.Generic;using System.Collections;using System.Text;using System.Data.SqlClient;using System.Data;using System.Data.SqlTypes;
namespace Prolog{ class SQLProlog { private static PrologEngine engine = new PrologEngine(); // Si funkcija atgriez sarakstu ar atbildem uz uzdoto vaicajumu public ArrayList ExecuteQuery(string query) { StringBuilder queryBuilder = new StringBuilder(); ArrayList list = new ArrayList(); bool result = engine.ExecuteQuery(ref query); while (!engine.Halted) { { string[] row = new string[engine.Variables.Count]; int j = 0; foreach (DictionaryEntry de in engine.Variables) { row[j++] = de.Value.ToString(); } list.Add(row); // pievieno jauno atbildi sarakstam } if (engine.CanBacktrack(false)) { result = engine.More(); } else break; } return list; }
// Si funkcija pievieno faktus no datu bazes public void AssertData() { string connetionstring = "Data Source=WINDOWSXP;Initial Cata-log=SQLPROLOG;Persist Security Info=True;User ID=Dmitry;Password=123"; SqlConnection con = new SqlConnection (connetionstring); con.Open(); SqlConnection tableconnection = new SqlConnection(connetion-string); tableconnection.Open(); SqlCommand com = new SqlCommand("dbo.GetTable"); com.Connection = con; com.CommandType = CommandType.StoredProcedure; com.Parameters.Add(new SqlParameter("@Table", "Facts")); com.Parameters[0].Direction = ParameterDirection.Input; SqlDataReader reader = com.ExecuteReader(); SqlCommand tablecommand = new SqlCommand(); SqlDataReader tablereader; string assertcommand; string tablename; while (reader.Read())
37
{ tablename = reader.GetString(0); tablecommand.CommandType = CommandType.Text; tablecommand.CommandText = "SELECT * FROM "+tablename; tablecommand.Connection = tableconnection; tablereader = tablecommand.ExecuteReader(); string retractcomand = "retractall(" + tablename.ToLower() + "("; for (int i = 0; i < tablereader.FieldCount; i++) { if (i != 0) retractcomand += ","; retractcomand += "_";
} retractcomand += "))."; engine.ExecuteQuery(ref retractcomand); while (tablereader.Read()) { assertcommand = "assert(" + tablename.ToLower() + "("; for (int i = 0; i < tablereader.FieldCount; ++i) { if (i != 0) assertcommand += ","; if (tablereader.GetProviderSpecificFieldType(i).ToString() == "System.Da-ta.SqlTypes.SqlString") { assertcommand += "'" + tablereader.GetString(i) + "'"; } if (tablereader.GetProviderSpecificFieldType(i).ToString() == "System.Da-ta.SqlTypes.SqlInt64") { assertcommand += tablereader.GetInt64(i).ToString() ; } if (i == tablereader.FieldCount - 1) { assertcommand += "))."; engine.ExecuteQuery(ref assertcommand); } } } tablereader.Close(); } reader.Close(); } public void LoadRules() { SqlConnection con = new SqlConnection ("Data Source=WINDOWSXP;Initial Catalog=SQLPROLOG;Persist Security Info=True;User ID=Dmitry;Password=123"); con.Open(); SqlCommand com = new SqlCommand("SELECT * FROM RULES", con); SqlDataReader reader = com.ExecuteReader(); while (reader.Read()) { string pred = reader.GetString(0); string body = reader.GetString(1); string newpred = pred; string predretract = "retractall(" + newpred + ")."; engine.ExecuteQuery(ref predretract);
38
} reader.Close(); reader = com.ExecuteReader(); while (reader.Read()) { string pred = reader.GetString(0); string body = reader.GetString(1); string newpred = pred; if (body.Trim().Length == 0) newpred += ""; else { newpred += ":-" + body; } string assertpred = "assert(" + newpred + ")."; engine.ExecuteQuery(ref assertpred); } } }
}
39