From 20ce0e4227363e893d81761d725500c0d8eb34b8 Mon Sep 17 00:00:00 2001 From: Vincent Pelletier <vincent@nexedi.com> Date: Wed, 28 Jul 2010 12:33:15 +0000 Subject: [PATCH] Fix providing a sort direction for a full-text column. This changes SQLExpression API, but this should not be a problem, since this API is internal to ZSQLCatalog. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@37338 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ZSQLCatalog/Query/EntireQuery.py | 7 ++----- product/ZSQLCatalog/SQLExpression.py | 12 ++++++++++-- .../ZSQLCatalog/interfaces/sql_expression.py | 7 +++++-- product/ZSQLCatalog/tests/testSQLCatalog.py | 18 +++++++++++++++++- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/product/ZSQLCatalog/Query/EntireQuery.py b/product/ZSQLCatalog/Query/EntireQuery.py index 41ab108d72..6811b61580 100644 --- a/product/ZSQLCatalog/Query/EntireQuery.py +++ b/product/ZSQLCatalog/Query/EntireQuery.py @@ -141,11 +141,8 @@ class EntireQuery(object): LOG('SQLCatalog', 100, 'Order by %r ignored: it could not be mapped to a known column.' % (order_by, )) rendered = None if rendered is not None: - if len(order_by) > 1: - if len(order_by) > 2 and order_by[2] not in (None, ''): - rendered = 'CAST(%s AS %s)' % (rendered, order_by[2]) - rendered = '%s %s' % (rendered, order_by[1]) - append(rendered) + append((rendered, ) + tuple(order_by[1:]) + ( + None, ) * (3 - len(order_by))) self.order_by_list = new_order_by_list # generate SQLExpression from query sql_expression_list = [self.query.asSQLExpression(sql_catalog, column_map, only_group_columns)] diff --git a/product/ZSQLCatalog/SQLExpression.py b/product/ZSQLCatalog/SQLExpression.py index 13850bff2e..7ee0aa1a87 100644 --- a/product/ZSQLCatalog/SQLExpression.py +++ b/product/ZSQLCatalog/SQLExpression.py @@ -238,9 +238,17 @@ class SQLExpression(object): Returns a rendered "order by" expression. See getOrderByList. """ + result = [] + append = result.append order_by_dict = self._getOrderByDict() - return SQL_LIST_SEPARATOR.join(conflictSafeGet(order_by_dict, x, str(x)) \ - for x in self.getOrderByList()) + for (column, direction, cast) in self.getOrderByList(): + expression = conflictSafeGet(order_by_dict, column, str(column)) + if cast not in (None, ''): + expression = 'CAST(%s AS %s)' % (expression, cast) + if direction is not None: + expression = '%s %s' % (expression, direction) + append(expression) + return SQL_LIST_SEPARATOR.join(result) @profiler_decorator def getWhereExpression(self): diff --git a/product/ZSQLCatalog/interfaces/sql_expression.py b/product/ZSQLCatalog/interfaces/sql_expression.py index dc9b4df518..4099cba2dc 100644 --- a/product/ZSQLCatalog/interfaces/sql_expression.py +++ b/product/ZSQLCatalog/interfaces/sql_expression.py @@ -76,8 +76,11 @@ class ISQLExpression(Interface): The Query instance which called this constructor. table_alias_dict (dict, key: string, value: string) Table alias dict as returned by ColumnMap.getTableAliasDict() . - order_by_list (list of strings) - List of result ordering, pre-rendered. + order_by_list (list of 3-tuples) + Result ordering. + - column (rendered) + - direction (string or None) + - cast (string or None) order_by_dict (dict, key: string, value: string) Column rendering replacement specific to order_by. group_by_list (list of strings) diff --git a/product/ZSQLCatalog/tests/testSQLCatalog.py b/product/ZSQLCatalog/tests/testSQLCatalog.py index 1127492b06..4e4e148ca7 100644 --- a/product/ZSQLCatalog/tests/testSQLCatalog.py +++ b/product/ZSQLCatalog/tests/testSQLCatalog.py @@ -583,7 +583,23 @@ class TestSQLCatalog(unittest.TestCase): # order_by_list on fulltext column, resulting "ORDER BY" must be non-empty. sql_expression = self.asSQLExpression({'fulltext': 'foo', 'order_by_list': [('fulltext', ), ]}) - self.assertNotEqual(sql_expression.getOrderByExpression(), '') + order_by_expression = sql_expression.getOrderByExpression() + self.assertNotEqual(order_by_expression, '') + # ... and must sort by relevance + self.assertTrue('MATCH' in order_by_expression, order_by_expression) + # ordering on fulltext column with sort order specified must preserve + # sorting by relevance. + for direction in ('ASC', 'DESC'): + sql_expression = self.asSQLExpression({'fulltext': 'foo', + 'order_by_list': [('fulltext', direction), ]}) + order_by_expression = sql_expression.getOrderByExpression() + self.assertTrue('MATCH' in order_by_expression, (order_by_expression, direction)) + # Providing a None cast should work too + for direction in ('ASC', 'DESC'): + sql_expression = self.asSQLExpression({'fulltext': 'foo', + 'order_by_list': [('fulltext', direction, None), ]}) + order_by_expression = sql_expression.getOrderByExpression() + self.assertTrue('MATCH' in order_by_expression, (order_by_expression, direction)) ##return catalog(title=Query(title='a', operator='not')) #return catalog(title={'query': 'a', 'operator': 'not'}) -- 2.30.9