#NEWLINE# def join( self , join , reuse = None ) : #NEWLINE# #INDENT# '\n        Returns an alias for the join in \'connection\', either reusing an\n        existing alias for that join or creating a new one. \'connection\' is a\n        tuple (lhs, table, join_cols) where \'lhs\' is either an existing\n        table alias or a table name. \'join_cols\' is a tuple of tuples containing\n        columns to join on ((l_id1, r_id1), (l_id2, r_id2)). The join corresponds\n        to the SQL equivalent of::\n\n            lhs.l_id1 = table.r_id1 AND lhs.l_id2 = table.r_id2\n\n        The \'reuse\' parameter can be either None which means all joins\n        (matching the connection) are reusable, or it can be a set containing\n        the aliases that can be reused.\n\n        A join is always created as LOUTER if the lhs alias is LOUTER to make\n        sure we do not generate chains like t1 LOUTER t2 INNER t3. All new\n        joins are created as LOUTER if nullable is True.\n\n        If \'nullable\' is True, the join can potentially involve NULL values and\n        is a candidate for promotion (to "left outer") when combining querysets.\n\n        The \'join_field\' is the field we are joining along (if any).\n        ' #NEWLINE# reuse = [ a for ( a , j ) in self . alias_map . items ( ) if ( ( ( reuse is None ) or ( a in reuse ) ) and ( j == join ) ) ] #NEWLINE# if reuse : #NEWLINE# #INDENT# self . ref_alias ( reuse [ 0 ] ) #NEWLINE# return reuse [ 0 ] #NEWLINE# #UNINDENT# ( alias , _ ) = self . table_alias ( join . table_name , create = True ) #NEWLINE# if join . join_type : #NEWLINE# #INDENT# if ( ( self . alias_map [ join . parent_alias ] . join_type == LOUTER ) or join . nullable ) : #NEWLINE# #INDENT# join_type = LOUTER #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# join_type = INNER #NEWLINE# #UNINDENT# join . join_type = join_type #NEWLINE# #UNINDENT# join . table_alias = alias #NEWLINE# self . alias_map [ alias ] = join #NEWLINE# return alias