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