hk_classes - dostęp do baz danych w C++

Wykorzystanie klas hk_classes do obsługi baz danych (MySQL, PostgreSQL, SQlite, ODBC) z poziomu kodu C++

Ta biblioteka jest już raczej porzucona i nie należy jej stosować, jako że może nie współpracować z najnowszymi wersjami GCC
hk_classes to biblioteka C++ służąca do łączenia się z bazami danych (MySQL, PostgreSQL, SQlite, ODBC i inne) - główna zaleta - dotyczy wielu baz danych a nie tylko jednej... strona projektu.

hk_classes mogą działać niejako w dwóch trybach - interaktywnym i pasywnym. Ten pierwszy pojawi się wtedy jeżeli nie określimy typu bazy danych ani danych połączenia - wtedy program poprosi o wprowadzenie odpowiednich danych. Oto najprostszy program w "wersji" interaktywnej:
#define HAVE_SSTREAM 1
#include <hk_classes.h>
#include <iostream>
int main()
	{
	hk_drivermanager* mydrivermanager = new hk_drivermanager();
	if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
	hk_connection* myconnection = mydrivermanager->new_connection();
	if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
	myconnection->connect();
	delete mydrivermanager;
	}
Kompilacja: musisz sprawdzić gdzie dokładnie znajdują się pliki hk_classes. Dla archa i innych dystrybucji instalujących wszystko z --prefix=/usr polecenie powinno wyglądać mniejwięcej tak:
g++ -o plik_wynikowy plik_zrodlowy.cpp -ldl -lhk_classes -L/usr/lib/hk_classes/ -I/usr/include/hk_classes/
Notka: jeżeli po udanej kompilacji program nie uruchamia się z powodu braku pliku libhk_classes.so.8 to trzeba skopiować albo lepiej zsymlinkować pliki z /usr/lib/hk_classes/ do /usr/lib/ (ln -sf /usr/lib/hk_classes/* /usr/lib/) albo poprawić coś w ścieżkach do bibliotek :P Po kompilacji i nadaniu praw wykonywalności (chmod 755 plik) wykonanie pliku w konsoli powinno dać generalnie taki efekt:
===========================================

The following database drivers were found:
===========================================
(1) mdb
(2) mysql
(3) odbc
(4) postgres
(5) sqlite3

(6) Select directory
===========================================

Please give me the following information:
=========================================
Host: localhost
User: piotr
Database name: test
Password (will not be displayed):
TCP Port: 5432
Najpierw wybieramy typ bazy danych a potem się z nią łączymy. Jeżeli program skończy działanie bez żadnych komunikatów to oznacza to iż połączenie zakończyło się sukcesem. Dostępne sterowniki znajdziemy w /usr/lib/hk_classes/drivers/.

Określenie typu bazy i danych połączenia

By wybrać typ bazy trzeba podać nazwę sterownika w new_connection("STEROWNIK"); oraz ustawić host, login i hasło za pomocą odpowiednich metod:
#define HAVE_SSTREAM 1
#include <hk_classes.h>
#include <iostream>
int main()
{
	hk_drivermanager* mydrivermanager = new hk_drivermanager();
	if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
	hk_connection* myconnection = mydrivermanager->new_connection("postgres");
	if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
	myconnection->set_host("localhost");
	myconnection->set_user("user");
	myconnection->set_password("haslo");
	myconnection->connect();
}
Jeżeli program wykona się bez żadnych błędów to wszystko działa.

Wykonywanie zapytań

hk_classes umożliwia wykonywanie zapytań SQL. Oto przykładowy kod:
#define HAVE_SSTREAM 1
#include <hk_classes.h>
#include <iostream>
int main()
{
	hk_drivermanager* mydrivermanager = new hk_drivermanager();
	if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
	hk_connection* myconnection = mydrivermanager->new_connection("postgres");
	if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
	myconnection->set_host("localhost");
	myconnection->set_user("user");
	myconnection->set_password("haslo");
	myconnection->connect();
	
	hk_database* mydatabase=myconnection->new_database("test");
	if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
	hk_datasource* mydatasource= mydatabase->new_resultquery();
	mydatasource->set_sql("SELECT * FROM boo_rk_posts");
	if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
	mydatasource->enable();
	mydatasource->dump_data(); // TYLKO DO TESTOWANIA
}
Nowy kod zaczyna się od hk_database* mydatabase=myconnection->new_database("test"); gdzie łączymy się z określoną bazą danych na serwerze PostgreSQL a następnie pobieramy dane z tabeli boo_rk_posts (instalka RkCMF). Wykonanie programu zwróci coś takiego:
driverspecific DUMP
====
0: 2 news_1 2 NULLvalue NULLvalue Komentarze dla newsa [b]Pierwszy news[/b] 0 1126356179 NULLvalue NULLvalue 2
1: 3 root 2 ::1 NULLvalue ssssssssssss 0 1126356218 NULLvalue NULLvalue 2
2: 1 root 2 127.0.0.1 NULLvalue Jeżeli widzisz ten post to oznacza to że instalacja punBB i RkCMF udała się. 0 1126356152 NULLvalue NULLvalue 1


Wyświetlanie danych z kolumny

By pokazać dane z określonej kolumny mamy obiekt hk_column. By wyświetlić dane z obecnie "zaznaczonego" wiersza kolumny należy użyć mycolumn->asstring(). Metoda hk_datasource::column_by_name pozwana natomiast na wybranie owej kolumny po jej nazwie. Po wybraniu kolumny zaznaczony jest pierwszy wiersz, by przejść do następnych trzeba skorzystać z metod:
bool goto_row (unsigned long r)
bool goto_first (void)
bool goto_last (void)
bool goto_next (void)
bool goto_previous (void)
A oto przykładowy kod
#define HAVE_SSTREAM 1
#include <hk_classes.h>
#include <iostream>
int main()
{
	hk_drivermanager* mydrivermanager = new hk_drivermanager();
	if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
	hk_connection* myconnection = mydrivermanager->new_connection("postgres");
	if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
	myconnection->set_host("localhost");
	myconnection->set_user("user");
	myconnection->set_password("haslo");
	myconnection->connect();
	hk_database* mydatabase=myconnection->new_database("test");
	if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
	// Wybieramy tabelę
	hk_datasource* mydatasource= mydatabase->new_table("boo_rk_posts");
	if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
	mydatasource->enable();
	
	// Wybieramy wiersz
	hk_column* mycolumn = mydatasource->column_by_name("message");
	if (mycolumn==NULL) {cout <<"error getting column"<<endl;exit(1);}
	// Wyświetlamy dwa wiersze
	cout <<"Pierwszy wiersz: "<<mycolumn->asstring()<<endl;
	mydatasource->goto_next();
	cout <<"Drugi wiersz: "<<mycolumn->asstring()<<endl;
	delete mydrivermanager;
}
Wyświetli pierwszy i drugi wpis... ale jak wyświetlić wszystkie? Zwróć uwagę że goto_next i koledzy to metody bool - zwrócą wartość prawda jeżeli uda im się przejść do wiersza... tak więc zastosujmy do while:
#define HAVE_SSTREAM 1
#include <hk_classes.h>
#include <iostream>
int main()
{
	hk_drivermanager* mydrivermanager = new hk_drivermanager();
	if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
	hk_connection* myconnection = mydrivermanager->new_connection("postgres");
	if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
	myconnection->set_host("localhost");
	myconnection->set_user("login");
	myconnection->set_password("haslo");
	myconnection->connect();
	hk_database* mydatabase=myconnection->new_database("test");
	if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
	hk_datasource* mydatasource= mydatabase->new_table("boo_rk_cmf_global_lang");
	if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
	mydatasource->enable();
	
	hk_column* mycolumn = mydatasource->column_by_name("lang_string");
	if (mycolumn==NULL) {cout <<"error getting column"<<endl;exit(1);}
	
	do
		{
		cout <<mycolumn->asstring()<<endl;
		} while (mydatasource->goto_next());
	delete mydrivermanager;
}
Pętla do ... while ma tą zaletę że warunek sprawdzany jest po przejściu pętli, a w przypadku zwykłego while - przed jej przejściem, co spowodowałoby że dopiero drugi wiersz by się wyświetlił.

Edycja wartości pola kolumny

#define HAVE_SSTREAM 1
#include <hk_classes.h>
#include <iostream>
int main()
{
	hk_drivermanager* mydrivermanager = new hk_drivermanager();
	if (mydrivermanager==NULL) {cout <<"error creating mydrivermanager"<<endl;exit(1);}
	hk_connection* myconnection = mydrivermanager->new_connection("postgres");
	if (myconnection==NULL) {cout <<"error creating myconnection"<<endl;exit(1);}
	myconnection->set_host("localhost");
	myconnection->set_user("login");
	myconnection->set_password("haslo");
	myconnection->connect();
	hk_database* mydatabase=myconnection->new_database("test");
	if (mydatabase==NULL) {cout <<"error creating mydatabase"<<endl;exit(1);}
	hk_datasource* mydatasource= mydatabase->new_table("boo_rk_cmf_global_lang");
	if (mydatasource==NULL) {cout <<"error creating mydatasource"<<endl;exit(1);}
	mydatasource->enable();
	
	hk_column* mycolumn = mydatasource->column_by_name("lang_string");
	if (mycolumn==NULL) {cout <<"error getting column"<<endl;exit(1);}
	// Tutaj owy kod jest
	// edytujemy dany wiersz
	mycolumn->set_asstring("nowy wpis");
	// zapisujemy
	mydatasource->store_changed_data();
	
	delete mydrivermanager;
}
hk_classes pozwala również na dodawanie i usuwanie wierszy jak i ich przeszukiwanie. Pełen opis znajduje się w dokumentacji klasy lecz np dodawanie pełnego wpisu do wieloelementowej tabeli najlepiej zrobić poprzez zwykłe zapytanie INSERT.
blog comments powered by Disqus

Kategorie

Strony