Ticket #12702: t12702-r12351.1.diff

File t12702-r12351.1.diff, 12.7 KB (added by russellm, 6 years ago)

First pass at unifying exceptions under multi-db

  • django/db/__init__.py

    diff -r 7145c0852013 django/db/__init__.py
    a b  
    11from django.conf import settings
    22from django.core import signals
    33from django.core.exceptions import ImproperlyConfigured
    4 from django.db.utils import ConnectionHandler, ConnectionRouter, load_backend, DEFAULT_DB_ALIAS
     4from django.db.utils import ConnectionHandler, ConnectionRouter, load_backend, DEFAULT_DB_ALIAS, \
     5                            DatabaseError, IntegrityError
    56from django.utils.functional import curry
    67
    78__all__ = ('backend', 'connection', 'connections', 'router', 'DatabaseError',
     
    7374# connections['default'] instead.
    7475connection = connections[DEFAULT_DB_ALIAS]
    7576backend = load_backend(connection.settings_dict['ENGINE'])
    76 DatabaseError = backend.DatabaseError
    77 IntegrityError = backend.IntegrityError
    7877
    7978# Register an event that closes the database connection
    8079# when a Django request is finished.
  • django/db/backends/mysql/base.py

    diff -r 7145c0852013 django/db/backends/mysql/base.py
    a b  
    55"""
    66
    77import re
     8import sys
    89
    910try:
    1011    import MySQLdb as Database
     
    2425from MySQLdb.converters import conversions
    2526from MySQLdb.constants import FIELD_TYPE, FLAG, CLIENT
    2627
     28from django.db import utils
    2729from django.db.backends import *
    2830from django.db.backends.signals import connection_created
    2931from django.db.backends.mysql.client import DatabaseClient
     
    8284    def execute(self, query, args=None):
    8385        try:
    8486            return self.cursor.execute(query, args)
     87        except Database.IntegrityError, e:
     88            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    8589        except Database.OperationalError, e:
    8690            # Map some error codes to IntegrityError, since they seem to be
    8791            # misclassified and Django would prefer the more logical place.
    8892            if e[0] in self.codes_for_integrityerror:
    89                 raise Database.IntegrityError(tuple(e))
     93                raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    9094            raise
     95        except Database.DatabaseError, e:
     96            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    9197
    9298    def executemany(self, query, args):
    9399        try:
    94100            return self.cursor.executemany(query, args)
     101        except Database.IntegrityError, e:
     102            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    95103        except Database.OperationalError, e:
    96104            # Map some error codes to IntegrityError, since they seem to be
    97105            # misclassified and Django would prefer the more logical place.
    98106            if e[0] in self.codes_for_integrityerror:
    99                 raise Database.IntegrityError(tuple(e))
     107                raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
    100108            raise
    101 
     109        except Database.DatabaseError, e:
     110            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    102111    def __getattr__(self, attr):
    103112        if attr in self.__dict__:
    104113            return self.__dict__[attr]
  • django/db/backends/oracle/base.py

    diff -r 7145c0852013 django/db/backends/oracle/base.py
    a b  
    44Requires cx_Oracle: http://cx-oracle.sourceforge.net/
    55"""
    66
     7
     8import datetime
    79import os
    8 import datetime
     10import sys
    911import time
    1012try:
    1113    from decimal import Decimal
     
    2426    from django.core.exceptions import ImproperlyConfigured
    2527    raise ImproperlyConfigured("Error loading cx_Oracle module: %s" % e)
    2628
     29from django.db import utils
    2730from django.db.backends import *
    2831from django.db.backends.signals import connection_created
    2932from django.db.backends.oracle.client import DatabaseClient
     
    480483        self._guess_input_sizes([params])
    481484        try:
    482485            return self.cursor.execute(query, self._param_generator(params))
    483         except DatabaseError, e:
     486        except Database.IntegrityError, e:
     487            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     488        except Database.DatabaseError, e:
    484489            # cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400.
    485490            if e.args[0].code == 1400 and not isinstance(e, IntegrityError):
    486                 e = IntegrityError(e.args[0])
    487             raise e
     491                raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     492            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    488493
    489494    def executemany(self, query, params=None):
    490495        try:
     
    504509        try:
    505510            return self.cursor.executemany(query,
    506511                                [self._param_generator(p) for p in formatted])
    507         except DatabaseError, e:
     512        except Database.IntegrityError, e:
     513            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     514        except Database.DatabaseError, e:
    508515            # cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400.
    509516            if e.args[0].code == 1400 and not isinstance(e, IntegrityError):
    510                 e = IntegrityError(e.args[0])
    511             raise e
     517                raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     518            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    512519
    513520    def fetchone(self):
    514521        row = self.cursor.fetchone()
  • django/db/backends/postgresql/base.py

    diff -r 7145c0852013 django/db/backends/postgresql/base.py
    a b  
    44Requires psycopg 1: http://initd.org/projects/psycopg1
    55"""
    66
     7import sys
     8
     9from django.db import utils
    710from django.db.backends import *
    811from django.db.backends.signals import connection_created
    912from django.db.backends.postgresql.client import DatabaseClient
     
    5053            return tuple([smart_str(p, self.charset, True) for p in params])
    5154
    5255    def execute(self, sql, params=()):
    53         return self.cursor.execute(smart_str(sql, self.charset), self.format_params(params))
     56        try:
     57            return self.cursor.execute(query, args)
     58        except Database.IntegrityError, e:
     59            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     60        except Database.DatabaseError, e:
     61            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    5462
    5563    def executemany(self, sql, param_list):
    56         new_param_list = [self.format_params(params) for params in param_list]
    57         return self.cursor.executemany(sql, new_param_list)
     64        try:
     65            new_param_list = [self.format_params(params) for params in param_list]
     66            return self.cursor.executemany(sql, new_param_list)
     67        except Database.IntegrityError, e:
     68            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     69        except Database.DatabaseError, e:
     70            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    5871
    5972    def __getattr__(self, attr):
    6073        if attr in self.__dict__:
  • django/db/backends/postgresql_psycopg2/base.py

    diff -r 7145c0852013 django/db/backends/postgresql_psycopg2/base.py
    a b  
    44Requires psycopg 2: http://initd.org/projects/psycopg2
    55"""
    66
     7import sys
     8
     9from django.db import utils
    710from django.db.backends import *
    811from django.db.backends.signals import connection_created
    912from django.db.backends.postgresql.operations import DatabaseOperations as PostgresqlDatabaseOperations
     
    2730psycopg2.extensions.register_adapter(SafeString, psycopg2.extensions.QuotedString)
    2831psycopg2.extensions.register_adapter(SafeUnicode, psycopg2.extensions.QuotedString)
    2932
     33class CursorWrapper(object):
     34    """
     35    A thin wrapper around psycopg2's normal cursor class so that we can catch
     36    particular exception instances and reraise them with the right types.
     37    """
     38
     39    def __init__(self, cursor):
     40        self.cursor = cursor
     41
     42    def execute(self, query, args=None):
     43        try:
     44            return self.cursor.execute(query, args)
     45        except Database.IntegrityError, e:
     46            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     47        except Database.DatabaseError, e:
     48            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     49
     50    def executemany(self, query, args):
     51        try:
     52            return self.cursor.executemany(query, args)
     53        except Database.IntegrityError, e:
     54            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     55        except Database.DatabaseError, e:
     56            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
     57
     58    def __getattr__(self, attr):
     59        if attr in self.__dict__:
     60            return self.__dict__[attr]
     61        else:
     62            return getattr(self.cursor, attr)
     63
     64    def __iter__(self):
     65        return iter(self.cursor)
     66
    3067class DatabaseFeatures(BaseDatabaseFeatures):
    3168    needs_datetime_string_cast = False
    3269    can_return_id_from_insert = False
     
    118155                    # versions that support it, but, right now, that's hard to
    119156                    # do without breaking other things (#10509).
    120157                    self.features.can_return_id_from_insert = True
    121         return cursor
     158        return CursorWrapper(cursor)
    122159
    123160    def _enter_transaction_management(self, managed):
    124161        """
  • django/db/backends/sqlite3/base.py

    diff -r 7145c0852013 django/db/backends/sqlite3/base.py
    a b  
    77standard library.
    88"""
    99
     10import sys
     11
     12from django.db import utils
    1013from django.db.backends import *
    1114from django.db.backends.signals import connection_created
    1215from django.db.backends.sqlite3.client import DatabaseClient
     
    185188    you'll need to use "%%s".
    186189    """
    187190    def execute(self, query, params=()):
    188         query = self.convert_query(query, len(params))
    189         return Database.Cursor.execute(self, query, params)
     191        try:
     192            query = self.convert_query(query, len(params))
     193            return Database.Cursor.execute(self, query, params)
     194        except Database.IntegrityError, e:
     195            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     196        except Database.DatabaseError, e:
     197            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    190198
    191199    def executemany(self, query, param_list):
    192200        try:
    193           query = self.convert_query(query, len(param_list[0]))
    194           return Database.Cursor.executemany(self, query, param_list)
     201            query = self.convert_query(query, len(param_list[0]))
     202            return Database.Cursor.executemany(self, query, param_list)
    195203        except (IndexError,TypeError):
    196           # No parameter list provided
    197           return None
     204            # No parameter list provided
     205            return None
     206        except Database.IntegrityError, e:
     207            raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
     208        except Database.DatabaseError, e:
     209            raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), sys.exc_info()[2]
    198210
    199211    def convert_query(self, query, num_params):
    200212        return query % tuple("?" * num_params)
  • django/db/utils.py

    diff -r 7145c0852013 django/db/utils.py
    a b  
    77
    88DEFAULT_DB_ALIAS = 'default'
    99
     10# Define some exceptions that mirror the PEP249 interface.
     11# We will rethrow any backend-specific errors using these
     12# common wrappers
     13class DatabaseError(Exception):
     14    pass
     15
     16class IntegrityError(DatabaseError):
     17    pass
     18
     19
    1020def load_backend(backend_name):
    1121    try:
    1222        module = import_module('.base', 'django.db.backends.%s' % backend_name)
     
    4050            else:
    4151                raise # If there's some other error, this must be an error in Django itself.
    4252
     53
    4354class ConnectionDoesNotExist(Exception):
    4455    pass
    4556
     57
    4658class ConnectionHandler(object):
    4759    def __init__(self, databases):
    4860        self.databases = databases
     
    8799    def all(self):
    88100        return [self[alias] for alias in self]
    89101
     102
    90103class ConnectionRouter(object):
    91104    def __init__(self, routers):
    92105        self.routers = []
Back to Top