Подключение к базе данных MySQL (библиотека mariadb.hpp)
Добавлено: 26 май 2025, 09:41
http://www.w3schools.com/mysql/
Необходимые пакеты к установке
Конфигурация:
config.hpp
Библиотека:
mariadb.hpp
для приведения типа std::to_string(переменная_другого_типа) к типу std::string в переменной query
Необходимые пакеты к установке
Код: Выделить всё
sudo apt install libmariadb-dev libmariadb-dev-compat
config.hpp
Код: Выделить всё
struct sqlDB
{
std::string sql_host = "localhost";
std::string sql_login = "";
std::string sql_passwd = "";
std::string sql_db = "";
};
mariadb.hpp
Код: Выделить всё
#include <iostream>
#include <unordered_map>
#include <string>
#include <vector>
#include <mysql/mysql.h>
class Database {
public:
static Database& getInstance() {
static Database instance; // Инициализация одиночки
return instance;
}
bool connect(const char* host, const char* user, const char* password, const char* db_name, int max_attempts = 5, int delay_seconds = 2) {
int attempts = 0;
while (attempts < max_attempts) {
conn = mysql_init(nullptr);
if (conn == nullptr) {
std::cerr << "mysql_init() failed" << std::endl;
return false;
}
if (mysql_real_connect(conn, host, user, password, db_name, 0, nullptr, 0) != nullptr) {
return true; // Успешное подключение
}
std::cerr << "mysql_real_connect() failed: " << mysql_error(conn) << std::endl;
mysql_close(conn);
conn = nullptr;
attempts++;
std::cerr << "Попытка подключения (" << attempts << "/" << max_attempts << ") через " << delay_seconds << " секунд..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(delay_seconds)); // Задержка перед повторной попыткой
}
return false; // Все попытки подключения завершились неудачно
}
void executeQuery(const char* query) {
if (mysql_query(conn, query)) {
std::cerr << "QUERY FAILED: " << mysql_error(conn) << std::endl;
} else {
MYSQL_RES *res = mysql_store_result(conn);
if (res) {
MYSQL_ROW row;
while ((row = mysql_fetch_row(res))) {
for (unsigned int i = 0; i < mysql_num_fields(res); i++) {
std::cout << (row[i] ? row[i] : "NULL") << "\t";
}
std::cout << std::endl;
}
mysql_free_result(res);
}
}
}
void executeQuery_select(const char* query, std::unordered_map<std::string, std::vector<std::string>>& data) {
if (mysql_query(conn, query)) {
std::cerr << "QUERY FAILED: " << mysql_error(conn) << std::endl;
std::cerr << "Неверный запрос в БД: " << query << std::endl;
} else {
MYSQL_RES *res = mysql_store_result(conn);
if (res) {
MYSQL_ROW row;
unsigned int num_fields = mysql_num_fields(res);
MYSQL_FIELD *fields = mysql_fetch_fields(res); // Получаем метаданные колонок
// Инициализируем векторы для каждого поля
for (unsigned int i = 0; i < num_fields; i++) {
data[fields[i].name] = std::vector<std::string>();
}
while ((row = mysql_fetch_row(res))) {
for (unsigned int i = 0; i < num_fields; i++) {
// Заполняем векторы соответствующими значениями
if (row[i]) {
data[fields[i].name].push_back(row[i]);
} else {
data[fields[i].name].push_back("NULL");
}
}
}
mysql_free_result(res);
}
}
}
// std::string value = data[0]["column_name"]; // Получение значения из первой строки для поля "column_name"
void executeQuery_select1(const char* query, std::unordered_map<int, std::unordered_map<std::string, std::string>>& data) {
if (mysql_query(conn, query)) {
std::cerr << "QUERY FAILED 1: " << mysql_error(conn) << std::endl;
std::cerr << "Неверный запрос в БД: " << query << std::endl;
} else {
MYSQL_RES *res = mysql_store_result(conn);
if (res) {
MYSQL_ROW row;
unsigned int num_fields = mysql_num_fields(res);
MYSQL_FIELD *fields = mysql_fetch_fields(res); // Получаем метаданные колонок
int row_index = 0; // Индекс для каждого ряда
while ((row = mysql_fetch_row(res))) {
std::unordered_map<std::string, std::string> row_map;
for (unsigned int i = 0; i < num_fields; i++) {
if (row[i]) {
row_map[fields[i].name] = row[i];
} else {
row_map[fields[i].name] = "NULL";
}
}
// Добавляем ассоциативный массив в основной map по индексу
data[row_index] = row_map;
row_index++; // Увеличиваем индекс для следующей строки
}
mysql_free_result(res);
}
}
}
bool executeQuery_insert(const char* query) {
if (mysql_query(conn, query)) {
std::cerr << "Error: " << mysql_error(conn) << std::endl;
std::cerr << "Неверный запрос в БД: " << query << std::endl;
return false; // Запрос не выполнен успешно
}
return true; // Запрос выполнен успешно
}
std::string AddSlashes(const std::string& input) {
std::string escaped;
for (char c : input) {
if (c == '\\' || c == '\'' || c == '"' || c == ';' || c == '/' || c == '%') {
escaped += '\\'; // Добавляем обратный слэш перед спецсимволами
}
escaped += c; // Добавляем текущий символ к результирующей строке
}
return escaped;
}
std::string AddSlashes_bash(const std::string& input) {
std::string escaped;
for (char c : input) {
if (c == '\\' || c == '\'' ) {
escaped += '\\'; // Добавляем обратный слэш перед спецсимволами
}
escaped += c; // Добавляем текущий символ к результирующей строке
}
return escaped;
}
~Database() {
if (conn) {
mysql_close(conn);
}
}
private:
Database() : conn(nullptr) {} // Приватный конструктор
Database(const Database&) = delete; // Запрет копирования
Database& operator=(const Database&) = delete; // Запрет присваивания
MYSQL *conn;
};
int mariadb() {
Database& db = Database::getInstance();
sqlDB sql_init_struct;
if (!db.connect(sql_init_struct.sql_host.c_str(), sql_init_struct.sql_login.c_str(), sql_init_struct.sql_passwd.c_str(), sql_init_struct.sql_db.c_str())) {
std::cerr << "Ошибка при подключении к базе данных." << std::endl;
return EXIT_FAILURE;
}
// Пример запроса к базе данных
//db.executeQuery("SELECT * FROM your_table;");
//std::unordered_map<std::string, std::vector<std::string>> resultData;
//const char* query = "SELECT * FROM your_table"; // Замените на свой запрос
//db.executeQuery_select(query, resultData);
// Пример вывода результатов
//for (const auto& [key, values] : resultData) {
// std::cout << key << ": ";
// for (const auto& value : values) {
// std::cout << value << " ";
// }
// std::cout << std::endl;
//}
// Создаем пример данных
// std::unordered_map<std::string, std::vector<std::string>> resultData = {
// {"key1", {"value1a", "value1b"}},
// {"key2", {"value2a"}},
// {"key3", {"value3a", "value3b", "value3c"}}
// };
return EXIT_SUCCESS;
}
Если сборка проекта только make командойто, перед компиляцией необходимо добавить в MakefileКод: Выделить всё
make -j$(nproc)
Код: Выделить всё
# Пути к библиотекам и заголовочным файлам INCLUDES = -I/usr/include/mariadb/mysql LIBS = -L/usr/lib/mysql -lmariadb -lmysqlcppconn -lmysqlclient_r -pthread
Если сборка проекта cmake и make командамито, перед компиляцией необходимо добавить в CMakeLists.txtКод: Выделить всё
cmake . make -j$(nproc)
в этом случае (Makefile будет создан автоматичеки) "имя_проекта" в CMakeLists.txt замените на своё, как указано в project(имя_проекта)Код: Выделить всё
#MySQL # Добавьте include директорию target_include_directories(имя_проекта PRIVATE /usr/include/mariadb/mysql) # Укажите путь к библиотекам (если необходимо) target_link_directories(имя_проекта PRIVATE /usr/lib/mysql) # Линковка библиотек target_link_libraries(имя_проекта mariadb mysqlcppconn mysqlclient_r pthread )
Пример подключения и использования библиотеки mariadb.hpp в проект.cppЕсли сборка проекта из командной строки:Код: Выделить всё
g++ -std=c++11 -o исполняемый_файл проект.cpp -I/usr/include/mariadb/mysql -L/usr/lib/mysql -lmariadb -lmysqlcppconn -lmysqlclient_r -pthread
Код: Выделить всё
#include "config.hpp"
#include "mariadb.hpp"
using namespace std;
int main() {
mariadb();
Database& db = Database::getInstance();
string query = "INSERT INTO table_name (column1, column2, column3, ...) VALUES (value1, value2, value3, ...)";
if(db.executeQuery_insert(query.c_str()) )
{ ... }
return 0;
}