def join(self, *props, **kwargs):
    'Create a SQL JOIN against this :class:`.Query` object\'s criterion\n        and apply generatively, returning the newly resulting :class:`.Query`.\n\n        **Simple Relationship Joins**\n\n        Consider a mapping between two classes ``User`` and ``Address``,\n        with a relationship ``User.addresses`` representing a collection\n        of ``Address`` objects associated with each ``User``.   The most\n        common usage of :meth:`~.Query.join` is to create a JOIN along this\n        relationship, using the ``User.addresses`` attribute as an indicator\n        for how this should occur::\n\n            q = session.query(User).join(User.addresses)\n\n        Where above, the call to :meth:`~.Query.join` along ``User.addresses``\n        will result in SQL equivalent to::\n\n            SELECT user.* FROM user JOIN address ON user.id = address.user_id\n\n        In the above example we refer to ``User.addresses`` as passed to\n        :meth:`~.Query.join` as the *on clause*, that is, it indicates\n        how the "ON" portion of the JOIN should be constructed.  For a\n        single-entity query such as the one above (i.e. we start by selecting\n        only from ``User`` and nothing else), the relationship can also be\n        specified by its string name::\n\n            q = session.query(User).join("addresses")\n\n        :meth:`~.Query.join` can also accommodate multiple\n        "on clause" arguments to produce a chain of joins, such as below\n        where a join across four related entities is constructed::\n\n            q = session.query(User).join("orders", "items", "keywords")\n\n        The above would be shorthand for three separate calls to\n        :meth:`~.Query.join`, each using an explicit attribute to indicate\n        the source entity::\n\n            q = session.query(User).\\\n                    join(User.orders).\\\n                    join(Order.items).\\\n                    join(Item.keywords)\n\n        **Joins to a Target Entity or Selectable**\n\n        A second form of :meth:`~.Query.join` allows any mapped entity\n        or core selectable construct as a target.   In this usage,\n        :meth:`~.Query.join` will attempt\n        to create a JOIN along the natural foreign key relationship between\n        two entities::\n\n            q = session.query(User).join(Address)\n\n        The above calling form of :meth:`~.Query.join` will raise an error if\n        either there are no foreign keys between the two entities, or if\n        there are multiple foreign key linkages between them.   In the\n        above calling form, :meth:`~.Query.join` is called upon to\n        create the "on clause" automatically for us.  The target can\n        be any mapped entity or selectable, such as a :class:`.Table`::\n\n            q = session.query(User).join(addresses_table)\n\n        **Joins to a Target with an ON Clause**\n\n        The third calling form allows both the target entity as well\n        as the ON clause to be passed explicitly.   Suppose for\n        example we wanted to join to ``Address`` twice, using\n        an alias the second time.  We use :func:`~sqlalchemy.orm.aliased`\n        to create a distinct alias of ``Address``, and join\n        to it using the ``target, onclause`` form, so that the\n        alias can be specified explicitly as the target along with\n        the relationship to instruct how the ON clause should proceed::\n\n            a_alias = aliased(Address)\n\n            q = session.query(User).\\\n                    join(User.addresses).\\\n                    join(a_alias, User.addresses).\\\n                    filter(Address.email_address==\'example@example.com\').\\\n                    filter(a_alias.email_address==\'example@example.com\')\n\n        Where above, the generated SQL would be similar to::\n\n            SELECT user.* FROM user\n                JOIN address ON user.id = address.user_id\n                JOIN address AS address_1 ON user.id=address_1.user_id\n                WHERE address.email_address = :email_address_1\n                AND address_1.email_address = :email_address_2\n\n        The two-argument calling form of :meth:`~.Query.join`\n        also allows us to construct arbitrary joins with SQL-oriented\n        "on clause" expressions, not relying upon configured relationships\n        at all.  Any SQL expression can be passed as the ON clause\n        when using the two-argument form, which should refer to the target\n        entity in some way as well as an applicable source entity::\n\n            q = session.query(User).join(Address, User.id==Address.user_id)\n\n        .. versionchanged:: 0.7\n            In SQLAlchemy 0.6 and earlier, the two argument form of\n            :meth:`~.Query.join` requires the usage of a tuple:\n            ``query(User).join((Address, User.id==Address.user_id))``\\ .\n            This calling form is accepted in 0.7 and further, though\n            is not necessary unless multiple join conditions are passed to\n            a single :meth:`~.Query.join` call, which itself is also not\n            generally necessary as it is now equivalent to multiple\n            calls (this wasn\'t always the case).\n\n        **Advanced Join Targeting and Adaption**\n\n        There is a lot of flexibility in what the "target" can be when using\n        :meth:`~.Query.join`.   As noted previously, it also accepts\n        :class:`.Table` constructs and other selectables such as\n        :func:`.alias` and :func:`.select` constructs, with either the one\n        or two-argument forms::\n\n            addresses_q = select([Address.user_id]).\\\n                        where(Address.email_address.endswith("@bar.com")).\\\n                        alias()\n\n            q = session.query(User).\\\n                        join(addresses_q, addresses_q.c.user_id==User.id)\n\n        :meth:`~.Query.join` also features the ability to *adapt* a\n        :meth:`~sqlalchemy.orm.relationship` -driven ON clause to the target\n        selectable. Below we construct a JOIN from ``User`` to a subquery\n        against ``Address``, allowing the relationship denoted by\n        ``User.addresses`` to *adapt* itself to the altered target::\n\n            address_subq = session.query(Address).\\\n                            filter(Address.email_address == \'example@example.com\').\\\n                            subquery()\n\n            q = session.query(User).join(address_subq, User.addresses)\n\n        Producing SQL similar to::\n\n            SELECT user.* FROM user\n                JOIN (\n                    SELECT address.id AS id,\n                            address.user_id AS user_id,\n                            address.email_address AS email_address\n                    FROM address\n                    WHERE address.email_address = :email_address_1\n                ) AS anon_1 ON user.id = anon_1.user_id\n\n        The above form allows one to fall back onto an explicit ON\n        clause at any time::\n\n            q = session.query(User).\\\n                    join(address_subq, User.id==address_subq.c.user_id)\n\n        **Controlling what to Join From**\n\n        While :meth:`~.Query.join` exclusively deals with the "right"\n        side of the JOIN, we can also control the "left" side, in those\n        cases where it\'s needed, using :meth:`~.Query.select_from`.\n        Below we construct a query against ``Address`` but can still\n        make usage of ``User.addresses`` as our ON clause by instructing\n        the :class:`.Query` to select first from the ``User``\n        entity::\n\n            q = session.query(Address).select_from(User).\\\n                            join(User.addresses).\\\n                            filter(User.name == \'ed\')\n\n        Which will produce SQL similar to::\n\n            SELECT address.* FROM user\n                JOIN address ON user.id=address.user_id\n                WHERE user.name = :name_1\n\n        **Constructing Aliases Anonymously**\n\n        :meth:`~.Query.join` can construct anonymous aliases\n        using the ``aliased=True`` flag.  This feature is useful\n        when a query is being joined algorithmically, such as\n        when querying self-referentially to an arbitrary depth::\n\n            q = session.query(Node).\\\n                    join("children", "children", aliased=True)\n\n        When ``aliased=True`` is used, the actual "alias" construct\n        is not explicitly available.  To work with it, methods such as\n        :meth:`.Query.filter` will adapt the incoming entity to\n        the last join point::\n\n            q = session.query(Node).\\\n                    join("children", "children", aliased=True).\\\n                    filter(Node.name == \'grandchild 1\')\n\n        When using automatic aliasing, the ``from_joinpoint=True``\n        argument can allow a multi-node join to be broken into\n        multiple calls to :meth:`~.Query.join`, so that\n        each path along the way can be further filtered::\n\n            q = session.query(Node).\\\n                    join("children", aliased=True).\\\n                    filter(Node.name=\'child 1\').\\\n                    join("children", aliased=True, from_joinpoint=True).\\\n                    filter(Node.name == \'grandchild 1\')\n\n        The filtering aliases above can then be reset back to the\n        original ``Node`` entity using :meth:`~.Query.reset_joinpoint`::\n\n            q = session.query(Node).\\\n                    join("children", "children", aliased=True).\\\n                    filter(Node.name == \'grandchild 1\').\\\n                    reset_joinpoint().\\\n                    filter(Node.name == \'parent 1)\n\n        For an example of ``aliased=True``, see the distribution\n        example :ref:`examples_xmlpersistence` which illustrates\n        an XPath-like query system using algorithmic joins.\n\n        :param \\*props: A collection of one or more join conditions,\n         each consisting of a relationship-bound attribute or string\n         relationship name representing an "on clause", or a single\n         target entity, or a tuple in the form of ``(target, onclause)``.\n         A special two-argument calling form of the form ``target, onclause``\n         is also accepted.\n        :param aliased=False: If True, indicate that the JOIN target should be\n         anonymously aliased.  Subsequent calls to :meth:`~.Query.filter`\n         and similar will adapt the incoming criterion to the target\n         alias, until :meth:`~.Query.reset_joinpoint` is called.\n        :param isouter=False: If True, the join used will be a left outer join,\n         just as if the :meth:`.Query.outerjoin` method were called.  This\n         flag is here to maintain consistency with the same flag as accepted\n         by :meth:`.FromClause.join` and other Core constructs.\n\n\n         .. versionadded:: 1.0.0\n\n        :param from_joinpoint=False: When using ``aliased=True``, a setting\n         of True here will cause the join to be from the most recent\n         joined target, rather than starting back from the original\n         FROM clauses of the query.\n\n        .. seealso::\n\n            :ref:`ormtutorial_joins` in the ORM tutorial.\n\n            :ref:`inheritance_toplevel` for details on how\n            :meth:`~.Query.join` is used for inheritance relationships.\n\n            :func:`.orm.join` - a standalone ORM-level join function,\n            used internally by :meth:`.Query.join`, which in previous\n            SQLAlchemy versions was the primary ORM-level joining interface.\n\n        '
    (aliased, from_joinpoint, isouter) = (kwargs.pop('aliased', False), kwargs.pop('from_joinpoint', False), kwargs.pop('isouter', False))
    if kwargs:
        raise TypeError(('unknown arguments: %s' % ','.join(kwargs.keys)))
    isouter = isouter
    return self._join(props, outerjoin=isouter, create_aliases=aliased, from_joinpoint=from_joinpoint)
Create a SQL JOIN against this :class:`.Query` object's criterion
and apply generatively, returning the newly resulting :class:`.Query`.

**Simple Relationship Joins**

Consider a mapping between two classes ``User`` and ``Address``,
with a relationship ``User.addresses`` representing a collection
of ``Address`` objects associated with each ``User``.   The most
common usage of :meth:`~.Query.join` is to create a JOIN along this
relationship, using the ``User.addresses`` attribute as an indicator
for how this should occur::

    q = session.query(User).join(User.addresses)

Where above, the call to :meth:`~.Query.join` along ``User.addresses``
will result in SQL equivalent to::

    SELECT user.* FROM user JOIN address ON user.id = address.user_id

In the above example we refer to ``User.addresses`` as passed to
:meth:`~.Query.join` as the *on clause*, that is, it indicates
how the "ON" portion of the JOIN should be constructed.  For a
single-entity query such as the one above (i.e. we start by selecting
only from ``User`` and nothing else), the relationship can also be
specified by its string name::

    q = session.query(User).join("addresses")

:meth:`~.Query.join` can also accommodate multiple
"on clause" arguments to produce a chain of joins, such as below
where a join across four related entities is constructed::

    q = session.query(User).join("orders", "items", "keywords")

The above would be shorthand for three separate calls to
:meth:`~.Query.join`, each using an explicit attribute to indicate
the source entity::

    q = session.query(User).\
            join(User.orders).\
            join(Order.items).\
            join(Item.keywords)

**Joins to a Target Entity or Selectable**

A second form of :meth:`~.Query.join` allows any mapped entity
or core selectable construct as a target.   In this usage,
:meth:`~.Query.join` will attempt
to create a JOIN along the natural foreign key relationship between
two entities::

    q = session.query(User).join(Address)

The above calling form of :meth:`~.Query.join` will raise an error if
either there are no foreign keys between the two entities, or if
there are multiple foreign key linkages between them.   In the
above calling form, :meth:`~.Query.join` is called upon to
create the "on clause" automatically for us.  The target can
be any mapped entity or selectable, such as a :class:`.Table`::

    q = session.query(User).join(addresses_table)

**Joins to a Target with an ON Clause**

The third calling form allows both the target entity as well
as the ON clause to be passed explicitly.   Suppose for
example we wanted to join to ``Address`` twice, using
an alias the second time.  We use :func:`~sqlalchemy.orm.aliased`
to create a distinct alias of ``Address``, and join
to it using the ``target, onclause`` form, so that the
alias can be specified explicitly as the target along with
the relationship to instruct how the ON clause should proceed::

    a_alias = aliased(Address)

    q = session.query(User).\
            join(User.addresses).\
            join(a_alias, User.addresses).\
            filter(Address.email_address=='example@example.com').\
            filter(a_alias.email_address=='example@example.com')

Where above, the generated SQL would be similar to::

    SELECT user.* FROM user
        JOIN address ON user.id = address.user_id
        JOIN address AS address_1 ON user.id=address_1.user_id
        WHERE address.email_address = :email_address_1
        AND address_1.email_address = :email_address_2

The two-argument calling form of :meth:`~.Query.join`
also allows us to construct arbitrary joins with SQL-oriented
"on clause" expressions, not relying upon configured relationships
at all.  Any SQL expression can be passed as the ON clause
when using the two-argument form, which should refer to the target
entity in some way as well as an applicable source entity::

    q = session.query(User).join(Address, User.id==Address.user_id)

.. versionchanged:: 0.7
    In SQLAlchemy 0.6 and earlier, the two argument form of
    :meth:`~.Query.join` requires the usage of a tuple:
    ``query(User).join((Address, User.id==Address.user_id))``\ .
    This calling form is accepted in 0.7 and further, though
    is not necessary unless multiple join conditions are passed to
    a single :meth:`~.Query.join` call, which itself is also not
    generally necessary as it is now equivalent to multiple
    calls (this wasn't always the case).

**Advanced Join Targeting and Adaption**

There is a lot of flexibility in what the "target" can be when using
:meth:`~.Query.join`.   As noted previously, it also accepts
:class:`.Table` constructs and other selectables such as
:func:`.alias` and :func:`.select` constructs, with either the one
or two-argument forms::

    addresses_q = select([Address.user_id]).\
                where(Address.email_address.endswith("@bar.com")).\
                alias()

    q = session.query(User).\
                join(addresses_q, addresses_q.c.user_id==User.id)

:meth:`~.Query.join` also features the ability to *adapt* a
:meth:`~sqlalchemy.orm.relationship` -driven ON clause to the target
selectable. Below we construct a JOIN from ``User`` to a subquery
against ``Address``, allowing the relationship denoted by
``User.addresses`` to *adapt* itself to the altered target::

    address_subq = session.query(Address).\
                    filter(Address.email_address == 'example@example.com').\
                    subquery()

    q = session.query(User).join(address_subq, User.addresses)

Producing SQL similar to::

    SELECT user.* FROM user
        JOIN (
            SELECT address.id AS id,
                    address.user_id AS user_id,
                    address.email_address AS email_address
            FROM address
            WHERE address.email_address = :email_address_1
        ) AS anon_1 ON user.id = anon_1.user_id

The above form allows one to fall back onto an explicit ON
clause at any time::

    q = session.query(User).\
            join(address_subq, User.id==address_subq.c.user_id)

**Controlling what to Join From**

While :meth:`~.Query.join` exclusively deals with the "right"
side of the JOIN, we can also control the "left" side, in those
cases where it's needed, using :meth:`~.Query.select_from`.
Below we construct a query against ``Address`` but can still
make usage of ``User.addresses`` as our ON clause by instructing
the :class:`.Query` to select first from the ``User``
entity::

    q = session.query(Address).select_from(User).\
                    join(User.addresses).\
                    filter(User.name == 'ed')

Which will produce SQL similar to::

    SELECT address.* FROM user
        JOIN address ON user.id=address.user_id
        WHERE user.name = :name_1

**Constructing Aliases Anonymously**

:meth:`~.Query.join` can construct anonymous aliases
using the ``aliased=True`` flag.  This feature is useful
when a query is being joined algorithmically, such as
when querying self-referentially to an arbitrary depth::

    q = session.query(Node).\
            join("children", "children", aliased=True)

When ``aliased=True`` is used, the actual "alias" construct
is not explicitly available.  To work with it, methods such as
:meth:`.Query.filter` will adapt the incoming entity to
the last join point::

    q = session.query(Node).\
            join("children", "children", aliased=True).\
            filter(Node.name == 'grandchild 1')

When using automatic aliasing, the ``from_joinpoint=True``
argument can allow a multi-node join to be broken into
multiple calls to :meth:`~.Query.join`, so that
each path along the way can be further filtered::

    q = session.query(Node).\
            join("children", aliased=True).\
            filter(Node.name='child 1').\
            join("children", aliased=True, from_joinpoint=True).\
            filter(Node.name == 'grandchild 1')

The filtering aliases above can then be reset back to the
original ``Node`` entity using :meth:`~.Query.reset_joinpoint`::

    q = session.query(Node).\
            join("children", "children", aliased=True).\
            filter(Node.name == 'grandchild 1').\
            reset_joinpoint().\
            filter(Node.name == 'parent 1)

For an example of ``aliased=True``, see the distribution
example :ref:`examples_xmlpersistence` which illustrates
an XPath-like query system using algorithmic joins.

:param \*props: A collection of one or more join conditions,
 each consisting of a relationship-bound attribute or string
 relationship name representing an "on clause", or a single
 target entity, or a tuple in the form of ``(target, onclause)``.
 A special two-argument calling form of the form ``target, onclause``
 is also accepted.
:param aliased=False: If True, indicate that the JOIN target should be
 anonymously aliased.  Subsequent calls to :meth:`~.Query.filter`
 and similar will adapt the incoming criterion to the target
 alias, until :meth:`~.Query.reset_joinpoint` is called.
:param isouter=False: If True, the join used will be a left outer join,
 just as if the :meth:`.Query.outerjoin` method were called.  This
 flag is here to maintain consistency with the same flag as accepted
 by :meth:`.FromClause.join` and other Core constructs.


 .. versionadded:: 1.0.0

:param from_joinpoint=False: When using ``aliased=True``, a setting
 of True here will cause the join to be from the most recent
 joined target, rather than starting back from the original
 FROM clauses of the query.

.. seealso::

    :ref:`ormtutorial_joins` in the ORM tutorial.

    :ref:`inheritance_toplevel` for details on how
    :meth:`~.Query.join` is used for inheritance relationships.

    :func:`.orm.join` - a standalone ORM-level join function,
    used internally by :meth:`.Query.join`, which in previous
    SQLAlchemy versions was the primary ORM-level joining interface.
def join(self, *props, **kwargs):
    'Create a SQL JOIN against this :class:`.Query` object\'s criterion\n        and apply generatively, returning the newly resulting :class:`.Query`.\n\n        **Simple Relationship Joins**\n\n        Consider a mapping between two classes ``User`` and ``Address``,\n        with a relationship ``User.addresses`` representing a collection\n        of ``Address`` objects associated with each ``User``.   The most\n        common usage of :meth:`~.Query.join` is to create a JOIN along this\n        relationship, using the ``User.addresses`` attribute as an indicator\n        for how this should occur::\n\n            q = session.query(User).join(User.addresses)\n\n        Where above, the call to :meth:`~.Query.join` along ``User.addresses``\n        will result in SQL equivalent to::\n\n            SELECT user.* FROM user JOIN address ON user.id = address.user_id\n\n        In the above example we refer to ``User.addresses`` as passed to\n        :meth:`~.Query.join` as the *on clause*, that is, it indicates\n        how the "ON" portion of the JOIN should be constructed.  For a\n        single-entity query such as the one above (i.e. we start by selecting\n        only from ``User`` and nothing else), the relationship can also be\n        specified by its string name::\n\n            q = session.query(User).join("addresses")\n\n        :meth:`~.Query.join` can also accommodate multiple\n        "on clause" arguments to produce a chain of joins, such as below\n        where a join across four related entities is constructed::\n\n            q = session.query(User).join("orders", "items", "keywords")\n\n        The above would be shorthand for three separate calls to\n        :meth:`~.Query.join`, each using an explicit attribute to indicate\n        the source entity::\n\n            q = session.query(User).\\\n                    join(User.orders).\\\n                    join(Order.items).\\\n                    join(Item.keywords)\n\n        **Joins to a Target Entity or Selectable**\n\n        A second form of :meth:`~.Query.join` allows any mapped entity\n        or core selectable construct as a target.   In this usage,\n        :meth:`~.Query.join` will attempt\n        to create a JOIN along the natural foreign key relationship between\n        two entities::\n\n            q = session.query(User).join(Address)\n\n        The above calling form of :meth:`~.Query.join` will raise an error if\n        either there are no foreign keys between the two entities, or if\n        there are multiple foreign key linkages between them.   In the\n        above calling form, :meth:`~.Query.join` is called upon to\n        create the "on clause" automatically for us.  The target can\n        be any mapped entity or selectable, such as a :class:`.Table`::\n\n            q = session.query(User).join(addresses_table)\n\n        **Joins to a Target with an ON Clause**\n\n        The third calling form allows both the target entity as well\n        as the ON clause to be passed explicitly.   Suppose for\n        example we wanted to join to ``Address`` twice, using\n        an alias the second time.  We use :func:`~sqlalchemy.orm.aliased`\n        to create a distinct alias of ``Address``, and join\n        to it using the ``target, onclause`` form, so that the\n        alias can be specified explicitly as the target along with\n        the relationship to instruct how the ON clause should proceed::\n\n            a_alias = aliased(Address)\n\n            q = session.query(User).\\\n                    join(User.addresses).\\\n                    join(a_alias, User.addresses).\\\n                    filter(Address.email_address==\'example@example.com\').\\\n                    filter(a_alias.email_address==\'example@example.com\')\n\n        Where above, the generated SQL would be similar to::\n\n            SELECT user.* FROM user\n                JOIN address ON user.id = address.user_id\n                JOIN address AS address_1 ON user.id=address_1.user_id\n                WHERE address.email_address = :email_address_1\n                AND address_1.email_address = :email_address_2\n\n        The two-argument calling form of :meth:`~.Query.join`\n        also allows us to construct arbitrary joins with SQL-oriented\n        "on clause" expressions, not relying upon configured relationships\n        at all.  Any SQL expression can be passed as the ON clause\n        when using the two-argument form, which should refer to the target\n        entity in some way as well as an applicable source entity::\n\n            q = session.query(User).join(Address, User.id==Address.user_id)\n\n        .. versionchanged:: 0.7\n            In SQLAlchemy 0.6 and earlier, the two argument form of\n            :meth:`~.Query.join` requires the usage of a tuple:\n            ``query(User).join((Address, User.id==Address.user_id))``\\ .\n            This calling form is accepted in 0.7 and further, though\n            is not necessary unless multiple join conditions are passed to\n            a single :meth:`~.Query.join` call, which itself is also not\n            generally necessary as it is now equivalent to multiple\n            calls (this wasn\'t always the case).\n\n        **Advanced Join Targeting and Adaption**\n\n        There is a lot of flexibility in what the "target" can be when using\n        :meth:`~.Query.join`.   As noted previously, it also accepts\n        :class:`.Table` constructs and other selectables such as\n        :func:`.alias` and :func:`.select` constructs, with either the one\n        or two-argument forms::\n\n            addresses_q = select([Address.user_id]).\\\n                        where(Address.email_address.endswith("@bar.com")).\\\n                        alias()\n\n            q = session.query(User).\\\n                        join(addresses_q, addresses_q.c.user_id==User.id)\n\n        :meth:`~.Query.join` also features the ability to *adapt* a\n        :meth:`~sqlalchemy.orm.relationship` -driven ON clause to the target\n        selectable. Below we construct a JOIN from ``User`` to a subquery\n        against ``Address``, allowing the relationship denoted by\n        ``User.addresses`` to *adapt* itself to the altered target::\n\n            address_subq = session.query(Address).\\\n                            filter(Address.email_address == \'example@example.com\').\\\n                            subquery()\n\n            q = session.query(User).join(address_subq, User.addresses)\n\n        Producing SQL similar to::\n\n            SELECT user.* FROM user\n                JOIN (\n                    SELECT address.id AS id,\n                            address.user_id AS user_id,\n                            address.email_address AS email_address\n                    FROM address\n                    WHERE address.email_address = :email_address_1\n                ) AS anon_1 ON user.id = anon_1.user_id\n\n        The above form allows one to fall back onto an explicit ON\n        clause at any time::\n\n            q = session.query(User).\\\n                    join(address_subq, User.id==address_subq.c.user_id)\n\n        **Controlling what to Join From**\n\n        While :meth:`~.Query.join` exclusively deals with the "right"\n        side of the JOIN, we can also control the "left" side, in those\n        cases where it\'s needed, using :meth:`~.Query.select_from`.\n        Below we construct a query against ``Address`` but can still\n        make usage of ``User.addresses`` as our ON clause by instructing\n        the :class:`.Query` to select first from the ``User``\n        entity::\n\n            q = session.query(Address).select_from(User).\\\n                            join(User.addresses).\\\n                            filter(User.name == \'ed\')\n\n        Which will produce SQL similar to::\n\n            SELECT address.* FROM user\n                JOIN address ON user.id=address.user_id\n                WHERE user.name = :name_1\n\n        **Constructing Aliases Anonymously**\n\n        :meth:`~.Query.join` can construct anonymous aliases\n        using the ``aliased=True`` flag.  This feature is useful\n        when a query is being joined algorithmically, such as\n        when querying self-referentially to an arbitrary depth::\n\n            q = session.query(Node).\\\n                    join("children", "children", aliased=True)\n\n        When ``aliased=True`` is used, the actual "alias" construct\n        is not explicitly available.  To work with it, methods such as\n        :meth:`.Query.filter` will adapt the incoming entity to\n        the last join point::\n\n            q = session.query(Node).\\\n                    join("children", "children", aliased=True).\\\n                    filter(Node.name == \'grandchild 1\')\n\n        When using automatic aliasing, the ``from_joinpoint=True``\n        argument can allow a multi-node join to be broken into\n        multiple calls to :meth:`~.Query.join`, so that\n        each path along the way can be further filtered::\n\n            q = session.query(Node).\\\n                    join("children", aliased=True).\\\n                    filter(Node.name=\'child 1\').\\\n                    join("children", aliased=True, from_joinpoint=True).\\\n                    filter(Node.name == \'grandchild 1\')\n\n        The filtering aliases above can then be reset back to the\n        original ``Node`` entity using :meth:`~.Query.reset_joinpoint`::\n\n            q = session.query(Node).\\\n                    join("children", "children", aliased=True).\\\n                    filter(Node.name == \'grandchild 1\').\\\n                    reset_joinpoint().\\\n                    filter(Node.name == \'parent 1)\n\n        For an example of ``aliased=True``, see the distribution\n        example :ref:`examples_xmlpersistence` which illustrates\n        an XPath-like query system using algorithmic joins.\n\n        :param \\*props: A collection of one or more join conditions,\n         each consisting of a relationship-bound attribute or string\n         relationship name representing an "on clause", or a single\n         target entity, or a tuple in the form of ``(target, onclause)``.\n         A special two-argument calling form of the form ``target, onclause``\n         is also accepted.\n        :param aliased=False: If True, indicate that the JOIN target should be\n         anonymously aliased.  Subsequent calls to :meth:`~.Query.filter`\n         and similar will adapt the incoming criterion to the target\n         alias, until :meth:`~.Query.reset_joinpoint` is called.\n        :param isouter=False: If True, the join used will be a left outer join,\n         just as if the :meth:`.Query.outerjoin` method were called.  This\n         flag is here to maintain consistency with the same flag as accepted\n         by :meth:`.FromClause.join` and other Core constructs.\n\n\n         .. versionadded:: 1.0.0\n\n        :param from_joinpoint=False: When using ``aliased=True``, a setting\n         of True here will cause the join to be from the most recent\n         joined target, rather than starting back from the original\n         FROM clauses of the query.\n\n        .. seealso::\n\n            :ref:`ormtutorial_joins` in the ORM tutorial.\n\n            :ref:`inheritance_toplevel` for details on how\n            :meth:`~.Query.join` is used for inheritance relationships.\n\n            :func:`.orm.join` - a standalone ORM-level join function,\n            used internally by :meth:`.Query.join`, which in previous\n            SQLAlchemy versions was the primary ORM-level joining interface.\n\n        '
    (aliased, from_joinpoint, isouter) = (kwargs.pop('aliased', False), kwargs.pop('from_joinpoint', False), kwargs.pop('isouter', False))
    if kwargs:
        raise TypeError(('unknown arguments: %s' % ','.join(kwargs.keys)))
    isouter = isouter
    return self._join(props, outerjoin=isouter, create_aliases=aliased, from_joinpoint=from_joinpoint)