Я использую драйвер ODBC от Microsoft для подключения приложения C ++ / Linux к удаленной базе данных SQL Server, и когда я пытаюсь подключиться к базе данных, вызов завершается неудачно с SQL_INVALID_HANDLE
.Читая их документацию , я нахожу это:
SQL_INVALID_HANDLE Функция не выполнена из-за недопустимой среды, соединения, оператора или дескриптора дескриптора.Это указывает на ошибку программирования.Никакая дополнительная информация не доступна из SQLGetDiagRec или SQLGetDiagField.Этот код возвращается только в том случае, если дескриптор является нулевым указателем или имеет неправильный тип, например, когда дескриптор оператора передается для аргумента, который требует дескриптор соединения.
Достаточно справедливо, но нетВ момент создания дескрипторов и окружения перед оператором соединения я получаю какие-либо ошибки.Кроме того, для второго аргумента их документация говорит, что я могу передать нулевой указатель, если нет рабочего стола (как в случае с этим консольным приложением Linux).Вот MVCE, адаптированный из примера программы Microsoft :
#include "sql.h"
#include "sqlext.h"
#include "msodbcsql.h"
#include <iostream>
#include <string>
int main(int, char**)
{
using std::cerr;
using std::endl;
SQLHENV henv;
SQLHDBC hdbc;
HWND dhandle = nullptr; // no desktop handle in linux
SQLHSTMT hstmt;
SQLRETURN retcode;
SQLCHAR OutConnStr[255];
SQLSMALLINT OutConnStrLen;
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLAllocHandle (environment) failed " << retcode << endl;
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLSetEnvAttr failed " << retcode << endl;
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLAllocHandle (connection) failed " << retcode << endl;
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLSetConnectAttr failed " << retcode << endl;
std::string dsn = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=*.*.*,1433;DATABASE=***;UID=***;PWD=***";
retcode = SQLDriverConnect(hdbc, dhandle, (SQLCHAR*)dsn.c_str(), dsn.length(), OutConnStr, 255, &OutConnStrLen, SQL_DRIVER_PROMPT);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
cerr << "SQLDriverConnect failed " << retcode << endl;
// cleanup code redacted for brevity
return 0;
}
Программа выводит SQLDriverConnect failed -2
, то есть SQL_INVALID_HANDLE
.Я в тупике.hdbc
явно является правильным типом, и проверка его в отладчике показывает, что он не равен нулю.
Возможно, стоит отметить, что точно такая же строка соединения работает в программе Python, использующей pyodbc
.Кажется, что программа на C ++ даже не смотрит так далеко, как на эту строку.Ему просто не нравится дескриптор, который я отправляю при соединении.
В документации Microsoft четко сказано, что они не предоставляют никакой дополнительной информации.Если кто-нибудь может предоставить какое-либо руководство по диагностике / отладке, я был бы очень признателен.
Это приложение использует gcc 4.9.1 в Centos 7.