I tried to create a very simple application using the MySQL embedded server.
I basically took the simple example from the MySQL documentation and modified it a bit.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "mysql.h"
MYSQL *mysql;
static char *server_options[] = { "mysql_test", "--datadir=/Users/admin/libmysqldtest", "--language=/Users/admin/libmysqldtest/german", NULL };
int num_elements = (sizeof(server_options) / sizeof(char *)) - 1;
static char *server_groups[] = { "libmysqld_server", "libmysqld_client", NULL };
int main(void)
{
mysql_library_init(num_elements, server_options, server_groups);
mysql = mysql_init(NULL);
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_client");
mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);
//Do some queries here...
mysql_close(mysql);
mysql_library_end();
return 0;
}
On start-up
mysql_embedded: Unknown error 1146
is logged and InnoDB initializes.
Afterwards the app crashes at mysql_init.
Linking against libmysqld-debug I get the following error message:
Assertion failed: (argc && *argc >= 1), function handle_options, file
/Volumes/hd2/pb2/build/sb_0-3198286-1302522144.5/mysql-5.5.12/mysys/my_getopt.c, line 167
I use the static libmysqld(-debug) library distributed with the community server TAR-Archive for Mac OS X from the MySQL website (64 bit).
Related
I have recently learned MySQL and I want to implement the knowledge on how to build a C Program using MySQL database on windows. Can anyone provide me with a detailed description on which files to download and whether I need XAMPP running or not?
I have tried to read the documentation here : https://dev.mysql.com/doc/refman/8.0/en/c-api-implementations.html . However , I couldn't figure out for my life how to do it on Windows.(Seems pretty easy for Linux, unfortunately I do not have a Linux machine)
It would be great if someone would provide me with a detailed and step by step explanation. Thanks in advance.
I know how the code would look like.
#include <stdio.h>
#include <stdlib.h>
#include <my_global.h>
#include <mysql.h>
typedef struct
{
char host[20];
char user[25];
char pass[50];
}DB_CONN_PARAMS;
MYSQL * connect_db(DB_CONN_PARAMS *params)
{
MYSQL *connection = mysql_init(NULL);//init connection
if (connection == NULL)
{//check init worked
fprintf(stderr, "%s\n", mysql_error(connection));
exit(EXIT_FAILURE):
}
//connect:
if (mysql_real_connect(
connection,
params->host,
params->user,
params->pass,
NULL,0,NULL,0)
==NULL)
{//connection failed?
fprintf(stderr, "%s\n", mysql_error(connection));
mysql_close(connection);
exit(EXIT_FAILURE):
}
return connection;
}
int main()
{
MYSQL *db;
DB_CONN_PARAMS *params = calloc(1,sizeof(DB_CONN_PARAMS));
//just an alternative way of passing connection params, find a struct easier
params->host = "127.0.0.1";
params->user = "root";
params->pass = "mySuperSecretPass";
MYSQL * connect_db(DB_CONN_PARAMS *params);
db = connect_db(params);
//we don't need the struct anymore
free(params);
params = NULL;
//do stuff
mysql_close(db);//close connection, of course!
return EXIT_SUCCESS;
}
I just need help with the setup.
I'm trying to connect to a MySQL database on localhost from within a UDF written in C.
I created a user defined function, provided it to the MySQL DB as shared object in the plugin folder and made the UDF available:
CREATE FUNCTION test_udf RETURNS INTEGER SONAME 'test_udf.so';
That means I can use:
SELECT test_udf();
As test_udf() is called, it should connect to the database on localhost, SELECT data from the database, process the data and return an Integer Value if successful.
This works perfectly under Mac OSX but there is no chance for me to get this working under CentOS 7. As soon as the UDF tries to connect to the DB on localhost I get the error:
Can't connect to MySQL server on 'localhost'
Of course I did a proper setup of my.cnf and took care about the firewall settings.
Does anybody have an idea? Has anybody ever tried something like this?
This code compiles both on Mac and CentOS perfectly using gcc.
gcc $(mysql_config —cflags —include —libs) -shared -fPIC -o test_udf.so test_udf.c
/// DEBUG MODE FOR IDE (comment out if UDF need´s to be compiled using gcc from commandline) ///////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//#define DEBUG //<---------- COMMENT OUT IF COMPILATION AS SHARED OBJECT
//#define LINUX
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/***********************************************************************************************************************
* MySQL udf function prototypes
*
* for STRING functions:
* ++++++++++++++++++++++
* char *xxx(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length,char *is_null,
* char *error);
*
* for INTEGER functions:
* ++++++++++++++++++++++
* long long xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
*
* for REAL functions:
* ++++++++++++++++++++++
* double xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
*
* for DECIMAL functions:
* ++++++++++++++++++++++
* DECIMAL functions return string values and should be declared the same way as STRING functions.
* ROW functions are not implemented.
*
* Initialization / Deinitialization
* +++++++++++++++++++++++++++++++++
* The initialization and deinitialization functions are declared like this:
* my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
* void xxx_deinit(UDF_INIT *initid);
*
***********************************************************************************************************************/
/***********************************************************************************************************************
* UDF global defines (needed for debug & UDF BOTH!)
***********************************************************************************************************************/
#define QUERY_1 "SELECT * FROM test_table"
/***********************************************************************************************************************
* UDF global defines (needed for debug & UDF)
***********************************************************************************************************************/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef DEBUG
#define DEBUG_ON 1 // Debugging mode is on -> for testing in IDE
#else
/***********************************************************************************************************************
* automatic UDF function name generation
***********************************************************************************************************************/
#define DEBUG_ON 0 // Debugging mode is of when compiled as shared object
#define UDF_RETURN_TYPE my_ulonglong // the return value type <---------- TYPE IN RETURN VALUE TYPE
#define UDF_FCT_NAME test_udf // the UDF function name <---------- TYPE IN UDF FUNCTION NAME
#define INIT_FCT_NAME test_udf_init // the UDF init function name <---------- TYPE IN UDF INIT FUNCTION NAME
#define DEINIT_FCT_NAME test_udf_deinit // the UDF deinit function name <---------- TYPE IN UDF DEINIT FUNCTION NAME
#endif
/***********************************************************************************************************************
* Includes
***********************************************************************************************************************/
#ifdef DEBUG
#include <stdio.h>
#include <stdlib.h>
#ifndef LINUX
#include "include/mysql.h"
#else
#include "mysql/mysql.h"
#endif
#include <string.h>
#include "my_mysql_header.h"
#else
#include "my_mysql_header.h"
#ifdef STANDARD
/* STANDARD is defined, don't use any mysql functions */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef __WIN__
typedef unsigned __int64 ulonglong;/* Microsofts 64 bit types */
typedef __int64 longlong;
#else
typedef unsigned long long ulonglong;
typedef long long longlong;
#endif /*__WIN__*/
#else
#include <my_global.h>
#include <my_sys.h>
#if defined(MYSQL_SERVER)
#include <m_string.h>/* To get strmov() */
#else
/* when compiled as standalone */
#include <string.h>
#define strmov(a,b) stpcpy(a,b)
#define bzero(a,b) memset(a,0,b)
#define memcpy_fixed(a,b,c) memcpy(a,b,c)
#endif
#endif
#include <mysql.h>
#include <ctype.h>
#endif
//#endif
#ifndef DEBUG
/***********************************************************************************************************************
* MySQL UDF function prototypes
***********************************************************************************************************************/
my_bool INIT_FCT_NAME(UDF_INIT *initid, UDF_ARGS *args, char *message);
void DEINIT_FCT_NAME(UDF_INIT *initid __attribute__((unused)));
UDF_RETURN_TYPE UDF_FCT_NAME(UDF_INIT* initid,
UDF_ARGS* args __attribute__((unused)),
char* is_null __attribute__((unused)),
char* error __attribute__((unused)));
#endif
/***********************************************************************************************************************
* Other function prototypes
***********************************************************************************************************************/
/***********************************************************************************************************************
* Other functions
***********************************************************************************************************************/
int finish_with_error(MYSQL *con)
{
mysql_close(con);
return 1;
}
/***********************************************************************************************************************
* MySQL udf function definitions
***********************************************************************************************************************/
#ifdef DEBUG
int main ()
{
#else
my_bool INIT_FCT_NAME(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if(!(args->arg_count == 0)) {
strcpy(message, "No Arguments expected!");
return 1;
}
return 0;
}
void DEINIT_FCT_NAME(UDF_INIT *initid __attribute__((unused)))
{
}
UDF_RETURN_TYPE UDF_FCT_NAME(UDF_INIT* initid,
UDF_ARGS* args __attribute__((unused)),
char* is_null __attribute__((unused)),
char* error __attribute__((unused)))
{
#endif
MYSQL *con = mysql_init(NULL);
if (con == NULL)
{
fprintf(stderr, "%s\n", mysql_error(con));
exit(1);
}
if (mysql_real_connect(con, ADDRESS, USER, PASSWORD, DATABASE, 0, NULL, 0) == NULL)
{
finish_with_error(con);
}
if (mysql_query(con, QUERY_1))
{
finish_with_error(con);
}
MYSQL_RES *result = mysql_store_result(con);
if (result == NULL)
{
finish_with_error(con);
}
/*
* UDF CODE GOING HERE!
*/
mysql_free_result(result);
mysql_close(con);
return 0;
}
Okay finally i figured out how to get this working.
1) Added mysql_options before connect:
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"client");
2) Changed from mysql_query to mysql_real_query
mysql_real_query(&mysql, "select * from new_schema.new_table", 34);
3) Set my.cnf to:
[client]
port=3306
socket=/var/lib/mysql/mysql.sock
4) Use 127.0.0.1 instead of "localhost" in mysql_real_connect function, else the socket configured won´t be used
I am currently working on a project where I have to count runners. At some point, I have to transfer the data from my local Database (mysqlLocal) to the one of the High School I'm working in (mysqlLycee).
I think doing this was a good idea, but for some reason I have a segfault when executing the program.
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <mysql.h>
int main(int argc, char *argv[]){
MYSQL mysqlLocal;
MYSQL_RES *result = NULL;
MYSQL_ROW row;
char requete[150];
int num_champs;
char noParticipant[5];
char kmParcourus[3];
mysql_init(&mysqlLocal);
if(!mysql_real_connect(&mysqlLocal,"127.0.0.1","root","debianCCF","localCCF",0,NULL,0))printf("Error on first connect");
sprintf(requete,"SELECT NO_PARTICIPANT, KMPARCOURUS FROM PARTICIPANTS WHERE NO_COURSE = %s",argv[5]);
if(!mysql_query(&mysqlLocal,requete))printf("Error on first query");
result = mysql_use_result(&mysqlLocal);
num_champs=mysql_num_fields(result);
mysql_close(&mysqlLocal);
MYSQL mysqlLycee;
mysql_init(&mysqlLycee);
if(!mysql_real_connect(&mysqlLycee,argv[1],argv[2],argv[3],argv[4],0,NULL,0))printf("Error on second connect");
int i;
while ((row = mysql_fetch_row(result))){
unsigned long *lengths;
lengths = mysql_fetch_lengths(result);
for(i=0;i<num_champs;i++){
if(i==0)sprintf(noParticipant,"%.*s", (int) lengths[i], row[i] ? row[i] : "NULL");
if(i==1)sprintf(kmParcourus,"%.*s", (int) lengths[i], row[i] ? row[i] : "NULL");
}
sprintf(requete,"UPDATE PARTICIPANTS SET KMPARCOURUS=%s WHERE NO_PARTICIPANT=%s",kmParcourus,noParticipant);
if(!mysql_query(&mysqlLycee,requete))printf("Error on second query");
}
mysql_free_result(result);
mysql_close(&mysqlLycee);
return 0;
}
I'm working on Debian 8, and compiling with the following command :
gcc updateLycee.c -o updateLycee -lmysqlclient -L/usr/lib64/mysql -I/usr/include/mysql;
EDIT: added mysql checks, but still segfault when starting the program.
You close your connection to the local database, and then later try to fetch rows from a result set associated with that connection. That will not work.
If you want to transfer data from one DB to the other then you must either
first slurp all the wanted data from one DB into memory (fetch all the rows and store the contents you need in ordinary arrays, for instance), OR
hold connections to both databases open at the same time.
I work on a C tool, in which I need to manipulate and query process-internal data intensively.
Hence, I've decided to use the MySQL C API on Embedded mode, so I can have an embedded DB for each running process of my tool, and use all the SQL features on it.
All the MySQL C API tutorials I've found over the web, deal with connecting to a running server, which is not my case.
There are some examples for working with Embedded mode in Oracle's MySQL website, but they are not simple, and it's hard to make them work.
Q: Can someone please point me or write me a short example for initiating a DB using MySQL C API on Embedded mode?
Thanks!
After a lot of tries, finally answering to myself and sharing it with you:
Create a central data directory that would be used for storing DBs. In this example, I'll use /tmp/mysql_embedded_data
> mkdir /tmp/mysql_embedded_data
Create a C file, as in the following example:
#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);
}
Compile your file (I assume in this example that my C filename is /tmp/mysql_try.c)
gcc /tmp/mysql_try.c -o /tmp/mysql_try -lz `mysql_config --include --libmysqld-libs`
Run your compiled program:
> /tmp/mysql_try
When your program returnes, ensure that the DB creation succeeded. We named our sample DB aNewDatabase, so we'll check if it now has a directory inside the data directory we created -> We'll check if the directory /tmp/mysql_embedded_data/aNewDatabase was created:
> ls /tmp/mysql_embedded_data/aNewDatabase
db.opt
Enjoy!
Does anyone know why the following would cause a segmentation fault when run?
#include <mysql.h>
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
printf("MySQL client version : %s\n", mysql_get_client_info());
MYSQL *conn=NULL;
mysql_init(conn);
char *server = "localhost";
char *user = "root";
char *password = "pass";
char *database = "weather";
char *table ="room_temp";
char *tst_qry="INSERT INTO `weather`.`room_temp` (`idx`, `date`, `temperature`) VALUES (NULL, CURRENT_TIMESTAMP, '10')";
mysql_real_connect(conn, server, user, password, database, 0, NULL, 0);
}
I complied as follows
gcc -o mysql $(mysql_config --cflags) mysql.c $(mysql_config --libs)
The output was as follows,
MySQL client version : 5.5.31
Segmentation fault
Please help!
The allocated new object isn't stored in your code. Hence you are passing the NULL to mysql_real_connect().
Change this line:
mysql_init(conn);
to:
conn = mysql_init(conn);
or rather directly:
conn = mysql_init(NULL);
You're passing a NULL-pointer to mysql_real_connect. According to the documentation mysql_init returns an initialized MYSQL object (when passed a NULL-pointer). Change your code either to this to use the return value:
conn = mysql_init(conn);
or this, to have mysql_init fill the object:
MYSQL conn; /* note that this isn't a pointer */
mysql_init(&conn);
...
mysql_real_connect(&conn, ...);