codekingpro/portable-devtools
115k
1# orm/mapper.py
2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7# mypy: allow-untyped-defs, allow-untyped-calls
8
9"""Logic to map Python classes to and from selectables.
10
11Defines the :class:`~sqlalchemy.orm.mapper.Mapper` class, the central
12configurational unit which associates a class with a database table.
13
14This is a semi-private module; the main configurational API of the ORM is
15available in :class:`~sqlalchemy.orm.`.
16
17"""
18from __future__ import annotations
19
20from collections import deque
21from functools import reduce
22from itertools import chain
23import sys
24import threading
25from typing import Any
26from typing import Callable
27from typing import cast
28from typing import Collection
29from typing import Deque
30from typing import Dict
31from typing import FrozenSet
32from typing import Generic
33from typing import Iterable
34from typing import Iterator
35from typing import List
36from typing import Mapping
37from typing import Optional
38from typing import Sequence
39from typing import Set
40from typing import Tuple
41from typing import Type
42from typing import TYPE_CHECKING
43from typing import TypeVar
44from typing import Union
45import weakref
46
47from . import attributes
48from . import exc as orm_exc
49from . import instrumentation
50from . import loading
51from . import properties
52from . import util as orm_util
53from ._typing import _O
54from .base import _class_to_mapper
55from .base import _parse_mapper_argument
56from .base import _state_mapper
57from .base import PassiveFlag
58from .base import state_str
59from .interfaces import _MappedAttribute
60from .interfaces import EXT_SKIP
61from .interfaces import InspectionAttr
62from .interfaces import MapperProperty
63from .interfaces import ORMEntityColumnsClauseRole
64from .interfaces import ORMFromClauseRole
65from .interfaces import StrategizedProperty
66from .path_registry import PathRegistry
67from .. import event
68from .. import exc as sa_exc
69from .. import inspection
70from .. import log
71from .. import schema
72from .. import sql
73from .. import util
74from ..event import dispatcher
75from ..event import EventTarget
76from ..sql import base as sql_base
77from ..sql import coercions
78from ..sql import expression
79from ..sql import operators
80from ..sql import roles
81from ..sql import TableClause
82from ..sql import util as sql_util
83from ..sql import visitors
84from ..sql.cache_key import MemoizedHasCacheKey
85from ..sql.elements import KeyedColumnElement
86from ..sql.schema import Column
87from ..sql.schema import Table
88from ..sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL
89from ..util import HasMemoized
90from ..util import HasMemoized_ro_memoized_attribute
91from ..util.typing import Literal
92
93if TYPE_CHECKING:
94 from ._typing import _IdentityKeyType
95 from ._typing import _InstanceDict
96 from ._typing import _ORMColumnExprArgument
97 from ._typing import _RegistryType
98 from .decl_api import registry
99 from .dependency import DependencyProcessor
100 from .descriptor_props import CompositeProperty
101 from .descriptor_props import SynonymProperty
102 from .events import MapperEvents
103 from .instrumentation import ClassManager
104 from .path_registry import CachingEntityRegistry
105 from .properties import ColumnProperty
106 from .relationships import RelationshipProperty
107 from .state import InstanceState
108 from .util import ORMAdapter
109 from ..engine import Row
110 from ..engine import RowMapping
111 from ..sql._typing import _ColumnExpressionArgument
112 from ..sql._typing import _EquivalentColumnMap
113 from ..sql.base import ReadOnlyColumnCollection
114 from ..sql.elements import ColumnClause
115 from ..sql.elements import ColumnElement
116 from ..sql.selectable import FromClause
117 from ..util import OrderedSet
118
119
120_T = TypeVar("_T", bound=Any)
121_MP = TypeVar("_MP", bound="MapperProperty[Any]")
122_Fn = TypeVar("_Fn", bound="Callable[..., Any]")
123
124
125_WithPolymorphicArg = Union[
126 Literal["*"],
127 Tuple[
128 Union[Literal["*"], Sequence[Union["Mapper[Any]", Type[Any]]]],
129 Optional["FromClause"],
130 ],
131 Sequence[Union["Mapper[Any]", Type[Any]]],
132]
133
134
135_mapper_registries: weakref.WeakKeyDictionary[_RegistryType, bool] = (
136 weakref.WeakKeyDictionary()
137)
138
139
140def _all_registries() -> Set[registry]:
141 with _CONFIGURE_MUTEX:
142 return set(_mapper_registries)
143
144
145def _unconfigured_mappers() -> Iterator[Mapper[Any]]:
146 for reg in _all_registries():
147 yield from reg._mappers_to_configure()
148
149
150_already_compiling = False
151
152
153# a constant returned by _get_attr_by_column to indicate
154# this mapper is not handling an attribute for a particular
155# column
156NO_ATTRIBUTE = util.symbol("NO_ATTRIBUTE")
157
158# lock used to synchronize the "mapper configure" step
159_CONFIGURE_MUTEX = threading.RLock()
160
161
162@inspection._self_inspects
163@log.class_logger
164class Mapper(
165 ORMFromClauseRole,
166 ORMEntityColumnsClauseRole[_O],
167 MemoizedHasCacheKey,
168 InspectionAttr,
169 log.Identified,
170 inspection.Inspectable["Mapper[_O]"],
171 EventTarget,
172 Generic[_O],
173):
174 """Defines an association between a Python class and a database table or
175 other relational structure, so that ORM operations against the class may
176 proceed.
177
178 The :class:`_orm.Mapper` object is instantiated using mapping methods
179 present on the :class:`_orm.registry` object. For information
180 about instantiating new :class:`_orm.Mapper` objects, see
181 :ref:`orm_mapping_classes_toplevel`.
182
183 """
184
185 dispatch: dispatcher[Mapper[_O]]
186
187 _dispose_called = False
188 _configure_failed: Any = False
189 _ready_for_configure = False
190
191 @util.deprecated_params(
192 non_primary=(
193 "1.3",
194 "The :paramref:`.mapper.non_primary` parameter is deprecated, "
195 "and will be removed in a future release. The functionality "
196 "of non primary mappers is now better suited using the "
197 ":class:`.AliasedClass` construct, which can also be used "
198 "as the target of a :func:`_orm.relationship` in 1.3.",
199 ),
200 )
201 def __init__(
202 self,
203 class_: Type[_O],
204 local_table: Optional[FromClause] = None,
205 properties: Optional[Mapping[str, MapperProperty[Any]]] = None,
206 primary_key: Optional[Iterable[_ORMColumnExprArgument[Any]]] = None,
207 non_primary: bool = False,
208 inherits: Optional[Union[Mapper[Any], Type[Any]]] = None,
209 inherit_condition: Optional[_ColumnExpressionArgument[bool]] = None,
210 inherit_foreign_keys: Optional[
211 Sequence[_ORMColumnExprArgument[Any]]
212 ] = None,
213 always_refresh: bool = False,
214 version_id_col: Optional[_ORMColumnExprArgument[Any]] = None,
215 version_id_generator: Optional[
216 Union[Literal[False], Callable[[Any], Any]]
217 ] = None,
218 polymorphic_on: Optional[
219 Union[_ORMColumnExprArgument[Any], str, MapperProperty[Any]]
220 ] = None,
221 _polymorphic_map: Optional[Dict[Any, Mapper[Any]]] = None,
222 polymorphic_identity: Optional[Any] = None,
223 concrete: bool = False,
224 with_polymorphic: Optional[_WithPolymorphicArg] = None,
225 polymorphic_abstract: bool = False,
226 polymorphic_load: Optional[Literal["selectin", "inline"]] = None,
227 allow_partial_pks: bool = True,
228 batch: bool = True,
229 column_prefix: Optional[str] = None,
230 include_properties: Optional[Sequence[str]] = None,
231 exclude_properties: Optional[Sequence[str]] = None,
232 passive_updates: bool = True,
233 passive_deletes: bool = False,
234 confirm_deleted_rows: bool = True,
235 eager_defaults: Literal[True, False, "auto"] = "auto",
236 legacy_is_orphan: bool = False,
237 _compiled_cache_size: int = 100,
238 ):
239 r"""Direct constructor for a new :class:`_orm.Mapper` object.
240
241 The :class:`_orm.Mapper` constructor is not called directly, and
242 is normally invoked through the
243 use of the :class:`_orm.registry` object through either the
244 :ref:`Declarative <orm_declarative_mapping>` or
245 :ref:`Imperative <orm_imperative_mapping>` mapping styles.
246
247 .. versionchanged:: 2.0 The public facing ``mapper()`` function is
248 removed; for a classical mapping configuration, use the
249 :meth:`_orm.registry.map_imperatively` method.
250
251 Parameters documented below may be passed to either the
252 :meth:`_orm.registry.map_imperatively` method, or may be passed in the
253 ``__mapper_args__`` declarative class attribute described at
254 :ref:`orm_declarative_mapper_options`.
255
256 :param class\_: The class to be mapped. When using Declarative,
257 this argument is automatically passed as the declared class
258 itself.
259
260 :param local_table: The :class:`_schema.Table` or other
261 :class:`_sql.FromClause` (i.e. selectable) to which the class is
262 mapped. May be ``None`` if this mapper inherits from another mapper
263 using single-table inheritance. When using Declarative, this
264 argument is automatically passed by the extension, based on what is
265 configured via the :attr:`_orm.DeclarativeBase.__table__` attribute
266 or via the :class:`_schema.Table` produced as a result of
267 the :attr:`_orm.DeclarativeBase.__tablename__` attribute being
268 present.
269
270 :param polymorphic_abstract: Indicates this class will be mapped in a
271 polymorphic hierarchy, but not directly instantiated. The class is
272 mapped normally, except that it has no requirement for a
273 :paramref:`_orm.Mapper.polymorphic_identity` within an inheritance
274 hierarchy. The class however must be part of a polymorphic
275 inheritance scheme which uses
276 :paramref:`_orm.Mapper.polymorphic_on` at the base.
277
278 .. versionadded:: 2.0
279
280 .. seealso::
281
282 :ref:`orm_inheritance_abstract_poly`
283
284 :param always_refresh: If True, all query operations for this mapped
285 class will overwrite all data within object instances that already
286 exist within the session, erasing any in-memory changes with
287 whatever information was loaded from the database. Usage of this
288 flag is highly discouraged; as an alternative, see the method
289 :meth:`_query.Query.populate_existing`.
290
291 :param allow_partial_pks: Defaults to True. Indicates that a
292 composite primary key with some NULL values should be considered as
293 possibly existing within the database. This affects whether a
294 mapper will assign an incoming row to an existing identity, as well
295 as if :meth:`.Session.merge` will check the database first for a
296 particular primary key value. A "partial primary key" can occur if
297 one has mapped to an OUTER JOIN, for example.
298
299 The :paramref:`.orm.Mapper.allow_partial_pks` parameter also
300 indicates to the ORM relationship lazy loader, when loading a
301 many-to-one related object, if a composite primary key that has
302 partial NULL values should result in an attempt to load from the
303 database, or if a load attempt is not necessary.
304
305 .. versionadded:: 2.0.36 :paramref:`.orm.Mapper.allow_partial_pks`
306 is consulted by the relationship lazy loader strategy, such that
307 when set to False, a SELECT for a composite primary key that
308 has partial NULL values will not be emitted.
309
310 :param batch: Defaults to ``True``, indicating that save operations
311 of multiple entities can be batched together for efficiency.
312 Setting to False indicates
313 that an instance will be fully saved before saving the next
314 instance. This is used in the extremely rare case that a
315 :class:`.MapperEvents` listener requires being called
316 in between individual row persistence operations.
317
318 :param column_prefix: A string which will be prepended
319 to the mapped attribute name when :class:`_schema.Column`
320 objects are automatically assigned as attributes to the
321 mapped class. Does not affect :class:`.Column` objects that
322 are mapped explicitly in the :paramref:`.Mapper.properties`
323 dictionary.
324
325 This parameter is typically useful with imperative mappings
326 that keep the :class:`.Table` object separate. Below, assuming
327 the ``user_table`` :class:`.Table` object has columns named
328 ``user_id``, ``user_name``, and ``password``::
329
330 class User(Base):
331 __table__ = user_table
332 __mapper_args__ = {"column_prefix": "_"}
333
334 The above mapping will assign the ``user_id``, ``user_name``, and
335 ``password`` columns to attributes named ``_user_id``,
336 ``_user_name``, and ``_password`` on the mapped ``User`` class.
337
338 The :paramref:`.Mapper.column_prefix` parameter is uncommon in
339 modern use. For dealing with reflected tables, a more flexible
340 approach to automating a naming scheme is to intercept the
341 :class:`.Column` objects as they are reflected; see the section
342 :ref:`mapper_automated_reflection_schemes` for notes on this usage
343 pattern.
344
345 :param concrete: If True, indicates this mapper should use concrete
346 table inheritance with its parent mapper.
347
348 See the section :ref:`concrete_inheritance` for an example.
349
350 :param confirm_deleted_rows: defaults to True; when a DELETE occurs
351 of one more rows based on specific primary keys, a warning is
352 emitted when the number of rows matched does not equal the number
353 of rows expected. This parameter may be set to False to handle the
354 case where database ON DELETE CASCADE rules may be deleting some of
355 those rows automatically. The warning may be changed to an
356 exception in a future release.
357
358 :param eager_defaults: if True, the ORM will immediately fetch the
359 value of server-generated default values after an INSERT or UPDATE,
360 rather than leaving them as expired to be fetched on next access.
361 This can be used for event schemes where the server-generated values
362 are needed immediately before the flush completes.
363
364 The fetch of values occurs either by using ``RETURNING`` inline
365 with the ``INSERT`` or ``UPDATE`` statement, or by adding an
366 additional ``SELECT`` statement subsequent to the ``INSERT`` or
367 ``UPDATE``, if the backend does not support ``RETURNING``.
368
369 The use of ``RETURNING`` is extremely performant in particular for
370 ``INSERT`` statements where SQLAlchemy can take advantage of
371 :ref:`insertmanyvalues <engine_insertmanyvalues>`, whereas the use of
372 an additional ``SELECT`` is relatively poor performing, adding
373 additional SQL round trips which would be unnecessary if these new
374 attributes are not to be accessed in any case.
375
376 For this reason, :paramref:`.Mapper.eager_defaults` defaults to the
377 string value ``"auto"``, which indicates that server defaults for
378 INSERT should be fetched using ``RETURNING`` if the backing database
379 supports it and if the dialect in use supports "insertmanyreturning"
380 for an INSERT statement. If the backing database does not support
381 ``RETURNING`` or "insertmanyreturning" is not available, server
382 defaults will not be fetched.
383
384 .. versionchanged:: 2.0.0rc1 added the "auto" option for
385 :paramref:`.Mapper.eager_defaults`
386
387 .. seealso::
388
389 :ref:`orm_server_defaults`
390
391 .. versionchanged:: 2.0.0 RETURNING now works with multiple rows
392 INSERTed at once using the
393 :ref:`insertmanyvalues <engine_insertmanyvalues>` feature, which
394 among other things allows the :paramref:`.Mapper.eager_defaults`
395 feature to be very performant on supporting backends.
396
397 :param exclude_properties: A list or set of string column names to
398 be excluded from mapping.
399
400 .. seealso::
401
402 :ref:`include_exclude_cols`
403
404 :param include_properties: An inclusive list or set of string column
405 names to map.
406
407 .. seealso::
408
409 :ref:`include_exclude_cols`
410
411 :param inherits: A mapped class or the corresponding
412 :class:`_orm.Mapper`
413 of one indicating a superclass to which this :class:`_orm.Mapper`
414 should *inherit* from. The mapped class here must be a subclass
415 of the other mapper's class. When using Declarative, this argument
416 is passed automatically as a result of the natural class
417 hierarchy of the declared classes.
418
419 .. seealso::
420
421 :ref:`inheritance_toplevel`
422
423 :param inherit_condition: For joined table inheritance, a SQL
424 expression which will
425 define how the two tables are joined; defaults to a natural join
426 between the two tables.
427
428 :param inherit_foreign_keys: When ``inherit_condition`` is used and
429 the columns present are missing a :class:`_schema.ForeignKey`
430 configuration, this parameter can be used to specify which columns
431 are "foreign". In most cases can be left as ``None``.
432
433 :param legacy_is_orphan: Boolean, defaults to ``False``.
434 When ``True``, specifies that "legacy" orphan consideration
435 is to be applied to objects mapped by this mapper, which means
436 that a pending (that is, not persistent) object is auto-expunged
437 from an owning :class:`.Session` only when it is de-associated
438 from *all* parents that specify a ``delete-orphan`` cascade towards
439 this mapper. The new default behavior is that the object is
440 auto-expunged when it is de-associated with *any* of its parents
441 that specify ``delete-orphan`` cascade. This behavior is more
442 consistent with that of a persistent object, and allows behavior to
443 be consistent in more scenarios independently of whether or not an
444 orphan object has been flushed yet or not.
445
446 See the change note and example at :ref:`legacy_is_orphan_addition`
447 for more detail on this change.
448
449 :param non_primary: Specify that this :class:`_orm.Mapper`
450 is in addition
451 to the "primary" mapper, that is, the one used for persistence.
452 The :class:`_orm.Mapper` created here may be used for ad-hoc
453 mapping of the class to an alternate selectable, for loading
454 only.
455
456 .. seealso::
457
458 :ref:`relationship_aliased_class` - the new pattern that removes
459 the need for the :paramref:`_orm.Mapper.non_primary` flag.
460
461 :param passive_deletes: Indicates DELETE behavior of foreign key
462 columns when a joined-table inheritance entity is being deleted.
463 Defaults to ``False`` for a base mapper; for an inheriting mapper,
464 defaults to ``False`` unless the value is set to ``True``
465 on the superclass mapper.
466
467 When ``True``, it is assumed that ON DELETE CASCADE is configured
468 on the foreign key relationships that link this mapper's table
469 to its superclass table, so that when the unit of work attempts
470 to delete the entity, it need only emit a DELETE statement for the
471 superclass table, and not this table.
472
473 When ``False``, a DELETE statement is emitted for this mapper's
474 table individually. If the primary key attributes local to this
475 table are unloaded, then a SELECT must be emitted in order to
476 validate these attributes; note that the primary key columns
477 of a joined-table subclass are not part of the "primary key" of
478 the object as a whole.
479
480 Note that a value of ``True`` is **always** forced onto the
481 subclass mappers; that is, it's not possible for a superclass
482 to specify passive_deletes without this taking effect for
483 all subclass mappers.
484
485 .. seealso::
486
487 :ref:`passive_deletes` - description of similar feature as
488 used with :func:`_orm.relationship`
489
490 :paramref:`.mapper.passive_updates` - supporting ON UPDATE
491 CASCADE for joined-table inheritance mappers
492
493 :param passive_updates: Indicates UPDATE behavior of foreign key
494 columns when a primary key column changes on a joined-table
495 inheritance mapping. Defaults to ``True``.
496
497 When True, it is assumed that ON UPDATE CASCADE is configured on
498 the foreign key in the database, and that the database will handle
499 propagation of an UPDATE from a source column to dependent columns
500 on joined-table rows.
501
502 When False, it is assumed that the database does not enforce
503 referential integrity and will not be issuing its own CASCADE
504 operation for an update. The unit of work process will
505 emit an UPDATE statement for the dependent columns during a
506 primary key change.
507
508 .. seealso::
509
510 :ref:`passive_updates` - description of a similar feature as
511 used with :func:`_orm.relationship`
512
513 :paramref:`.mapper.passive_deletes` - supporting ON DELETE
514 CASCADE for joined-table inheritance mappers
515
516 :param polymorphic_load: Specifies "polymorphic loading" behavior
517 for a subclass in an inheritance hierarchy (joined and single
518 table inheritance only). Valid values are:
519
520 * "'inline'" - specifies this class should be part of
521 the "with_polymorphic" mappers, e.g. its columns will be included
522 in a SELECT query against the base.
523
524 * "'selectin'" - specifies that when instances of this class
525 are loaded, an additional SELECT will be emitted to retrieve
526 the columns specific to this subclass. The SELECT uses
527 IN to fetch multiple subclasses at once.
528
529 .. versionadded:: 1.2
530
531 .. seealso::
532
533 :ref:`with_polymorphic_mapper_config`
534
535 :ref:`polymorphic_selectin`
536
537 :param polymorphic_on: Specifies the column, attribute, or
538 SQL expression used to determine the target class for an
539 incoming row, when inheriting classes are present.
540
541 May be specified as a string attribute name, or as a SQL
542 expression such as a :class:`_schema.Column` or in a Declarative
543 mapping a :func:`_orm.mapped_column` object. It is typically
544 expected that the SQL expression corresponds to a column in the
545 base-most mapped :class:`.Table`::
546
547 class Employee(Base):
548 __tablename__ = "employee"
549
550 id: Mapped[int] = mapped_column(primary_key=True)
551 discriminator: Mapped[str] = mapped_column(String(50))
552
553 __mapper_args__ = {
554 "polymorphic_on": discriminator,
555 "polymorphic_identity": "employee",
556 }
557
558 It may also be specified
559 as a SQL expression, as in this example where we
560 use the :func:`.case` construct to provide a conditional
561 approach::
562
563 class Employee(Base):
564 __tablename__ = "employee"
565
566 id: Mapped[int] = mapped_column(primary_key=True)
567 discriminator: Mapped[str] = mapped_column(String(50))
568
569 __mapper_args__ = {
570 "polymorphic_on": case(
571 (discriminator == "EN", "engineer"),
572 (discriminator == "MA", "manager"),
573 else_="employee",
574 ),
575 "polymorphic_identity": "employee",
576 }
577
578 It may also refer to any attribute using its string name,
579 which is of particular use when using annotated column
580 configurations::
581
582 class Employee(Base):
583 __tablename__ = "employee"
584
585 id: Mapped[int] = mapped_column(primary_key=True)
586 discriminator: Mapped[str]
587
588 __mapper_args__ = {
589 "polymorphic_on": "discriminator",
590 "polymorphic_identity": "employee",
591 }
592
593 When setting ``polymorphic_on`` to reference an
594 attribute or expression that's not present in the
595 locally mapped :class:`_schema.Table`, yet the value
596 of the discriminator should be persisted to the database,
597 the value of the
598 discriminator is not automatically set on new
599 instances; this must be handled by the user,
600 either through manual means or via event listeners.
601 A typical approach to establishing such a listener
602 looks like::
603
604 from sqlalchemy import event
605 from sqlalchemy.orm import object_mapper
606
607
608 @event.listens_for(Employee, "init", propagate=True)
609 def set_identity(instance, *arg, **kw):
610 mapper = object_mapper(instance)
611 instance.discriminator = mapper.polymorphic_identity
612
613 Where above, we assign the value of ``polymorphic_identity``
614 for the mapped class to the ``discriminator`` attribute,
615 thus persisting the value to the ``discriminator`` column
616 in the database.
617
618 .. warning::
619
620 Currently, **only one discriminator column may be set**, typically
621 on the base-most class in the hierarchy. "Cascading" polymorphic
622 columns are not yet supported.
623
624 .. seealso::
625
626 :ref:`inheritance_toplevel`
627
628 :param polymorphic_identity: Specifies the value which
629 identifies this particular class as returned by the column expression
630 referred to by the :paramref:`_orm.Mapper.polymorphic_on` setting. As
631 rows are received, the value corresponding to the
632 :paramref:`_orm.Mapper.polymorphic_on` column expression is compared
633 to this value, indicating which subclass should be used for the newly
634 reconstructed object.
635
636 .. seealso::
637
638 :ref:`inheritance_toplevel`
639
640 :param properties: A dictionary mapping the string names of object
641 attributes to :class:`.MapperProperty` instances, which define the
642 persistence behavior of that attribute. Note that
643 :class:`_schema.Column`
644 objects present in
645 the mapped :class:`_schema.Table` are automatically placed into
646 ``ColumnProperty`` instances upon mapping, unless overridden.
647 When using Declarative, this argument is passed automatically,
648 based on all those :class:`.MapperProperty` instances declared
649 in the declared class body.
650
651 .. seealso::
652
653 :ref:`orm_mapping_properties` - in the
654 :ref:`orm_mapping_classes_toplevel`
655
656 :param primary_key: A list of :class:`_schema.Column`
657 objects, or alternatively string names of attribute names which
658 refer to :class:`_schema.Column`, which define
659 the primary key to be used against this mapper's selectable unit.
660 This is normally simply the primary key of the ``local_table``, but
661 can be overridden here.
662
663 .. versionchanged:: 2.0.2 :paramref:`_orm.Mapper.primary_key`
664 arguments may be indicated as string attribute names as well.
665
666 .. seealso::
667
668 :ref:`mapper_primary_key` - background and example use
669
670 :param version_id_col: A :class:`_schema.Column`
671 that will be used to keep a running version id of rows
672 in the table. This is used to detect concurrent updates or
673 the presence of stale data in a flush. The methodology is to
674 detect if an UPDATE statement does not match the last known
675 version id, a
676 :class:`~sqlalchemy.orm.exc.StaleDataError` exception is
677 thrown.
678 By default, the column must be of :class:`.Integer` type,
679 unless ``version_id_generator`` specifies an alternative version
680 generator.
681
682 .. seealso::
683
684 :ref:`mapper_version_counter` - discussion of version counting
685 and rationale.
686
687 :param version_id_generator: Define how new version ids should
688 be generated. Defaults to ``None``, which indicates that
689 a simple integer counting scheme be employed. To provide a custom
690 versioning scheme, provide a callable function of the form::
691
692 def generate_version(version):
693 return next_version
694
695 Alternatively, server-side versioning functions such as triggers,
696 or programmatic versioning schemes outside of the version id
697 generator may be used, by specifying the value ``False``.
698 Please see :ref:`server_side_version_counter` for a discussion
699 of important points when using this option.
700
701 .. seealso::
702
703 :ref:`custom_version_counter`
704
705 :ref:`server_side_version_counter`
706
707
708 :param with_polymorphic: A tuple in the form ``(<classes>,
709 <selectable>)`` indicating the default style of "polymorphic"
710 loading, that is, which tables are queried at once. <classes> is
711 any single or list of mappers and/or classes indicating the
712 inherited classes that should be loaded at once. The special value
713 ``'*'`` may be used to indicate all descending classes should be
714 loaded immediately. The second tuple argument <selectable>
715 indicates a selectable that will be used to query for multiple
716 classes.
717
718 The :paramref:`_orm.Mapper.polymorphic_load` parameter may be
719 preferable over the use of :paramref:`_orm.Mapper.with_polymorphic`
720 in modern mappings to indicate a per-subclass technique of
721 indicating polymorphic loading styles.
722
723 .. seealso::
724
725 :ref:`with_polymorphic_mapper_config`
726
727 """
728 self.class_ = util.assert_arg_type(class_, type, "class_")
729 self._sort_key = "%s.%s" % (
730 self.class_.__module__,
731 self.class_.__name__,
732 )
733
734 self._primary_key_argument = util.to_list(primary_key)
735 self.non_primary = non_primary
736
737 self.always_refresh = always_refresh
738
739 if isinstance(version_id_col, MapperProperty):
740 self.version_id_prop = version_id_col
741 self.version_id_col = None
742 else:
743 self.version_id_col = (
744 coercions.expect(
745 roles.ColumnArgumentOrKeyRole,
746 version_id_col,
747 argname="version_id_col",
748 )
749 if version_id_col is not None
750 else None
751 )
752
753 if version_id_generator is False:
754 self.version_id_generator = False
755 elif version_id_generator is None:
756 self.version_id_generator = lambda x: (x or 0) + 1
757 else:
758 self.version_id_generator = version_id_generator
759
760 self.concrete = concrete
761 self.single = False
762
763 if inherits is not None:
764 self.inherits = _parse_mapper_argument(inherits)
765 else:
766 self.inherits = None
767
768 if local_table is not None:
769 self.local_table = coercions.expect(
770 roles.StrictFromClauseRole,
771 local_table,
772 disable_inspection=True,
773 argname="local_table",
774 )
775 elif self.inherits:
776 # note this is a new flow as of 2.0 so that
777 # .local_table need not be Optional
778 self.local_table = self.inherits.local_table
779 self.single = True
780 else:
781 raise sa_exc.ArgumentError(
782 f"Mapper[{self.class_.__name__}(None)] has None for a "
783 "primary table argument and does not specify 'inherits'"
784 )
785
786 if inherit_condition is not None:
787 self.inherit_condition = coercions.expect(
788 roles.OnClauseRole, inherit_condition
789 )
790 else:
791 self.inherit_condition = None
792
793 self.inherit_foreign_keys = inherit_foreign_keys
794 self._init_properties = dict(properties) if properties else {}
795 self._delete_orphans = []
796 self.batch = batch
797 self.eager_defaults = eager_defaults
798 self.column_prefix = column_prefix
799
800 # interim - polymorphic_on is further refined in
801 # _configure_polymorphic_setter
802 self.polymorphic_on = (
803 coercions.expect( # type: ignore
804 roles.ColumnArgumentOrKeyRole,
805 polymorphic_on,
806 argname="polymorphic_on",
807 )
808 if polymorphic_on is not None
809 else None
810 )
811 self.polymorphic_abstract = polymorphic_abstract
812 self._dependency_processors = []
813 self.validators = util.EMPTY_DICT
814 self.passive_updates = passive_updates
815 self.passive_deletes = passive_deletes
816 self.legacy_is_orphan = legacy_is_orphan
817 self._clause_adapter = None
818 self._requires_row_aliasing = False
819 self._inherits_equated_pairs = None
820 self._memoized_values = {}
821 self._compiled_cache_size = _compiled_cache_size
822 self._reconstructor = None
823 self.allow_partial_pks = allow_partial_pks
824
825 if self.inherits and not self.concrete:
826 self.confirm_deleted_rows = False
827 else:
828 self.confirm_deleted_rows = confirm_deleted_rows
829
830 self._set_with_polymorphic(with_polymorphic)
831 self.polymorphic_load = polymorphic_load
832
833 # our 'polymorphic identity', a string name that when located in a
834 # result set row indicates this Mapper should be used to construct
835 # the object instance for that row.
836 self.polymorphic_identity = polymorphic_identity
837
838 # a dictionary of 'polymorphic identity' names, associating those
839 # names with Mappers that will be used to construct object instances
840 # upon a select operation.
841 if _polymorphic_map is None:
842 self.polymorphic_map = {}
843 else:
844 self.polymorphic_map = _polymorphic_map
845
846 if include_properties is not None:
847 self.include_properties = util.to_set(include_properties)
848 else:
849 self.include_properties = None
850 if exclude_properties:
851 self.exclude_properties = util.to_set(exclude_properties)
852 else:
853 self.exclude_properties = None
854
855 # prevent this mapper from being constructed
856 # while a configure_mappers() is occurring (and defer a
857 # configure_mappers() until construction succeeds)
858 with _CONFIGURE_MUTEX:
859 cast("MapperEvents", self.dispatch._events)._new_mapper_instance(
860 class_, self
861 )
862 self._configure_inheritance()
863 self._configure_class_instrumentation()
864 self._configure_properties()
865 self._configure_polymorphic_setter()
866 self._configure_pks()
867 self.registry._flag_new_mapper(self)
868 self._log("constructed")
869 self._expire_memoizations()
870
871 self.dispatch.after_mapper_constructed(self, self.class_)
872
873 def _prefer_eager_defaults(self, dialect, table):
874 if self.eager_defaults == "auto":
875 if not table.implicit_returning:
876 return False
877
878 return (
879 table in self._server_default_col_keys
880 and dialect.insert_executemany_returning
881 )
882 else:
883 return self.eager_defaults
884
885 def _gen_cache_key(self, anon_map, bindparams):
886 return (self,)
887
888 # ### BEGIN
889 # ATTRIBUTE DECLARATIONS START HERE
890
891 is_mapper = True
892 """Part of the inspection API."""
893
894 represents_outer_join = False
895
896 registry: _RegistryType
897
898 @property
899 def mapper(self) -> Mapper[_O]:
900 """Part of the inspection API.
901
902 Returns self.
903
904 """
905 return self
906
907 @property
908 def entity(self):
909 r"""Part of the inspection API.
910
911 Returns self.class\_.
912
913 """
914 return self.class_
915
916 class_: Type[_O]
917 """The class to which this :class:`_orm.Mapper` is mapped."""
918
919 _identity_class: Type[_O]
920
921 _delete_orphans: List[Tuple[str, Type[Any]]]
922 _dependency_processors: List[DependencyProcessor]
923 _memoized_values: Dict[Any, Callable[[], Any]]
924 _inheriting_mappers: util.WeakSequence[Mapper[Any]]
925 _all_tables: Set[TableClause]
926 _polymorphic_attr_key: Optional[str]
927
928 _pks_by_table: Dict[FromClause, OrderedSet[ColumnClause[Any]]]
929 _cols_by_table: Dict[FromClause, OrderedSet[ColumnElement[Any]]]
930
931 _props: util.OrderedDict[str, MapperProperty[Any]]
932 _init_properties: Dict[str, MapperProperty[Any]]
933
934 _columntoproperty: _ColumnMapping
935
936 _set_polymorphic_identity: Optional[Callable[[InstanceState[_O]], None]]
937 _validate_polymorphic_identity: Optional[
938 Callable[[Mapper[_O], InstanceState[_O], _InstanceDict], None]
939 ]
940
941 tables: Sequence[TableClause]
942 """A sequence containing the collection of :class:`_schema.Table`
943 or :class:`_schema.TableClause` objects which this :class:`_orm.Mapper`
944 is aware of.
945
946 If the mapper is mapped to a :class:`_expression.Join`, or an
947 :class:`_expression.Alias`
948 representing a :class:`_expression.Select`, the individual
949 :class:`_schema.Table`
950 objects that comprise the full construct will be represented here.
951
952 This is a *read only* attribute determined during mapper construction.
953 Behavior is undefined if directly modified.
954
955 """
956
957 validators: util.immutabledict[str, Tuple[str, Dict[str, Any]]]
958 """An immutable dictionary of attributes which have been decorated
959 using the :func:`_orm.validates` decorator.
960
961 The dictionary contains string attribute names as keys
962 mapped to the actual validation method.
963
964 """
965
966 always_refresh: bool
967 allow_partial_pks: bool
968 version_id_col: Optional[ColumnElement[Any]]
969
970 with_polymorphic: Optional[
971 Tuple[
972 Union[Literal["*"], Sequence[Union[Mapper[Any], Type[Any]]]],
973 Optional[FromClause],
974 ]
975 ]
976
977 version_id_generator: Optional[Union[Literal[False], Callable[[Any], Any]]]
978
979 local_table: FromClause
980 """The immediate :class:`_expression.FromClause` to which this
981 :class:`_orm.Mapper` refers.
982
983 Typically is an instance of :class:`_schema.Table`, may be any
984 :class:`.FromClause`.
985
986 The "local" table is the
987 selectable that the :class:`_orm.Mapper` is directly responsible for
988 managing from an attribute access and flush perspective. For
989 non-inheriting mappers, :attr:`.Mapper.local_table` will be the same
990 as :attr:`.Mapper.persist_selectable`. For inheriting mappers,
991 :attr:`.Mapper.local_table` refers to the specific portion of
992 :attr:`.Mapper.persist_selectable` that includes the columns to which
993 this :class:`.Mapper` is loading/persisting, such as a particular
994 :class:`.Table` within a join.
995
996 .. seealso::
997
998 :attr:`_orm.Mapper.persist_selectable`.
999
1000 :attr:`_orm.Mapper.selectable`.
1001
1002 """
1003
1004 persist_selectable: FromClause
1005 """The :class:`_expression.FromClause` to which this :class:`_orm.Mapper`
1006 is mapped.
1007
1008 Typically is an instance of :class:`_schema.Table`, may be any
1009 :class:`.FromClause`.
1010
1011 The :attr:`_orm.Mapper.persist_selectable` is similar to
1012 :attr:`.Mapper.local_table`, but represents the :class:`.FromClause` that
1013 represents the inheriting class hierarchy overall in an inheritance
1014 scenario.
1015
1016 :attr.`.Mapper.persist_selectable` is also separate from the
1017 :attr:`.Mapper.selectable` attribute, the latter of which may be an
1018 alternate subquery used for selecting columns.
1019 :attr.`.Mapper.persist_selectable` is oriented towards columns that
1020 will be written on a persist operation.
1021
1022 .. seealso::
1023
1024 :attr:`_orm.Mapper.selectable`.
1025
1026 :attr:`_orm.Mapper.local_table`.
1027
1028 """
1029
1030 inherits: Optional[Mapper[Any]]
1031 """References the :class:`_orm.Mapper` which this :class:`_orm.Mapper`
1032 inherits from, if any.
1033
1034 """
1035
1036 inherit_condition: Optional[ColumnElement[bool]]
1037
1038 configured: bool = False
1039 """Represent ``True`` if this :class:`_orm.Mapper` has been configured.
1040
1041 This is a *read only* attribute determined during mapper construction.
1042 Behavior is undefined if directly modified.
1043
1044 .. seealso::
1045
1046 :func:`.configure_mappers`.
1047
1048 """
1049
1050 concrete: bool
1051 """Represent ``True`` if this :class:`_orm.Mapper` is a concrete
1052 inheritance mapper.
1053
1054 This is a *read only* attribute determined during mapper construction.
1055 Behavior is undefined if directly modified.
1056
1057 """
1058
1059 primary_key: Tuple[ColumnElement[Any], ...]
1060 """An iterable containing the collection of :class:`_schema.Column`
1061 objects
1062 which comprise the 'primary key' of the mapped table, from the
1063 perspective of this :class:`_orm.Mapper`.
1064
1065 This list is against the selectable in
1066 :attr:`_orm.Mapper.persist_selectable`.
1067 In the case of inheriting mappers, some columns may be managed by a
1068 superclass mapper. For example, in the case of a
1069 :class:`_expression.Join`, the
1070 primary key is determined by all of the primary key columns across all
1071 tables referenced by the :class:`_expression.Join`.
1072
1073 The list is also not necessarily the same as the primary key column
1074 collection associated with the underlying tables; the :class:`_orm.Mapper`
1075 features a ``primary_key`` argument that can override what the
1076 :class:`_orm.Mapper` considers as primary key columns.
1077
1078 This is a *read only* attribute determined during mapper construction.
1079 Behavior is undefined if directly modified.
1080
1081 """
1082
1083 class_manager: ClassManager[_O]
1084 """The :class:`.ClassManager` which maintains event listeners
1085 and class-bound descriptors for this :class:`_orm.Mapper`.
1086
1087 This is a *read only* attribute determined during mapper construction.
1088 Behavior is undefined if directly modified.
1089
1090 """
1091
1092 single: bool
1093 """Represent ``True`` if this :class:`_orm.Mapper` is a single table
1094 inheritance mapper.
1095
1096 :attr:`_orm.Mapper.local_table` will be ``None`` if this flag is set.
1097
1098 This is a *read only* attribute determined during mapper construction.
1099 Behavior is undefined if directly modified.
1100
1101 """
1102
1103 non_primary: bool
1104 """Represent ``True`` if this :class:`_orm.Mapper` is a "non-primary"
1105 mapper, e.g. a mapper that is used only to select rows but not for
1106 persistence management.
1107
1108 This is a *read only* attribute determined during mapper construction.
1109 Behavior is undefined if directly modified.
1110
1111 """
1112
1113 polymorphic_on: Optional[KeyedColumnElement[Any]]
1114 """The :class:`_schema.Column` or SQL expression specified as the
1115 ``polymorphic_on`` argument
1116 for this :class:`_orm.Mapper`, within an inheritance scenario.
1117
1118 This attribute is normally a :class:`_schema.Column` instance but
1119 may also be an expression, such as one derived from
1120 :func:`.cast`.
1121
1122 This is a *read only* attribute determined during mapper construction.
1123 Behavior is undefined if directly modified.
1124
1125 """
1126
1127 polymorphic_map: Dict[Any, Mapper[Any]]
1128 """A mapping of "polymorphic identity" identifiers mapped to
1129 :class:`_orm.Mapper` instances, within an inheritance scenario.
1130
1131 The identifiers can be of any type which is comparable to the
1132 type of column represented by :attr:`_orm.Mapper.polymorphic_on`.
1133
1134 An inheritance chain of mappers will all reference the same
1135 polymorphic map object. The object is used to correlate incoming
1136 result rows to target mappers.
1137
1138 This is a *read only* attribute determined during mapper construction.
1139 Behavior is undefined if directly modified.
1140
1141 """
1142
1143 polymorphic_identity: Optional[Any]
1144 """Represent an identifier which is matched against the
1145 :attr:`_orm.Mapper.polymorphic_on` column during result row loading.
1146
1147 Used only with inheritance, this object can be of any type which is
1148 comparable to the type of column represented by
1149 :attr:`_orm.Mapper.polymorphic_on`.
1150
1151 This is a *read only* attribute determined during mapper construction.
1152 Behavior is undefined if directly modified.
1153
1154 """
1155
1156 base_mapper: Mapper[Any]
1157 """The base-most :class:`_orm.Mapper` in an inheritance chain.
1158
1159 In a non-inheriting scenario, this attribute will always be this
1160 :class:`_orm.Mapper`. In an inheritance scenario, it references
1161 the :class:`_orm.Mapper` which is parent to all other :class:`_orm.Mapper`
1162 objects in the inheritance chain.
1163
1164 This is a *read only* attribute determined during mapper construction.
1165 Behavior is undefined if directly modified.
1166
1167 """
1168
1169 columns: ReadOnlyColumnCollection[str, Column[Any]]
1170 """A collection of :class:`_schema.Column` or other scalar expression
1171 objects maintained by this :class:`_orm.Mapper`.
1172
1173 The collection behaves the same as that of the ``c`` attribute on
1174 any :class:`_schema.Table` object,
1175 except that only those columns included in
1176 this mapping are present, and are keyed based on the attribute name
1177 defined in the mapping, not necessarily the ``key`` attribute of the
1178 :class:`_schema.Column` itself. Additionally, scalar expressions mapped
1179 by :func:`.column_property` are also present here.
1180
1181 This is a *read only* attribute determined during mapper construction.
1182 Behavior is undefined if directly modified.
1183
1184 """
1185
1186 c: ReadOnlyColumnCollection[str, Column[Any]]
1187 """A synonym for :attr:`_orm.Mapper.columns`."""
1188
1189 @util.non_memoized_property
1190 @util.deprecated("1.3", "Use .persist_selectable")
1191 def mapped_table(self):
1192 return self.persist_selectable
1193
1194 @util.memoized_property
1195 def _path_registry(self) -> CachingEntityRegistry:
1196 return PathRegistry.per_mapper(self)
1197
1198 def _configure_inheritance(self):
1199 """Configure settings related to inheriting and/or inherited mappers
1200 being present."""
