def join(self, connection, always_create=False, exclusions=(),
            promote=False, outer_if_first=False, nullable=False, reuse=None):
        """
        Returns an alias for the join in 'connection', either reusing an
        existing alias for that join or creating a new one. 'connection' is a
        tuple (lhs, table, lhs_col, col) where 'lhs' is either an existing
        table alias or a table name. The join correspods to the SQL equivalent
        of::

            lhs.lhs_col = table.col

        If 'always_create' is True and 'reuse' is None, a new alias is always
        created, regardless of whether one already exists or not. If
        'always_create' is True and 'reuse' is a set, an alias in 'reuse' that
        matches the connection will be returned, if possible.  If
        'always_create' is False, the first existing alias that matches the
        'connection' is returned, if any. Otherwise a new join is created.

        If 'exclusions' is specified, it is something satisfying the container
        protocol ("foo in exclusions" must work) and specifies a list of
        aliases that should not be returned, even if they satisfy the join.

        If 'promote' is True, the join type for the alias will be LOUTER (if
        the alias previously existed, the join type will be promoted from INNER
        to LOUTER, if necessary).

        If 'outer_if_first' is True and a new join is created, it will have the
        LOUTER join type. This is used when joining certain types of querysets
        and Q-objects together.

        A join is always created as LOUTER if the lhs alias is LOUTER to make
        sure we do not generate chains like a LOUTER b INNER c.

        If 'nullable' is True, the join can potentially involve NULL values and
        is a candidate for promotion (to "left outer") when combining querysets.
        """
        lhs, table, lhs_col, col = connection
        if lhs in self.alias_map:
            lhs_table = self.alias_map[lhs].table_name
        else:
            lhs_table = lhs

        if reuse and always_create and table in self.table_map:
            # Convert the 'reuse' to case to be "exclude everything but the
            # reusable set, minus exclusions, for this table".
            exclusions = set(self.table_map[table]).difference(reuse).union(set(exclusions))
            always_create = False
        t_ident = (lhs_table, table, lhs_col, col)
        if not always_create:
            for alias in self.join_map.get(t_ident, ()):
                if alias not in exclusions:
                    if lhs_table and not self.alias_refcount[self.alias_map[alias].lhs_alias]:
                        # The LHS of this join tuple is no longer part of the
                        # query, so skip this possibility.
                        continue
                    if self.alias_map[alias].lhs_alias != lhs:
                        continue
                    self.ref_alias(alias)
                    if promote or (lhs and self.alias_map[lhs].join_type == self.LOUTER):
                        self.promote_joins([alias])
                    return alias

        # No reuse is possible, so we need a new alias.
        alias, _ = self.table_alias(table, True)
        if not lhs:
            # Not all tables need to be joined to anything. No join type
            # means the later columns are ignored.
            join_type = None
        elif (promote or outer_if_first
              or self.alias_map[lhs].join_type == self.LOUTER):
            # We need to use LOUTER join if asked by promote or outer_if_first,
            # or if the LHS table is left-joined in the query. Adding inner join
            # to an existing outer join effectively cancels the effect of the
            # outer join.
            join_type = self.LOUTER
        else:
            join_type = self.INNER
        join = JoinInfo(table, alias, join_type, lhs, lhs_col, col, nullable)
        self.alias_map[alias] = join
        if t_ident in self.join_map:
            self.join_map[t_ident] += (alias,)
        else:
            self.join_map[t_ident] = (alias,)
        return alias
dataset/ETHPy150Open AppScale/appscale/AppServer/lib/django-1.5/django/db/models/sql/query.py/Query.join/original