Compare commits

..

6 Commits

  1. 45
      .vscode/settings.json
  2. 116
      README.md
  3. 212
      lib/mysql.hpp
  4. 119
      lib/sqlqa.hpp
  5. 253
      src/mysql.cpp
  6. 97
      src/sqlqa.cpp
  7. 260
      test/test.cpp
  8. BIN
      test/test.o

@ -18,6 +18,49 @@
"thread": "cpp", "thread": "cpp",
"chrono": "cpp", "chrono": "cpp",
"sstream": "cpp", "sstream": "cpp",
"map": "cpp" "map": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"atomic": "cpp",
"bit": "cpp",
"compare": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdint": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"random": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"numbers": "cpp",
"semaphore": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp",
"any": "cpp",
"variant": "cpp"
} }
} }

@ -9,10 +9,11 @@ A small framework for basic MySQL database operations via MySQL/Connector++
- Object oriented - Object oriented
- Active connection pool - Active connection pool
- Retries to connect - Retries to connect
- Native C++ containers: map, vector - Native C++ containers: vector, tuple
- QA object - Response object
- Thread safe - Thread safe
- Exceptions - Exceptions and log error callback
- Can use external time loop for connection management
## Installation ## Installation
@ -31,34 +32,111 @@ using namespace marcelb;
## Usage ## Usage
### Internal engine
It internally initializes a single thread that periodically checks the states of the connection pool, adds new ones as needed, and cleans up inactive ones.
```c++ ```c++
#include "../lib/mysql.hpp"
using namespace marcelb::mysql;
/** /**
* Init * Init
*/ */
mySQL mydb("tcp://192.168.2.10:3306", "user_nm", "passss", "my_db", 5); MySQL mydb("tcp://192.168.2.10:3306", "user_nm", "passss", "my_db", 5);
/** /**
* Use * Use ------------------
*/ */ | |
sqlQA test_qa; ------------------ |
// build qa try { | | | |
test_qa.select().from("records").where("enabled = 1"); // execute | | | |
try { auto response = mydb.exec<int,string>("SELECT id,domain FROM records WHERE enabled = 0;");
// execute // response is MySQL_Res<int,string> type
mydb.exec(test_qa);
// check is execute // check is execute
if (test_qa.executed) { cout << response.affected << " " << response.have_result << endl;
// print cout << response.rows << " " << response.columns << endl;
test_qa.print(true);
// access to first result of column id for (auto row : response) { // row is tuple<int,string> type
cout << test_qa.result["id"][0] << endl; cout << get<0>(row) << " " << get<1>(row) << endl;
// num of returned rows and columns }
cout << test_qa.num_rows << " " << test_qa.num_columns << endl;
// access columns name
for (auto column_name : response.columns_name) {
cout << column_name << endl;
} }
} catch (const string err) { } catch (const string err) {
cout << err << endl; cout << err << endl;
} }
``` ```
### External engine
As I developed quite a few wrappers that have some internal thread, I realized that it was inefficient and made it possible to call the necessary functions periodically outside (one thread per whole application or timer (ASIO), or my asynco wrapper).
```c++
#include "../lib/mysql.hpp"
using namespace marcelb::mysql;
#include "../../asynco/lib/timers.hpp"
using namespace marcelb::asynco;
/**
* Init
*/
MySQL mydb("tcp://192.168.2.10:3306", "user_nm", "passss", "my_db", 5, time_loop_type::external);
periodic mysql_maintenance ( [&mydb] () {
mydb.periodic_maintenance();
}, MYSQL_PERIODIC_INTERNAL_TIME);
mydb.set_on_error( [](const string& error) {
cout << error << endl; // print or log
});
/**
* You can call multiple queries asynchronously
*/
auto a1 = atask ( [&mydb] () {
try {
auto response = mydb.exec<int,string>("SELECT id,domain FROM records WHERE enabled = 1;");
for (auto row : response) {
cout << get<0>(row) << " " << get<1>(row) << endl;
}
} catch (const string err) {
cout << err << endl;
}
});
auto a2 = atask ( [&mydb] () {
try {
auto response = mydb.exec<string,string>("SELECT zonename,auth_key FROM zones;");
for (auto row : response) {
cout << get<0>(row) << " " << get<1>(row) << endl;
}
} catch (const string err) {
cout << err << endl;
}
});
auto a3 = atask ( [&mydb] () {
try {
auto response = mydb.exec<string,string>("SELECT username,email FROM users WHERE enabled = 1;");
for (auto row : response) {
cout << get<0>(row) << " " << get<1>(row) << endl;
}
} catch (const string err) {
cout << err << endl;
}
});
wait(a1);
wait(a2);
wait(a3);
```
## License ## License
[APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/) [APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/)

@ -1,12 +1,14 @@
#ifndef _MYSQL_ #ifndef _MYSQL_
#define _MYSQL_ #define _MYSQL_
#include <deque> #include <queue>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <future> #include <future>
#include <string>
#include "sqlqa.hpp" #include <vector>
#include <tuple>
#include "ctime"
#include <mysql_driver.h> #include <mysql_driver.h>
#include <mysql_connection.h> #include <mysql_connection.h>
@ -24,77 +26,223 @@ using namespace sql;
using namespace mysql; using namespace mysql;
namespace marcelb { namespace marcelb {
namespace mysql {
/**
*
*/
#define MYSQL_PERIODIC_INTERNAL_TIME 1000
/**
* An enumeration of how periodic functions will be run
* internal - run periodic_maintenance() i new thread
* external - expects periodic_maintenance() to be run periodically outside the library
*
*/
enum class time_loop_type {
internal,
external
};
/**
* A class for creating sql responses
*/
template<typename... Types>
class MySQL_Res : public vector<tuple<Types...>> {
public:
bool have_result = false;
uint16_t affected = 0;
uint16_t rows = 0;
uint16_t columns = sizeof...(Types);
vector<string> columns_name;
};
class mySQL { /**
* Type conversion functions
*/
template<typename T>
T getValue(ResultSet* res, int column);
template<>
inline int getValue<int>(ResultSet* res, int column) {
return res->getInt(column);
}
template<>
inline uint32_t getValue<uint32_t>(ResultSet* res, int column) {
return res->getUInt(column);
}
template<>
inline int64_t getValue<int64_t>(ResultSet* res, int column) {
return res->getInt64(column);
}
template<>
inline uint64_t getValue<uint64_t>(ResultSet* res, int column) {
return res->getUInt64(column);
}
template<>
inline float getValue<float>(ResultSet* res, int column) {
return res->getDouble(column);
}
template<>
inline double getValue<double>(ResultSet* res, int column) {
return res->getDouble(column);
}
template<>
inline string getValue<string>(ResultSet* res, int column) {
return res->getString(column);
}
template<>
inline bool getValue<bool>(ResultSet* res, int column) {
return res->getBoolean(column);
}
// implementiraj neku c++ kompatibilnu pretvorbu za timestampe, time, date datetime itd.
class MySQL {
mutex io; mutex io;
condition_variable condition;
MySQL_Driver *drv; MySQL_Driver *drv;
deque<Connection*> con; queue<Connection*> connection_pool;
string path, username, password, db; string path, username, password, database;
uint available; uint32_t pool_size;
uint reconTrys = 3; uint32_t connect_trys = 3;
bool runBot = true; bool run_tloop = true;
future<void> bot; future<void> tloop_future;
time_loop_type tloop_type;
time_t last_loop_time = time(nullptr);
function<void(const string&)> on_error;
/** /**
* Get column names for a table * Open one database server connection
*/ */
void getColumns(const string _table, vector<string> &_columns, Connection *ptr_con); // privatno Connection* create_connection();
/** /**
* Open one database * Close one database connection
*/ */
bool open_one(Connection* con_ptr); bool disconnect_connection(Connection* connection);
/** /**
* Open one database server connection * Take an pool_size database connection
*/ */
Connection* create_con(); Connection* occupy_connection();
/** /**
* Close one database connection * Free an database connection
*/
void release_connection(Connection* connection);
/**
* Function parses a parameterized row
*/ */
bool disconnect_one(Connection* con_ptr);
template<typename... Types, size_t... Is>
static tuple<Types...> getRow(sql::ResultSet* res, index_sequence<Is...>) {
return make_tuple(getValue<Types>(res, Is + 1)...);
}
/** /**
* Take an available database connection * Connect all connections to server
*/
void connect_pool();
/**
* Disconnect all connections to server
*/ */
Connection* shift_con(); void disconnect_pool();
public: /**
* Internal tloop periodic
*/
void _tloop();
public:
/** /**
* mySQL constructor, * MySQL constructor,
* receive the path to the mysql server, * receive the path to the mysql server,
* username, password, database name, * username, password, database name,
* and number of active connections (optional) * and number of active connections (optional)
*/ */
mySQL(const string _path, const string _username, const string _password, const string _db, const uint _available = 1); MySQL(const string _path, const string _username, const string _password, const string _db, const uint32_t _available = 1, const time_loop_type _engine_type = time_loop_type::internal);
/**
* Disconnect all connections to server
*/
bool disconnect();
/** /**
* Define the maximum number of attempts to * Define the maximum number of attempts to
* reconnect to the server * reconnect to the server
*/ */
void reconnectTrys(const uint _trys); void set_connect_trys(const uint32_t _trys);
/**
* Set callback on error
*/
void set_on_error(function<void(const string&)> _on_error);
/**
* Execute the SQL statement
*/
template<typename... Types>
MySQL_Res<Types...> exec(const string& sql_q) {
Connection* connection = occupy_connection();
MySQL_Res<Types...> result;
try {
Statement *stmt;
stmt = connection->createStatement();
result.have_result = stmt->execute(sql_q);
if (result.have_result) {
ResultSet* res = stmt->getResultSet();
result.rows = res->rowsCount();
ResultSetMetaData *metaData = res->getMetaData();
int columnCount = metaData->getColumnCount();
for (int i = 1; i <= columnCount; ++i) {
result.columns_name.push_back(metaData->getColumnName(i));
}
while (res->next()) {
result.push_back(MySQL::getRow<Types...>(res, make_index_sequence<sizeof...(Types)>{}));
}
res->close();
delete res;
} else {
result.affected = stmt->getUpdateCount();
}
stmt->close();
delete stmt;
release_connection(connection);
} catch (sql::SQLException& e) {
throw runtime_error(e.what());
// std::cerr << "SQLState: " << e.getSQLState() << std::endl;
// std::cerr << "Error code: " << e.getErrorCode() << std::endl;
}
return result;
}
/** /**
* Execute SQLQA * If you are using an external periodic motor,
* please call this function in it for proper operation at a certain time interval.
* You can use the default MYSQL_PERIODIC_INTERNAL_TIME
*/ */
void exec(sqlQA &sql_qa); void tloop();
/** /**
* Destruktor * Destruktor
* close all connections * close all connections
*/ */
~mySQL(); ~MySQL();
}; };
}
} }
#endif #endif

@ -1,119 +0,0 @@
#ifndef _SQLQA_
#define _SQLQA_
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
using namespace std;
namespace marcelb {
/**
* A class for creating sql queries and responses
*/
class sqlQA {
public:
// query variable list
// SQL Command
string cmd;
// Table name
string table;
// Columns name list
vector<string> columns;
// Query is update type
bool isUpdate = false;
// Query is select type
bool isSelect = false;
// answer
// Number of updates caught
uint updateCatch = 0;
// Executing status
bool executed = false;
// Answer
map<string, vector<string>> result;
// Number of returned rows
uint num_rows = 0;
// Number of returned columns
uint num_columns = 0;
// query methods
/**
* SELECT
* accept columns names, comma separated
* defualt *
*/
sqlQA& select(const string _select = "*");
/**
* FROM
* accept table name
*/
sqlQA& from(const string _tablename);
/**
* WHERE
* accept string sql condition
*/
sqlQA& where(const string _condition);
/**
* LIMIT
* set limit result
*/
sqlQA& limit(const uint _limit);
/**
* INSERT IN TO
* accept table name, and columns
*/
sqlQA& insertInTo(const string _tablename, const string _columns = "");
/**
* VALUES
* accept values
*/
sqlQA& values(const string _values);
/**
* UPDATE
* accept tablename for update query
*/
sqlQA& update(const string _tablename);
/**
* SET
* accept column and value pairs
*/
sqlQA& set(const string _column_value_pairs);
/**
* DELETE FROM
* accept table name
*/
sqlQA& deleteFrom(const string _table);
/**
* Print SQLQA
*/
void print(bool withDetail = false);
// intern methods
private:
/**
* Parse column names
*/
void parse_columns(const string _cloumns);
};
}
#endif

@ -1,99 +1,86 @@
#include "../lib/mysql.hpp" #include "../lib/mysql.hpp"
marcelb::mySQL::mySQL(const string _path, const string _username, const string _password, const string _db, const uint _available) { marcelb::mysql::MySQL::MySQL(const string _path, const string _username, const string _password, const string _db, const uint32_t _available, const time_loop_type _engine_type) {
path = _path; path = _path;
username = _username; username = _username;
password = _password; password = _password;
db = _db; database = _db;
available = _available > 0 ? _available : 1; pool_size = _available > 0 ? _available : 1;
tloop_type = _engine_type;
drv = get_mysql_driver_instance(); drv = get_mysql_driver_instance();
connect_pool();
bot = async(launch::async, [&](){ if (tloop_type == time_loop_type::internal) {
while (runBot) { tloop_future = async(launch::async, [&](){
sleep(1); while (run_tloop) {
while (available>con.size() && runBot) { usleep(MYSQL_PERIODIC_INTERNAL_TIME*1000);
try { _tloop();
Connection* new_con_ptr = create_con();
if (!db.empty()) {
if (open_one(new_con_ptr)) {
throw string("[ERROR] Unable to open database " + db);
}
}
io.lock();
con.push_back(new_con_ptr);
io.unlock();
} catch (const SQLException except) {
cout << except.what() << endl;
} catch (const string except) {
cout << except << endl;
}
} }
return;
for (int i=0; i<con.size() && runBot; i++) { });
if (!con[i]->isValid()) { }
io.lock();
con.erase(con.begin()+i);
io.unlock();
i--;
}
}
}
return;
});
} }
Connection* marcelb::mySQL::create_con() { Connection* marcelb::mysql::MySQL::create_connection() {
uint trys = 0; uint32_t trys = 0;
bool status = true; bool status = true;
Connection* new_con = NULL; Connection* new_con = NULL;
while (reconTrys == unlimited ? status : (trys <= reconTrys && status)) { while (connect_trys == unlimited ? status : (trys <= connect_trys && status)) {
try { try {
Connection* con_can = drv->connect(path, username, password); Connection* con_can = drv->connect(path, username, password);
con_can->setSchema(database);
status = !con_can->isValid(); status = !con_can->isValid();
if (!status) { if (!status) {
new_con = con_can; new_con = con_can;
} }
else if (!con_can->isClosed()) { else if (!con_can->isClosed()) {
disconnect_one(con_can); disconnect_connection(con_can);
} }
} }
catch (const SQLException &error) { catch (const SQLException &error) {
cout << error.what() << endl; if (on_error) {
on_error(error.what() + string(", SQL state: ") + error.getSQLState() + string(", Error code: ") + to_string(error.getErrorCode()));
}
usleep(reconnectSleep); usleep(reconnectSleep);
reconTrys == unlimited ? trys : trys++; connect_trys == unlimited ? trys : trys++;
} }
} }
return new_con; return new_con;
} }
bool marcelb::mySQL::disconnect() { void marcelb::mysql::MySQL::connect_pool() {
io.lock(); lock_guard<mutex> lock(io);
bool status = true; for (uint32_t i=0; i<pool_size; i++) {
Connection* connection = create_connection();
for (uint i=0; i<con.size(); i++) { connection_pool.push(connection);
status = disconnect_one(con[i]) ;
} }
io.unlock();
return status;
} }
bool marcelb::mySQL::disconnect_one(Connection* con_ptr) { void marcelb::mysql::MySQL::disconnect_pool() {
bool status = !con_ptr->isClosed(); lock_guard<mutex> lock(io);
for (uint32_t i=0; i<connection_pool.size(); i++) {
Connection* connection = connection_pool.front();
connection_pool.pop();
disconnect_connection(connection) ;
}
}
bool marcelb::mysql::MySQL::disconnect_connection(Connection* connection) {
bool status = !connection->isClosed();
if (status) { if (status) {
try { try {
con_ptr->close(); connection->close();
status = !con_ptr->isClosed(); status = !connection->isClosed();
} }
catch (const SQLException &error) { catch (const SQLException &error) {
cout << error.what() << endl; if (on_error) {
on_error(error.what() + string(", SQL state: ") + error.getSQLState() + string(", Error code: ") + to_string(error.getErrorCode()));
}
status = true; status = true;
} }
} }
@ -102,132 +89,78 @@ bool marcelb::mySQL::disconnect_one(Connection* con_ptr) {
status = false; // već je zatvorena status = false; // već je zatvorena
} }
delete con_ptr; delete connection;
return status; return status;
} }
bool marcelb::mySQL::open_one(Connection* con_ptr) { void marcelb::mysql::MySQL::_tloop() {
bool status = true; // ako true greška je for (size_t i = 0; i < pool_size && run_tloop; i++) {
uint trys = 0;
while (reconTrys == unlimited ? status : (trys <= reconTrys && status)) {
try { try {
if (con_ptr->isValid()) { Connection *conn = occupy_connection();
con_ptr->setSchema(db); if (conn->isValid()) {
status = false; release_connection(conn);
} else {
if (!conn->isClosed()){
conn->close();
}
Connection *n_conn = create_connection();
release_connection(n_conn);
} }
else { } catch (const SQLException &error) {
break; if (on_error) {
on_error(error.what() + string(", SQL state: ") + error.getSQLState() + string(", Error code: ") + to_string(error.getErrorCode()));
} }
} }
catch (const SQLException &error) {
cout << error.what() << endl;
usleep(reconnectSleep);
reconTrys == unlimited ? trys : trys++;
}
} }
last_loop_time = time(nullptr);
return status;
} }
/** void marcelb::mysql::MySQL::set_connect_trys(const uint32_t _trys) {
* Broj pokušaja usljed povezivanja s bazom od 1 do unlimited; // lock_guard<mutex> lock(io);
*/ connect_trys = _trys;
void marcelb::mySQL::reconnectTrys(const uint _trys) {
io.lock();
reconTrys = _trys;
io.unlock();
} }
void marcelb::mysql::MySQL::set_on_error(function<void(const string&)> _on_error) {
on_error = _on_error;
}
void marcelb::mySQL::exec(sqlQA &sql_qa) { Connection* marcelb::mysql::MySQL::occupy_connection() {
Connection* con_ptr = shift_con(); if (last_loop_time + (MYSQL_PERIODIC_INTERNAL_TIME/1000)*3 < time(nullptr) && on_error) { // ako je zadnje vrijeme + 3 intervala manje od trenutnog vremena emitiraj grešku
on_error("The time loop is not executing properly");
try {
vector<string> columns = sql_qa.columns;
if (columns.empty() && !sql_qa.table.empty()) {
getColumns(sql_qa.table, columns, con_ptr);
}
Statement *stmt;
stmt = con_ptr->createStatement();
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; i<columns.size(); i++) {
sql_qa.result[columns[i]].push_back(res->getString(columns[i]));
num_raw_columns++;
}
}
res->close();
delete res;
sql_qa.num_columns = columns.size();
sql_qa.num_rows = num_raw_columns/columns.size();
}
if (sql_qa.isUpdate) {
sql_qa.updateCatch = stmt->executeUpdate(sql_qa.cmd);
sql_qa.executed = true;
}
else {
sql_qa.executed = stmt->execute(sql_qa.cmd);
}
stmt->close();
delete stmt;
disconnect_one(con_ptr);
}
catch (const SQLException &error) {
cout << error.what() << endl;
sql_qa.executed = false;
} }
catch (const string error) { unique_lock<mutex> lock(io);
throw error; while (connection_pool.empty()) {
condition.wait(lock);
} }
Connection *connection = connection_pool.front();
connection_pool.pop();
return connection;
} }
void marcelb::mySQL::getColumns(const string _table, vector<string> &_columns, Connection *ptr_con) { void marcelb::mysql::MySQL::release_connection(Connection* connection) {
Statement *stmt; lock_guard<std::mutex> lock(io);
stmt = ptr_con->createStatement(); connection_pool.push(connection);
condition.notify_one();
ResultSet *columnsRes = stmt->executeQuery("SHOW COLUMNS from " + _table); }
while (columnsRes->next()) { marcelb::mysql::MySQL::~MySQL() {
_columns.push_back(columnsRes->getString("Field")); if (tloop_type == time_loop_type::internal) {
run_tloop = false;
tloop_future.get();
} else {
run_tloop = false;
} }
columnsRes->close(); disconnect_pool();
stmt->close();
delete columnsRes;
delete stmt;
} }
Connection* marcelb::mySQL::shift_con() {
while (true) { void marcelb::mysql::MySQL::tloop() {
while(con.size()) { if (tloop_type == time_loop_type::internal) {
io.lock(); if (on_error) {
Connection* con_ptr = con[0]; on_error("Can't start external call tloop, internal is active!");
con.pop_front();
if (con_ptr->isValid()) {
io.unlock();
return con_ptr;
}
io.unlock();
} }
usleep(1000); return;
} }
} _tloop();
marcelb::mySQL::~mySQL() {
runBot = false;
bot.get();
disconnect();
} }

@ -1,97 +0,0 @@
#include "../lib/sqlqa.hpp"
using namespace marcelb;
sqlQA& marcelb::sqlQA::select(const string _columns) {
if (_columns != "*") {
parse_columns(_columns);
}
isSelect = true;
cmd += "SELECT " + _columns + " ";
return *this;
}
sqlQA& marcelb::sqlQA::from(const string _table) {
table = _table;
cmd += "FROM " + _table + " ";
return *this;
}
sqlQA& marcelb::sqlQA::where(const string _condition) {
cmd += "WHERE " + _condition + " ";
return *this;
}
sqlQA& marcelb::sqlQA::limit(const uint _limit) {
cmd += "LIMIT " + to_string(_limit) + " ";
return *this;
}
sqlQA& marcelb::sqlQA::insertInTo(const string _tablename, const string _columns) {
isUpdate = true;
cmd += "INSERT INTO " + _tablename;
if (_columns.empty()) {
cmd += " ";
}
else {
cmd += " (" + _columns + ") ";
}
return *this;
}
sqlQA& marcelb::sqlQA::values(const string _values) {
cmd += "VALUES (" + _values + ") ";
return *this;
}
sqlQA& marcelb::sqlQA::update(const string _table) {
isUpdate = true;
cmd += "UPDATE " + _table + " ";
return *this;
}
sqlQA& marcelb::sqlQA::set(const string _column_value_pairs) {
cmd += "SET " + _column_value_pairs + " ";
return *this;
}
sqlQA& marcelb::sqlQA::deleteFrom(const string _table) {
isUpdate = true;
cmd += "DELETE FROM " + _table + " ";
return *this;
}
void marcelb::sqlQA::print(bool withDetail) {
cout << "============================================" << endl;
for (auto i : result) {
for (auto j: i.second) {
cout << i.first << " : " << j << endl;
}
cout << "--------------------------------------------" << endl;
}
if (withDetail) {
cout << "-----------------DETAILS--------------------" << endl;
cout << "Is executed: " << (executed ? "true" : "false") << endl;
cout << "Update catch: " << updateCatch << endl;
cout << "Num of rows: " << num_rows << endl;
cout << "Num of columns: " << num_columns << endl;
}
cout << "============================================" << endl;
}
void marcelb::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));
}
}
}

@ -1,141 +1,162 @@
#include <iostream> #include <iostream>
#include <thread> #include <thread>
#include <chrono> #include <chrono>
using namespace std;
using namespace chrono;
#include "../lib/mysql.hpp" #include "../lib/mysql.hpp"
using namespace marcelb::mysql;
using namespace std; #include "../../asynco/lib/asynco.hpp"
using namespace chrono; #include "../../asynco/lib/timers.hpp"
using namespace marcelb; using namespace marcelb::asynco;
int main() { int main() {
try { try {
// mySQL mydb("tcp://192.168.2.10:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 1); MySQL mydb("tcp://192.168.2.10:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 5, time_loop_type::internal);
mySQL mydb("tcp://192.168.2.10:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 5); // MySQL mydb("tcp://bitelex.ddns.net:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 10, time_loop_type::external);
// MySQL mydb("tcp://bitelex.ddns.net:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 5);
// sleep(3600*10); mydb.set_on_error( [](const string& error) {
cout << error << endl;
});
periodic mysql_tloop ( [&mydb] () {
mydb.tloop();
}, MYSQL_PERIODIC_INTERNAL_TIME);
auto start = high_resolution_clock::now();
sleep(5);
auto start = high_resolution_clock::now();
// thread t1([&](){ auto a1 = nonsync ( [&mydb] () {
// try { try {
// sqlQA test_qa; auto response = mydb.exec<int,string>("SELECT id,domain FROM records WHERE enabled = 1;");
// test_qa.select().from("records").where("enabled = 1"); cout << response.affected << " " << response.have_result << endl;
// mydb.exec(test_qa); cout << response.rows << " " << response.columns << endl;
// test_qa.print(true);
// } catch (const string err) { for (auto row : response) {
// cout << err << endl; cout << get<0>(row) << " " << get<1>(row) << endl;
// } }
// });
for (auto column_name : response.columns_name) {
// // sleep(2); cout << column_name << endl;
}
// thread t2([&](){
// try { } catch (const string err) {
// sqlQA test_qa; cout << err << endl;
// test_qa.select().from("zones"); }
// mydb.exec(test_qa); });
// test_qa.print(true);
// } catch (const string err) { auto a2 = nonsync ( [&mydb] () {
// cout << err << endl; try {
// } auto response = mydb.exec<string,string>("SELECT zonename,auth_key FROM zones;");
// }); cout << response.affected << " " << response.have_result << endl;
cout << response.rows << " " << response.columns << endl;
// // sleep(3);
for (auto row : response) {
// thread t3([&](){ cout << get<0>(row) << " " << get<1>(row) << endl;
// try { }
// sqlQA test_qa;
// test_qa.select().from("users"); for (auto column_name : response.columns_name) {
// mydb.exec(test_qa); cout << column_name << endl;
// test_qa.print(true); }
// } catch (const string err) {
// cout << err << endl; } catch (const string err) {
// } cout << err << endl;
// }); }
});
// // sleep(1);
auto a3 = nonsync ( [&mydb] () {
// thread t4([&](){ try {
// try { auto response = mydb.exec<string,string>("SELECT username,email FROM users WHERE enabled = 1;");
// sqlQA test_qa; cout << response.affected << " " << response.have_result << endl;
// test_qa.select().from("records").where("enabled = 1"); cout << response.rows << " " << response.columns << endl;
// mydb.exec(test_qa);
// test_qa.print(true); for (auto row : response) {
// } catch (const string err) { cout << get<0>(row) << " " << get<1>(row) << endl;
// cout << err << endl; }
// }
// }); for (auto column_name : response.columns_name) {
cout << column_name << endl;
// thread t5([&](){ }
// try {
// sqlQA test_qa; } catch (const string err) {
// test_qa.select().from("zones"); cout << err << endl;
// mydb.exec(test_qa); }
// test_qa.print(true); });
// } catch (const string err) {
// cout << err << endl; auto a4 = nonsync ( [&mydb] () {
// } try {
// }); auto response = mydb.exec<int,string>("SELECT id,domain FROM records WHERE enabled = 1;");
cout << response.affected << " " << response.have_result << endl;
// thread t6([&](){ cout << response.rows << " " << response.columns << endl;
// try {
// sqlQA test_qa; for (auto row : response) {
// test_qa.select().from("users"); cout << get<0>(row) << " " << get<1>(row) << endl;
// mydb.exec(test_qa); }
// test_qa.print(true);
// } catch (const string err) { for (auto column_name : response.columns_name) {
// cout << err << endl; cout << column_name << endl;
// } }
// });
} catch (const string err) {
// t1.join(); cout << err << endl;
// t2.join(); }
// t3.join(); });
// t4.join();
// t5.join(); auto a5 = nonsync ( [&mydb] () {
// t6.join(); try {
auto response = mydb.exec<string,string>("SELECT zonename,auth_key FROM zones;");
// one by one cout << response.affected << " " << response.have_result << endl;
try { cout << response.rows << " " << response.columns << endl;
sqlQA test_qa;
test_qa.select().from("records").where("enabled = 1"); for (auto row : response) {
mydb.exec(test_qa); cout << get<0>(row) << " " << get<1>(row) << endl;
test_qa.print(true); }
} catch (const string err) {
cout << err << endl; for (auto column_name : response.columns_name) {
} cout << column_name << endl;
}
sleep(20);
} catch (const string err) {
try { cout << err << endl;
sqlQA test_qa; }
test_qa.select().from("users"); });
mydb.exec(test_qa);
test_qa.print(true); auto a6 = nonsync ( [&mydb] () {
} catch (const string err) { try {
cout << err << endl; auto response = mydb.exec<string,string>("SELECT username,email FROM users WHERE enabled = 1;");
} cout << response.affected << " " << response.have_result << endl;
cout << response.rows << " " << response.columns << endl;
sleep(20);
for (auto row : response) {
try { cout << get<0>(row) << " " << get<1>(row) << endl;
sqlQA test_qa; }
test_qa.select("zone_id,record_type,enabled").from("records").where("domain = 'bitelex.test'");
mydb.exec(test_qa); for (auto column_name : response.columns_name) {
test_qa.print(true); cout << column_name << endl;
} catch (const string err) { }
cout << err << endl;
} } catch (const string err) {
cout << err << endl;
}
});
wait(a1);
wait(a2);
wait(a3);
wait(a4);
wait(a5);
wait(a6);
auto end = high_resolution_clock::now(); auto end = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(end - start); auto duration = duration_cast<microseconds>(end - start);
cout << "-------------Izvršilo se za: " << (double)(duration.count() / 1000.0) << " ms"<< endl; cout << "-------------Izvršilo se za: " << (double)(duration.count() / 1000.0) << " ms"<< endl;
// sleep(100); sleep(100);
} catch (const SQLException error) { } catch (const SQLException error) {
@ -146,7 +167,8 @@ int main() {
cout << "Jebi ga" << endl; cout << "Jebi ga" << endl;
} }
sleep(600); // sleep(600);
_asynco_engine.run();
return 0; return 0;
} }

Binary file not shown.
Loading…
Cancel
Save