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
49
Embed
Web view1.1.Paplašinājuma izstrāde MS Visual Studio vidē5. ... valodu Prolog, funkcionālo valodu – LISP, datu bāzes paplašinājumu – DATALOG utt.).
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Rīgas Tehniskā universitāte
DATORZINĀTNES UN INFORMĀCIJAS TEHNOLOĢIJAS FAKULTĀTE
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.1. TABULU DATI............................................................................................................172.2. DATU IEVADE AR RĪKU BCP......................................................................................182.3. FAKTU IZGŪŠANA.....................................................................................................20
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
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ā.
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ņā)
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);