Return an alias for the 'join', either reusing an existing alias for that join or creating a new one. 'join' is either a base_table_class or join_class. The 'reuse' parameter can be either None which means all joins are reusable, or it can be a set containin
(self, join, reuse=None)
| 1132 | return len([1 for count in self.alias_refcount.values() if count]) |
| 1133 | |
| 1134 | def join(self, join, reuse=None): |
| 1135 | class="st">""" |
| 1136 | Return an alias for the &class="cm">#x27;join', either reusing an existing alias for |
| 1137 | that join or creating a new one. &class="cm">#x27;join' is either a base_table_class or |
| 1138 | join_class. |
| 1139 | |
| 1140 | The &class="cm">#x27;reuse' parameter can be either None which means all joins are |
| 1141 | reusable, or it can be a set containing the aliases that can be reused. |
| 1142 | |
| 1143 | A join is always created as LOUTER if the lhs alias is LOUTER to make |
| 1144 | sure chains like t1 LOUTER t2 INNER t3 aren&class="cm">#x27;t generated. All new |
| 1145 | joins are created as LOUTER if the join is nullable. |
| 1146 | class="st">""" |
| 1147 | reuse_aliases = [ |
| 1148 | a |
| 1149 | for a, j in self.alias_map.items() |
| 1150 | if (reuse is None or a in reuse) and j == join |
| 1151 | ] |
| 1152 | if reuse_aliases: |
| 1153 | if join.table_alias in reuse_aliases: |
| 1154 | reuse_alias = join.table_alias |
| 1155 | else: |
| 1156 | class="cm"># Reuse the most recent alias of the joined table |
| 1157 | class="cm"># (a many-to-many relation may be joined multiple times). |
| 1158 | reuse_alias = reuse_aliases[-1] |
| 1159 | self.ref_alias(reuse_alias) |
| 1160 | return reuse_alias |
| 1161 | |
| 1162 | class="cm"># No reuse is possible, so we need a new alias. |
| 1163 | alias, _ = self.table_alias( |
| 1164 | join.table_name, create=True, filtered_relation=join.filtered_relation |
| 1165 | ) |
| 1166 | if join.join_type: |
| 1167 | if self.alias_map[join.parent_alias].join_type == LOUTER or join.nullable: |
| 1168 | join_type = LOUTER |
| 1169 | else: |
| 1170 | join_type = INNER |
| 1171 | join.join_type = join_type |
| 1172 | join.table_alias = alias |
| 1173 | self.alias_map[alias] = join |
| 1174 | if filtered_relation := join.filtered_relation: |
| 1175 | resolve_reuse = reuse |
| 1176 | if resolve_reuse is not None: |
| 1177 | resolve_reuse = set(reuse) | {alias} |
| 1178 | joins_len = len(self.alias_map) |
| 1179 | join.filtered_relation = filtered_relation.resolve_expression( |
| 1180 | self, reuse=resolve_reuse |
| 1181 | ) |
| 1182 | class="cm"># Some joins were during expression resolving, they must be present |
| 1183 | class="cm"># before the one we just added. |
| 1184 | if joins_len < len(self.alias_map): |
| 1185 | self.alias_map[alias] = self.alias_map.pop(alias) |
| 1186 | return alias |
| 1187 | |
| 1188 | def join_parent_model(self, opts, model, alias, seen): |
| 1189 | class="st">""" |