Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
erp5
Commits
9cdf7a81
Commit
9cdf7a81
authored
Dec 14, 2011
by
Leonardo Rochael Almeida
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'catalog_join'
parents
07cbd374
d2a9088a
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
904 additions
and
115 deletions
+904
-115
product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_grand_parent.xml
...rtal_catalog/erp5_mysql_innodb/z_related_grand_parent.xml
+7
-6
product/ERP5Catalog/tests/testERP5Catalog.py
product/ERP5Catalog/tests/testERP5Catalog.py
+194
-13
product/ERP5Type/Core/Predicate.py
product/ERP5Type/Core/Predicate.py
+3
-0
product/ZSQLCatalog/ColumnMap.py
product/ZSQLCatalog/ColumnMap.py
+217
-22
product/ZSQLCatalog/Query/EntireQuery.py
product/ZSQLCatalog/Query/EntireQuery.py
+65
-24
product/ZSQLCatalog/SQLCatalog.py
product/ZSQLCatalog/SQLCatalog.py
+10
-0
product/ZSQLCatalog/SQLExpression.py
product/ZSQLCatalog/SQLExpression.py
+16
-11
product/ZSQLCatalog/SearchKey/RelatedKey.py
product/ZSQLCatalog/SearchKey/RelatedKey.py
+107
-23
product/ZSQLCatalog/TableDefinition.py
product/ZSQLCatalog/TableDefinition.py
+283
-0
product/ZSQLCatalog/interfaces/column_map.py
product/ZSQLCatalog/interfaces/column_map.py
+0
-15
product/ZSQLCatalog/tests/testSQLCatalog.py
product/ZSQLCatalog/tests/testSQLCatalog.py
+2
-1
No files found.
product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/z_related_grand_parent.xml
View file @
9cdf7a81
...
...
@@ -14,8 +14,10 @@
</item>
<item>
<key>
<string>
arguments_src
</string>
</key>
<value>
<string>
table_0\n
table_1
</string>
</value>
<value>
<string>
table_0\r\n
table_1\r\n
RELATED_QUERY_SEPARATOR=" AND "\r\n
query_table="catalog"
</string>
</value>
</item>
<item>
<key>
<string>
cache_time_
</string>
</key>
...
...
@@ -55,10 +57,9 @@ table_1</string> </value>
<key>
<string>
src
</string>
</key>
<value>
<string
encoding=
"cdata"
>
<![CDATA[
<dtml-var table_0>
.uid = catalog.parent_uid\n
AND
<dtml-var
table_1
>
.uid =
<dtml-var
table_0
>
.parent_uid\n
\n
<dtml-var table_1>
.uid =
<dtml-var
table_0
>
.parent_uid\n
<dtml-var
RELATED_QUERY_SEPARATOR
>
\n
<dtml-var
table_0
>
.uid =
<dtml-var
query_table
>
.parent_uid
]]>
</string>
</value>
</item>
...
...
product/ERP5Catalog/tests/testERP5Catalog.py
View file @
9cdf7a81
This diff is collapsed.
Click to expand it.
product/ERP5Type/Core/Predicate.py
View file @
9cdf7a81
...
...
@@ -329,7 +329,10 @@ class Predicate(XMLObject):
catalog_kw
[
'where_expression'
]
=
SQLQuery
(
sql_text
)
else
:
catalog_kw
[
'where_expression'
]
=
''
# force implicit join
catalog_kw
[
'implicit_join'
]
=
True
sql_query
=
portal_catalog
.
buildSQLQuery
(
**
catalog_kw
)
# XXX from_table_list is None most of the time after the explicit_join work
for
alias
,
table
in
sql_query
[
'from_table_list'
]:
if
from_table_dict
.
has_key
(
alias
):
raise
KeyError
,
"The same table is used twice for an identity criterion and for a membership criterion"
...
...
product/ZSQLCatalog/ColumnMap.py
View file @
9cdf7a81
This diff is collapsed.
Click to expand it.
product/ZSQLCatalog/Query/EntireQuery.py
View file @
9cdf7a81
...
...
@@ -28,6 +28,7 @@
#
##############################################################################
import
warnings
from
Products.ZSQLCatalog.SQLExpression
import
SQLExpression
from
Products.ZSQLCatalog.ColumnMap
import
ColumnMap
from
zLOG
import
LOG
...
...
@@ -35,6 +36,7 @@ from Products.ZSQLCatalog.interfaces.entire_query import IEntireQuery
from
zope.interface.verify
import
verifyClass
from
zope.interface
import
implements
from
Products.ZSQLCatalog.SQLCatalog
import
profiler_decorator
from
Products.ZSQLCatalog.TableDefinition
import
LegacyTableDefinition
def
defaultDict
(
value
):
if
value
is
None
:
...
...
@@ -54,19 +56,28 @@ class EntireQuery(object):
column_map
=
None
@
profiler_decorator
def
__init__
(
self
,
query
,
order_by_list
=
(),
group_by_list
=
(),
select_dict
=
None
,
limit
=
None
,
catalog_table_name
=
None
,
extra_column_list
=
(),
from_expression
=
None
,
order_by_override_list
=
None
):
def
__init__
(
self
,
query
,
order_by_list
=
(),
group_by_list
=
(),
select_dict
=
None
,
left_join_list
=
(),
limit
=
None
,
catalog_table_name
=
None
,
extra_column_list
=
(),
from_expression
=
None
,
order_by_override_list
=
None
,
implicit_join
=
False
):
self
.
query
=
query
self
.
order_by_list
=
list
(
order_by_list
)
self
.
order_by_override_set
=
frozenset
(
order_by_override_list
)
self
.
group_by_list
=
list
(
group_by_list
)
self
.
select_dict
=
defaultDict
(
select_dict
)
self
.
left_join_list
=
left_join_list
self
.
limit
=
limit
self
.
catalog_table_name
=
catalog_table_name
self
.
extra_column_list
=
list
(
extra_column_list
)
self
.
from_expression
=
from_expression
self
.
implicit_join
=
implicit_join
def
asSearchTextExpression
(
self
,
sql_catalog
):
return
self
.
query
.
asSearchTextExpression
(
sql_catalog
)
...
...
@@ -78,7 +89,12 @@ class EntireQuery(object):
# XXX: should we provide a way to register column map as a separate
# method or do it here ?
# Column Map was not built yet, do it.
self
.
column_map
=
column_map
=
ColumnMap
(
catalog_table_name
=
self
.
catalog_table_name
)
column_map
=
ColumnMap
(
catalog_table_name
=
self
.
catalog_table_name
,
table_override_map
=
self
.
from_expression
,
left_join_list
=
self
.
left_join_list
,
implicit_join
=
self
.
implicit_join
,
)
self
.
column_map
=
column_map
for
extra_column
in
self
.
extra_column_list
:
table
,
column
=
extra_column
.
replace
(
'`'
,
''
).
split
(
'.'
)
if
table
!=
self
.
catalog_table_name
:
...
...
@@ -145,30 +161,55 @@ class EntireQuery(object):
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
)]
# generate join expression based on column_map.getJoinTableAliasList
sql_expression_list
=
[
self
.
query
.
asSQLExpression
(
sql_catalog
,
column_map
,
only_group_columns
)]
append
=
sql_expression_list
.
append
for
join_query
in
column_map
.
iterJoinQueryList
():
append
(
join_query
.
asSQLExpression
(
sql_catalog
,
column_map
,
only_group_columns
))
join_table_list
=
column_map
.
getJoinTableAliasList
()
if
len
(
join_table_list
):
# XXX: Is there any special rule to observe when joining tables ?
# Maybe we could check which column is a primary key instead of
# hardcoding "uid".
where_pattern
=
'`%s`.`uid` = `%%s`.`uid`'
%
\
(
column_map
.
getCatalogTableAlias
(),
)
# XXX: It would cleaner from completeness point of view to use column
# mapper to render column, but makes code much more complex to just do
# a simple text rendering. If there is any reason why we should have
# those column in the mapper, then we should use the clean way.
append
(
SQLExpression
(
self
,
where_expression
=
' AND '
.
join
(
where_pattern
%
(
x
,
)
for
x
in
join_table_list
)))
append
(
join_query
.
asSQLExpression
(
sql_catalog
,
column_map
,
only_group_columns
))
# generate join expression based on column_map.getJoinTableAliasList
# XXX: This is now done by ColumnMap to its table_definition,
# during build()
#
# join_table_list = column_map.getJoinTableAliasList()
# if len(join_table_list):
# # XXX: Is there any special rule to observe when joining tables ?
# # Maybe we could check which column is a primary key instead of
# # hardcoding "uid".
# where_pattern = '`%s`.`uid` = `%%s`.`uid`' % \
# (column_map.getCatalogTableAlias(), )
# # XXX: It would cleaner from completeness point of view to use column
# # mapper to render column, but makes code much more complex to just do
# # a simple text rendering. If there is any reason why we should have
# # those column in the mapper, then we should use the clean way.
# append(SQLExpression(self, where_expression=' AND '.join(
# where_pattern % (x, ) for x in join_table_list
# )))
# BBB self.from_expression forces use of implicit inner join
table_alias_dict
=
column_map
.
getTableAliasDict
()
if
self
.
from_expression
:
warnings
.
warn
(
"Providing a 'from_expression' is deprecated."
,
DeprecationWarning
)
# XXX: perhaps move this code to ColumnMap?
legacy_from_expression
=
self
.
from_expression
from_expression
=
LegacyTableDefinition
(
legacy_from_expression
,
table_alias_dict
)
table_alias_dict
=
None
else
:
from_expression
=
column_map
.
getTableDefinition
()
assert
((
from_expression
is
None
)
!=
(
table_alias_dict
is
None
)),
(
"Got both a from_expression "
"and a table_alias_dict"
)
self
.
sql_expression_list
=
sql_expression_list
# TODO: wrap the table_alias_dict above into a TableDefinition as well,
# even without a legacy_table_definition.
return
SQLExpression
(
self
,
table_alias_dict
=
column_map
.
getTableAliasDict
()
,
from_expression
=
self
.
from_expression
,
table_alias_dict
=
table_alias_dict
,
from_expression
=
from_expression
,
order_by_list
=
self
.
order_by_list
,
group_by_list
=
self
.
group_by_list
,
select_dict
=
self
.
final_select_dict
,
...
...
product/ZSQLCatalog/SQLCatalog.py
View file @
9cdf7a81
...
...
@@ -2291,6 +2291,13 @@ class Catalog(Folder,
select_dict
=
None
elif
isinstance
(
select_dict
,
(
list
,
tuple
)):
select_dict
=
dict
([(
x
,
None
)
for
x
in
select_dict
])
# Handle left_join_list
left_join_list
=
kw
.
pop
(
'left_join_list'
,
())
# Handle implicit_join. It's True by default, as there's a lot of code
# in BT5s and elsewhere that calls buildSQLQuery() expecting implicit
# join. self._queryResults() defaults it to False for those using
# catalog.searchResults(...) or catalog(...) directly.
implicit_join
=
kw
.
pop
(
'implicit_join'
,
True
)
# Handle order_by_list
order_by_list
=
kw
.
pop
(
'order_by_list'
,
None
)
sort_on
=
kw
.
pop
(
'sort_on'
,
None
)
...
...
@@ -2328,6 +2335,8 @@ class Catalog(Folder,
order_by_override_list
=
order_by_override_list
,
group_by_list
=
group_by_list
,
select_dict
=
select_dict
,
left_join_list
=
left_join_list
,
implicit_join
=
implicit_join
,
limit
=
limit
,
catalog_table_name
=
query_table
,
extra_column_list
=
extra_column_list
,
...
...
@@ -2413,6 +2422,7 @@ class Catalog(Folder,
""" Returns a list of brains from a set of constraints on variables """
if
build_sql_query_method
is
None
:
build_sql_query_method
=
self
.
buildSQLQuery
kw
.
setdefault
(
'implicit_join'
,
False
)
query
=
build_sql_query_method
(
REQUEST
=
REQUEST
,
**
kw
)
# XXX: decide if this should be made normal
ENFORCE_SEPARATION
=
True
...
...
product/ZSQLCatalog/SQLExpression.py
View file @
9cdf7a81
...
...
@@ -166,7 +166,7 @@ class SQLExpression(object):
@
profiler_decorator
def
getFromExpression
(
self
):
"""
Returns a
string.
Returns a
TableDefinition stored in one of the from_expressions or None
If there are nested SQLExpression, it checks that they either don't
define any from_expression or the exact same from_expression. Otherwise,
...
...
@@ -175,7 +175,7 @@ class SQLExpression(object):
result
=
self
.
from_expression
for
sql_expression
in
self
.
sql_expression_list
:
from_expression
=
sql_expression
.
getFromExpression
()
if
None
not
in
(
result
,
from_expression
):
if
from_expression
not
in
(
result
,
None
):
message
=
'I don
\
'
t know how to merge from_expressions'
if
DEBUG
:
message
=
message
+
'. I was created by %r, and I am working on %r (%r) out of [%s]'
%
(
...
...
@@ -385,20 +385,25 @@ class SQLExpression(object):
SQL_SELECT_ALIAS_FORMAT
%
(
column
,
alias
)
for
alias
,
column
in
self
.
getSelectDict
().
iteritems
())
@
profiler_decorator
def
asSQLExpressionDict
(
self
):
def
getFromTableList
(
self
):
table_alias_dict
=
self
.
getTableAliasDict
()
if
not
table_alias_dict
:
return
None
from_table_list
=
[]
append
=
from_table_list
.
append
for
alias
,
table
in
table_alias_dict
.
iteritems
():
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
(
from_expression_dict
.
get
(
alias
,
'`%s` AS `%s`'
%
(
table
,
alias
))
for
alias
,
table
in
table_alias_dict
.
iteritems
())
else
:
from_expression
=
None
return
from_table_list
@
profiler_decorator
def
asSQLExpressionDict
(
self
):
from_expression
=
self
.
getFromExpression
()
from_table_list
=
self
.
getFromTableList
()
assert
None
in
(
from_expression
,
from_table_list
),
(
"Cannot return both a from_expression "
"and a from_table_list"
)
if
from_expression
is
not
None
:
from_expression
=
from_expression
.
render
()
return
{
'where_expression'
:
self
.
getWhereExpression
(),
'order_by_expression'
:
self
.
getOrderByExpression
(),
...
...
product/ZSQLCatalog/SearchKey/RelatedKey.py
View file @
9cdf7a81
...
...
@@ -37,12 +37,29 @@ 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
from
Products.ZSQLCatalog.TableDefinition
import
TableAlias
,
InnerJoin
,
LeftJoin
from
logging
import
getLogger
log
=
getLogger
(
__name__
)
BACKWARD_COMPATIBILITY
=
True
RELATED_QUERY_SEPARATOR
=
"
\
n
AND -- related query separator
\
n
"
RELATED_KEY_MISMATCH_MESSAGE
=
"
\
A rendered related key must contain the same number of querying
\
conditions as the tables it relates, properly separated by
\
RELATED_QUERY_SEPARATOR.
\
n
\
Offending related key: %r, for column %r, table_alias_list: %r,
\
rendered_related_key:
\
n
%s"
RELATED_KEY_ALIASED_MESSAGE
=
"
\
Support for explicit joins of aliased related keys is not yet implemented.
\
Offending related key: %r, for column %r, table_alias_list: %r"
class
RelatedKey
(
SearchKey
):
"""
This SearchKey handles searche
d
on virtual columns of RelatedKey type.
This SearchKey handles searche
s
on virtual columns of RelatedKey type.
It generates joins required by the virtual column to reach the actual
column to compare, plus a regular query on that column if needed.
"""
...
...
@@ -115,13 +132,23 @@ class RelatedKey(SearchKey):
def
registerColumnMap
(
self
,
column_map
,
table_alias_list
=
None
):
related_column
=
self
.
getColumn
()
group
=
column_map
.
registerRelatedKey
(
related_column
,
self
.
real_column
)
# Each table except last one must be registered to their own group, so that
# the same table can be used multiple time (and aliased multiple times)
# in the same related key. The last one must be register to related key
# "main" group (ie, the value of the "group" variable) to be the same as
# the ta ble used in join_condition.
# Each table except last one must be registered to their own
# group, so that the same table can be used multiple times (and
# aliased multiple times) in the same related key. The last one
# must be registered to the related key "main" group (ie, the
# value of the "group" variable) to be the same as the table used
# in join_condition.
if
table_alias_list
is
not
None
:
assert
len
(
self
.
table_list
)
==
len
(
table_alias_list
)
# XXX-Leo: remove the rest of this 'if' branch after making sure
# that ColumnMap.addRelatedKeyJoin() can handle collapsing
# chains of inner-joins that are subsets of one another based on
# having the same aliases:
msg
=
RELATED_KEY_ALIASED_MESSAGE
%
(
self
.
related_key_id
,
self
.
column
,
table_alias_list
,)
log
.
warning
(
msg
+
"
\
n
\
n
Forcing implicit join..."
)
column_map
.
implicit_join
=
True
for
table_position
in
xrange
(
len
(
self
.
table_list
)
-
1
):
table_name
=
self
.
table_list
[
table_position
]
local_group
=
column_map
.
registerRelatedKeyColumn
(
related_column
,
table_position
,
group
)
...
...
@@ -145,6 +172,23 @@ class RelatedKey(SearchKey):
column_map
.
registerCatalog
()
return
group
def
stitchJoinDefinition
(
self
,
table_alias_list
,
join_query_list
,
column_map
):
alias
,
table
=
table_alias_list
[
-
1
]
right
=
column_map
.
makeTableAliasDefinition
(
table
,
alias
)
if
not
join_query_list
:
# nothing to do, just return the table alias
assert
len
(
table_alias_list
)
==
1
return
right
else
:
# create an InnerJoin of the last element of the alias list with
# a chain of InnerJoins of the rest of the list conditioned on
# the the last element of the join_query_list
left
=
self
.
stitchJoinDefinition
(
table_alias_list
[:
-
1
],
join_query_list
[:
-
1
],
column_map
)
condition
=
join_query_list
[
-
1
]
return
InnerJoin
(
left
,
right
,
condition
)
@
profiler_decorator
def
buildSQLExpression
(
self
,
sql_catalog
,
column_map
,
only_group_columns
,
group
):
"""
...
...
@@ -170,20 +214,26 @@ class RelatedKey(SearchKey):
table_alias_list
=
[(
getTableAlias
(
related_table
,
group
=
getRelatedKeyGroup
(
index
,
group
)),
related_table
)
for
(
index
,
related_table
)
in
enumerate
(
related_table_list
)]
# table alias for destination table
table_alias_list
.
append
((
getTableAlias
(
destination_table
,
group
=
group
),
destination_table
))
table_alias_list
.
append
((
getTableAlias
(
destination_table
,
group
=
group
),
destination_table
))
# map aliases to use in ZSQLMethod.
table_alias_dict
=
dict
((
'table_%s'
%
(
index
,
),
table_alias
[
0
])
for
(
index
,
table_alias
)
in
enumerate
(
table_alias_list
))
table_alias_dict
=
dict
((
'table_%s'
%
(
index
,
),
table_alias
)
for
(
index
,
(
table_alias
,
table_name
))
in
enumerate
(
table_alias_list
))
assert
len
(
table_alias_list
)
==
len
(
table_alias_dict
)
query_table
=
column_map
.
getCatalogTableAlias
()
rendered_related_key
=
related_key
(
query_table
=
column_map
.
getCatalogTableAlias
(),
query_table
=
query_table
,
RELATED_QUERY_SEPARATOR
=
RELATED_QUERY_SEPARATOR
,
src__
=
1
,
**
table_alias_dict
)
join_condition_list
=
rendered_related_key
.
split
(
RELATED_QUERY_SEPARATOR
)
# Important:
#
Former catalog separated join condition from
related query.
#
Previously the catalog separated join condition from the
related query.
# Example:
# ComplexQuery(Query(title="foo"),
# Query(subordination_title="bar")
...
...
@@ -199,19 +249,53 @@ class RelatedKey(SearchKey):
# 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
#
# Because of this, we never return an SQLExpression here, as it
# would mix join definition with column condition in the body of
# the WHERE clause. Instead we explicitly define a Join to the
# catalog. The ColumnMap defines whether this is an Inner Join or
# a Left Outer Join. Notice that if an Inner Join is decided,
# objects lacking a relationship will never appear in the result.
if
len
(
join_condition_list
)
==
len
(
table_alias_list
):
# Good! we got a compatible method that splits the join
# conditions according to the related tables.
#
# Add a join on this related key, based on the chain of
# inner-joins of the related key tables.
query_table_join_condition
=
join_condition_list
.
pop
()
right_side
=
self
.
stitchJoinDefinition
(
table_alias_list
,
join_condition_list
,
column_map
)
column_map
.
addRelatedKeyJoin
(
self
.
column
,
right_side
=
right_side
,
condition
=
query_table_join_condition
)
else
:
return
SQLExpression
(
self
,
where_expression
=
rendered_related_key
)
# Method did not render the related key condition with the
# appropriate separators so we could split it
# XXX: Can we try to parse rendered_related_key to select which
# conditions go with each table? Maybe we could still use
# explicit joins this way...
msg
=
RELATED_KEY_MISMATCH_MESSAGE
%
(
self
.
related_key_id
,
self
.
column
,
table_alias_list
,
rendered_related_key
)
if
BACKWARD_COMPATIBILITY
:
# BBB: remove this branch of the condition, and the above
# constant, when all zsql_methods have been adapted to return
# the join queries properly separated by the
# RELATED_QUERY_SEPARATOR.
# The rendered related key doesn't have the separators for each
# joined table, so we revert to doing implicit inner joins:
log
.
warning
(
msg
+
"
\
n
\
n
Adding an Implicit Join Condition..."
)
column_map
.
_addJoinQueryForColumn
(
self
.
column
,
SQLQuery
(
rendered_related_key
))
else
:
raise
RuntimeError
(
msg
)
return
None
verifyClass
(
IRelatedKey
,
RelatedKey
)
product/ZSQLCatalog/TableDefinition.py
0 → 100644
View file @
9cdf7a81
This diff is collapsed.
Click to expand it.
product/ZSQLCatalog/interfaces/column_map.py
View file @
9cdf7a81
...
...
@@ -284,18 +284,3 @@ class IColumnMap(Interface):
Return a copy of the table alias list for tables requiring a join with
catalog table.
"""
def
getStraightJoinTableList
():
"""
Returns the list of tables used this search and which
need to be joined with the main table using explicit
indices.
"""
def
getLeftJoinTableList
():
"""
Returns the list of tables used this search and which
need to be LEFT joined with the main table using explicit
indices.
"""
product/ZSQLCatalog/tests/testSQLCatalog.py
View file @
9cdf7a81
...
...
@@ -202,6 +202,7 @@ class DummyCatalog(SQLCatalog):
assert
'query_table'
in
kw
assert
'table_0'
in
kw
assert
'table_1'
in
kw
assert
'AND'
in
kw
.
pop
(
'RELATED_QUERY_SEPARATOR'
)
assert
len
(
kw
)
==
4
return
'%(table_0)s.uid = %(query_table)s.uid AND %(table_0)s.other_uid = %(table_1)s'
%
kw
...
...
@@ -629,7 +630,7 @@ class TestSQLCatalog(unittest.TestCase):
select_dict
=
sql_expression
.
getSelectDict
()
self
.
assertTrue
(
'ambiguous_mapping'
in
select_dict
,
select_dict
)
self
.
assertTrue
(
'bar'
in
select_dict
[
'ambiguous_mapping'
],
select_dict
[
'ambiguous_mapping'
])
# Doted alias: table name must get stripped. This is required to have an
# Dot
t
ed alias: table name must get stripped. This is required to have an
# upgrade path from old ZSQLCatalog versions where pre-mapped columns were
# used in their select_expression. This must only happen in the
# "{column: None}" form, as otherwise it's the user explicitely asking for
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment