sql: add method to load evolutions in batch (#7015)
This commit is contained in:
parent
9195b848bc
commit
0b455795ed
|
@ -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():
|
||||
|
|
|
@ -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:
|
||||
|
|
34
wcs/sql.py
34
wcs/sql.py
|
@ -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 = {
|
||||
|
|
Loading…
Reference in New Issue