Commit d095c65c authored by jan.koester's avatar jan.koester
Browse files

mariadb support

parent f6ed80cf
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -72,3 +72,37 @@ if(SQLITE3_FOUND)
    endif()
endif()

find_package(MariaDB)
if(MariaDB_FOUND)

    add_library(mariadb SHARED mariadb/mariadb.cpp)

    target_include_directories(mariadb PRIVATE
        "${CMAKE_CURRENT_SOURCE_DIR}/../include"
        "${MariaDB_INCLUDE_DIRS}"
    )

    add_definitions(-DMARIADB)

    target_link_libraries(mariadb PUBLIC dbpp PRIVATE MariaDB::MariaDB)

    set_target_properties(mariadb PROPERTIES PREFIX "")

    install(TARGETS mariadb
        RUNTIME_DEPENDENCY_SET mariadbdep
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/dbpp NAMELINK_SKIP
        RUNTIME DESTINATION bin
    )

    if(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows")
        install(
            RUNTIME_DEPENDENCY_SET mariadbdep
            DIRECTORIES
                "$<TARGET_FILE_DIR:MariaDB::MariaDB>"
            DESTINATION bin
            PRE_EXCLUDE_REGEXES   "((api|ext)-ms-.*|.*azureattest.*|vcruntime.*|ucrtbase.*|msvcrt.*|wpaxholder.*)\\.dll"
            POST_EXCLUDE_REGEXES [[.*(\\|/)system32(\\|/).*\.dll]]
        )
    endif()
endif()
+165 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Copyright (c) 2023, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#include <stdexcept>
#include <sstream>
#include <map>
#include <cstring>

#include <mysql/mysql.h>

#include "mariadb.h"

static std::map<std::string,std::string> parseConnStr(const char *constr){
    std::map<std::string,std::string> params;
    std::istringstream stream(constr);
    std::string token;
    while(std::getline(stream,token,' ')){
        auto pos = token.find('=');
        if(pos != std::string::npos){
            params[token.substr(0,pos)] = token.substr(pos+1);
        }
    }
    return params;
}

dbpp::MariaDB::MariaDB(const char *constr) {
    _dbconn = mysql_init(nullptr);
    if(_dbconn == nullptr){
        throw std::runtime_error("mysql_init failed (out of memory)");
    }

    auto params = parseConnStr(constr);

    const char *host = nullptr;
    const char *user = nullptr;
    const char *password = nullptr;
    const char *dbname = nullptr;
    unsigned int port = 0;
    const char *unix_socket = nullptr;

    if(params.count("host"))
        host = params["host"].c_str();
    if(params.count("user"))
        user = params["user"].c_str();
    if(params.count("password"))
        password = params["password"].c_str();
    if(params.count("dbname"))
        dbname = params["dbname"].c_str();
    if(params.count("port"))
        port = static_cast<unsigned int>(std::stoul(params["port"]));
    if(params.count("unix_socket"))
        unix_socket = params["unix_socket"].c_str();

    if(!mysql_real_connect(_dbconn, host, user, password, dbname, port, unix_socket, 0)){
        std::string errmsg = "Connection to database failed: ";
        errmsg += mysql_error(_dbconn);
        mysql_close(_dbconn);
        _dbconn = nullptr;
        throw std::runtime_error(errmsg);
    }
}

dbpp::MariaDB::~MariaDB(){
    if(_dbconn)
        mysql_close(_dbconn);
}

int dbpp::MariaDB::exec(const SQL &sql,DBResult &res){
    const std::lock_guard<std::mutex> lock(_mutex);

    if(mysql_real_query(_dbconn, sql.c_str(), sql.size())){
        throw std::runtime_error(mysql_error(_dbconn));
    }

    res.clear();

    MYSQL_RES *mres = mysql_store_result(_dbconn);

    if(!mres){
        if(mysql_field_count(_dbconn) == 0){
            return 0;
        }
        throw std::runtime_error(mysql_error(_dbconn));
    }

    int rcount = 0;
    int nfields = mysql_num_fields(mres);
    DBResult::Data *lastdat = nullptr;
    MYSQL_ROW row;
    unsigned long *lengths;

    while((row = mysql_fetch_row(mres))){
        lengths = mysql_fetch_lengths(mres);
        for(int i = 0; i < nfields; ++i){
            const char *val = row[i] ? row[i] : "";
            int len = row[i] ? static_cast<int>(lengths[i]) : 0;
            if(!res.firstRow){
                res.firstRow = new DBResult::Data(rcount, i, val, len);
                lastdat = res.firstRow;
            }else{
                lastdat->nextData = new DBResult::Data(rcount, i, val, len);
                lastdat = lastdat->nextData;
            }
        }
        ++rcount;
    }

    mysql_free_result(mres);

    return rcount;
}

const char *dbpp::MariaDB::getDriverName(){
    return "mariadb";
}

const dbpp::SQL &dbpp::MariaDB::autoincrement(SQL &sql){
    return (sql << "AUTO_INCREMENT");
}

const dbpp::SQL &dbpp::MariaDB::getUUIDType(SQL &sql){
    return (sql << "CHAR(36)");
}

bool dbpp::MariaDB::isConnected(){
    const std::lock_guard<std::mutex> lock(_mutex);
    return mysql_ping(_dbconn) == 0;
}

void dbpp::MariaDB::reset(){
    const std::lock_guard<std::mutex> lock(_mutex);
    mysql_ping(_dbconn);
}

EXPORT dbpp::MariaDB* create(const char *coninfo) {
    return new dbpp::MariaDB(coninfo);
}

EXPORT void destroy(dbpp::MariaDB* p) {
    delete p;
}
+57 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Copyright (c) 2023, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#include <mutex>

#include "database.h"

#pragma once

typedef struct st_mysql MYSQL;

namespace dbpp {
    class MariaDB : public DatabaseApi{
    public:
        MariaDB(const char *constr);
        ~MariaDB();

        int exec(const SQL &sql,DBResult &res) override;

        const char *getDriverName() override;

        const SQL &autoincrement(SQL &sql) override;
        const SQL &getUUIDType(SQL &sql) override;

        bool isConnected() override;

        void reset() override;

    private:
        MYSQL       *_dbconn;
        std::mutex   _mutex;
    };
}
+48 −0
Original line number Diff line number Diff line
# FindMariaDB.cmake
# Find the MariaDB client library
#
# This module defines:
#   MariaDB_FOUND        - True if MariaDB was found
#   MariaDB_INCLUDE_DIRS - Include directories
#   MariaDB_LIBRARIES    - Libraries to link
#   MariaDB::MariaDB     - Imported target

find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
    pkg_check_modules(PC_MARIADB QUIET libmariadb)
endif()

find_path(MariaDB_INCLUDE_DIR
    NAMES mysql/mysql.h mysql.h
    HINTS
        ${PC_MARIADB_INCLUDEDIR}
        ${PC_MARIADB_INCLUDE_DIRS}
    PATH_SUFFIXES mariadb mysql
)

find_library(MariaDB_LIBRARY
    NAMES mariadb mariadbclient mysqlclient
    HINTS
        ${PC_MARIADB_LIBDIR}
        ${PC_MARIADB_LIBRARY_DIRS}
)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MariaDB
    REQUIRED_VARS MariaDB_LIBRARY MariaDB_INCLUDE_DIR
)

if(MariaDB_FOUND)
    set(MariaDB_INCLUDE_DIRS ${MariaDB_INCLUDE_DIR})
    set(MariaDB_LIBRARIES ${MariaDB_LIBRARY})

    if(NOT TARGET MariaDB::MariaDB)
        add_library(MariaDB::MariaDB UNKNOWN IMPORTED)
        set_target_properties(MariaDB::MariaDB PROPERTIES
            IMPORTED_LOCATION "${MariaDB_LIBRARY}"
            INTERFACE_INCLUDE_DIRECTORIES "${MariaDB_INCLUDE_DIR}"
        )
    endif()
endif()

mark_as_advanced(MariaDB_INCLUDE_DIR MariaDB_LIBRARY)
+11 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@ Section: libs
Priority: optional
Maintainer: Jan Koester <jan.koester@tuxist.de>
Build-Depends: debhelper-compat (= 13), cmake (>= 3.18),
 libpq-dev, libsqlite3-dev, pkg-config
 libpq-dev, libsqlite3-dev, libmariadb-dev, pkg-config
Standards-Version: 4.6.2
Rules-Requires-Root: no

@@ -39,3 +39,13 @@ Description: SQLite backend for libdbpp
 architecture for backend drivers.
 .
 This package contains the SQLite backend plugin.

Package: libdbpp-mariadb
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: MariaDB backend for libdbpp
 libdbpp is a C++ database abstraction library with a plugin
 architecture for backend drivers.
 .
 This package contains the MariaDB backend plugin.
Loading