Compare commits

..

No commits in common. 'dev' and 'v0.7' have entirely different histories.
dev ... v0.7

  1. 45
      .vscode/settings.json
  2. 114
      README.md
  3. 201
      lib/mysql.hpp
  4. 119
      lib/sqlqa.hpp
  5. 244
      src/mysql.cpp
  6. 97
      src/sqlqa.cpp
  7. 240
      test/test.cpp
  8. BIN
      test/test.o

@ -18,49 +18,6 @@
"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,11 +9,10 @@ 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: vector, tuple - Native C++ containers: map, vector
- Response object - QA object
- Thread safe - Thread safe
- Exceptions and log error callback - Exceptions
- Can use external time loop for connection management
## Installation ## Installation
@ -32,111 +31,34 @@ 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++
#include "../lib/mysql.hpp"
using namespace marcelb::mysql;
/**
* Init
*/
MySQL mydb("tcp://192.168.2.10:3306", "user_nm", "passss", "my_db", 5);
/**
* Use ------------------
*/ | |
------------------ |
try { | | | |
// execute | | | |
auto response = mydb.exec<int,string>("SELECT id,domain FROM records WHERE enabled = 0;");
// response is MySQL_Res<int,string> type
// check is execute
cout << response.affected << " " << response.have_result << endl;
cout << response.rows << " " << response.columns << endl;
for (auto row : response) { // row is tuple<int,string> type
cout << get<0>(row) << " " << get<1>(row) << endl;
}
// access columns name
for (auto column_name : response.columns_name) {
cout << column_name << endl;
}
} catch (const string err) {
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++ ```c++
#include "../lib/mysql.hpp"
using namespace marcelb::mysql;
#include "../../asynco/lib/timers.hpp"
using namespace marcelb::asynco;
/** /**
* Init * Init
*/ */
MySQL mydb("tcp://192.168.2.10:3306", "user_nm", "passss", "my_db", 5, time_loop_type::external); mySQL mydb("tcp://192.168.2.10:3306", "user_nm", "passss", "my_db", 5);
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 * Use
*/ */
sqlQA test_qa;
auto a1 = atask ( [&mydb] () { // build qa
test_qa.select().from("records").where("enabled = 1");
try { try {
auto response = mydb.exec<int,string>("SELECT id,domain FROM records WHERE enabled = 1;"); // execute
for (auto row : response) { mydb.exec(test_qa);
cout << get<0>(row) << " " << get<1>(row) << endl; // check is execute
} if (test_qa.executed) {
} catch (const string err) { // print
cout << err << endl; test_qa.print(true);
} // access to first result of column id
}); cout << test_qa.result["id"][0] << endl;
// num of returned rows and columns
auto a2 = atask ( [&mydb] () { cout << test_qa.num_rows << " " << test_qa.num_columns << endl;
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) { } catch (const string err) {
cout << err << endl; 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,14 +1,12 @@
#ifndef _MYSQL_ #ifndef _MYSQL_
#define _MYSQL_ #define _MYSQL_
#include <queue> #include <deque>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <future> #include <future>
#include <string>
#include <vector> #include "sqlqa.hpp"
#include <tuple>
#include "ctime"
#include <mysql_driver.h> #include <mysql_driver.h>
#include <mysql_connection.h> #include <mysql_connection.h>
@ -26,212 +24,77 @@ 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
};
/** class mySQL {
* 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;
};
/**
* 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;
queue<Connection*> connection_pool; deque<Connection*> con;
string path, username, password, database; string path, username, password, db;
uint32_t pool_size; uint available;
bool run_tloop = true; uint reconTrys = 3;
future<void> tloop_future; bool runBot = true;
time_loop_type tloop_type; future<void> bot;
time_t last_loop_time;
/** /**
* Open one database server connection * Get column names for a table
*/ */
Connection* create_connection(); void getColumns(const string _table, vector<string> &_columns, Connection *ptr_con); // privatno
/** /**
* Close one database connection * Open one database
*/ */
bool disconnect_connection(Connection* connection); bool open_one(Connection* con_ptr);
/** /**
* Take an pool_size database connection * Open one database server connection
*/
Connection* occupy_connection();
/**
* Free an database connection
*/
void release_connection(Connection* connection);
/**
* Function parses a parameterized row
*/ */
Connection* create_con();
template<typename... Types, size_t... Is>
static tuple<Types...> getRow(sql::ResultSet* res, index_sequence<Is...>) {
return make_tuple(getValue<Types>(res, Is + 1)...);
}
/** /**
* Connect all connections to server * Close one database connection
*/
void connect_pool();
/**
* Disconnect all connections to server
*/ */
void disconnect_pool(); bool disconnect_one(Connection* con_ptr);
/** /**
* Internal tloop periodic * Take an available database connection
*/ */
Connection* shift_con();
void _tloop();
public: public:
function<void(const string&)> on_error;
uint32_t connect_trys = 3;
/** /**
* 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 uint32_t _available = 1, const time_loop_type _engine_type = time_loop_type::internal); mySQL(const string _path, const string _username, const string _password, const string _db, const uint _available = 1);
/** /**
* Execute the SQL statement * Disconnect all connections to server
*/ */
template<typename... Types> bool disconnect();
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(); * Define the maximum number of attempts to
result.rows = res->rowsCount(); * reconnect to the server
*/
ResultSetMetaData *metaData = res->getMetaData(); void reconnectTrys(const uint _trys);
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;
}
/** /**
* If you are using an external periodic motor, * Execute SQLQA
* please call this function in it for proper operation at a certain time interval.
* You can use the default MYSQL_PERIODIC_INTERNAL_TIME
*/ */
void tloop(); void exec(sqlQA &sql_qa);
/** /**
* Destruktor * Destruktor
* close all connections * close all connections
*/ */
~MySQL(); ~mySQL();
}; };
}
} }
#endif #endif

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

@ -0,0 +1,97 @@
#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,165 +1,142 @@
#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;
#include "../../asynco/lib/asynco.hpp" using namespace std;
#include "../../asynco/lib/timers.hpp" using namespace chrono;
using namespace marcelb::asynco; using namespace marcelb;
int main() { int main() {
try { try {
// 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", 1);
MySQL mydb("tcp://bitelex.ddns.net:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 5, time_loop_type::external); 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", 5);
mydb.on_error = [](const string& error) { // sleep(3600*10);
cout << error << endl;
};
periodic mysql_tloop ( [&mydb] () {
cout << "loop---------------------------" << endl;
mydb.tloop();
}, MYSQL_PERIODIC_INTERNAL_TIME);
while (true) {
sleep(5);
auto start = high_resolution_clock::now(); auto start = high_resolution_clock::now();
auto a1 = nonsync ( [&mydb] () {
try {
auto response = mydb.exec<int,string>("SELECT id,domain FROM records WHERE enabled = 1;");
cout << response.affected << " " << response.have_result << endl;
cout << response.rows << " " << response.columns << endl;
for (auto row : response) {
cout << get<0>(row) << " " << get<1>(row) << endl;
}
for (auto column_name : response.columns_name) {
cout << column_name << endl;
}
} catch (const SQLException error) {
cout << error.what() << endl;
}
});
auto a2 = nonsync ( [&mydb] () {
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;
for (auto row : response) {
cout << get<0>(row) << " " << get<1>(row) << endl;
}
for (auto column_name : response.columns_name) {
cout << column_name << endl;
}
} catch (const SQLException error) {
cout << error.what() << endl;
}
});
auto a3 = nonsync ( [&mydb] () {
try {
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;
for (auto row : response) {
cout << get<0>(row) << " " << get<1>(row) << endl;
}
for (auto column_name : response.columns_name) {
cout << column_name << endl;
}
} catch (const SQLException error) {
cout << error.what() << endl;
}
});
auto a4 = nonsync ( [&mydb] () { // thread t1([&](){
// try {
// sqlQA test_qa;
// test_qa.select().from("records").where("enabled = 1");
// mydb.exec(test_qa);
// test_qa.print(true);
// } catch (const string err) {
// cout << err << endl;
// }
// });
// // sleep(2);
// thread t2([&](){
// try {
// sqlQA test_qa;
// test_qa.select().from("zones");
// mydb.exec(test_qa);
// test_qa.print(true);
// } catch (const string err) {
// cout << err << endl;
// }
// });
// // sleep(3);
// thread t3([&](){
// try {
// sqlQA test_qa;
// test_qa.select().from("users");
// mydb.exec(test_qa);
// test_qa.print(true);
// } catch (const string err) {
// cout << err << endl;
// }
// });
// // sleep(1);
// thread t4([&](){
// try {
// sqlQA test_qa;
// test_qa.select().from("records").where("enabled = 1");
// mydb.exec(test_qa);
// test_qa.print(true);
// } catch (const string err) {
// cout << err << endl;
// }
// });
// thread t5([&](){
// try {
// sqlQA test_qa;
// test_qa.select().from("zones");
// mydb.exec(test_qa);
// test_qa.print(true);
// } catch (const string err) {
// cout << err << endl;
// }
// });
// thread t6([&](){
// try {
// sqlQA test_qa;
// test_qa.select().from("users");
// mydb.exec(test_qa);
// test_qa.print(true);
// } catch (const string err) {
// cout << err << endl;
// }
// });
// t1.join();
// t2.join();
// t3.join();
// t4.join();
// t5.join();
// t6.join();
// one by one
try { try {
auto response = mydb.exec<int,string>("SELECT id,domain FROM records 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) { sleep(20);
cout << column_name << endl;
}
} catch (const SQLException error) {
cout << error.what() << endl;
}
});
auto a5 = nonsync ( [&mydb] () {
try { try {
auto response = mydb.exec<string,string>("SELECT zonename,auth_key FROM zones;"); sqlQA test_qa;
cout << response.affected << " " << response.have_result << endl; test_qa.select().from("users");
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) { sleep(20);
cout << column_name << endl;
}
} catch (const SQLException error) {
cout << error.what() << endl;
}
});
auto a6 = nonsync ( [&mydb] () {
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("zone_id,record_type,enabled").from("records").where("domain = 'bitelex.test'");
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;
} }
} catch (const SQLException error) {
cout << error.what() << 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) {
cout << error.what() << endl; cout << error.what() << endl;
@ -169,8 +146,7 @@ while (true) {
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