diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py index c9dff6b61f..4766c84005 100644 --- a/django/db/backends/base/schema.py +++ b/django/db/backends/base/schema.py @@ -1,11 +1,10 @@ -import hashlib import logging from datetime import datetime from django.db.backends.ddl_references import ( Columns, ForeignKeyName, IndexName, Statement, Table, ) -from django.db.backends.utils import split_identifier +from django.db.backends.utils import names_digest, split_identifier from django.db.models import Index from django.db.transaction import TransactionManagementError, atomic from django.utils import timezone @@ -135,17 +134,6 @@ class BaseDatabaseSchemaEditor: def quote_name(self, name): return self.connection.ops.quote_name(name) - @classmethod - def _digest(cls, *args): - """ - Generate a 32-bit digest of a set of arguments that can be used to - shorten identifying names. - """ - h = hashlib.md5() - for arg in args: - h.update(arg.encode()) - return h.hexdigest()[:8] - # Field <-> database mapping functions def column_sql(self, model, field, include_default=False): @@ -885,7 +873,7 @@ class BaseDatabaseSchemaEditor: and a unique digest and suffix. """ _, table_name = split_identifier(table_name) - hash_suffix_part = '%s%s' % (self._digest(table_name, *column_names), suffix) + hash_suffix_part = '%s%s' % (names_digest(table_name, *column_names, length=8), suffix) max_length = self.connection.ops.max_name_length() or 200 # If everything fits into max_length, use that name. index_name = '%s_%s_%s' % (table_name, '_'.join(column_names), hash_suffix_part) diff --git a/django/db/backends/utils.py b/django/db/backends/utils.py index a762175025..2062af91f1 100644 --- a/django/db/backends/utils.py +++ b/django/db/backends/utils.py @@ -213,10 +213,21 @@ def truncate_name(identifier, length=None, hash_len=4): if length is None or len(name) <= length: return identifier - digest = hashlib.md5(name.encode()).hexdigest()[:hash_len] + digest = names_digest(name, length=hash_len) return '%s%s%s' % ('%s"."' % namespace if namespace else '', name[:length - hash_len], digest) +def names_digest(*args, length): + """ + Generate a 32-bit digest of a set of arguments that can be used to shorten + identifying names. + """ + h = hashlib.md5() + for arg in args: + h.update(arg.encode()) + return h.hexdigest()[:length] + + def format_number(value, max_digits, decimal_places): """ Format a number into a string with the requisite number of digits and diff --git a/django/db/models/indexes.py b/django/db/models/indexes.py index c378b13a5c..5e325c918f 100644 --- a/django/db/models/indexes.py +++ b/django/db/models/indexes.py @@ -1,7 +1,4 @@ -import hashlib - -from django.db.backends.utils import split_identifier -from django.utils.encoding import force_bytes +from django.db.backends.utils import names_digest, split_identifier __all__ = ['Index'] @@ -81,17 +78,6 @@ class Index: _, _, kwargs = self.deconstruct() return self.__class__(**kwargs) - @staticmethod - def _hash_generator(*args): - """ - Generate a 32-bit digest of a set of arguments that can be used to - shorten identifying names. - """ - h = hashlib.md5() - for arg in args: - h.update(force_bytes(arg)) - return h.hexdigest()[:6] - def set_name_with_model(self, model): """ Generate a unique name for the index. @@ -112,7 +98,7 @@ class Index: self.name = '%s_%s_%s' % ( table_name[:11], column_names[0][:7], - '%s_%s' % (self._hash_generator(*hash_data), self.suffix), + '%s_%s' % (names_digest(*hash_data, length=6), self.suffix), ) assert len(self.name) <= self.max_name_length, ( 'Index too long for multiple database support. Is self.suffix '