Add metadata columns to ModelSQL with table query

Closes #9414
This commit is contained in:
Cédric Krier
2024-10-25 00:24:39 +02:00
parent c40169b8a9
commit b26ff9757e
27 changed files with 54 additions and 165 deletions
+1 -5
View File
@@ -8,7 +8,7 @@ from itertools import groupby, zip_longest
from dateutil.relativedelta import relativedelta
from sql import Column, Literal, Null, Window
from sql.aggregate import Count, Max, Min, Sum
from sql.aggregate import Count, Min, Sum
from sql.conditionals import Case, Coalesce
from trytond import backend
@@ -3019,10 +3019,6 @@ class AgedBalance(ModelSQL, ModelView):
& (line.credit != 0))
columns = [
line.party.as_('id'),
Literal(0).as_('create_uid'),
Max(line.create_date).as_('create_date'),
Literal(0).as_('write_uid'),
Max(line.write_date).as_('write_date'),
line.party.as_('party'),
move.company.as_('company'),
(Sum(line.debit) - Sum(line.credit)).as_('balance'),
+2 -7
View File
@@ -1,7 +1,6 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from sql import Literal
from sql.aggregate import Max, Min, Sum
from sql.aggregate import Min, Sum
from trytond.model import ModelSQL, ModelView, fields
from trytond.modules.account.exceptions import FiscalYearNotFoundError
@@ -98,11 +97,7 @@ class BEVATCustomer(ModelSQL, ModelView):
.join(party_identifier,
condition=invoice.party_tax_identifier == party_identifier.id)
.select(
Max(invoice_tax.id).as_('id'),
Literal(0).as_('create_uid'),
Min(invoice_tax.create_date).as_('create_date'),
Literal(0).as_('write_uid'),
Max(invoice_tax.write_date).as_('write_date'),
Min(invoice_tax.id).as_('id'),
invoice.tax_identifier.as_('company_tax_identifier'),
invoice.party_tax_identifier.as_('party_tax_identifier'),
Sum(invoice_tax.base).as_('turnover'),
-8
View File
@@ -473,10 +473,6 @@ class ESVATList(ModelSQL, ModelView):
.join(company, condition=company.id == invoice.company)
.select(
Min(tax_line.id).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
invoice.tax_identifier.as_('company_tax_identifier'),
invoice.party.as_('party'),
invoice.party_tax_identifier.as_('party_tax_identifier'),
@@ -606,10 +602,6 @@ class ECOperationList(ECSalesList):
.join(company, condition=company.id == invoice.company)
.select(
Min(tax_line.id).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
invoice.tax_identifier.as_('company_tax_identifier'),
invoice.party.as_('party'),
invoice.party_tax_identifier.as_('party_tax_identifier'),
+1 -6
View File
@@ -1,8 +1,7 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from sql import Literal, Null
from sql import Null
from sql.aggregate import Min, Sum
from sql.functions import CurrentTimestamp
from trytond.model import ModelSQL, ModelView, fields
from trytond.modules.account.exceptions import FiscalYearNotFoundError
@@ -87,10 +86,6 @@ class ECSalesList(ModelSQL, ModelView):
.join(company, condition=company.id == invoice.company)
.select(
Min(tax_line.id).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
invoice.tax_identifier.as_('company_tax_identifier'),
invoice.party.as_('party'),
invoice.party_tax_identifier.as_('party_tax_identifier'),
+4 -19
View File
@@ -1,8 +1,8 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from sql import As, Literal, Null, Select, Window
from sql import As, Null, Select, Window
from sql.aggregate import BoolAnd, BoolOr, Min, Sum
from sql.functions import CurrentTimestamp, FirstValue
from sql.functions import FirstValue
from trytond.model import ModelSQL, ModelView, fields
from trytond.modules.account import MoveLineMixin
@@ -142,13 +142,7 @@ class MoveLineGroup(MoveLineMixin, ModelSQL, ModelView):
Line = pool.get('account.move.line')
line = Line.__table__()
std_columns = [
Min(line.id).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
]
std_columns = [Min(line.id).as_('id')]
grouped_columns = cls._grouped_columns(line)
aggregated_columns = cls._aggregated_columns(line)
@@ -229,13 +223,6 @@ class MoveLineGroup_MoveLine(ModelSQL):
database = transaction.database
line = Line.__table__()
std_columns = [
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
]
if database.has_window_functions():
grouped_columns = LineGroup._grouped_columns(line)
window = Window(
@@ -244,14 +231,12 @@ class MoveLineGroup_MoveLine(ModelSQL):
query = line.select(
line.id.as_('id'),
FirstValue(line.id, window=window).as_('group'),
line.id.as_('line'),
*std_columns)
line.id.as_('line'))
else:
query = Select(
Null.as_('id'),
Null.as_('group'),
Null.as_('line'),
*std_columns,
limit=0)
return query
@@ -7,7 +7,6 @@ import uuid
import braintree
from braintree.exceptions import TooManyRequestsError
from braintree.exceptions.braintree_error import BraintreeError
from sql import Literal
try:
from braintree.exceptions import GatewayTimeoutError
@@ -1214,10 +1213,6 @@ class PaymentBraintreeCustomerIdentical(ModelSQL):
source.braintree_customer_id
== target.braintree_customer_id))
.select(
Literal(0).as_('create_uid'),
source.create_date.as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
sql_pairing(source.id, target.id).as_('id'),
source.id.as_('source'),
target.id.as_('target'),
@@ -9,7 +9,6 @@ from itertools import groupby
from operator import attrgetter
import stripe
from sql import Literal
from trytond.cache import Cache
from trytond.config import config
@@ -1910,10 +1909,6 @@ class CustomerIdentical(ModelSQL):
source
.join(target, condition=source.fingerprint == target.fingerprint)
.select(
Literal(0).as_('create_uid'),
source.create_date.as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
sql_pairing(source.id, target.id).as_('id'),
source.customer.as_('source'),
target.customer.as_('target'),
-4
View File
@@ -420,10 +420,6 @@ class TemplateAccountCategory(ModelSQL):
template = Template.__table__()
return template.select(
template.id.as_('id'),
template.create_uid.as_('create_uid'),
template.create_date.as_('create_date'),
template.write_uid.as_('write_uid'),
template.write_date.as_('write_date'),
template.id.as_('template'),
template.account_category.as_('category'),
where=template.account_category != Null)
-4
View File
@@ -1129,10 +1129,6 @@ class LineGroup(ModelSQL, ModelView):
std_columns = [
move.id,
move.create_uid,
move.create_date,
move.write_uid,
move.write_date,
line.second_currency,
]
+2 -6
View File
@@ -6,9 +6,9 @@ import zipfile
from io import BytesIO, TextIOWrapper
from itertools import groupby
from sql import Literal, Null
from sql import Null
from sql.aggregate import Min, Sum
from sql.functions import CurrentTimestamp, Extract, Round
from sql.functions import Extract, Round
from trytond.cache import Cache
from trytond.model import (
@@ -325,10 +325,6 @@ class IntrastatDeclarationLine(ModelSQL, ModelView):
return (move
.select(
Min(move.id).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
*cls._columns(move),
where=where,
group_by=cls._group_by(move),
+2 -14
View File
@@ -5,10 +5,10 @@ import datetime as dt
from collections import defaultdict
from itertools import chain
from sql import Column, Literal, Null, Window
from sql import Column, Window
from sql.aggregate import Min, Sum
from sql.conditionals import Coalesce
from sql.functions import CurrentTimestamp, Function, NthValue
from sql.functions import Function, NthValue
from trytond import backend
from trytond.cache import Cache
@@ -350,10 +350,6 @@ class SheetLine(ModelSQL, ModelView):
duration = query.to - from_
return query.select(
query.id.as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
query.company.as_('company'),
query.employee.as_('employee'),
from_.as_('from_'),
@@ -387,10 +383,6 @@ class Sheet(ModelSQL, ModelView):
return line.select(
(Min(line.id * 2)).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
line.company.as_('company'),
line.employee.as_('employee'),
Sum(line.duration).as_('duration'),
@@ -424,10 +416,6 @@ class Sheet_Timesheet(metaclass=PoolMeta):
& (attendance.date == timesheet.date))
.select(
Coalesce(attendance.id, timesheet.id).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
Coalesce(attendance.company, timesheet.company).as_('company'),
Coalesce(
attendance.employee, timesheet.employee).as_('employee'),
+2 -6
View File
@@ -2,10 +2,10 @@
# this repository contains the full copyright notices and license terms.
from dateutil.relativedelta import relativedelta
from sql import Literal, Null
from sql import Null
from sql.aggregate import Count, Min, Sum
from sql.conditionals import Coalesce
from sql.functions import CurrentTimestamp, DateTrunc, Round
from sql.functions import DateTrunc, Round
from trytond.model import ModelSQL, ModelView, fields
from trytond.modules.currency.fields import Monetary
@@ -68,10 +68,6 @@ class Agent(ModelView, ModelSQL):
currency = tables['commission.agent.currency']
return [
cls._column_id(tables, withs).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
commission.agent.as_('agent'),
agent.currency.as_('currency'),
Count(commission.id, distinct=True).as_('number'),
@@ -2,10 +2,10 @@
# this repository contains the full copyright notices and license terms.
from dateutil.relativedelta import relativedelta
from sql import Literal, Null
from sql import Literal
from sql.aggregate import Count, Min
from sql.conditionals import NullIf
from sql.functions import CurrentTimestamp, DateTrunc, Round
from sql.functions import DateTrunc, Round
from trytond.model import ModelSQL, ModelView, fields
from trytond.pool import Pool
@@ -73,10 +73,6 @@ class Abstract(ModelSQL, ModelView):
def _columns(cls, tables, withs):
return [
cls._column_id(tables, withs).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
cls._column_date(tables, withs).as_('date'),
]
+2 -10
View File
@@ -1,9 +1,9 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from sql import Column, Literal, Window
from sql import Column, Window
from sql.aggregate import Max
from sql.conditionals import Coalesce
from sql.functions import CurrentTimestamp, LastValue
from sql.functions import LastValue
from trytond.model import ModelSQL, ModelView, convert_from, fields
from trytond.modules.product import round_price
@@ -117,10 +117,6 @@ class ProductCostHistory(ModelSQL, ModelView):
where=clause)
query = move_history.select(
Max(move_history.id).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
move_history.date.as_('date'),
move_history.product.as_('product'),
Max(move_history.cost_price).as_('cost_price'),
@@ -154,10 +150,6 @@ class ProductCostHistory(ModelSQL, ModelView):
query |= price_history.select(
Max(price_history.id).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
price_history.date.as_('date'),
price_history.product.as_('product'),
Max(price_history.cost_price).as_('cost_price'),
+2 -6
View File
@@ -2,10 +2,10 @@
# this repository contains the full copyright notices and license terms.
from dateutil.relativedelta import relativedelta
from sql import Literal, Null
from sql import Null
from sql.aggregate import Count, Min, Sum
from sql.conditionals import Coalesce
from sql.functions import CurrentTimestamp, DateTrunc
from sql.functions import DateTrunc
from trytond.i18n import lazy_gettext
from trytond.model import ModelSQL, ModelView, fields
@@ -68,10 +68,6 @@ class Abstract(ModelSQL):
Sum(quantity * line.unit_price))
return [
cls._column_id(tables).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
purchase.company.as_('company'),
purchase.currency.as_('currency'),
expense.as_('expense'),
+1 -5
View File
@@ -7,7 +7,7 @@ from dateutil.relativedelta import relativedelta
from sql import Column, Literal, Null, Union, With
from sql.aggregate import Count, Max, Min, Sum
from sql.conditionals import Coalesce
from sql.functions import Ceil, CurrentTimestamp, DateTrunc, Log, Power, Round
from sql.functions import Ceil, DateTrunc, Log, Power, Round
from sql.operators import Concat
from trytond.i18n import lazy_gettext
@@ -133,10 +133,6 @@ class Abstract(ModelSQL):
currency.digits)
return [
cls._column_id(tables, withs).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
line.company.as_('company'),
revenue.as_('revenue'),
Count(line.order, distinct=True).as_('number'),
@@ -5,7 +5,6 @@ from dateutil.relativedelta import relativedelta
from sql import Literal, Null, With
from sql.aggregate import Count, Min, Sum
from sql.conditionals import Case
from sql.functions import CurrentTimestamp
from trytond.i18n import lazy_gettext
from trytond.model import ModelSQL, ModelView, fields
@@ -120,10 +119,6 @@ class Abstract(ModelSQL):
opportunity = tables['opportunity']
return [
cls._column_id(tables, withs).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
opportunity.company.as_('company'),
Count(Literal(1)).as_('number'),
Sum(opportunity.amount).as_('amount'),
-4
View File
@@ -962,10 +962,6 @@ class POSCashSessionRelation(ModelSQL):
session = Session.__table__()
return session.select(
session.id.as_('id'),
session.create_date.as_('create_date'),
session.create_uid.as_('create_uid'),
session.write_date.as_('write_date'),
session.write_uid.as_('write_uid'),
session.previous_session.as_('previous'),
session.id.as_('next'))
-13
View File
@@ -10,7 +10,6 @@ from simpleeval import InvalidExpression, simple_eval
from sql import Literal, Null, Select, Window, With
from sql.aggregate import Max, Sum
from sql.conditionals import Case, Coalesce
from sql.functions import CurrentTimestamp
from sql.operators import Concat
from trytond.i18n import gettext
@@ -724,10 +723,6 @@ class ProductQuantitiesByWarehouse(ModelSQL, ModelView):
date_column = Coalesce(move.effective_date, move.planned_date)
query = (from_.select(
Max(move.id * 3).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
product_column.as_('product'),
date_column.as_('date'),
move.company.as_('company'),
@@ -749,10 +744,6 @@ class ProductQuantitiesByWarehouse(ModelSQL, ModelView):
gap = ['product.template', 'product.product'].index(model) + 1
query |= Select([
Literal(id_ * 3 + gap).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
Literal('%s,%s' % (model, id_)).as_('product'),
Literal(today).as_('date'),
Literal(context.get('company', -1)).as_('company'),
@@ -1006,10 +997,6 @@ class ProductQuantitiesByWarehouseMove(ModelSQL, ModelView):
cumulative_quantity_delta = Literal(0)
return (from_.select(
move.id.as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
Literal(None).as_('write_uid'),
Literal(None).as_('write_date'),
product_column.as_('product'),
date_column.as_('date'),
move.id.as_('move'),
+1 -5
View File
@@ -8,7 +8,7 @@ from dateutil.relativedelta import relativedelta
from sql import Literal, Null, With
from sql.aggregate import Max, Min, Sum
from sql.conditionals import Case, Coalesce
from sql.functions import Ceil, CurrentTimestamp, DateTrunc, Log, Power, Round
from sql.functions import Ceil, DateTrunc, Log, Power, Round
from trytond.i18n import lazy_gettext
from trytond.model import ModelSQL, ModelView, fields, sum_tree
@@ -119,10 +119,6 @@ class Abstract(ModelSQL, ModelView):
else_=Null)
return [
cls._column_id(tables, withs).as_('id'),
Literal(0).as_('create_uid'),
CurrentTimestamp().as_('create_date'),
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
move.company.as_('company'),
cls.cost.sql_cast(
Round(cost, currency.digits)).as_('cost'),
-4
View File
@@ -246,10 +246,6 @@ class LotTrace(ModelSQL, ModelView):
move = tables['move']
return [
move.id.as_('id'),
move.create_uid.as_('create_uid'),
move.create_date.as_('create_date'),
move.write_uid.as_('write_uid'),
move.write_date.as_('write_date'),
move.product.as_('product'),
move.lot.as_('lot'),
move.from_location.as_('from_location'),
-12
View File
@@ -239,10 +239,6 @@ class HoursEmployee(ModelSQL, ModelView):
where &= line.date <= Transaction().context['end_date']
return line.select(
line.employee.as_('id'),
Max(line.create_uid).as_('create_uid'),
Max(line.create_date).as_('create_date'),
Max(line.write_uid).as_('write_uid'),
Max(line.write_date).as_('write_date'),
line.employee,
Sum(line.duration).as_('duration'),
where=where,
@@ -280,10 +276,6 @@ class HoursEmployeeWeekly(ModelSQL, ModelView):
Max(Extract('WEEK', line.date)
+ Extract('YEAR', line.date) * 100
+ line.employee * 1000000).as_('id'),
Max(line.create_uid).as_('create_uid'),
Max(line.create_date).as_('create_date'),
Max(line.write_uid).as_('write_uid'),
Max(line.write_date).as_('write_date'),
year_column,
week_column,
line.employee,
@@ -318,10 +310,6 @@ class HoursEmployeeMonthly(ModelSQL, ModelView):
Max(Extract('MONTH', line.date)
+ Extract('YEAR', line.date) * 100
+ line.employee * 1000000).as_('id'),
Max(line.create_uid).as_('create_uid'),
Max(line.create_date).as_('create_date'),
Max(line.write_uid).as_('write_uid'),
Max(line.write_date).as_('write_date'),
year_column,
month.id.as_('month'),
line.employee,
+1
View File
@@ -1,3 +1,4 @@
* Add metadata columns to ModelSQL with table query
* Add report data to header_key
* Validate integer digits
* Add support for DATE_TRUNC from INTERVAL to SQLite backend
+3 -1
View File
@@ -668,7 +668,9 @@ Class methods:
Could be defined to use a custom SQL query instead of a table of the
database.
It should return a SQL FromItem.
It should return a SQL FromItem with a column ``id`` with a unique value and
a column for each field except for ``create_uid``, ``create_date``,
``write_uid`` and ``write_date``.
.. warning::
By default all CRUD operation raises an error on models implementing this
+8 -2
View File
@@ -551,10 +551,16 @@ class Field(object):
return translations
def searchable(self, model):
return hasattr(model, 'search')
from ..modelsql import _TABLE_QUERY_COLUMNS
return (hasattr(model, 'search')
and (not callable(getattr(model, 'table_query', None))
or self.name not in _TABLE_QUERY_COLUMNS))
def sortable(self, model):
return hasattr(model, 'search')
from ..modelsql import _TABLE_QUERY_COLUMNS
return (hasattr(model, 'search')
and (not callable(getattr(model, 'table_query', None))
or self.name not in _TABLE_QUERY_COLUMNS))
class FieldTranslate(Field):
+16 -2
View File
@@ -303,6 +303,14 @@ def apply_sorting(keywords):
return lambda col: NullOrdering(Order(col))
_TABLE_QUERY_COLUMNS = {
'create_uid': Literal(0),
'create_date': CurrentTimestamp(),
'write_uid': Literal(None),
'write_date': Literal(None),
}
class ModelSQL(ModelStorage):
"""
Define a model with storage in database.
@@ -1100,7 +1108,11 @@ class ModelSQL(ModelStorage):
for f in all_fields:
field = cls._fields.get(f)
if field and field.sql_type():
columns[f] = field.sql_column(table).as_(f)
if f in _TABLE_QUERY_COLUMNS and callable(cls.table_query):
column = _TABLE_QUERY_COLUMNS[f]
else:
column = field.sql_column(table)
columns[f] = column.as_(f)
if backend.name == 'sqlite':
columns[f].output_name += ' [%s]' % field.sql_type().base
elif f in {'_write', '_delete'}:
@@ -1812,13 +1824,15 @@ class ModelSQL(ModelStorage):
columns.append(Column(table, '__id').as_('__id'))
if eager:
table_query = callable(cls.table_query)
columns += [f.sql_column(table).as_(n)
for n, f in sorted(cls._fields.items())
if not hasattr(f, 'get')
and n != 'id'
and (not table_query or n not in _TABLE_QUERY_COLUMNS)
and not getattr(f, 'translate', False)
and f.loading == 'eager']
if not callable(cls.table_query):
if not table_query:
sql_type = fields.Char('timestamp').sql_type().base
columns += [Extract('EPOCH',
Coalesce(table.write_date, table.create_date)
+4 -1
View File
@@ -5,6 +5,8 @@ from sql import Column, Literal, Union
from trytond.model import fields
from trytond.pool import Pool
from .modelsql import _TABLE_QUERY_COLUMNS
class UnionMixin:
'Mixin to combine models'
@@ -53,7 +55,8 @@ class UnionMixin:
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'):
if (name == 'id' or name in _TABLE_QUERY_COLUMNS
or hasattr(field, 'set')):
continue
column = cls.union_column(name, field, table, Model)
columns.append(field.sql_cast(column).as_(name))