Kurz6 - Kapitola7

17. června 2007 v 10:38 | http://www.sweb.cz/kurz_evt/ |  Programování pro WinCE

8.7 Vytvoření databáze

Vrátíme se zpět k našemu původnímu projektu PhoNumbs. Knihovnu, kterou budeme používat, máme už vytvořenou a uloženou i s hlavičkovým souborem sqlite3.h v adresáři PhoNumbs.
Zkopírování souborů do adresáře však nestačí k tomu, abychom s knihovnou mohli pracovat. Do souboru PhoNumbsDlg.cpp umístíme dvě hlavičky:
#include "sqlite3.h"
#include "atlconv.h"
Druhá hlavička nepatří ke knihovně, ale umožní nám v programu používat konverzní makra z UNICODE na 8bitové znaky. Ve funkci, kde budeme používat konverzní makra pak musíme na začátku vložit
   USES_CONVERSION;
Vlastní knihovnu si "zaregistrujeme" do projektu v Project -> Settings... na kartě Link v okénku Object/library modules napíšeme jméno vytvořené knihovny SQLite322.lib.
Nyní již můžeme knihovnu použít. Nejprve přepíšeme obsah funkce FillListView
int radek;
static int callback(void *pListView, int argc, char **argv, char **azColName)
{
USES_CONVERSION;
CListView* pView;

pView=(CListView*)pListView;
pView->GetListCtrl().InsertItem(radek,A2W(argv[0]));
pView->GetListCtrl().SetItemText(radek,1,A2W(argv[1]));
pView->GetListCtrl().SetItemText(radek,2,A2W(argv[2]));

radek++;
return 0;
}

void CPhoNumbsDlg::FillListView()
{
USES_CONVERSION;

CFile dbFile; // Soubor pro zjisteni, zda databaze existuje
sqlite3 *db;
CString pom; // ... a pomocne promenne ...
int rc;
char *zErrMsg = NULL;
// Ukazatel na pohled listu a vycisteni pohledu
CListView* pView=(CListView*)GetDlgItem(IDC_LIST1);
pView->GetListCtrl().DeleteAllItems();
radek=0;

// Podle prepnute karty nachystam prikaz SELECT pro vyber z databaze
pom=(_T("SELECT * FROM TelNumbers WHERE "));
switch(m_karta) {
case 0: pom+=(_T("Surname >= 'A' AND Surname < 'D'")); break;
case 1: pom+=(_T("Surname >= 'D' AND Surname < 'G'")); break;
case 2: pom+=(_T("Surname >= 'G' AND Surname < 'J'")); break;
case 3: pom+=(_T("Surname >= 'J' AND Surname < 'M'")); break;
case 4: pom+=(_T("Surname >= 'M' AND Surname < 'P'")); break;
case 5: pom+=(_T("Surname >= 'P' AND Surname < 'T'")); break;
case 6: pom+=(_T("Surname >= 'T' AND Surname < 'W'")); break;
case 7: pom+=(_T("Surname >= 'W'")); break;
}
// Z databaze vyberu polozky prislusne kategorie
switch (m_kategorie) {
case 1: pom+=_T(" AND Category = 1 ORDER BY Surname"); break;
case 2: pom+=_T(" AND Category = 2 ORDER BY Surname"); break;
case 3: pom+=_T(" AND Category > 0 ORDER BY Surname"); break;
default: pom+=_T(" AND Category = 0 ORDER BY Surname");
}

if(dbFile.Open(_T("TelNumbs.tnb"),CFile::modeRead)) {
dbFile.Close();
// Databaze existuje, muzu s ni pracovat
rc = sqlite3_open("TelNumbs.tnb", &db);
if( rc ){
MessageBox(_T("Can't open database:"));
sqlite3_close(db);
exit(1);
}
// Vyjmu z databaze recordset s polozkami ...
rc = sqlite3_exec(db, W2A(pom), callback, pView, &zErrMsg);
if( rc!=SQLITE_OK ){
MessageBox(_T("SQL SELECT Error!"));
sqlite3_free(zErrMsg);
}
}
else {
// Pokud databazi neobjevim, tak si vytvorim novou
rc = sqlite3_open("TelNumbs.tnb", &db);
if( rc ){
MessageBox(_T("Can't open database:"));
sqlite3_close(db);
exit(1);
}
rc = sqlite3_exec(db, "CREATE TABLE TelNumbers (Surname TEXT, Name TEXT, Number TEXT, Category INTEGER)", NULL, 0, &zErrMsg);
if( rc!=SQLITE_OK ){
MessageBox(_T("Table creating error!"));
sqlite3_free(zErrMsg);
}
}

// Na zaver databazi zavru
sqlite3_close(db);

}
Pomocí dvou řetězcových proměnných nejprve vytvoříme SQL příkaz podle nastavené kategorie a stránky např.:
SELECT * FROM TelNumbers WHERE Surname >= 'G' AND Surname < 'J' AND Category = 2 ORDER BY Surname
Tento příkaz můžeme databázi vydat pouze, pokud existuje a podařilo se ji otevřít. Výstupem je určitý počet řádků, který vyhovuje zadaným podmínkám. Pro každý z řádků SQLite zavolá uživatelskou "callback" funkci, která má předepsaný tvar a je jedním z parametrů funkce sqlite3_exec. V našem případě callback funkce pouze plní ListView. Pomocný parametr této funkce jsem využil pro předání ukazatele na ListView.
Abych si udržel přehled, který řádek bude v ListView vkládán, použil jsem globální proměnnou radek jako počítadlo.
Pokud soubor s databází neexistuje, pokusím se ji vytvořit a příkazem "CREATE TABLE" v této databázi vytvořím tabulku se 4 sloupci (3 textové a 1 číselný). V tomto případě, kdy není výstup, není vyžadována callback funkce.
V obou dvou funkcích přehazuji řetězcová data podle potřeby mezi UNICODE a 8bity pomocí maker W2A a A2W. U obou funkcí jsem proto v jejich úvodu použil makro USES_CONVERSION. Důvodem, proč jsem zvolil ukládání dat v 8bitové formě, je to, že databáze je pak snadno přenositelná i do Windows 98 apod.

Co bychom si měli z této lekce zapamatovat?

  • Pro konverzi mezi různými typy řetězců je možné použít připravená makra.
 

Buď první, kdo ohodnotí tento článek.

Nový komentář

Přihlásit se
  Ještě nemáte vlastní web? Můžete si jej zdarma založit na Blog.cz.