1236 # here |
1236 # here |
1237 return '' |
1237 return '' |
1238 |
1238 |
1239 |
1239 |
1240 def _visit_outer_join_inlined_relation(self, relation, rschema): |
1240 def _visit_outer_join_inlined_relation(self, relation, rschema): |
1241 leftvar, leftconst, rightvar, rightconst = relation_info(relation) |
1241 lhsvar, lhsconst, rhsvar, rhsconst = relation_info(relation) |
1242 assert not (leftconst and rightconst), "doesn't make sense" |
1242 assert not (lhsconst and rhsconst), "doesn't make sense" |
1243 if relation.optional != 'right': |
|
1244 leftvar, rightvar = rightvar, leftvar |
|
1245 leftconst, rightconst = rightconst, leftconst |
|
1246 outertype = 'FULL' if relation.optional == 'both' else 'LEFT' |
|
1247 leftalias = self._var_table(leftvar) |
|
1248 attr = 'eid' if relation.r_type == 'identity' else relation.r_type |
1243 attr = 'eid' if relation.r_type == 'identity' else relation.r_type |
1249 lhs, rhs = relation.get_variable_parts() |
1244 lhsalias = self._var_table(lhsvar) |
|
1245 rhsalias = rhsvar and self._var_table(rhsvar) |
1250 try: |
1246 try: |
1251 lhssql = self._varmap['%s.%s' % (lhs.name, attr)] |
1247 lhssql = self._varmap['%s.%s' % (lhsvar.name, attr)] |
1252 except KeyError: |
1248 except KeyError: |
1253 lhssql = '%s.%s%s' % (self._var_table(lhs.variable), SQL_PREFIX, attr) |
1249 if lhsalias is None: |
1254 if rightvar is not None: |
1250 lhssql = lhsconst.accept(self) |
1255 rightalias = self._var_table(rightvar) |
1251 else: |
1256 if rightalias is None: |
1252 lhssql = '%s.%s%s' % (lhsalias, SQL_PREFIX, attr) |
1257 if rightconst is not None: |
1253 condition = '%s=%s' % (lhssql, (rhsconst or rhsvar).accept(self)) |
1258 # inlined relation with invariant as rhs |
1254 # this is not a typo, rhs optional variable means lhs outer join and vice-versa |
1259 condition = '%s=%s' % (lhssql, rightconst.accept(self)) |
1255 if relation.optional == 'left': |
1260 if relation.r_type != 'identity': |
1256 lhsvar, rhsvar = rhsvar, lhsvar |
1261 condition = '(%s OR %s IS NULL)' % (condition, lhssql) |
1257 lhsconst, rhsconst = rhsconst, lhsconst |
1262 if not leftvar.stinfo.get('optrelations'): |
1258 lhsalias, rhsalias = rhsalias, lhsalias |
1263 return condition |
1259 outertype = 'LEFT' |
1264 self._state.add_outer_join_condition(leftalias, condition) |
1260 elif relation.optional == 'both': |
1265 return |
1261 outertype = 'FULL' |
1266 if leftalias is None: |
1262 else: |
1267 leftalias = leftvar._q_sql.split('.', 1)[0] |
1263 outertype = 'LEFT' |
1268 self._state.replace_tables_by_outer_join( |
1264 if rhsalias is None: |
1269 leftalias, rightalias, outertype, '%s=%s' % (lhssql, rhs.accept(self))) |
1265 if rhsconst is not None: |
|
1266 # inlined relation with invariant as rhs |
|
1267 if relation.r_type != 'identity': |
|
1268 condition = '(%s OR %s IS NULL)' % (condition, lhssql) |
|
1269 if not lhsvar.stinfo.get('optrelations'): |
|
1270 return condition |
|
1271 self._state.add_outer_join_condition(lhsalias, condition) |
|
1272 return |
|
1273 if lhsalias is None: |
|
1274 if lhsconst is not None and not rhsvar.stinfo.get('optrelations'): |
|
1275 return condition |
|
1276 lhsalias = lhsvar._q_sql.split('.', 1)[0] |
|
1277 if lhsalias == rhsalias: |
|
1278 self._state.add_outer_join_condition(lhsalias, condition) |
|
1279 else: |
|
1280 self._state.replace_tables_by_outer_join( |
|
1281 lhsalias, rhsalias, outertype, condition) |
1270 return '' |
1282 return '' |
1271 |
1283 |
1272 def _visit_var_attr_relation(self, relation, rhs_vars): |
1284 def _visit_var_attr_relation(self, relation, rhs_vars): |
1273 """visit an attribute relation with variable(s) in the RHS |
1285 """visit an attribute relation with variable(s) in the RHS |
1274 |
1286 |