from sqlalchemy import testing
from test.orm import _fixtures
-from sqlalchemy.testing import fixtures
+from sqlalchemy.testing import fixtures, AssertsCompiledSQL
from sqlalchemy.testing.schema import Table, Column
def test_relationship_to_subclass(self):
- JuniorEngineer, Company, companies, Manager, Employee, employees, Engineer = (self.classes.JuniorEngineer,
+ JuniorEngineer, Company, companies, Manager, \
+ Employee, employees, Engineer = (self.classes.JuniorEngineer,
self.classes.Company,
self.tables.companies,
self.classes.Manager,
)
go()
+
+class ManyToManyToSingleTest(fixtures.MappedTest, AssertsCompiledSQL):
+ __dialect__ = 'default'
+
+ @classmethod
+ def define_tables(cls, metadata):
+ Table('parent', metadata,
+ Column('id', Integer, primary_key=True,
+ test_needs_autoincrement=True)
+ )
+ Table('m2m', metadata,
+ Column('parent_id', Integer,
+ ForeignKey('parent.id'), primary_key=True),
+ Column('child_id', Integer,
+ ForeignKey('child.id'), primary_key=True),
+ )
+ Table('child', metadata,
+ Column('id', Integer, primary_key=True,
+ test_needs_autoincrement=True),
+ Column('discriminator', String(20)),
+ Column('name', String(20))
+ )
+
+ @classmethod
+ def setup_classes(cls):
+ class Parent(cls.Comparable):
+ pass
+
+ class Child(cls.Comparable):
+ pass
+
+ class SubChild1(Child):
+ pass
+
+ class SubChild2(Child):
+ pass
+
+ @classmethod
+ def setup_mappers(cls):
+ mapper(cls.classes.Parent, cls.tables.parent, properties={
+ "s1": relationship(cls.classes.SubChild1,
+ secondary=cls.tables.m2m,
+ uselist=False),
+ "s2": relationship(cls.classes.SubChild2,
+ secondary=cls.tables.m2m)
+ })
+ mapper(cls.classes.Child, cls.tables.child,
+ polymorphic_on=cls.tables.child.c.discriminator)
+ mapper(cls.classes.SubChild1, inherits=cls.classes.Child,
+ polymorphic_identity='sub1')
+ mapper(cls.classes.SubChild2, inherits=cls.classes.Child,
+ polymorphic_identity='sub2')
+
+ @classmethod
+ def insert_data(cls):
+ Parent = cls.classes.Parent
+ SubChild1 = cls.classes.SubChild1
+ SubChild2 = cls.classes.SubChild2
+ s = Session()
+ s.add_all([
+ Parent(s1=SubChild1(name='sc1_1'),
+ s2=[SubChild2(name="sc2_1"), SubChild2(name="sc2_2")]
+ ),
+ ])
+ s.commit()
+
+ def test_eager_join(self):
+ Parent = self.classes.Parent
+ SubChild1 = self.classes.SubChild1
+
+ s = Session()
+
+ p1 = s.query(Parent).options(joinedload(Parent.s1)).all()[0]
+ eq_(p1.__dict__['s1'], SubChild1(name='sc1_1'))
+
+ def test_manual_join(self):
+ Parent = self.classes.Parent
+ Child = self.classes.Child
+ SubChild1 = self.classes.SubChild1
+
+ s = Session()
+
+ p1, c1 = s.query(Parent, Child).outerjoin(Parent.s1).all()[0]
+ eq_(c1, SubChild1(name='sc1_1'))
+
+ def test_assert_join_sql(self):
+ Parent = self.classes.Parent
+ Child = self.classes.Child
+
+ s = Session()
+
+ self.assert_compile(
+ s.query(Parent, Child).outerjoin(Parent.s1),
+ "SELECT parent.id AS parent_id, child.id AS child_id, "
+ "child.discriminator AS child_discriminator, "
+ "child.name AS child_name "
+ "FROM parent LEFT OUTER JOIN (m2m AS m2m_1 "
+ "JOIN child ON child.id = m2m_1.child_id "
+ "AND child.discriminator IN (:discriminator_1)) "
+ "ON parent.id = m2m_1.parent_id"
+ )
+
+ def test_assert_joinedload_sql(self):
+ Parent = self.classes.Parent
+ Child = self.classes.Child
+
+ s = Session()
+
+ self.assert_compile(
+ s.query(Parent).options(joinedload(Parent.s1)),
+ "SELECT parent.id AS parent_id, child_1.id AS child_1_id, "
+ "child_1.discriminator AS child_1_discriminator, "
+ "child_1.name AS child_1_name "
+ "FROM parent LEFT OUTER JOIN "
+ "(m2m AS m2m_1 JOIN child AS child_1 "
+ "ON child_1.id = m2m_1.child_id AND child_1.discriminator "
+ "IN (:discriminator_1)) ON parent.id = m2m_1.parent_id"
+ )
+
class SingleOnJoinedTest(fixtures.MappedTest):
@classmethod
def define_tables(cls, metadata):
class Manager(Employee):
pass
- mapper(Person, persons_table, polymorphic_on=persons_table.c.type, polymorphic_identity='person')
+ mapper(Person, persons_table, polymorphic_on=persons_table.c.type,
+ polymorphic_identity='person')
mapper(Employee, employees_table, inherits=Person,polymorphic_identity='engineer')
mapper(Manager, inherits=Employee,polymorphic_identity='manager')
class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL):
run_inserts = 'once'
run_deletes = None
+ __dialect__ = 'default'
def test_basic(self):
users, Address, addresses, User = (self.tables.users,
"""test that the subquery wrapping only occurs with
limit/offset and m2m or o2m joins present."""
- users, items, order_items, Order, Item, User, Address, orders, addresses = (self.tables.users,
+ users, items, order_items, Order, Item, User, \
+ Address, orders, addresses = (self.tables.users,
self.tables.items,
self.tables.order_items,
self.classes.Order,
orders=relationship(Order, backref='user')
))
mapper(Order, orders, properties=odict([
- ('items', relationship(Item, secondary=order_items, backref='orders')),
+ ('items', relationship(Item, secondary=order_items,
+ backref='orders')),
('address', relationship(Address))
]))
mapper(Address, addresses)
self.assert_compile(
sess.query(User).options(joinedload(User.orders)).limit(10),
- "SELECT anon_1.users_id AS anon_1_users_id, anon_1.users_name AS anon_1_users_name, "
- "orders_1.id AS orders_1_id, orders_1.user_id AS orders_1_user_id, orders_1.address_id AS "
- "orders_1_address_id, orders_1.description AS orders_1_description, orders_1.isopen AS orders_1_isopen "
+ "SELECT anon_1.users_id AS anon_1_users_id, "
+ "anon_1.users_name AS anon_1_users_name, "
+ "orders_1.id AS orders_1_id, orders_1.user_id AS orders_1_user_id, "
+ "orders_1.address_id AS "
+ "orders_1_address_id, orders_1.description AS orders_1_description, "
+ "orders_1.isopen AS orders_1_isopen "
"FROM (SELECT users.id AS users_id, users.name AS users_name "
"FROM users "
- "LIMIT :param_1) AS anon_1 LEFT OUTER JOIN orders AS orders_1 ON anon_1.users_id = orders_1.user_id",
- {'param_1':10},
- use_default_dialect=True
+ "LIMIT :param_1) AS anon_1 LEFT OUTER JOIN orders AS orders_1 "
+ "ON anon_1.users_id = orders_1.user_id",
+ {'param_1':10}
)
self.assert_compile(
sess.query(Order).options(joinedload(Order.user)).limit(10),
- "SELECT orders.id AS orders_id, orders.user_id AS orders_user_id, orders.address_id AS "
- "orders_address_id, orders.description AS orders_description, orders.isopen AS orders_isopen, "
- "users_1.id AS users_1_id, users_1.name AS users_1_name FROM orders LEFT OUTER JOIN users AS "
+ "SELECT orders.id AS orders_id, orders.user_id AS orders_user_id, "
+ "orders.address_id AS "
+ "orders_address_id, orders.description AS orders_description, "
+ "orders.isopen AS orders_isopen, "
+ "users_1.id AS users_1_id, users_1.name AS users_1_name "
+ "FROM orders LEFT OUTER JOIN users AS "
"users_1 ON users_1.id = orders.user_id LIMIT :param_1",
- {'param_1':10},
- use_default_dialect=True
+ {'param_1':10}
)
self.assert_compile(
- sess.query(Order).options(joinedload(Order.user, innerjoin=True)).limit(10),
- "SELECT orders.id AS orders_id, orders.user_id AS orders_user_id, orders.address_id AS "
- "orders_address_id, orders.description AS orders_description, orders.isopen AS orders_isopen, "
- "users_1.id AS users_1_id, users_1.name AS users_1_name FROM orders JOIN users AS "
+ sess.query(Order).options(
+ joinedload(Order.user, innerjoin=True)).limit(10),
+ "SELECT orders.id AS orders_id, orders.user_id AS orders_user_id, "
+ "orders.address_id AS "
+ "orders_address_id, orders.description AS orders_description, "
+ "orders.isopen AS orders_isopen, "
+ "users_1.id AS users_1_id, users_1.name AS users_1_name "
+ "FROM orders JOIN users AS "
"users_1 ON users_1.id = orders.user_id LIMIT :param_1",
- {'param_1':10},
- use_default_dialect=True
+ {'param_1':10}
)
self.assert_compile(
- sess.query(User).options(joinedload_all("orders.address")).limit(10),
- "SELECT anon_1.users_id AS anon_1_users_id, anon_1.users_name AS anon_1_users_name, "
- "addresses_1.id AS addresses_1_id, addresses_1.user_id AS addresses_1_user_id, "
- "addresses_1.email_address AS addresses_1_email_address, orders_1.id AS orders_1_id, "
- "orders_1.user_id AS orders_1_user_id, orders_1.address_id AS orders_1_address_id, "
- "orders_1.description AS orders_1_description, orders_1.isopen AS orders_1_isopen FROM "
- "(SELECT users.id AS users_id, users.name AS users_name FROM users LIMIT :param_1) AS anon_1 "
- "LEFT OUTER JOIN orders AS orders_1 ON anon_1.users_id = orders_1.user_id LEFT OUTER JOIN "
+ sess.query(User).options(
+ joinedload_all("orders.address")).limit(10),
+ "SELECT anon_1.users_id AS anon_1_users_id, "
+ "anon_1.users_name AS anon_1_users_name, "
+ "addresses_1.id AS addresses_1_id, "
+ "addresses_1.user_id AS addresses_1_user_id, "
+ "addresses_1.email_address AS addresses_1_email_address, "
+ "orders_1.id AS orders_1_id, "
+ "orders_1.user_id AS orders_1_user_id, "
+ "orders_1.address_id AS orders_1_address_id, "
+ "orders_1.description AS orders_1_description, "
+ "orders_1.isopen AS orders_1_isopen FROM "
+ "(SELECT users.id AS users_id, users.name AS users_name "
+ "FROM users LIMIT :param_1) AS anon_1 "
+ "LEFT OUTER JOIN orders AS orders_1 "
+ "ON anon_1.users_id = orders_1.user_id LEFT OUTER JOIN "
"addresses AS addresses_1 ON addresses_1.id = orders_1.address_id",
- {'param_1':10},
- use_default_dialect=True
+ {'param_1':10}
)
self.assert_compile(
- sess.query(User).options(joinedload_all("orders.items"), joinedload("orders.address")),
- "SELECT users.id AS users_id, users.name AS users_name, items_1.id AS items_1_id, "
- "items_1.description AS items_1_description, addresses_1.id AS addresses_1_id, "
- "addresses_1.user_id AS addresses_1_user_id, addresses_1.email_address AS "
- "addresses_1_email_address, orders_1.id AS orders_1_id, orders_1.user_id AS "
- "orders_1_user_id, orders_1.address_id AS orders_1_address_id, orders_1.description "
- "AS orders_1_description, orders_1.isopen AS orders_1_isopen FROM users LEFT OUTER JOIN "
- "orders AS orders_1 ON users.id = orders_1.user_id LEFT OUTER JOIN order_items AS "
- "order_items_1 ON orders_1.id = order_items_1.order_id LEFT OUTER JOIN items AS "
- "items_1 ON items_1.id = order_items_1.item_id LEFT OUTER JOIN addresses AS "
- "addresses_1 ON addresses_1.id = orders_1.address_id"
- ,use_default_dialect=True
+ sess.query(User).options(joinedload_all("orders.items"),
+ joinedload("orders.address")),
+ "SELECT users.id AS users_id, users.name AS users_name, "
+ "items_1.id AS items_1_id, "
+ "items_1.description AS items_1_description, "
+ "addresses_1.id AS addresses_1_id, "
+ "addresses_1.user_id AS addresses_1_user_id, "
+ "addresses_1.email_address AS "
+ "addresses_1_email_address, orders_1.id AS orders_1_id, "
+ "orders_1.user_id AS "
+ "orders_1_user_id, orders_1.address_id AS orders_1_address_id, "
+ "orders_1.description "
+ "AS orders_1_description, orders_1.isopen AS orders_1_isopen "
+ "FROM users LEFT OUTER JOIN orders AS orders_1 "
+ "ON users.id = orders_1.user_id "
+ "LEFT OUTER JOIN (order_items AS order_items_1 "
+ "JOIN items AS items_1 ON items_1.id = order_items_1.item_id) "
+ "ON orders_1.id = order_items_1.order_id "
+ "LEFT OUTER JOIN addresses AS addresses_1 "
+ "ON addresses_1.id = orders_1.address_id"
)
self.assert_compile(
"FROM users "
"LIMIT :param_1) AS anon_1 LEFT OUTER JOIN orders AS orders_1 ON anon_1.users_id = "
"orders_1.user_id LEFT OUTER JOIN addresses AS addresses_1 ON addresses_1.id = orders_1.address_id",
- {'param_1':10},
- use_default_dialect=True
+ {'param_1':10}
)
self.assert_compile(
"FROM users "
"LIMIT :param_1) AS anon_1 JOIN orders AS orders_1 ON anon_1.users_id = "
"orders_1.user_id JOIN addresses AS addresses_1 ON addresses_1.id = orders_1.address_id",
- {'param_1':10},
- use_default_dialect=True
+ {'param_1':10}
)
def test_one_to_many_scalar(self):
"SELECT users.id AS users_id, users.name AS users_name, "
"addresses_1.id AS addresses_1_id, addresses_1.user_id AS addresses_1_user_id, "
"addresses_1.email_address AS addresses_1_email_address FROM users JOIN "
- "addresses AS addresses_1 ON users.id = addresses_1.user_id ORDER BY addresses_1.id"
- , use_default_dialect=True)
+ "addresses AS addresses_1 ON users.id = addresses_1.user_id ORDER BY addresses_1.id")
def test_inner_join_chaining_options(self):
users, items, order_items, Order, Item, User, orders = (self.tables.users,
"orders_1.isopen AS orders_1_isopen FROM users JOIN orders AS orders_1 ON "
"users.id = orders_1.user_id JOIN order_items AS order_items_1 ON orders_1.id = "
"order_items_1.order_id JOIN items AS items_1 ON items_1.id = "
- "order_items_1.item_id",
- use_default_dialect=True
+ "order_items_1.item_id"
)
self.assert_compile(
"items_1_id, items_1.description AS items_1_description, orders_1.id AS "
"orders_1_id, orders_1.user_id AS orders_1_user_id, orders_1.address_id AS "
"orders_1_address_id, orders_1.description AS orders_1_description, "
- "orders_1.isopen AS orders_1_isopen FROM users LEFT OUTER JOIN orders AS orders_1 ON "
- "users.id = orders_1.user_id LEFT OUTER JOIN order_items AS order_items_1 ON orders_1.id = "
- "order_items_1.order_id LEFT OUTER JOIN items AS items_1 ON items_1.id = "
- "order_items_1.item_id",
- use_default_dialect=True
+ "orders_1.isopen AS orders_1_isopen "
+ "FROM users LEFT OUTER JOIN orders AS orders_1 "
+ "ON users.id = orders_1.user_id "
+ "LEFT OUTER JOIN (order_items AS order_items_1 "
+ "JOIN items AS items_1 ON items_1.id = order_items_1.item_id) "
+ "ON orders_1.id = order_items_1.order_id"
)
self.assert_compile(
"items_1_id, items_1.description AS items_1_description, orders_1.id AS "
"orders_1_id, orders_1.user_id AS orders_1_user_id, orders_1.address_id AS "
"orders_1_address_id, orders_1.description AS orders_1_description, "
- "orders_1.isopen AS orders_1_isopen FROM users JOIN orders AS orders_1 ON "
- "users.id = orders_1.user_id LEFT OUTER JOIN order_items AS order_items_1 ON orders_1.id = "
- "order_items_1.order_id LEFT OUTER JOIN items AS items_1 ON items_1.id = "
- "order_items_1.item_id",
- use_default_dialect=True
+ "orders_1.isopen AS orders_1_isopen "
+ "FROM users JOIN orders AS orders_1 ON users.id = orders_1.user_id "
+ "LEFT OUTER JOIN (order_items AS order_items_1 "
+ "JOIN items AS items_1 ON items_1.id = order_items_1.item_id) "
+ "ON orders_1.id = order_items_1.order_id"
+
+ )
+
+ def test_catch_the_right_target(self):
+ # test eager join chaining to the "nested" join on the left,
+ # a new feature as of [ticket:2369]
+
+ users, Keyword, orders, items, order_items, Order, Item, \
+ User, keywords, item_keywords = (self.tables.users,
+ self.classes.Keyword,
+ self.tables.orders,
+ self.tables.items,
+ self.tables.order_items,
+ self.classes.Order,
+ self.classes.Item,
+ self.classes.User,
+ self.tables.keywords,
+ self.tables.item_keywords)
+
+ mapper(User, users, properties={
+ 'orders':relationship(Order, backref='user'), # o2m, m2o
+ })
+ mapper(Order, orders, properties={
+ 'items':relationship(Item, secondary=order_items,
+ order_by=items.c.id), #m2m
+ })
+ mapper(Item, items, properties={
+ 'keywords':relationship(Keyword, secondary=item_keywords,
+ order_by=keywords.c.id) #m2m
+ })
+ mapper(Keyword, keywords)
+
+ sess = create_session()
+ q = sess.query(User).join(User.orders).join(Order.items).\
+ options(joinedload_all("orders.items.keywords"))
+
+ # here, the eager join for keywords can catch onto
+ # join(Order.items) or the nested (orders LEFT OUTER JOIN items),
+ # it should catch the latter
+ self.assert_compile(
+ q,
+ "SELECT users.id AS users_id, users.name AS users_name, "
+ "keywords_1.id AS keywords_1_id, keywords_1.name AS keywords_1_name, "
+ "items_1.id AS items_1_id, items_1.description AS items_1_description, "
+ "orders_1.id AS orders_1_id, orders_1.user_id AS orders_1_user_id, "
+ "orders_1.address_id AS orders_1_address_id, "
+ "orders_1.description AS orders_1_description, "
+ "orders_1.isopen AS orders_1_isopen "
+ "FROM users JOIN orders ON users.id = orders.user_id "
+ "JOIN order_items AS order_items_1 ON orders.id = order_items_1.order_id "
+ "JOIN items ON items.id = order_items_1.item_id "
+ "LEFT OUTER JOIN orders AS orders_1 ON users.id = orders_1.user_id "
+ "LEFT OUTER JOIN (order_items AS order_items_2 "
+ "JOIN items AS items_1 ON items_1.id = order_items_2.item_id) "
+ "ON orders_1.id = order_items_2.order_id "
+ "LEFT OUTER JOIN (item_keywords AS item_keywords_1 "
+ "JOIN keywords AS keywords_1 ON keywords_1.id = item_keywords_1.keyword_id) "
+ "ON items_1.id = item_keywords_1.item_id "
+ "ORDER BY items_1.id, keywords_1.id"
)
def test_inner_join_chaining_fixed(self):
"orders_1_id, orders_1.user_id AS orders_1_user_id, orders_1.address_id AS "
"orders_1_address_id, orders_1.description AS orders_1_description, "
"orders_1.isopen AS orders_1_isopen FROM users LEFT OUTER JOIN orders AS orders_1 ON "
- "users.id = orders_1.user_id LEFT OUTER JOIN order_items AS order_items_1 ON orders_1.id = "
- "order_items_1.order_id LEFT OUTER JOIN items AS items_1 ON items_1.id = "
- "order_items_1.item_id",
- use_default_dialect=True
+ "users.id = orders_1.user_id LEFT OUTER JOIN "
+ "(order_items AS order_items_1 JOIN items AS items_1 ON items_1.id = "
+ "order_items_1.item_id) ON orders_1.id = "
+ "order_items_1.order_id"
)
# joining just from Order, innerjoin=True can be respected
"AS items_1_id, items_1.description AS items_1_description FROM "
"orders JOIN order_items AS order_items_1 ON orders.id = "
"order_items_1.order_id JOIN items AS items_1 ON items_1.id = "
- "order_items_1.item_id",
- use_default_dialect=True
+ "order_items_1.item_id"
)
"SELECT users.id AS users_id, users.name AS users_name, orders_1.id AS orders_1_id, "
"orders_1.user_id AS orders_1_user_id, orders_1.address_id AS orders_1_address_id, "
"orders_1.description AS orders_1_description, orders_1.isopen AS orders_1_isopen "
- "FROM users JOIN orders AS orders_1 ON users.id = orders_1.user_id ORDER BY orders_1.id"
- , use_default_dialect=True)
+ "FROM users JOIN orders AS orders_1 ON users.id = orders_1.user_id ORDER BY orders_1.id")
self.assert_compile(sess.query(User).options(joinedload_all(User.orders, Order.items, innerjoin=True)),
"SELECT users.id AS users_id, users.name AS users_name, items_1.id AS items_1_id, "
"orders_1.description AS orders_1_description, orders_1.isopen AS orders_1_isopen "
"FROM users JOIN orders AS orders_1 ON users.id = orders_1.user_id JOIN order_items AS "
"order_items_1 ON orders_1.id = order_items_1.order_id JOIN items AS items_1 ON "
- "items_1.id = order_items_1.item_id ORDER BY orders_1.id, items_1.id"
- , use_default_dialect=True)
+ "items_1.id = order_items_1.item_id ORDER BY orders_1.id, items_1.id")
def go():
eq_(
"orders_address_id, orders.description AS orders_description, orders.isopen AS "
"orders_isopen, users_1.id AS users_1_id, users_1.name AS users_1_name "
"FROM orders JOIN users AS users_1 ON users_1.id = orders.user_id "
- "WHERE orders.description = :description_1",
- use_default_dialect=True
+ "WHERE orders.description = :description_1"
)
run_setup_mappers = 'once'
run_inserts = 'once'
run_deletes = None
+ __dialect__ = 'default'
@classmethod
def setup_mappers(cls):
- def test_aliased_entity(self):
+ def test_aliased_entity_one(self):
Item, Order, User, Address = (self.classes.Item,
self.classes.Order,
self.classes.User,
)
self.assert_sql_count(testing.db, go, 1)
+ def test_aliased_entity_two(self):
+ Item, Order, User, Address = (self.classes.Item,
+ self.classes.Order,
+ self.classes.User,
+ self.classes.Address)
+
+ sess = create_session()
+
+ oalias = sa.orm.aliased(Order)
+
+
# one FROM clause
def go():
eq_(
)
self.assert_sql_count(testing.db, go, 1)
- from sqlalchemy.engine.default import DefaultDialect
+
+ def test_aliased_entity_three(self):
+ Item, Order, User, Address = (self.classes.Item,
+ self.classes.Order,
+ self.classes.User,
+ self.classes.Address)
+
+ sess = create_session()
+
+ oalias = sa.orm.aliased(Order)
+
# improper setup: oalias in the columns clause but join to usual
# orders alias. this should create two FROM clauses even though the
# query has a from_clause set up via the join
- self.assert_compile(sess.query(User, oalias).join(User.orders).options(joinedload(oalias.items)).with_labels().statement,
- "SELECT users.id AS users_id, users.name AS users_name, orders_1.id AS orders_1_id, "\
- "orders_1.user_id AS orders_1_user_id, orders_1.address_id AS orders_1_address_id, "\
- "orders_1.description AS orders_1_description, orders_1.isopen AS orders_1_isopen, items_1.id AS items_1_id, "\
- "items_1.description AS items_1_description FROM users JOIN orders ON users.id = orders.user_id, "\
- "orders AS orders_1 LEFT OUTER JOIN order_items AS order_items_1 ON orders_1.id = order_items_1.order_id "\
- "LEFT OUTER JOIN items AS items_1 ON items_1.id = order_items_1.item_id ORDER BY items_1.id",
- dialect=DefaultDialect()
+ self.assert_compile(
+ sess.query(User, oalias).join(User.orders).
+ options(joinedload(oalias.items)).with_labels().statement,
+ "SELECT users.id AS users_id, users.name AS users_name, "
+ "orders_1.id AS orders_1_id, "
+ "orders_1.user_id AS orders_1_user_id, "
+ "orders_1.address_id AS orders_1_address_id, "
+ "orders_1.description AS orders_1_description, "
+ "orders_1.isopen AS orders_1_isopen, items_1.id AS items_1_id, "
+ "items_1.description AS items_1_description FROM users "
+ "JOIN orders ON users.id = orders.user_id, "
+ "orders AS orders_1 LEFT OUTER JOIN (order_items AS order_items_1 "
+ "JOIN items AS items_1 ON items_1.id = order_items_1.item_id) "
+ "ON orders_1.id = order_items_1.order_id ORDER BY items_1.id"
)