Visual C++ ODBC application cannot connect to MySQL database - c++

I'm writing my first database application following a sample program the teacher given, but neither the sample, nor my own program can't connect to the database. (The JDBC sample program can, so the server should be OK).
I have these vars in the class declaration:
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLRETURN ret;
Here's the constructor of my database handler class, that's where the connection should be made:
DBModule::DBModule(string server, string database)
{
this->server = server; //"localhost" is loaded into it
this->database = database; //"test" is loaded into it, of course it exists on the server
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
command = "DRIVER={MySQL ODBC 3.51 Driver};SERVER="+this->server+";DATABASE="+this->database+";";
//command looks like this now:
//"DRIVER={MySQL ODBC 3.51 Driver};SERVER=localhost;DATABASE=test;"
ret = SQLDriverConnect(dbc, NULL, (SQLWCHAR *)command.c_str(), SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
if (!SQL_SUCCEEDED(ret)) {
err += CONNECT_DATABASE*DATABASE_UNREACHABLE;
good = false;
return;
} else {
good = true;
}
SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
command = sysToStd(DBINIT);
SQLPrepare(stmt, (SQLWCHAR *)command.c_str(), SQL_NTS);
ret = SQLExecute(stmt);
}
The ret at SQLDriverConnect gets a -1 value.
I'm using the latest XAMPP as server with all the default settings (so i'm "root" and there is no password). I've tried adding UID=root to the connection string, but it did the same.
Thanks for any help.

You probably do not have MySQL ODBC drivers installed. JDBC works because you need not "install" them: they are some .jar files that can come with Java application. If you will use ODBC then install MySQL ODBC drivers, configure connection in ODBC Manager as System DSN, then from ODBC manager check if it connects to database (most ODBC drivers I know have "test connection" button).
When such test shows you "connected" or similar, then you can test if your application connects. Your connect sting looks like:
DRIVER={MySQL ODBC 3.51 Driver};SERVER=...;DATABASE....
so according to: http://www.connectionstrings.com/mysql#p30 it looks you are trying to use MySQL Connector/ODBC 3.51
Maybe database is not listening on dafult port?

Related

Connect to SUSE using libssh

I am trying to establish a connection using libssh(https://www.libssh.org/) to a machine with SUSE Enterprise operating system installed.
ssh_options_set(tempSshSession, SSH_OPTIONS_HOST, host2Connect);
ssh_options_set(tempSshSession, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(tempSshSession, SSH_OPTIONS_PORT, &port);
int rc = ssh_connect(tempSshSession);
if(rc != SSH_OK) {
printf("Error connecting to the localhost\n");
exit(-1);
}
// Authorized by the password.
rc = ssh_userauth_password(tempSshSession, username, password);
After ssh_userauth_password() call it returns the response : "SSH_AUTH_DENIED: Authentication failed: use another method"
It works fine for operating systems like: Ubuntu, Linux Generic and CentOS.
Thanks
Check /etc/ssh/sshd_config. You should find PermitRootLogin forced-command-only somewhere there. Set that to yes and your problem should be gone. Please keep in mind that there is a reason, why folks have decided to not allow per default root user/pass logins.

SQL bulk copy for native clients causes access violation

I have a windows application that does a bulk copy of data to an SQL table, using the bcp_xxx() functions and a standard "SQL Server" ODBC connector.
I want to move to supporting native SQL client connections
According to what I have seen, all I need to do is add
#define _SQLNCLI_ODBC_
#include <sqlncli.h>
to the top of the cpp file, and link against "sqlncli10.lib" rather than "odbcbcp.lib."
However, when I call bcp_bind(), I get "Access violation reading location 0xffffffffffffffff"
This happens with both "SQL server" and "SQL Native Client" ODBC connections.
The code being executed is:
SQLHANDLE hEnv;
SQLHANDLE hConnection;
LPCBYTE data = (LPCBYTE)malloc(100);
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hConnection);
SQLSetConnectAttr(hConnection, SQL_COPT_SS_BCP, (void *)SQL_BCP_ON, SQL_IS_INTEGER) ;
SQLConnect(hConnection, "DSN", SQL_NTSL, NULL, 0, NULL, 0);
bcp_init(hConnection, "DB_TABLE", NULL, NULL, DB_IN);
bcp_bind(hConnection, data, 0, SQL_VARLEN_DATA, (LPCBYTE)"", 1, SQLCHARACTER, 1);
The problem appears to be due to using "SQL server" ODBC connections at the same time as the bulk copy routines are trying to use native connections.
If I change all other ODBC connections to be SQL Native, the bulk copy routines work correctly.

SQL statement much slower from ODBC than in T-SQL

I have a C/C++ DLL that is connecting to SQL and issuing a large number of ODBC queries rapidly in a loop. The only thing is that it is turning out to be so much slower from the ODBC DLL than running the query from T-SQL in Management Studio. Many orders of magnitude slower.
At first I thought it might be the query itself, but then I stripped it down to a simple "select NULL" and still got the same results.
I was wondering if this is expected or whether there is some ODBC setting that I am missing or getting wrong?
First I connect like this (for brevity I have omitted all error checking, however, retcode is returning SQL_SUCCESS in all cases):
char *connString = "Driver={SQL Server};Server=.\\ENT2012;uid=myuser;pwd=mypwd";
...
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_UINTEGER);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (void*)5, 0);
retcode = SQLDriverConnect(
hdbc,
0,
(SQLTCHAR*) connString,
SQL_NTS,
connStringOut,
MAX_PATH,
(SQLSMALLINT*)&connLen,
SQL_DRIVER_COMPLETE);
Then I prepare the statement, bind a parameter (unused in this example), and bind a column like this:
char queryString = "select NULL;";
SQLLEN g_int32 = 4;
SQLLEN bytesRead = 0;
...
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt)
retcode = SQLPrepare(hstmt, queryString, SQL_NTS);
retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
SQL_C_LONG, SQL_INTEGER, sizeof(int), 0, spid, 0, (SQLLEN*)&g_int32))
retcode = SQLBindCol(hstmt, 1, SQL_C_CHAR, col_1, 32, &bytesRead);
Finally, I repeatedly call the query (e.g., 10000 times) in a loop like this:
retcode = SQLExecute(hstmt);
retcode = SQLFetch(hstmt);
SQLCloseCursor(hstmt);
This takes about 90 seconds to run 10000 times in the ODBC DLL. Testing on a 4 core Windows 2008 R2 Server running SQL 2012 x64.
On the other hand, if I run, what looks to me to be, an equivalent test in Management Studio, it takes less than a second:
declare #sql varchar(128), #repeat int;
set #repeat = 10000;
set #sql = 'select NULL;';
while #repeat > 0 begin
exec(#sql);
set #repeat = #repeat - 1;
end;
Can someone point out something that I am overlooking? Some flaw in my logic?
Thanks.
Neil Weicher
www.netlib.com
This is too long for a comment
declare #sql varchar(128), #repeat int;
set #repeat = 10000;
set #sql = 'select NULL;';
while #repeat > 0 begin
exec(#sql);
set #repeat = #repeat - 1;
end;
does not realistically simulate the same as 10000 remote calls. exec bypasses a lot of the internals of setting up a request. To simulate 10000 calls do this in SSMS:
select NULL;
go 10000
and measure. Output as text probably should be used to avoid timing around SSMS grid display.
I'm not all that familiar with the T-SQL stuff but here are a couple things to consider.
Your ODBC driver has to transfer data via your network and I suspect the T-SQL execution does not. Next to disk IO, transfering data on the network is one of the slowest things your ODBC driver will have to do. You may find that the driver is spending considerable time either waiting on the data to travel to clearing data off the wire.
Also, it's not clear to me that your T-SQL example actually moves and data but your ODBC example does when SQLFetch is called. The T-SQL may just be executing the query and never fetching any data. So, removing SQLFetch from the loop might be a more equal comparison.
To see if data transfer is your limiting factor estimate how much data will be included in all the records you fetch with ODBC and try to move that much data between the two machines with something like FTP. An ODBC driver will never be able to fetch data faster than a simple raw transfer of data. I see you are just fetching NULL so not much in your result set but the driver and database still transfer data between them to service this request. Could be several hundred bytes per execution\fetch.
I faced the same issue. I solved it by changing the "Cursor Default Mode" setting of the DSN for the ODBC driver (through the ODBC Administrator tool) from "READ_ONLY" to "READ_ONLY_STREAMING". This alone increased the speed of my application (query data and write them to file) from 260 seconds to 51 seconds using Java 32-bit and from 1234 seconds to 11 seconds using C++.
See this post: http://www.etl-tools.com/forum/visual-importer/1587-question-about-data-transformation-memory-usage?start=6

How to access a DB2 database with ODBC from a separate thread?

I have a DB2 database in my CentOS 6.5 64 bit machine and have installed ODBC drivers to access the database from my C++ application.
I am using SQL CLI APIs to fetch the data from the database.
If I fetch the data from my main() function of the C++ application, SQL CLI APIs work fine (e.g. SQLAllocHandle) and I am able to read/write data from the database.
If I try to do the same operation on my POSIX thread, SQL CLI APIs fail to initialize the handle and eventually read/write fails.
SQLRETURN sqlrc = SQL_SUCCESS;
SQLCHAR pszSqlState[100];
SQLINTEGER pfNativeError[100];
SQLCHAR pszErrorMsg[100];
SQLSMALLINT cbErrorMsgMax;
SQLSMALLINT pcbErrorMsg;
/* allocate an environment handle */
sqlrc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_hEnv);
if (sqlrc != SQL_SUCCESS)
{
return 1;
}
sqlrc = SQLGetDiagRec(SQL_HANDLE_ENV, m_hEnv, 1, pszSqlState, pfNativeError, pszErrorMsg, 100, &pcbErrorMsg);
/* set attribute to enable application to run as ODBC 3.0 application */
sqlrc = SQLSetEnvAttr(m_hEnv,
SQL_ATTR_ODBC_VERSION,
(void*)SQL_OV_ODBC3,
0);
/* allocate a database connection handle */
sqlrc = SQLAllocHandle(SQL_HANDLE_DBC, m_hEnv, &m_hDBconn);
sqlrc = SQLGetDiagRec(SQL_HANDLE_DBC, m_hEnv, 1, pszSqlState, pfNativeError, pszErrorMsg, 100, &pcbErrorMsg);
/* connect to the database */
sqlrc = SQLConnect(m_hDBconn,
(SQLCHAR *)db1Alias, SQL_NTS,
(SQLCHAR *)user, SQL_NTS,
(SQLCHAR *)pswd, SQL_NTS);
//sqlrc = SQLGetDiagRec(SQL_HANDLE_DBC, m_hDBconn, 1, pszSqlState, pfNativeError, pszErrorMsg, 100, &pcbErrorMsg);
return sqlrc;
I am using Eclipse / IBM Data Studio for development.
I googled for known issues without any luck.
How to access a DB2 database with ODBC from a separate thread?
Info :
The first APi
SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_hEnv )
returns SUCCESS but the value of m_hEnv is invalid (-ve value).
So the subsequent APIs return -2 which is SQL_INVALID_HANDLE .
Call to
SQLSetEnvAttr(m_hEnv,SQL_ATTR_ODBC_VERSION,(void *)SQL_OV_ODBC3, 0);
returns -2 SQL_INVALID_HANDLE .
The problem was, my application which uses SQL CLI code was not compiled using -D_REENTRANT flag.
Now I am able to use the SQL APIs inside my threads. Thanks all for your inputs.

connect to mssql on linux via odbc

I connected MSSQL (on windows) via odbc on linux redhat 64bit.
Below is odbc and freetds configuration files.
freetds.conf:
[FreeTDS]
host=172.21.32.20
port=1433
tds version=7.2
client charset = GB2312
odbcinst.ini:
[TDS]
Description = TDS
Driver = /usr/local/lib/libtdsodbc.so
Trace = Yes
TraceFile=/tmp/odbcinst.log
UsageCount = 1
odbc.ini:
[SQLSERVER]
Driver = TDS
Description = sql server dsn
Trace = NO
Server = 172.21.32.20
Database = Live
Port = 1433
TDS_Version = 7.2
TraceFile=/tmp/sqlserver.log
Snippets:
QString f3ErpDsn = QString::fromLocal8Bit("Driver={SQLSERVER};server=172.21.32.20;database=Live;uid=inp;pwd=inp;");
QSqlDatabase f3ErpDb= QSqlDatabase::addDatabase("QODBC");
f3ErpDb.setDatabaseName(f3ErpDsn);
// f3ErpDb.setDatabaseName("SQLSERVER");
f3ErpDb.setUserName("inp");
f3ErpDb.setPassword("inp");
QString sqlCmdStr = "select * from dbo.Table_Drilling_Data01 where status=1";
if ( ! f3ErpDb.open() )
{
qDebug() << f3ErpDb.lastError().text();
return 1;
}
QSqlTableModel model;
model.setTable("dbo.Table_Drilling_Data01");
model.setFilter("status=3");
model.select();
qDebug() << model.lastError().text();
Error messages:
f3ErpDb.setDatabaseName(f3ErpDsn);
If setDatabaseName is f3ErpDsn error message is:
"QODBC3: Unable to connect", "[unixODBC][Driver Manager]Data source name not found, and no default driver specified")
I had defined SQLSERVER in odbc.ini. Why it can not find it?
But if I changed f3ErpDb.setDatabaseName("SQLSERVER");, error message is:
"[FreeTDS][SQL Server]The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 1 (""): Data type 0x00 is unknown. QODBC3: Unable to execute statement"
It makes me confounded, could anybody help me?
I'm not sure what QSqlDatabase is. But it seems that you have improper SQL connection string.
Try something like this:
UID=inp;PWD=inp;DSN=SQLSERVER;database=Live;SERVER=AMIN\SQLEXPRESS;charset=UTF-8
DSN=SQLSERVER because SQLSERVER is the only DSN which defined in your odbc.ini
SERVER=AMIN\SQLEXPRESS - try Windows name of SQL Server, not host's IP address (I'm not sure that IP is not allowed here, but Windows name is 100% working)
I had the same problem and I solve it when I changed TDS protocol to 8.0, it was at 7.0 before. I've used freetds, unixodbc, via Qt to connect to MSSQL database.