Basically, I am trying to connect to a MySQL Database using Connector C drivers for MySQL. I am writing the code in Netbeans on a Linux system. But here is the mystery: I can connect to my database in Debug Mode, but not Release Mode??? I am using Netbeans as my IDE on Linux, and I set up all the libraries and include folders using the dropdown under project properties so it applies the properties to both the Debug Configuration and Release Configuration, and yet it will connect to the database when I execute in Debug, but not when I execute in Run - ??? I simplified the code to show you the actual connection code:
int readDB(void) {
MYSQL *mysql = NULL;
char *server = "localhost";
char *user = "root";
char *password = "";
char *database = "myDB";
int port = 3306;
mysql = mysql_init(mysql);
if (!mysql) {
puts("Init failed, out of memory?");
return EXIT_FAILURE;
} else {
puts("SUCCESS!\n");
}
if (!mysql_real_connect(mysql,server,user,password,database,port,NULL,0)) {
puts("Connect failed\n");
}
return 1;
}
So when I run it in Debug, it prints "SUCCESS" and nothing else. When I run it, it prints "SUCCESS" followed by "Connect failed". I am at a loss. Could this be a problem with the IDE? Is there another IDE for C that works well on Linux that I should consider? Or am I missing something quite obvious?
Update:
calling mysql_error() revealed
"Can't connect to local MySQL server through socket '/tmp/mysql.sock'
(2)"
When using a mysql client library in most languages including C, if the hostname is specified as localhost the client library will attempt to connect through a unix domain socket. You can force connection using TCP/IP by specifying the hostname as 127.0.0.1
Yes they are one and the same but
If unix_socket is not NULL, the string specifies the socket or named
pipe to use. Note that the host parameter determines the type of the
connection.
Alternatively you can examine your mysql configuration to find out where the socket has been created when the server starts and use that as the unix_socket parameter.
Third alternative is to change your server configuration to create the socket on /tmp/
Related
Context:
I am trying to use mySQL in my Xcode c++ project. And I have this simple program available to connect to mysql:
int main(){
if(!mysql_real_connect(&mysql, "localhost", "root", "PassWord", "DB", 0, NULL, 0)) {
printf("connecting to Mysql error:%d from %s\n",mysql_errno(&mysql), mysql_error(&mysql));
return -1;
}else {
printf("Connected Mysql successful!\n");
}
mysql_close(&mysql);
return 0;
}
However, I was able to connect to MySQL. After I ran this CML in my terminal
export DYLD_LIBRARY_PATH=/usr/local/lib
the program doesn't work anymore with the error showing:
(my code in Xcode is below:)
I got this Error in Xcode command:
I am still able to log in to mySQL in CML with
mysql -u root -p
And By Showing all port variables, the port shows shows it is running on 3306
SHOW GLOBAL VARIABLES LIKE 'PORT';
So everything is still normal in Terminal.
Also I tried to unset the DYLD_LIBRARY_PATH but got no luck.
I am wondering what is the reason to cause the problem and any possible resolutions/workaround.
I am trying to run Wordpress on Google App Engine standard environment. I have configured a Cloud SQL for MySQL Second Generation instance and can access it using Cloud SQL Proxy with this command:
cloud_sql_proxy -instances=my_project_id:us-central1:my_project=tcp:3306
The wp-config.php file:
if (isset($_SERVER['GAE_ENV'])) {
define('DB_HOST', ':/cloudsql/my_project_id:us-central1:my_project');
} else {
define('DB_HOST', '127.0.0.1');
}
Finally, I connect to the database using this:
$dbConn = mysqli_connect (DB_HOST, DB_USER, DB_PASSWORD) or die (mysqli_error($dbConn));
mysqli_select_db($dbConn, DB_NAME) or die(mysqli_error($dbConn));
This setup works perfectly from the local development environment, which is Cloud Shell. The website runs and I am able to query the database and insert records etc. My problem arises when I deploy to my_project_id.appspot.com using google app deploy. The website runs, but when I try to query the database I receive this error:
Warning: mysqli_connect(): php_network_getaddresses: getaddrinfo failed: Name or service not known in /srv/wp-content/themes/mytheme/system/db.php on line 14
Line 14 is $dbConn = mysqli_connect (DB_HOST, DB_USER, DB_PASSWORD)
so I am guessing that mysqli must not like the format of the specified DB_HOST which is :/cloudsql/my_project_id:us-central1:my_project.
In this Community Tutorial there is sample code which uses a unix socket and PDO to connect to the database. I don't know if I should be adding these lines to the app.yaml file and someone using this different connection string.
env_variables:
MYSQL_DSN: mysql:unix_socket=/cloudsql/my_project_id:us-central1:my_project;dbname=my_dbname
MYSQL_USER: username
MYSQL_PASSWORD: password
My apologies for the lengthy question, but I wanted to provide as much information as possible. Anyone have any ideas what I am doing wrong? Thanks.
It looks like you might be passing in the information incorrectly into mysqli_connect. If you take a look a the documentation for it, it actually takes in 6 parameters: host, username, passwd, dbname, port, socket.
Under host, you can read the following:
Passing the NULL value or the string "localhost" to this parameter, the local host is assumed. When possible, pipes will be used instead of the TCP/IP protocol.
Under socket, it clarifies it should be the socket path:
Specifies the socket or named pipe that should be used.
So you need to call mysqli_connect like this:
mysqli_connect (null, "user", "password", "database", 3306, "/cloudsql/<INSTANCE_CONNECTION_NAME>")
From Cloud Shell, your environment is all setup properly in order to directly connect to Cloud SQL. From AppEngine there's a few other steps necessary in order to connect.
Check out this documentation:
https://cloud.google.com/sql/docs/mysql/connect-app-engine
It should get you up and running.
The answer by #Kurtisvg is absolutely correct in terms of this being the proper format for connecting to Cloud SQL using mysqli_connect:
mysqli_connect (null, DB_USER, DB_PASSWORD, DB_NAME, 3306, "/cloudsql/<INSTANCE_CONNECTION_NAME>")
The original question, however, also mentioned that I was trying to get the connection working for a Wordpress installation. These are the two areas with additional information relevant to this tutorial on how to run Wordpress on Google App Engine standard.
1. Specifying correct mysqli_connect() parameters
Testing the app in the local development environment only required mysqli_connect to use these four parameters: DB_HOST, DB_USER, DB_PASSWORD, DB_NAME. Once the app is deployed to Google App Engine, the mysqli_connect has to use all six parameters: DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT, DB_SOCK. This is the code in db.php that provides the correct parameters, depending on the environment:
if (isset($_SERVER['GAE_ENV'])) {
$dbConn = mysqli_connect (null, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT, DB_SOCK);
} else { // local environment
$dbConn = mysqli_connect (DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
}
2. Specify correct Wordpress configuration in wp-config.php
What I was finding was that in order Wordpress to function correctly, it was necessary to not only define and use the socket DB_SOCK in mysqli_connect(), but I also had to define a DB_HOST for purposes of the Wordpress installation. This was the configuration that worked in my wp-config.php file:
define('DB_USER', 'user');
define('DB_PASSWORD', 'password');
define('DB_NAME', 'database');
define('DB_PORT', 3306);
// Check for Google App Engine Environment
if (isset($_SERVER['GAE_ENV'])) {
$onGae = true;
define('DB_HOST', ':/cloudsql/<INSTANCE_CONNECTION_NAME>');
define('DB_SOCK', '/cloudsql/<INSTANCE_CONNECTION_NAME>');
} else {
$onGae = false;
define('DB_HOST', '127.0.0.1');
}
In the above code, the variable for DB_HOST requires a full-colon : at the beginning of the socket. This DB_HOST variable is not used as one of the connection parameters of mysqli_connect when in the GAE environment. This variable does seem to be used elsewhere in Wordpress (such as setup-config.php), which is why it needs to be defined. The variable for DB_SOCK does not require the full-colon : in order to work in the GAE environment. This socket needs to be the last (6th) parameter of mysqli_connect, with the first parameter specified as null, which forces the connection to use the socket.
It took a while to get this sorted, but eventually got it working using these settings above. I wonder if anyone else had such a complicated experience as I did getting Wordpress on Google App Engine standard environment to connect to a Cloud SQL for MySQL Second Generation instance. I hope these comments help someone.
You are better off using wpdb class. Wpdb is a WordPress database access abstraction class. Check out this documentation
I am trying to troubleshoot a C program that connects to a local SQL database and then runs a series of commands. Should be SQL Coding 101... but I'm missing something fundamental. I'm working in a Linux container, which supports both the SQL server and is where my C program runs.
Some basics: Here's the Linux version:
root#1234567890:/home/me# uname -mrs
Linux 4.4.0-64-generic x86_64
root#1234567890:/home/me#
I have my SQL server running, installed from the instructions here. The service is up, and I can manually query it with SQLCMD:
root#1234567890:/home/me#
root#1234567890:/home/me# ps -ef | grep sql
root 1 0 0 15:45 ? 00:00:00 /opt/mssql/bin/sqlservr
root 8 1 0 15:45 ? 00:01:25 /opt/mssql/bin/sqlservr
root 13988 13639 0 18:38 pts/2 00:00:00 grep --color=auto sql
root#1234567890:/home/me#
root#1234567890:/home/me#
root#1234567890:/home/me# /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'Password01'
1> SELECT ##servername;
2> go
--------------------------------------------------------------------------------------------------------------------------------
abc123456789
(1 rows affected)
1>
Not sure why there are two instances of "sqlservr", but overall, the above is promising. Back when I set up the SQL server, I let it pick the default TCP port, 1433, and it looks like the service is listening there:
root#1234567890:/home/me# netstat -l
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.11:40962 *:* LISTEN
tcp 0 0 *:1433 *:* LISTEN
udp 0 0 127.0.0.11:60893 *:*
Active UNIX domain sockets (only servers)
Proto RefCnt Flags Type State I-Node Path
root#1234567890:/home/me#
Some Networking 101 troubleshooting here:
root#1234567890:/home/me# telnet 127.0.0.1 1433
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
^C
Connection closed by foreign host.
root#1234567890:/home/me#
Hmm. If my SQL server was listening on this port, would this be the response I would expect to see here? Not sure.
Now to my C code. I have the "mysqlclient" library in on my machine and it seems to be running just fine. Here's the code:
/* sqlToy.c */
#include <stdio.h>
#include "/usr/include/mysql/mysql.h"
/* Adapted from:
https://www.youth4work.com/Talent/C-Language/Forum/118317-how-do-link-database-with-in-a-c-program
*/
int main() {
MYSQL mysql;
printf("...attempting initization... ");
if(mysql_init(&mysql)==NULL) {
printf("\nInitialization error\n");
return 0;
} else {
printf("Initilization successful!\n");
}
printf("...attempting connection... ");
if(mysql_real_connect(&mysql, "localhost", "sa", "Password01", NULL, 1433, NULL, 0) == NULL){
printf("Connection error\n");
return 0;
}
mysql_close(&mysql);
return 1;
}
Here's program compilation and the output:
root#1234567890:/home/me# gcc -Wall sqlToy.c -lmysqlclient
root#1234567890:/home/me# ./a.out
...attempting initization... Initilization successful!
...attempting connection... Connection error
root#1234567890:/home/me#
The "Connection error" message pops up IMMEDIATELY, with no waiting.
I also note that when I do a "tail -f /var/opt/mssql/log/errorlog", I never see an error message when my program runs. Which makes me wonder if the C program's request is reaching the SQL server at all.
I suspect there are one of two possibilities going on here:
(A) The mysql_real_connect() command in the C code is wrong, I'm using the wrong options, the wrong flags, etc. And a failed login is not logged in /var/opt/mssql/log/errorlog.
(B) Although it looks like everything is good to go, there's some network problem. ie, the SQL server really isn't listening on 1433, something like that.
Any ideas? Thanks...
Transferring comment into an answer.
I would expect to use the MySQL client libraries (functions such as mysql_init() in your code) to connect to a MySQL database server. Similarly, I'd expect to use the SQL Server client libraries (probably ODBC plus the SQL Server driver) to connect to SQL Server.
Expecting the MySQL client library to connect to an SQL Server database is at least 'not obviously correct'. Having looked briefly at the MySQL C API documentation, I think that it is 'obviously not correct'. So, if you want to connect to SQL Server, you should probably use ODBC (and the SQL Server driver).
There's an ODBC driver for MySQL too; if you do need to connect to both SQL Server and MySQL in the same program, it might be sensible to use ODBC for both.
Generalizing, most DBMS provide several methods of connecting to the database server. For Java code, there is likely a JDBC driver; for .NET code, there might be a .NET driver, or it might use ODBC under the covers. For most other languages, the usual technique is to choose between an ODBC driver for the DBMS or the DBMS's native connectivity, which goes by many different names. You need to match the client code libraries with the database server you want to connect to. Expecting an Oracle driver to connect to DB2 is not plausible; expecting a MySQL driver to connect to SQL Server is not plausible. There may be techniques that allow such inter-connectivity, but they require great care. The ODBC infrastructure has a common, driver independent layer (driver manager) and a unique-per-DBMS, driver dependent layer. You can sometimes write code using ODBC and arrange to connect to different DBMS by having different drivers loaded concurrently.
I'm connecting to a remote MySQL server (on the default port 3306) using the C API call mysql_real_connect().
How can I discover which TCP port is used on the client host?
Is it possible to specify the port that I wish to use?
1
You can use lsof.
Type following in your shell:
$ lsof | grep TCP
And then look for the port on which your mysql server is listening.
You can also make use of netstat.
Details can be found by man netstat.
2
As far as I know, you can not.
the MYSQL structure has an FD buried in it (for me at least; tested on centos7 with mariadb 5.5.58).
you can use that to find the local address and port
struct sockaddr_in laddr;
socklen_t sb = sizeof(laddr);
if (getsockname(mysql.net.fd, (sockaddr*)&laddr, &sb) == -1)
printf("getsockname() failed, err %s\n",strerror(errno));
else
printf("local address [%x] port [%u]",ntohl(laddr.sin_addr.s_addr),ntohs(laddr.sin_port));
I have my unixodbc odbc.ini configure file like this:
[test]
Driver = /usr/local/lib/libmyodbc5-5.1.8.so
Description = Connector/ODBC 5.1.8 Driver DSN
SERVER = 127.0.0.1
PORT = 3306
USER = root
Password =
DATABASE = test
OPTION =
SOCKET =
And the problem is that it will not use the database as specified above, which is 'test'.
What I have to do is to manually execute a direct sql to change to database and run my query:
SQLExecDirect(stmt, "USE test", SQL_NTS);
SQLExecDirect(stmt, "SELECT * FROM mytable", SQL_NTS);
Any idea on how should I get rid of the 'USE test' which is a mysql command.
Why is unixodbc not setting 'test' as the default db since it's already specified in the conf file?
As on windows the driver manager (unixODBC in this case) only acts on the Driver tag, all other entries in the DSN are up to the driver to interpret. It doesn't notice there is a database= entry and know by magic that in this driver it should execute a "USE" command, and for another call SQLSetConnectAttr( SQL_ATTR_CURRENT_CATALOG ).
On my copy of the MySQL driver, it certainly uses the database= entry. However, I would check that 1. The copy of the driver you are using is built to use the unixODBC lib to access the shared config file (libodbcinst.so), or the driver is reading it directly, and is reading the same ini file as unixODBC. Possibly check with strace to see what ini is opened after the driver is loaded. Maybe try setting ODBCINI=/path/to/your/odbc.ini
[test]
Driver = /usr/local/lib/libmyodbc5-5.1.8.so
Description = Connector/ODBC 5.1.8 Driver DSN
SERVER = 127.0.0.1
PORT = 3306
USER = root
Password =
**DATABASE** = test
**OPTION** = **3**
**SOCKET** =
and can change options between 1,2 too