Jako bibliotekę obsługującą bazę danych wybrałem sobie Sqlite3. Jest dość nieskomplikowana i nie trzeba stawiać żadnych serwerów SQL czy coś takiego. Instaluje się ją poleceniem:
sudo apt-get install libsqlite3-0 libsqlite3-dev
Bardzo prawdopodobne, że libsqlite3-0 będzie już w systemie gdyż korzysta z niej na przykład Firefox.
Teraz należy stworzyć nowy projekt, dodać do linkera /usr/lib/libsqlite3.so i napisać trochę kodu:
/*
* File: main.cpp
* Author: daniel
*
* Created on 14 wrzesień 2009, 22:24
*/
#include <stdlib.h>
#include <sqlite3.h>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using std::cout;
using std::endl;
/*
*
*/
//pokazuje wiadomość błędu jeśli istnieje, a jeśli nie to wartość kodu
void handleReturnCode(int returnCode, char* ErrorMsg = NULL) {
if (returnCode != SQLITE_OK) {
if (ErrorMsg != NULL) {
std::cout << ErrorMsg << std::endl;
sqlite3_free(ErrorMsg);
} else {
std::cout << "Return code: " << returnCode << std::endl;
}
}
}
//struktura przechowująca dane o osobie
struct sOsoba {
std::string imie;
std::string nazwisko;
int rokUrodzenia;
sOsoba(const char* p_imie, const char* p_nazwisko, const int p_rokUrodzenia) {
imie = p_imie;
nazwisko = p_nazwisko;
rokUrodzenia = p_rokUrodzenia;
}
};
int main(int argc, char** argv) {
sqlite3* db;
int returnCode;
cout << "Otwieranie bazy danych: " << endl;
returnCode = sqlite3_open("test2.db", &db);
if (returnCode != 0) std::cout << returnCode << std::endl;
char* ErrorMsg;
cout << "Usunięcie tabeli tab" << endl;
returnCode = sqlite3_exec(db, "drop table if exists tab", NULL, NULL, &ErrorMsg);
handleReturnCode(returnCode, ErrorMsg);
cout << "Utworzenie tabeli tab" << endl;
returnCode = sqlite3_exec(db,
"create table tab (imie string, nazwisko string,
rokUrodzenia integer);",
NULL, NULL, &ErrorMsg);
handleReturnCode(returnCode, ErrorMsg);
cout << "Utworzenie listy osob" << endl;
std::vector<sOsoba> listaOsob;
listaOsob.push_back(sOsoba("Donald", "Tusk", 1957));
listaOsob.push_back(sOsoba("Lech", "Kaczyński", 1949));
listaOsob.push_back(sOsoba("Jarosław", "Kaczyński", 1949));
listaOsob.push_back(sOsoba("Grzegorz", "Napieralski", 1974));
listaOsob.push_back(sOsoba("Waldemar", "Pawlak", 1959));
listaOsob.push_back(sOsoba("Grzegorz", "Schetyna", 1963));
//Dodawanie kolejnych nazwisk
std::vector<sOsoba>::iterator it = listaOsob.begin();
while (it != listaOsob.end()) {
cout << "Dodawanie " << it->imie<< " " << it->nazwisko << endl;
std::stringstream query;
query << "insert into tab values (\""
<< it->imie
<<"\", \""
<< it->nazwisko
<< "\", "
<< it->rokUrodzenia <<");";
returnCode = sqlite3_exec(db, query.str().c_str(), NULL, NULL, &ErrorMsg);
handleReturnCode(returnCode, ErrorMsg);
it++;
}
char** result;
int nRows, nCols;
//zapytanie o polityków którzy urodzili się po 1960
sqlite3_get_table(db,
"select nazwisko, rokUrodzenia
from tab
where rokUrodzenia > 1960
order by rokUrodzenia asc",
&result, &nRows, &nCols, &ErrorMsg);
cout << "Result: [" << nRows << ", " << nCols << "]" << endl;
//zerowy wiersz to nagłówki tabeli, a reszta to wyniki, więc rzędów jest nRows + 1
for (int i = 0; i <= nRows; i++) {
for (int j = 0; j < nCols; j++) {
cout << result[i * nCols + j] << "\t";
if (j > 0 && i>0) {
//dla sprawdzenia czy da się łatwo skonwertować liczbę
int rok = atoi(result[i * nCols + j]);
cout << "\t skonwertowany rok: " << rok;
}
}
cout << endl;
}
//zwalnianie pamięci przydzielonej dla tabeli
sqlite3_free_table(result);
cout << "Zamykanie bazy danych" << endl;
sqlite3_close(db);
//wywołanie polecenia systemowego eksportującego tabelę tab do pliku csv
system("sqlite3 -csv test2.db \"select * from tab;\" > wyjscie.csv");
cout << endl;
//wyświetlenie zawartości pliku csv w konsoli
system("cat wyjscie.csv");
return (EXIT_SUCCESS);
}