Skip to content

pyodbc cannot connect to ODBC 2.X drivers because it assumes ODBC 3.X #1420

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
BrooksPettit opened this issue Apr 7, 2025 · 1 comment

Comments

@BrooksPettit
Copy link

I am working with a proprietary 32 bit ODBC server application. I tried using Python 3.8.10 and pyodbc 5.2.0 to access the driver.
On connection, I get the error "[08001] [Microsoft][ODBC Driver Manager] The driver doesn't support the version of ODBC behavior that the application requested (see SQLSetEnvAttr). (0)".

Searching around led me to this stack overflow post:
https://stackoverflow.com/questions/66204772/python-connect-to-odbc-2-x-database

in which one of the answers hints that the call to SQLSetEnvAttr is an ODBC 3.X call.

I found this explanation of connection differences between 2.X and 3.X ODBC applications:
https://learn.microsoft.com/en-us/sql/odbc/reference/appendixes/behavioral-changes-and-odbc-3-x-drivers?view=sql-server-ver16

The environment attribute SQL_ATTR_ODBC_VERSION indicates to the driver whether it needs to exhibit ODBC 2.x behavior or ODBC 3.x behavior. How the SQL_ATTR_ODBC_VERSION environment attribute is set depends on the application. ODBC 3.x applications must call SQLSetEnvAttr to set this attribute after they call SQLAllocHandle to allocate an environment handle and before they call SQLAllocHandle to allocate a connection handle. If they fail to do this, the Driver Manager returns SQLSTATE HY010 (Function sequence error) on the latter call to SQLAllocHandle.

ODBC 2.x applications and ODBC 2.x applications recompiled with the ODBC 3.x header files do not call SQLSetEnvAttr. However, they call SQLAllocEnv instead of SQLAllocHandle to allocate an environment handle. Therefore, when the application calls SQLAllocEnv in the Driver Manager, the Driver Manager calls SQLAllocHandle and SQLSetEnvAttr in the driver. Thus, ODBC 3.x drivers can always count on this attribute being set.

I see in L292 and L315 of 'pyodbcmodule.cpp' that there are hard-coded calls to SQLSetEnvAttr. Therefore, I think that my driver is ODBC 2.X only, and this is why the connection will not work. I also tried setting pyodbc.odbcversion="2.X" before making any connection, but this has no effect.

Sadly, I am unable to use a 64 bit ODBC driver or a newer version of Python. I could start using older versions of Python or pyodbc. However, it's not very clear from the documentation what older version of pyodbc supports ODBC 2.X only applications, if any.

@BrooksPettit
Copy link
Author

Update:

I wound up solving my issue, which was not actually due to pyodbc.
The proprietary odbc server has some user licensing stuff. I had to add my local user to the server's configuration. Then queries would go through. The "authentication" is basically just a whitelist of local usernames... so if you're not on the list, you get obscure ODBC errors. Nice.

Anyway, happy to report I have it working in Python 3.8.10 using pyodbc 2.5.0 without having to recompile any C++.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant