Hlavní navigace

GLib: Relace (2)

Michal Burda 8. 3. 2001

Minule jsme začali výklad o posledním datovém typu knihovny GLib - relacích GRelation. Dnes povídání o nich dokončíme. Ukážeme si ještě pár funkcí, které při práci s relačními tabulkami můžete potřebovat a také obvyklou ukázku použití.

Další práce s GRelation

gboolean g_relation_exists(GRelation *relation, ...);

Tato funkce rozhodne, existuje-li už v relaci relation záznam s předanými prvky ( ...). Počet argumentů za parametrem relation musí být roven počtu sloupců v tabulce. Porovnávání probíhá přímo (tedy na úrovni pointerů), takže např. dvě kopie stejného řetězce nebudou souhlasit.

Funkce vrátí TRUE, pokud se řádek s takovými položkami v relaci nachází.

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

…spočítá počet záznamů v GRelation relation, které mají v políčku field hodnotu key. K úspěšnému provedení této akce je nutné, aby relation měla inicializovanou indexaci pro sloupec field viz g_relation_index(), jinak volání skončí neúspěchem.

Porovnávání neprobíhá přímo (na rozdíl od g_relation_exists()), ale pomocí příslušné funkce  key_compare_func.

void g_relation_print(GRelation *relation);

…vypíše ladicí informace o relaci relation. Ladicí výpis obsahuje výpis všech záznamů v tabulce a také výpis podle klíčů v indexovaných sloupcích.

Vezměme například v úvahu takovouto relační tabulku:

#include <glib.h>

gint main(void)
{
  GRelation *rel;

  rel = g_relation_new(2);
  g_relation_index(rel, 0, g_str_hash, g_str_equal);
  g_relation_index(rel, 1, g_str_hash, g_str_equal);

  g_relation_insert(rel, "Josef Noga", "delnik");
  g_relation_insert(rel, "Petr Mach", "mistr");
  g_relation_insert(rel, "Karel Novak", "delnik");

  g_relation_print(rel);
  g_relation_destroy(rel);
}

Informačním výstupem takto vytvořené relační tabulky bude něco jako (řádky jsem z demonstračních účelů očísloval):

01 – GLib-INFO: *** all tuples (3)
02 – GLib-INFO: [0x804881b,0x8048814]
03 – GLib-INFO: [0x8048826,0x8048814]
04 – GLib-INFO: [0x8048838,0x8048832]

…tuto část budete mít ve výpisech vždy. Řádky 1 – 4 totiž popisují relaci jako celek. Vypíšou se jednoduše všechny záznamy.

Další výpis se uskuteční podle toho, jaké (a kolik) sloupců indexujeme. My jsme za indexované sloupce prohlásili oba dva. Dostaneme tedy ještě takovouto informaci:

05 – GLib-INFO: *** index 0
06 – GLib-INFO: *** key 0x8048838
07 – GLib-INFO: [0x8048838,0x8048832]
08 – GLib-INFO: *** key 0x804881b
09 – GLib-INFO: [0x804881b,0x8048814]
10 – GLib-INFO: *** key 0x8048826
11 – GLib-INFO: [0x8048826,0x8048814]

…tento úsek vypisuje položky podle sloupce 0 (první sloupec). Vždy se vypíše jeden prvek ze zpracovávaného sloupce (např. řádek 06) a po něm všechny záznamy, které tuto hodnotu obsahují (07).

Podobné údaje získáte i o druhém indexovaném sloupci:

12 – GLib-INFO: *** index 1
13 – GLib-INFO: *** key 0x8048814
14 – GLib-INFO: [0x804881b,0x8048814]
15 – GLib-INFO: [0x8048826,0x8048814]
16 – GLib-INFO: *** key 0x8048832
17 – GLib-INFO: [0x8048838,0x8048832]

Jak jste asi poznali, vypisují se vždy adresy na data (obsahy pointerů). Např. hodnota 0x8048814 bude patrně adresa na konstantní řetězec "delnik"  atd.

Příklad:

#include <glib.h>

#define REL_JMENO  0
#define REL_FUNKCE 1


/* vypise vsechny pracovniky s funkci funkce */
void vypis_podle_funkce(GRelation *rel, gchar *funkce) {
  GTuples *vysledek;
  gint x;

  vysledek = g_relation_select(rel, funkce, REL_FUNKCE);

  printf("Pracovnici s funkci %s:\n", funkce);

  for (x = 0; x < vysledek->len; x++) {
    printf("%s\n", g_tuples_index(vysledek, x, REL_JMENO));
  }

  g_tuples_destroy(vysledek);
  printf("\n");
}


/* hlavni program */
gint main(void)
{
  GRelation *rel;

  /* vytvoreni nove relacni tabulky */
  rel = g_relation_new(2);
   
  /* indexovanym bude druhy sloupec */
  g_relation_index(rel, REL_FUNKCE, 
      g_str_hash, g_str_equal);

  /* naplneni tabulky hodnotami */
  g_relation_insert(rel, "Josef Noga", "delnik");
  g_relation_insert(rel, "Petr Mach", "mistr");
  g_relation_insert(rel, "Karel Novak", "delnik");
  g_relation_insert(rel, "Pavel Maly", "manazer");
  g_relation_insert(rel, "Karel Vlach", "mistr");
  g_relation_insert(rel, "Jana Zelena", "delnik");

  /* vypis podle pracovni funkce */
  vypis_podle_funkce(rel, "delnik");
  vypis_podle_funkce(rel, "manazer");
  vypis_podle_funkce(rel, "mistr");

  /* uvolneni relacni tabulky z pameti */
  g_relation_destroy(rel);
}

Na tomto jednoduchém příkladu můžete vidět proces vyhledávání v relaci. V programu se nejprve vytvoří relační tabulka rel. Poté se ihned inicializuje indexace druhého sloupce, protože podle něj budeme později vyhledávat. Tabulka se naplní několika údaji – do prvního sloupce se ukládají jména pracovníků a do druhého funkce, které v zaměstnání plní.

Funkce vypis_podle_funkce() provádí samotné hledání pomocí GTuples. Nesmíme zapomínat výsledek hledání nakonec dealokovat voláním  g_tuples_destroy()!

Nakonec se celá relační tabulka uvolní z paměti. Jelikož v ní byla jen statická data, nemusíme si s nimi lámat hlavu. Jinak by samozřejmě bylo třeba data ručně dealokovat.

Závěr

Omezení na pouhé dva sloupce v každé tabulce je možná dost svazující, než aby se GRelation s daly výhodně použít v praxi. Patrně se na relacích bude ještě dělat (doufám!), protože jde jistě o zajímavý a neméně užitečný datový typ. Snad se mi podařilo vysvětlit dnešní stav věcí a to, v čem GRelation využijete, už ponechám na vás.

Jako alternativu k relacím knihovny GLib, po které jistě sáhnete při tvorbě větších databází, je přímé napojení na nějaký databázový stroj – třeba MySQL. Kolosu jako MySQL GLibovské GRelation vůbec nemohou (a jistě ani nechtějí) konkurovat. Nicméně i tak se pro ně jistě někde najde uplatnění.

A to je moji milí o datových typech, které knihovna GLib poskytuje, úplně vše. Ale my se ještě neloučíme. Čeká nás ještě dlouhá a strastiplná cesta přes mnoho dalších nástrojů, které GLib nabízí a jistě by bylo škoda se o nich nezmínit. Tak zase za týden – nashledanou!

Našli jste v článku chybu?
Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

120na80.cz: Bojíte se encefalitidy?

Bojíte se encefalitidy?

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně

Vitalia.cz: Říká amoleta - a myslí palačinka

Říká amoleta - a myslí palačinka

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

Vitalia.cz: Tesco: Chudá rodina si koupí levné polské kuře

Tesco: Chudá rodina si koupí levné polské kuře

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

Podnikatel.cz: EET zvládneme, budou horší zákony

EET zvládneme, budou horší zákony

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

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

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

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

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

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

Sony KD-55XD8005 s Android 6.0

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: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Lupa.cz: Není sleva jako sleva. Jak obchodům nenaletět?

Není sleva jako sleva. Jak obchodům nenaletět?