Compare commits

...

6 Commits

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

@ -18,6 +18,49 @@
"thread": "cpp",
"chrono": "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
- Active connection pool
- Retries to connect
- Native C++ containers: map, vector
- QA object
- Native C++ containers: vector, tuple
- Response object
- Thread safe
- Exceptions
- Exceptions and log error callback
- Can use external time loop for connection management
## Installation
@ -31,34 +32,111 @@ using namespace marcelb;
## 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);
MySQL mydb("tcp://192.168.2.10:3306", "user_nm", "passss", "my_db", 5);
/**
* Use
*/
sqlQA test_qa;
// build qa
test_qa.select().from("records").where("enabled = 1");
try {
// execute
mydb.exec(test_qa);
* 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
if (test_qa.executed) {
// print
test_qa.print(true);
// access to first result of column id
cout << test_qa.result["id"][0] << endl;
// num of returned rows and columns
cout << test_qa.num_rows << " " << test_qa.num_columns << endl;
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++
#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
[APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/)

@ -1,12 +1,14 @@
#ifndef _MYSQL_
#define _MYSQL_
#include <deque>
#include <queue>
#include <mutex>
#include <thread>
#include <future>
#include "sqlqa.hpp"
#include <string>
#include <vector>
#include <tuple>
#include "ctime"
#include <mysql_driver.h>
#include <mysql_connection.h>
@ -24,77 +26,223 @@ using namespace sql;
using namespace mysql;
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;
};
/**
* 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 {
class MySQL {
mutex io;
condition_variable condition;
MySQL_Driver *drv;
deque<Connection*> con;
string path, username, password, db;
uint available;
uint reconTrys = 3;
bool runBot = true;
future<void> bot;
queue<Connection*> connection_pool;
string path, username, password, database;
uint32_t pool_size;
uint32_t connect_trys = 3;
bool run_tloop = true;
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
*/
bool disconnect_one(Connection* con_ptr);
void release_connection(Connection* connection);
/**
* Take an available database connection
* Function parses a parameterized row
*/
Connection* shift_con();
public:
template<typename... Types, size_t... Is>
static tuple<Types...> getRow(sql::ResultSet* res, index_sequence<Is...>) {
return make_tuple(getValue<Types>(res, Is + 1)...);
}
/**
* mySQL constructor,
* receive the path to the mysql server,
* username, password, database name,
* and number of active connections (optional)
* Connect all connections to server
*/
mySQL(const string _path, const string _username, const string _password, const string _db, const uint _available = 1);
void connect_pool();
/**
* Disconnect all connections to server
*/
bool disconnect();
void disconnect_pool();
/**
* Internal tloop periodic
*/
void _tloop();
public:
/**
* MySQL constructor,
* receive the path to the mysql server,
* username, password, database name,
* 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);
/**
* Define the maximum number of attempts to
* 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 SQLQA
* Execute the SQL statement
*/
void exec(sqlQA &sql_qa);
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;
}
/**
* 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 tloop();
/**
* Destruktor
* close all connections
*/
~mySQL();
~MySQL();
};
}
}
#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"
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;
username = _username;
password = _password;
db = _db;
available = _available > 0 ? _available : 1;
database = _db;
pool_size = _available > 0 ? _available : 1;
tloop_type = _engine_type;
drv = get_mysql_driver_instance();
connect_pool();
bot = async(launch::async, [&](){
while (runBot) {
sleep(1);
while (available>con.size() && runBot) {
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--;
}
}
if (tloop_type == time_loop_type::internal) {
tloop_future = async(launch::async, [&](){
while (run_tloop) {
usleep(MYSQL_PERIODIC_INTERNAL_TIME*1000);
_tloop();
}
return;
});
}
}
Connection* marcelb::mySQL::create_con() {
uint trys = 0;
Connection* marcelb::mysql::MySQL::create_connection() {
uint32_t trys = 0;
bool status = true;
Connection* new_con = NULL;
while (reconTrys == unlimited ? status : (trys <= reconTrys && status)) {
while (connect_trys == unlimited ? status : (trys <= connect_trys && status)) {
try {
Connection* con_can = drv->connect(path, username, password);
con_can->setSchema(database);
status = !con_can->isValid();
if (!status) {
new_con = con_can;
}
else if (!con_can->isClosed()) {
disconnect_one(con_can);
disconnect_connection(con_can);
}
}
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);
reconTrys == unlimited ? trys : trys++;
connect_trys == unlimited ? trys : trys++;
}
}
return new_con;
}
bool marcelb::mySQL::disconnect() {
io.lock();
bool status = true;
for (uint i=0; i<con.size(); i++) {
status = disconnect_one(con[i]) ;
void marcelb::mysql::MySQL::connect_pool() {
lock_guard<mutex> lock(io);
for (uint32_t i=0; i<pool_size; i++) {
Connection* connection = create_connection();
connection_pool.push(connection);
}
io.unlock();
return status;
}
bool marcelb::mySQL::disconnect_one(Connection* con_ptr) {
bool status = !con_ptr->isClosed();
void marcelb::mysql::MySQL::disconnect_pool() {
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) {
try {
con_ptr->close();
status = !con_ptr->isClosed();
connection->close();
status = !connection->isClosed();
}
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;
}
}
@ -102,132 +89,78 @@ bool marcelb::mySQL::disconnect_one(Connection* con_ptr) {
status = false; // već je zatvorena
}
delete con_ptr;
delete connection;
return status;
}
bool marcelb::mySQL::open_one(Connection* con_ptr) {
bool status = true; // ako true greška je
uint trys = 0;
while (reconTrys == unlimited ? status : (trys <= reconTrys && status)) {
void marcelb::mysql::MySQL::_tloop() {
for (size_t i = 0; i < pool_size && run_tloop; i++) {
try {
if (con_ptr->isValid()) {
con_ptr->setSchema(db);
status = false;
Connection *conn = occupy_connection();
if (conn->isValid()) {
release_connection(conn);
} else {
if (!conn->isClosed()){
conn->close();
}
else {
break;
Connection *n_conn = create_connection();
release_connection(n_conn);
}
} catch (const SQLException &error) {
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++;
}
}
return status;
last_loop_time = time(nullptr);
}
/**
* Broj pokušaja usljed povezivanja s bazom od 1 do unlimited;
*/
void marcelb::mySQL::reconnectTrys(const uint _trys) {
io.lock();
reconTrys = _trys;
io.unlock();
void marcelb::mysql::MySQL::set_connect_trys(const uint32_t _trys) {
// lock_guard<mutex> lock(io);
connect_trys = _trys;
}
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* 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);
}
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);
Connection* marcelb::mysql::MySQL::occupy_connection() {
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");
}
catch (const SQLException &error) {
cout << error.what() << endl;
sql_qa.executed = false;
unique_lock<mutex> lock(io);
while (connection_pool.empty()) {
condition.wait(lock);
}
catch (const string error) {
throw error;
}
Connection *connection = connection_pool.front();
connection_pool.pop();
return connection;
}
void marcelb::mySQL::getColumns(const string _table, vector<string> &_columns, Connection *ptr_con) {
Statement *stmt;
stmt = ptr_con->createStatement();
ResultSet *columnsRes = stmt->executeQuery("SHOW COLUMNS from " + _table);
void marcelb::mysql::MySQL::release_connection(Connection* connection) {
lock_guard<std::mutex> lock(io);
connection_pool.push(connection);
condition.notify_one();
}
while (columnsRes->next()) {
_columns.push_back(columnsRes->getString("Field"));
marcelb::mysql::MySQL::~MySQL() {
if (tloop_type == time_loop_type::internal) {
run_tloop = false;
tloop_future.get();
} else {
run_tloop = false;
}
columnsRes->close();
stmt->close();
delete columnsRes;
delete stmt;
disconnect_pool();
}
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();
void marcelb::mysql::MySQL::tloop() {
if (tloop_type == time_loop_type::internal) {
if (on_error) {
on_error("Can't start external call tloop, internal is active!");
}
usleep(1000);
return;
}
}
marcelb::mySQL::~mySQL() {
runBot = false;
bot.get();
disconnect();
_tloop();
}

@ -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 <thread>
#include <chrono>
using namespace std;
using namespace chrono;
#include "../lib/mysql.hpp"
using namespace marcelb::mysql;
using namespace std;
using namespace chrono;
using namespace marcelb;
#include "../../asynco/lib/asynco.hpp"
#include "../../asynco/lib/timers.hpp"
using namespace marcelb::asynco;
int main() {
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);
MySQL mydb("tcp://192.168.2.10:3306", "dinio", "H€r5elfInd1aH@nds", "dinio", 5, time_loop_type::internal);
// 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);
mydb.set_on_error( [](const string& error) {
cout << error << endl;
});
periodic mysql_tloop ( [&mydb] () {
mydb.tloop();
}, MYSQL_PERIODIC_INTERNAL_TIME);
// sleep(3600*10);
sleep(5);
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;
}
// 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
for (auto column_name : response.columns_name) {
cout << column_name << endl;
}
} catch (const string err) {
cout << err << endl;
}
});
auto a2 = nonsync ( [&mydb] () {
try {
sqlQA test_qa;
test_qa.select().from("records").where("enabled = 1");
mydb.exec(test_qa);
test_qa.print(true);
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 string err) {
cout << err << 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;
}
sleep(20);
for (auto column_name : response.columns_name) {
cout << column_name << endl;
}
} catch (const string err) {
cout << err << endl;
}
});
auto a4 = nonsync ( [&mydb] () {
try {
sqlQA test_qa;
test_qa.select().from("users");
mydb.exec(test_qa);
test_qa.print(true);
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 string err) {
cout << err << endl;
}
});
sleep(20);
auto a5 = 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 string err) {
cout << err << endl;
}
});
auto a6 = nonsync ( [&mydb] () {
try {
sqlQA test_qa;
test_qa.select("zone_id,record_type,enabled").from("records").where("domain = 'bitelex.test'");
mydb.exec(test_qa);
test_qa.print(true);
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 string err) {
cout << err << endl;
}
});
wait(a1);
wait(a2);
wait(a3);
wait(a4);
wait(a5);
wait(a6);
auto end = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(end - start);
cout << "-------------Izvršilo se za: " << (double)(duration.count() / 1000.0) << " ms"<< endl;
// sleep(100);
sleep(100);
} catch (const SQLException error) {
@ -146,7 +167,8 @@ int main() {
cout << "Jebi ga" << endl;
}
sleep(600);
// sleep(600);
_asynco_engine.run();
return 0;
}

Binary file not shown.
Loading…
Cancel
Save