diff options
| author | Simon Charette <charette.s@gmail.com> | 2017-11-11 19:17:20 -0500 |
|---|---|---|
| committer | Simon Charette <charette.s@gmail.com> | 2017-11-14 22:06:30 -0500 |
| commit | a35ab95ed4eec5c62fa19bdc69ecfe0eff3e1fca (patch) | |
| tree | de4cba97ae2ee5cbf65d5669d0f06a7b3f481fbb /django | |
| parent | afcde50497983ec48020600345367e161f6ff9c3 (diff) | |
[1.11.x] Fixed #28792 -- Fixed index name truncation of namespaced tables.
Refs #27458, #27843.
Thanks Tim and Mariusz for the review.
Backport of ee85ef8315db839e5723dea19d8b971420a2ebb4 from master
Diffstat (limited to 'django')
| -rw-r--r-- | django/db/backends/base/schema.py | 4 | ||||
| -rw-r--r-- | django/db/backends/utils.py | 34 |
2 files changed, 26 insertions, 12 deletions
diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py index f4b8b02049..56102ff27b 100644 --- a/django/db/backends/base/schema.py +++ b/django/db/backends/base/schema.py @@ -2,7 +2,7 @@ import hashlib import logging from datetime import datetime -from django.db.backends.utils import strip_quotes +from django.db.backends.utils import split_identifier from django.db.models import Index from django.db.transaction import TransactionManagementError, atomic from django.utils import six, timezone @@ -852,7 +852,7 @@ class BaseDatabaseSchemaEditor(object): The name is divided into 3 parts: the table name, the column names, and a unique digest and suffix. """ - table_name = strip_quotes(model._meta.db_table) + _, table_name = split_identifier(model._meta.db_table) hash_data = [table_name] + list(column_names) hash_suffix_part = '%s%s' % (self._digest(*hash_data), suffix) max_length = self.connection.ops.max_name_length() or 200 diff --git a/django/db/backends/utils.py b/django/db/backends/utils.py index ad87eb82e7..e7f55d2972 100644 --- a/django/db/backends/utils.py +++ b/django/db/backends/utils.py @@ -4,7 +4,6 @@ import datetime import decimal import hashlib import logging -import re from time import time from django.conf import settings @@ -180,20 +179,35 @@ def rev_typecast_decimal(d): return str(d) -def truncate_name(name, length=None, hash_len=4): +def split_identifier(identifier): """ - Shorten a string to a repeatable mangled version with the given length. - If a quote stripped name contains a username, e.g. USERNAME"."TABLE, + Split a SQL identifier into a two element tuple of (namespace, name). + + The identifier could be a table, column, or sequence name might be prefixed + by a namespace. + """ + try: + namespace, name = identifier.split('"."') + except ValueError: + namespace, name = '', identifier + return namespace.strip('"'), name.strip('"') + + +def truncate_name(identifier, length=None, hash_len=4): + """ + Shorten a SQL identifier to a repeatable mangled version with the given + length. + + If a quote stripped name contains a namespace, e.g. USERNAME"."TABLE, truncate the table portion only. """ - match = re.match(r'([^"]+)"\."([^"]+)', name) - table_name = match.group(2) if match else name + namespace, name = split_identifier(identifier) - if length is None or len(table_name) <= length: - return name + if length is None or len(name) <= length: + return identifier - 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) + digest = hashlib.md5(force_bytes(name)).hexdigest()[:hash_len] + return '%s%s%s' % ('%s"."' % namespace if namespace else '', name[:length - hash_len], digest) def format_number(value, max_digits, decimal_places): |
