67
68
# LEFT JOIN "table_c" ON ("table_a"."table_a_col2" = "table_c"."table_c_col")
68
69
self.joins = joins or {}
70
def join(self, connection, outer=False):
71
"""Adds the JOIN specified in ``connection``.
73
:param connection: a tuple ``(lhs, table, lhs_col, col)``.
74
The join corresponds to the SQL equivalent of::
76
``(lhs.lhs_col = table.col)``
78
:param outer: True if a LEFT OUTER JOIN should be used, if possible
71
def _get_table_aliases(self):
72
from openerp.osv.expression import get_alias_from_query
73
return [get_alias_from_query(from_statement)[1] for from_statement in self.tables]
75
def _get_alias_mapping(self):
76
from openerp.osv.expression import get_alias_from_query
78
for table in self.tables:
79
alias, statement = get_alias_from_query(table)
80
mapping[statement] = table
83
def add_join(self, connection, implicit=True, outer=False):
84
""" Join a destination table to the current table.
86
:param implicit: False if the join is an explicit join. This allows
87
to fall back on the previous implementation of ``join`` before
88
OpenERP 7.0. It therefore adds the JOIN specified in ``connection``
89
If True, the join is done implicitely, by adding the table alias
90
in the from clause and the join condition in the where clause
91
of the query. Implicit joins do not handle outer parameter.
92
:param connection: a tuple ``(lhs, table, lhs_col, col, link)``.
93
The join corresponds to the SQL equivalent of::
95
(lhs.lhs_col = table.col)
97
Note that all connection elements are strings. Please refer to expression.py for more details about joins.
99
:param outer: True if a LEFT OUTER JOIN should be used, if possible
79
100
(no promotion to OUTER JOIN is supported in case the JOIN
80
was already present in the query, as for the moment
81
implicit INNER JOINs are only connected from NON-NULL
82
columns so it would not be correct (e.g. for
83
``_inherits`` or when a domain criterion explicitly
101
was already present in the query, as for the moment
102
implicit INNER JOINs are only connected from NON-NULL
103
columns so it would not be correct (e.g. for
104
``_inherits`` or when a domain criterion explicitly
86
(lhs, table, lhs_col, col) = connection
89
assert lhs in self.tables, "Left-hand-side table must already be part of the query!"
90
if table in self.tables:
91
# already joined, must ignore (promotion to outer and multiple joins not supported yet)
107
from openerp.osv.expression import generate_table_alias
108
(lhs, table, lhs_col, col, link) = connection
109
alias, alias_statement = generate_table_alias(lhs, [(table, link)])
112
if alias_statement not in self.tables:
113
self.tables.append(alias_statement)
114
condition = '("%s"."%s" = "%s"."%s")' % (lhs, lhs_col, alias, col)
115
self.where_clause.append(condition)
119
return alias, alias_statement
95
self.tables.append(table)
96
self.joins.setdefault(lhs, []).append((table, lhs_col, col, outer and 'LEFT JOIN' or 'JOIN'))
121
aliases = self._get_table_aliases()
122
assert lhs in aliases, "Left-hand-side table %s must already be part of the query tables %s!" % (lhs, str(self.tables))
123
if alias_statement in self.tables:
124
# already joined, must ignore (promotion to outer and multiple joins not supported yet)
128
self.tables.append(alias_statement)
129
self.joins.setdefault(lhs, []).append((alias, lhs_col, col, outer and 'LEFT JOIN' or 'JOIN'))
130
return alias, alias_statement
99
132
def get_sql(self):
100
"""Returns (query_from, query_where, query_params)"""
133
""" Returns (query_from, query_where, query_params). """
134
from openerp.osv.expression import get_alias_from_query
102
136
tables_to_process = list(self.tables)
137
alias_mapping = self._get_alias_mapping()
104
139
def add_joins_for_table(table, query_from):
105
for (dest_table, lhs_col, col, join) in self.joins.get(table,[]):
106
tables_to_process.remove(dest_table)
107
query_from += ' %s %s ON (%s."%s" = %s."%s")' % \
108
(join, dest_table, table, lhs_col, dest_table, col)
140
for (dest_table, lhs_col, col, join) in self.joins.get(table, []):
141
tables_to_process.remove(alias_mapping[dest_table])
142
query_from += ' %s %s ON ("%s"."%s" = "%s"."%s")' % \
143
(join, alias_mapping[dest_table], table, lhs_col, dest_table, col)
109
144
query_from = add_joins_for_table(dest_table, query_from)
110
145
return query_from
112
147
for table in tables_to_process:
113
148
query_from += table
114
if table in self.joins:
115
query_from = add_joins_for_table(table, query_from)
149
table_alias = get_alias_from_query(table)[1]
150
if table_alias in self.joins:
151
query_from = add_joins_for_table(table_alias, query_from)
116
152
query_from += ','
117
query_from = query_from[:-1] # drop last comma
118
return (query_from, " AND ".join(self.where_clause), self.where_clause_params)
153
query_from = query_from[:-1] # drop last comma
154
return query_from, " AND ".join(self.where_clause), self.where_clause_params
120
156
def __str__(self):
121
157
return '<osv.Query: "SELECT ... FROM %s WHERE %s" with params: %r>' % self.get_sql()
123
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
b'\\ No newline at end of file'
159
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: