Commit 28d9d29e authored by Jérome Perrin's avatar Jérome Perrin

sort-index was not workfing for dynamic related keys, and was poorly tested.



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@9225 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 12cc382b
...@@ -39,13 +39,14 @@ from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase ...@@ -39,13 +39,14 @@ from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
from zLOG import LOG from zLOG import LOG
from DateTime import DateTime from DateTime import DateTime
from Products.CMFCore.tests.base.testcase import LogInterceptor
try: try:
from transaction import get as get_transaction from transaction import get as get_transaction
except ImportError: except ImportError:
pass pass
class TestERP5Catalog(ERP5TypeTestCase): class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor):
""" """
Tests for ERP5 Catalog. Tests for ERP5 Catalog.
""" """
...@@ -62,10 +63,15 @@ class TestERP5Catalog(ERP5TypeTestCase): ...@@ -62,10 +63,15 @@ class TestERP5Catalog(ERP5TypeTestCase):
def afterSetUp(self, quiet=1, run=1): def afterSetUp(self, quiet=1, run=1):
self.login() self.login()
portal = self.getPortal()
catalog_tool = self.getCatalogTool() def beforeTearDown(self):
# XXX This does not works for module in [ self.getPersonModule(),
#catalog_tool.reindexObject(portal) self.getOrganisationModule(),
self.getCategoryTool().region,
self.getCategoryTool().group ]:
module.manage_delObjects(list(module.objectIds()))
self.getPortal().portal_activities.manageClearActivities()
get_transaction().commit()
def login(self, quiet=0, run=run_all_test): def login(self, quiet=0, run=run_all_test):
uf = self.getPortal().acl_users uf = self.getPortal().acl_users
...@@ -740,3 +746,70 @@ class TestERP5Catalog(ERP5TypeTestCase): ...@@ -740,3 +746,70 @@ class TestERP5Catalog(ERP5TypeTestCase):
self.assertNotEquals([], self.getCatalogTool().searchResults( self.assertNotEquals([], self.getCatalogTool().searchResults(
portal_type='Person', title=u'A Person')) portal_type='Person', title=u'A Person'))
def test_SortOn(self, quiet=quiet, run=run_all_test):
if not run: return
self.assertEquals('catalog.title',
self.getCatalogTool().buildSQLQuery(
sort_on=(('catalog.title', 'ascending'),))['order_by_expression'])
def test_SortOnDescending(self, quiet=quiet, run=run_all_test):
if not run: return
self.assertEquals('catalog.title DESC',
self.getCatalogTool().buildSQLQuery(
sort_on=(('catalog.title', 'descending'),))['order_by_expression'])
def test_SortOnUnknownKeys(self, quiet=quiet, run=run_all_test):
if not run: return
self.assertEquals('',
self.getCatalogTool().buildSQLQuery(
sort_on=(('ignored', 'ascending'),))['order_by_expression'])
def test_SortOnAmbigousKeys(self, quiet=quiet, run=run_all_test):
if not run: return
# if the sort key is found on the catalog table, it will use that catalog
# table.
self.assertEquals('catalog.title',
self.getCatalogTool().buildSQLQuery(
sort_on=(('title', 'ascending'),))['order_by_expression'])
# if not found on catalog, it won't do any filtering
# in the above, start_date exists both in delivery and movement table.
self._catch_log_errors(ignored_level = sys.maxint)
self.assertEquals('',
self.getCatalogTool().buildSQLQuery(
sort_on=(('start_date', 'ascending'),))['order_by_expression'])
self._ignore_log_errors()
# buildSQLQuery will simply put a warning in the error log and ignore
# this key
logged_errors = [ logrecord for logrecord in self.logged
if logrecord[0] == 'SQLCatalog' ]
self.failUnless(
'could not build the new sort index' in logged_errors[0][2])
# of course, in that case, it's possible to prefix with table name
self.assertEquals('delivery.start_date',
self.getCatalogTool().buildSQLQuery(
sort_on=(('delivery.start_date', 'ascending'),
))['order_by_expression'])
def test_SortOnMultipleKeys(self, quiet=quiet, run=run_all_test):
if not run: return
self.assertEquals('catalog.title,catalog.id',
self.getCatalogTool().buildSQLQuery(
sort_on=(('catalog.title', 'ascending'),
('catalog.id', 'asc')))
['order_by_expression'].replace(' ', ''))
def test_SortOnRelatedKey(self, quiet=quiet, run=run_all_test):
"""Sort-on parameter and related key. (Assumes that region_title is a \
valid related key)"""
if not run: return
self.assertNotEquals('',
self.getCatalogTool().buildSQLQuery(region_title='',
sort_on=(('region_title', 'ascending'),))['order_by_expression'])
self.assertNotEquals('',
self.getCatalogTool().buildSQLQuery(
sort_on=(('region_title', 'ascending'),))['order_by_expression'],
'sort_on parameter must be taken into account even if related key '
'is not a parameter of the current query')
...@@ -1380,7 +1380,7 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -1380,7 +1380,7 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base):
return full_list return full_list
def buildSQLQuery(self, query_table='catalog', REQUEST=None, def buildSQLQuery(self, query_table='catalog', REQUEST=None,
ignore_empty_string=1,**kw): ignore_empty_string=1, **kw):
""" Builds a complex SQL query to simulate ZCalatog behaviour """ """ Builds a complex SQL query to simulate ZCalatog behaviour """
# Get search arguments: # Get search arguments:
if REQUEST is None and (kw is None or kw == {}): if REQUEST is None and (kw is None or kw == {}):
...@@ -1401,10 +1401,45 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -1401,10 +1401,45 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base):
topic_search_keys = self.sql_catalog_topic_search_keys topic_search_keys = self.sql_catalog_topic_search_keys
multivalue_keys = self.sql_catalog_multivalue_keys multivalue_keys = self.sql_catalog_multivalue_keys
# Compute "sort_index", which is a sort index, or none:
if kw.has_key('sort-on'):
sort_index=kw['sort-on']
elif hasattr(self, 'sort-on'):
sort_index=getattr(self, 'sort-on')
elif kw.has_key('sort_on'):
sort_index=kw['sort_on']
else: sort_index=None
# Compute the sort order
if kw.has_key('sort-order'):
so=kw['sort-order']
elif hasattr(self, 'sort-order'):
so=getattr(self, 'sort-order')
elif kw.has_key('sort_order'):
so=kw['sort_order']
else: so=None
# We must now turn sort_index into
# a dict with keys as sort keys and values as sort order
if isinstance(sort_index, basestring):
sort_index = [(sort_index, so)]
elif not isinstance(sort_index, (list, tuple)):
sort_index = None
# if we have a sort index, we must take it into account to get related
# keys.
if sort_index:
related_key_kw = dict(kw)
for sort_info in sort_index:
related_key_kw.setdefault(sort_info[0], '')
related_tuples = self.getSqlCatalogRelatedKeyList(**related_key_kw)
else:
related_tuples = self.getSqlCatalogRelatedKeyList(**kw)
# Define related maps # Define related maps
# each tuple has the form (key, 'table1,table2,table3/column/where_expression') # each tuple from `related_tuples` has the form (key,
related_tuples = self.getSqlCatalogRelatedKeyList(**kw) # 'table1,table2,table3/column/where_expression')
#LOG('related_tuples', 0, str(related_tuples))
related_keys = [] related_keys = []
related_method = {} related_method = {}
related_table_map = {} related_table_map = {}
...@@ -1451,35 +1486,6 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -1451,35 +1486,6 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base):
where_expression = [] where_expression = []
from_table_dict = {'catalog' : 'catalog'} # Always include catalog table from_table_dict = {'catalog' : 'catalog'} # Always include catalog table
# Compute "sort_index", which is a sort index, or none:
if kw.has_key('sort-on'):
sort_index=kw['sort-on']
elif hasattr(self, 'sort-on'):
sort_index=getattr(self, 'sort-on')
elif kw.has_key('sort_on'):
sort_index=kw['sort_on']
else: sort_index=None
# Compute the sort order
if kw.has_key('sort-order'):
so=kw['sort-order']
elif hasattr(self, 'sort-order'):
so=getattr(self, 'sort-order')
elif kw.has_key('sort_order'):
so=kw['sort_order']
else: so=None
# We must now turn sort_index into
# a dict with keys as sort keys and values as sort order
if isinstance(sort_index, basestring):
sort_index = [(sort_index, so)]
elif not isinstance(sort_index, (list, tuple)):
sort_index = None
# If sort_index is a dictionnary
# then parse it and change it
sort_on = None sort_on = None
if sort_index is not None: if sort_index is not None:
new_sort_index = [] new_sort_index = []
...@@ -1528,7 +1534,7 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -1528,7 +1534,7 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base):
raise raise
except: except:
LOG('SQLCatalog', WARNING, 'buildSQLQuery could not build the new sort index', error=sys.exc_info()) LOG('SQLCatalog', WARNING, 'buildSQLQuery could not build the new sort index', error=sys.exc_info())
pass sort_on = ''
# Rebuild keywords to behave as new style query (_usage='toto:titi' becomes {'toto':'titi'}) # Rebuild keywords to behave as new style query (_usage='toto:titi' becomes {'toto':'titi'})
new_kw = {} new_kw = {}
...@@ -1698,7 +1704,7 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -1698,7 +1704,7 @@ class Catalog(Folder, Persistent, Acquisition.Implicit, ExtensionClass.Base):
if k != query_table: if k != query_table:
where_expression.append('%s.uid = %s.uid' % (query_table, tid)) where_expression.append('%s.uid = %s.uid' % (query_table, tid))
# Calculate extra where_expressions based on related definition # Calculate extra where_expressions based on related definition
for (table_list,method_id) in related_methods.keys(): for (table_list, method_id) in related_methods.keys():
related_method = getattr(self, method_id, None) related_method = getattr(self, method_id, None)
if related_method is not None: if related_method is not None:
table_id = {'src__' : 1} # Return query source, do not evaluate table_id = {'src__' : 1} # Return query source, do not evaluate
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment