Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #12702 -- Introduced a common implementation of DatabaseError a…

…nd IntegrityError, so that database backends can (re)raise common error classes. Thanks for Waldemar Kornewald for the report.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12352 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 11ee9746a0530ec38f523fb4de44950d9b783877 1 parent 47acb1d
@freakboy3742 freakboy3742 authored
View
5 django/db/__init__.py
@@ -1,7 +1,8 @@
from django.conf import settings
from django.core import signals
from django.core.exceptions import ImproperlyConfigured
-from django.db.utils import ConnectionHandler, ConnectionRouter, load_backend, DEFAULT_DB_ALIAS
+from django.db.utils import ConnectionHandler, ConnectionRouter, load_backend, DEFAULT_DB_ALIAS, \
+ DatabaseError, IntegrityError
from django.utils.functional import curry
__all__ = ('backend', 'connection', 'connections', 'router', 'DatabaseError',
@@ -73,8 +74,6 @@
# connections['default'] instead.
connection = connections[DEFAULT_DB_ALIAS]
backend = load_backend(connection.settings_dict['ENGINE'])
-DatabaseError = backend.DatabaseError
-IntegrityError = backend.IntegrityError
# Register an event that closes the database connection
# when a Django request is finished.
View
14 django/db/backends/mysql/base.py
@@ -5,6 +5,7 @@
"""
import re
+import sys
try:
import MySQLdb as Database
@@ -24,6 +25,7 @@
from MySQLdb.converters import conversions
from MySQLdb.constants import FIELD_TYPE, FLAG, CLIENT
+from django.db import utils
from django.db.backends import *
from django.db.backends.signals import connection_created
from django.db.backends.mysql.client import DatabaseClient
@@ -82,22 +84,30 @@ def __init__(self, cursor):
def execute(self, query, args=None):
try:
return self.cursor.execute(query, args)
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
except Database.OperationalError, e:
# Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place.
if e[0] in self.codes_for_integrityerror:
- raise Database.IntegrityError(tuple(e))
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
raise
+ except Database.DatabaseError, e:
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
def executemany(self, query, args):
try:
return self.cursor.executemany(query, args)
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
except Database.OperationalError, e:
# Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place.
if e[0] in self.codes_for_integrityerror:
- raise Database.IntegrityError(tuple(e))
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
raise
+ except Database.DatabaseError, e:
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
def __getattr__(self, attr):
if attr in self.__dict__:
View
21 django/db/backends/oracle/base.py
@@ -4,8 +4,10 @@
Requires cx_Oracle: http://cx-oracle.sourceforge.net/
"""
-import os
+
import datetime
+import os
+import sys
import time
try:
from decimal import Decimal
@@ -24,6 +26,7 @@
from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured("Error loading cx_Oracle module: %s" % e)
+from django.db import utils
from django.db.backends import *
from django.db.backends.signals import connection_created
from django.db.backends.oracle.client import DatabaseClient
@@ -480,11 +483,13 @@ def execute(self, query, params=None):
self._guess_input_sizes([params])
try:
return self.cursor.execute(query, self._param_generator(params))
- except DatabaseError, e:
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ except Database.DatabaseError, e:
# cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400.
if e.args[0].code == 1400 and not isinstance(e, IntegrityError):
- e = IntegrityError(e.args[0])
- raise e
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
def executemany(self, query, params=None):
try:
@@ -504,11 +509,13 @@ def executemany(self, query, params=None):
try:
return self.cursor.executemany(query,
[self._param_generator(p) for p in formatted])
- except DatabaseError, e:
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ except Database.DatabaseError, e:
# cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400.
if e.args[0].code == 1400 and not isinstance(e, IntegrityError):
- e = IntegrityError(e.args[0])
- raise e
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
def fetchone(self):
row = self.cursor.fetchone()
View
19 django/db/backends/postgresql/base.py
@@ -4,6 +4,9 @@
Requires psycopg 1: http://initd.org/projects/psycopg1
"""
+import sys
+
+from django.db import utils
from django.db.backends import *
from django.db.backends.signals import connection_created
from django.db.backends.postgresql.client import DatabaseClient
@@ -50,11 +53,21 @@ def format_params(self, params):
return tuple([smart_str(p, self.charset, True) for p in params])
def execute(self, sql, params=()):
- return self.cursor.execute(smart_str(sql, self.charset), self.format_params(params))
+ try:
+ return self.cursor.execute(query, args)
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ except Database.DatabaseError, e:
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
def executemany(self, sql, param_list):
- new_param_list = [self.format_params(params) for params in param_list]
- return self.cursor.executemany(sql, new_param_list)
+ try:
+ new_param_list = [self.format_params(params) for params in param_list]
+ return self.cursor.executemany(sql, new_param_list)
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ except Database.DatabaseError, e:
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
def __getattr__(self, attr):
if attr in self.__dict__:
View
39 django/db/backends/postgresql_psycopg2/base.py
@@ -4,6 +4,9 @@
Requires psycopg 2: http://initd.org/projects/psycopg2
"""
+import sys
+
+from django.db import utils
from django.db.backends import *
from django.db.backends.signals import connection_created
from django.db.backends.postgresql.operations import DatabaseOperations as PostgresqlDatabaseOperations
@@ -27,6 +30,40 @@
psycopg2.extensions.register_adapter(SafeString, psycopg2.extensions.QuotedString)
psycopg2.extensions.register_adapter(SafeUnicode, psycopg2.extensions.QuotedString)
+class CursorWrapper(object):
+ """
+ A thin wrapper around psycopg2's normal cursor class so that we can catch
+ particular exception instances and reraise them with the right types.
+ """
+
+ def __init__(self, cursor):
+ self.cursor = cursor
+
+ def execute(self, query, args=None):
+ try:
+ return self.cursor.execute(query, args)
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ except Database.DatabaseError, e:
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
+
+ def executemany(self, query, args):
+ try:
+ return self.cursor.executemany(query, args)
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ except Database.DatabaseError, e:
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
+
+ def __getattr__(self, attr):
+ if attr in self.__dict__:
+ return self.__dict__[attr]
+ else:
+ return getattr(self.cursor, attr)
+
+ def __iter__(self):
+ return iter(self.cursor)
+
class DatabaseFeatures(BaseDatabaseFeatures):
needs_datetime_string_cast = False
can_return_id_from_insert = False
@@ -118,7 +155,7 @@ def _cursor(self):
# versions that support it, but, right now, that's hard to
# do without breaking other things (#10509).
self.features.can_return_id_from_insert = True
- return cursor
+ return CursorWrapper(cursor)
def _enter_transaction_management(self, managed):
"""
View
24 django/db/backends/sqlite3/base.py
@@ -7,6 +7,9 @@
standard library.
"""
+import sys
+
+from django.db import utils
from django.db.backends import *
from django.db.backends.signals import connection_created
from django.db.backends.sqlite3.client import DatabaseClient
@@ -185,16 +188,25 @@ class SQLiteCursorWrapper(Database.Cursor):
you'll need to use "%%s".
"""
def execute(self, query, params=()):
- query = self.convert_query(query, len(params))
- return Database.Cursor.execute(self, query, params)
+ try:
+ query = self.convert_query(query, len(params))
+ return Database.Cursor.execute(self, query, params)
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ except Database.DatabaseError, e:
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
def executemany(self, query, param_list):
try:
- query = self.convert_query(query, len(param_list[0]))
- return Database.Cursor.executemany(self, query, param_list)
+ query = self.convert_query(query, len(param_list[0]))
+ return Database.Cursor.executemany(self, query, param_list)
except (IndexError,TypeError):
- # No parameter list provided
- return None
+ # No parameter list provided
+ return None
+ except Database.IntegrityError, e:
+ raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
+ except Database.DatabaseError, e:
+ raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
def convert_query(self, query, num_params):
return query % tuple("?" * num_params)
View
13 django/db/utils.py
@@ -7,6 +7,16 @@
DEFAULT_DB_ALIAS = 'default'
+# Define some exceptions that mirror the PEP249 interface.
+# We will rethrow any backend-specific errors using these
+# common wrappers
+class DatabaseError(Exception):
+ pass
+
+class IntegrityError(DatabaseError):
+ pass
+
+
def load_backend(backend_name):
try:
module = import_module('.base', 'django.db.backends.%s' % backend_name)
@@ -40,9 +50,11 @@ def load_backend(backend_name):
else:
raise # If there's some other error, this must be an error in Django itself.
+
class ConnectionDoesNotExist(Exception):
pass
+
class ConnectionHandler(object):
def __init__(self, databases):
self.databases = databases
@@ -87,6 +99,7 @@ def __iter__(self):
def all(self):
return [self[alias] for alias in self]
+
class ConnectionRouter(object):
def __init__(self, routers):
self.routers = []
Please sign in to comment.
Something went wrong with that request. Please try again.