Opened 16 years ago
Closed 13 years ago
#8740 closed Bug (invalid)
save(force_update=True) should raise a consistent exception when update is not possible
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | richard.davies@… | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
At present save(force_update=True) raises different exceptions according to database backend when update is not possible. These should be unified so that calling code is not specific to the database backend, rather like IntegrityError is already. They could be unified onto IntegrityError itself or a different new error.
I attach a patch which adds an extra test, regressiontests/save_force_update. This test assumes that save(force_update=True) would raise IntegrityError. In the trace below you can see that different database backends actually each fail with different exceptions.
$ ./runtests.py --settings=sqlite save_force_update ====================================================================== FAIL: Doctest: regressiontests.save_force_update.models.__test__.API_TESTS ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/elastic/django-dev/trunk/django/test/_doctest.py", line 2180, in runTest raise self.failureException(self.format_failure(new.getvalue())) AssertionError: Failed doctest test for regressiontests.save_force_update.models.__test__.API_TESTS File "/home/elastic/django-dev/trunk/tests/regressiontests/save_force_update/models.py", line unknown line number, in API_TESTS ---------------------------------------------------------------------- File "/home/elastic/django-dev/trunk/tests/regressiontests/save_force_update/models.py", line ?, in regressiontests.save_force_update.models.__test__.API_TESTS Failed example: try: m = ManualPrimaryKeyTest(id=2, data='Different') m.save(force_update=True) except Exception, e: if isinstance(e, IntegrityError): print "Pass" else: print "Fail with %s" % type(e) Expected: Pass Got: Fail with <class 'sqlite3.DatabaseError'> ---------------------------------------------------------------------- Ran 1 test in 0.012s FAILED (failures=1) $ ./runtests.py --settings=postgresql_psycopg2 save_force_update ====================================================================== FAIL: Doctest: regressiontests.save_force_update.models.__test__.API_TESTS ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/elastic/django-dev/trunk/django/test/_doctest.py", line 2180, in runTest raise self.failureException(self.format_failure(new.getvalue())) AssertionError: Failed doctest test for regressiontests.save_force_update.models.__test__.API_TESTS File "/home/elastic/django-dev/trunk/tests/regressiontests/save_force_update/models.py", line unknown line number, in API_TESTS ---------------------------------------------------------------------- File "/home/elastic/django-dev/trunk/tests/regressiontests/save_force_update/models.py", line ?, in regressiontests.save_force_update.models.__test__.API_TESTS Failed example: try: m = ManualPrimaryKeyTest(id=2, data='Different') m.save(force_update=True) except Exception, e: if isinstance(e, IntegrityError): print "Pass" else: print "Fail with %s" % type(e) Expected: Pass Got: Fail with <class 'psycopg2.DatabaseError'> ---------------------------------------------------------------------- Ran 1 test in 0.067s FAILED (failures=1)
Attachments (3)
Change History (10)
by , 16 years ago
Attachment: | save_force_update.diff added |
---|
comment:2 by , 16 years ago
Triage Stage: | Unreviewed → Accepted |
---|
By the way, cases where this doesn't raise an IntegrityError
are arguably bugs with the particular database wrapper. We're already getting one of this fixed in cx_Oracle
. Fixes should be made in the appropriate django/db/backends/
files so that IntegrityError
is raised.
by , 16 years ago
Attachment: | 8740_save_force_update.v2.diff added |
---|
Extra test case for force_update functionality only - can be used until we get a consistent exception
comment:3 by , 16 years ago
Forget that last attachment - turns out there's a test for force_update functionality already in modeltests/force_insert_update
by , 16 years ago
Attachment: | 8740_r8911_save_force_update.v3.diff added |
---|
Patch to modeltests/force_insert_update so that it will fail unless a consistent exception is raised
comment:4 by , 14 years ago
Severity: | → Normal |
---|---|
Type: | → Bug |
comment:7 by , 13 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
To me it seems this is no longer issue. We now check if a row was updated, if not raise a consistent error. I also tried a couple of combinations raising IntegerityErrors
on PostgreSQL, and it seems these are correctly converted to django's exception types. As Malcolm said 4 years ago, if this conversion does not happen, then it is an error in the backend, not in save().
I will close this as invalid, although I am not sure if this should be resolved as "fixed" instead, as originally this wasn't invalid...
Extra test case (note that the init.py must be created too)