<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def join(self, source, op='LEFT JOIN', on=''):
 """ Join `source`. 'SELECT c1, c2 FROM main JOIN sub ON main.id = sub.id' It is possible to pass another `SQLConstructor` as a source. SELECT c1, c2, d1 FROM main JOIN ( SELECT d1, d2 FROM sub WHERE (d1 = ?) ) ON main.id = sub.id WHERE (c1 = ?) `params` is set appropriately to include parameters for joined source: ['abc', 111] is called. Therefore, calling `subsc.add_<predicate>` does not effect `sc`. :type source: str or SQLConstructor :arg source: table :type op: str :arg op: operation (e.g., 'JOIN') :type on: str :arg on: on clause. `source` ("right" source) can be referred using `{r}` formatting field. """

        if isinstance(source, SQLConstructor):
            (sql, params, _) = source.compile()
            self.join_params.extend(params)
            jsrc = '( {0} )'.format(sql)
            if source.table_alias:
                jsrc += ' AS ' + source.table_alias
                on = on.format(r=source.table_alias)
        else:
            jsrc = source
            on = on.format(r=source)
        constraint = 'ON {0}'.format(on) if on else ''
        self.join_source = ' '.join([self.join_source, op, jsrc, constraint])