99 def rewrite_unstable_outer_join(select, solutions, unstable, schema): |
99 def rewrite_unstable_outer_join(select, solutions, unstable, schema): |
100 """if some optional variables are unstable, they should be selected in a |
100 """if some optional variables are unstable, they should be selected in a |
101 subquery. This function check this and rewrite the rql syntax tree if |
101 subquery. This function check this and rewrite the rql syntax tree if |
102 necessary (in place). Return a boolean telling if the tree has been modified |
102 necessary (in place). Return a boolean telling if the tree has been modified |
103 """ |
103 """ |
104 torewrite = set() |
|
105 modified = False |
104 modified = False |
106 for varname in tuple(unstable): |
105 for varname in tuple(unstable): |
107 var = select.defined_vars[varname] |
106 var = select.defined_vars[varname] |
108 if not var.stinfo.get('optrelations'): |
107 if not var.stinfo.get('optrelations'): |
109 continue |
108 continue |
110 modified = True |
|
111 unstable.remove(varname) |
109 unstable.remove(varname) |
112 torewrite.add(var) |
|
113 newselect = Select() |
110 newselect = Select() |
114 newselect.need_distinct = False |
111 newselect.need_distinct = False |
115 myunion = Union() |
112 myunion = Union() |
116 myunion.append(newselect) |
113 myunion.append(newselect) |
117 # extract aliases / selection |
114 # extract aliases / selection |
137 var = vref.variable |
134 var = vref.variable |
138 var.stinfo['relations'].add(newrel) |
135 var.stinfo['relations'].add(newrel) |
139 var.stinfo['rhsrelations'].add(newrel) |
136 var.stinfo['rhsrelations'].add(newrel) |
140 if rel.optional in ('right', 'both'): |
137 if rel.optional in ('right', 'both'): |
141 var.add_optional_relation(newrel) |
138 var.add_optional_relation(newrel) |
|
139 if not select.where and not modified: |
|
140 # oops, generated the same thing as the original select.... |
|
141 # restore original query, else we'll indefinitly loop |
|
142 for var, rel in towrap_rels: |
|
143 select.add_restriction(rel) |
|
144 continue |
|
145 modified = True |
142 # extract subquery solutions |
146 # extract subquery solutions |
143 mysolutions = [sol.copy() for sol in solutions] |
147 mysolutions = [sol.copy() for sol in solutions] |
144 cleanup_solutions(newselect, mysolutions) |
148 cleanup_solutions(newselect, mysolutions) |
145 newselect.set_possible_types(solutions) |
149 newselect.set_possible_types(mysolutions) |
146 # full sub-query |
150 # full sub-query |
147 aliases = [VariableRef(select.get_variable(avar.name, i)) |
151 aliases = [VariableRef(select.get_variable(avar.name, i)) |
148 for i, avar in enumerate(newselect.selection)] |
152 for i, avar in enumerate(newselect.selection)] |
149 select.add_subquery(SubQuery(aliases, myunion), check=False) |
153 select.add_subquery(SubQuery(aliases, myunion), check=False) |
150 return modified |
154 return modified |