From a41b09266dcdd01036d59d76fe926fe0386aaade Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Fri, 19 Apr 2019 20:34:20 +0200 Subject: [PATCH] Fixed #30380 -- Handled bytes in MySQL backend for PyMySQL support. This commit partly reverts efd8a82e268a82b3ad0be77bd5b4548c30bcb4d7. --- django/db/backends/mysql/operations.py | 7 +++---- django/db/backends/mysql/schema.py | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/django/db/backends/mysql/operations.py b/django/db/backends/mysql/operations.py index da15e79ec2..a0d1095edd 100644 --- a/django/db/backends/mysql/operations.py +++ b/django/db/backends/mysql/operations.py @@ -4,6 +4,7 @@ from django.conf import settings from django.db.backends.base.operations import BaseDatabaseOperations from django.utils import timezone from django.utils.duration import duration_microseconds +from django.utils.encoding import force_str class DatabaseOperations(BaseDatabaseOperations): @@ -141,10 +142,8 @@ class DatabaseOperations(BaseDatabaseOperations): # With MySQLdb, cursor objects have an (undocumented) "_executed" # attribute where the exact query sent to the database is saved. # See MySQLdb/cursors.py in the source distribution. - query = getattr(cursor, '_executed', None) - if query is not None: - query = query.decode(errors='replace') - return query + # MySQLdb returns string, PyMySQL bytes. + return force_str(getattr(cursor, '_last_executed', None), errors='replace') def no_limit_value(self): # 2**64 - 1, as recommended by the MySQL documentation diff --git a/django/db/backends/mysql/schema.py b/django/db/backends/mysql/schema.py index 172e9b9ac8..666aa292e8 100644 --- a/django/db/backends/mysql/schema.py +++ b/django/db/backends/mysql/schema.py @@ -31,8 +31,9 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): def quote_value(self, value): self.connection.ensure_connection() + # MySQLdb escapes to string, PyMySQL to bytes. quoted = self.connection.connection.escape(value, self.connection.connection.encoders) - if isinstance(value, str): + if isinstance(value, str) and isinstance(quoted, bytes): quoted = quoted.decode() return quoted