I am trying to figure out why ODBC connection to the database is not working, I wrote code (the top part) and commented out the source code of another program. That is working completely fine and the driver window pops up asking me to select the database / etc. I've been looking at this for over 20 mins now and my code (in my eyes) is COMPLETELY the same, but doesn't work. So I would like to have a fresh set of eyes to look at this and let me know if something is different than the commented out part.
Thanks <3
case IDB_LOGIN:{
SQLHENV SQLEnviroment = NULL;
SQLHDBC SQLConnection = NULL;
if (SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &SQLEnviroment) != SQL_SUCCESS) {
MessageBox(NULL, NULL, NULL, NULL);
}
if (SQLSetEnvAttr(SQLEnviroment, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0) != SQL_SUCCESS)
{
MessageBox(NULL, NULL, NULL, NULL);
}
if (SQLAllocHandle(SQL_HANDLE_DBC, SQLEnviroment, &SQLConnection) != SQL_SUCCESS) {
MessageBox(NULL, NULL, NULL, NULL);
}
if (SQLDriverConnect(SQLConnection, GetDesktopWindow(), L"DRIVER={SQL DRIVER}; Server=LIVINGTREE; Database=Application Database;Uid=AdminNick;Pwd=spawn1234;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_PROMPT) == SQL_SUCCESS_WITH_INFO) {
MessageBox(NULL, L"Connected!", NULL, MB_OK);
}
//SQLHENV hEnv = NULL;
//SQLHDBC hDbc = NULL;
//SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
//
//SQLSetEnvAttr(hEnv,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,0);
//SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
//SQLDriverConnect(hDbc,
// GetDesktopWindow(),
// L"Driver={SQL Server};Server=.\\LIVINGTREE;Database=Application Database;Uid=AdminNick; Pwd=spawn123;",
// SQL_NTS,
// NULL,
// 0,
// NULL,
// SQL_DRIVER_COMPLETE);
break;
}
Related
I have been trying to insert a row into my SQL table, i get no syntax error but unfortunately when i check my table in the SQL Server Management Studio, no new entry is added. When debugging, the retCode becomes less than zero starting from the SQLConnect() function.
int main()
{
SQLHANDLE SQLEnvHandle = NULL;
SQLHANDLE SQLConnectionHandle = NULL;
SQLHANDLE SQLStatementHandle = NULL;
SQLRETURN retCode = 0;
// Insert Query
char SQLQuery[] = "insert into crm.dbo.company_name values (22,'01 electronics','#01electronics.net');";
// SQL Server Identifier
char SQLServer[] = "DRIVER={SQL Server}; SERVER=localhost, 8000; DATABASE=xxxx; UID=xxxx_xxxx; PWD=xxxx;";
do
{
// Allocate environment
retCode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &SQLEnvHandle);
// Set ODBC Version
retCode = SQLSetEnvAttr(SQLEnvHandle, SQL_ATTR_ODBC_VERSION,(SQLPOINTER*)SQL_OV_ODBC3, 0);
// Allocate Connection
retCode = SQLAllocHandle(SQL_HANDLE_DBC, SQLEnvHandle, &SQLConnectionHandle);
// Set Login Timeout
retCode = SQLSetConnectAttr(SQLConnectionHandle, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
// Set Auto Commit
retCode = SQLSetConnectAttr(SQLConnectionHandle, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)TRUE, 0);
// Connect to DSN
retCode = SQLConnect(SQLConnectionHandle, (SQLCHAR*) SQLServer, SQL_NTS, (SQLCHAR*)NULL, 0, NULL, 0);
// Allocate Statement Handle
retCode = SQLAllocHandle(SQL_HANDLE_STMT, SQLConnectionHandle, &SQLStatementHandle);
// Prepare Statement
retCode = SQLPrepare(SQLStatementHandle, (SQLCHAR*)SQLQuery, SQL_NTS);
// Execute Statement
if (SQLExecute(SQLStatementHandle) == SQL_SUCCESS || SQLExecute(SQLStatementHandle) == SQL_SUCCESS_WITH_INFO)
cout << "SUCCESS";
else
cout << "FAILURE";
} while (FALSE);
// Frees the resources and disconnects
SQLFreeHandle(SQL_HANDLE_STMT, SQLStatementHandle);
SQLDisconnect(SQLConnectionHandle);
SQLFreeHandle(SQL_HANDLE_DBC, SQLConnectionHandle);
SQLFreeHandle(SQL_HANDLE_ENV, SQLEnvHandle);
getchar();
}
When debugging, the retCode becomes less than zero starting from the SQLConnect() function.
From the docs:
When SQLConnect returns SQL_ERROR or SQL_SUCCESS_WITH_INFO, an
associated SQLSTATE value can be obtained by calling SQLGetDiagRec
with a HandleType of SQL_HANDLE_DBC and a Handle of ConnectionHandle
I have the following code (using ODBC to connect to an SQL database):
The connection is OK and also the first SQL_ExecuteQuery(), but the second and third SQL_ExecuteQuery() will return with an error (returncode -1 for SQLExecDirect).
I assume, that the "statement handle hstmt" will be overwritten after the first execution. But how can I avoid this? Thank you so much.
SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc = SQL_NULL_HDBC;
SQLHDBC hstmt= SQL_NULL_HSTMT;
SQLRETURN retcode = SQL_SUCCESS;
//Connect function
int SQL_Connect()
{
SQLWCHAR OutConnStr[255];
SQLSMALLINT OutConnStrLen;
// 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)5, 0);
retcode = SQLDriverConnect( hdbc,
NULL,
#ifdef IPC
(SQLWCHAR *)L"DSN=TEST;Description=ODK;UID=FFF;PWD=XXX;Trusted_Connection=No;DATABASE=DDD;",
#else
(SQLWCHAR *)L"DSN=ODKSQL64;Description=ODK;UID=auto;PWD=Visu_KDbos;Trusted_Connection=No;DATABASE=Giesserei_BKO;",
#endif
SQL_NTS,
OutConnStr,
255,
&OutConnStrLen,
SQL_DRIVER_NOPROMPT);
// Allocate statement handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
cout<<"Verbindung OK"<<std::endl;
}
}
}
}
return retcode;
}
//Disonnect function
int SQL_Disconnect ()
{
SQLFreeHandle(SQL_HANDLE_STMT, hstmt );
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return 1;
}
//Query function
int SQL_ExecuteQuery()
{
short rc;
char material[50];
SQLINTEGER strlenmaterial;
//prepare query
std::wstring SQL_Statement = L"SELECT blablabla";
rc = SQLExecDirect(hstmt, const_cast<SQLWCHAR*>(SQL_Statement.c_str()), SQL_NTS);
if (rc==SQL_SUCCESS || rc==SQL_SUCCESS_WITH_INFO) {
SQLBindCol(hstmt, 1, SQL_C_CHAR, &material, (SQLINTEGER) sizeof(material), &strlenmaterial);
while (1) {
rc = SQLFetch(hstmt);
if (rc==SQL_SUCCESS || rc==SQL_SUCCESS_WITH_INFO) {
rc = 1;
}else {
break;
}
}
} else {
//no data found
rc = 3;
}
return rc;
}
int main()
{
short rc;
rc = SQL_Connect();
rc = SQL_ExecuteQuery();
rc = SQL_ExecuteQuery();
rc = SQL_ExecuteQuery();
rc = SQL_Disconnect();
return 0;
}
You can re-use a HSTMT handle, but before running a new query, you need to close the pending cursor. As you are binding the columns using SQLBindCol, you also need to unbind the columns, before binding them again.
In your SQL_ExecuteQuery(), before returning from the function call:
SQLFreeStmt(hstmt, SQL_UNBIND)
SQLFreeStmt(hstmt, SQL_CLOSE)
Now you are ready to execute another query, bind again and fetch the result.
Note that you could also change the logic of your program, and bind only once, and then skip the unbind-step: If you know that you are always interested in the result of the same column, you could bind the column before executing the query. You can then execute the query, read the result, call SQLFreeStmt with the SQL_CLOSE option and start over with executing the query.
See here for more details:
https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlfreestmt-function
I am trying to read a large object from a PostgreSQL database using ODBC from Visual Studio C++. I can't get it to work.
The driver is PostgresSQL ANSI(x64) 9.50.04.00.
The data type of the column is lo, created with:
CREATE DOMAIN lo AS oid;
The column contains the object ids of the large objects.
My understanding is that when the driver sees a lo type, it will handle it as SQL_LONGVARBINARY.
However, the query fails. The diagnostics message is:
HY003 [Microsoft][OBDC Driver Manager] Program type out of range
Here is the code with the noise removed:
wchar_t* connect0 = L"DSN=picdb;";
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLLEN sqllen = -1;
PBYTE image = new BYTE[0];
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);
SQLDriverConnect(dbc, NULL, connect0, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
SQLExecDirect(stmt, L"select lo from image_list where id=964945", SQL_NTS);
SQLFetch(stmt);
SQLGetData(stmt, 1, SQL_LONGVARBINARY, image, 0, &sqllen); //<----- It fails here
image = new BYTE[sqllen];
SQLGetData(stmt, 1, SQL_LONGVARBINARY, image, sqllen, &sqllen);
SQLDisconnect(dbc);
SQLFreeHandle(SQL_HANDLE_DBC, dbc);
SQLFreeHandle(SQL_HANDLE_ENV, env);
I can read regular data from the database just fine. And I can read the BLOB data from the database with Java/JDBC, but I need it to work in C++.
Why do I get the error, and what can I do to fix it?
This seems to work:
wchar_t* connect0 = L"DSN=picdb;";
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLLEN sqllen = -1;
PBYTE image = new BYTE[0];
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);
SQLDriverConnect(dbc, NULL, connect0, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
SQLExecDirect(stmt, L"select lo from image_list where id=964945", SQL_NTS);
SQLFetch(stmt);
SQLGetData(stmt, 1, SQL_C_BINARY, image, 0, &sqllen);
image = new BYTE[sqllen];
SQLBindParameter(stmt, 1, SQL_PARAM_OUTPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 0, 0, image, sqllen, NULL );
SQLGetData(stmt, 1, SQL_C_BINARY, image, sqllen, &sqllen);
SQLDisconnect(dbc);
SQLFreeHandle(SQL_HANDLE_DBC, dbc);
SQLFreeHandle(SQL_HANDLE_ENV, env);
How to make this to read from custom string the information
I would like to read Host,User,Password,Database from the custom string, how can i do that?
Also another problem here in code is that it show that is connected with ODBC , but it doesnt read anything from database
GetPrivateProfileStringA("SQL","Host","127.0.0.1",szServer2,sizeof(szServer2),SQL_PATH);
GetPrivateProfileStringA("SQL","User","sa",szUser,sizeof(szUser),SQL_PATH);
GetPrivateProfileStringA("SQL","Password","12345",szPassword,sizeof(szPassword),SQL_PATH);
GetPrivateProfileStringA("SQL","Database","DbName",szDatabase,sizeof(szDatabase),SQL_PATH);
BOOL SQLCONNECT::Connect()
{
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLRETURN ret;
SQLSMALLINT columns;
int row = 0;
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN */
SQLDriverConnectW(dbc, NULL, L"DRIVER={SQL Server};SERVER=(local);DATABASE=DbName;UID=sa;PWD=password;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
/* Check for success */
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt))
{
MessageBoxA(0, "Failed to connect to Database!", "Error", MB_OK);
}
std::cin.get();
return FALSE;
}
I am using C++ ODBC to connect to a local SQL Server.
Once I have attempted to make connecton to the server; Is there a way to validate that the connection was indeed successful?
Here is a sample of my code, which delegates the connection handles and makes the connection:
//Allocate the pre-connection handles
this->sReturn = SQL_SUCCESS;
this->sReturn = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &this->eHandle);
this->sReturn = SQLSetEnvAttr(this->eHandle, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3_80), 4);
SQLAllocHandle(SQL_HANDLE_DBC, this->eHandle, &this->cHandle);
//Connect to the database
this->sReturn = SQLConnect(this->cHandle, reinterpret_cast<SQLWCHAR*>(serverName), SQL_NTS, NULL, 0, NULL, 0);
According to MSDN, the return values of SQLConnect() are:
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR, SQL_INVALID_HANDLE, or SQL_STILL_EXECUTING.
So I'm assuming SQL_SUCCESS or SQL_SUCCESS_WITH_INFO indicate the connection was indeed successful.
If by "validate", you mean something other than just looking at the return code, I would imagine any subsequent call using the connection would fail if for some reason the connection were no longer valid.
Here's a code example from the same MSDN site - note they check for success OR success with info:
// Connect to data source
retcode = SQLConnect(hdbc, (SQLCHAR*) "NorthWind", SQL_NTS, (SQLCHAR*) NULL, 0, NULL, 0);
// Allocate statement handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
// Process data
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}
SQLDisconnect(hdbc);
}