details: https://code.tryton.org/tryton/commit/9895805863b9
branch: default
user: Cédric Krier <[email protected]>
date: Fri Dec 26 10:57:44 2025 +0100
description:
Deprecate reduce_ids for SQL_OPERATORS['in']
Closes #12989 #13897
diffstat:
modules/account/account.py | 29 +++++++----
modules/account/company.py | 5 +-
modules/account/journal.py | 6 +-
modules/account/move.py | 21 +++++---
modules/account/party.py | 5 +-
modules/account_budget/account.py | 11 ++--
modules/account_deposit/party.py | 5 +-
modules/account_invoice/invoice.py | 13 ++--
modules/account_invoice_history/account.py | 4 +-
modules/account_payment/account.py | 5 +-
modules/account_payment/payment.py | 8 +-
modules/account_payment_clearing/payment.py | 5 +-
modules/account_payment_sepa/payment.py | 12 ++--
modules/account_statement/journal.py | 10 ++--
modules/analytic_budget/analytic_account.py | 3 +-
modules/commission/commission.py | 5 +-
modules/marketing_automation/marketing_automation.py | 12 ++--
modules/marketing_email/marketing.py | 5 +-
modules/product_price_list_cache/product.py | 15 +++--
modules/production_work/work.py | 5 +-
modules/project_invoice/invoice.py | 4 +-
modules/project_invoice/project.py | 11 ++--
modules/project_revenue/work.py | 8 +-
modules/purchase/product.py | 5 +-
modules/purchase_history/purchase.py | 5 +-
modules/sale/sale_reporting.py | 8 ++-
modules/sale_history/sale.py | 5 +-
modules/sale_point/sale.py | 8 ++-
modules/sale_promotion_coupon/sale.py | 5 +-
modules/stock/move.py | 11 ++--
modules/stock/product.py | 14 +++--
modules/stock/stock_reporting_margin.py | 5 +-
modules/stock_forecast/forecast.py | 6 +-
modules/stock_quantity_issue/stock.py | 3 +-
modules/stock_shipment_measurements/stock.py | 8 ++-
modules/stock_supply/purchase_request.py | 4 +-
modules/stock_supply/shipment.py | 4 +-
modules/timesheet/work.py | 6 +-
modules/web_shortener/web.py | 4 +-
trytond/CHANGELOG | 1 +
trytond/trytond/ir/cron.py | 4 +-
trytond/trytond/ir/note.py | 4 +-
trytond/trytond/ir/trigger.py | 11 ++--
trytond/trytond/model/modelsql.py | 1 -
trytond/trytond/tests/test_tools.py | 48 +-------------------
trytond/trytond/tools/misc.py | 48 ++-----------------
46 files changed, 191 insertions(+), 234 deletions(-)
diffs (1431 lines):
diff -r 65be67251d10 -r 9895805863b9 modules/account/account.py
--- a/modules/account/account.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account/account.py Fri Dec 26 10:57:44 2025 +0100
@@ -22,8 +22,8 @@
from trytond.pyson import Bool, Eval, Id, If, PYSONEncoder
from trytond.report import Report
from trytond.tools import (
- grouped_slice, is_full_text, lstrip_wildcard, pair, reduce_ids,
- sql_pairing, sqlite_apply_types)
+ grouped_slice, is_full_text, lstrip_wildcard, pair, sql_pairing,
+ sqlite_apply_types)
from trytond.transaction import Transaction, check_access, inactive_records
from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
@@ -1019,7 +1019,7 @@
with transaction.set_context(company=company.id):
line_query, fiscalyear_ids = MoveLine.query_get(line)
for sub_ids in grouped_slice(ids):
- red_sql = reduce_ids(table_a.id, sub_ids)
+ red_sql = fields.SQL_OPERATORS['in'](table_a.id, sub_ids)
if context.get('flat_balance'):
query = (table_a
.join(line, condition=line.account == table_a.id))
@@ -1092,7 +1092,7 @@
Sum(Coalesce(Column(line, name), 0)).as_(name))
types.append('NUMERIC')
for sub_ids in grouped_slice(ids):
- red_sql = reduce_ids(table.id, sub_ids)
+ red_sql = fields.SQL_OPERATORS['in'](table.id, sub_ids)
query = (table.join(line, 'LEFT',
condition=line.account == table.id
).select(*columns,
@@ -1531,9 +1531,11 @@
with transaction.set_context(company=company.id):
line_query, fiscalyear_ids = MoveLine.query_get(line)
for sub_account_ids in grouped_slice(account_ids):
- account_sql = reduce_ids(table_a.id, sub_account_ids)
+ account_sql = fields.SQL_OPERATORS['in'](
+ table_a.id, sub_account_ids)
for sub_party_ids in grouped_slice(party_ids):
- party_sql = reduce_ids(line.party, sub_party_ids)
+ party_sql = fields.SQL_OPERATORS['in'](
+ line.party, sub_party_ids)
if context.get('flat_balance'):
query = (table_a
.join(line, condition=line.account == table_a.id))
@@ -1608,9 +1610,11 @@
line_query, fiscalyear_ids = MoveLine.query_get(line)
for sub_account_ids in grouped_slice(account_ids):
- account_sql = reduce_ids(table.id, sub_account_ids)
+ account_sql = fields.SQL_OPERATORS['in'](
+ table.id, sub_account_ids)
for sub_party_ids in grouped_slice(party_ids):
- party_sql = reduce_ids(line.party, sub_party_ids)
+ party_sql = fields.SQL_OPERATORS['in'](
+ line.party, sub_party_ids)
query = (table.join(line, 'LEFT',
condition=line.account == table.id
).select(*columns,
@@ -1750,7 +1754,8 @@
balances = defaultdict(Decimal)
for sub_deferrals in grouped_slice(deferrals):
- red_sql = reduce_ids(table.id, [d.id for d in sub_deferrals])
+ red_sql = fields.SQL_OPERATORS['in'](
+ table.id, [d.id for d in sub_deferrals])
query = (table
.join(account, condition=table.account == account.id)
.join(account_child,
@@ -2487,10 +2492,12 @@
query = account_party.select(
account_party.account, account_party.party, account_party.id)
for sub_account_ids in grouped_slice(account_ids):
- account_where = reduce_ids(account_party.account, sub_account_ids)
+ account_where = fields.SQL_OPERATORS['in'](
+ account_party.account, sub_account_ids)
for sub_party_ids in grouped_slice(party_ids):
query.where = (account_where
- & reduce_ids(account_party.party, sub_party_ids))
+ & fields.SQL_OPERATORS['in'](
+ account_party.party, sub_party_ids))
cursor.execute(*query)
for account, party, id_ in cursor:
key = (account, party)
diff -r 65be67251d10 -r 9895805863b9 modules/account/company.py
--- a/modules/account/company.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account/company.py Fri Dec 26 10:57:44 2025 +0100
@@ -12,7 +12,7 @@
from trytond.model.exceptions import AccessError
from trytond.modules.currency.fields import Monetary
from trytond.pool import Pool, PoolMeta
-from trytond.tools import grouped_slice, reduce_ids, sqlite_apply_types
+from trytond.tools import grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction
@@ -67,7 +67,8 @@
today_where = Literal(True)
for sub_companies in grouped_slice(companies):
sub_ids = [p.id for p in sub_companies]
- company_where = reduce_ids(account.company, sub_ids)
+ company_where = fields.SQL_OPERATORS['in'](
+ account.company, sub_ids)
query = (line
.join(account,
condition=account.id == line.account)
diff -r 65be67251d10 -r 9895805863b9 modules/account/journal.py
--- a/modules/account/journal.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account/journal.py Fri Dec 26 10:57:44 2025 +0100
@@ -14,8 +14,7 @@
from trytond.pool import Pool
from trytond.pyson import Eval
from trytond.tools import (
- grouped_slice, is_full_text, lstrip_wildcard, reduce_ids,
- sqlite_apply_types)
+ grouped_slice, is_full_text, lstrip_wildcard, sqlite_apply_types)
from trytond.transaction import Transaction
STATES = {
@@ -115,7 +114,8 @@
& (move.company == company.id))
for sub_journals in grouped_slice(journals):
sub_journals = list(sub_journals)
- red_sql = reduce_ids(move.journal, [j.id for j in sub_journals])
+ red_sql = fields.SQL_OPERATORS['in'](
+ move.journal, [j.id for j in sub_journals])
query = line.join(move, 'LEFT', condition=line.move == move.id
).join(account, 'LEFT', condition=line.account == account.id
).join(account_type, 'LEFT',
diff -r 65be67251d10 -r 9895805863b9 modules/account/move.py
--- a/modules/account/move.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account/move.py Fri Dec 26 10:57:44 2025 +0100
@@ -21,8 +21,7 @@
from trytond.pyson import Bool, Eval, If, PYSONEncoder
from trytond.report import Report
from trytond.rpc import RPC
-from trytond.tools import (
- firstline, grouped_slice, reduce_ids, sqlite_apply_types)
+from trytond.tools import firstline, grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction, check_access
from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
@@ -363,7 +362,8 @@
for company, moves in groupby(moves, key=lambda m: m.company):
currency = company.currency
for sub_moves in grouped_slice(list(moves)):
- red_sql = reduce_ids(line.move, [m.id for m in sub_moves])
+ red_sql = fields.SQL_OPERATORS['in'](
+ line.move, [m.id for m in sub_moves])
valid_move_query = line.select(
line.move,
@@ -465,7 +465,8 @@
cursor.execute(*move.select(
move.id,
- where=reduce_ids(move.id, sub_moves_ids)
+ where=fields.SQL_OPERATORS['in'](
+ move.id, sub_moves_ids)
& ~Exists(line.select(
line.move,
where=line.move == move.id))))
@@ -480,7 +481,8 @@
cursor.execute(*line.select(
line.move,
- where=reduce_ids(line.move, sub_moves_ids),
+ where=fields.SQL_OPERATORS['in'](
+ line.move, sub_moves_ids),
group_by=line.move,
having=Abs(Round(
Sum(line.debit - line.credit),
@@ -496,7 +498,8 @@
cursor.execute(*line.select(
line.id,
- where=reduce_ids(line.move, sub_moves_ids)
+ where=fields.SQL_OPERATORS['in'](
+ line.move, sub_moves_ids)
& (line.debit == Decimal(0))
& (line.credit == Decimal(0))
& (line.reconciliation == Null)
@@ -864,7 +867,8 @@
parties = {l.party for l in sub_lines}
if None in parties:
party_where |= line.party == parties.discard(None)
- party_where |= reduce_ids(line.party, map(int, parties))
+ party_where |= fields.SQL_OPERATORS['in'](
+ line.party, map(int, parties))
where &= party_where
query = (line
@@ -878,7 +882,8 @@
where=where))
query = query.select(
query.id, query.balance.as_('balance'),
- where=reduce_ids(query.id, [l.id for l in sub_lines]))
+ where=fields.SQL_OPERATORS['in'](
+ query.id, [l.id for l in sub_lines]))
if backend.name == 'sqlite':
sqlite_apply_types(query, [None, 'NUMERIC'])
cursor.execute(*query)
diff -r 65be67251d10 -r 9895805863b9 modules/account/party.py
--- a/modules/account/party.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account/party.py Fri Dec 26 10:57:44 2025 +0100
@@ -16,7 +16,7 @@
from trytond.modules.party.exceptions import EraseError
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, If
-from trytond.tools import grouped_slice, reduce_ids, sqlite_apply_types
+from trytond.tools import grouped_slice, sqlite_apply_types
from trytond.tools import timezone as tz
from trytond.transaction import Transaction
@@ -165,7 +165,8 @@
columns.append(Coalesce(expressions[name], Decimal()).as_(name))
if parties is not None:
- party_where = reduce_ids(move_line.party, [p.id for p in parties])
+ party_where = fields.SQL_OPERATORS['in'](
+ move_line.party, [p.id for p in parties])
else:
party_where = Literal(True)
diff -r 65be67251d10 -r 9895805863b9 modules/account_budget/account.py
--- a/modules/account_budget/account.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account_budget/account.py Fri Dec 26 10:57:44 2025 +0100
@@ -17,7 +17,7 @@
from trytond.pool import Pool
from trytond.pyson import Bool, Eval, If
from trytond.rpc import RPC
-from trytond.tools import grouped_slice, reduce_ids, sqlite_apply_types
+from trytond.tools import grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction
from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
@@ -213,7 +213,7 @@
sqlite_apply_types(query, [None, 'NUMERIC'])
for sub_ids in grouped_slice(ids):
- query.where = reduce_ids(table.id, sub_ids)
+ query.where = fields.SQL_OPERATORS['in'](table.id, sub_ids)
cursor.execute(*query)
amounts.update(cursor)
@@ -549,7 +549,7 @@
line = Line.__table__()
amount = Sum(Coalesce(line.credit, 0) - Coalesce(line.debit, 0))
- red_sql = reduce_ids(table.id, [r.id for r in records])
+ red_sql = fields.SQL_OPERATORS['in'](table.id, [r.id for r in records])
periods = Transaction().context.get('periods')
if not periods:
periods = [p.id for p in Period.search([
@@ -693,7 +693,7 @@
line = MoveLine.__table__()
amount = Sum(Coalesce(line.credit, 0) - Coalesce(line.debit, 0))
- red_sql = reduce_ids(table.id, [r.id for r in records])
+ red_sql = fields.SQL_OPERATORS['in'](table.id, [r.id for r in records])
periods = Transaction().context.get('periods')
if not periods:
periods = [p.id for p in Period.search([
@@ -737,7 +737,8 @@
for sub_ids in grouped_slice({p.budget_line.id for p in periods}):
cursor.execute(*table.select(
table.budget_line,
- where=reduce_ids(table.budget_line, sub_ids),
+ where=fields.SQL_OPERATORS['in'](
+ table.budget_line, sub_ids),
group_by=table.budget_line,
having=Sum(table.ratio) > 1,
limit=1))
diff -r 65be67251d10 -r 9895805863b9 modules/account_deposit/party.py
--- a/modules/account_deposit/party.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account_deposit/party.py Fri Dec 26 10:57:44 2025 +0100
@@ -12,7 +12,7 @@
from trytond.modules.currency.fields import Monetary
from trytond.modules.party.exceptions import EraseError
from trytond.pool import Pool, PoolMeta
-from trytond.tools import grouped_slice, reduce_ids, sqlite_apply_types
+from trytond.tools import grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction
@@ -46,7 +46,8 @@
line_clause, _ = MoveLine.query_get(line)
for sub_parties in grouped_slice(parties):
- party_clause = reduce_ids(line.party, [p.id for p in sub_parties])
+ party_clause = fields.SQL_OPERATORS['in'](
+ line.party, [p.id for p in sub_parties])
query = (line
.join(account, condition=account.id == line.account)
.join(account_type, condition=account.type == account_type.id)
diff -r 65be67251d10 -r 9895805863b9 modules/account_invoice/invoice.py
--- a/modules/account_invoice/invoice.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account_invoice/invoice.py Fri Dec 26 10:57:44 2025 +0100
@@ -32,8 +32,7 @@
from trytond.report import Report
from trytond.rpc import RPC
from trytond.tools import (
- cached_property, firstline, grouped_slice, reduce_ids, slugify,
- sqlite_apply_types)
+ cached_property, firstline, grouped_slice, slugify, sqlite_apply_types)
from trytond.transaction import Transaction
from trytond.wizard import (
Button, StateAction, StateReport, StateTransition, StateView, Wizard)
@@ -829,8 +828,9 @@
type_name = cls.tax_amount._field.sql_type().base
tax = InvoiceTax.__table__()
- for sub_ids in grouped_slice(invoices_no_cache):
- red_sql = reduce_ids(tax.invoice, sub_ids)
+ for sub_invoices in grouped_slice(invoices_no_cache):
+ red_sql = fields.SQL_OPERATORS['in'](
+ tax.invoice, map(int, sub_invoices))
query = (tax.select(tax.invoice,
Coalesce(Sum(tax.amount), 0).as_(type_name),
where=red_sql,
@@ -885,7 +885,8 @@
invoice = cls.__table__()
additional_move = AdditionalMove.__table__()
- red_sql = reduce_ids(invoice.id, invoices)
+ red_sql = fields.SQL_OPERATORS['in'](
+ invoice.id, map(int, invoices))
query = (invoice
.join(line,
condition=((invoice.move == line.move)
@@ -1152,7 +1153,7 @@
for sub_invoices in grouped_slice(invoices):
sub_ids = map(int, sub_invoices)
cursor.execute(*table.select(table.id, has_cache,
- where=reduce_ids(table.id, sub_ids)))
+ where=fields.SQL_OPERATORS['in'](table.id, sub_ids)))
result.update(cursor)
return result
diff -r 65be67251d10 -r 9895805863b9 modules/account_invoice_history/account.py
--- a/modules/account_invoice_history/account.py Fri Dec 26 10:58:30
2025 +0100
+++ b/modules/account_invoice_history/account.py Fri Dec 26 10:57:44
2025 +0100
@@ -7,7 +7,7 @@
from trytond import backend
from trytond.model import ModelView, Workflow, fields
from trytond.pool import Pool, PoolMeta
-from trytond.tools import grouped_slice, reduce_ids, sqlite_apply_types
+from trytond.tools import grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction
@@ -55,7 +55,7 @@
Greatest(table.numbered_at, party.create_date,
address.create_date, identifier.create_date,
payment_term.create_date).as_('history_datetime'),
- where=reduce_ids(table.id, ids)
+ where=fields.SQL_OPERATORS['in'](table.id, ids)
& (table.numbered_at != Null)
& (table.state.in_(cls._history_states()))))
if backend.name == 'sqlite':
diff -r 65be67251d10 -r 9895805863b9 modules/account_payment/account.py
--- a/modules/account_payment/account.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account_payment/account.py Fri Dec 26 10:57:44 2025 +0100
@@ -19,7 +19,7 @@
from trytond.modules.currency.fields import Monetary
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, Id, If
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction, check_access, without_check_access
from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
@@ -195,7 +195,8 @@
for sub_lines in grouped_slice(lines):
query.where = (
table.account.in_(accounts)
- & reduce_ids(table.id, map(int, sub_lines)))
+ & fields.SQL_OPERATORS['in'](
+ table.id, map(int, sub_lines)))
cursor.execute(*query)
else:
cursor.execute(*query)
diff -r 65be67251d10 -r 9895805863b9 modules/account_payment/payment.py
--- a/modules/account_payment/payment.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account_payment/payment.py Fri Dec 26 10:57:44 2025 +0100
@@ -22,8 +22,7 @@
from trytond.pyson import Eval, If
from trytond.rpc import RPC
from trytond.tools import (
- cursor_dict, grouped_slice, reduce_ids, sortable_values,
- sqlite_apply_types)
+ cursor_dict, grouped_slice, sortable_values, sqlite_apply_types)
from trytond.transaction import Transaction
from trytond.wizard import StateAction, Wizard
@@ -202,9 +201,10 @@
).as_('payment_not_complete'),
]
- for sub_ids in grouped_slice(groups):
+ for sub_groups in grouped_slice(groups):
query = payment.select(*columns,
- where=reduce_ids(payment.group, sub_ids),
+ where=fields.SQL_OPERATORS['in'](
+ payment.group, map(int, sub_groups)),
group_by=payment.group)
if backend.name == 'sqlite':
sqlite_apply_types(
diff -r 65be67251d10 -r 9895805863b9 modules/account_payment_clearing/payment.py
--- a/modules/account_payment_clearing/payment.py Fri Dec 26 10:58:30
2025 +0100
+++ b/modules/account_payment_clearing/payment.py Fri Dec 26 10:57:44
2025 +0100
@@ -13,7 +13,7 @@
from trytond.modules.account.exceptions import AccountMissing
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, If, TimeDelta
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
from trytond.wizard import Button, StateTransition, StateView, Wizard
@@ -447,7 +447,8 @@
for sub_groups in grouped_slice(groups):
cursor.execute(*payment.select(
payment.group, column,
- where=reduce_ids(payment.group, sub_groups),
+ where=fields.SQL_OPERATORS['in'](
+ payment.group, map(int, sub_groups)),
group_by=payment.group))
result.update(cursor)
return result
diff -r 65be67251d10 -r 9895805863b9 modules/account_payment_sepa/payment.py
--- a/modules/account_payment_sepa/payment.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account_payment_sepa/payment.py Fri Dec 26 10:57:44 2025 +0100
@@ -26,7 +26,7 @@
from trytond.pyson import Eval, If
from trytond.report import Report
from trytond.tools import (
- cached_property, grouped_slice, is_full_text, lstrip_wildcard, reduce_ids,
+ cached_property, grouped_slice, is_full_text, lstrip_wildcard,
sortable_values)
from trytond.transaction import Transaction
@@ -786,8 +786,9 @@
cursor = Transaction().connection.cursor()
has_payments = dict.fromkeys([m.id for m in mandates], False)
- for sub_ids in grouped_slice(mandates):
- red_sql = reduce_ids(payment.sepa_mandate, sub_ids)
+ for sub_mandates in grouped_slice(mandates):
+ red_sql = fields.SQL_OPERATORS['in'](
+ payment.sepa_mandate, map(int, sub_mandates))
cursor.execute(*payment.select(payment.sepa_mandate, Literal(True),
where=red_sql,
group_by=payment.sepa_mandate))
@@ -803,8 +804,9 @@
cursor = Transaction().connection.cursor()
is_first = dict.fromkeys([m.id for m in mandates], True)
- for sub_ids in grouped_slice(mandates):
- red_sql = reduce_ids(payment.sepa_mandate, sub_ids)
+ for sub_mandates in grouped_slice(mandates):
+ red_sql = fields.SQL_OPERATORS['in'](
+ payment.sepa_mandate, map(int, sub_mandates))
cursor.execute(*payment.select(
payment.sepa_mandate, Literal(False),
where=red_sql
diff -r 65be67251d10 -r 9895805863b9 modules/account_statement/journal.py
--- a/modules/account_statement/journal.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/account_statement/journal.py Fri Dec 26 10:57:44 2025 +0100
@@ -10,8 +10,7 @@
from trytond.pool import Pool
from trytond.pyson import Eval
from trytond.rpc import RPC
-from trytond.tools import (
- cursor_dict, grouped_slice, reduce_ids, sqlite_apply_types)
+from trytond.tools import cursor_dict, grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction
@@ -145,9 +144,10 @@
columns.append(
FirstValue(statement.date, window=w).as_('last_date'))
query = statement.select(*columns,
- distinct=True,
- where=reduce_ids(statement.journal, sub_ids)
- & (statement.state != 'cancelled'))
+ distinct=True,
+ where=(fields.SQL_OPERATORS['in'](
+ statement.journal, sub_ids)
+ & (statement.state != 'cancelled')))
if backend.name == 'sqlite':
types = [None]
if 'last_amount' in names:
diff -r 65be67251d10 -r 9895805863b9 modules/analytic_budget/analytic_account.py
--- a/modules/analytic_budget/analytic_account.py Fri Dec 26 10:58:30
2025 +0100
+++ b/modules/analytic_budget/analytic_account.py Fri Dec 26 10:57:44
2025 +0100
@@ -8,7 +8,6 @@
BudgetLineMixin, BudgetMixin, CopyBudgetMixin, CopyBudgetStartMixin)
from trytond.pool import Pool
from trytond.pyson import Eval
-from trytond.tools import reduce_ids
from trytond.transaction import Transaction
from trytond.wizard import Button, StateAction, StateView, Wizard
@@ -179,7 +178,7 @@
children = cls.__table__()
balance = Sum(Coalesce(line.credit, 0) - Coalesce(line.debit, 0))
- red_sql = reduce_ids(table.id, [r.id for r in records])
+ red_sql = fields.SQL_OPERATORS['in'](table.id, [r.id for r in records])
with Transaction().set_context(context):
query_where = Line.query_get(line)
return (table
diff -r 65be67251d10 -r 9895805863b9 modules/commission/commission.py
--- a/modules/commission/commission.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/commission/commission.py Fri Dec 26 10:57:44 2025 +0100
@@ -21,8 +21,7 @@
from trytond.modules.product import price_digits, round_price
from trytond.pool import Pool
from trytond.pyson import Bool, Eval, Id, If
-from trytond.tools import (
- decistmt, grouped_slice, reduce_ids, sqlite_apply_types)
+from trytond.tools import decistmt, grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction, check_access
from trytond.wizard import Button, StateAction, StateView, Wizard
@@ -129,7 +128,7 @@
ids = [a.id for a in agents]
amounts = dict.fromkeys(ids, None)
for sub_ids in grouped_slice(ids):
- where = reduce_ids(commission.agent, sub_ids)
+ where = fields.SQL_OPERATORS['in'](commission.agent, sub_ids)
where &= commission.invoice_line == Null
query = commission.select(
commission.agent, Sum(commission.amount).as_('pending_amount'),
diff -r 65be67251d10 -r 9895805863b9
modules/marketing_automation/marketing_automation.py
--- a/modules/marketing_automation/marketing_automation.py Fri Dec 26
10:58:30 2025 +0100
+++ b/modules/marketing_automation/marketing_automation.py Fri Dec 26
10:57:44 2025 +0100
@@ -26,7 +26,7 @@
from trytond.pyson import Eval, If, PYSONDecoder, TimeDelta
from trytond.report import Report, html_to_text, mjml_to_html
from trytond.sendmail import SMTPDataManager, send_message_transactional
-from trytond.tools import grouped_slice, pairwise_longest, reduce_ids
+from trytond.tools import grouped_slice, pairwise_longest
from trytond.tools.chart import sparkline
from trytond.tools.email_ import format_address, has_rcpt, set_from_header
from trytond.transaction import Transaction
@@ -178,12 +178,13 @@
others.append(scenario)
count = {name: defaultdict(int) for name in names}
- for sub in grouped_slice(others):
+ for sub_others in grouped_slice(others):
cursor.execute(*record.select(
record.scenario,
Count(),
Count(filter_=record.blocked),
- where=reduce_ids(record.scenario, sub),
+ where=fields.SQL_OPERATORS['in'](
+ record.scenario, map(int, sub_others)),
group_by=record.scenario))
for id_, all_, blocked in cursor:
if 'record_count' in count:
@@ -521,13 +522,14 @@
cursor = Transaction().connection.cursor()
count = {name: defaultdict(int) for name in names}
- for sub in grouped_slice(activities):
+ for sub_activities in grouped_slice(activities):
cursor.execute(*record_activity.select(
record_activity.activity,
Count(filter_=record_activity.state == 'done'),
Count(filter_=record_activity.email_opened),
Count(filter_=record_activity.email_clicked),
- where=reduce_ids(record_activity.activity, sub),
+ where=fields.SQL_OPERATORS['in'](
+ record_activity.activity, map(int, sub_activities)),
group_by=record_activity.activity))
for id_, all_, email_opened, email_clicked in cursor:
if 'record_count' in count:
diff -r 65be67251d10 -r 9895805863b9 modules/marketing_email/marketing.py
--- a/modules/marketing_email/marketing.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/marketing_email/marketing.py Fri Dec 26 10:57:44 2025 +0100
@@ -22,7 +22,7 @@
from trytond.pyson import Eval
from trytond.report import Report, get_email, html_to_text, mjml_to_html
from trytond.sendmail import SMTPDataManager, send_message_transactional
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.tools.email_ import (
EmailNotValidError, format_address, normalize_email, set_from_header,
validate_email)
@@ -259,7 +259,8 @@
email.list_, Count(), group_by=[email.list_])
for sub_lists in grouped_slice(lists):
query.where = (
- reduce_ids(email.list_, sub_lists)
+ fields.SQL_OPERATORS['in'](
+ email.list_, map(int, sub_lists))
& email.active)
cursor.execute(*query)
subscribed.update(cursor)
diff -r 65be67251d10 -r 9895805863b9 modules/product_price_list_cache/product.py
--- a/modules/product_price_list_cache/product.py Fri Dec 26 10:58:30
2025 +0100
+++ b/modules/product_price_list_cache/product.py Fri Dec 26 10:57:44
2025 +0100
@@ -10,7 +10,7 @@
from trytond.model import ModelSQL, dualmethod, fields
from trytond.pool import Pool, PoolMeta
from trytond.protocols.jsonrpc import JSONDecoder, JSONEncoder
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
dumps = partial(
@@ -164,20 +164,21 @@
cursor.execute(*cache.delete())
elif price_lists and products is None:
for sub_price_lists in grouped_slice(price_lists):
- cursor.execute(*cache.delete(where=reduce_ids(
+ cursor.execute(*cache.delete(where=fields.SQL_OPERATORS['in'](
cache.price_list, [
p.id for p in sub_price_lists])))
elif price_lists is None and products:
for sub_products in grouped_slice(products):
- cursor.execute(*cache.delete(where=reduce_ids(
+ cursor.execute(*cache.delete(where=fields.SQL_OPERATORS['in'](
cache.product, [p.id for p in sub_products])))
else:
for sub_products in grouped_slice(products):
for sub_price_lists in grouped_slice(price_lists):
- cursor.execute(*cache.delete(where=reduce_ids(
- cache.price_list, [
- p.id for p in sub_price_lists])
- & reduce_ids(
+ cursor.execute(*cache.delete(
+ where=fields.SQL_OPERATORS['in'](
+ cache.price_list, [
+ p.id for p in sub_price_lists])
+ & fields.SQL_OPERATORS['in'](
cache.product, [p.id for p in sub_products])))
@classmethod
diff -r 65be67251d10 -r 9895805863b9 modules/production_work/work.py
--- a/modules/production_work/work.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/production_work/work.py Fri Dec 26 10:57:44 2025 +0100
@@ -19,7 +19,7 @@
from trytond.modules.product import price_digits, round_price
from trytond.pool import Pool
from trytond.pyson import Bool, Eval, If, TimeDelta
-from trytond.tools import grouped_slice, reduce_ids, sqlite_apply_types
+from trytond.tools import grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction
from .exceptions import PickerError
@@ -250,7 +250,8 @@
costs = defaultdict(Decimal)
for sub_works in grouped_slice(works):
- red_sql = reduce_ids(cycle.work, [w.id for w in sub_works])
+ red_sql = fields.SQL_OPERATORS['in'](
+ cycle.work, [w.id for w in sub_works])
query = cycle.select(
cycle.work, Sum(Coalesce(cycle.cost, 0)).as_('cost'),
where=red_sql & (cycle.state == 'done'),
diff -r 65be67251d10 -r 9895805863b9 modules/project_invoice/invoice.py
--- a/modules/project_invoice/invoice.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/project_invoice/invoice.py Fri Dec 26 10:57:44 2025 +0100
@@ -10,7 +10,7 @@
from trytond.modules.account_invoice.exceptions import (
InvoiceLineValidationError)
from trytond.pool import Pool, PoolMeta
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
@@ -92,7 +92,7 @@
ts_line.invoice_line, Sum(ts_line.duration),
group_by=ts_line.invoice_line)
for sub_lines in grouped_slice(lines):
- query.where = reduce_ids(
+ query.where = fields.SQL_OPERATORS['in'](
ts_line.invoice_line, map(int, sub_lines))
cursor.execute(*query)
diff -r 65be67251d10 -r 9895805863b9 modules/project_invoice/project.py
--- a/modules/project_invoice/project.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/project_invoice/project.py Fri Dec 26 10:57:44 2025 +0100
@@ -18,7 +18,7 @@
from trytond.modules.currency.fields import Monetary
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, Id, If
-from trytond.tools import grouped_slice, reduce_ids, sqlite_apply_types
+from trytond.tools import grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction
from trytond.wizard import StateAction, Wizard
@@ -114,7 +114,7 @@
quantities = {}
for sub_works in grouped_slice(works):
sub_works = list(sub_works)
- where = reduce_ids(
+ where = fields.SQL_OPERATORS['in'](
table.id, [x.id for x in sub_works if x.invoice_unit_price])
cursor.execute(*table.join(progress,
condition=progress.work == table.id
@@ -162,7 +162,7 @@
work2currency = {}
ids2work = dict((w.id, w) for w in works)
for sub_ids in grouped_slice(ids2work.keys()):
- where = reduce_ids(table.id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](table.id, sub_ids)
query = (table.join(progress,
condition=progress.work == table.id
).join(invoice_line,
@@ -275,7 +275,8 @@
group_by=line.work)
for upto, tworks in upto2tworks.items():
for sub_ids in grouped_slice(tworks):
- query.where = (reduce_ids(line.work, sub_ids)
+ query.where = (
+ fields.SQL_OPERATORS['in'](line.work, sub_ids)
& (line.invoice_line == Null))
if upto:
query.where &= (line.date <= upto)
@@ -318,7 +319,7 @@
work2currency = {}
work_ids = [w.id for w in works]
for sub_ids in grouped_slice(work_ids):
- where = reduce_ids(table.id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](table.id, sub_ids)
cursor.execute(*table.join(timesheet_work,
condition=(
Concat(cls.__name__ + ',', table.id)
diff -r 65be67251d10 -r 9895805863b9 modules/project_revenue/work.py
--- a/modules/project_revenue/work.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/project_revenue/work.py Fri Dec 26 10:57:44 2025 +0100
@@ -13,7 +13,7 @@
from trytond.modules.product import price_digits, round_price
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
@@ -95,13 +95,13 @@
work_ids = [w.id for w in works]
for sub_ids in grouped_slice(work_ids):
- red_sql = reduce_ids(table.id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](table.id, sub_ids)
cursor.execute(*table.join(work,
condition=(
Concat(cls.__name__ + ',', table.id) == work.origin)
).join(line, condition=line.work == work.id
).select(table.id, Sum(line.cost_price * line.duration),
- where=red_sql,
+ where=where,
group_by=[table.id]))
for work_id, cost in cursor:
# SQLite stores timedelta as float
@@ -135,7 +135,7 @@
work2currency = {}
iline2work = {}
for sub_ids in grouped_slice(work_ids):
- where = reduce_ids(table.id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](table.id, sub_ids)
cursor.execute(*table.join(purchase_line,
condition=purchase_line.work == table.id
).join(invoice_line,
diff -r 65be67251d10 -r 9895805863b9 modules/purchase/product.py
--- a/modules/purchase/product.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/purchase/product.py Fri Dec 26 10:57:44 2025 +0100
@@ -13,8 +13,7 @@
ProductDeactivatableMixin, price_digits, round_price)
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, If, TimeDelta
-from trytond.tools import (
- grouped_slice, is_full_text, lstrip_wildcard, reduce_ids)
+from trytond.tools import grouped_slice, is_full_text, lstrip_wildcard
from trytond.transaction import Transaction
from .exceptions import PurchaseUOMWarning
@@ -160,7 +159,7 @@
.join(purchase, condition=line.purchase == purchase.id)
.select(
Max(line.id),
- where=where & reduce_ids(
+ where=where & fields.SQL_OPERATORS['in'](
line.product, map(int, sub_products)),
group_by=[line.product]))
cursor.execute(*query)
diff -r 65be67251d10 -r 9895805863b9 modules/purchase_history/purchase.py
--- a/modules/purchase_history/purchase.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/purchase_history/purchase.py Fri Dec 26 10:57:44 2025 +0100
@@ -4,7 +4,7 @@
from trytond.model import ModelView, Workflow, fields
from trytond.pool import PoolMeta
from trytond.pyson import Eval
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
@@ -49,7 +49,8 @@
cursor.execute(*table.update(
[table.revision],
[table.revision + 1],
- where=reduce_ids(table.id, sub_purchases)))
+ where=fields.SQL_OPERATORS['in'](
+ table.id, map(int, sub_purchases))))
super().draft(purchases)
diff -r 65be67251d10 -r 9895805863b9 modules/sale/sale_reporting.py
--- a/modules/sale/sale_reporting.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/sale/sale_reporting.py Fri Dec 26 10:57:44 2025 +0100
@@ -15,7 +15,7 @@
from trytond.modules.currency.fields import Monetary
from trytond.pool import Pool
from trytond.pyson import Eval, If
-from trytond.tools import grouped_slice, pairwise_longest, reduce_ids
+from trytond.tools import grouped_slice, pairwise_longest
from trytond.tools.chart import sparkline
from trytond.transaction import Transaction
from trytond.wizard import StateAction, StateTransition, Wizard
@@ -517,7 +517,8 @@
reporting_customer_categories = []
for sub_ids in grouped_slice(ids):
sub_ids = list(sub_ids)
- where = reduce_ids(reporting_product_category.id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](
+ reporting_product_category.id, sub_ids)
cursor.execute(
*reporting_product_category.select(
reporting_product_category.id, where=where))
@@ -758,7 +759,8 @@
reporting_product_categories = []
for sub_ids in grouped_slice(ids):
sub_ids = list(sub_ids)
- where = reduce_ids(reporting_product_category.id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](
+ reporting_product_category.id, sub_ids)
cursor.execute(
*reporting_product_category.select(
reporting_product_category.id, where=where))
diff -r 65be67251d10 -r 9895805863b9 modules/sale_history/sale.py
--- a/modules/sale_history/sale.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/sale_history/sale.py Fri Dec 26 10:57:44 2025 +0100
@@ -4,7 +4,7 @@
from trytond.model import ModelView, Workflow, fields
from trytond.pool import PoolMeta
from trytond.pyson import Eval
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
@@ -45,7 +45,8 @@
cursor.execute(*table.update(
[table.revision],
[table.revision + 1],
- where=reduce_ids(table.id, sub_records)))
+ where=fields.SQL_OPERATORS['in'](
+ table.id, map(int, sub_records))))
super().draft(records)
diff -r 65be67251d10 -r 9895805863b9 modules/sale_point/sale.py
--- a/modules/sale_point/sale.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/sale_point/sale.py Fri Dec 26 10:57:44 2025 +0100
@@ -21,7 +21,7 @@
from trytond.modules.product import price_digits, round_price
from trytond.pool import Pool
from trytond.pyson import Bool, Eval, Id, If
-from trytond.tools import grouped_slice, reduce_ids, sqlite_apply_types
+from trytond.tools import grouped_slice, sqlite_apply_types
from trytond.transaction import Transaction
from trytond.wizard import Button, StateTransition, StateView, Wizard
@@ -865,12 +865,14 @@
payment.select(
payment.session.as_('session'),
Sum(payment.amount).as_('amount'),
- where=reduce_ids(payment.session, sub_ids),
+ where=fields.SQL_OPERATORS['in'](
+ payment.session, sub_ids),
group_by=[payment.session]),
transfer.select(
transfer.session.as_('session'),
Sum(transfer.amount).as_('amount'),
- where=reduce_ids(transfer.session, sub_ids),
+ where=fields.SQL_OPERATORS['in'](
+ transfer.session, sub_ids),
group_by=[transfer.session]),
all_=True)
query = query.select(
diff -r 65be67251d10 -r 9895805863b9 modules/sale_promotion_coupon/sale.py
--- a/modules/sale_promotion_coupon/sale.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/sale_promotion_coupon/sale.py Fri Dec 26 10:57:44 2025 +0100
@@ -15,7 +15,7 @@
from trytond.pyson import Eval, If
from trytond.sql.functions import DateRange
from trytond.sql.operators import RangeOverlap
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
from .exceptions import PromotionCouponNumberDatesError
@@ -302,7 +302,8 @@
result = {}
for sub_numbers in grouped_slice(numbers):
- query.where = reduce_ids(table.id, map(int, sub_numbers))
+ query.where = fields.SQL_OPERATORS['in'](
+ table.id, map(int, sub_numbers))
cursor.execute(*query)
result.update(dict(cursor))
return result
diff -r 65be67251d10 -r 9895805863b9 modules/stock/move.py
--- a/modules/stock/move.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/stock/move.py Fri Dec 26 10:57:44 2025 +0100
@@ -19,7 +19,7 @@
from trytond.modules.product import price_digits, round_price
from trytond.pool import Pool
from trytond.pyson import Bool, Eval, Id, If, TimeDelta
-from trytond.tools import cached_property, grouped_slice, reduce_ids
+from trytond.tools import cached_property, grouped_slice
from trytond.transaction import Transaction, without_check_access
from .exceptions import MoveFutureWarning, MoveOriginWarning
@@ -1331,9 +1331,9 @@
sub_location_ids = list(sub_location_ids)
table = cls.__table__()
query = table.select(Literal(1),
- where=(reduce_ids(
+ where=(fields.SQL_OPERATORS['in'](
table.to_location, sub_location_ids)
- | reduce_ids(
+ | fields.SQL_OPERATORS['in'](
table.from_location, sub_location_ids))
& table.product.in_(product_ids)
& (table.company == company_id),
@@ -1635,9 +1635,10 @@
if PeriodCache:
cache_column = Column(period_cache, fieldname)
if isinstance(grouping_ids[0], (int, float, Decimal)):
- where &= reduce_ids(column, grouping_ids)
+ where &= fields.SQL_OPERATORS['in'](column, grouping_ids)
if PeriodCache:
- where_period &= reduce_ids(cache_column, grouping_ids)
+ where_period &= fields.SQL_OPERATORS['in'](
+ cache_column, grouping_ids)
else:
where &= column.in_(grouping_ids)
if PeriodCache:
diff -r 65be67251d10 -r 9895805863b9 modules/stock/product.py
--- a/modules/stock/product.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/stock/product.py Fri Dec 26 10:57:44 2025 +0100
@@ -17,7 +17,7 @@
from trytond.modules.product import price_digits, round_price
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, If, PYSONEncoder
-from trytond.tools import decistmt, grouped_slice, reduce_ids
+from trytond.tools import decistmt, grouped_slice
from trytond.tools import timezone as tz
from trytond.transaction import Transaction, without_check_access
from trytond.wizard import (
@@ -679,7 +679,8 @@
raise AccessError(gettext(
'stock.msg_product_quantities_max',
max=transaction.database.IN_MAX))
- product_clause = reduce_ids(product.template, product_template)
+ product_clause = fields.SQL_OPERATORS['in'](
+ product.template, product_template)
else:
product_clause = product.template == Null
product_column = Concat('product.template,', product.template)
@@ -695,7 +696,8 @@
raise AccessError(gettext(
'stock.msg_product_quantities_max',
max=transaction.database.IN_MAX))
- product_clause = reduce_ids(move.product, product)
+ product_clause = fields.SQL_OPERATORS['in'](
+ move.product, product)
else:
product_clause = move.product == Null
product_column = Concat('product.product,', move.product)
@@ -945,7 +947,8 @@
raise AccessError(gettext(
'stock.msg_product_quantities_max',
max=transaction.database.IN_MAX))
- product_clause = reduce_ids(product.template, product_template)
+ product_clause = fields.SQL_OPERATORS['in'](
+ product.template, product_template)
else:
product_clause = product.template == Null
product_column = Concat('product.template,', product.template)
@@ -960,7 +963,8 @@
raise AccessError(gettext(
'stock.msg_product_quantities_max',
max=transaction.database.IN_MAX))
- product_clause = reduce_ids(move.product, product)
+ product_clause = fields.SQL_OPERATORS['in'](
+ move.product, product)
else:
product_clause = move.product == Null
product_column = Concat('product.product,', move.product)
diff -r 65be67251d10 -r 9895805863b9 modules/stock/stock_reporting_margin.py
--- a/modules/stock/stock_reporting_margin.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/stock/stock_reporting_margin.py Fri Dec 26 10:57:44 2025 +0100
@@ -15,7 +15,7 @@
from trytond.modules.currency.fields import Monetary
from trytond.pool import Pool
from trytond.pyson import Eval, If
-from trytond.tools import grouped_slice, pairwise_longest, reduce_ids
+from trytond.tools import grouped_slice, pairwise_longest
from trytond.tools.chart import sparkline
from trytond.transaction import Transaction
@@ -596,7 +596,8 @@
reporting_categories = []
for sub_ids in grouped_slice(ids):
sub_ids = list(sub_ids)
- where = reduce_ids(reporting_category.id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](
+ reporting_category.id, sub_ids)
cursor.execute(
*reporting_category.select(reporting_category.id, where=where))
reporting_categories.extend(r for r, in cursor)
diff -r 65be67251d10 -r 9895805863b9 modules/stock_forecast/forecast.py
--- a/modules/stock_forecast/forecast.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/stock_forecast/forecast.py Fri Dec 26 10:57:44 2025 +0100
@@ -18,7 +18,7 @@
from trytond.pyson import Bool, Eval, If
from trytond.sql.functions import DateRange
from trytond.sql.operators import RangeOverlap
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
from trytond.wizard import Button, StateTransition, StateView, Wizard
@@ -357,13 +357,13 @@
product2line = dict((line.product.id, line) for line in lines)
product_ids = product2line.keys()
for sub_ids in grouped_slice(product_ids):
- red_sql = reduce_ids(move.product, sub_ids)
+ where = fields.SQL_OPERATORS['in'](move.product, sub_ids)
cursor.execute(*move.join(location_from,
condition=move.from_location == location_from.id
).join(location_to,
condition=move.to_location == location_to.id
).select(move.product, Sum(move.internal_quantity),
- where=red_sql
+ where=where
& (location_from.left >= forecast.warehouse.left)
& (location_from.right <= forecast.warehouse.right)
& (location_to.left >= forecast.destination.left)
diff -r 65be67251d10 -r 9895805863b9 modules/stock_quantity_issue/stock.py
--- a/modules/stock_quantity_issue/stock.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/stock_quantity_issue/stock.py Fri Dec 26 10:57:44 2025 +0100
@@ -249,12 +249,11 @@
issue.issue_products = []
issues[issue.origin] = issue
- # Order by id to speedup reduce_ids
products = Product.search([
('type', 'in', ['goods', 'assets']),
('consumable', '=', False),
],
- order=[('id', 'ASC')])
+ order=[])
for product in products:
for warehouse in warehouses:
diff -r 65be67251d10 -r 9895805863b9
modules/stock_shipment_measurements/stock.py
--- a/modules/stock_shipment_measurements/stock.py Fri Dec 26 10:58:30
2025 +0100
+++ b/modules/stock_shipment_measurements/stock.py Fri Dec 26 10:57:44
2025 +0100
@@ -13,7 +13,7 @@
from trytond.modules.company.model import CompanyValueMixin
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, Id
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
@@ -285,7 +285,9 @@
where = query.where
for sub_shipments in grouped_slice(shipments):
query.where = (
- where & reduce_ids(table.id, map(int, sub_shipments)))
+ where
+ & fields.SQL_OPERATORS['in'](
+ table.id, map(int, sub_shipments)))
cursor.execute(*query)
else:
cursor.execute(*query)
@@ -331,7 +333,7 @@
if s.state not in states
or s.internal_weight is None
or s.internal_volume is None)):
- query.where = reduce_ids(
+ query.where = fields.SQL_OPERATORS['in'](
table.id, [s.id for s in sub_shipments])
cursor.execute(*query)
for id_, weight, volume in cursor:
diff -r 65be67251d10 -r 9895805863b9 modules/stock_supply/purchase_request.py
--- a/modules/stock_supply/purchase_request.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/stock_supply/purchase_request.py Fri Dec 26 10:57:44 2025 +0100
@@ -65,12 +65,12 @@
if products is None:
# fetch goods and assets
- # ordered by ids to speedup reduce_ids in products_by_location
products = Product.search([
('type', 'in', ['goods', 'assets']),
('consumable', '=', False),
('purchasable', '=', True),
- ], order=[('id', 'ASC')])
+ ],
+ order=[])
# aggregate product by minimum supply date
date2products = defaultdict(list)
for product in products:
diff -r 65be67251d10 -r 9895805863b9 modules/stock_supply/shipment.py
--- a/modules/stock_supply/shipment.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/stock_supply/shipment.py Fri Dec 26 10:57:44 2025 +0100
@@ -89,11 +89,11 @@
location_ids, with_childs=True,
grouping_filter=grouping_filter)
- # ordered by ids to speedup reduce_ids in products_by_location
if implicit_locations:
products = Product.search([
('type', 'in', ['goods', 'assets']),
- ], order=[('id', 'ASC')])
+ ],
+ order=[])
product_ids = [p.id for p in products]
pbl = get_pbl(None, today, None)
else:
diff -r 65be67251d10 -r 9895805863b9 modules/timesheet/work.py
--- a/modules/timesheet/work.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/timesheet/work.py Fri Dec 26 10:57:44 2025 +0100
@@ -10,7 +10,7 @@
from trytond.model import ModelSQL, ModelStorage, ModelView, Unique, fields
from trytond.pool import Pool
from trytond.pyson import Bool, Eval, If
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
from .exceptions import CompanyValidationError
@@ -106,9 +106,9 @@
condition=line.work == table_w.id)
for sub_ids in grouped_slice(ids):
- red_sql = reduce_ids(table_w.id, sub_ids)
cursor.execute(*query_table.select(table_w.id, Sum(line.duration),
- where=red_sql & where,
+ where=where
+ & fields.SQL_OPERATORS['in'](table_w.id, sub_ids),
group_by=table_w.id))
for work_id, duration in cursor:
# SQLite uses float for SUM
diff -r 65be67251d10 -r 9895805863b9 modules/web_shortener/web.py
--- a/modules/web_shortener/web.py Fri Dec 26 10:58:30 2025 +0100
+++ b/modules/web_shortener/web.py Fri Dec 26 10:57:44 2025 +0100
@@ -10,7 +10,7 @@
import trytond.config as config
from trytond.model import ModelSQL, ModelView, fields
from trytond.pool import Pool
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
from trytond.url import http_host
from trytond.wsgi import Base64Converter
@@ -56,7 +56,7 @@
for sub_ids in grouped_slice(shortened_urls):
cursor.execute(*access.select(
access.url, Count(access.id),
- where=reduce_ids(access.url, sub_ids),
+ where=fields.SQL_OPERATORS['in'](access.url, sub_ids),
group_by=[access.url]))
counts.update(cursor)
return counts
diff -r 65be67251d10 -r 9895805863b9 trytond/CHANGELOG
--- a/trytond/CHANGELOG Fri Dec 26 10:58:30 2025 +0100
+++ b/trytond/CHANGELOG Fri Dec 26 10:57:44 2025 +0100
@@ -1,3 +1,4 @@
+* Deprecate ``reduce_ids`` for ``SQL_OPERATORS['in']``
* Use array for ``in`` operators
* Update to Psycopg 3
* Add support for Python 3.14
diff -r 65be67251d10 -r 9895805863b9 trytond/trytond/ir/cron.py
--- a/trytond/trytond/ir/cron.py Fri Dec 26 10:58:30 2025 +0100
+++ b/trytond/trytond/ir/cron.py Fri Dec 26 10:57:44 2025 +0100
@@ -22,7 +22,7 @@
from trytond.pool import Pool
from trytond.pyson import Eval
from trytond.status import processing
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.tools import timezone as tz
from trytond.transaction import Transaction, TransactionError
from trytond.worker import run_task
@@ -143,7 +143,7 @@
ids = [c.id for c in sub_crons]
query = table.select(
table.id,
- where=reduce_ids(table.id, ids),
+ where=fields.SQL_OPERATORS['in'](table.id, ids),
for_=For('UPDATE'))
cursor.execute(*query)
not_running = {i for i, in cursor}
diff -r 65be67251d10 -r 9895805863b9 trytond/trytond/ir/note.py
--- a/trytond/trytond/ir/note.py Fri Dec 26 10:58:30 2025 +0100
+++ b/trytond/trytond/ir/note.py Fri Dec 26 10:57:44 2025 +0100
@@ -9,7 +9,7 @@
from trytond.model import ModelSQL, ModelView, fields
from trytond.pool import Pool
from trytond.pyson import Eval
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
from .resource import ResourceMixin, resource_copy
@@ -52,7 +52,7 @@
unread = {}
for sub_ids in grouped_slice(ids):
- where = reduce_ids(table.id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](table.id, sub_ids)
query = table.join(read, 'LEFT',
condition=(table.id == read.note)
& (read.user == user_id)
diff -r 65be67251d10 -r 9895805863b9 trytond/trytond/ir/trigger.py
--- a/trytond/trytond/ir/trigger.py Fri Dec 26 10:58:30 2025 +0100
+++ b/trytond/trytond/ir/trigger.py Fri Dec 26 10:57:44 2025 +0100
@@ -15,7 +15,7 @@
from trytond.model.exceptions import ValidationError
from trytond.pool import Pool
from trytond.pyson import Eval, If, PYSONDecoder, TimeDelta
-from trytond.tools import grouped_slice, reduce_ids
+from trytond.tools import grouped_slice
from trytond.transaction import Transaction
@@ -206,10 +206,10 @@
new_ids = []
for sub_ids in grouped_slice(ids):
sub_ids = list(sub_ids)
- red_sql = reduce_ids(trigger_log.record_id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](trigger_log.record_id,
sub_ids)
cursor.execute(*trigger_log.select(
trigger_log.record_id, Count(),
- where=red_sql & (trigger_log.trigger == self.id),
+ where=where & (trigger_log.trigger == self.id),
group_by=trigger_log.record_id))
number = dict(cursor)
for record_id in sub_ids:
@@ -231,10 +231,11 @@
now = datetime.datetime.fromisoformat(now)
for sub_ids in grouped_slice(ids):
sub_ids = list(sub_ids)
- red_sql = reduce_ids(trigger_log.record_id, sub_ids)
+ where = fields.SQL_OPERATORS['in'](
+ trigger_log.record_id, sub_ids)
cursor.execute(*trigger_log.select(
trigger_log.record_id, Max(trigger_log.create_date),
- where=(red_sql & (trigger_log.trigger == self.id)),
+ where=where & (trigger_log.trigger == self.id),
group_by=trigger_log.record_id))
delay = dict(cursor)
for record_id in sub_ids:
diff -r 65be67251d10 -r 9895805863b9 trytond/trytond/model/modelsql.py
--- a/trytond/trytond/model/modelsql.py Fri Dec 26 10:58:30 2025 +0100
+++ b/trytond/trytond/model/modelsql.py Fri Dec 26 10:57:44 2025 +0100
@@ -383,7 +383,6 @@
@classmethod
def __setup_indexes__(cls):
pool = Pool()
- # Define Range index to optimise with reduce_ids
for field_name, field in cls._fields.items():
Targets = []
if isinstance(field, fields.Many2One):
diff -r 65be67251d10 -r 9895805863b9 trytond/trytond/tests/test_tools.py
--- a/trytond/trytond/tests/test_tools.py Fri Dec 26 10:58:30 2025 +0100
+++ b/trytond/trytond/tests/test_tools.py Fri Dec 26 10:57:44 2025 +0100
@@ -6,7 +6,6 @@
import doctest
import email.message
import os
-import sys
import unittest
from copy import deepcopy
from decimal import Decimal
@@ -29,7 +28,7 @@
from trytond.tools import (
cached_property, decimal_, email_, escape_wildcard, file_open, firstline,
grouped_slice, is_full_text, is_instance_method, likify, lstrip_wildcard,
- pair, pairwise_longest, reduce_domain, reduce_ids, remove_forbidden_chars,
+ pair, pairwise_longest, reduce_domain, remove_forbidden_chars,
rstrip_wildcard, slugify, sortable_values, sqlite_apply_types,
strip_wildcard, timezone, unescape_wildcard, unpair)
from trytond.tools.chart import sparkline
@@ -56,51 +55,6 @@
'Test tools'
table = sql.Table('test')
- def test_reduce_ids_empty(self):
- 'Test reduce_ids empty list'
- self.assertEqual(reduce_ids(self.table.id, []), sql.Literal(False))
-
- def test_reduce_ids_continue(self):
- 'Test reduce_ids continue list'
- self.assertEqual(reduce_ids(self.table.id, list(range(10))),
- sql.operators.Or(((self.table.id >= 0) & (self.table.id <= 9),)))
-
- def test_reduce_ids_one_hole(self):
- 'Test reduce_ids continue list with one hole'
- self.assertEqual(reduce_ids(
- self.table.id, list(range(10)) + list(range(20, 30))),
- ((self.table.id >= 0) & (self.table.id <= 9))
- | ((self.table.id >= 20) & (self.table.id <= 29)))
-
- def test_reduce_ids_short_continue(self):
- 'Test reduce_ids short continue list'
- self.assertEqual(reduce_ids(self.table.id, list(range(4))),
- sql.operators.Or((self.table.id.in_(list(range(4))),)))
-
- def test_reduce_ids_complex(self):
- 'Test reduce_ids complex list'
- self.assertEqual(reduce_ids(self.table.id,
- list(range(10)) + list(range(25, 30)) + list(range(15, 20))),
- (((self.table.id >= 0) & (self.table.id <= 14))
- | (self.table.id.in_(list(range(25, 30))))))
-
- def test_reduce_ids_complex_small_continue(self):
- 'Test reduce_ids complex list with small continue'
- self.assertEqual(reduce_ids(self.table.id,
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 18, 19, 21]),
- (((self.table.id >= 1) & (self.table.id <= 12))
- | (self.table.id.in_([15, 18, 19, 21]))))
-
- @unittest.skipIf(sys.flags.optimize, "assert removed by optimization")
- def test_reduce_ids_float(self):
- 'Test reduce_ids with integer as float'
- self.assertEqual(reduce_ids(self.table.id,
- [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0,
- 15.0, 18.0, 19.0, 21.0]),
- (((self.table.id >= 1.0) & (self.table.id <= 12.0))
- | (self.table.id.in_([15.0, 18.0, 19.0, 21.0]))))
- self.assertRaises(AssertionError, reduce_ids, self.table.id, [1.1])
-
def test_reduce_domain(self):
'Test reduce_domain'
clause = ('x', '=', 'x')
diff -r 65be67251d10 -r 9895805863b9 trytond/trytond/tools/misc.py
--- a/trytond/trytond/tools/misc.py Fri Dec 26 10:58:30 2025 +0100
+++ b/trytond/trytond/tools/misc.py Fri Dec 26 10:57:44 2025 +0100
@@ -12,14 +12,12 @@
import types
import unicodedata
import warnings
-from array import array
from collections.abc import Iterable, Sized
from functools import cache, wraps
from itertools import chain, islice, tee, zip_longest
-from sql import As, Cast, Literal, Select
+from sql import As, Cast, Select
from sql.conditionals import Case
-from sql.operators import Or
from trytond.const import MODULES_GROUP, OPERATORS
@@ -111,45 +109,11 @@
def reduce_ids(field, ids):
- '''
- Return a small SQL expression for the list of ids and the sql column
- '''
- if __debug__:
- def strict_int(value):
- assert not isinstance(value, float) or value.is_integer(), \
- "ids must be integer"
- return int(value)
- else:
- strict_int = int
- ids = list(map(strict_int, ids))
- if not ids:
- return Literal(False)
- ids.sort()
- prev = ids.pop(0)
- continue_list = [prev, prev]
- discontinue_list = array('l')
- sql = Or()
- for i in ids:
- if i == prev:
- continue
- if i != prev + 1:
- if continue_list[-1] - continue_list[0] < 5:
- discontinue_list.extend([continue_list[0] + x for x in
- range(continue_list[-1] - continue_list[0] + 1)])
- else:
- sql.append((field >= continue_list[0])
- & (field <= continue_list[-1]))
- continue_list = []
- continue_list.append(i)
- prev = i
- if continue_list[-1] - continue_list[0] < 5:
- discontinue_list.extend([continue_list[0] + x for x in
- range(continue_list[-1] - continue_list[0] + 1)])
- else:
- sql.append((field >= continue_list[0]) & (field <= continue_list[-1]))
- if discontinue_list:
- sql.append(field.in_(discontinue_list))
- return sql
+ from trytond.model.fields import SQL_OPERATORS
+ warnings.warn(
+ "reduce_ids is deprecated use trytond.fields.SQL_OPERATORS['in']",
+ DeprecationWarning)
+ return SQL_OPERATORS['in'](field, ids)
def reduce_domain(domain):