Základné pojmy
Skôr než sa pustíme do praktických ukážok, zhrnieme si základné pojmy modelu a vlastnosti systému Bandicoot. Relačný model a algebra sú tu s nami už od roku 1969. Ide o komplexný matematický model, ale pre účely tohto článku predstavíme len nasledujúce pojmy: Relácia, Relačná premenná, Relačná algebra a operácia priradenia.
Základom modelu je dátový typ Relácia. Je to v podstate štruktúra, ktorá sa skladá z atribútov, kde každý atribút má svoje vlastné meno a dátový typ.
Príklad: relácia Kniha s atribútmi Autor (reťazec znakov) a Rok vydania (celočíselná hodnota).
Model teda definuje Reláciu ako dátový typ. Okrem toho definuje aj relačné premenné. Každá takáto premenná je typu konkrétnej Relácie. Obsah premennej je vždy množina záznamov s rovnakou štruktúrou.
Príklad: premenná Moje knihy je typu Kniha (táto premenná reprezentuje množinu všetkých mojich kníh)
Ďalším dôležitým pojmom je Relačná algebra. Tá definuje základnú množinu operácií pre manipuláciu s relačnými premennými. Tieto operácie sú definované tak, aby tvorili uzavretý systém. Pomocou nich je možné meniť existujúce relácie ľubovoľným spôsobom a tým vytvárať nové relácie. Pre ilustráciu odporúčam pozrieť si vizualizáciu týchto operácií.
Okrem definovania nových relácii, deklarácie relačných premenných a používania operátorov relačnej algebry, máme k dispozícii aj koncept priradenia novej hodnoty do relačnej premennej. V princípe je to to isté, ako príkaz priradenia v klasickom programovaní.
Bandicoot
Bandicoot, začínajúci open-source projekt kompletne napísaný v jazyku C, je programovací systém s novým jazykom založeným na relačnej algebre, zabudovanou persistenciou a vlastným “run-time” prostredím. Programovací jazyk je navrhnutý takým spôsobom, aby bol použiteľný nie len ako dotazovací jazyk, ale aj ako jazyk na programovanie aplikačnej logiky.
V tomot dieli si predstavíme iba jazyk systému Bandicoot. Na ostatné vlastnosti, ako funkcie, HTTP rozhranie, persistenciu a transakcie, sa detailne pozrieme v druhom dieli článku.
Nový programovací jazyk
Nový pohľad na relačný model začína novým programovacím jazykom. V súčasnosti je SQL všeobecne uznávaným jazykom „relačných“ databáz, aj keď porušuje základné princípy relačného modelu. Tejto tematike sa podrobnejšie venuje kniha „Database in Depth“, ktorej autorom je Chris Date. Nasledujúce odstavce popisujú syntax jazyka Bandicoot a porovnávajú ho s SQL.
Základnými prvkami sú: relácie, relačné premenné a funkcie.
Príklad: definícia relácie Kniha, jednej premennej a jednoduchej funkcie
rel Kniha {
titul: string,
autor: string,
rok: int,
pocetStran: int,
pocetSlov: int,
}
knihy: Kniha;
fn Knihy(): Kniha
{
return knihy;
}
Tento príklad nie je možné prepísať do SQL, ktorý neposkytuje koncept oddeleného definovania relácie a premenných. Jediný spôsob ako niečo podobné zapísať je použitie príkazu na vytvorenie tabuľky.
create table Kniha (
titul character(30),
autor character(30),
rok integer,
pocetStran integer,
pocetSlov integer
);
Neprítomnosť relačných premenných v SQL má za následok niektoré zásadné nevýhody tohto jazyka a znemožňuje jeho použitie ako plnohodnotného progamovacieho jazyka pre implementáciu aplikačnej logiky. Tradičné relačné databázy to obchádzajú implementáciou procedurálnych jazykov (Oracle PL/SQL, Sybase Transact SQL, PostgreSQL PL/pgSQL, atď.), ktoré už ale neposkytujú vysokú abstrakciu relačnej algebry.
Bandicoot implementuje operátory relačnej algebry pre manipuláciu s premennými. V nasledujúcich odstavcoch si ukážeme každý operátor samostatne a porovnáme si ho s implementáciou v SQL. Pre účely týchto príkladov si definujeme nasledovné premenné.
archiv: Kniha; # nová premenná rovnakého typu ako "knihy"
rel Predajca {
meno: string,
# titul a cena knihy
titul: string,
cena: real,
}
predajcovia: Predajca;
Select
Operácia na filtrovanie záznamov z premennej pomocou podmienky.
Príklad: výber kníh s rokom vydania vyšším než 1990
Bandicoot: knihy select(rok > 1990);
SQL: select * from knihy where rok > 1990;
Project
Operácia na zmenu relácie definovaním atribútov, ktoré sa majú zachovať vo výsledku.
Príklad: výber autorov v rámci kníh
Bandicoot: knihy project(autor);
SQL: select distinct autor from knihy;
Extend
Operácia na pridávanie nových atribútov, ktorých hodnota je vypočítaná z hodnôt ostatných atribútov v relácií.
Príklad: výpočet počtu slov na stránku
Banicoot: knihy extend(slovNaStranku = real(pocetSlov) / real(pocetStran));
SQL: select k.*, pocetSlov / pocetStran as slovNaStranku from knihy k;
Join
Operácia na spojenie dvoch relačných premenných. Výsledná relácia má atribúty obidvoch vstupných premenných a záznamy sa spájajú na atribútoch rovnakého názvu a typu.
Príklad: spojenie predajcov a kníh cez atribút „titul“
Banicoot: knihy * predajcovia;
SQL: select * from knihy natural join predajcovia;
Union
Operácia na sčítanie dvoch premenných rovnakého typu. Vo výsledku sú všetky záznamy zo vstupných premenných.
Príklad: sčítanie kníh a archívu
Banicoot: knihy + archiv;
SQL: select * from knihy union select * from archiv;
Minus
Operácia na odpočítanie obsahu jednej premennej od obsahu druhej premennej.
Príklad: vyňatie kníh, ktoré sú aspoň u jedného predajcu
Banicoot: knihy - predajcovia;
SQL: select * from knihy k
where not exists (select 1
from predajcovia p
where p.titul = k.titul);
Summary
Operácia na sumárne výpočty jednej premennej nad druhou premennou.
Príklad: výpočet priemernej ceny knihy u predajcov
Banicoot: (predajcovia, knihy) summary(priemer = avg(cena, 0.0));
SQL: -- pre jednoduchosť použijeme funkciu nvl() z Oracle
select k.titul, k.autor, k.rok, k.pocetStran,
nvl(avg(p.cena), 0.0) as priemer
from knihy k
left outer join predajcovia p on (a.titul = k.titul)
group by k.titul, k.autor, k.rok, k.pocetStran;
Priradenie
Samostatnou kapitolou je priradenie novej hodnoty do relačnej premennej. Koncept priradenia v Bandicoote je identický s tradičným programovaním. SQL namiesto toho poskytuje príkazy na pridanie (insert), vymazanie (delete) a zmenu (update) záznamov priamo v tabuľke.
Príklad: priradenie obsahu jednej premennej do druhej premennej
Bandicoot: archiv = knihy;
SQL: delete from archiv;
insert into archiv select * from archiv;
Príklad: pridanie a vymazanie záznamov
Banicoot: archiv = archiv + knihy;
archiv = archiv - knihy;
SQL: insert into archiv
select * from knihy minus select * from archiv;
delete from archiv a
where exists (select 1
from knihy k
where a.titul = k.titul);
Programovací jazyk Bandicoot umožňuje použiť viacero operátorov v jednom príkaze. Podobne je to aj v SQL. Zásadným rozdielom je však to, že v SQL nie je možné určiť poradie vykonávania týchto príkazov. V prípade Bandicootu sa príkazy vykonávajú podľa jednoznačne určených pravidiel. Výhodou je, že vývojár má plnú moc nad tým, ako vykonať výpočet. Preto optimalizátor, ako ho poznáme z tradičných relačných databáz, nie je potrebný.
Príklad: výpočet priemernej ceny stránky na knihu u rôznych predajcov
Bandicoot: (predajcovia * knihy)
extend(cenaStranky = cena / real(pocetStran))
project(titul, meno, cenaStranky);
SQL: select titul, meno, cenaStranky
from (select *, cena / pocetStran as cenaStranky
from predajcovia natural join knihy);
Záver
Bandicoot umožňuje používanie relačného modelu netradičným a jednoduchým spôsobom. Snaží sa poskytnúť softvérovým inžinierom jeho potenciál v plne miere. Druhý diel článku popíše zvyšné vlastnosti systému ako funkcie, globálne a lokálne premenné, presistenciu, transakcie a HTTP rozhranie. Zároveň poskytne návod, ako vytvoriť jednoduchú webovú aplikáciu v Bandicoote, ktorej používateľské rozhranie je napísané v jazyku JavaScript.