From 87775b64cdda97567a33c7bad65ad42853048525 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Wed, 15 Feb 2017 12:22:34 +0100 Subject: [PATCH] [1.11.x] Fixed #27843 -- Fixed truncate_name() when the name contains a username. Backport of b9351905721771fb49ea0020c751ae4280754c43 from master --- django/db/backends/utils.py | 15 +++++++++++---- tests/backends/test_utils.py | 4 ++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/django/db/backends/utils.py b/django/db/backends/utils.py index e4ee025077..ce5e274649 100644 --- a/django/db/backends/utils.py +++ b/django/db/backends/utils.py @@ -4,6 +4,7 @@ import datetime import decimal import hashlib import logging +import re from time import time from django.conf import settings @@ -180,13 +181,19 @@ def rev_typecast_decimal(d): def truncate_name(name, length=None, hash_len=4): - """Shortens a string to a repeatable mangled version with the given length. """ - if length is None or len(name) <= length: + Shorten a string to a repeatable mangled version with the given length. + If a quote stripped name contains a username, e.g. USERNAME"."TABLE, + truncate the table portion only. + """ + match = re.match('([^"]+)"\."([^"]+)', name) + table_name = match.group(2) if match else name + + if length is None or len(table_name) <= length: return name - hsh = hashlib.md5(force_bytes(name)).hexdigest()[:hash_len] - return '%s%s' % (name[:length - hash_len], hsh) + hsh = hashlib.md5(force_bytes(table_name)).hexdigest()[:hash_len] + return '%s%s%s' % (match.group(1) + '"."' if match else '', table_name[:length - hash_len], hsh) def format_number(value, max_digits, decimal_places): diff --git a/tests/backends/test_utils.py b/tests/backends/test_utils.py index ac7f9ab848..47720f7c92 100644 --- a/tests/backends/test_utils.py +++ b/tests/backends/test_utils.py @@ -21,3 +21,7 @@ class TestLoadBackend(SimpleTestCase): self.assertEqual(truncate_name('some_long_table', 10), 'some_la38a') self.assertEqual(truncate_name('some_long_table', 10, 3), 'some_loa38') self.assertEqual(truncate_name('some_long_table'), 'some_long_table') + # "user"."table" syntax + self.assertEqual(truncate_name('username"."some_table', 10), 'username"."some_table') + self.assertEqual(truncate_name('username"."some_long_table', 10), 'username"."some_la38a') + self.assertEqual(truncate_name('username"."some_long_table', 10, 3), 'username"."some_loa38')