diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..394cbad --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +example +test/test.o \ No newline at end of file diff --git a/lib/mysql.hpp b/lib/mysql.hpp index 762007d..1ca1392 100644 --- a/lib/mysql.hpp +++ b/lib/mysql.hpp @@ -2,6 +2,7 @@ #define _MYSQL_ #include +#include #include #include #include @@ -21,6 +22,40 @@ using namespace std; using namespace sql; using namespace mysql; +class sqlQA { + public: + // query + string cmd; + string table; + vector columns; + bool isUpdate = false; + bool isSelect = false; + + // answer + uint updateCatch = 0; + bool executed = false; + map> result; + uint num_rows = 0; + uint num_columns = 0; + + // query methods + sqlQA& select(const string _select = "*"); + sqlQA& from(const string _tablename); + sqlQA& where(const string _condition); + // sqlQA& limit(); + // sqlQA& insertInTo(string _tablename, string _columns); + // sqlQA& values(); // proizvoljan broj argumenata + sqlQA& update(const string _tablename); + sqlQA& set(const string _column_value_pairs); + // sqlQA& deleteFrom(); + + // answer methods + + + private: + void parse_columns(const string _cloumns); +}; + class mySQL { public: mutex io; @@ -32,12 +67,10 @@ class mySQL { mySQL(const string _path, const string _username, const string _password, const string _db, bool _isPersistent = false); bool open(const string _db = ""); bool connect(); - bool close(); - map> query(const string sql_command); - bool change(const string sql_command); - string getTable(const string req); + bool disconnect(); + void exec(sqlQA &sql_qa); + void getColumns(const string _table, vector &_columns); ~mySQL(); - }; diff --git a/src/mysql.cpp b/src/mysql.cpp index 59cc5f6..0dc1d93 100644 --- a/src/mysql.cpp +++ b/src/mysql.cpp @@ -1,5 +1,51 @@ #include "../lib/mysql.hpp" +sqlQA& sqlQA::select(const string _columns) { + if (_columns != "*") { + parse_columns(_columns); + } + isSelect = true; + cmd += "SELECT " + _columns + " "; + return *this; +} + +sqlQA& sqlQA::from(const string _table) { + table = _table; + cmd += "FROM " + _table + " "; + return *this; +} + +sqlQA& sqlQA::where(const string _condition) { + cmd += "WHERE " + _condition + " "; + return *this; +} + +sqlQA& sqlQA::update(const string _table) { + isUpdate = true; + cmd += "UPDATE " + _table + " "; + return *this; +} + +sqlQA& sqlQA::set(const string _column_value_pairs) { + cmd += "SET " + _column_value_pairs + " "; + return *this; +} + + +void sqlQA::parse_columns(const string _columns) { + istringstream iss(_columns); + string columnName; + + while (getline(iss, columnName, ',')) { + size_t startPos = columnName.find_first_not_of(" "); + size_t endPos = columnName.find_last_not_of(" "); + + if (startPos != string::npos && endPos != string::npos) { + columns.push_back(columnName.substr(startPos, endPos - startPos + 1)); + } + } +} + mySQL::mySQL(const string _path, const string _username, const string _password, const string _db, bool _isPersistent) { path = _path; username = _username; @@ -60,7 +106,7 @@ bool mySQL::connect() { return status; } -bool mySQL::close() { +bool mySQL::disconnect() { io.lock(); bool status = true; @@ -72,14 +118,19 @@ bool mySQL::close() { } catch (const SQLException &error) { cout << error.what() << endl; + status = true; io.unlock(); } } + else { + status = false; + } + return status; } -map> mySQL::query(const string sql_command) { +void mySQL::exec(sqlQA &sql_qa) { if (!isPersistent || !con->isValid() || con->isClosed()) { if (connect()) { @@ -93,87 +144,47 @@ map> mySQL::query(const string sql_command) { io.lock(); /**/ - map> maped; - try { - Statement *stmt; - stmt = con->createStatement(); + vector columns = sql_qa.columns; - const string table = getTable(sql_command); - if (table.empty()) { - throw string ("[ERROR] SQL command not have table "); - } - - ResultSet *columnsRes = stmt->executeQuery("SHOW COLUMNS from " + table); - vector tableFields; - - while (columnsRes->next()) { - tableFields.push_back(columnsRes->getString("Field")); + if (columns.empty() && !sql_qa.table.empty()) { + getColumns(sql_qa.table, columns); } - delete columnsRes; - - ResultSet *res = stmt->executeQuery(sql_command); + Statement *stmt; + stmt = con->createStatement(); - while (res->next()) { - for (uint i=0; igetString(tableFields[i])); + if (sql_qa.isSelect) { + ResultSet *res = stmt->executeQuery(sql_qa.cmd); + sql_qa.executed = true; + uint num_raw_columns = 0; + while (res->next()) { + for (uint i=0; igetString(columns[i])); + num_raw_columns++; + } } - } - delete res; - delete stmt; - - io.unlock(); - } - catch (const SQLException &error) { - cout << error.what() << endl; - io.unlock(); - } - catch (const string error) { - throw error; - io.unlock(); - } - - /**/ - - if (!isPersistent) { - if(close()) { - throw string("[ERROR] Unable to close database "); + delete res; + sql_qa.num_columns = columns.size(); + sql_qa.num_rows = num_raw_columns/columns.size(); } - } - return maped; -} - -bool mySQL::change(const string sql_command) { - - if (!isPersistent || !con->isValid() || con->isClosed()) { - if (connect()) { - throw string("[ERROR] Unable to connect database "); + if (sql_qa.isUpdate) { + sql_qa.updateCatch = stmt->executeUpdate(sql_qa.cmd); + sql_qa.executed = true; } - if (open()) { - throw string("[ERROR] Unable to open database " + db); + else { + sql_qa.executed = stmt->execute(sql_qa.cmd); } - } - - io.lock(); - /**/ - bool status = false; - - try { - Statement *stmt; - stmt = con->createStatement(); - - uint changeCatch = stmt->executeUpdate(sql_command); - status = (bool)changeCatch; delete stmt; io.unlock(); } catch (const SQLException &error) { cout << error.what() << endl; + sql_qa.executed = false; io.unlock(); } catch (const string error) { @@ -184,29 +195,29 @@ bool mySQL::change(const string sql_command) { /**/ if (!isPersistent) { - if(close()) { + if(disconnect()) { throw string("[ERROR] Unable to close database "); } } - return status; } +void mySQL::getColumns(const string _table, vector &_columns) { + Statement *stmt; + stmt = con->createStatement(); + + ResultSet *columnsRes = stmt->executeQuery("SHOW COLUMNS from " + _table); -string mySQL::getTable(const string req) { - size_t from = req.find("FROM") < req.find("from") ? req.find("FROM") : req.find("from"); - size_t ends = req.find(" ", from+5) < req.length() ? req.find(" ", from+5) : req.length(); - if (from > req.length()) { - return ""; + while (columnsRes->next()) { + _columns.push_back(columnsRes->getString("Field")); } - string table = req.substr(from+5, ends-from-5); - return table; -} - + delete columnsRes; + delete stmt; +} mySQL::~mySQL() { - if(close()) { + if(disconnect()) { throw string("[ERROR] Unable to close database "); } } diff --git a/test/test.cpp b/test/test.cpp index f80a0be..435ca05 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -10,24 +10,36 @@ int main() { try { - auto res = mydb.query("SELECT * FROM records WHERE enabled = 1;"); + sqlQA test_qa; + // id,user_id,zone_id,domain,record_type,auth_key,last_update,enabled + // test_qa.select().from("records").where("enabled = 1"); + // mydb.exec(test_qa); + + // for (auto i : test_qa.result) { + // for (auto j: i.second) { + // cout << i.first << " : " << j << endl; + // } + // } + - for (auto i : res) { - for (auto j: i.second) { - cout << i.first << " : " << j << endl; - } + test_qa.update("records").set("enabled = 1").where("domain = 'bitelex.test'"); + mydb.exec(test_qa); + if (test_qa.executed) { + cout << "Num rows affect " << test_qa.updateCatch << endl; } - // if (mydb.change("UPDATE records SET enabled = 0 WHERE domain = 'bitelex.ml'")) { - // cout << "Update sucessfuly" << endl; - // } + cout << "Num rows " << test_qa.num_rows << " num columns " << test_qa.num_columns << " executed " << test_qa.executed << endl; + } catch (const SQLException error) { cout << error.what() << endl; } - catch (const string error) { - cout << error << endl; + // catch (const string error) { + // cout << error << endl; + // } + catch (...) { + cout << "Jebi ga" << endl; } diff --git a/test/test.o b/test/test.o index 4b2c9c0..b7575eb 100755 Binary files a/test/test.o and b/test/test.o differ