0x_Anakin
0x_Anakin

Reputation: 3269

Simple C++ connection to mysql database

I just started with c++, after reading some tutorials I'm trying to create a simple myqsl connection with a database. Keep in mind that I'm mainly a web developer hence this is a new thing for me. My current code (taken from a tutorial) is this:

#include <mysql.h>
#include <stdio.h>
#include <stdlib.h>
//#include <string>

using namespace std;

struct connection_details
{
    char *server;
    char *user;
    char *password;
    char *database;
};

MYSQL* mysql_connection_setup(struct connection_details mysql_details) {

    MYSQL *connection = mysql_init(NULL);

    if (!mysql_real_connect(connection,mysql_details.server, mysql_details.user, mysql_details.password, mysql_details.database, 0, NULL, 0)) {
      printf("Conection error : %s\n", mysql_error(connection));
      exit(1);
    }

    return connection;
}

MYSQL_RES* mysql_perform_query(MYSQL *connection, char *sql_query) {

   if (mysql_query(connection, sql_query)) {
      printf("MySQL query error : %s\n", mysql_error(connection));
      exit(1);
   }

   return mysql_use_result(connection);
}

int main() {

  MYSQL *conn;      // the connection
  MYSQL_RES *res;   // the results
  MYSQL_ROW row;    // the results row (line by line)

  struct connection_details mysqlD;

  mysqlD.server = "localhost";  // line 46
  mysqlD.user = "root";         // line 47
  mysqlD.password = "root";     // line 48
  mysqlD.database = "backseat"; // line 49

  conn = mysql_connection_setup(mysqlD);

  res = mysql_perform_query(conn, "show tables"); // line 53

  printf("MySQL Tables in mysql database:\n");

  while ((row = mysql_fetch_row(res)) !=NULL)
      printf("%s\n", row[0]);


  mysql_free_result(res);
  mysql_close(conn);

  return 0;
}

however g++ gives me the followign warning:

main.cpp:46:19: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
main.cpp:47:17: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
main.cpp:48:21: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
main.cpp:49:21: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
main.cpp:53:48: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

Which is beyond my understanding at the time being, although the program works. What I did in order to remove the warning was the following:

char s[] = "localhost";
char u[] = "root";
char p[] = "root";
char d[] = "backseat";

and then

mysqlD.server = s;
mysqlD.user = u;
mysqlD.password = p;
mysqlD.database = d;

That took care of the warning but I assume there must be a better way & explanation on how I should take care of this. Moreover I tried to use:

struct connection_details
{
    string *server;
    string *user;
    string *password;
    string *database;
};

But that didn't take care the warning on line 53 plus all hell broke loose after doing this. My question is how should I be approaching simple mysql connection, why did those warnings came up and was it a bad idea to use strings in the struct?

I'm sorry for the long post, but I'm on a learning curve here and there a lot of things to take in.

PS: Any good tutorials / guides will be appreciated. Thank you.

Upvotes: 0

Views: 703

Answers (1)

flyx
flyx

Reputation: 39688

You're missing some basics. I don't know about good tutorials to link to, but I'll explain what you're doing wrong:

First of all, when you're writing C++, you should use string rather than char*. You should read up the details of char*; it's a pointer and handling it is therefore significantly different from handling a string.

What happens in your code is that you assign the address of a string literal like "localhost" to a char* (because it's a pointer). The problem is, gcc converts string literals to constants, which are read-only (as the warning tells you). The type char* however implies that the contents of the string can be changed. Change the type to const char* to get rid of the warning.

Here's some code to illustrate the issue:

char* a;
const char* b;

a = "foo";
b = "bar";

a[0] = 'a'; // you're changing the constant string!
b[0] = 'b'; // compiler error; b is const

a = "foz"; // both allowed because you're not changing
b = "baz"; // the string, but only the pointer

The easier option is to use string:

struct connection_details
{
    string server;
    string user;
    string password;
    string database;
}

You shouldn't use pointers here. string manages the low-level memory stuff internally. Now the problem is that you're using the C-level MySQL binding, which expects char* rather than string. To call it when you're using strings in your code, use c_str() for conversion:

connection.server.c_str()

and so on.

Alternatively, you might want to use a higher-level C++ API to connect to MySQL. If you're learning C++, you'll be better off avoiding C APIs if possible. There is, for example, MySQL++, but I don't know it and therefore cannot recommend it. A higher-level API is provided by SOCI, which works with multiple database backends (including MySQL).

Upvotes: 1

Related Questions