Commit 315145f7 authored by Adrian Holovaty's avatar Adrian Holovaty
Browse files

Fixed #10459 -- Refactored the internals of database connection objects so...

Fixed #10459 -- Refactored the internals of database connection objects so that connections know their own settings and pass around settings as dictionaries instead of passing around the Django settings module itself. This will make it easier for multiple database support. Thanks to Alex Gaynor for the initial patch.

This is backwards-compatible but will likely break third-party database backends. Specific API changes are:

* BaseDatabaseWrapper.__init__() now takes a settings_dict instead of a settings module. It's called settings_dict to disambiguate, and for easy grepability. This should be a dictionary containing DATABASE_NAME, etc.

* BaseDatabaseWrapper has a settings_dict attribute instead of an options attribute. BaseDatabaseWrapper.options is now BaseDatabaseWrapper['DATABASE_OPTIONS']

* BaseDatabaseWrapper._cursor() no longer takes a settings argument.

* BaseDatabaseClient.__init__() now takes a connection argument (a DatabaseWrapper instance) instead of no arguments.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@10026 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 7daf0b94
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -36,8 +36,22 @@ except ImportError, e:
        else:
            raise # If there's some other error, this must be an error in Django itself.

# Convenient aliases for backend bits.
connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS)
# `connection`, `DatabaseError` and `IntegrityError` are convenient aliases
# for backend bits.

# DatabaseWrapper.__init__() takes a dictionary, not a settings module, so
# we manually create the dictionary from the settings, passing only the
# settings that the database backends care about. Note that TIME_ZONE is used
# by the PostgreSQL backends.
connection = backend.DatabaseWrapper({
    'DATABASE_HOST': settings.DATABASE_HOST,
    'DATABASE_NAME': settings.DATABASE_NAME,
    'DATABASE_OPTIONS': settings.DATABASE_OPTIONS,
    'DATABASE_PASSWORD': settings.DATABASE_PASSWORD,
    'DATABASE_PORT': settings.DATABASE_PORT,
    'DATABASE_USER': settings.DATABASE_USER,
    'TIME_ZONE': settings.TIME_ZONE,
})
DatabaseError = backend.DatabaseError
IntegrityError = backend.IntegrityError

+11 −3
Original line number Diff line number Diff line
@@ -24,10 +24,14 @@ class BaseDatabaseWrapper(local):
    Represents a database connection.
    """
    ops = None
    def __init__(self, **kwargs):
    def __init__(self, settings_dict):
        # `settings_dict` should be a dictionary containing keys such as
        # DATABASE_NAME, DATABASE_USER, etc. It's called `settings_dict`
        # instead of `settings` to disambiguate it from Django settings
        # modules.
        self.connection = None
        self.queries = []
        self.options = kwargs
        self.settings_dict = settings_dict

    def _commit(self):
        if self.connection is not None:
@@ -59,7 +63,7 @@ class BaseDatabaseWrapper(local):

    def cursor(self):
        from django.conf import settings
        cursor = self._cursor(settings)
        cursor = self._cursor()
        if settings.DEBUG:
            return self.make_debug_cursor(cursor)
        return cursor
@@ -498,6 +502,10 @@ class BaseDatabaseClient(object):
    # (e.g., "psql"). Subclasses must override this.
    executable_name = None

    def __init__(self, connection):
        # connection is an instance of BaseDatabaseWrapper.
        self.connection = connection

    def runshell(self):
        raise NotImplementedError()

+1 −1
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ class DatabaseWrapper(object):

        self.features = BaseDatabaseFeatures()
        self.ops = DatabaseOperations()
        self.client = DatabaseClient()
        self.client = DatabaseClient(self)
        self.creation = BaseDatabaseCreation(self)
        self.introspection = DatabaseIntrospection(self)
        self.validation = BaseDatabaseValidation()
+17 −16
Original line number Diff line number Diff line
@@ -234,11 +234,11 @@ class DatabaseWrapper(BaseDatabaseWrapper):

    def __init__(self, **kwargs):
        super(DatabaseWrapper, self).__init__(**kwargs)
        self.server_version = None

        self.server_version = None
        self.features = DatabaseFeatures()
        self.ops = DatabaseOperations()
        self.client = DatabaseClient()
        self.client = DatabaseClient(self)
        self.creation = DatabaseCreation(self)
        self.introspection = DatabaseIntrospection(self)
        self.validation = DatabaseValidation()
@@ -253,26 +253,27 @@ class DatabaseWrapper(BaseDatabaseWrapper):
                self.connection = None
        return False

    def _cursor(self, settings):
    def _cursor(self):
        if not self._valid_connection():
            kwargs = {
                'conv': django_conversions,
                'charset': 'utf8',
                'use_unicode': True,
            }
            if settings.DATABASE_USER:
                kwargs['user'] = settings.DATABASE_USER
            if settings.DATABASE_NAME:
                kwargs['db'] = settings.DATABASE_NAME
            if settings.DATABASE_PASSWORD:
                kwargs['passwd'] = settings.DATABASE_PASSWORD
            if settings.DATABASE_HOST.startswith('/'):
                kwargs['unix_socket'] = settings.DATABASE_HOST
            elif settings.DATABASE_HOST:
                kwargs['host'] = settings.DATABASE_HOST
            if settings.DATABASE_PORT:
                kwargs['port'] = int(settings.DATABASE_PORT)
            kwargs.update(self.options)
            settings_dict = self.settings_dict
            if settings_dict['DATABASE_USER']:
                kwargs['user'] = settings_dict['DATABASE_USER']
            if settings_dict['DATABASE_NAME']:
                kwargs['db'] = settings_dict['DATABASE_NAME']
            if settings_dict['DATABASE_PASSWORD']:
                kwargs['passwd'] = settings_dict['DATABASE_PASSWORD']
            if settings_dict['DATABASE_HOST'].startswith('/'):
                kwargs['unix_socket'] = settings_dict['DATABASE_HOST']
            elif settings_dict['DATABASE_HOST']:
                kwargs['host'] = settings_dict['DATABASE_HOST']
            if settings_dict['DATABASE_PORT']:
                kwargs['port'] = int(settings_dict['DATABASE_PORT'])
            kwargs.update(settings_dict['DATABASE_OPTIONS'])
            self.connection = Database.connect(**kwargs)
            self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode]
            self.connection.encoders[SafeString] = self.connection.encoders[str]
+7 −7
Original line number Diff line number Diff line
from django.db.backends import BaseDatabaseClient
from django.conf import settings
import os

class DatabaseClient(BaseDatabaseClient):
    executable_name = 'mysql'

    def runshell(self):
        settings_dict = self.connection.settings_dict
        args = ['']
        db = settings.DATABASE_OPTIONS.get('db', settings.DATABASE_NAME)
        user = settings.DATABASE_OPTIONS.get('user', settings.DATABASE_USER)
        passwd = settings.DATABASE_OPTIONS.get('passwd', settings.DATABASE_PASSWORD)
        host = settings.DATABASE_OPTIONS.get('host', settings.DATABASE_HOST)
        port = settings.DATABASE_OPTIONS.get('port', settings.DATABASE_PORT)
        defaults_file = settings.DATABASE_OPTIONS.get('read_default_file')
        db = settings_dict['DATABASE_OPTIONS'].get('db', settings_dict['DATABASE_NAME'])
        user = settings_dict['DATABASE_OPTIONS'].get('user', settings_dict['DATABASE_USER'])
        passwd = settings_dict['DATABASE_OPTIONS'].get('passwd', settings_dict['DATABASE_PASSWORD'])
        host = settings_dict['DATABASE_OPTIONS'].get('host', settings_dict['DATABASE_HOST'])
        port = settings_dict['DATABASE_OPTIONS'].get('port', settings_dict['DATABASE_PORT'])
        defaults_file = settings_dict['DATABASE_OPTIONS'].get('read_default_file')
        # Seems to be no good way to set sql_mode with CLI.
    
        if defaults_file:
Loading