Files
tradon/model/union.py
2025-12-26 13:11:43 +00:00

69 lines
2.1 KiB
Python
Executable File

# This file is part of Tryton. The COPYRIGHT file at the toplevel of this
# repository contains the full copyright notices and license terms.
from sql import Column, Literal, Union
from trytond.model import fields
from trytond.pool import Pool
class UnionMixin:
'Mixin to combine models'
__slots__ = ()
@staticmethod
def union_models():
return []
@classmethod
def union_shard(cls, column, model):
models = cls.union_models()
length = len(models)
i = models.index(model)
return ((column * length) + i)
@classmethod
def union_unshard(cls, record_id):
pool = Pool()
models = cls.union_models()
length = len(models)
record_id, i = divmod(record_id, length)
Model = pool.get(models[i])
return Model(record_id)
@classmethod
def union_column(cls, name, field, table, Model):
column = Literal(None)
union_field = Model._fields.get(name)
if union_field:
column = Column(table, union_field.name)
if (isinstance(field, fields.Many2One)
and field.model_name == cls.__name__):
target_model = union_field.model_name
if target_model in cls.union_models():
column = cls.union_shard(column, target_model)
else:
column = Literal(None)
return column
@classmethod
def union_columns(cls, model):
pool = Pool()
Model = pool.get(model)
table = Model.__table__()
columns = [cls.union_shard(table.id, model).as_('id')]
for name in sorted(cls._fields.keys()):
field = cls._fields[name]
if name == 'id' or hasattr(field, 'set'):
continue
column = cls.union_column(name, field, table, Model)
columns.append(field.sql_cast(column).as_(name))
return table, columns
@classmethod
def table_query(cls):
queries = []
for model in cls.union_models():
table, columns = cls.union_columns(model)
queries.append(table.select(*columns))
return Union(*queries)