Re: Oracle IntregrityError and get_or_create test case -- MySQL also

10 views
Skip to first unread message

Karen Tracey

unread,
Aug 25, 2008, 12:51:02 PM8/25/08
to django-d...@googlegroups.com
On Mon, Aug 25, 2008 at 12:12 PM, Malcolm Tredinnick <mal...@pointy-stick.com> wrote:
On Mon, 2008-08-25 at 08:47 -0700, Matt Boersma wrote:
> I can wrap the execute() and executemany() calls in oracle\base.py in
> a try/except that re-raises this specific error as an IntegrityError:
>
>         try:
>             return Database.Cursor.execute(self, query,
> self._param_generator(params))
>         except DatabaseError, e:
>             # cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for
> ORA-01400.
>             if e.message.code == 1400 and type(e) != IntegrityError:
>                 e = IntegrityError(e)
>             raise e
>
> This seems to work fine, fixes the get_or_create test case, and
> doesn't require changes outside the oracle backend.  Let me know if
> you think that's acceptable.

I hadn't thought of that, but it looks like the best solution by far.
Everybody can then write natural-looking code that catches
IntegrityError without having to remember to call some custom Django
function to work around a problem they probably don't even know exists.


I just noticed that the MySQL backend also fails on this get_or_create test.  It is returning an OperationalError instead of an IntegrityError.  Looks like MySQL returns errno 1364 (ER_NO_DEFAULT_FOR_FIELD) in this case but this is not recognized as anything special in MySQLdb so it's just mapped to a general OperationalError.  I don't see a corresponding place in the mysql backend to do the sort of catch & transform you have found to do with Oracle?

Karen

Matt Boersma

unread,
Aug 25, 2008, 1:33:06 PM8/25/08
to Django developers
On Aug 25, 10:51 am, "Karen Tracey" <kmtra...@gmail.com> wrote:
> I just noticed that the MySQL backend also fails on this get_or_create
> test.  It is returning an OperationalError instead of an IntegrityError.
> Looks like MySQL returns errno 1364 (ER_NO_DEFAULT_FOR_FIELD) in this case
> but this is not recognized as anything special in MySQLdb so it's just
> mapped to a general OperationalError.  I don't see a corresponding place in
> the mysql backend to do the sort of catch & transform you have found to do
> with Oracle?

OperationalError according to PEP 249 is for "errors that are related
to the database's operation and not necessarily under the control of
the programmer, e.g. an unexpected disconnect occurs, the data source
name is not found, a transaction could not be processed, a memory
allocation error occurred during processing, etc." That doesn't seem
to fit an INSERT lacking a NOT NULL value (and no table default
value).

So at first glance, I'd say that's a bug in MySQLdb that should be
rectified so it also raises IntegrityError. And following what I just
committed in [8545], we should perhaps find a way to work around the
driver so we can rely on IntegrityError in this situation. But since
the MySQL backend isn't as customized as Oracle, there's no existing
place to trap this. We could add execute() and executemany() to a new
MySQLCursor class to fix it similarly, but as Senator Obama likes to
say, "that's above my pay grade."


> Karen
Reply all
Reply to author
Forward
0 new messages