#include "Database.h" // if (!_db.CheckSyntax(req)) // { // wxString s = req; // std::cout << s.mb_str() << " is invalid !\n" ; // code_if_syntax_fail; // return return_value; // } #define EXECUTE_SQL_QUERY_WITH_CODE(req, res, return_value, code_if_fail, code_if_syntax_fail) \ do{\ try\ {\ res = _db.ExecuteQuery(req);\ }\ catch (wxSQLite3Exception e)\ {\ std::cerr << e.GetMessage().mb_str() << "\n" ;\ code_if_fail; \ return return_value;\ }\ } while(0); #define EXECUTE_SQL_QUERY(req, res, return_value) EXECUTE_SQL_QUERY_WITH_CODE(req, res, return_value, {}, {}) Database::Database() { std::ifstream bdd_file; bdd_file.open(BDD_FILE); if (!bdd_file) { CreateDatabase(); } else _db.Open(_(BDD_FILE)); bdd_file.close(); } void Database::CreateDatabase() { std::ifstream init_script; std::string line; wxString wxline; wxMessageBox(_("No database found, creating a new one"), _("KissCount"), wxICON_EXCLAMATION | wxOK ); init_script.open(INIT_SCRIPT); if (!init_script) { wxMessageBox(_(INIT_SCRIPT " not found, aborting"), _("Error"), wxICON_ERROR | wxOK ); throw "init.sql not found, aborting"; } _db.Open(_(BDD_FILE)); do { getline(init_script, line); wxline = wxString(line.c_str(), wxConvUTF8); wxline.Trim(false); if (!wxline.Length() || wxline.StartsWith(_("--"))) continue; if (!_db.CheckSyntax(wxline)) { std::cout << line << " is invalid !\n" ; continue; } try { _db.ExecuteUpdate(wxline); } catch (...) { wxMessageBox(_("Error creating original database"), _("Error"), wxICON_ERROR | wxOK ); remove(BDD_FILE); throw line; } } while (init_script); init_script.close(); } std::list Database::GetUsers() { std::list res; // Check whether value exists in table wxSQLite3ResultSet set ; EXECUTE_SQL_QUERY(_("SELECT name FROM user ORDER BY name"), set, res); while (set.NextRow()) { res.push_front(set.GetAsString(0)); } set.Finalize(); return res; } bool Database::IsValidUser(wxString user, wxString password) { bool res; blk_SHA_CTX sha_ctx; unsigned char sha[20]; wxString req, wxSHA; wxSQLite3ResultSet set; blk_SHA1_Init(&sha_ctx); blk_SHA1_Update(&sha_ctx, password.c_str(), password.Length()); blk_SHA1_Final(sha, &sha_ctx); for(int i=0; i<20; i++) wxSHA += wxString::Format(wxT("%02x"), (int)sha[i]); req = _("SELECT name FROM user WHERE name='") + user + _("' AND password='") + wxSHA + _("'"); EXECUTE_SQL_QUERY(req, set, false); res = set.NextRow() ; set.Finalize(); return res; } User* Database::LoadUser(wxString name) { wxSQLite3ResultSet set; wxString req; User* user; struct Account account; std::map::iterator it; req = _("SELECT * FROM user WHERE name='") + name + _("'"); EXECUTE_SQL_QUERY(req, set, NULL); if (!set.NextRow()) return NULL; user = new User(); user->_id = set.GetAsString(_("id")); user->_name = set.GetAsString(_("name")); user->_password = _("") ; // Security reasons set.GetAsString("password"); set.Finalize(); req = _("SELECT * FROM account WHERE user='") + user->_id + _("' ORDER BY default_account DESC, name ASC"); EXECUTE_SQL_QUERY_WITH_CODE(req, set, NULL, {delete user;}, {delete user;}); while (set.NextRow()) { account.id = set.GetAsString(_("id")); account.name = set.GetAsString(_("name")); account.number = set.GetAsString(_("number")); account.shared = set.GetBool(_("shared")); account._default = set.GetBool(_("default_account")); user->_accounts[account.id] = account; } set.Finalize(); if (!user->_accounts.empty()) { it = user->_accounts.begin(); req = _("SELECT DISTINCT year FROM account_amount WHERE account IN('") + it->first; it++; for (;it != user->_accounts.end(); it++) { req += _("', '") + it->first ; } req += _("') ORDER BY year ASC"); EXECUTE_SQL_QUERY_WITH_CODE(req, set, NULL, {delete user;}, {delete user;}); while (set.NextRow()) { user->_operations[set.GetInt(_("year"))] = NULL; } set.Finalize(); } req = _("SELECT id, value FROM preference WHERE type='category' AND name='name' AND user='") + user->_id + _("' ORDER BY value ASC"); EXECUTE_SQL_QUERY_WITH_CODE(req, set, NULL, {delete user;}, {delete user;}); while (set.NextRow()) user->_preferences._categories[set.GetAsString(_("id"))] = set.GetAsString(_("value")); set.Finalize(); return user; } void Database::LoadYear(User* user, int year) { wxSQLite3ResultSet set; wxString req; std::map::iterator it; if (user->_operations[year] == NULL) user->_operations[year] = new std::map >(); it = user->_accounts.begin(); req = _("SELECT * FROM operation WHERE account IN('") + it->first; it++; for (;it != user->_accounts.end(); it++) { req += _("', '") + it->first ; } req += _("') ORDER BY fix_cost DESC, year,month,day ASC"); EXECUTE_SQL_QUERY(req, set, ); while (set.NextRow()) { operation op; op.id = set.GetAsString(_("id")); op.account = set.GetAsString(_("account")); op.day = set.GetInt(_("day")); op.month = set.GetInt(_("month")); op.year = set.GetInt(_("year")); op.amount = set.GetDouble(_("amount")); op.description = set.GetAsString(_("description")); op.category = set.GetAsString(_("category")); op.fix_cost = set.GetBool(_("fix_cost")); (*user->_operations[op.year])[op.month].push_back(op); } set.Finalize(); } double Database::GetAccountAmount(wxString id, int month, int year) { wxSQLite3ResultSet set; wxString req; double res; req = _("SELECT amount FROM account_amount WHERE account='") + id ; req += _("' AND month='") + wxString::Format(_("%d"), month); req += _("' AND year='") + wxString::Format(_("%d"), year); req += _("'"); EXECUTE_SQL_QUERY(req , set, 0.0); if (set.NextRow()) res = set.GetDouble(_("amount")); else res = 0.0; set.Finalize(); return res; }