From e79a3675d13eacfd3d38e9725bbb354c778f0252 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 1 Aug 2014 12:34:41 +0200 Subject: [PATCH] [FIX] orm.search_count: ignore `limit`, `offset` and most importantly `order` These parameters are (or should be) irrelevant for a search_count(), and they could actually break the result or make it significantly slower (e.g applying `order` on large tables). This fixes a performance regression introduced by 0f43032b. We could also raise an error offset/limit are passed in combination with count, but that seems unnecessary. Also switched to "SELECT count(1)" for the count query, as it is simpler and just as fast. We'd get the same perf with * or any constant value, as in "SELECT count('me in')", but let's keep it simple ;-) --- openerp/osv/orm.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 79d6d213939..808276c4639 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -4606,18 +4606,19 @@ class BaseModel(object): order_by = self._generate_order_by(order, query) from_clause, where_clause, where_clause_params = query.get_sql() - limit_str = limit and ' limit %d' % limit or '' - offset_str = offset and ' offset %d' % offset or '' where_str = where_clause and (" WHERE %s" % where_clause) or '' - query_str = 'SELECT "%s".id FROM ' % self._table + from_clause + where_str + order_by + limit_str + offset_str if count: - # /!\ the main query must be executed as a subquery, otherwise - # offset and limit apply to the result of count()! - cr.execute('SELECT count(*) FROM (%s) AS count' % query_str, where_clause_params) + # Ignore order, limit and offset when just counting, they don't make sense and could + # hurt performance + query_str = 'SELECT count(1) FROM ' + from_clause + where_str + cr.execute(query_str, where_clause_params) res = cr.fetchone() return res[0] + limit_str = limit and ' limit %d' % limit or '' + offset_str = offset and ' offset %d' % offset or '' + query_str = 'SELECT "%s".id FROM ' % self._table + from_clause + where_str + order_by + limit_str + offset_str cr.execute(query_str, where_clause_params) res = cr.fetchall()