sql: add method to load evolutions in batch (#7015)

This commit is contained in:
Frédéric Péters 2015-04-22 16:34:22 +02:00
parent 9195b848bc
commit 0b455795ed
3 changed files with 59 additions and 0 deletions

View File

@ -254,6 +254,27 @@ def test_sql_evolution_change():
assert len(formdata.evolution) == 2
assert formdata.evolution[-1].comment == 'foobar'
@postgresql
def test_sql_multiple_evolutions():
data_class = formdef.data_class(mode='sql')
for i in range(20):
formdata = data_class()
formdata.just_created()
formdata.store()
id = formdata.id
formdata = data_class.get(id)
evo = Evolution()
evo.time = time.localtime()
evo.status = formdata.status
evo.comment = 'hello world %d' % i
formdata.evolution.append(evo)
formdata.store()
values = data_class.select()
data_class.load_all_evolutions(values)
assert [x._evolution for x in values]
@postgresql
def test_sql_get_ids_with_indexed_value():

View File

@ -1116,6 +1116,10 @@ class FormPage(Directory):
do_graphs = get_publisher().is_using_postgresql()
values = self.formdef.data_class().select(criterias)
if get_publisher().is_using_postgresql():
# load all evolutions in a single batch, to avoid as many query as
# there are formdata when computing resolution times statistics.
self.formdef.data_class().load_all_evolutions(values)
r += htmltext('<div id="statistics">')
if do_graphs:

View File

@ -883,6 +883,40 @@ class SqlFormData(SqlMixin, wcs.formdata.FormData):
evolution = property(get_evolution, set_evolution)
@guard_postgres
def load_all_evolutions(cls, values):
# Typically formdata.evolution is loaded on-demand (see above
# property()) and this is fine to minimize queries, especially when
# dealing with a single formdata. However in some places (to compute
# statistics for example) it is sometimes useful to access .evolution
# on a serie of formdata and in that case, it's more efficient to
# optimize the process loading all evolutions in a single batch query.
object_dict = dict([(x.id, x) for x in values if x.id and x._evolution is None])
conn, cur = get_connection_and_cursor()
sql_statement = '''SELECT id, who, status, time, comment, parts, formdata_id
FROM %s_evolutions''' % cls._table_name
sql_statement += ''' WHERE formdata_id IN %(object_ids)s ORDER BY id'''
cur.execute(sql_statement, {'object_ids': tuple(object_dict.keys())})
for value in values:
value._evolution = []
while True:
row = cur.fetchone()
if row is None:
break
_sql_id, who, status, time, comment, parts, formdata_id = tuple(row[:7])
formdata = object_dict.get(formdata_id)
if not formdata:
continue
formdata._evolution.append(formdata._row2evo(row))
conn.commit()
cur.close()
load_all_evolutions = classmethod(load_all_evolutions)
@guard_postgres
def store(self):
sql_dict = {