Skip to content
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

Inconsistent error tuples #1206

Open
nick-rossi opened this issue Apr 21, 2023 · 2 comments
Open

Inconsistent error tuples #1206

nick-rossi opened this issue Apr 21, 2023 · 2 comments

Comments

@nick-rossi
Copy link

I'm using pyodbc to perform tasks to insert data in sql server database. I wanted to catch certain errors and it looks like the error tuples generated do not follow a consistent structure. This makes it harder to handle errors dynamically in code.

For example:

pyodbc.IntegrityError: ('23000', "[23000] [Microsoft][ODBC SQL Server Driver][SQL Server]Violation of UNIQUE KEY constraint 'UC_EventId'. Cannot insert duplicate key in object 'table. (2627) (SQLExecDirectW); [23000] [Microsoft][ODBC SQL Server Driver][SQL Server]The statement has been terminated. (3621)")

pyodbc.ProgrammingError: ('The SQL contains 16 parameter markers, but 15 parameters were supplied', 'HY000')

So IntegrityError has structure: (code, message) and ProgrammingError has structure (message, code) .

I wanted to do something in python like:

handle_errors = ["23000", "HY000"]
if ex.args[0] in recoverable_errors:
    do_something()

But this will not work as intended because of pyodbc's inconsistent error tuple structure. For the above example, the ProgrammingError code will be overlooked.

@mkleehammer
Copy link
Owner

That is a problem. Also, I'd rather be able to get at the SQLSTATE directly via ex.sqlstate.

I wanted to end the 4.x line, but I would consider swapped constructor parameters a serious enough error to put out another release. I'll try to complete it this weekend.

@RobertLD
Copy link

RobertLD commented Aug 9, 2023

I'm having what I think to be related issue if only slightly. I'm handling errors returned from PYODBC dynamically as a way to map to HTTP Status in an API. In SQLSERVER I have a ID check as follows

  begin
        ; throw 51000, 'The Role does not exist.', 1;
  end;

Docs on throw: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql?view=sql-server-ver16

and from this pyodbc returns
[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]The Role does not exist. (51000) (SQLExecDirectW)
in args[1].

I'd greatly appreciate some way to get the error-code (51000) out from the ProgrammingError object returned from pyodbc, seperate from the SQLSTATE itself. Currently I have a hack in place that relies on regex and that is less than ideal. What are your thoughts @mkleehammer?

Here is a link to the code that is related to this behavior I'm reporting

PyObject* RaiseErrorV(const char* sqlstate, PyObject* exc_class, const char* format, ...)

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

3 participants