Loading django/db/backends/mysql/base.py +7 −5 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) Loading Loading @@ -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: Loading @@ -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()) Loading django/db/backends/mysql/introspection.py +8 −21 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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): Loading django/db/backends/mysql/validation.py +6 −23 Original line number Diff line number Diff line Loading @@ -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__}) docs/ref/databases.txt +11 −22 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 ~~~~~~~~~~~~~~~ Loading Loading
django/db/backends/mysql/base.py +7 −5 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) Loading Loading @@ -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: Loading @@ -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()) Loading
django/db/backends/mysql/introspection.py +8 −21 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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): Loading
django/db/backends/mysql/validation.py +6 −23 Original line number Diff line number Diff line Loading @@ -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__})
docs/ref/databases.txt +11 −22 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 ~~~~~~~~~~~~~~~ Loading