1.. _inheritance_loading_toplevel:
2
3.. currentmodule:: sqlalchemy.orm
4
5Loading Inheritance Hierarchies
6===============================
7
8When classes are mapped in inheritance hierarchies using the "joined",
9"single", or "concrete" table inheritance styles as described at
10:ref:`inheritance_toplevel`, the usual behavior is that a query for a
11particular base class will also yield objects corresponding to subclasses
12as well.   When a single query is capable of returning a result with
13a different class or subclasses per result row, we use the term
14"polymorphic loading".
15
16Within the realm of polymorphic loading, specifically with joined and single
17table inheritance, there is an additional problem of which subclass attributes
18are to be queried up front, and which are to be loaded later. When an attribute
19of a particular subclass is queried up front, we can use it in our query as
20something to filter on, and it also will be loaded when we get our objects
21back.   If it's not queried up front, it gets loaded later when we first need
22to access it.   Basic control of this behavior is provided using the
23:func:`.orm.with_polymorphic` function, as well as two variants, the mapper
24configuration :paramref:`.mapper.with_polymorphic` and the :class:`.Query`
25-level :meth:`.Query.with_polymorphic` method.    The "with_polymorphic" family
26each provide a means of specifying which specific subclasses of a particular
27base class should be included within a query, which implies what columns and
28tables will be available in the SELECT.
29
30.. _with_polymorphic:
31
32Using with_polymorphic
33----------------------
34
35For the following sections, assume the ``Employee`` / ``Engineer`` / ``Manager``
36examples introduced in :ref:`inheritance_toplevel`.
37
38Normally, when a :class:`.Query` specifies the base class of an
39inheritance hierarchy, only the columns that are local to that base
40class are queried::
41
42    session.query(Employee).all()
43
44Above, for both single and joined table inheritance, only the columns
45local to ``Employee`` will be present in the SELECT.   We may get back
46instances of ``Engineer`` or ``Manager``, however they will not have the
47additional attributes loaded until we first access them, at which point a
48lazy load is emitted.
49
50Similarly, if we wanted to refer to columns mapped
51to ``Engineer`` or ``Manager`` in our query that's against ``Employee``,
52these columns aren't available directly in either the single or joined table
53inheritance case, since the ``Employee`` entity does not refer to these columns
54(note that for single-table inheritance, this is common if Declarative is used,
55but not for a classical mapping).
56
57To solve both of these issues, the :func:`.orm.with_polymorphic` function
58provides a special :class:`.AliasedClass` that represents a range of
59columns across subclasses. This object can be used in a :class:`.Query`
60like any other alias.  When queried, it represents all the columns present in
61the classes given::
62
63    from sqlalchemy.orm import with_polymorphic
64
65    eng_plus_manager = with_polymorphic(Employee, [Engineer, Manager])
66
67    query = session.query(eng_plus_manager)
68
69If the above mapping were using joined table inheritance, the SELECT
70statement for the above would be:
71
72.. sourcecode:: python+sql
73
74    query.all()
75    {opensql}
76    SELECT employee.id AS employee_id,
77        engineer.id AS engineer_id,
78        manager.id AS manager_id,
79        employee.name AS employee_name,
80        employee.type AS employee_type,
81        engineer.engineer_info AS engineer_engineer_info,
82        manager.manager_data AS manager_manager_data
83    FROM employee
84        LEFT OUTER JOIN engineer
85        ON employee.id = engineer.id
86        LEFT OUTER JOIN manager
87        ON employee.id = manager.id
88    []
89
90Where above, the additional tables / columns for "engineer" and "manager" are
91included.  Similar behavior occurs in the case of single table inheritance.
92
93:func:`.orm.with_polymorphic` accepts a single class or
94mapper, a list of classes/mappers, or the string ``'*'`` to indicate all
95subclasses:
96
97.. sourcecode:: python+sql
98
99    # include columns for Engineer
100    entity = with_polymorphic(Employee, Engineer)
101
102    # include columns for Engineer, Manager
103    entity = with_polymorphic(Employee, [Engineer, Manager])
104
105    # include columns for all mapped subclasses
106    entity = with_polymorphic(Employee, '*')
107
108Using aliasing with with_polymorphic
109~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110
111The :func:`.orm.with_polymorphic` function also provides "aliasing" of the
112polymorphic selectable itself, meaning, two different :func:`.orm.with_polymorphic`
113entities, referring to the same class hierarchy, can be used together.  This
114is available using the :paramref:`.orm.with_polymorphic.aliased` flag.
115For a polymorphic selectable that is across multiple tables, the default behavior
116is to wrap the selectable into a subquery.  Below we emit a query that will
117select for "employee or manager" paired with "employee or engineer" on employees
118with the same name:
119
120.. sourcecode:: python+sql
121
122    engineer_employee = with_polymorphic(
123        Employee, [Engineer], aliased=True)
124    manager_employee = with_polymorphic(
125        Employee, [Manager], aliased=True)
126
127    q = s.query(engineer_employee, manager_employee).\
128        join(
129            manager_employee,
130            and_(
131                engineer_employee.id > manager_employee.id,
132                engineer_employee.name == manager_employee.name
133            )
134    )
135    q.all()
136    {opensql}
137    SELECT
138        anon_1.employee_id AS anon_1_employee_id,
139        anon_1.employee_name AS anon_1_employee_name,
140        anon_1.employee_type AS anon_1_employee_type,
141        anon_1.engineer_id AS anon_1_engineer_id,
142        anon_1.engineer_engineer_name AS anon_1_engineer_engineer_name,
143        anon_2.employee_id AS anon_2_employee_id,
144        anon_2.employee_name AS anon_2_employee_name,
145        anon_2.employee_type AS anon_2_employee_type,
146        anon_2.manager_id AS anon_2_manager_id,
147        anon_2.manager_manager_name AS anon_2_manager_manager_name
148    FROM (
149        SELECT
150            employee.id AS employee_id,
151            employee.name AS employee_name,
152            employee.type AS employee_type,
153            engineer.id AS engineer_id,
154            engineer.engineer_name AS engineer_engineer_name
155        FROM employee
156        LEFT OUTER JOIN engineer ON employee.id = engineer.id
157    ) AS anon_1
158    JOIN (
159        SELECT
160            employee.id AS employee_id,
161            employee.name AS employee_name,
162            employee.type AS employee_type,
163            manager.id AS manager_id,
164             manager.manager_name AS manager_manager_name
165        FROM employee
166        LEFT OUTER JOIN manager ON employee.id = manager.id
167    ) AS anon_2
168    ON anon_1.employee_id > anon_2.employee_id
169    AND anon_1.employee_name = anon_2.employee_name
170
171The creation of subqueries above is very verbose.  While it creates the best
172encapsulation of the two distinct queries, it may be inefficient.
173:func:`.orm.with_polymorphic` includes an additional flag to help with this
174situation, :paramref:`.orm.with_polymorphic.flat`, which will "flatten" the
175subquery / join combination into straight joins, applying aliasing to the
176individual tables instead.   Setting :paramref:`.orm.with_polymorphic.flat`
177implies :paramref:`.orm.with_polymorphic.aliased`, so only one flag
178is necessary:
179
180.. sourcecode:: python+sql
181
182    engineer_employee = with_polymorphic(
183        Employee, [Engineer], flat=True)
184    manager_employee = with_polymorphic(
185        Employee, [Manager], flat=True)
186
187    q = s.query(engineer_employee, manager_employee).\
188        join(
189            manager_employee,
190            and_(
191                engineer_employee.id > manager_employee.id,
192                engineer_employee.name == manager_employee.name
193            )
194    )
195    q.all()
196    {opensql}
197    SELECT
198        employee_1.id AS employee_1_id,
199        employee_1.name AS employee_1_name,
200        employee_1.type AS employee_1_type,
201        engineer_1.id AS engineer_1_id,
202        engineer_1.engineer_name AS engineer_1_engineer_name,
203        employee_2.id AS employee_2_id,
204        employee_2.name AS employee_2_name,
205        employee_2.type AS employee_2_type,
206        manager_1.id AS manager_1_id,
207        manager_1.manager_name AS manager_1_manager_name
208    FROM employee AS employee_1
209    LEFT OUTER JOIN engineer AS engineer_1
210    ON employee_1.id = engineer_1.id
211    JOIN (
212        employee AS employee_2
213        LEFT OUTER JOIN manager AS manager_1
214        ON employee_2.id = manager_1.id
215    )
216    ON employee_1.id > employee_2.id
217    AND employee_1.name = employee_2.name
218
219Note above, when using :paramref:`.orm.with_polymorphic.flat`, it is often the
220case when used in conjunction with joined table inheritance that we get a
221right-nested JOIN in our statement.   Some older databases, in particular older
222versions of SQLite, may have a problem with this syntax, although virtually all
223modern database versions now support this syntax.
224
225Referring to Specific Subclass Attributes
226~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
227
228The entity returned by :func:`.orm.with_polymorphic` is an :class:`.AliasedClass`
229object, which can be used in a :class:`.Query` like any other alias, including
230named attributes for those attributes on the ``Employee`` class.   In our
231previous example, ``eng_plus_manager`` becomes the entity that we use to refer to the
232three-way outer join above.  It also includes namespaces for each class named
233in the list of classes, so that attributes specific to those subclasses can be
234called upon as well.   The following example illustrates calling upon attributes
235specific to ``Engineer`` as well as ``Manager`` in terms of ``eng_plus_manager``::
236
237    eng_plus_manager = with_polymorphic(Employee, [Engineer, Manager])
238    query = session.query(eng_plus_manager).filter(
239                    or_(
240                        eng_plus_manager.Engineer.engineer_info=='x',
241                        eng_plus_manager.Manager.manager_data=='y'
242                    )
243                )
244
245
246Setting with_polymorphic at mapper configuration time
247~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
248
249The :func:`.orm.with_polymorphic` function serves the purpose of allowing
250"eager" loading of attributes from subclass tables, as well as the ability
251to refer to the attributes from subclass tables at query time.   Historically,
252the "eager loading" of columns has been the more important part of the
253equation.   So just as eager loading for relationships can be specified
254as a configurational option, the :paramref:`.mapper.with_polymorphic`
255configuration parameter allows an entity to use a polymorphic load by
256default.  We can add the parameter to our ``Employee`` mapping
257first introduced at :ref:`joined_inheritance`::
258
259    class Employee(Base):
260        __tablename__ = 'employee'
261        id = Column(Integer, primary_key=True)
262        name = Column(String(50))
263        type = Column(String(50))
264
265        __mapper_args__ = {
266            'polymorphic_identity':'employee',
267            'polymorphic_on':type,
268            'with_polymorphic': '*'
269        }
270
271Above is the most common setting for :paramref:`.mapper.with_polymorphic`,
272which is to indicate an asterisk to load all subclass columns.   In the
273case of joined table inheritance, this option
274should be used sparingly, as it implies that the mapping will always emit
275a (often large) series of LEFT OUTER JOIN to many tables, which is not
276efficient from a SQL perspective.   For single table inheritance, specifying the
277asterisk is often a good idea as the load is still against a single table only,
278but an additional lazy load of subclass-mapped columns will be prevented.
279
280Using :func:`.orm.with_polymorphic` or :meth:`.Query.with_polymorphic`
281will override the mapper-level :paramref:`.mapper.with_polymorphic` setting.
282
283The :paramref:`.mapper.with_polymorphic` option also accepts a list of
284classes just like :func:`.orm.with_polymorphic` to polymorphically load among
285a subset of classes, however this API was first designed with classical
286mapping in mind; when using Declarative, the subclasses aren't
287available yet.   The current workaround is to set the
288:paramref:`.mapper.with_polymorphic`
289setting after all classes have been declared, using the semi-private
290method :meth:`.mapper._set_with_polymorphic`.  A future release
291of SQLAlchemy will allow finer control over mapper-level polymorphic
292loading with declarative, using new options specified on individual
293subclasses.   When using concrete inheritance, special helpers are provided
294to help with these patterns which are described at :ref:`concrete_polymorphic`.
295
296Setting with_polymorphic against a query
297~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
298
299The :func:`.orm.with_polymorphic` function evolved from a query-level
300method :meth:`.Query.with_polymorphic`.  This method has the same purpose
301as :func:`.orm.with_polymorphic`, except is not as
302flexible in its usage patterns in that it only applies to the first entity
303of the :class:`.Query`.   It then takes effect for all occurences of
304that entity, so that the entity (and its subclasses) can be referred to
305directly, rather than using an alias object.  For simple cases it might be
306considered to be more succinct::
307
308    session.query(Employee).\
309        with_polymorphic([Engineer, Manager]).\
310        filter(
311            or_(
312                Engineer.engineer_info=='w',
313                Manager.manager_data=='q'
314            )
315        )
316
317The :meth:`.Query.with_polymorphic` method has a more complicated job
318than the :func:`.orm.with_polymorphic` function, as it needs to correctly
319transform entities like ``Engineer`` and ``Manager`` appropriately, but
320not interfere with other entities.  If its flexibility is lacking, switch
321to using :func:`.orm.with_polymorphic`.
322
323Referring to specific subtypes on relationships
324-----------------------------------------------
325
326Mapped attributes which correspond to a :func:`.relationship` are used
327in querying in order to refer to the linkage between two mappings.  Common
328uses for this are to refer to a :func:`.relationship` in :meth:`.Query.join`
329as well as in loader options like :func:`.joinedload`.   When using
330:func:`.relationship` where the target class is an inheritance hierarchy,
331the API allows that the join, eager load, or other linkage should target a specific
332subclass, alias, or :func:`.orm.with_polymorphic` alias, of that class hierarchy,
333rather than the class directly targeted by the :func:`.relationship`.
334
335The :func:`~sqlalchemy.orm.interfaces.PropComparator.of_type` method allows the
336construction of joins along :func:`~sqlalchemy.orm.relationship` paths while
337narrowing the criterion to specific derived aliases or subclasses. Suppose the
338``employees`` table represents a collection of employees which are associated
339with a ``Company`` object. We'll add a ``company_id`` column to the
340``employees`` table and a new table ``companies``:
341
342.. sourcecode:: python
343
344    class Company(Base):
345        __tablename__ = 'company'
346        id = Column(Integer, primary_key=True)
347        name = Column(String(50))
348        employees = relationship("Employee",
349                        backref='company')
350
351    class Employee(Base):
352        __tablename__ = 'employee'
353        id = Column(Integer, primary_key=True)
354        type = Column(String(20))
355        company_id = Column(Integer, ForeignKey('company.id'))
356        __mapper_args__ = {
357            'polymorphic_on':type,
358            'polymorphic_identity':'employee',
359        }
360
361    class Engineer(Employee):
362        __tablename__ = 'engineer'
363        id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
364        engineer_info = Column(String(50))
365        __mapper_args__ = {'polymorphic_identity':'engineer'}
366
367    class Manager(Employee):
368        __tablename__ = 'manager'
369        id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
370        manager_data = Column(String(50))
371        __mapper_args__ = {'polymorphic_identity':'manager'}
372
373When querying from ``Company`` onto the ``Employee`` relationship, the
374:meth:`.Query.join` method as well as operators like :meth:`.PropComparator.any`
375and :meth:`.PropComparator.has` will create
376a join from ``company`` to ``employee``, without including ``engineer`` or
377``manager`` in the mix. If we wish to have criterion which is specifically
378against the ``Engineer`` class, we can tell those methods to join or subquery
379against the set of columns representing the subclass using the
380:meth:`~.orm.interfaces.PropComparator.of_type` operator::
381
382    session.query(Company).\
383        join(Company.employees.of_type(Engineer)).\
384        filter(Engineer.engineer_info=='someinfo')
385
386Similarly, to join from ``Company`` to the polymorphic entity that includes both
387``Engineer`` and ``Manager`` columns::
388
389    manager_and_engineer = with_polymorphic(
390                                Employee, [Manager, Engineer])
391
392    session.query(Company).\
393        join(Company.employees.of_type(manager_and_engineer)).\
394        filter(
395            or_(
396                manager_and_engineer.Engineer.engineer_info == 'someinfo',
397                manager_and_engineer.Manager.manager_data == 'somedata'
398            )
399        )
400
401The :meth:`.PropComparator.any` and :meth:`.PropComparator.has` operators also
402can be used with :func:`~sqlalchemy.orm.interfaces.PropComparator.of_type`,
403such as when the embedded criterion is in terms of a subclass::
404
405    session.query(Company).\
406            filter(
407                Company.employees.of_type(Engineer).
408                    any(Engineer.engineer_info=='someinfo')
409                ).all()
410
411.. _eagerloading_polymorphic_subtypes:
412
413Eager Loading of Specific or Polymorphic Subtypes
414~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
415
416The :func:`.joinedload`, :func:`.subqueryload`, :func:`.contains_eager` and
417other eagerloader options support
418paths which make use of :func:`~.PropComparator.of_type`.
419Below, we load ``Company`` rows while eagerly loading related ``Engineer``
420objects, querying the ``employee`` and ``engineer`` tables simultaneously::
421
422    session.query(Company).\
423        options(
424            subqueryload(Company.employees.of_type(Engineer)).
425            subqueryload(Engineer.machines)
426            )
427        )
428
429As is the case with :meth:`.Query.join`, :meth:`~.PropComparator.of_type`
430can be used to combine eager loading and :func:`.orm.with_polymorphic`,
431so that all sub-attributes of all referenced subtypes
432can be loaded::
433
434    manager_and_engineer = with_polymorphic(
435                                Employee, [Manager, Engineer],
436                                flat=True)
437
438    session.query(Company).\
439        options(
440            joinedload(
441                Company.employees.of_type(manager_and_engineer)
442            )
443        )
444
445When using :func:`.with_polymorphic` in conjunction with
446:func:`.joinedload`, the :func:`.with_polymorphic` object must include
447the ``aliased=True`` or ``flat=True`` flag, so that the polymorphic
448selectable is aliased (an informative error message is raised otherwise).
449"flat" is an alternate form of aliasing that produces fewer subqueries.
450
451Once :meth:`~.PropComparator.of_type` is the target of the eager load,
452that's the entity we would use for subsequent chaining, not the original class
453or derived class.  If we wanted to further eager load a collection on the
454eager-loaded ``Engineer`` class, we access this class from the namespace of the
455:func:`.orm.with_polymorphic` object::
456
457    session.query(Company).\
458        options(
459            joinedload(Company.employees.of_type(manager_and_engineer)).\
460            subqueryload(manager_and_engineer.Engineer.computers)
461            )
462        )
463
464.. _loading_joined_inheritance:
465
466Loading objects with joined table inheritance
467---------------------------------------------
468
469When using joined table inheritance, if we query for a specific subclass
470that represents a JOIN of two tables such as our ``Engineer`` example
471from the inheritance section, the SQL emitted is a join::
472
473    session.query(Engineer).all()
474
475The above query will emit SQL like:
476
477.. sourcecode:: python+sql
478
479    {opensql}
480    SELECT employee.id AS employee_id,
481        employee.name AS employee_name, employee.type AS employee_type,
482        engineer.name AS engineer_name
483    FROM employee JOIN engineer
484    ON employee.id = engineer.id
485
486We will then get a collection of ``Engineer`` objects back, which will
487contain all columns from ``employee`` and ``engineer`` loaded.
488
489However, when emitting a :class:`.Query` against a base class, the behavior
490is to load only from the base table::
491
492    session.query(Employee).all()
493
494Above, the default behavior would be to SELECT only from the ``employee``
495table and not from any "sub" tables (``engineer`` and ``manager``, in our
496previous examples):
497
498.. sourcecode:: python+sql
499
500    {opensql}
501    SELECT employee.id AS employee_id,
502        employee.name AS employee_name, employee.type AS employee_type
503    FROM employee
504    []
505
506After a collection of ``Employee`` objects has been returned from the
507query, and as attributes are requested from those ``Employee`` objects which are
508represented in either the ``engineer`` or ``manager`` child tables, a second
509load is issued for the columns in that related row, if the data was not
510already loaded. So above, after accessing the objects you'd see further SQL
511issued along the lines of:
512
513.. sourcecode:: python+sql
514
515    {opensql}
516    SELECT manager.id AS manager_id,
517        manager.manager_data AS manager_manager_data
518    FROM manager
519    WHERE ? = manager.id
520    [5]
521    SELECT engineer.id AS engineer_id,
522        engineer.engineer_info AS engineer_engineer_info
523    FROM engineer
524    WHERE ? = engineer.id
525    [2]
526
527The :func:`.orm.with_polymorphic`
528function and related configuration options allow us to instead emit a JOIN up
529front which will conditionally load against ``employee``, ``engineer``, or
530``manager``, very much like joined eager loading works for relationships,
531removing the necessity for a second per-entity load::
532
533    from sqlalchemy.orm import with_polymorphic
534
535    eng_plus_manager = with_polymorphic(Employee, [Engineer, Manager])
536
537    query = session.query(eng_plus_manager)
538
539The above produces a query which joins the ``employee`` table to both the
540``engineer`` and ``manager`` tables like the following:
541
542.. sourcecode:: python+sql
543
544    query.all()
545    {opensql}
546    SELECT employee.id AS employee_id,
547        engineer.id AS engineer_id,
548        manager.id AS manager_id,
549        employee.name AS employee_name,
550        employee.type AS employee_type,
551        engineer.engineer_info AS engineer_engineer_info,
552        manager.manager_data AS manager_manager_data
553    FROM employee
554        LEFT OUTER JOIN engineer
555        ON employee.id = engineer.id
556        LEFT OUTER JOIN manager
557        ON employee.id = manager.id
558    []
559
560The section :ref:`with_polymorphic` discusses the :func:`.orm.with_polymorphic`
561function and its configurational variants.
562
563.. seealso::
564
565    :ref:`with_polymorphic`
566
567.. _loading_single_inheritance:
568
569Loading objects with single table inheritance
570---------------------------------------------
571
572In modern Declarative, single inheritance mappings produce :class:`.Column`
573objects that are mapped only to a subclass, and not available from the
574superclass, even though they are present on the same table.
575In our example from :ref:`single_inheritance`, the ``Manager`` mapping for example had a
576:class:`.Column` specified::
577
578    class Manager(Employee):
579        manager_data = Column(String(50))
580
581        __mapper_args__ = {
582            'polymorphic_identity':'manager'
583        }
584
585Above, there would be no ``Employee.manager_data``
586attribute, even though the ``employee`` table has a ``manager_data`` column.
587A query against ``Manager`` will include this column in the query, as well
588as an IN clause to limit rows only to ``Manager`` objects:
589
590.. sourcecode:: python+sql
591
592    session.query(Manager).all()
593    {opensql}
594    SELECT
595        employee.id AS employee_id,
596        employee.name AS employee_name,
597        employee.type AS employee_type,
598        employee.manager_data AS employee_manager_data
599    FROM employee
600    WHERE employee.type IN (?)
601
602    ('manager',)
603
604However, in a similar way to that of joined table inheritance, a query
605against ``Employee`` will only query for columns mapped to ``Employee``:
606
607.. sourcecode:: python+sql
608
609    session.query(Employee).all()
610    {opensql}
611    SELECT employee.id AS employee_id,
612        employee.name AS employee_name,
613        employee.type AS employee_type
614    FROM employee
615
616If we get back an instance of ``Manager`` from our result, accessing
617additional columns only mapped to ``Manager`` emits a lazy load
618for those columns, in a similar way to joined inheritance::
619
620    SELECT employee.manager_data AS employee_manager_data
621    FROM employee
622    WHERE employee.id = ? AND employee.type IN (?)
623
624The :func:`.orm.with_polymorphic` function serves a similar role as  joined
625inheritance in the case of single inheritance; it allows both for eager loading
626of subclass attributes as well as specification of subclasses in a query,
627just without the overhead of using OUTER JOIN::
628
629    employee_poly = with_polymorphic(Employee, '*')
630
631    q = session.query(employee_poly).filter(
632        or_(
633            employee_poly.name == 'a',
634            employee_poly.Manager.manager_data == 'b'
635        )
636    )
637
638Above, our query remains against a single table however we can refer to the
639columns present in ``Manager`` or ``Engineer`` using the "polymorphic" namespace.
640Since we specified ``"*"`` for the entities, both ``Engineer`` and
641``Manager`` will be loaded at once.  SQL emitted would be:
642
643.. sourcecode:: python+sql
644
645    q.all()
646    {opensql}
647    SELECT
648        employee.id AS employee_id, employee.name AS employee_name,
649        employee.type AS employee_type,
650        employee.manager_data AS employee_manager_data,
651        employee.engineer_info AS employee_engineer_info
652    FROM employee
653    WHERE employee.name = :name_1
654    OR employee.manager_data = :manager_data_1
655
656
657Inheritance Loading API
658-----------------------
659
660.. autofunction:: sqlalchemy.orm.with_polymorphic
661