Hlavní navigace

GLib: Relace (2)

8. 3. 2001
Doba čtení: 4 minuty

Sdílet

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.

CS24_early

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!

Byl pro vás článek přínosný?

Autor článku

Michal Burda vystudoval informatiku a aplikovanou matematiku a nyní pracuje na Ostravské univerzitě jako odborný asistent. Zajímá se o data mining, Javu a Linux.