M
M
Mercury132021-02-09 14:37:28
MinGW
Mercury13, 2021-02-09 14:37:28

ODBC/Win32 library failed, which MSYS package should be rolled back?

Here is the simplest project. Qt 5.12.2 (not important though), MinGW/MSYS compiler is fresh.

It compiles and works under Win64. Under Win32 after updating MSYS does not find ODBC libraries (it used to work!).

debug/main.o: in function `Z11listDriversPv':
undefined reference to `SQLDriversW'

...and so on through all the ODBC functions.

Which MSYS package should be rolled back to make it work?
.PRO
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp

DEFINES += SQL_WCHART_CONVERT

LIBS += -lodbc32


.CPP
// SQLDriverConnect_ref.cpp
// compile with: odbc32.lib user32.lib
#include <windows.h>
#include <sqlext.h>
#include <iostream>

#define DEFDRIVER L"DRIVER={MySQL ODBC 5.3 Unicode Driver}"

enum {
    BUFF_LENGTH = 1024
};


void listDrivers(SQLHENV henv)
{
    SQLWCHAR nameBuffer[BUFF_LENGTH];
    SQLWCHAR descBuffer[BUFF_LENGTH];
    SQLSMALLINT nameBufferLength = 0;
    SQLSMALLINT descBufferLength = 0;
    SQLRETURN ret = SQLDrivers(henv, SQL_FETCH_FIRST, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
    while (ret == SQL_SUCCESS) {
        std::wcout << nameBuffer << std::endl;
        ret = SQLDrivers(henv, SQL_FETCH_NEXT, nameBuffer, BUFF_LENGTH, &nameBufferLength, descBuffer, BUFF_LENGTH, &descBufferLength);
    }
}


int main() {
   SQLHENV henv;
   SQLHDBC hdbc;
   SQLHSTMT hstmt;
   SQLRETURN retcode;

   SQLWCHAR OutConnStr[255];
   SQLSMALLINT OutConnStrLen;

   HWND desktopHandle = GetDesktopWindow();   // desktop's window handle

   // 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);

         listDrivers(henv);

         // 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( // SQL_NULL_HDBC
               hdbc,
               desktopHandle,
               (SQLWCHAR*)DEFDRIVER,
               _countof(DEFDRIVER),
               OutConnStr,
               255,
               &OutConnStrLen,
               SQL_DRIVER_COMPLETE );

            // 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);
            }

            SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
         }
      }
      SQLFreeHandle(SQL_HANDLE_ENV, henv);
   }
   std::wcout << OutConnStr << std::endl;
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Mercury13, 2021-02-09
@Mercury13

Wrong, but very interesting mechanism will hide under the spoiler.

I repeat, this is not true!
1. *.dll → *.def
c:\msys64\mingw32\bin\gendef.exe odbc32.dll
2. *.def → *.a
c:\msys64\mingw32\bin\dlltool.exe --dllname odbc32.dll --input-def odbc32.def --output-lib libodbc32_merc.a
win32-g++: {
    contains(QMAKE_HOST.arch, x86_64):{
        # x64
        LIBS += -lodbc32
    } else {
        LIBS += -lodbc32_merc
    }
}

And what you need is to pull it out of MinGW ODBC for Windows (c:\msys64\mingw32\i686-w64-mingw32\include\) and correct #include so that it takes from the current directory, and not from the standard one.
// SqlUnglitch.h
#ifdef _WIN32
  #include "SqlWin/sql.h"
  #include "SqlWin/sqlext.h"
#else
  #include <sql.h>
  #include <sqlext.h>
#endif

Reason: MSYS has its own ODBC library with blackjack and whores. Under Win64, according to the calling conventions, it matched, but under Win32, it didn't. For some reason, with -O0 it somehow works, but with -O1 it no longer works.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question