codekingpro/portable-devtools
114k
1# orm/mapper.py
2# Copyright (C) 2005-2024 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 :param batch: Defaults to ``True``, indicating that save operations
300 of multiple entities can be batched together for efficiency.
301 Setting to False indicates
302 that an instance will be fully saved before saving the next
303 instance. This is used in the extremely rare case that a
304 :class:`.MapperEvents` listener requires being called
305 in between individual row persistence operations.
306
307 :param column_prefix: A string which will be prepended
308 to the mapped attribute name when :class:`_schema.Column`
309 objects are automatically assigned as attributes to the
310 mapped class. Does not affect :class:`.Column` objects that
311 are mapped explicitly in the :paramref:`.Mapper.properties`
312 dictionary.
313
314 This parameter is typically useful with imperative mappings
315 that keep the :class:`.Table` object separate. Below, assuming
316 the ``user_table`` :class:`.Table` object has columns named
317 ``user_id``, ``user_name``, and ``password``::
318
319 class User(Base):
320 __table__ = user_table
321 __mapper_args__ = {'column_prefix':'_'}
322
323 The above mapping will assign the ``user_id``, ``user_name``, and
324 ``password`` columns to attributes named ``_user_id``,
325 ``_user_name``, and ``_password`` on the mapped ``User`` class.
326
327 The :paramref:`.Mapper.column_prefix` parameter is uncommon in
328 modern use. For dealing with reflected tables, a more flexible
329 approach to automating a naming scheme is to intercept the
330 :class:`.Column` objects as they are reflected; see the section
331 :ref:`mapper_automated_reflection_schemes` for notes on this usage
332 pattern.
333
334 :param concrete: If True, indicates this mapper should use concrete
335 table inheritance with its parent mapper.
336
337 See the section :ref:`concrete_inheritance` for an example.
338
339 :param confirm_deleted_rows: defaults to True; when a DELETE occurs
340 of one more rows based on specific primary keys, a warning is
341 emitted when the number of rows matched does not equal the number
342 of rows expected. This parameter may be set to False to handle the
343 case where database ON DELETE CASCADE rules may be deleting some of
344 those rows automatically. The warning may be changed to an
345 exception in a future release.
346
347 :param eager_defaults: if True, the ORM will immediately fetch the
348 value of server-generated default values after an INSERT or UPDATE,
349 rather than leaving them as expired to be fetched on next access.
350 This can be used for event schemes where the server-generated values
351 are needed immediately before the flush completes.
352
353 The fetch of values occurs either by using ``RETURNING`` inline
354 with the ``INSERT`` or ``UPDATE`` statement, or by adding an
355 additional ``SELECT`` statement subsequent to the ``INSERT`` or
356 ``UPDATE``, if the backend does not support ``RETURNING``.
357
358 The use of ``RETURNING`` is extremely performant in particular for
359 ``INSERT`` statements where SQLAlchemy can take advantage of
360 :ref:`insertmanyvalues <engine_insertmanyvalues>`, whereas the use of
361 an additional ``SELECT`` is relatively poor performing, adding
362 additional SQL round trips which would be unnecessary if these new
363 attributes are not to be accessed in any case.
364
365 For this reason, :paramref:`.Mapper.eager_defaults` defaults to the
366 string value ``"auto"``, which indicates that server defaults for
367 INSERT should be fetched using ``RETURNING`` if the backing database
368 supports it and if the dialect in use supports "insertmanyreturning"
369 for an INSERT statement. If the backing database does not support
370 ``RETURNING`` or "insertmanyreturning" is not available, server
371 defaults will not be fetched.
372
373 .. versionchanged:: 2.0.0rc1 added the "auto" option for
374 :paramref:`.Mapper.eager_defaults`
375
376 .. seealso::
377
378 :ref:`orm_server_defaults`
379
380 .. versionchanged:: 2.0.0 RETURNING now works with multiple rows
381 INSERTed at once using the
382 :ref:`insertmanyvalues <engine_insertmanyvalues>` feature, which
383 among other things allows the :paramref:`.Mapper.eager_defaults`
384 feature to be very performant on supporting backends.
385
386 :param exclude_properties: A list or set of string column names to
387 be excluded from mapping.
388
389 .. seealso::
390
391 :ref:`include_exclude_cols`
392
393 :param include_properties: An inclusive list or set of string column
394 names to map.
395
396 .. seealso::
397
398 :ref:`include_exclude_cols`
399
400 :param inherits: A mapped class or the corresponding
401 :class:`_orm.Mapper`
402 of one indicating a superclass to which this :class:`_orm.Mapper`
403 should *inherit* from. The mapped class here must be a subclass
404 of the other mapper's class. When using Declarative, this argument
405 is passed automatically as a result of the natural class
406 hierarchy of the declared classes.
407
408 .. seealso::
409
410 :ref:`inheritance_toplevel`
411
412 :param inherit_condition: For joined table inheritance, a SQL
413 expression which will
414 define how the two tables are joined; defaults to a natural join
415 between the two tables.
416
417 :param inherit_foreign_keys: When ``inherit_condition`` is used and
418 the columns present are missing a :class:`_schema.ForeignKey`
419 configuration, this parameter can be used to specify which columns
420 are "foreign". In most cases can be left as ``None``.
421
422 :param legacy_is_orphan: Boolean, defaults to ``False``.
423 When ``True``, specifies that "legacy" orphan consideration
424 is to be applied to objects mapped by this mapper, which means
425 that a pending (that is, not persistent) object is auto-expunged
426 from an owning :class:`.Session` only when it is de-associated
427 from *all* parents that specify a ``delete-orphan`` cascade towards
428 this mapper. The new default behavior is that the object is
429 auto-expunged when it is de-associated with *any* of its parents
430 that specify ``delete-orphan`` cascade. This behavior is more
431 consistent with that of a persistent object, and allows behavior to
432 be consistent in more scenarios independently of whether or not an
433 orphan object has been flushed yet or not.
434
435 See the change note and example at :ref:`legacy_is_orphan_addition`
436 for more detail on this change.
437
438 :param non_primary: Specify that this :class:`_orm.Mapper`
439 is in addition
440 to the "primary" mapper, that is, the one used for persistence.
441 The :class:`_orm.Mapper` created here may be used for ad-hoc
442 mapping of the class to an alternate selectable, for loading
443 only.
444
445 .. seealso::
446
447 :ref:`relationship_aliased_class` - the new pattern that removes
448 the need for the :paramref:`_orm.Mapper.non_primary` flag.
449
450 :param passive_deletes: Indicates DELETE behavior of foreign key
451 columns when a joined-table inheritance entity is being deleted.
452 Defaults to ``False`` for a base mapper; for an inheriting mapper,
453 defaults to ``False`` unless the value is set to ``True``
454 on the superclass mapper.
455
456 When ``True``, it is assumed that ON DELETE CASCADE is configured
457 on the foreign key relationships that link this mapper's table
458 to its superclass table, so that when the unit of work attempts
459 to delete the entity, it need only emit a DELETE statement for the
460 superclass table, and not this table.
461
462 When ``False``, a DELETE statement is emitted for this mapper's
463 table individually. If the primary key attributes local to this
464 table are unloaded, then a SELECT must be emitted in order to
465 validate these attributes; note that the primary key columns
466 of a joined-table subclass are not part of the "primary key" of
467 the object as a whole.
468
469 Note that a value of ``True`` is **always** forced onto the
470 subclass mappers; that is, it's not possible for a superclass
471 to specify passive_deletes without this taking effect for
472 all subclass mappers.
473
474 .. seealso::
475
476 :ref:`passive_deletes` - description of similar feature as
477 used with :func:`_orm.relationship`
478
479 :paramref:`.mapper.passive_updates` - supporting ON UPDATE
480 CASCADE for joined-table inheritance mappers
481
482 :param passive_updates: Indicates UPDATE behavior of foreign key
483 columns when a primary key column changes on a joined-table
484 inheritance mapping. Defaults to ``True``.
485
486 When True, it is assumed that ON UPDATE CASCADE is configured on
487 the foreign key in the database, and that the database will handle
488 propagation of an UPDATE from a source column to dependent columns
489 on joined-table rows.
490
491 When False, it is assumed that the database does not enforce
492 referential integrity and will not be issuing its own CASCADE
493 operation for an update. The unit of work process will
494 emit an UPDATE statement for the dependent columns during a
495 primary key change.
496
497 .. seealso::
498
499 :ref:`passive_updates` - description of a similar feature as
500 used with :func:`_orm.relationship`
501
502 :paramref:`.mapper.passive_deletes` - supporting ON DELETE
503 CASCADE for joined-table inheritance mappers
504
505 :param polymorphic_load: Specifies "polymorphic loading" behavior
506 for a subclass in an inheritance hierarchy (joined and single
507 table inheritance only). Valid values are:
508
509 * "'inline'" - specifies this class should be part of
510 the "with_polymorphic" mappers, e.g. its columns will be included
511 in a SELECT query against the base.
512
513 * "'selectin'" - specifies that when instances of this class
514 are loaded, an additional SELECT will be emitted to retrieve
515 the columns specific to this subclass. The SELECT uses
516 IN to fetch multiple subclasses at once.
517
518 .. versionadded:: 1.2
519
520 .. seealso::
521
522 :ref:`with_polymorphic_mapper_config`
523
524 :ref:`polymorphic_selectin`
525
526 :param polymorphic_on: Specifies the column, attribute, or
527 SQL expression used to determine the target class for an
528 incoming row, when inheriting classes are present.
529
530 May be specified as a string attribute name, or as a SQL
531 expression such as a :class:`_schema.Column` or in a Declarative
532 mapping a :func:`_orm.mapped_column` object. It is typically
533 expected that the SQL expression corresponds to a column in the
534 base-most mapped :class:`.Table`::
535
536 class Employee(Base):
537 __tablename__ = 'employee'
538
539 id: Mapped[int] = mapped_column(primary_key=True)
540 discriminator: Mapped[str] = mapped_column(String(50))
541
542 __mapper_args__ = {
543 "polymorphic_on":discriminator,
544 "polymorphic_identity":"employee"
545 }
546
547 It may also be specified
548 as a SQL expression, as in this example where we
549 use the :func:`.case` construct to provide a conditional
550 approach::
551
552 class Employee(Base):
553 __tablename__ = 'employee'
554
555 id: Mapped[int] = mapped_column(primary_key=True)
556 discriminator: Mapped[str] = mapped_column(String(50))
557
558 __mapper_args__ = {
559 "polymorphic_on":case(
560 (discriminator == "EN", "engineer"),
561 (discriminator == "MA", "manager"),
562 else_="employee"),
563 "polymorphic_identity":"employee"
564 }
565
566 It may also refer to any attribute using its string name,
567 which is of particular use when using annotated column
568 configurations::
569
570 class Employee(Base):
571 __tablename__ = 'employee'
572
573 id: Mapped[int] = mapped_column(primary_key=True)
574 discriminator: Mapped[str]
575
576 __mapper_args__ = {
577 "polymorphic_on": "discriminator",
578 "polymorphic_identity": "employee"
579 }
580
581 When setting ``polymorphic_on`` to reference an
582 attribute or expression that's not present in the
583 locally mapped :class:`_schema.Table`, yet the value
584 of the discriminator should be persisted to the database,
585 the value of the
586 discriminator is not automatically set on new
587 instances; this must be handled by the user,
588 either through manual means or via event listeners.
589 A typical approach to establishing such a listener
590 looks like::
591
592 from sqlalchemy import event
593 from sqlalchemy.orm import object_mapper
594
595 @event.listens_for(Employee, "init", propagate=True)
596 def set_identity(instance, *arg, **kw):
597 mapper = object_mapper(instance)
598 instance.discriminator = mapper.polymorphic_identity
599
600 Where above, we assign the value of ``polymorphic_identity``
601 for the mapped class to the ``discriminator`` attribute,
602 thus persisting the value to the ``discriminator`` column
603 in the database.
604
605 .. warning::
606
607 Currently, **only one discriminator column may be set**, typically
608 on the base-most class in the hierarchy. "Cascading" polymorphic
609 columns are not yet supported.
610
611 .. seealso::
612
613 :ref:`inheritance_toplevel`
614
615 :param polymorphic_identity: Specifies the value which
616 identifies this particular class as returned by the column expression
617 referred to by the :paramref:`_orm.Mapper.polymorphic_on` setting. As
618 rows are received, the value corresponding to the
619 :paramref:`_orm.Mapper.polymorphic_on` column expression is compared
620 to this value, indicating which subclass should be used for the newly
621 reconstructed object.
622
623 .. seealso::
624
625 :ref:`inheritance_toplevel`
626
627 :param properties: A dictionary mapping the string names of object
628 attributes to :class:`.MapperProperty` instances, which define the
629 persistence behavior of that attribute. Note that
630 :class:`_schema.Column`
631 objects present in
632 the mapped :class:`_schema.Table` are automatically placed into
633 ``ColumnProperty`` instances upon mapping, unless overridden.
634 When using Declarative, this argument is passed automatically,
635 based on all those :class:`.MapperProperty` instances declared
636 in the declared class body.
637
638 .. seealso::
639
640 :ref:`orm_mapping_properties` - in the
641 :ref:`orm_mapping_classes_toplevel`
642
643 :param primary_key: A list of :class:`_schema.Column`
644 objects, or alternatively string names of attribute names which
645 refer to :class:`_schema.Column`, which define
646 the primary key to be used against this mapper's selectable unit.
647 This is normally simply the primary key of the ``local_table``, but
648 can be overridden here.
649
650 .. versionchanged:: 2.0.2 :paramref:`_orm.Mapper.primary_key`
651 arguments may be indicated as string attribute names as well.
652
653 .. seealso::
654
655 :ref:`mapper_primary_key` - background and example use
656
657 :param version_id_col: A :class:`_schema.Column`
658 that will be used to keep a running version id of rows
659 in the table. This is used to detect concurrent updates or
660 the presence of stale data in a flush. The methodology is to
661 detect if an UPDATE statement does not match the last known
662 version id, a
663 :class:`~sqlalchemy.orm.exc.StaleDataError` exception is
664 thrown.
665 By default, the column must be of :class:`.Integer` type,
666 unless ``version_id_generator`` specifies an alternative version
667 generator.
668
669 .. seealso::
670
671 :ref:`mapper_version_counter` - discussion of version counting
672 and rationale.
673
674 :param version_id_generator: Define how new version ids should
675 be generated. Defaults to ``None``, which indicates that
676 a simple integer counting scheme be employed. To provide a custom
677 versioning scheme, provide a callable function of the form::
678
679 def generate_version(version):
680 return next_version
681
682 Alternatively, server-side versioning functions such as triggers,
683 or programmatic versioning schemes outside of the version id
684 generator may be used, by specifying the value ``False``.
685 Please see :ref:`server_side_version_counter` for a discussion
686 of important points when using this option.
687
688 .. seealso::
689
690 :ref:`custom_version_counter`
691
692 :ref:`server_side_version_counter`
693
694
695 :param with_polymorphic: A tuple in the form ``(<classes>,
696 <selectable>)`` indicating the default style of "polymorphic"
697 loading, that is, which tables are queried at once. <classes> is
698 any single or list of mappers and/or classes indicating the
699 inherited classes that should be loaded at once. The special value
700 ``'*'`` may be used to indicate all descending classes should be
701 loaded immediately. The second tuple argument <selectable>
702 indicates a selectable that will be used to query for multiple
703 classes.
704
705 The :paramref:`_orm.Mapper.polymorphic_load` parameter may be
706 preferable over the use of :paramref:`_orm.Mapper.with_polymorphic`
707 in modern mappings to indicate a per-subclass technique of
708 indicating polymorphic loading styles.
709
710 .. seealso::
711
712 :ref:`with_polymorphic_mapper_config`
713
714 """
715 self.class_ = util.assert_arg_type(class_, type, "class_")
716 self._sort_key = "%s.%s" % (
717 self.class_.__module__,
718 self.class_.__name__,
719 )
720
721 self._primary_key_argument = util.to_list(primary_key)
722 self.non_primary = non_primary
723
724 self.always_refresh = always_refresh
725
726 if isinstance(version_id_col, MapperProperty):
727 self.version_id_prop = version_id_col
728 self.version_id_col = None
729 else:
730 self.version_id_col = (
731 coercions.expect(
732 roles.ColumnArgumentOrKeyRole,
733 version_id_col,
734 argname="version_id_col",
735 )
736 if version_id_col is not None
737 else None
738 )
739
740 if version_id_generator is False:
741 self.version_id_generator = False
742 elif version_id_generator is None:
743 self.version_id_generator = lambda x: (x or 0) + 1
744 else:
745 self.version_id_generator = version_id_generator
746
747 self.concrete = concrete
748 self.single = False
749
750 if inherits is not None:
751 self.inherits = _parse_mapper_argument(inherits)
752 else:
753 self.inherits = None
754
755 if local_table is not None:
756 self.local_table = coercions.expect(
757 roles.StrictFromClauseRole,
758 local_table,
759 disable_inspection=True,
760 argname="local_table",
761 )
762 elif self.inherits:
763 # note this is a new flow as of 2.0 so that
764 # .local_table need not be Optional
765 self.local_table = self.inherits.local_table
766 self.single = True
767 else:
768 raise sa_exc.ArgumentError(
769 f"Mapper[{self.class_.__name__}(None)] has None for a "
770 "primary table argument and does not specify 'inherits'"
771 )
772
773 if inherit_condition is not None:
774 self.inherit_condition = coercions.expect(
775 roles.OnClauseRole, inherit_condition
776 )
777 else:
778 self.inherit_condition = None
779
780 self.inherit_foreign_keys = inherit_foreign_keys
781 self._init_properties = dict(properties) if properties else {}
782 self._delete_orphans = []
783 self.batch = batch
784 self.eager_defaults = eager_defaults
785 self.column_prefix = column_prefix
786
787 # interim - polymorphic_on is further refined in
788 # _configure_polymorphic_setter
789 self.polymorphic_on = (
790 coercions.expect( # type: ignore
791 roles.ColumnArgumentOrKeyRole,
792 polymorphic_on,
793 argname="polymorphic_on",
794 )
795 if polymorphic_on is not None
796 else None
797 )
798 self.polymorphic_abstract = polymorphic_abstract
799 self._dependency_processors = []
800 self.validators = util.EMPTY_DICT
801 self.passive_updates = passive_updates
802 self.passive_deletes = passive_deletes
803 self.legacy_is_orphan = legacy_is_orphan
804 self._clause_adapter = None
805 self._requires_row_aliasing = False
806 self._inherits_equated_pairs = None
807 self._memoized_values = {}
808 self._compiled_cache_size = _compiled_cache_size
809 self._reconstructor = None
810 self.allow_partial_pks = allow_partial_pks
811
812 if self.inherits and not self.concrete:
813 self.confirm_deleted_rows = False
814 else:
815 self.confirm_deleted_rows = confirm_deleted_rows
816
817 self._set_with_polymorphic(with_polymorphic)
818 self.polymorphic_load = polymorphic_load
819
820 # our 'polymorphic identity', a string name that when located in a
821 # result set row indicates this Mapper should be used to construct
822 # the object instance for that row.
823 self.polymorphic_identity = polymorphic_identity
824
825 # a dictionary of 'polymorphic identity' names, associating those
826 # names with Mappers that will be used to construct object instances
827 # upon a select operation.
828 if _polymorphic_map is None:
829 self.polymorphic_map = {}
830 else:
831 self.polymorphic_map = _polymorphic_map
832
833 if include_properties is not None:
834 self.include_properties = util.to_set(include_properties)
835 else:
836 self.include_properties = None
837 if exclude_properties:
838 self.exclude_properties = util.to_set(exclude_properties)
839 else:
840 self.exclude_properties = None
841
842 # prevent this mapper from being constructed
843 # while a configure_mappers() is occurring (and defer a
844 # configure_mappers() until construction succeeds)
845 with _CONFIGURE_MUTEX:
846 cast("MapperEvents", self.dispatch._events)._new_mapper_instance(
847 class_, self
848 )
849 self._configure_inheritance()
850 self._configure_class_instrumentation()
851 self._configure_properties()
852 self._configure_polymorphic_setter()
853 self._configure_pks()
854 self.registry._flag_new_mapper(self)
855 self._log("constructed")
856 self._expire_memoizations()
857
858 self.dispatch.after_mapper_constructed(self, self.class_)
859
860 def _prefer_eager_defaults(self, dialect, table):
861 if self.eager_defaults == "auto":
862 if not table.implicit_returning:
863 return False
864
865 return (
866 table in self._server_default_col_keys
867 and dialect.insert_executemany_returning
868 )
869 else:
870 return self.eager_defaults
871
872 def _gen_cache_key(self, anon_map, bindparams):
873 return (self,)
874
875 # ### BEGIN
876 # ATTRIBUTE DECLARATIONS START HERE
877
878 is_mapper = True
879 """Part of the inspection API."""
880
881 represents_outer_join = False
882
883 registry: _RegistryType
884
885 @property
886 def mapper(self) -> Mapper[_O]:
887 """Part of the inspection API.
888
889 Returns self.
890
891 """
892 return self
893
894 @property
895 def entity(self):
896 r"""Part of the inspection API.
897
898 Returns self.class\_.
899
900 """
901 return self.class_
902
903 class_: Type[_O]
904 """The class to which this :class:`_orm.Mapper` is mapped."""
905
906 _identity_class: Type[_O]
907
908 _delete_orphans: List[Tuple[str, Type[Any]]]
909 _dependency_processors: List[DependencyProcessor]
910 _memoized_values: Dict[Any, Callable[[], Any]]
911 _inheriting_mappers: util.WeakSequence[Mapper[Any]]
912 _all_tables: Set[TableClause]
913 _polymorphic_attr_key: Optional[str]
914
915 _pks_by_table: Dict[FromClause, OrderedSet[ColumnClause[Any]]]
916 _cols_by_table: Dict[FromClause, OrderedSet[ColumnElement[Any]]]
917
918 _props: util.OrderedDict[str, MapperProperty[Any]]
919 _init_properties: Dict[str, MapperProperty[Any]]
920
921 _columntoproperty: _ColumnMapping
922
923 _set_polymorphic_identity: Optional[Callable[[InstanceState[_O]], None]]
924 _validate_polymorphic_identity: Optional[
925 Callable[[Mapper[_O], InstanceState[_O], _InstanceDict], None]
926 ]
927
928 tables: Sequence[TableClause]
929 """A sequence containing the collection of :class:`_schema.Table`
930 or :class:`_schema.TableClause` objects which this :class:`_orm.Mapper`
931 is aware of.
932
933 If the mapper is mapped to a :class:`_expression.Join`, or an
934 :class:`_expression.Alias`
935 representing a :class:`_expression.Select`, the individual
936 :class:`_schema.Table`
937 objects that comprise the full construct will be represented here.
938
939 This is a *read only* attribute determined during mapper construction.
940 Behavior is undefined if directly modified.
941
942 """
943
944 validators: util.immutabledict[str, Tuple[str, Dict[str, Any]]]
945 """An immutable dictionary of attributes which have been decorated
946 using the :func:`_orm.validates` decorator.
947
948 The dictionary contains string attribute names as keys
949 mapped to the actual validation method.
950
951 """
952
953 always_refresh: bool
954 allow_partial_pks: bool
955 version_id_col: Optional[ColumnElement[Any]]
956
957 with_polymorphic: Optional[
958 Tuple[
959 Union[Literal["*"], Sequence[Union[Mapper[Any], Type[Any]]]],
960 Optional[FromClause],
961 ]
962 ]
963
964 version_id_generator: Optional[Union[Literal[False], Callable[[Any], Any]]]
965
966 local_table: FromClause
967 """The immediate :class:`_expression.FromClause` to which this
968 :class:`_orm.Mapper` refers.
969
970 Typically is an instance of :class:`_schema.Table`, may be any
971 :class:`.FromClause`.
972
973 The "local" table is the
974 selectable that the :class:`_orm.Mapper` is directly responsible for
975 managing from an attribute access and flush perspective. For
976 non-inheriting mappers, :attr:`.Mapper.local_table` will be the same
977 as :attr:`.Mapper.persist_selectable`. For inheriting mappers,
978 :attr:`.Mapper.local_table` refers to the specific portion of
979 :attr:`.Mapper.persist_selectable` that includes the columns to which
980 this :class:`.Mapper` is loading/persisting, such as a particular
981 :class:`.Table` within a join.
982
983 .. seealso::
984
985 :attr:`_orm.Mapper.persist_selectable`.
986
987 :attr:`_orm.Mapper.selectable`.
988
989 """
990
991 persist_selectable: FromClause
992 """The :class:`_expression.FromClause` to which this :class:`_orm.Mapper`
993 is mapped.
994
995 Typically is an instance of :class:`_schema.Table`, may be any
996 :class:`.FromClause`.
997
998 The :attr:`_orm.Mapper.persist_selectable` is similar to
999 :attr:`.Mapper.local_table`, but represents the :class:`.FromClause` that
1000 represents the inheriting class hierarchy overall in an inheritance
1001 scenario.
1002
1003 :attr.`.Mapper.persist_selectable` is also separate from the
1004 :attr:`.Mapper.selectable` attribute, the latter of which may be an
1005 alternate subquery used for selecting columns.
1006 :attr.`.Mapper.persist_selectable` is oriented towards columns that
1007 will be written on a persist operation.
1008
1009 .. seealso::
1010
1011 :attr:`_orm.Mapper.selectable`.
1012
1013 :attr:`_orm.Mapper.local_table`.
1014
1015 """
1016
1017 inherits: Optional[Mapper[Any]]
1018 """References the :class:`_orm.Mapper` which this :class:`_orm.Mapper`
1019 inherits from, if any.
1020
1021 """
1022
1023 inherit_condition: Optional[ColumnElement[bool]]
1024
1025 configured: bool = False
1026 """Represent ``True`` if this :class:`_orm.Mapper` has been configured.
1027
1028 This is a *read only* attribute determined during mapper construction.
1029 Behavior is undefined if directly modified.
1030
1031 .. seealso::
1032
1033 :func:`.configure_mappers`.
1034
1035 """
1036
1037 concrete: bool
1038 """Represent ``True`` if this :class:`_orm.Mapper` is a concrete
1039 inheritance mapper.
1040
1041 This is a *read only* attribute determined during mapper construction.
1042 Behavior is undefined if directly modified.
1043
1044 """
1045
1046 primary_key: Tuple[Column[Any], ...]
1047 """An iterable containing the collection of :class:`_schema.Column`
1048 objects
1049 which comprise the 'primary key' of the mapped table, from the
1050 perspective of this :class:`_orm.Mapper`.
1051
1052 This list is against the selectable in
1053 :attr:`_orm.Mapper.persist_selectable`.
1054 In the case of inheriting mappers, some columns may be managed by a
1055 superclass mapper. For example, in the case of a
1056 :class:`_expression.Join`, the
1057 primary key is determined by all of the primary key columns across all
1058 tables referenced by the :class:`_expression.Join`.
1059
1060 The list is also not necessarily the same as the primary key column
1061 collection associated with the underlying tables; the :class:`_orm.Mapper`
1062 features a ``primary_key`` argument that can override what the
1063 :class:`_orm.Mapper` considers as primary key columns.
1064
1065 This is a *read only* attribute determined during mapper construction.
1066 Behavior is undefined if directly modified.
1067
1068 """
1069
1070 class_manager: ClassManager[_O]
1071 """The :class:`.ClassManager` which maintains event listeners
1072 and class-bound descriptors for this :class:`_orm.Mapper`.
1073
1074 This is a *read only* attribute determined during mapper construction.
1075 Behavior is undefined if directly modified.
1076
1077 """
1078
1079 single: bool
1080 """Represent ``True`` if this :class:`_orm.Mapper` is a single table
1081 inheritance mapper.
1082
1083 :attr:`_orm.Mapper.local_table` will be ``None`` if this flag is set.
1084
1085 This is a *read only* attribute determined during mapper construction.
1086 Behavior is undefined if directly modified.
1087
1088 """
1089
1090 non_primary: bool
1091 """Represent ``True`` if this :class:`_orm.Mapper` is a "non-primary"
1092 mapper, e.g. a mapper that is used only to select rows but not for
1093 persistence management.
1094
1095 This is a *read only* attribute determined during mapper construction.
1096 Behavior is undefined if directly modified.
1097
1098 """
1099
1100 polymorphic_on: Optional[KeyedColumnElement[Any]]
1101 """The :class:`_schema.Column` or SQL expression specified as the
1102 ``polymorphic_on`` argument
1103 for this :class:`_orm.Mapper`, within an inheritance scenario.
1104
1105 This attribute is normally a :class:`_schema.Column` instance but
1106 may also be an expression, such as one derived from
1107 :func:`.cast`.
1108
1109 This is a *read only* attribute determined during mapper construction.
1110 Behavior is undefined if directly modified.
1111
1112 """
1113
1114 polymorphic_map: Dict[Any, Mapper[Any]]
1115 """A mapping of "polymorphic identity" identifiers mapped to
1116 :class:`_orm.Mapper` instances, within an inheritance scenario.
1117
1118 The identifiers can be of any type which is comparable to the
1119 type of column represented by :attr:`_orm.Mapper.polymorphic_on`.
1120
1121 An inheritance chain of mappers will all reference the same
1122 polymorphic map object. The object is used to correlate incoming
1123 result rows to target mappers.
1124
1125 This is a *read only* attribute determined during mapper construction.
1126 Behavior is undefined if directly modified.
1127
1128 """
1129
1130 polymorphic_identity: Optional[Any]
1131 """Represent an identifier which is matched against the
1132 :attr:`_orm.Mapper.polymorphic_on` column during result row loading.
1133
1134 Used only with inheritance, this object can be of any type which is
1135 comparable to the type of column represented by
1136 :attr:`_orm.Mapper.polymorphic_on`.
1137
1138 This is a *read only* attribute determined during mapper construction.
1139 Behavior is undefined if directly modified.
1140
1141 """
1142
1143 base_mapper: Mapper[Any]
1144 """The base-most :class:`_orm.Mapper` in an inheritance chain.
1145
1146 In a non-inheriting scenario, this attribute will always be this
1147 :class:`_orm.Mapper`. In an inheritance scenario, it references
1148 the :class:`_orm.Mapper` which is parent to all other :class:`_orm.Mapper`
1149 objects in the inheritance chain.
1150
1151 This is a *read only* attribute determined during mapper construction.
1152 Behavior is undefined if directly modified.
1153
1154 """
1155
1156 columns: ReadOnlyColumnCollection[str, Column[Any]]
1157 """A collection of :class:`_schema.Column` or other scalar expression
1158 objects maintained by this :class:`_orm.Mapper`.
1159
1160 The collection behaves the same as that of the ``c`` attribute on
1161 any :class:`_schema.Table` object,
1162 except that only those columns included in
1163 this mapping are present, and are keyed based on the attribute name
1164 defined in the mapping, not necessarily the ``key`` attribute of the
1165 :class:`_schema.Column` itself. Additionally, scalar expressions mapped
1166 by :func:`.column_property` are also present here.
1167
1168 This is a *read only* attribute determined during mapper construction.
1169 Behavior is undefined if directly modified.
1170
1171 """
1172
1173 c: ReadOnlyColumnCollection[str, Column[Any]]
1174 """A synonym for :attr:`_orm.Mapper.columns`."""
1175
1176 @util.non_memoized_property
1177 @util.deprecated("1.3", "Use .persist_selectable")
1178 def mapped_table(self):
1179 return self.persist_selectable
1180
1181 @util.memoized_property
1182 def _path_registry(self) -> CachingEntityRegistry:
1183 return PathRegistry.per_mapper(self)
1184
1185 def _configure_inheritance(self):
1186 """Configure settings related to inheriting and/or inherited mappers
1187 being present."""
1188
1189 # a set of all mappers which inherit from this one.
1190 self._inheriting_mappers = util.WeakSequence()
1191
1192 if self.inherits:
1193 if not issubclass(self.class_, self.inherits.class_):
1194 raise sa_exc.ArgumentError(
1195 "Class '%s' does not inherit from '%s'"
1196 % (self.class_.__name__, self.inherits.class_.__name__)
1197 )
1198
1199 self.dispatch._update(self.inherits.dispatch)
1200
