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