Commit 1dc82392 authored by Vincent Pelletier's avatar Vincent Pelletier

Implement select expression merge in a column-name-independent way.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@26139 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent d9e879bd
...@@ -126,6 +126,7 @@ class MatchComparisonOperator(MonovaluedComparisonOperator): ...@@ -126,6 +126,7 @@ class MatchComparisonOperator(MonovaluedComparisonOperator):
select_dict=select_dict, select_dict=select_dict,
where_expression=match_string, where_expression=match_string,
order_by_dict=order_by_dict, order_by_dict=order_by_dict,
can_merge_select_dict=True,
) )
verifyClass(IOperator, MatchComparisonOperator) verifyClass(IOperator, MatchComparisonOperator)
......
...@@ -70,13 +70,15 @@ class SQLExpression(object): ...@@ -70,13 +70,15 @@ class SQLExpression(object):
sql_expression_list=(), sql_expression_list=(),
select_dict=None, select_dict=None,
limit=None, limit=None,
from_expression=None): from_expression=None,
can_merge_select_dict=False):
if DEBUG: if DEBUG:
self.query = query self.query = query
self.table_alias_dict = defaultDict(table_alias_dict) self.table_alias_dict = defaultDict(table_alias_dict)
self.order_by_list = list(order_by_list) self.order_by_list = list(order_by_list)
self.group_by_list = list(group_by_list) self.group_by_list = list(group_by_list)
self.order_by_dict = defaultDict(order_by_dict) self.order_by_dict = defaultDict(order_by_dict)
self.can_merge_select_dict = can_merge_select_dict
# Only one of (where_expression, where_expression_operator) must be given (never both) # Only one of (where_expression, where_expression_operator) must be given (never both)
assert None in (where_expression, where_expression_operator) assert None in (where_expression, where_expression_operator)
# Exactly one of (where_expression, where_expression_operator) must be given, except if sql_expression_list is given and contains exactly one entry # Exactly one of (where_expression, where_expression_operator) must be given, except if sql_expression_list is given and contains exactly one entry
...@@ -283,26 +285,28 @@ class SQLExpression(object): ...@@ -283,26 +285,28 @@ class SQLExpression(object):
""" """
return SQL_LIST_SEPARATOR.join(self.getGroupByset()) return SQL_LIST_SEPARATOR.join(self.getGroupByset())
@profiler_decorator def canMergeSelectDict(self):
def getSelectDict(self): return self.can_merge_select_dict
"""
Returns a dict:
key: alias (string)
value: column (string) or None
If there are nested SQLExpression, it aggregates their mappings and @profiler_decorator
checks that they don't alias different columns with the same name. If def _getSelectDict(self):
they do, it raises a ValueError.
"""
result = self.select_dict.copy() result = self.select_dict.copy()
mergeable_set = set()
if self.canMergeSelectDict():
mergeable_set.update(result)
for sql_expression in self.sql_expression_list: for sql_expression in self.sql_expression_list:
for alias, column in sql_expression.getSelectDict().iteritems(): can_merge_sql_expression = sql_expression.canMergeSelectDict()
sql_expression_select_dict, sql_expression_mergeable_set = \
sql_expression._getSelectDict()
mergeable_set.update(sql_expression_mergeable_set)
for alias, column in sql_expression_select_dict.iteritems():
existing_value = result.get(alias) existing_value = result.get(alias)
if existing_value not in (None, column): if existing_value not in (None, column):
if alias == 'SearchableText': if can_merge_sql_expression and alias in mergeable_set:
# Custom conflict resolution # Custom conflict resolution
column = '%s + %s' % (existing_value, column) column = '%s + %s' % (existing_value, column)
else: else:
import pdb; pdb.set_trace()
message = '%r is a known alias for column %r, can\'t alias it now to column %r' % (alias, existing_value, column) message = '%r is a known alias for column %r, can\'t alias it now to column %r' % (alias, existing_value, column)
if DEBUG: if DEBUG:
message = message + '. I was created by %r, and I am working on %r (%r) out of [%s]' % ( message = message + '. I was created by %r, and I am working on %r (%r) out of [%s]' % (
...@@ -311,8 +315,23 @@ class SQLExpression(object): ...@@ -311,8 +315,23 @@ class SQLExpression(object):
sql_expression.query, sql_expression.query,
', '.join('%r (%r)' % (x, x.query) for x in self.sql_expression_list)) ', '.join('%r (%r)' % (x, x.query) for x in self.sql_expression_list))
raise ValueError, message raise ValueError, message
result[alias] = column result[alias] = (column, can_merge_sql_expression)
return result if can_merge_sql_expression:
mergeable_set.add(alias)
return result, mergeable_set
@profiler_decorator
def getSelectDict(self):
"""
Returns a dict:
key: alias (string)
value: column (string) or None
If there are nested SQLExpression, it aggregates their mappings and
checks that they don't alias different columns with the same name. If
they do, it raises a ValueError.
"""
return self._getSelectDict()[0]
@profiler_decorator @profiler_decorator
def getSelectExpression(self): def getSelectExpression(self):
......
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