Commit 9841da3a authored by Jérome Perrin's avatar Jérome Perrin

Catalog: raise error when provided unknown query parameters

This behaviour can be disabled:
 - for a given query, by passing ignore_unknown_query_parameter=True. This can
   be helpful if you pass user parameters to the catalog, like listbox does.
 - globally, by setting sql_catalog_raise_error_on_unknown_query_parameter
   property on catalog. This can be helpful if you just want to hide errors
   from users without having to fix the code.
parent 90fda2d3
...@@ -235,6 +235,12 @@ class Selection(Acquisition.Implicit, Traversable, Persistent): ...@@ -235,6 +235,12 @@ class Selection(Acquisition.Implicit, Traversable, Persistent):
kw['selection_domain'] = self.domain kw['selection_domain'] = self.domain
if self.report is not None: if self.report is not None:
kw['selection_report'] = self.report kw['selection_report'] = self.report
# As we are passing user provided values to the catalog, pass this
# special argument to tell the catalog not to raise on unknown
# parameters.
kw['ignore_unknown_query_parameter'] = True
if callable(method): if callable(method):
result = method(**kw) result = method(**kw)
else: else:
......
...@@ -584,7 +584,13 @@ class Catalog(Folder, ...@@ -584,7 +584,13 @@ class Catalog(Folder,
'type': 'boolean', 'type': 'boolean',
'default' : True, 'default' : True,
'mode': 'w' }, 'mode': 'w' },
{ 'id': 'sql_catalog_raise_error_on_unknown_query_parameter',
'title': 'Raise error on unknown query parameter',
'description': 'Boolean used to tell if we raise error when search '
'is provided unknown values',
'type': 'boolean',
'default' : True,
'mode': 'w' },
) )
sql_catalog_produce_reserved = '' sql_catalog_produce_reserved = ''
...@@ -626,6 +632,7 @@ class Catalog(Folder, ...@@ -626,6 +632,7 @@ class Catalog(Folder,
sql_catalog_security_uid_columns = (' | security_uid',) sql_catalog_security_uid_columns = (' | security_uid',)
sql_catalog_table_vote_scripts = () sql_catalog_table_vote_scripts = ()
sql_catalog_raise_error_on_uid_check = True sql_catalog_raise_error_on_uid_check = True
sql_catalog_raise_error_on_unknown_query_parameter = True
# These are ZODB variables, so shared by multiple Zope instances. # These are ZODB variables, so shared by multiple Zope instances.
# This is set to the last logical time when clearReserved is called. # This is set to the last logical time when clearReserved is called.
...@@ -2205,7 +2212,8 @@ class Catalog(Folder, ...@@ -2205,7 +2212,8 @@ class Catalog(Folder,
return self._parseSearchText(self.getSearchKey( return self._parseSearchText(self.getSearchKey(
column, search_key=search_key), search_text, is_valid=is_valid) column, search_key=search_key), search_text, is_valid=is_valid)
def buildQuery(self, kw, ignore_empty_string=True, operator='and'): def buildQuery(self, kw, ignore_empty_string=True,
ignore_unknown_query_parameter=False, operator='and'):
query_list = [] query_list = []
append = query_list.append append = query_list.append
# unknown_column_dict: contains all (key, value) pairs which could not be # unknown_column_dict: contains all (key, value) pairs which could not be
...@@ -2288,6 +2296,10 @@ class Catalog(Folder, ...@@ -2288,6 +2296,10 @@ class Catalog(Folder,
if len(empty_value_dict): if len(empty_value_dict):
LOG('SQLCatalog', WARNING, 'Discarding columns with empty values: %r' % (empty_value_dict, )) LOG('SQLCatalog', WARNING, 'Discarding columns with empty values: %r' % (empty_value_dict, ))
if len(unknown_column_dict): if len(unknown_column_dict):
if self.sql_catalog_raise_error_on_unknown_query_parameter:
if not ignore_unknown_query_parameter:
raise ValueError("Unknown catalog columns: %s" % unknown_column_dict.keys(),)
else:
LOG('SQLCatalog', WARNING, 'Unknown columns %r, skipped.' % (unknown_column_dict.keys(), )) LOG('SQLCatalog', WARNING, 'Unknown columns %r, skipped.' % (unknown_column_dict.keys(), ))
return ComplexQuery(query_list, logical_operator=operator, return ComplexQuery(query_list, logical_operator=operator,
unknown_column_dict=unknown_column_dict) unknown_column_dict=unknown_column_dict)
...@@ -2336,6 +2348,7 @@ class Catalog(Folder, ...@@ -2336,6 +2348,7 @@ class Catalog(Folder,
return order_by_list return order_by_list
def buildEntireQuery(self, kw, query_table='catalog', ignore_empty_string=1, def buildEntireQuery(self, kw, query_table='catalog', ignore_empty_string=1,
ignore_unknown_query_parameter=False,
limit=None, extra_column_list=()): limit=None, extra_column_list=()):
group_by_list = kw.pop('group_by_list', kw.pop('group_by', kw.pop('group_by_expression', ()))) group_by_list = kw.pop('group_by_list', kw.pop('group_by', kw.pop('group_by_expression', ())))
if isinstance(group_by_list, basestring): if isinstance(group_by_list, basestring):
...@@ -2394,7 +2407,8 @@ class Catalog(Folder, ...@@ -2394,7 +2407,8 @@ class Catalog(Folder,
# new API. # new API.
order_by_override_list = kw.pop('select_expression_key', ()) order_by_override_list = kw.pop('select_expression_key', ())
return EntireQuery( return EntireQuery(
query=self.buildQuery(kw, ignore_empty_string=ignore_empty_string), query=self.buildQuery(kw, ignore_empty_string=ignore_empty_string,
ignore_unknown_query_parameter=ignore_unknown_query_parameter),
order_by_list=order_by_list, order_by_list=order_by_list,
order_by_override_list=order_by_override_list, order_by_override_list=order_by_override_list,
group_by_list=group_by_list, group_by_list=group_by_list,
...@@ -2407,11 +2421,15 @@ class Catalog(Folder, ...@@ -2407,11 +2421,15 @@ class Catalog(Folder,
from_expression=from_expression) from_expression=from_expression)
def buildSQLQuery(self, query_table='catalog', REQUEST=None, def buildSQLQuery(self, query_table='catalog', REQUEST=None,
ignore_empty_string=1, only_group_columns=False, ignore_empty_string=1,
ignore_unknown_query_parameter=False,
only_group_columns=False,
limit=None, extra_column_list=(), limit=None, extra_column_list=(),
**kw): **kw):
query = self.buildEntireQuery(kw, query_table=query_table, query = self.buildEntireQuery(kw, query_table=query_table,
ignore_empty_string=ignore_empty_string, limit=limit, ignore_empty_string=ignore_empty_string,
ignore_unknown_query_parameter=ignore_unknown_query_parameter,
limit=limit,
extra_column_list=extra_column_list) extra_column_list=extra_column_list)
result = query.asSQLExpression(self, only_group_columns).asSQLExpressionDict() result = query.asSQLExpression(self, only_group_columns).asSQLExpressionDict()
return result return result
......
...@@ -791,6 +791,11 @@ class TestSQLCatalog(ERP5TypeTestCase): ...@@ -791,6 +791,11 @@ class TestSQLCatalog(ERP5TypeTestCase):
self._searchTextInDictQuery('date') self._searchTextInDictQuery('date')
self._searchTextInDictQuery('related_date') self._searchTextInDictQuery('related_date')
def test_raiseOnUnknownParameter(self):
self.assertRaises(ValueError, self._catalog._queryResults, foobar=1)
self._catalog._queryResults(ignore_unknown_query_parameter=True, foobar=1)
##return catalog(title=Query(title='a', operator='not')) ##return catalog(title=Query(title='a', operator='not'))
#return catalog(title={'query': 'a', 'operator': 'not'}) #return catalog(title={'query': 'a', 'operator': 'not'})
#return catalog(title={'query': ['a', 'b'], 'operator': 'not'}) #return catalog(title={'query': ['a', 'b'], 'operator': 'not'})
......
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