caches recursive selects for references

Why didn't we think before ? References are lazy, but when asked 
for representation why should we fetch the same referenced record
over and over ?

NB: the code caches only represent() fetching records from tables, that
are the only idempotent represent() calls out there. We could cache
every representation only asking for every represent() call to be 
idempotent. As I feel there will be someone returning random values,
I left it out.

I'll make a PR soon for pyDAL to fix the same behaviour.
This commit is contained in:
niphlod
2015-03-11 00:48:51 +01:00
parent ac24ce446e
commit d1ec005924

View File

@@ -2626,6 +2626,7 @@ class SQLFORM(FORM):
htmltable = TABLE(COLGROUP(*cols), THEAD(head))
tbody = TBODY()
numrec = 0
repr_cache = {}
for row in rows:
trcols = []
id = row[field_id]
@@ -2641,14 +2642,31 @@ class SQLFORM(FORM):
value = row[str(field)]
maxlength = maxtextlengths.get(str(field), maxtextlength)
if field.represent:
try:
value = field.represent(value, row)
except KeyError:
if field.type.startswith('reference'):
if field not in repr_cache:
repr_cache[field] = {}
try:
value = field.represent(
value, row[field.tablename])
nvalue = repr_cache[field][value]
except KeyError:
pass
try:
nvalue = field.represent(value, row)
except KeyError:
try:
nvalue = field.represent(
value, row[field.tablename])
except KeyError:
nvalue = None
repr_cache[field][value] = nvalue
else:
try:
nvalue = field.represent(value, row)
except KeyError:
try:
nvalue = field.represent(
value, row[field.tablename])
except KeyError:
nvalue = None
value = nvalue
elif field.type == 'boolean':
value = INPUT(_type="checkbox", _checked=value,
_disabled=True)
@@ -3118,6 +3136,7 @@ class SQLTABLE(TABLE):
components.append(THEAD(TR(*row)))
tbody = []
repr_cache = {}
for (rc, record) in enumerate(sqlrows):
row = []
if rc % 2 == 1:
@@ -3176,7 +3195,11 @@ class SQLTABLE(TABLE):
href = '%s/%s?%s' % (linkto, tref, urllib.urlencode({fref: r}))
r = A(represent(field, r, record), _href=str(href))
elif field.represent:
r = represent(field, r, record)
if field not in repr_cache:
repr_cache[field] = {}
if r not in repr_cache[field]:
repr_cache[field][r] = represent(field, r, record)
r = repr_cache[field][r]
elif linkto and hasattr(field._table, '_primarykey')\
and fieldname in field._table._primarykey:
# have to test this with multi-key tables
@@ -3293,6 +3316,7 @@ class ExportClass(object):
return value
represented = []
repr_cache = {}
for record in self.rows:
row = []
for col in self.rows.colnames:
@@ -3308,7 +3332,14 @@ class ExportClass(object):
if field.type == 'blob' and value is not None:
value = ''
elif field.represent:
value = field.represent(value, record)
if field.type.startswith('reference'):
if field not in repr_cache:
repr_cache[field] = {}
if value not in repr_cache[field]:
repr_cache[field][value] = field.represent(value, record)
value = repr_cache[field][value]
else:
value = field.represent(value, record)
row.append(none_exception(value))
represented.append(row)