Do not use Literal to count in SQL

The * is not actually a parameter of the aggregate function so it is better to
let python-sql manage it with its default value.
This commit is contained in:
Cédric Krier
2025-12-25 09:47:23 +01:00
parent 4ab7069dab
commit 7fb5a4a3de
19 changed files with 33 additions and 39 deletions
+3 -3
View File
@@ -1085,7 +1085,7 @@ class Account(
types = [None]
for name in names:
if name == 'line_count':
columns.append(Count(Literal('*')))
columns.append(Count())
types.append(None)
else:
columns.append(
@@ -1593,7 +1593,7 @@ class AccountParty(ActivePeriodMixin, ModelSQL):
types = [None, None]
for name in names:
if name == 'line_count':
columns.append(Count(Literal('*')).as_(name))
columns.append(Count().as_(name))
types.append(None)
else:
columns.append(Sum(Coalesce(Column(line, name), 0)).as_(name))
@@ -1721,7 +1721,7 @@ class AccountDeferral(ModelSQL, ModelView):
.join(period, condition=move.period == period.id)
.select(
move_line.account, period.fiscalyear,
Count(Literal('*')).as_('line_count'),
Count().as_('line_count'),
group_by=[move_line.account, period.fiscalyear]))
cursor.execute(*deferral.update(
[deferral.line_count], [counting_query.line_count],
+1 -1
View File
@@ -53,7 +53,7 @@ exclude = ['doc']
[tool.hatch.metadata.hooks.tryton]
dependencies = [
'python-dateutil',
'python-sql >= 0.7',
'python-sql >= 1.4',
'simpleeval',
]
copyright = 'COPYRIGHT'
+1 -1
View File
@@ -55,7 +55,7 @@ exclude = ['doc']
[tool.hatch.metadata.hooks.tryton]
dependencies = [
'python-sql >= 1.1.0',
'python-sql >= 1.4',
]
copyright = 'COPYRIGHT'
readme = 'README.rst'
+2 -2
View File
@@ -196,8 +196,8 @@ class AEATPartyReport(AEATReport):
from_ = convert_from(None, tables)
cursor.execute(*from_.select(
expression, where=where, group_by=(expression,)).select(
Count(Literal('*'))))
expression, where=where, group_by=(expression,))
.select(Count()))
row = cursor.fetchone()
if row:
parties[tax_code.code] += row[0]
@@ -15,7 +15,6 @@ from genshi.core import END, START, Attrs, QName
from genshi.template import MarkupTemplate
from genshi.template import TemplateError as GenshiTemplateError
from genshi.template import TextTemplate
from sql import Literal
from sql.aggregate import Count
import trytond.config as config
@@ -182,8 +181,8 @@ class Scenario(
for sub in grouped_slice(others):
cursor.execute(*record.select(
record.scenario,
Count(Literal('*')),
Count(Literal('*'), filter_=record.blocked),
Count(),
Count(filter_=record.blocked),
where=reduce_ids(record.scenario, sub),
group_by=record.scenario))
for id_, all_, blocked in cursor:
@@ -525,10 +524,9 @@ class Activity(
for sub in grouped_slice(activities):
cursor.execute(*record_activity.select(
record_activity.activity,
Count(Literal('*'),
filter_=record_activity.state == 'done'),
Count(Literal('*'), filter_=record_activity.email_opened),
Count(Literal('*'), filter_=record_activity.email_clicked),
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),
group_by=record_activity.activity))
for id_, all_, email_opened, email_clicked in cursor:
@@ -99,8 +99,8 @@ class Scenario(Abstract):
def _columns(cls, tables, withs):
record = tables['record']
record_count = Count(Literal('*'))
record_count_blocked = Count(Literal('*'), filter_=record.blocked)
record_count = Count()
record_count_blocked = Count(filter_=record.blocked)
return super()._columns(tables, withs) + [
record.scenario.as_('scenario'),
@@ -203,12 +203,9 @@ class Activity(Abstract):
def _columns(cls, tables, withs):
record_activity = tables['record_activity']
record_count = Count(
Literal('*'), filter_=record_activity.state == 'done')
email_opened = Count(
Literal('*'), filter_=record_activity.email_opened)
email_clicked = Count(
Literal('*'), filter_=record_activity.email_clicked)
record_count = Count(filter_=record_activity.state == 'done')
email_opened = Count(filter_=record_activity.email_opened)
email_clicked = Count(filter_=record_activity.email_clicked)
return super()._columns(tables, withs) + [
record_activity.activity.as_('activity'),
@@ -57,6 +57,7 @@ exclude = ['doc']
dependencies = [
'Genshi',
'python-dateutil',
'python-sql >= 1.4',
]
copyright = 'COPYRIGHT'
readme = 'README.rst'
+1 -2
View File
@@ -11,7 +11,6 @@ from urllib.parse import (
from genshi.core import END, START, Attrs, QName
from genshi.template import MarkupTemplate
from genshi.template import TemplateError as GenshiTemplateError
from sql import Literal
from sql.aggregate import Count
import trytond.config as config
@@ -257,7 +256,7 @@ class EmailList(DeactivableMixin, ModelSQL, ModelView):
subscribed = defaultdict(int)
query = email.select(
email.list_, Count(Literal('*')), group_by=[email.list_])
email.list_, Count(), group_by=[email.list_])
for sub_lists in grouped_slice(lists):
query.where = (
reduce_ids(email.list_, sub_lists)
+1 -2
View File
@@ -3,7 +3,6 @@
import datetime
from collections import defaultdict
from sql import Literal
from sql.aggregate import Count, Max
from trytond.i18n import gettext
@@ -407,7 +406,7 @@ class ProductSupplier(
cursor.execute(*table.select(table.currency,
where=table.party == self.party.id,
group_by=table.currency,
order_by=Count(Literal(1)).desc))
order_by=Count().desc))
row = cursor.fetchone()
if row:
self.currency, = row
+2 -2
View File
@@ -6,7 +6,7 @@ from collections import defaultdict
from decimal import Decimal
from itertools import chain, groupby
from sql import Literal, Null
from sql import Null
from sql.aggregate import Count
from sql.functions import CharLength
@@ -458,7 +458,7 @@ class Purchase(
subquery.payment_term,
subquery.invoice_method,
],
order_by=Count(Literal(1)).desc))
order_by=Count().desc))
row = cursor.fetchone()
if row:
self.currency, self.payment_term, self.invoice_method = row
+1 -1
View File
@@ -51,7 +51,7 @@ exclude = ['doc']
"" = "trytond/modules/purchase"
[tool.hatch.metadata.hooks.tryton]
dependencies = ['python-sql >= 0.4']
dependencies = ['python-sql >= 1.4']
copyright = 'COPYRIGHT'
readme = 'README.rst'
@@ -120,7 +120,7 @@ class Abstract(ModelSQL):
return [
cls._column_id(tables, withs).as_('id'),
opportunity.company.as_('company'),
Count(Literal(1)).as_('number'),
Count().as_('number'),
Sum(opportunity.amount).as_('amount'),
Sum(Case(
(opportunity.state.in_(cls._converted_states()),
+1 -1
View File
@@ -54,7 +54,7 @@ exclude = ['doc']
[tool.hatch.metadata.hooks.tryton]
dependencies = [
'python-dateutil',
'python-sql >= 0.4',
'python-sql >= 1.4',
]
copyright = 'COPYRIGHT'
readme = 'README.rst'
@@ -489,7 +489,7 @@ class Database(DatabaseInterface):
'WHERE relname = %s',
(from_item._name,))
else:
cursor.execute(*from_item.select(Count(Literal('*'))))
cursor.execute(*from_item.select(Count()))
return cursor.fetchone()[0]
def notify(self, connection, channel, payload):
+1 -1
View File
@@ -742,7 +742,7 @@ class Database(DatabaseInterface):
def estimated_count(self, connection, table):
cursor = connection.cursor()
cursor.execute(*table.select(Count(Literal('*'))))
cursor.execute(*table.select(Count()))
return cursor.fetchone()[0]
@classmethod
+1 -1
View File
@@ -208,7 +208,7 @@ class Trigger(DeactivableMixin, ModelSQL, ModelView):
sub_ids = list(sub_ids)
red_sql = reduce_ids(trigger_log.record_id, sub_ids)
cursor.execute(*trigger_log.select(
trigger_log.record_id, Count(Literal(1)),
trigger_log.record_id, Count(),
where=red_sql & (trigger_log.trigger == self.id),
group_by=trigger_log.record_id))
number = dict(cursor)
+2 -2
View File
@@ -1941,9 +1941,9 @@ class ModelSQL(ModelStorage):
if (limit is not None and limit < cls.estimated_count()) or offset:
select = table.select(
Literal(1), where=expression, limit=limit, offset=offset
).select(Count(Literal('*')))
).select(Count())
else:
select = table.select(Count(Literal('*')), where=expression)
select = table.select(Count(), where=expression)
if query:
return select
else:
+1 -1
View File
@@ -91,7 +91,7 @@ class Notification(
notification = cls.__table__()
cursor = Transaction().connection.cursor()
cursor.execute(*notification.select(
notification.user, Count(Literal('*')),
notification.user, Count(),
where=((notification.user.in_(list(notifications_by_user)))
& notification.unread),
group_by=[notification.user]))
+2 -2
View File
@@ -812,7 +812,7 @@ class LoginAttempt(ModelSQL):
def count(cls, login, device_cookie=None):
cursor = Transaction().connection.cursor()
table = cls.__table__()
cursor.execute(*table.select(Count(Literal('*')),
cursor.execute(*table.select(Count(),
where=(table.login == login)
& (table.device_cookie == device_cookie)
& (table.create_date >= cls.delay())))
@@ -825,7 +825,7 @@ class LoginAttempt(ModelSQL):
table = cls.__table__()
_, ip_network = transaction.remote_address()
ip_network = str(ip_network) if ip_network else None
cursor.execute(*table.select(Count(Literal('*')),
cursor.execute(*table.select(Count(),
where=(table.ip_network == ip_network)
& (table.create_date >= cls.delay())))
return cursor.fetchone()[0]