engine: remove use of cross join (#38691)

It prevented reporting of NULL values.
This commit is contained in:
Benjamin Dauvergne 2020-01-06 22:07:05 +01:00
parent 8f204362a4
commit 16b60621d4
4 changed files with 1468 additions and 166577 deletions

View File

@ -371,7 +371,6 @@ class EngineCube(object):
where = []
group_by = []
order_by = []
join_conditions = []
for dimension_name, values in filters:
dimension = self.dimensions[dimension_name]
@ -381,7 +380,7 @@ class EngineCube(object):
if dimension.filter_needs_join and dimension.join:
joins.update(dimension.join)
if dimension.filter_in_join:
join_conditions.append(condition)
assert False, 'filter in join is not supported anymore'
else:
where.append(condition)
@ -403,8 +402,7 @@ class EngineCube(object):
sql = 'SELECT ' + ', '.join(projections)
table_expression = ' %s' % self.cube.fact_table
if joins:
table_expression = self.build_table_expression(
joins, self.fact_table, other_conditions=join_conditions)
table_expression = self.build_table_expression(joins, self.fact_table)
sql += ' FROM %s' % table_expression
where_conditions = 'true'
if where:
@ -450,7 +448,14 @@ class EngineCube(object):
))
yield cells
def build_table_expression(self, joins, table_name, other_conditions=None):
JOIN_KINDS = {
'inner': 'INNER JOIN',
'left': 'LEFT OUTER JOIN',
'right': 'RIGHT OUTER JOIN',
'full': 'FULL OUTER JOIN',
}
def build_table_expression(self, joins, table_name):
'''Recursively build the table expression from the join tree,
starting from the fact table'''
@ -461,45 +466,37 @@ class EngineCube(object):
master_table = join.master_table or self.fact_table
join_tree.setdefault(master_table, {}).setdefault(join.kind, {})[join.name] = join
def build_table_expression_helper(join_tree, table_name, alias=None, top=True, other_conditions=None):
def build_table_expression_helper(join_tree, table_name, alias=None, top=True):
contain_joins = False
sql = table_name
if alias:
sql += ' AS %s' % quote(alias)
add_paren = False
for kind in ['left', 'inner', 'right', 'full']:
joins = join_tree.get(alias or table_name, {}).get(kind)
if not joins:
continue
add_paren = True
join_kinds = {
'inner': 'INNER JOIN',
'left': 'LEFT OUTER JOIN',
'right': 'RIGHT OUTER JOIN',
'full': 'FULL OUTER JOIN',
}
sql += ' %s ' % join_kinds[kind]
sub_joins = []
conditions = []
if other_conditions:
conditions = other_conditions
other_conditions = None
for join_name, join in joins.iteritems():
sub_joins.append(
build_table_expression_helper(join_tree, join.table, alias=join.name, top=False))
conditions.append('%s.%s = %s.%s' % (
contain_joins = True
sql += ' %s ' % self.JOIN_KINDS[kind]
sql += ' ' + build_table_expression_helper(join_tree, join.table, alias=join.name, top=False)
condition = '%s.%s = %s.%s' % (
alias or table_name,
join.master.split('.')[-1],
quote(join.name), join.detail))
sub_join = ' CROSS JOIN '.join(sub_joins)
if len(sub_joins) > 1:
sub_join = '(%s)' % sub_join
sql += sub_join
sql += ' ON %s' % ' AND '.join(conditions)
if not top and add_paren:
quote(join.name),
join.detail)
sql += ' ON ' + condition
# if the table expression contains joins and is not the full table
# expression but used in another join, it must be quoted with
# parenthesis
if not top and contain_joins:
sql = '(%s)' % sql
return sql
return build_table_expression_helper(
join_tree, table_name, other_conditions=other_conditions)
return build_table_expression_helper(join_tree, table_name)
class Engine(object):

View File

@ -328,7 +328,7 @@ class Join(Base):
'kind': join_kind,
}
kind = 'right'
kind = 'full'
@property
def master_table(self):

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff