Bug #45378 SQLDriverConnect can't connect to DB with connection string
Submitted: 8 Jun 2009 16:11 Modified: 24 May 2010 12:23
Reporter: York Lo Email Updates:
Status: Closed Impact on me:
Category:Connector / ODBC Severity:S2 (Serious)
Version:5.1.5 OS:Linux (RedHat EL v3)
Assigned to: CPU Architecture:Any

[8 Jun 2009 16:11] York Lo
If the program is invoked by root user, SQLDriverConnect() can't use user name and password from connection string to connect to database.  The following is the error from connection:
retcode=-1, DriverConnect Failed.
SQLDriverConnect failed with ret=0, errText=[MySQL][ODBC 5.1 Driver]Access denied for user 'root'@'localhost' (using password: NO).

However, if user and password information is defined in the odbc.ini file, then it has no problem to connect to db.

More strangely, if the program is invoked by a normal user, SQLDriverConnect can use user and password information from the connection string to connect to DB.

The test system I used is:
uname -a
Linux nc-linux1 2.4.21.-27.EL #1 Wed Dec 1 22:08:15 EST 2004 i686 i686 i386 GNU/Linux

Also, I have the following relevant softwares:
MySQL: 5.1.31 MySQL Community Server
MySQL Connector/ODBC: 5.1.5
unixODBC: 2.2.14 (only libodbcint.so library).

How to repeat:
The following is the simple test program to repeat the problem on my linux system:
#include <stdio.h>
#include <sqltypes.h>
#include <sql.h>
#include <sqlext.h>

int main() {
  SQLHENV henv;
  SQLHDBC hdbc;
  SQLHSTMT hstmt;
  SQLRETURN retcode;
  SQLPOINTER rgbValue;
  int i = 5;
  rgbValue = &i;

  SQLCHAR connStr[] = {"dsn=MyODBC; user=nervectr; password=nervectr;"};

  SQLCHAR OutConnStr[255];

  // Allocate environment handle
  retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);

  // Set the ODBC version environment attribute
  if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
    retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0); 

    // Allocate connection handle
    if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
      retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); 

      // Set login timeout to 5 seconds
      if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
	SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)(rgbValue), 0);

	retcode = SQLDriverConnect( // SQL_NULL_HDBC

	// Allocate statement handle
	if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {               
	  retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); 

	  // Process data
	  retcode = SQLGetInfo(hdbc, SQL_DATABASE_NAME, OutConnStr, 255, &OutConnStrLen);
	  printf ("ret=%d, SQLGetInfo: retStr=%s. \n", retcode, OutConnStr);

	  if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
	    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);

	else {
	  printf("retcode=%d, DriverConnect Failed.\n", retcode);

	  SQLCHAR sqlstate[255];
	  SQLINTEGER nativeErrorPtr;

	  retcode = SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, sqlstate, &nativeErrorPtr, OutConnStr, 255, &OutConnStrLen);
	  printf("SQLDriverConnect failed with ret=%d, errText=%s.\n", retcode, OutConnStr);

	SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
The above program is compiled with the following command:
g++ -ggdb -lodbc test.cpp

The odbc.ini file contains the following information:
[ncdev@nc-linux1 odbctest]$ cat /opt/OSInc/db/unixODBC/etc/odbc.ini
[ODBC Data Sources]
MyODBC          = MyODBC 5.1.5 Driver DSN
Driver          = /opt/OSInc/db/mysqlODBC/lib/libodbc.so
Description     = MyODBC 5.1.5 Driver DSN
SERVER          = localhost
PORT            = 4000
Database        = nervecenter
OPTION          = 3
SOCKET          = /opt/OSInc/db/mysql/data/mysql.sock
TraceFile       = /opt/OSInc/db/odbc.trace
Trace           = On
Driver          = /opt/OSInc/db/mysqlODBC/lib/libodbc.so
Description     = MyODBC 5.1.5 Driver DSN
SERVER          = localhost
PORT            = 4000
Database        = nervecenter
SOCKET          = /opt/OSInc/db/mysql/data/mysql.sock
TraceFile       = /opt/OSInc/db/odbc.trace
Trace           = On

Thank you very much to look at this problem.  If you need any additional information, please let me know.
[10 Jun 2009 7:24] Tonci Grgin
Hi York and thanks for your report.

Just a few quick questions. Does "normal" user have the *same* name as MySQL user? Are you sure you have only libodbcinst library? It appears to me your compile command would failed in that case...
[10 Jun 2009 13:43] York Lo
Hi Tonci,

Normal user is not the same as MySQL user.  In my testing case, the "normal" user is ncdev, and MySQL's user is nervectr.

For compiling/linking, it is used the libs from /usr/local/lib.  To ensure that I am using the right libs, I modified the g++ command line as following:
g++ -ggdb -L/opt/OSInc/db/lib -lodbc -lodbcinst test.cpp

after compile, the following is the ldd result:
ldd a.out
        libmyodbc5-5.1.5.so => /opt/OSInc/db/lib/libmyodbc5-5.1.5.so (0x00627000)
        libodbcinst.so.1 => /opt/OSInc/db/lib/libodbcinst.so.1 (0x00838000)
        libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0x00da9000)
        libm.so.6 => /lib/tls/libm.so.6 (0x00b44000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00fc7000)
        libc.so.6 => /lib/tls/libc.so.6 (0x00111000)
        libdl.so.2 => /lib/libdl.so.2 (0x003cf000)
        libcrypt.so.1 => /lib/libcrypt.so.1 (0x00249000)
        libnsl.so.1 => /lib/libnsl.so.1 (0x00f15000)
        libpthread.so.0 => /lib/tls/libpthread.so.0 (0x003f4000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00517000)

Again, if I am invoking the program as root, I am still getting the same error as I had reported.

Are you able to see the same problem?

Thank you for all helps.

[10 Jun 2009 13:59] Tonci Grgin
Thanks for info provided, looking into this.
[16 Jun 2009 12:04] Jess Balint
fix + test

Attachment: bug45378.diff (text/x-diff), 3.08 KiB.

[13 Aug 2009 21:27] Jess Balint
This needs an additional fix to prevent a problem when the value is only spaces:
=== modified file 'util/installer.c'
--- util/installer.c    2009-06-16 11:58:20 +0000
+++ util/installer.c    2009-08-13 21:26:24 +0000
@@ -953,7 +953,7 @@

     /* remove trailing spaces on value (not escaped part) */
     len = end - split - 1;
-    while (split[len] == ' ' && split[len+1] != '}')
+    while (end > split && split[len] == ' ' && split[len+1] != '}')
[25 Feb 2010 4:39] Russell Levy
I am getting a strange error on W2K on a connection string that works perfectly in XP, Vista, 7, etc. When I removed the spaces between semicolons and the next attribute from connection string, it worked.

Even though I was not connecting to localhost, the error message was "Can't connect to MySQL server on 'localhost'". Would I be correct to assume that this patch will correct the problem?
[25 Feb 2010 9:26] Lawrenty Novitsky
yes, that is correct assumption.
[24 May 2010 12:23] Tony Bedford
An entry has been added to the 5.1.7 changelog:

If an application was invoked by the root user, SQLDriverConnect() was not able to use the username and password in the connection string to connect to the database.