1
0
mirror of https://github.com/django/django.git synced 2025-06-05 11:39:13 +00:00

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
This commit is contained in:
Ramiro Morales 2012-04-21 03:04:10 +00:00
parent 53fb45c6d8
commit 4536359887
4 changed files with 33 additions and 72 deletions

View File

@ -15,11 +15,13 @@ except ImportError, e:
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e) 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 # 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') # lexicographic ordering in this check because then (1, 2, 1, 'gamma')
# inadvertently passes the version test. # inadvertently passes the version test.
version = Database.version_info version = Database.version_info
if (version < (1,2,1) or (version[:3] == (1, 2, 1) and if (version < (1, 2, 1) or (version[:3] == (1, 2, 1) and
(len(version) < 5 or version[3] != 'final' or version[4] < 2))): (len(version) < 5 or version[3] != 'final' or version[4] < 2))):
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured("MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__) raise ImproperlyConfigured("MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__)
@ -163,6 +165,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
supports_timezones = False supports_timezones = False
requires_explicit_null_ordering_when_grouping = True requires_explicit_null_ordering_when_grouping = True
allows_primary_key_0 = False allows_primary_key_0 = False
uses_savepoints = True
def __init__(self, connection): def __init__(self, connection):
super(DatabaseFeatures, self).__init__(connection) super(DatabaseFeatures, self).__init__(connection)
@ -387,8 +390,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
self.connection = Database.connect(**kwargs) self.connection = Database.connect(**kwargs)
self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode] self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode]
self.connection.encoders[SafeString] = self.connection.encoders[str] 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) connection_created.send(sender=self.__class__, connection=self)
cursor = self.connection.cursor() cursor = self.connection.cursor()
if new_connection: if new_connection:
@ -405,10 +406,11 @@ class DatabaseWrapper(BaseDatabaseWrapper):
except Database.NotSupportedError: except Database.NotSupportedError:
pass pass
def get_server_version(self): @cached_property
def mysql_version(self):
if not self.server_version: if not self.server_version:
if not self._valid_connection(): if not self._valid_connection():
self.cursor() self.cursor().close()
m = server_version_re.match(self.connection.get_server_info()) m = server_version_re.match(self.connection.get_server_info())
if not m: if not m:
raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info()) raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())

View File

@ -65,27 +65,14 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
key columns in given table. key columns in given table.
""" """
key_columns = [] key_columns = []
try: cursor.execute("""
cursor.execute(""" SELECT column_name, referenced_table_name, referenced_column_name
SELECT column_name, referenced_table_name, referenced_column_name FROM information_schema.key_column_usage
FROM information_schema.key_column_usage WHERE table_name = %s
WHERE table_name = %s AND table_schema = DATABASE()
AND table_schema = DATABASE() AND referenced_table_name IS NOT NULL
AND referenced_table_name IS NOT NULL AND referenced_column_name IS NOT NULL""", [table_name])
AND referenced_column_name IS NOT NULL""", [table_name]) key_columns.extend(cursor.fetchall())
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 return key_columns
def get_primary_key_column(self, cursor, table_name): def get_primary_key_column(self, cursor, table_name):

View File

@ -3,30 +3,13 @@ from django.db.backends import BaseDatabaseValidation
class DatabaseValidation(BaseDatabaseValidation): class DatabaseValidation(BaseDatabaseValidation):
def validate_field(self, errors, opts, f): def validate_field(self, errors, opts, f):
""" """
There are some field length restrictions for MySQL: MySQL has the following field length restriction:
No character (varchar) fields can have a length exceeding 255
- Prior to version 5.0.3, character fields could not exceed 255 characters if they have a unique index on them.
characters in length.
- 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 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, varchar_fields = (models.CharField, models.CommaSeparatedIntegerField,
models.SlugField) models.SlugField)
if isinstance(f, varchar_fields) and f.max_length > 255: if isinstance(f, varchar_fields) and f.max_length > 255 and f.unique:
if db_version and db_version < (5, 0, 3): msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when using "unique=True".'
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).' errors.add(opts, msg % {'name': f.name, 'cls': f.__class__.__name__})
elif f.unique == True:
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})

View File

@ -122,30 +122,23 @@ lookups that use the ``LIKE`` operator in their SQL, as is done with the
MySQL notes MySQL notes
=========== ===========
Django expects the database to support transactions, referential integrity, and Version support
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.
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
---------
`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed `MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed
data on all database schema. Django's ``inspectdb`` feature uses this data on all database schema. Django's ``inspectdb`` feature uses this feature.
``information_schema`` if it's available. 5.0 also has support for stored
procedures, but Django currently doesn't use stored procedures. .. versionchanged:: 1.5
The minimum version requirement of MySQL 5.0.3 was set in Django 1.5.
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: 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 .. _MySQL 5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html
Storage engines 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.SlugField` and
:class:`~django.db.models.CommaSeparatedIntegerField`. :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 DateTime fields
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~