Microsoft ODBC не может создать действительный дескриптор - PullRequest
0 голосов
/ 26 сентября 2018

Я использую драйвер 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.

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

После двух недель копания это оказалось некоторой проблемой управления версиями.

В конце концов, эта программа будет выполнять некоторые загрузки BCP через расширения Microsoft в libmsodbcsql.so.Оказывается, в библиотеке также есть реализации многих функций SQL*, которые не работают в этой тестовой программе.Когда я изменяю порядок ссылки так, чтобы libodbc.so был перед библиотекой расширений MSFT, чтобы загрузчик сначала находил эти реализации, программа работает нормально.

Мне интересно, почему это так, и, вероятно,указывает на что-то еще, что я делаю неправильно, что может укусить меня в будущем.Но сейчас, по крайней мере, я могу подключиться к базе данных и выполнять базовые запросы и обновления.

Спасибо тем, кто помог.

0 голосов
/ 26 сентября 2018

В Unix дескриптор не должен быть ненулевым значением для отображения диалогов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...