diff --git a/product/ZSQLCatalog/ColumnMap.py b/product/ZSQLCatalog/ColumnMap.py index f7259569861fc209e2507f09fa5aa073a3a591d6..78cd0226279cf917e59ed9d249d4a7f1dc53eb56 100644 --- a/product/ZSQLCatalog/ColumnMap.py +++ b/product/ZSQLCatalog/ColumnMap.py @@ -82,7 +82,6 @@ class ColumnMap(object): # Entries: column name self.column_ignore_set = set() self.join_table_set = set() - self.ignore_table_join_set = set() self.straight_join_table_list = [] self.left_join_table_list = [] self.join_query_list = [] @@ -500,19 +499,6 @@ class ColumnMap(object): self.resolveColumn('uid', catalog_table) self.join_table_set.add((group, table_name)) - def getIgnoreingTableAliasList(self): - return [self.getTableAlias(table_name, group=group) - for (group, table_name) in self.ignore_table_join_set] - - @profiler_decorator - def ignoreTableJoin(self, table_name, group=DEFAULT_GROUP_ID): - """ - Add a table, which is already or will be joined in anywhere, - to be ignored to join. - This values will be referred by EntireQuery. - """ - self.ignore_table_join_set.add((group, table_name)) - def getJoinTableAliasList(self): return [self.getTableAlias(table_name, group=group) for (group, table_name) in self.join_table_set] diff --git a/product/ZSQLCatalog/Query/EntireQuery.py b/product/ZSQLCatalog/Query/EntireQuery.py index 276a93484c26e539ce0ddd3650264a043f3c7714..1174af8ab634f4c95b472a27a83e05bea7e6baee 100644 --- a/product/ZSQLCatalog/Query/EntireQuery.py +++ b/product/ZSQLCatalog/Query/EntireQuery.py @@ -174,8 +174,7 @@ class EntireQuery(object): select_dict=self.final_select_dict, limit=self.limit, where_expression_operator='and', - sql_expression_list=self.sql_expression_list, - ignoreing_table_alias_list=column_map.getIgnoreingTableAliasList()) + sql_expression_list=self.sql_expression_list) verifyClass(IEntireQuery, EntireQuery) diff --git a/product/ZSQLCatalog/Query/SubCatalogQuery.py b/product/ZSQLCatalog/Query/SubCatalogQuery.py deleted file mode 100644 index 3935f6fcac5bf3c80b2322f6db321f3ccabc070a..0000000000000000000000000000000000000000 --- a/product/ZSQLCatalog/Query/SubCatalogQuery.py +++ /dev/null @@ -1,83 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002-2006 Nexedi SARL and Contributors. All Rights Reserved. -# Copyright (c) 2007-2009 Nexedi SA and Contributors. All Rights Reserved. -# Jean-Paul Smets-Solanes <jp@nexedi.com> -# MURAOKA Yusuke <yusuke@nexedi.com> -# -# WARNING: This program as such is intended to be used by professional -# programmers who take the whole responsability of assessing all potential -# consequences resulting from its eventual inadequacies and bugs -# End users who are looking for a ready-to-use solution with commercial -# garantees and support are strongly adviced to contract a Free Software -# Service Company -# -# This program is Free Software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -############################################################################## - -from Query import Query -from Products.ZSQLCatalog.SQLExpression import SQLExpression -from SQLQuery import SQLQuery -from Products.ZSQLCatalog.interfaces.query import IQuery -from zope.interface.verify import verifyClass -from Products.ZSQLCatalog.SQLCatalog import profiler_decorator - -class SubCatalogQuery(Query): - """ - A Query do out child query of the Query to sub query and - relate to that in SQL. - """ - - method_id = 'z_SubCatalogQuery' - - @profiler_decorator - def __init__(self, query): - self.query = query - - @profiler_decorator - def _asSearchTextExpression(self, sql_catalog, column=None): - if self.query: - return self.query._asSearchTextExpression(sql_catalog, column=column) - else: - return (False, '') - - @profiler_decorator - def asSQLExpression(self, sql_catalog, column_map, only_group_columns): - sql_expression = self.query.asSQLExpression(sql_catalog, - column_map, - only_group_columns) - method = getattr(sql_catalog, self.method_id, None) - # XXX: this if clause is exist for backward compatibility of testSQLCatalog. - if method: - where_expression = method(src__=1, **sql_expression.asSQLExpressionDict()) - else: - where_expression = None - return SQLExpression(self, - where_expression=where_expression, - sql_expression_list=(sql_expression,)) - - @profiler_decorator - def registerColumnMap(self, sql_catalog, column_map): - if self.query: - self.query.registerColumnMap(sql_catalog, column_map) - - @profiler_decorator - def setTableAliasList(self, table_alias_list): - if self.query: - self.query.setTableAliasList(table_alias_list) - - def __repr__(self): - return '<%s with %r>' % (self.__class__.__name__, self.query) diff --git a/product/ZSQLCatalog/SQLCatalog.py b/product/ZSQLCatalog/SQLCatalog.py index 5e04bd14a988cd9118cc4a59ec521614a470fd5f..33b53a1080cf4ebf33c427871daff4f5f67eda92 100644 --- a/product/ZSQLCatalog/SQLCatalog.py +++ b/product/ZSQLCatalog/SQLCatalog.py @@ -2253,7 +2253,6 @@ class Catalog(Folder, kw['where_expression'] = query['where_expression'] kw['sort_on'] = query['order_by_expression'] kw['from_table_list'] = query['from_table_list'] - kw['valid_from_table_list'] = query['valid_from_table_list'] kw['from_expression'] = query['from_expression'] kw['limit_expression'] = query['limit_expression'] kw['select_expression'] = query['select_expression'] diff --git a/product/ZSQLCatalog/SQLExpression.py b/product/ZSQLCatalog/SQLExpression.py index 9a1bfbc9385433c416c5bb58e7eeb59207e308ef..e1458caf50edcc2082589746a81af1ca63f99927 100644 --- a/product/ZSQLCatalog/SQLExpression.py +++ b/product/ZSQLCatalog/SQLExpression.py @@ -72,8 +72,7 @@ class SQLExpression(object): select_dict=None, limit=None, from_expression=None, - can_merge_select_dict=False, - ignoreing_table_alias_list=()): + can_merge_select_dict=False): if DEBUG: self.query = query self.table_alias_dict = defaultDict(table_alias_dict) @@ -109,7 +108,6 @@ class SQLExpression(object): if from_expression is not None: LOG('SQLExpression', 0, 'Providing a from_expression is deprecated.') self.from_expression = from_expression - self.ignoreing_table_alias_list = ignoreing_table_alias_list @profiler_decorator def getTableAliasDict(self): @@ -350,15 +348,9 @@ class SQLExpression(object): def asSQLExpressionDict(self): table_alias_dict = self.getTableAliasDict() from_table_list = [] - valid_from_table_list = [] - # method caching append = from_table_list.append - append_valid = valid_from_table_list.append for alias, table in table_alias_dict.iteritems(): - formatted_table_alias = (SQL_TABLE_FORMAT % (alias, ), SQL_TABLE_FORMAT % (table, )) - append(formatted_table_alias) - if alias not in self.ignoreing_table_alias_list: - append_valid(formatted_table_alias) + append((SQL_TABLE_FORMAT % (alias, ), SQL_TABLE_FORMAT % (table, ))) from_expression_dict = self.getFromExpression() if from_expression_dict is not None: from_expression = SQL_LIST_SEPARATOR.join( @@ -370,7 +362,6 @@ class SQLExpression(object): 'where_expression': self.getWhereExpression(), 'order_by_expression': self.getOrderByExpression(), 'from_table_list': from_table_list, - 'valid_from_table_list': valid_from_table_list, 'from_expression': from_expression, 'limit_expression': self.getLimitExpression(), 'select_expression': self.getSelectExpression(), diff --git a/product/ZSQLCatalog/SearchKey/RelatedKey.py b/product/ZSQLCatalog/SearchKey/RelatedKey.py index 1e5b49a25dc0a1b15ef3bbee3d8ce7e756b048d3..f2ecfb220f8c3ed1deea92048512e296a3f6785f 100644 --- a/product/ZSQLCatalog/SearchKey/RelatedKey.py +++ b/product/ZSQLCatalog/SearchKey/RelatedKey.py @@ -32,13 +32,14 @@ from SearchKey import SearchKey from Products.ZSQLCatalog.Query.Query import Query from Products.ZSQLCatalog.Query.RelatedQuery import RelatedQuery from Products.ZSQLCatalog.Query.SQLQuery import SQLQuery -from Products.ZSQLCatalog.Query.SubCatalogQuery import SubCatalogQuery from Products.ZSQLCatalog.SQLExpression import SQLExpression from Products.ZSQLCatalog.interfaces.search_key import IRelatedKey from zope.interface.verify import verifyClass from zope.interface import implements from Products.ZSQLCatalog.SQLCatalog import profiler_decorator +BACKWARD_COMPATIBILITY = True + class RelatedKey(SearchKey): """ This SearchKey handles searched on virtual columns of RelatedKey type. @@ -107,8 +108,8 @@ class RelatedKey(SearchKey): if isinstance(search_value, Query): search_value.setGroup(self.getColumn()) join_condition = search_value - return SubCatalogQuery(RelatedQuery(search_key=self, - join_condition=join_condition)) + return RelatedQuery(search_key=self, + join_condition=join_condition) @profiler_decorator def registerColumnMap(self, column_map, table_alias_list=None): @@ -125,7 +126,6 @@ class RelatedKey(SearchKey): table_name = self.table_list[table_position] local_group = column_map.registerRelatedKeyColumn(related_column, table_position, group) column_map.registerTable(table_name, group=local_group) - column_map.ignoreTableJoin(table_name, group=local_group) if table_alias_list is not None: # Pre-resolve all tables with given aliases given_name, given_alias = table_alias_list[table_position] @@ -133,7 +133,6 @@ class RelatedKey(SearchKey): column_map.resolveTable(table_name, given_alias, group=local_group) table_name = self.table_list[-1] column_map.registerTable(table_name, group=group) - column_map.ignoreTableJoin(table_name, group=group) if table_alias_list is not None: given_name, given_alias = table_alias_list[-1] assert table_name == given_name @@ -183,9 +182,36 @@ class RelatedKey(SearchKey): query_table=column_map.getCatalogTableAlias(), src__=1, **table_alias_dict) - return SQLExpression(self, - where_expression=rendered_related_key, - table_alias_dict=dict(table_alias_list)) + # Important: + # Former catalog separated join condition from related query. + # Example: + # ComplexQuery(Query(title="foo"), + # Query(subordination_title="bar") + # , operator='OR') + # Former catalog rendering (truncated where-expression): + # AND ((catalog.title LIKE '%foo%') OR + # (related_catalog_1.title LIKE '%bar%')) + # AND (related_catalog_1.uid = related_category_0.category_uid AND + # related_category_0.base_category_uid = 873 AND + # related_category_0.uid = catalog.uid) + # As you can see, the part of the query joining the tables is *out* of the + # OR expression, and therefor applies to the entire query. + # This was done on purpose, because doing otherwise gives very poor + # performances (on a simple data set, similar query can take *minutes* to + # execute - as of MySQL 5.x). + # Doing the same way as the former catalog is required for backward + # compatibility, until a decent alternative is found (like spliting the + # "OR" expression into ensemblist operations at query level). + # Note that doing this has a side effect on result list, as objects + # lacking a relation will never appear in the result. + if BACKWARD_COMPATIBILITY: + # XXX: Calling a private-ish method on column_map. + # This should never happen. It should be removed as soon as an + # alternative exists. + column_map._addJoinQuery(SQLQuery(rendered_related_key)) + return None + else: + return SQLExpression(self, where_expression=rendered_related_key) verifyClass(IRelatedKey, RelatedKey) diff --git a/product/ZSQLCatalog/tests/testSQLCatalog.py b/product/ZSQLCatalog/tests/testSQLCatalog.py index 329090bc76fa4c2a8d87ca560a347c89ca4a8359..b92136d190bebeff9896ef637ccf8ff13426dff1 100644 --- a/product/ZSQLCatalog/tests/testSQLCatalog.py +++ b/product/ZSQLCatalog/tests/testSQLCatalog.py @@ -34,7 +34,6 @@ from Products.ZSQLCatalog.SQLCatalog import ComplexQuery from Products.ZSQLCatalog.SQLCatalog import SimpleQuery from Products.ZSQLCatalog.Query.EntireQuery import EntireQuery from Products.ZSQLCatalog.Query.RelatedQuery import RelatedQuery -from Products.ZSQLCatalog.Query.SubCatalogQuery import SubCatalogQuery from DateTime import DateTime class ReferenceQuery: @@ -120,8 +119,6 @@ class ReferenceQuery: self.args[0] == other.query elif isinstance(other, RelatedQuery): return self == other.join_condition - elif isinstance(other, SubCatalogQuery): - return self == other.query elif isinstance(other, Query): return self == other.wrapped_query else: @@ -141,9 +138,8 @@ class RelatedReferenceQuery: self.subquery = reference_subquery def __eq__(self, other): - return isinstance(other, SubCatalogQuery) and \ - isinstance(other.query, RelatedQuery) and \ - self.subquery == other.query.join_condition + return isinstance(other, RelatedQuery) and \ + self.subquery == other.join_condition def __repr__(self): return '<%s %r>' % (self.__class__.__name__, self.subquery)