Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedded MariaDB C/C++ API

Tags:

c

mysql

mariadb

I'm trying to get an embedded MariaDB (i.e. not connecting to running server) setup going but I'm failing to get any of the examples I find to work.

The most recent example I have is from this post https://stackoverflow.com/a/24548826/400048

When the app runs it produces: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) The docs https://mariadb.com/kb/en/library/embedded-mariadb-interface/ isn't much help on this.

For convenience the code from that StackOverflow post is:

#include <my_global.h>
#include <mysql.h>

int main(int argc, char **argv) {  
    static char *server_options[] = {
                                   "mysql_test", // An unused string 
                                    "--datadir=/tmp/mysql_embedded_data", // Your data dir
                                    NULL };
    int num_elements = (sizeof(server_options) / sizeof(char *)) - 1;

    static char *server_groups[] = { "libmysqld_server",
                                     "libmysqld_client", NULL };


    // Init MySQL lib and connection    
    mysql_library_init(num_elements, server_options, server_groups);
    MYSQL *con = mysql_init(NULL);

    if (con == NULL) {
        fprintf(stderr, "%s\n", mysql_error(con));
        exit(1);
    }

    mysql_options(con, MYSQL_READ_DEFAULT_GROUP, "libmysqld_client");
    mysql_options(con, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);

    // Connect to no host/port -> Embedded mode
    if (mysql_real_connect(con, NULL, NULL, NULL, NULL, 0, NULL, 0) == NULL) {
        fprintf(stderr, "%s\n", mysql_error(con));
        mysql_close(con);
        exit(1);
    }

    // Create a sample empty DB, named "aNewDatabase"
    if (mysql_query(con, "CREATE DATABASE aNewDatabase")) {
        fprintf(stderr, "%s\n", mysql_error(con));
        mysql_close(con);
        exit(1);
    }

    // Close connection
    mysql_close(con);
    exit(0);
}

I had a cursory look at https://github.com/MariaDB/server but didn't know where to really look...or in fact what I was looking for. How does one go about getting an embedded mariadb going? I'm running on Mac OS High Sierra, MariaDB was installed with brew install mariadb --with-embedded.

UPDATE:

I'm fairly certain I'm linking to the correct lib.

ls /usr/local/lib | grep maria

MariaDB

FIND_LIBRARY(mariadb mariadb)
MESSAGE(FATAL_ERROR "BOOM ${mariadb}")

Output of which is: BOOM /usr/local/lib/libmariadb.dylib

UPDATE 2

I'm now linking to the following. Note that I started with just libmysqld and added libraries until all link errors went away. The trouble here is I may not have all the correct libs or versions.

TARGET_LINK_LIBRARIES(sql_fn /usr/local/lib/libmysqld.a)
TARGET_LINK_LIBRARIES(sql_fn /usr/local/opt/openssl/lib/libcrypto.a)
TARGET_LINK_LIBRARIES(sql_fn /usr/local/opt/openssl/lib/libssl.a)
TARGET_LINK_LIBRARIES(sql_fn /usr/local/opt/bzip2/lib/libbz2.a)
TARGET_LINK_LIBRARIES(sql_fn /usr/local/lib/liblz4.a)
TARGET_LINK_LIBRARIES(sql_fn /usr/local/opt/zlib/lib/libz.a)
TARGET_LINK_LIBRARIES(sql_fn /usr/local/opt/xz/lib/liblzma.a)
TARGET_LINK_LIBRARIES(sql_fn /usr/local/lib/libsnappy.a)

It now compiles but exits with code 6 CLion Debugger of exit stack

Process finished with exit code 6 Looking at https://stackoverflow.com/a/7495907/400048 if it's points to the same thing/is still true then exit code 6 means EX_ILLEGAL_TABLE 6, unfortunately I don't know what table that would be. The mysql_test and datadir strings passed in are valid identifiers/path.

like image 993
zcourts Avatar asked Jan 16 '18 21:01

zcourts


People also ask

What is MariaDB embedded?

MariaDB starting with 10.5. mysql_embedded is a mysql client statically linked to libmysqld, the embedded server. Upon execution, an embedded MariaDB server is instantiated and you can execute statements just as you would using the normal mysql client, using the same options.

Is MariaDB a TCP?

If your system is running a software firewall (or behind a hardware firewall or NAT) you must allow connections destined to TCP port that MariaDB runs on (by default and almost always 3306).

Can MariaDB replace MySQL?

Yes, it is possible to replace MySQL with MariaDB. MariaDB is considered to be a drop-in replacement for the corresponding MySQL version (i.e MariaDB 10.2 and MySQL 5.7). Please review feature differences between MariaDB and MySQL to make sure the switch won't affect applications using database server.

Is MySQL embedded?

MySQL has an embedded server library which can be linked directly into an application.


1 Answers

Ok first a little explanation about your example. The user is using gcc to compile and I can see you are using cmake. First what does -lz and mysql_config --include --libmysqld-libs means. The first is link zlib to link zlib in cmake you can refer to this answer, but long story short:

find_package( ZLIB REQUIRED )
if ( ZLIB_FOUND )
    include_directories( ${ZLIB_INCLUDE_DIRS} )
    target_link_libraries( sql_fn ${ZLIB_LIBRARIES} )
endif( ZLIB_FOUND )

Then you need the mariaDB library and that is the second part. mysql_config --include --libmysqld-libs this means execute the command mysql_config --include --libmysqld-libs which will return a string with the link options so execute the command:

$mysql_config --include --libmysqld-libs
-I/usr/local/mysql/include
-L/usr/local/mysql/lib  -lmysqld

And you should get an output like the one above. The -I is to look for headers in a given directory and the -L is to search a library in a directory, the -l is to link a given library it serves the same purpose as -lz only you are adding -lmysqld.

Well now that all is explained you need only include the -I -L and -l options with mysql however this is not such a standard library so you need to include directories and libraries through a script as explained in this anwer. So again long story short there is no bullet proof for this for example my library is in /usr/local/mysql/lib and yours is in /usr/local/lib. Since that is the case it will be easier to use the second method.

execute_process(COMMAND mysql_config --include
    OUTPUT_VARIABLE MYSQL_INCLUDE)
execute_process(COMMAND mysql_config --libmysqld-libs
    OUTPUT_VARIABLE MYSQL_LIBS)

target_compile_options(sql_fn PUBLIC ${MYSQL_INCLUDE})
target_link_libraries(sql_fn ${MYSQL_LIBS})

And that is all the required information you need. Now we are glad we have Cmake to make things easier for us don't we. ;) Here is my CMakeLists.txt

cmake_minimum_required(VERSION 3.6)
project(embedded_mysql)

set(CMAKE_CXX_STANDARD 14)

set(SOURCE_FILES main.cpp)
add_executable(embedded_mysql ${SOURCE_FILES})

find_package( ZLIB REQUIRED )
if ( ZLIB_FOUND )
    include_directories( ${ZLIB_INCLUDE_DIRS} )
    target_link_libraries( embedded_mysql ${ZLIB_LIBRARIES} )
endif( ZLIB_FOUND )

execute_process(COMMAND mysql_config --include
        OUTPUT_VARIABLE MYSQL_INCLUDE)
execute_process(COMMAND mysql_config --libmysqld-libs
        OUTPUT_VARIABLE MYSQL_LIBS)

string(STRIP ${MYSQL_LIBS} MYSQL_LIBS)

target_compile_options(embedded_mysql PUBLIC ${MYSQL_INCLUDE})
target_link_libraries(embedded_mysql ${MYSQL_LIBS})

You can see the code in github here

like image 186
Nord Avatar answered Nov 06 '22 00:11

Nord