Commit 22da5f88 authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #19716 -- Added support for microseconds with MySQL 5.6.4 and up

Thanks erik@cederstrand.dk for the report and Tim Graham for the review.
parent 9e746c13
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -79,7 +79,7 @@ def adapt_datetime_with_timezone_support(value, conv):
            default_timezone = timezone.get_default_timezone()
            value = timezone.make_aware(value, default_timezone)
        value = value.astimezone(timezone.utc).replace(tzinfo=None)
    return Thing2Literal(value.strftime("%Y-%m-%d %H:%M:%S"), conv)
    return Thing2Literal(value.strftime("%Y-%m-%d %H:%M:%S.%f"), conv)

# MySQLdb-1.2.1 returns TIME columns as timedelta -- they are more like
# timedelta in terms of actual behavior as they are signed and include days --
@@ -175,7 +175,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
    supports_forward_references = False
    # XXX MySQL DB-API drivers currently fail on binary data on Python 3.
    supports_binary_field = six.PY2
    supports_microsecond_precision = False
    supports_regex_backreferencing = False
    supports_date_lookup_using_string = False
    can_introspect_binary_field = False
@@ -210,6 +209,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
        "Confirm support for introspected foreign keys"
        return self._mysql_storage_engine != 'MyISAM'

    @cached_property
    def supports_microsecond_precision(self):
        return self.connection.mysql_version >= (5, 6, 4)

    @cached_property
    def has_zoneinfo_database(self):
        # MySQL accepts full time zones names (eg. Africa/Nairobi) but rejects
+9 −1
Original line number Diff line number Diff line
from django.db.backends.creation import BaseDatabaseCreation
from django.utils.functional import cached_property


class DatabaseCreation(BaseDatabaseCreation):
@@ -6,7 +7,7 @@ class DatabaseCreation(BaseDatabaseCreation):
    # types, as strings. Column-type strings can contain format strings; they'll
    # be interpolated against the values of Field.__dict__ before being output.
    # If a column type is set to None, it won't be included in the output.
    data_types = {
    _data_types = {
        'AutoField': 'integer AUTO_INCREMENT',
        'BinaryField': 'longblob',
        'BooleanField': 'bool',
@@ -33,6 +34,13 @@ class DatabaseCreation(BaseDatabaseCreation):
        'UUIDField': 'char(32)',
    }

    @cached_property
    def data_types(self):
        if self.connection.features.supports_microsecond_precision:
            return dict(self._data_types, DateTimeField='datetime(6)', TimeField='time(6)')
        else:
            return self._data_types

    def sql_table_creation_suffix(self):
        suffix = []
        test_settings = self.connection.settings_dict['TEST']
+25 −4
Original line number Diff line number Diff line
@@ -496,11 +496,32 @@ for the field. This affects :class:`~django.db.models.CharField`,
:class:`~django.db.models.SlugField` and
:class:`~django.db.models.CommaSeparatedIntegerField`.

DateTime fields
~~~~~~~~~~~~~~~
.. _mysql-fractional-seconds:

MySQL does not store fractions of seconds. Fractions of seconds are truncated
to zero when the time is stored.
Fractional seconds support for Time and DateTime fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

MySQL 5.6.4 and later can store fractional seconds, provided that the
column definition includes a fractional indication (e.g. ``DATETIME(6)``).
Earlier versions do not support them at all.

Django will not upgrade existing columns to include fractional seconds if the
database server supports it. If you want to enable them on an existing database,
it's up to you to either manually update the column on the target database, by
executing a command like::

    ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)

or using a :class:`~django.db.migrations.operations.RunSQL` operation in a
:ref:`data migration <data-migrations>`.

.. versionchanged:: 1.8

    Previously, Django truncated fractional seconds from ``datetime`` and
    ``time`` values when using the MySQL backend. Now it lets the database
    decide whether it should drop that part of the value or not. By default, new
    ``DateTimeField`` or ``TimeField`` columns are now created with fractional
    seconds support on MySQL 5.6.4 or later.

``TIMESTAMP`` columns
~~~~~~~~~~~~~~~~~~~~~
+3 −1
Original line number Diff line number Diff line
@@ -166,7 +166,9 @@ Database backends
* The MySQL backend no longer strips microseconds from ``datetime`` values as
  MySQL 5.6.4 and up supports fractional seconds depending on the declaration
  of the datetime field (when ``DATETIME`` includes fractional precision greater
  than 0).
  than 0). New datetime database columns created with Django 1.8 and MySQL 5.6.4
  and up will support microseconds. See the :ref:`MySQL database notes
  <mysql-fractional-seconds>` for more details.

Email
^^^^^