Commit e9ef9776 authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #18461 -- Ensured that last_executed_query returns Unicode

Thanks Anssi Kääriäinen for the review.
parent a7ef802f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -238,7 +238,7 @@ class DatabaseOperations(BaseDatabaseOperations):
        # With MySQLdb, cursor objects have an (undocumented) "_last_executed"
        # attribute where the exact query sent to the database is saved.
        # See MySQLdb/cursors.py in the source distribution.
        return cursor._last_executed
        return cursor._last_executed.decode('utf-8')

    def no_limit_value(self):
        # 2**64 - 1, as recommended by the MySQL documentation
+3 −1
Original line number Diff line number Diff line
@@ -193,7 +193,9 @@ class DatabaseOperations(BaseDatabaseOperations):
    def last_executed_query(self, cursor, sql, params):
        # http://initd.org/psycopg/docs/cursor.html#cursor.query
        # The query attribute is a Psycopg extension to the DB API 2.0.
        return cursor.query
        if cursor.query is not None:
            return cursor.query.decode('utf-8')
        return None

    def return_insert_id(self):
        return "RETURNING %s", ()
+15 −9
Original line number Diff line number Diff line
@@ -125,20 +125,14 @@ class DateQuotingTest(TestCase):
        classes = models.SchoolClass.objects.filter(last_updated__day=20)
        self.assertEqual(len(classes), 1)

class LastExecutedQueryTest(TestCase):

    def setUp(self):
        # connection.queries will not be filled in without this
        settings.DEBUG = True

    def tearDown(self):
        settings.DEBUG = False

    # There are no tests for the sqlite backend because it does not
class LastExecutedQueryTest(TestCase):
    # There are no escaping tests for the sqlite backend because it does not
    # implement paramater escaping. See #14091.

    @unittest.skipUnless(connection.vendor in ('oracle', 'postgresql'),
                         "These backends use the standard parameter escaping rules")
    @override_settings(DEBUG=True)
    def test_parameter_escaping(self):
        # check that both numbers and string are properly quoted
        list(models.Tag.objects.filter(name="special:\\\"':", object_id=12))
@@ -148,6 +142,7 @@ class LastExecutedQueryTest(TestCase):

    @unittest.skipUnless(connection.vendor == 'mysql',
                         "MySQL uses backslashes to escape parameters.")
    @override_settings(DEBUG=True)
    def test_parameter_escaping(self):
        list(models.Tag.objects.filter(name="special:\\\"':", object_id=12))
        sql = connection.queries[-1]['sql']
@@ -155,6 +150,17 @@ class LastExecutedQueryTest(TestCase):
        self.assertTrue("= 'special:\\\\\\\"\\':' " in sql)
        self.assertTrue("= 12 " in sql)

    def test_query_encoding(self):
        """
        Test that last_executed_query() returns an Unicode string
        """
        tags = models.Tag.objects.filter(name="й", object_id=12).extra(select={'föö':1})
        sql, params = tags.query.sql_with_params()
        cursor = tags.query.get_compiler('default').execute_sql(None)
        last_sql = cursor.db.ops.last_executed_query(cursor, sql, params)
        self.assertTrue(isinstance(last_sql, unicode))


class ParameterHandlingTest(TestCase):
    def test_bad_parameter_count(self):
        "An executemany call with too many/not enough parameters will raise an exception (Refs #12612)"