Files
tradon/backend/table.py
2025-12-26 13:11:43 +00:00

141 lines
4.1 KiB
Python
Executable File

# 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
from weakref import WeakKeyDictionary
from trytond.transaction import Transaction
class TableHandlerInterface(object):
'''
Define generic interface to handle database table
'''
namedatalen = None
index_translators = None
__handlers = WeakKeyDictionary()
def __new__(cls, model, history=False):
transaction = Transaction()
handlers = cls.__handlers.setdefault(transaction, {})
key = (model.__name__, history)
if key not in handlers:
instance = handlers[key] = super().__new__(cls)
instance._init(model, history=history)
return handlers[key]
def _init(self, model, history=False):
'''
:param model: the Model linked to the table
:param module_name: the module name
:param history: a boolean to define if it is a history table
'''
super(TableHandlerInterface, self).__init__()
if history:
self.table_name = model._table + '__history'
else:
self.table_name = model._table
self.object_name = model.__name__
if history:
self.sequence_name = self.table_name + '___id_seq'
else:
self.sequence_name = self.table_name + '_id_seq'
self.history = history
@classmethod
def table_exist(cls, table_name):
raise NotImplementedError
@classmethod
def table_rename(cls, old_name, new_name):
raise NotImplementedError
def column_exist(self, column_name):
raise NotImplementedError
def column_rename(self, old_name, new_name):
raise NotImplementedError
def alter_size(self, column_name, column_type):
raise NotImplementedError
def alter_type(self, column_name, column_type):
raise NotImplementedError
def column_is_type(self, column_name, type_, *, size=-1):
raise NotImplementedError
def db_default(self, column_name, value):
raise NotImplementedError
def add_column(self, column_name, abstract_type, default=None, comment=''):
raise NotImplementedError
def add_fk(self, columns, reference, ref_columns=None, on_delete=None):
raise NotImplementedError
def drop_fk(self, columns, ref_columns=None, table=None):
raise NotImplementedError
def not_null_action(self, column_name, action='add'):
raise NotImplementedError
def add_constraint(self, ident, constraint):
raise NotImplementedError
def drop_constraint(self, ident, table=None):
raise NotImplementedError
def create_index(self, index):
raise NotImplementedError
def drop_column(self, column_name):
raise NotImplementedError
@classmethod
def drop_table(cls, model, table, cascade=False):
raise NotImplementedError
@classmethod
def convert_name(cls, name, reserved=0):
if cls.namedatalen:
length = cls.namedatalen - reserved
if length <= 0:
raise ValueError
if len(name) >= length:
if isinstance(name, str):
name = name.encode('utf-8')
name = hashlib.sha256(name).hexdigest()[:length - 1]
return name
def set_indexes(self, indexes, concurrently=False):
raise NotImplementedError
def index_translator_for(self, index):
return next(
filter(
lambda t: t.score(index) > 0,
sorted(
self.index_translators, key=lambda t: t.score(index),
reverse=True)),
None)
class IndexTranslatorInterface:
@classmethod
def _get_name(cls, query, params):
def hash_(s):
return hashlib.shake_128(s.encode('utf-8')).hexdigest(16)
names = [str(query)]
if params:
names.append(str(params))
return '_'.join(map(hash_, names))
@classmethod
def definition(cls, index):
raise NotImplementedError
@classmethod
def score(cls, index):
raise NotImplementedError