optimization: use SELECT 1 instead of SELECT count(*) (#65362)

This commit is contained in:
Pierre Ducroquet 2022-05-17 18:10:20 +02:00
parent 2dd0aea804
commit 033f80f2f2
11 changed files with 37 additions and 14 deletions

View File

@ -1875,7 +1875,7 @@ class FormsDirectory(AccessControlled, Directory):
def new(self):
get_response().breadcrumb.append(('new', _('New')))
if get_publisher().role_class.count() == 0:
if not (get_publisher().role_class.exists()):
return template.error_page(self.section, _('You first have to define roles.'))
formdefui = self.formdef_ui_class(None)
form = formdefui.new_form_ui()

View File

@ -498,7 +498,7 @@ class UsersDirectory(Directory):
# XXX: user must be logged in to get here
user = get_publisher().user_class()
user_ui = UserUI(user)
first_user = get_publisher().user_class.count() == 0
first_user = not (get_publisher().user_class.exists())
if first_user:
user.is_admin = first_user
form = user_ui.form()

View File

@ -428,7 +428,7 @@ class ApiFormsDirectory(Directory):
if get_request().form.get('full') == 'on':
raise RequestError('no such parameter "full"')
if FormDef.count() == 0:
if not (FormDef.exists()):
# early return, this avoids running a query against a missing SQL view.
get_response().set_content_type('application/json')
return json.dumps({'data': []}, cls=misc.JSONEncoder)
@ -908,7 +908,7 @@ class ApiUserDirectory(Directory):
return json.dumps(user_info, cls=misc.JSONEncoder)
def get_user_forms(self, user):
if FormDef.count() == 0:
if not (FormDef.exists()):
# early return, this avoids running a query against a missing SQL view.
return []

View File

@ -92,7 +92,7 @@ class DataManagementDirectory(ManagementDirectory):
def _q_index(self):
html_top('data_management', _('Cards'))
if CardDef.count() == 0:
if not (CardDef.exists()):
return self.empty_site_message(_('Cards'))
return template.QommonTemplateResponse(
templates=['wcs/backoffice/data-management.html'], context={'view': self}

View File

@ -409,7 +409,7 @@ class ManagementDirectory(Directory):
html_top('management', _('Global statistics'))
get_response().breadcrumb.append(('statistics', _('Global statistics')))
if FormDef.count() == 0:
if not (FormDef.exists()):
r = TemplateIO(html=True)
r += htmltext('<div class="top-title">')
r += htmltext('<h2>%s</h2>') % _('Global statistics')
@ -605,7 +605,7 @@ class ManagementDirectory(Directory):
html_top('management', _('Management'))
if FormDef.count() == 0:
if not (FormDef.exists()):
return self.empty_site_message(_('Global View'))
limit = misc.get_int_or_400(
@ -733,7 +733,7 @@ class ManagementDirectory(Directory):
def count(self):
if not get_publisher().is_using_postgresql():
raise errors.TraversalError()
if FormDef.count() == 0:
if not (FormDef.exists()):
return misc.json_response({'count': 0})
from wcs import sql
@ -853,7 +853,7 @@ class FormPage(Directory):
def check_access(self, api_name=None):
session = get_session()
user = get_request().user
if user is None and get_publisher().user_class.count() == 0:
if user is None and not (get_publisher().user_class.exists()):
user = get_publisher().user_class()
user.is_admin = True
if not user:

View File

@ -92,7 +92,7 @@ class RootDirectory(BackofficeRootDirectory):
return True
if not get_request().user:
if get_publisher().user_class.count() == 0:
if not (get_publisher().user_class.exists()):
# setting up the site, access is granted to settings and users
# sections
return subdirectory in ('settings', 'users')
@ -146,7 +146,7 @@ class RootDirectory(BackofficeRootDirectory):
get_response().filter['admin_for_all'] = True
return
if get_publisher().user_class.count() > 0:
if get_publisher().user_class.exists():
user = req.user
if not user:
raise errors.AccessUnauthorizedError(

View File

@ -466,7 +466,7 @@ class FormDef(StorableObject):
# or if there are not yet any submitted forms (or if site
# is using the SQL storage as internal identifier is not used
# in that mode.
if self.id is None or get_publisher().is_using_postgresql() or self.data_class().count() == 0:
if self.id is None or get_publisher().is_using_postgresql() or not (self.data_class().exists()):
self.internal_identifier = new_internal_identifier
object_only = kwargs.pop('object_only', False)

View File

@ -200,7 +200,7 @@ class MethodDirectory(Directory):
user.set_attributes_from_formdata(data)
user.form_data = data
if get_publisher().user_class.count() == 0:
if not (get_publisher().user_class.exists()):
user.is_admin = True
session = get_session()

View File

@ -592,7 +592,7 @@ class MethodDirectory(Directory):
if identities_cfg.get('email-as-username', False):
user.email = username
if get_publisher().user_class.count() == 0:
if not (get_publisher().user_class.exists()):
user.is_admin = True
user.store()

View File

@ -456,6 +456,10 @@ class StorableObject:
return len(cls.select(clause))
return len(cls.keys())
@classmethod
def exists(cls, clause=None):
return bool(cls.count(clause))
@classmethod
def sort_results(cls, objects, order_by):
if not order_by:

View File

@ -1878,6 +1878,25 @@ class SqlMixin:
cur.close()
return count
@classmethod
@guard_postgres
def exists(cls, clause=None):
where_clauses, parameters, func_clause = parse_clause(clause)
if func_clause:
# fallback to counting the result of a select()
return len(cls.select(clause))
sql_statement = 'SELECT 1 FROM %s' % cls._table_name
if where_clauses:
sql_statement += ' WHERE ' + ' AND '.join(where_clauses)
sql_statement += ' LIMIT 1'
conn, cur = get_connection_and_cursor()
cur.execute(sql_statement, parameters)
check = cur.fetchone()
result = check is not None
conn.commit()
cur.close()
return result
@classmethod
@guard_postgres
def get_with_indexed_value(