Commit 45363598 authored by Ramiro Morales's avatar Ramiro Morales
Browse files

Fixed #18116 -- Raised minimum MySQL version officially suported to 5.0.3.

Thanks Carl, Claude and Anssi for discussion and patch review.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17921 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 53fb45c6
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@ except ImportError, e:
    from django.core.exceptions import ImproperlyConfigured
    raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e)

from django.utils.functional import cached_property

# We want version (1, 2, 1, 'final', 2) or later. We can't just use
# lexicographic ordering in this check because then (1, 2, 1, 'gamma')
# inadvertently passes the version test.
@@ -163,6 +165,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
    supports_timezones = False
    requires_explicit_null_ordering_when_grouping = True
    allows_primary_key_0 = False
    uses_savepoints = True

    def __init__(self, connection):
        super(DatabaseFeatures, self).__init__(connection)
@@ -387,8 +390,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
            self.connection = Database.connect(**kwargs)
            self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode]
            self.connection.encoders[SafeString] = self.connection.encoders[str]
            self.features.uses_savepoints = \
                self.get_server_version() >= (5, 0, 3)
            connection_created.send(sender=self.__class__, connection=self)
        cursor = self.connection.cursor()
        if new_connection:
@@ -405,10 +406,11 @@ class DatabaseWrapper(BaseDatabaseWrapper):
        except Database.NotSupportedError:
            pass

    def get_server_version(self):
    @cached_property
    def mysql_version(self):
        if not self.server_version:
            if not self._valid_connection():
                self.cursor()
                self.cursor().close()
            m = server_version_re.match(self.connection.get_server_info())
            if not m:
                raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())
+8 −21
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
        key columns in given table.
        """
        key_columns = []
        try:
        cursor.execute("""
            SELECT column_name, referenced_table_name, referenced_column_name
            FROM information_schema.key_column_usage
@@ -74,18 +73,6 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
                AND referenced_table_name IS NOT NULL
                AND referenced_column_name IS NOT NULL""", [table_name])
        key_columns.extend(cursor.fetchall())
        except (ProgrammingError, OperationalError):
            # Fall back to "SHOW CREATE TABLE", for previous MySQL versions.
            # Go through all constraints and save the equal matches.
            cursor.execute("SHOW CREATE TABLE %s" % self.connection.ops.quote_name(table_name))
            for row in cursor.fetchall():
                pos = 0
                while True:
                    match = foreign_key_re.search(row[1], pos)
                    if match == None:
                        break
                    pos = match.end()
                    key_columns.append(match.groups())
        return key_columns

    def get_primary_key_column(self, cursor, table_name):
+6 −23
Original line number Diff line number Diff line
@@ -3,30 +3,13 @@ from django.db.backends import BaseDatabaseValidation
class DatabaseValidation(BaseDatabaseValidation):
    def validate_field(self, errors, opts, f):
        """
        There are some field length restrictions for MySQL:

        - Prior to version 5.0.3, character fields could not exceed 255
          characters in length.
        - No character (varchar) fields can have a length exceeding 255
        MySQL has the following field length restriction:
        No character (varchar) fields can have a length exceeding 255
        characters if they have a unique index on them.
        """
        from django.db import models
        from MySQLdb import OperationalError
        try:
            db_version = self.connection.get_server_version()
            text_version = '.'.join([str(n) for n in db_version[:3]])
        except OperationalError:
            db_version = None
            text_version = ''
        varchar_fields = (models.CharField, models.CommaSeparatedIntegerField,
                models.SlugField)
        if isinstance(f, varchar_fields) and f.max_length > 255:
            if db_version and db_version < (5, 0, 3):
                msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %(version)s).'
            elif f.unique == True:
        if isinstance(f, varchar_fields) and f.max_length > 255 and f.unique:
            msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when using "unique=True".'
            else:
                msg = None

            if msg:
                errors.add(opts, msg % {'name': f.name, 'cls': f.__class__.__name__, 'version': text_version})
            errors.add(opts, msg % {'name': f.name, 'cls': f.__class__.__name__})
+11 −22
Original line number Diff line number Diff line
@@ -122,30 +122,23 @@ lookups that use the ``LIKE`` operator in their SQL, as is done with the
MySQL notes
===========

Django expects the database to support transactions, referential integrity, and
Unicode (UTF-8 encoding). Fortunately, MySQL_ has all these features as
available as far back as 3.23. While it may be possible to use 3.23 or 4.0,
you'll probably have less trouble if you use 4.1 or 5.0.
Version support
---------------

MySQL 4.1
---------
Django supports MySQL 5.0.3 and higher.

`MySQL 4.1`_ has greatly improved support for character sets. It is possible to
set different default character sets on the database, table, and column.
Previous versions have only a server-wide character set setting. It's also the
first version where the character set can be changed on the fly. 4.1 also has
support for views, but Django currently doesn't use views.
`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed
data on all database schema. Django's ``inspectdb`` feature uses this feature.

MySQL 5.0
---------
.. versionchanged:: 1.5
    The minimum version requirement of MySQL 5.0.3 was set in Django 1.5.

`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed
data on all database schema. Django's ``inspectdb`` feature uses this
``information_schema`` if it's available. 5.0 also has support for stored
procedures, but Django currently doesn't use stored procedures.
Django expects the database to support Unicode (UTF-8 encoding) and delegates to
it the task of enforcing transactions and referential integrity. It is important
to be aware of the fact that the two latter ones aren't actually enforced by
MySQL when using the MyISAM storage engine, see the next section.

.. _MySQL: http://www.mysql.com/
.. _MySQL 4.1: http://dev.mysql.com/doc/refman/4.1/en/index.html
.. _MySQL 5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html

Storage engines
@@ -381,10 +374,6 @@ for the field. This affects :class:`~django.db.models.CharField`,
:class:`~django.db.models.SlugField` and
:class:`~django.db.models.CommaSeparatedIntegerField`.

Furthermore, if you are using a version of MySQL prior to 5.0.3, all of those
column types have a maximum length restriction of 255 characters, regardless
of whether ``unique=True`` is specified or not.

DateTime fields
~~~~~~~~~~~~~~~