Hlavní navigace

GLib: Relace

Michal Burda

Posledním datovým typem, který si v tomto seriálu probereme, budou jednoduché relační tabulky GRelation.

Relace knihovny GLib jsou množiny neuspořádaných záznamů. Můžete si je představovat jako jakési tabulky s několika řádky a sloupci. Řádky jsou jednotlivé záznamy a sloupce příslušné atributy (položky, části záznamů).

Jak již bylo řečeno, záznamy nejsou v relační tabulce nijak uspořádány. Nelze se proto na ně odkazovat konkrétními indexy, jako například na prvky pole. Přístup k datům organizovaným do relací se provádí úplně jiným způsobem, ale o tom až za chvilku. Vnitřně se záznamy ukládají do hash tabulek, takže přístup k nim je velice rychlý.

Relační tabulka je rozdělena do sloupců, takže každý řádek má nutně stejné množství prvků. Z obecného hlediska není počet sloupců omezen. Skutečnost je ale poněkud jiná: relace knihovny GLib jsou stále ještě implementovány tak, že umožňují pracovat jen s tabulkami tvořenými právě dvěma sloupci. Doufejme, že v příštích verzích bude toto omezení odstraněno.

Vytvoření nové GRelation

Relační tabulka je reprezentována neveřejnou strukturou:

struct GRelation; 

Novou relaci vytvoříte voláním funkce:

GRelation* g_relation_new(gint fields); 

…, kde fields je počet sloupců tabulky (počet prvků na řádku). Jak už jsem zmínil, nyní musí být fields rovno 2.

Ihned za vytvořením relační tabulky by mělo následovat jedno nebo několik volání funkce:

void g_relation_index(GRelation *relation,
                      gint field,
                      GHashFunc hash_func,
                      GCompareFunc key_compare_func);

Touto funkcí se inicializuje systém indexování podle sloupce field. g_relation_in­dex() připraví GRelation relation na to, že v budoucnu budete chtít v tabulce vyhledávat záznamy podle jeho hodnot.

field 

Jako argument hash_func musí být předána funkce, která z hodnot ve sloupci field vyrobí tzv. hash-hodnotu (viz hash tabulky). A kde je hash_func, dá se čekat že bude i nějaká key_compare_func. Také ona musí pracovat s prvky ve sloupci field a jejím úkolem bude rozhodovat, jsou-li dvě položky shodné (a pak musí vrátit TRUE) nebo nikoliv ( FALSE). Za tyto argumenty můžete použít i předpřipravené funkce g_str_hash(), g_str_equal(), g_direct_hash(), g_direct_equal() nebo g_int_hash() a g_int_equal() (opět viz hash-tabulky).

Funkce g_relation_in­dex() musí být volána před jakýmkoliv přidáváním prvků do tabulky!

Počet indexovaných sloupců není nikterak omezen, z praktického hlediska je ovšem vhodné, aby byl takto indexován alespoň jeden.

Vkládání záznamů do GRelation

void g_relation_insert(GRelation *relation, ...); 

…vloží do GRelation relation nový záznam. Počet parametrů za pointerem relation musí odpovídat počtu sloupců v tabulce – jsou to vkládaná políčka, která se uloží do patřičných sloupců a dohromady vytvoří jednu datovou položku v relaci.

Vyhledávání záznamů v GRelation

GTuples* g_relation_select(GRelation *relation,
                           gconstpointer key,
                           gint field);

Funkce g_relation_select() je nástrojem pro vyhledávání záznamů v relacích. V relační tabulce relation vyhledá všechny řádky, které ve sloupci field mají hodnotu key. Sloupec field musí být tzv. „indexovaným“ sloupcem, tedy musí být na něj ihned po vytvoření relace zavoláno funkce g_relation_in­dex(). Porovnávání hodnoty key se záznamy v tabulce se provádí pomocí funkce key_compare_func (viz g_relation_in­dex()).

Jak můžete vidět z funkčního prototypu, výsledkem je nový typ, o kterém ještě nebyla ani zmínka – GTuples. Je to struktura, jejíž prvky (až na jeden) jsou neveřejné:

typedef struct {
  guint len;
} GTuples;

Úkolem struktury GTuples je uchovávat výsledek hledání, tedy jakýsi souhrn hledacímu kritériu odpovídajících záznamů relace. Přímo ze struktury lze přímo vyčíst jen počet výsledných řádků – podává o něm informaci položka  len.

Abyste se dostali k samotným záznamům tvořících výstup prohledávání, musíte k tomu použít speciální funkci:

gpointer g_tuples_index(GTuples *tuples,
                        gint index,
                        gint field);
g_tuples_index() 

Vždy, když s GTuples  přestanete pracovat, je nutné je dealokovat speciální funkcí:

void g_tuples_destroy(GTuples *tuples); 

Odstraňování záznamů z GRelation

Také pro mazání záznamů máte pochopitelně k dispozici nějaký nástroj. Je jím funkce:

gint g_relation_delete(GRelation *relation,
                       gconstpointer key,
                       gint field);
g_relation_delete() 

Dealokace GRelation

Stejně tak, ukončíte-li práci s celou relační tabulkou GRelation, sluší se podle dobrých mravů programátora jí obsazenou paměť vrátit operačnímu systému. I GRelation  pro to mají speciální funkci:

void g_relation_destroy(GRelation *relation); 

Dokončení příště.

Našli jste v článku chybu?