From 1dc823925d4fab0d3aab80a0eb2ec72831e40b3b Mon Sep 17 00:00:00 2001 From: Vincent Pelletier <vincent@nexedi.com> Date: Tue, 24 Mar 2009 11:41:17 +0000 Subject: [PATCH] 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 --- .../Operator/ComparisonOperator.py | 1 + product/ZSQLCatalog/SQLExpression.py | 49 +++++++++++++------ 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/product/ZSQLCatalog/Operator/ComparisonOperator.py b/product/ZSQLCatalog/Operator/ComparisonOperator.py index 8755bcd36f..8f5236b81d 100644 --- a/product/ZSQLCatalog/Operator/ComparisonOperator.py +++ b/product/ZSQLCatalog/Operator/ComparisonOperator.py @@ -126,6 +126,7 @@ class MatchComparisonOperator(MonovaluedComparisonOperator): select_dict=select_dict, where_expression=match_string, order_by_dict=order_by_dict, + can_merge_select_dict=True, ) verifyClass(IOperator, MatchComparisonOperator) diff --git a/product/ZSQLCatalog/SQLExpression.py b/product/ZSQLCatalog/SQLExpression.py index 9fda41d4da..4164c9c0f1 100644 --- a/product/ZSQLCatalog/SQLExpression.py +++ b/product/ZSQLCatalog/SQLExpression.py @@ -70,13 +70,15 @@ class SQLExpression(object): sql_expression_list=(), select_dict=None, limit=None, - from_expression=None): + from_expression=None, + can_merge_select_dict=False): if DEBUG: self.query = query self.table_alias_dict = defaultDict(table_alias_dict) self.order_by_list = list(order_by_list) self.group_by_list = list(group_by_list) 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) 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 @@ -283,26 +285,28 @@ class SQLExpression(object): """ return SQL_LIST_SEPARATOR.join(self.getGroupByset()) - @profiler_decorator - def getSelectDict(self): - """ - Returns a dict: - key: alias (string) - value: column (string) or None + def canMergeSelectDict(self): + return self.can_merge_select_dict - 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. - """ + @profiler_decorator + def _getSelectDict(self): result = self.select_dict.copy() + mergeable_set = set() + if self.canMergeSelectDict(): + mergeable_set.update(result) 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) if existing_value not in (None, column): - if alias == 'SearchableText': + if can_merge_sql_expression and alias in mergeable_set: # Custom conflict resolution column = '%s + %s' % (existing_value, column) 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) if DEBUG: message = message + '. I was created by %r, and I am working on %r (%r) out of [%s]' % ( @@ -311,8 +315,23 @@ class SQLExpression(object): sql_expression.query, ', '.join('%r (%r)' % (x, x.query) for x in self.sql_expression_list)) raise ValueError, message - result[alias] = column - return result + result[alias] = (column, can_merge_sql_expression) + 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 def getSelectExpression(self): -- 2.30.9