Hlavní navigace

Nový pohľad na tradičný relačný model

Július Chrobák 9. 6. 2011

Relačný model je dobre známym pojmom v oblasti softvérového inžinierstva. Tento dvojdielny článok vám predstaví projekt Bandicoot, ktorý implementuje relačný model netradičným spôsobom. Zároveň si ukážeme, ako vyvíjať softvér pomocou relačného modelu, a to bez použitia tradičných relačných databáz či jazyka SQL.

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.

Našli jste v článku chybu?

9. 6. 2011 12:05

Ano, přesně na těchto místech jsem si také říkal "WTF?!"

To že dnešní implementace RDBMS vesměs nejsou z pohledu relační algebry 100% korektní není sporu (opakovaně to konstatoval např. i E. F. Codd). Možná by nebylo od věci vyjmenovat hlavní body definice relačního modelu, porušované dnešními RDBMS a případně demonstrovat že v tomhle udělátku to tak není. Případně demonstrovat jaké to má důsledky - jako důvody těch porušení jsou totiž většinou uváděny výkonnostní důvody.

Každopádně vyč…

9. 6. 2011 1:09

VM (neregistrovaný)

Ach jo, to jsou zase moudra:
- SQL neumí odděleně definovat relace a proměnné
- SQL nelze použít jako plnohodnotný jazyk pro implementaci aplikační logiky proto že do proměnné nenarve celou relaci najednou
- v SQL nelze určit pořadí vykonávání příkazů
- optimalizátor není potřeba, má-li vývojář plnou kontrolu nad výpočtem

Z článku jsem se dozvěděl, že Bandicot umí snáze než SQL zapsat rozdíl relací, ale jinak že má své možnosti silně omezené, například spojování tabulek že lze pouze jediným způ…





Podnikatel.cz: Hledáte investora? Neunáhlete se

Hledáte investora? Neunáhlete se

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Podnikatel.cz: Alza.cz má StreetShop. Mall.cz více výdejních míst

Alza.cz má StreetShop. Mall.cz více výdejních míst

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Vitalia.cz: Znáte „černý detox“? Ani to nezkoušejte

Znáte „černý detox“? Ani to nezkoušejte

Měšec.cz: Air Bank zruší TOP3 garanci a zdražuje kurzy

Air Bank zruší TOP3 garanci a zdražuje kurzy

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

120na80.cz: Na ucho teplý, nebo studený obklad?

Na ucho teplý, nebo studený obklad?

Podnikatel.cz: Chtějte údaje k dani z nemovitostí do mailu

Chtějte údaje k dani z nemovitostí do mailu

Podnikatel.cz: Babiše přesvědčila 89letá podnikatelka?!

Babiše přesvědčila 89letá podnikatelka?!

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

DigiZone.cz: Sat novinky: slovenská TV8 HD i ruský NTV Mir

Sat novinky: slovenská TV8 HD i ruský NTV Mir

120na80.cz: Horní cesty dýchací. Zkuste fytofarmaka

Horní cesty dýchací. Zkuste fytofarmaka

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

120na80.cz: Boreliózu nelze žádným testem prokázat

Boreliózu nelze žádným testem prokázat

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Vitalia.cz: Manželka je bio, ale na sex moc není

Manželka je bio, ale na sex moc není

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?