Commit 886a6526 authored by Vincent Pelletier's avatar Vincent Pelletier

ZSQLCatalog: Drop support for *_expression arguments

parent c335c68f
...@@ -3546,31 +3546,6 @@ VALUES ...@@ -3546,31 +3546,6 @@ VALUES
self.assertEqual([x.getTitle() for x in self.assertEqual([x.getTitle() for x in
folder_object_list], real_title_list) folder_object_list], real_title_list)
def test_countResultsUsesFromExpression(self):
person_module = self.getPersonModule()
module_len = len(person_module)
if module_len == 0:
person = person_module.newContent(portal_type='Person')
module_len = len(person_module)
module_uid = person_module.getUid()
self.tic()
catalog = self.getCatalogTool()
# Test sanity checks
self.assertEqual(len(catalog.searchResults(parent_uid=module_uid)),
module_len)
self.assertEqual(catalog.countResults(parent_uid=module_uid)[0][0],
module_len)
from_expression = {
'catalog': '(SELECT sub_catalog.* FROM catalog AS sub_catalog'
' WHERE sub_catalog.parent_uid=%i)'
' AS catalog' % (module_uid, ),
}
count = catalog.countResults(from_expression=from_expression)[0][0]
self.assertEqual(count, module_len)
def test_getParentUid(self): def test_getParentUid(self):
from Products.ERP5.Document.Assignment import Assignment from Products.ERP5.Document.Assignment import Assignment
import erp5.portal_type import erp5.portal_type
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
from Query import Query from Query import Query
from Products.ZSQLCatalog.SQLExpression import SQLExpression from Products.ZSQLCatalog.SQLExpression import SQLExpression
from SQLQuery import SQLQuery
from Products.ZSQLCatalog.interfaces.query import IQuery from Products.ZSQLCatalog.interfaces.query import IQuery
from zope.interface.verify import verifyClass from zope.interface.verify import verifyClass
from Products.ZSQLCatalog.Query.AutoQuery import AutoQuery from Products.ZSQLCatalog.Query.AutoQuery import AutoQuery
...@@ -53,20 +52,9 @@ class ComplexQuery(Query): ...@@ -53,20 +52,9 @@ class ComplexQuery(Query):
logical_operator ('and', 'or', 'not') logical_operator ('and', 'or', 'not')
Logical operator. Logical operator.
Default: 'and' Default: 'and'
Deprecated
unknown_column_dict (dict)
Only one key of this dictionnary is used here:
key: 'from_expression'
value: string
This value will be passed through to SQLExpression. If it is
provided, this ComplexQuery must have no subquery (regular
SQLExpression limitation)
""" """
self.logical_operator = kw.pop('logical_operator', 'and').lower() self.logical_operator = kw.pop('logical_operator', 'and').lower()
assert self.logical_operator in ('and', 'or', 'not'), self.logical_operator assert self.logical_operator in ('and', 'or', 'not'), self.logical_operator
unknown_column_dict = kw.pop('unknown_column_dict', {})
self.from_expression = unknown_column_dict.pop('from_expression', None)
if kw: if kw:
raise TypeError('Unknown named arguments: %r' % (kw.keys(), )) raise TypeError('Unknown named arguments: %r' % (kw.keys(), ))
query_list = [] query_list = []
...@@ -78,14 +66,10 @@ class ComplexQuery(Query): ...@@ -78,14 +66,10 @@ class ComplexQuery(Query):
extend(arg) extend(arg)
else: else:
append(arg) append(arg)
new_query_list = []
append = new_query_list.append
# Iterate over the flaten argument list to cast each into a query type.
for query in query_list: for query in query_list:
if not isinstance(query, Query): if not isinstance(query, Query):
query = SQLQuery(query) raise TypeError('Got a non-query argument: %r' % (query, ))
append(query) self.query_list = query_list
self.query_list = new_query_list
self.checkQueryTree() self.checkQueryTree()
def _findRelatedQuery(self, query): def _findRelatedQuery(self, query):
...@@ -190,7 +174,7 @@ class ComplexQuery(Query): ...@@ -190,7 +174,7 @@ class ComplexQuery(Query):
return SQLExpression(self, return SQLExpression(self,
sql_expression_list=sql_expression_list, sql_expression_list=sql_expression_list,
where_expression_operator=self.logical_operator, where_expression_operator=self.logical_operator,
from_expression=self.from_expression) )
def registerColumnMap(self, sql_catalog, column_map): def registerColumnMap(self, sql_catalog, column_map):
for query in self.query_list: for query in self.query_list:
......
...@@ -64,12 +64,9 @@ class EntireQuery(object): ...@@ -64,12 +64,9 @@ class EntireQuery(object):
catalog_table_name=None, catalog_table_name=None,
catalog_table_alias=None, catalog_table_alias=None,
extra_column_list=(), extra_column_list=(),
from_expression=None,
order_by_override_list=None,
implicit_join=False): implicit_join=False):
self.query = query self.query = query
self.order_by_list = list(order_by_list) self.order_by_list = list(order_by_list)
self.order_by_override_set = frozenset(order_by_override_list)
self.group_by_list = list(group_by_list) self.group_by_list = list(group_by_list)
self.select_dict = defaultDict(select_dict) self.select_dict = defaultDict(select_dict)
self.left_join_list = left_join_list self.left_join_list = left_join_list
...@@ -78,7 +75,6 @@ class EntireQuery(object): ...@@ -78,7 +75,6 @@ class EntireQuery(object):
self.catalog_table_name = catalog_table_name self.catalog_table_name = catalog_table_name
self.catalog_table_alias = catalog_table_alias self.catalog_table_alias = catalog_table_alias
self.extra_column_list = list(extra_column_list) self.extra_column_list = list(extra_column_list)
self.from_expression = from_expression
self.implicit_join = implicit_join self.implicit_join = implicit_join
def asSearchTextExpression(self, sql_catalog): def asSearchTextExpression(self, sql_catalog):
...@@ -91,7 +87,6 @@ class EntireQuery(object): ...@@ -91,7 +87,6 @@ class EntireQuery(object):
# method or do it here ? # method or do it here ?
# Column Map was not built yet, do it. # Column Map was not built yet, do it.
column_map = ColumnMap(catalog_table_name=self.catalog_table_name, column_map = ColumnMap(catalog_table_name=self.catalog_table_name,
table_override_map=self.from_expression,
left_join_list=self.left_join_list, left_join_list=self.left_join_list,
inner_join_list=self.inner_join_list, inner_join_list=self.inner_join_list,
implicit_join=self.implicit_join, implicit_join=self.implicit_join,
...@@ -115,8 +110,6 @@ class EntireQuery(object): ...@@ -115,8 +110,6 @@ class EntireQuery(object):
else: else:
column_map.ignoreColumn(alias) column_map.ignoreColumn(alias)
column_map.registerColumn(column) column_map.registerColumn(column)
for override in self.order_by_override_set:
column_map.ignoreColumn(override)
for order_by in self.order_by_list: for order_by in self.order_by_list:
assert isinstance(order_by, (tuple, list)) assert isinstance(order_by, (tuple, list))
assert len(order_by) assert len(order_by)
...@@ -155,15 +148,11 @@ class EntireQuery(object): ...@@ -155,15 +148,11 @@ class EntireQuery(object):
append = new_order_by_list.append append = new_order_by_list.append
for order_by in self.order_by_list: for order_by in self.order_by_list:
column = order_by[0] column = order_by[0]
if column in self.order_by_override_set: try:
LOG('EntireQuery', WARNING, 'Order-by column %r is forcibly accepted. This use is strongly discouraged.' % (column, )) rendered = column_map.asSQLColumn(column)
rendered = column except KeyError:
else: LOG('EntireQuery', WARNING, 'Order by %r ignored: it could not be mapped to a known column.' % (order_by, ))
try: rendered = None
rendered = column_map.asSQLColumn(column)
except KeyError:
LOG('EntireQuery', WARNING, 'Order by %r ignored: it could not be mapped to a known column.' % (order_by, ))
rendered = None
if rendered is not None: if rendered is not None:
append((rendered, ) + tuple(order_by[1:]) + ( append((rendered, ) + tuple(order_by[1:]) + (
None, ) * (3 - len(order_by))) None, ) * (3 - len(order_by)))
...@@ -196,21 +185,11 @@ class EntireQuery(object): ...@@ -196,21 +185,11 @@ class EntireQuery(object):
# where_pattern % (x, ) for x in join_table_list # where_pattern % (x, ) for x in join_table_list
# ))) # )))
# BBB self.from_expression forces use of implicit inner join
table_alias_dict = column_map.getTableAliasDict() table_alias_dict = column_map.getTableAliasDict()
if self.from_expression: from_expression = column_map.getTableDefinition()
warnings.warn("Providing a 'from_expression' is deprecated.", assert ((from_expression is None) !=
DeprecationWarning) (table_alias_dict is None)), ("Got both a from_expression "
# XXX: perhaps move this code to ColumnMap? "and a table_alias_dict")
legacy_from_expression = self.from_expression
from_expression = LegacyTableDefinition(legacy_from_expression,
table_alias_dict)
table_alias_dict = None
else:
from_expression = column_map.getTableDefinition()
assert ((from_expression is None) !=
(table_alias_dict is None)), ("Got both a from_expression "
"and a table_alias_dict")
self.sql_expression_list = sql_expression_list self.sql_expression_list = sql_expression_list
# TODO: wrap the table_alias_dict above into a TableDefinition as well, # TODO: wrap the table_alias_dict above into a TableDefinition as well,
# even without a legacy_table_definition. # even without a legacy_table_definition.
......
...@@ -296,7 +296,7 @@ class Catalog(Folder, ...@@ -296,7 +296,7 @@ class Catalog(Folder,
An Object Catalog maintains a table of object metadata, and a An Object Catalog maintains a table of object metadata, and a
series of manageable indexes to quickly search for objects series of manageable indexes to quickly search for objects
(references in the metadata) that satisfy a search where_expression. (references in the metadata) that satisfy search conditions.
This class is not Zope specific, and can be used in any python This class is not Zope specific, and can be used in any python
program to build catalogs of objects. Note that it does require program to build catalogs of objects. Note that it does require
...@@ -2014,11 +2014,7 @@ class Catalog(Folder, ...@@ -2014,11 +2014,7 @@ class Catalog(Folder,
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
# changed into queries. This is here for backward compatibility, because # changed into queries.
# scripts can invoke this method and expect extra parameters (such as
# from_expression) to be handled. As they are normaly handled at
# buildSQLQuery level, we must store them into final ComplexQuery, which
# will handle them.
unknown_column_dict = {} unknown_column_dict = {}
# empty_value_dict: contains all keys whose value causes them to be # empty_value_dict: contains all keys whose value causes them to be
# discarded. # discarded.
...@@ -2107,11 +2103,10 @@ class Catalog(Folder, ...@@ -2107,11 +2103,10 @@ class Catalog(Folder,
LOG('SQLCatalog', WARNING, message) LOG('SQLCatalog', WARNING, message)
else: else:
raise TypeError(message) raise TypeError(message)
return ComplexQuery(query_list, logical_operator=operator, return ComplexQuery(query_list, logical_operator=operator)
unknown_column_dict=unknown_column_dict)
security.declarePrivate('buildOrderByList') security.declarePrivate('buildOrderByList')
def buildOrderByList(self, sort_on=None, sort_order=None, order_by_expression=None): def buildOrderByList(self, sort_on=None, sort_order=None):
""" """
Internal method. Should not be used by code outside buildSQLQuery. Internal method. Should not be used by code outside buildSQLQuery.
...@@ -2128,8 +2123,6 @@ class Catalog(Folder, ...@@ -2128,8 +2123,6 @@ class Catalog(Folder,
order_by_list = [] order_by_list = []
append = order_by_list.append append = order_by_list.append
if sort_on is not None: if sort_on is not None:
if order_by_expression is not None:
LOG('SQLCatalog', WARNING, 'order_by_expression (%r) and sort_on (%r) were given. Ignoring order_by_expression.' % (order_by_expression, sort_on))
if not isinstance(sort_on, (tuple, list)): if not isinstance(sort_on, (tuple, list)):
sort_on = [[sort_on]] sort_on = [[sort_on]]
for item in sort_on: for item in sort_on:
...@@ -2150,16 +2143,6 @@ class Catalog(Folder, ...@@ -2150,16 +2143,6 @@ class Catalog(Folder,
elif item[2] == 'float': elif item[2] == 'float':
item[2] = 'DECIMAL' item[2] = 'DECIMAL'
append(item) append(item)
elif order_by_expression is not None:
if not isinstance(order_by_expression, basestring):
raise TypeError, 'order_by_expression must be a basestring instance. Got %r.' % (order_by_expression, )
for x in order_by_expression.split(','):
x = x.strip()
item = x.rsplit(None, 1)
if len(item) > 1 and item[-1].upper() in ('ASC', 'DESC'):
append(item)
else:
append([x])
return order_by_list return order_by_list
security.declarePrivate('buildEntireQuery') security.declarePrivate('buildEntireQuery')
...@@ -2182,23 +2165,9 @@ class Catalog(Folder, ...@@ -2182,23 +2165,9 @@ class Catalog(Folder,
implicit_join = kw.pop('implicit_join', True) implicit_join = kw.pop('implicit_join', True)
# Handle order_by_list # Handle order_by_list
order_by_list = kw.pop('order_by_list', []) order_by_list = kw.pop('order_by_list', [])
# Handle from_expression
from_expression = kw.pop('from_expression', None)
# Handle where_expression
where_expression = kw.get('where_expression', None)
if isinstance(where_expression, basestring) and len(where_expression):
LOG('SQLCatalog', INFO, 'Giving where_expression a string value is deprecated.')
# Transform given where_expression into a query, and update kw.
kw['where_expression'] = SQLQuery(where_expression)
# Handle select_expression_key
# It is required to support select_expression_key parameter for backward
# compatiblity, but I'm not sure if there can be a serious use for it in
# new API.
order_by_override_list = kw.pop('select_expression_key', ())
return EntireQuery( return EntireQuery(
query=self.buildQuery(kw, ignore_empty_string=ignore_empty_string, ignore_unknown_columns=ignore_unknown_columns), query=self.buildQuery(kw, ignore_empty_string=ignore_empty_string, ignore_unknown_columns=ignore_unknown_columns),
order_by_list=order_by_list, order_by_list=order_by_list,
order_by_override_list=order_by_override_list,
group_by_list=group_by_list, group_by_list=group_by_list,
select_dict=select_dict, select_dict=select_dict,
left_join_list=left_join_list, left_join_list=left_join_list,
...@@ -2208,7 +2177,7 @@ class Catalog(Folder, ...@@ -2208,7 +2177,7 @@ class Catalog(Folder,
catalog_table_name=query_table, catalog_table_name=query_table,
catalog_table_alias=query_table_alias, catalog_table_alias=query_table_alias,
extra_column_list=extra_column_list, extra_column_list=extra_column_list,
from_expression=from_expression) )
security.declarePublic('buildSQLQuery') security.declarePublic('buildSQLQuery')
def buildSQLQuery(self, query_table='catalog', def buildSQLQuery(self, query_table='catalog',
...@@ -2240,56 +2209,32 @@ class Catalog(Folder, ...@@ -2240,56 +2209,32 @@ class Catalog(Folder,
""" """
Convert some catalog arguments to generic arguments. Convert some catalog arguments to generic arguments.
group_by, group_by_expression -> group_by_list group_by -> group_by_list
select_list, select_expression -> select_dict select_list -> select_dict
sort_on, sort_on_order, order_by_expression -> order_list sort_on, sort_on_order -> order_list
""" """
kw = kw.copy() kw = kw.copy()
group_by = kw.pop('group_by', None)
group_by_expression = kw.pop('group_by_expression', None) kw['group_by_list'] = kw.pop('group_by_list', None) or kw.pop('group_by', [])
group_by_list = kw.pop('group_by_list', None) or group_by or group_by_expression or []
if isinstance(group_by_list, basestring): select_dict = kw.pop('select_dict', None) or kw.pop('select_list', {})
group_by_list = [x.strip() for x in group_by_list.split(',')]
kw['group_by_list'] = group_by_list
select_list = kw.pop('select_list', None)
select_expression = kw.pop('select_expression', None)
select_dict = kw.pop('select_dict', None) or select_list or select_expression or {}
if isinstance(select_dict, (list, tuple)): if isinstance(select_dict, (list, tuple)):
select_dict = dict.fromkeys(select_dict) select_dict = dict.fromkeys(select_dict)
if isinstance(select_dict, basestring):
if len(select_dict):
real_select_dict = {}
for column in select_dict.split(','):
index = column.lower().find(' as ')
if index != -1:
real_select_dict[column[index + 4:].strip()] = column[:index].strip()
else:
real_select_dict[column.strip()] = None
select_dict = real_select_dict
else:
select_dict = None
elif isinstance(select_dict, (list, tuple)):
select_dict = dict.fromkeys(select_dict)
kw['select_dict'] = select_dict kw['select_dict'] = select_dict
order_by_list = kw.pop('order_by_list', None) order_by_list = kw.pop('order_by_list', None)
sort_on = kw.pop('sort_on', None) sort_on = kw.pop('sort_on', None)
sort_order = kw.pop('sort_order', None) sort_order = kw.pop('sort_order', None)
order_by_expression = kw.pop('order_by_expression', None)
if order_by_list is None: if order_by_list is None:
order_by_list = self.buildOrderByList( order_by_list = self.buildOrderByList(
sort_on=sort_on, sort_on=sort_on,
sort_order=sort_order, sort_order=sort_order,
order_by_expression=order_by_expression,
) )
else: else:
if sort_on is not None: if sort_on is not None:
LOG('SQLCatalog', WARNING, 'order_by_list and sort_on were given, ignoring sort_on.') LOG('SQLCatalog', WARNING, 'order_by_list and sort_on were given, ignoring sort_on.')
if sort_order is not None: if sort_order is not None:
LOG('SQLCatalog', WARNING, 'order_by_list and sort_order were given, ignoring sort_order.') LOG('SQLCatalog', WARNING, 'order_by_list and sort_order were given, ignoring sort_order.')
if order_by_expression is not None:
LOG('SQLCatalog', WARNING, 'order_by_list and order_by_expression were given, ignoring order_by_expression.')
kw['order_by_list'] = order_by_list or [] kw['order_by_list'] = order_by_list or []
return kw return kw
...@@ -2412,7 +2357,7 @@ class Catalog(Folder, ...@@ -2412,7 +2357,7 @@ class Catalog(Folder,
security.declarePrivate('countResults') security.declarePrivate('countResults')
def countResults(self, REQUEST=None, **kw): def countResults(self, REQUEST=None, **kw):
""" Returns the number of items which satisfy the where_expression """ """ Returns the number of items which satisfy the conditions """
return self.queryResults( return self.queryResults(
self.getCountResultsMethod(), self.getCountResultsMethod(),
REQUEST=REQUEST, REQUEST=REQUEST,
......
...@@ -45,8 +45,7 @@ class IEntireQuery(Interface): ...@@ -45,8 +45,7 @@ class IEntireQuery(Interface):
def __init__(query, order_by_list=None, group_by_list=None, def __init__(query, order_by_list=None, group_by_list=None,
select_dict=None, limit=None, catalog_table_name=None, select_dict=None, limit=None, catalog_table_name=None,
extra_column_list=None, from_expression=None, extra_column_list=None):
order_by_override_list=None):
""" """
query (Query instance) query (Query instance)
The root of the Query tree this query will contain. The root of the Query tree this query will contain.
...@@ -73,12 +72,6 @@ class IEntireQuery(Interface): ...@@ -73,12 +72,6 @@ class IEntireQuery(Interface):
The list of columns to register to column map. They will not be used The list of columns to register to column map. They will not be used
in final rendering, but are hint on which table are supposed to be in final rendering, but are hint on which table are supposed to be
used when mapping columns. used when mapping columns.
from_expression
See SQLExpression.
order_by_override_list (list of string)
If a column is in order_by_list, cannot be mapped to a table column
but is present in this list, it will be passed through to
SQLExpression.
""" """
def asSQLExpression(sql_catalog, only_group_columns): def asSQLExpression(sql_catalog, only_group_columns):
......
...@@ -805,21 +805,6 @@ class TestSQLCatalog(ERP5TypeTestCase): ...@@ -805,21 +805,6 @@ class TestSQLCatalog(ERP5TypeTestCase):
sort_on=[['default', 'DESC', 'INT']] sort_on=[['default', 'DESC', 'INT']]
) )
self.assertEqual(order_by_list, [['default', 'DESC', 'INT']]) self.assertEqual(order_by_list, [['default', 'DESC', 'INT']])
order_by_list = self._catalog.buildOrderByList(
order_by_expression='default'
)
order_by_list = self._catalog.buildOrderByList(
order_by_expression='default DESC'
)
self.assertEqual(order_by_list, [['default', 'DESC']])
order_by_list = self._catalog.buildOrderByList(
order_by_expression='CAST(default AS INT) DESC'
)
self.assertEqual(order_by_list, [['CAST(default AS INT)', 'DESC']])
order_by_list = self._catalog.buildOrderByList(
order_by_expression='CAST(default AS INT)'
)
self.assertEqual(order_by_list, [['CAST(default AS INT)']])
##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'})
......
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