9

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.

zcourts
  • 4,863
  • 6
  • 49
  • 74
  • One question, did the `/tmp/mysql.sock` exists...if not, then try to create a new one with `touch /tmp/mysql.sock` and then try to run again your app. – Hackerman Jan 26 '18 at 13:03
  • Creating the file does change the error msg from: `Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)` to `Can't connect to local MySQL server through socket '/tmp/mysql.sock' (38)`. Not much else I'm afraid. – zcourts Jan 26 '18 at 19:24
  • @zcourts: Are you linking with libmysqlclient.a or with libmysqld.a ? – Mark Benningfield Jan 27 '18 at 00:07
  • `libmariadb.dylib`, which is not the client if the file name is anything to go by. – zcourts Jan 27 '18 at 00:32
  • @zcourts: Do you have `libmysqld.a` on your system? – Mark Benningfield Jan 27 '18 at 16:43
  • Yes there is. `➜ ~ find /usr/local/lib -name "libmysqld.*"` results in `/usr/local/lib/libmysqld.a` as one of the results – zcourts Jan 28 '18 at 00:10
  • `Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)` tells you that the UNIX domain socket `/tmp/mysql.sock` is not around. `Can't connect to local MySQL server through socket '/tmp/mysql.sock' (38)` tells you that `/tmp/mysql.sock` is not a (UNIX domain) socket, which makes sense if you created it via `touch`, because `touch` creates a file, not a (UNIX domain) socket. – alk Jan 28 '18 at 15:22
  • @zcourts: Did you try linking to `libmysqld.a` (as in `-lmysqld`)? – Mark Benningfield Jan 28 '18 at 20:32
  • @MarkBenningfield - I've updated the post after linking to `libmysqld.a` instead of `libmariadb` – zcourts Jan 31 '18 at 16:28
  • @zcourts: The image you posted looks like the abort is a result of an OS error when creating a file. Did you try building and running the simple test code that is posted in your OP? – Mark Benningfield Jan 31 '18 at 16:55
  • @MarkBenningfield I'm running the simple test from the OP mostly unmodified. The only change is the includes I have are #include #include #include – zcourts Jan 31 '18 at 17:23
  • 2
    @zcourts: Well, we're about to run out of room on this comment thread (comments are not meant for extended discussion). Set a breakpoint in the debugger and make sure the connection is created. If it is, then you know that the server is live, and that the problem is in creating the file, which is really up to the OS, not the server. – Mark Benningfield Jan 31 '18 at 17:40
  • @zcourts: I read all your question sorry about the previous misunderstandings. I read the other example and your problem is while linking the library can you post CMakeLists.txt – Nord Feb 02 '18 at 00:21

1 Answers1

5

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

Nord
  • 253
  • 2
  • 6
  • Nord, thanks for the detailed answer. Can I ask which OS did you try this on? It builds as in my example but still exits with code 6. Following @Mark's last comment `mysql_library_init` is where the exit happens and the dir is /tmp so I don't think it's a file/permission issue. My next step will be to try building in a VM Centos/Ubuntu etc so if you let me know which OS you used, I'll try to use the same. – zcourts Feb 02 '18 at 15:48
  • I did it in OS X Sierra, I don't remember the exact build but will update it as soon as I am on my mobile computer. I changed the directory to one I had privileges with my user for example /Users//tmp/embbeded and it worked. it send a warning but ended with exitcode 0. The table is created at the directory I specified. I don't remember how I installed MariaDB. Maybe it has something to do with your installation of MariDB. – Nord Feb 02 '18 at 16:29
  • I'm using Sierra as well. Did you link to the actual MySQL or MariaDB? Was it installed with homebrew or some other means? – zcourts Feb 02 '18 at 16:33
  • 1
    I remember now. I used MySQL since installing MariaDB in OS X was a hassle. I have "myql Ver 14.14 Distrib 5.6.23, for osx10.8 (x84_64) using EditLine wrapper" but it should be the same I checked the MariaDB documentation. OS X High Sierra 10.13.2. – Nord Feb 02 '18 at 16:47
  • 1
    ok. I got it working. I went through my `/usr/local` and manually deleted all libs it depends on, as well as clearing out all header files from `includes`. rebuilt your version and it failed with exit code 6 as before, then I created the data dir and chmod it (reflecting on @ MarkBenningfield's comments then your version worked. I went back, made sure the dir exists and tried my original and that also worked. Ultimately I think I had a messed up lib installed. The data dir definitely existed before after Mark's comments and I still got exit code 6. Works now though, thanks again! – zcourts Feb 02 '18 at 20:37