diff --git a/trytond/backend/mysql/table.py b/trytond/backend/mysql/table.py index a16f40945d..b0f81fa0a4 100644 --- a/trytond/backend/mysql/table.py +++ b/trytond/backend/mysql/table.py @@ -11,6 +11,7 @@ VARCHAR_SIZE_RE = re.compile('VARCHAR\(([0-9]+)\)') class TableHandler(TableHandlerInterface): + namedatalen = 64 def __init__(self, model, module_name=None, history=False): super(TableHandler, self).__init__(model, @@ -247,7 +248,8 @@ class TableHandler(TableHandlerInterface): def add_fk(self, column_name, reference, on_delete=None): if on_delete is None: on_delete = 'SET NULL' - conname = '%s_%s_fkey' % (self.table_name, column_name) + conname = self.convert_name( + '%s_%s_fkey' % (self.table_name, column_name)) if conname in self._fkeys: self.drop_fk(column_name) cursor = Transaction().connection.cursor() @@ -259,7 +261,8 @@ class TableHandler(TableHandlerInterface): self._update_definitions(constraints=True) def drop_fk(self, column_name, table=None): - conname = '%s_%s_fkey' % (self.table_name, column_name) + conname = self.convert_name( + '%s_%s_fkey' % (self.table_name, column_name)) if conname not in self._fkeys: return cursor = Transaction().connection.cursor() @@ -270,10 +273,9 @@ class TableHandler(TableHandlerInterface): def index_action(self, column_name, action='add', table=None): if isinstance(column_name, basestring): column_name = [column_name] - index_name = ((table or self.table_name) + "_" + '_'.join(column_name) - + "_index") - # Index name length is limited to 64 - index_name = index_name[:64] + index_name = self.convert_name( + ((table or self.table_name) + "_" + '_'.join(column_name) + + "_index")) for k in column_name: if k in self._columns: @@ -348,7 +350,7 @@ class TableHandler(TableHandlerInterface): raise Exception('Not null action not supported!') def add_constraint(self, ident, constraint, exception=False): - ident = self.table_name + "_" + ident + ident = self.convert_name(self.table_name + "_" + ident) if ident in self._constraints: # This constrain already exists return @@ -371,7 +373,7 @@ class TableHandler(TableHandlerInterface): self._update_definitions(constraints=True) def drop_constraint(self, ident, exception=False, table=None): - ident = (table or self.table_name) + "_" + ident + ident = self.convert_name((table or self.table_name) + "_" + ident) if ident not in self._constraints: return diff --git a/trytond/backend/postgresql/table.py b/trytond/backend/postgresql/table.py index f2cacb8a30..f09172d379 100644 --- a/trytond/backend/postgresql/table.py +++ b/trytond/backend/postgresql/table.py @@ -13,6 +13,7 @@ VARCHAR_SIZE_RE = re.compile('VARCHAR\(([0-9]+)\)') class TableHandler(TableHandlerInterface): + namedatalen = 64 def __init__(self, model, module_name=None, history=False): super(TableHandler, self).__init__(model, @@ -314,17 +315,14 @@ class TableHandler(TableHandlerInterface): on_delete = 'SET NULL' cursor = Transaction().connection.cursor() - name = self.table_name + '_' + column_name + '_fkey' - cursor.execute('SELECT 1 ' - 'FROM information_schema.key_column_usage ' - 'WHERE table_name = %s AND table_schema = %s ' - 'AND constraint_name = %s', - (self.table_name, self.table_schema, name)) - add = False - if not cursor.rowcount: - add = True - elif self._fk_deltypes.get(column_name) != on_delete: - self.drop_fk(column_name) + name = self.convert_name(self.table_name + '_' + column_name + '_fkey') + if name in self._constraints: + if self._fk_deltypes.get(column_name) != on_delete: + self.drop_fk(column_name) + add = True + else: + add = False + else: add = True if add: cursor.execute('ALTER TABLE "' + self.table_name + '" ' @@ -340,16 +338,13 @@ class TableHandler(TableHandlerInterface): def index_action(self, column_name, action='add', table=None): if isinstance(column_name, basestring): column_name = [column_name] - index_name = ((table or self.table_name) + "_" + '_'.join(column_name) - + "_index") - if self._indexes: - test_index_name = index_name[:max(map(len, self._indexes))] - else: - test_index_name = index_name + index_name = self.convert_name( + ((table or self.table_name) + "_" + '_'.join(column_name) + + "_index")) with Transaction().connection.cursor() as cursor: if action == 'add': - if test_index_name in self._indexes: + if index_name in self._indexes: return cursor.execute('CREATE INDEX "' + index_name + '" ' 'ON "' + self.table_name + '" ( ' @@ -361,7 +356,7 @@ class TableHandler(TableHandlerInterface): self.module_name) != self.module_name): return - if test_index_name in self._indexes: + if index_name in self._indexes: cursor.execute('DROP INDEX "%s" ' % (index_name,)) self._update_definitions(indexes=True) else: @@ -407,7 +402,7 @@ class TableHandler(TableHandlerInterface): raise Exception('Not null action not supported!') def add_constraint(self, ident, constraint, exception=False): - ident = self.table_name + "_" + ident + ident = self.convert_name(self.table_name + "_" + ident) if ident in self._constraints: # This constrain already exist return @@ -429,7 +424,7 @@ class TableHandler(TableHandlerInterface): self._update_definitions(constraints=True) def drop_constraint(self, ident, exception=False, table=None): - ident = (table or self.table_name) + "_" + ident + ident = self.convert_name((table or self.table_name) + "_" + ident) if ident not in self._constraints: return cursor = Transaction().connection.cursor() diff --git a/trytond/backend/sqlite/table.py b/trytond/backend/sqlite/table.py index c45502cf86..a4190372d2 100644 --- a/trytond/backend/sqlite/table.py +++ b/trytond/backend/sqlite/table.py @@ -248,7 +248,8 @@ class TableHandler(TableHandlerInterface): def index_action(self, column_name, action='add', table=None): if isinstance(column_name, basestring): column_name = [column_name] - index_name = self.table_name + "_" + '_'.join(column_name) + "_index" + index_name = self.convert_name( + self.table_name + "_" + '_'.join(column_name) + "_index") cursor = Transaction().connection.cursor() if action == 'add': diff --git a/trytond/backend/table.py b/trytond/backend/table.py index 53261f6e00..093d2a7b13 100644 --- a/trytond/backend/table.py +++ b/trytond/backend/table.py @@ -1,11 +1,13 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. +import hashlib class TableHandlerInterface(object): ''' Define generic interface to handle database table ''' + namedatalen = None def __init__(self, model, module_name=None, history=False): ''' @@ -204,3 +206,14 @@ class TableHandlerInterface(object): :param cascade: a boolean to add "CASCADE" to the delete query ''' raise NotImplementedError + + @classmethod + def convert_name(cls, name): + ''' + Convert data name in respect of namedatalen. + + :param name: the data name + ''' + if cls.namedatalen and len(name) >= cls.namedatalen: + name = hashlib.sha256(name).hexdigest()[:cls.namedatalen - 1] + return name diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 11e38707c8..9bb8c33469 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -261,6 +261,7 @@ class ModelSQL(ModelStorage): def __raise_integrity_error( cls, exception, values, field_names=None, transaction=None): pool = Pool() + TableHandler = backend.get('TableHandler') if field_names is None: field_names = cls._fields.keys() if transaction is None: @@ -293,10 +294,10 @@ class ModelSQL(ModelStorage): cls.raise_user_error('foreign_model_missing', error_args=error_args) for name, _, error in cls._sql_constraints: - if name in str(exception): + if TableHandler.convert_name(name) in str(exception): cls.raise_user_error(error) for name, error in cls._sql_error_messages.iteritems(): - if name in str(exception): + if TableHandler.convert_name(name) in str(exception): cls.raise_user_error(error) @classmethod