relationships.py 118 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875
  1. # orm/relationships.py
  2. # Copyright (C) 2005-2017 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: http://www.opensource.org/licenses/mit-license.php
  7. """Heuristics related to join conditions as used in
  8. :func:`.relationship`.
  9. Provides the :class:`.JoinCondition` object, which encapsulates
  10. SQL annotation and aliasing behavior focused on the `primaryjoin`
  11. and `secondaryjoin` aspects of :func:`.relationship`.
  12. """
  13. from __future__ import absolute_import
  14. from .. import sql, util, exc as sa_exc, schema, log
  15. import weakref
  16. from .util import CascadeOptions, _orm_annotate, _orm_deannotate
  17. from . import dependency
  18. from . import attributes
  19. from ..sql.util import (
  20. ClauseAdapter,
  21. join_condition, _shallow_annotate, visit_binary_product,
  22. _deep_deannotate, selectables_overlap, adapt_criterion_to_null
  23. )
  24. from ..sql import operators, expression, visitors
  25. from .interfaces import (MANYTOMANY, MANYTOONE, ONETOMANY,
  26. StrategizedProperty, PropComparator)
  27. from ..inspection import inspect
  28. from . import mapper as mapperlib
  29. import collections
  30. def remote(expr):
  31. """Annotate a portion of a primaryjoin expression
  32. with a 'remote' annotation.
  33. See the section :ref:`relationship_custom_foreign` for a
  34. description of use.
  35. .. versionadded:: 0.8
  36. .. seealso::
  37. :ref:`relationship_custom_foreign`
  38. :func:`.foreign`
  39. """
  40. return _annotate_columns(expression._clause_element_as_expr(expr),
  41. {"remote": True})
  42. def foreign(expr):
  43. """Annotate a portion of a primaryjoin expression
  44. with a 'foreign' annotation.
  45. See the section :ref:`relationship_custom_foreign` for a
  46. description of use.
  47. .. versionadded:: 0.8
  48. .. seealso::
  49. :ref:`relationship_custom_foreign`
  50. :func:`.remote`
  51. """
  52. return _annotate_columns(expression._clause_element_as_expr(expr),
  53. {"foreign": True})
  54. @log.class_logger
  55. @util.langhelpers.dependency_for("sqlalchemy.orm.properties")
  56. class RelationshipProperty(StrategizedProperty):
  57. """Describes an object property that holds a single item or list
  58. of items that correspond to a related database table.
  59. Public constructor is the :func:`.orm.relationship` function.
  60. See also:
  61. :ref:`relationship_config_toplevel`
  62. """
  63. strategy_wildcard_key = 'relationship'
  64. _dependency_processor = None
  65. def __init__(self, argument,
  66. secondary=None, primaryjoin=None,
  67. secondaryjoin=None,
  68. foreign_keys=None,
  69. uselist=None,
  70. order_by=False,
  71. backref=None,
  72. back_populates=None,
  73. post_update=False,
  74. cascade=False, extension=None,
  75. viewonly=False, lazy=True,
  76. collection_class=None, passive_deletes=False,
  77. passive_updates=True, remote_side=None,
  78. enable_typechecks=True, join_depth=None,
  79. comparator_factory=None,
  80. single_parent=False, innerjoin=False,
  81. distinct_target_key=None,
  82. doc=None,
  83. active_history=False,
  84. cascade_backrefs=True,
  85. load_on_pending=False,
  86. bake_queries=True,
  87. _local_remote_pairs=None,
  88. query_class=None,
  89. info=None):
  90. """Provide a relationship between two mapped classes.
  91. This corresponds to a parent-child or associative table relationship.
  92. The constructed class is an instance of
  93. :class:`.RelationshipProperty`.
  94. A typical :func:`.relationship`, used in a classical mapping::
  95. mapper(Parent, properties={
  96. 'children': relationship(Child)
  97. })
  98. Some arguments accepted by :func:`.relationship` optionally accept a
  99. callable function, which when called produces the desired value.
  100. The callable is invoked by the parent :class:`.Mapper` at "mapper
  101. initialization" time, which happens only when mappers are first used,
  102. and is assumed to be after all mappings have been constructed. This
  103. can be used to resolve order-of-declaration and other dependency
  104. issues, such as if ``Child`` is declared below ``Parent`` in the same
  105. file::
  106. mapper(Parent, properties={
  107. "children":relationship(lambda: Child,
  108. order_by=lambda: Child.id)
  109. })
  110. When using the :ref:`declarative_toplevel` extension, the Declarative
  111. initializer allows string arguments to be passed to
  112. :func:`.relationship`. These string arguments are converted into
  113. callables that evaluate the string as Python code, using the
  114. Declarative class-registry as a namespace. This allows the lookup of
  115. related classes to be automatic via their string name, and removes the
  116. need to import related classes at all into the local module space::
  117. from sqlalchemy.ext.declarative import declarative_base
  118. Base = declarative_base()
  119. class Parent(Base):
  120. __tablename__ = 'parent'
  121. id = Column(Integer, primary_key=True)
  122. children = relationship("Child", order_by="Child.id")
  123. .. seealso::
  124. :ref:`relationship_config_toplevel` - Full introductory and
  125. reference documentation for :func:`.relationship`.
  126. :ref:`orm_tutorial_relationship` - ORM tutorial introduction.
  127. :param argument:
  128. a mapped class, or actual :class:`.Mapper` instance, representing
  129. the target of the relationship.
  130. :paramref:`~.relationship.argument` may also be passed as a callable
  131. function which is evaluated at mapper initialization time, and may
  132. be passed as a Python-evaluable string when using Declarative.
  133. .. seealso::
  134. :ref:`declarative_configuring_relationships` - further detail
  135. on relationship configuration when using Declarative.
  136. :param secondary:
  137. for a many-to-many relationship, specifies the intermediary
  138. table, and is typically an instance of :class:`.Table`.
  139. In less common circumstances, the argument may also be specified
  140. as an :class:`.Alias` construct, or even a :class:`.Join` construct.
  141. :paramref:`~.relationship.secondary` may
  142. also be passed as a callable function which is evaluated at
  143. mapper initialization time. When using Declarative, it may also
  144. be a string argument noting the name of a :class:`.Table` that is
  145. present in the :class:`.MetaData` collection associated with the
  146. parent-mapped :class:`.Table`.
  147. The :paramref:`~.relationship.secondary` keyword argument is
  148. typically applied in the case where the intermediary :class:`.Table`
  149. is not otherwise expressed in any direct class mapping. If the
  150. "secondary" table is also explicitly mapped elsewhere (e.g. as in
  151. :ref:`association_pattern`), one should consider applying the
  152. :paramref:`~.relationship.viewonly` flag so that this
  153. :func:`.relationship` is not used for persistence operations which
  154. may conflict with those of the association object pattern.
  155. .. seealso::
  156. :ref:`relationships_many_to_many` - Reference example of "many
  157. to many".
  158. :ref:`orm_tutorial_many_to_many` - ORM tutorial introduction to
  159. many-to-many relationships.
  160. :ref:`self_referential_many_to_many` - Specifics on using
  161. many-to-many in a self-referential case.
  162. :ref:`declarative_many_to_many` - Additional options when using
  163. Declarative.
  164. :ref:`association_pattern` - an alternative to
  165. :paramref:`~.relationship.secondary` when composing association
  166. table relationships, allowing additional attributes to be
  167. specified on the association table.
  168. :ref:`composite_secondary_join` - a lesser-used pattern which
  169. in some cases can enable complex :func:`.relationship` SQL
  170. conditions to be used.
  171. .. versionadded:: 0.9.2 :paramref:`~.relationship.secondary` works
  172. more effectively when referring to a :class:`.Join` instance.
  173. :param active_history=False:
  174. When ``True``, indicates that the "previous" value for a
  175. many-to-one reference should be loaded when replaced, if
  176. not already loaded. Normally, history tracking logic for
  177. simple many-to-ones only needs to be aware of the "new"
  178. value in order to perform a flush. This flag is available
  179. for applications that make use of
  180. :func:`.attributes.get_history` which also need to know
  181. the "previous" value of the attribute.
  182. :param backref:
  183. indicates the string name of a property to be placed on the related
  184. mapper's class that will handle this relationship in the other
  185. direction. The other property will be created automatically
  186. when the mappers are configured. Can also be passed as a
  187. :func:`.backref` object to control the configuration of the
  188. new relationship.
  189. .. seealso::
  190. :ref:`relationships_backref` - Introductory documentation and
  191. examples.
  192. :paramref:`~.relationship.back_populates` - alternative form
  193. of backref specification.
  194. :func:`.backref` - allows control over :func:`.relationship`
  195. configuration when using :paramref:`~.relationship.backref`.
  196. :param back_populates:
  197. Takes a string name and has the same meaning as
  198. :paramref:`~.relationship.backref`, except the complementing
  199. property is **not** created automatically, and instead must be
  200. configured explicitly on the other mapper. The complementing
  201. property should also indicate
  202. :paramref:`~.relationship.back_populates` to this relationship to
  203. ensure proper functioning.
  204. .. seealso::
  205. :ref:`relationships_backref` - Introductory documentation and
  206. examples.
  207. :paramref:`~.relationship.backref` - alternative form
  208. of backref specification.
  209. :param bake_queries=True:
  210. Use the :class:`.BakedQuery` cache to cache the construction of SQL
  211. used in lazy loads, when the :func:`.bake_lazy_loaders` function has
  212. first been called. Defaults to True and is intended to provide an
  213. "opt out" flag per-relationship when the baked query cache system is
  214. in use.
  215. .. warning::
  216. This flag **only** has an effect when the application-wide
  217. :func:`.bake_lazy_loaders` function has been called. It
  218. defaults to True so is an "opt out" flag.
  219. Setting this flag to False when baked queries are otherwise in
  220. use might be to reduce
  221. ORM memory use for this :func:`.relationship`, or to work around
  222. unresolved stability issues observed within the baked query
  223. cache system.
  224. .. versionadded:: 1.0.0
  225. .. seealso::
  226. :ref:`baked_toplevel`
  227. :param cascade:
  228. a comma-separated list of cascade rules which determines how
  229. Session operations should be "cascaded" from parent to child.
  230. This defaults to ``False``, which means the default cascade
  231. should be used - this default cascade is ``"save-update, merge"``.
  232. The available cascades are ``save-update``, ``merge``,
  233. ``expunge``, ``delete``, ``delete-orphan``, and ``refresh-expire``.
  234. An additional option, ``all`` indicates shorthand for
  235. ``"save-update, merge, refresh-expire,
  236. expunge, delete"``, and is often used as in ``"all, delete-orphan"``
  237. to indicate that related objects should follow along with the
  238. parent object in all cases, and be deleted when de-associated.
  239. .. seealso::
  240. :ref:`unitofwork_cascades` - Full detail on each of the available
  241. cascade options.
  242. :ref:`tutorial_delete_cascade` - Tutorial example describing
  243. a delete cascade.
  244. :param cascade_backrefs=True:
  245. a boolean value indicating if the ``save-update`` cascade should
  246. operate along an assignment event intercepted by a backref.
  247. When set to ``False``, the attribute managed by this relationship
  248. will not cascade an incoming transient object into the session of a
  249. persistent parent, if the event is received via backref.
  250. .. seealso::
  251. :ref:`backref_cascade` - Full discussion and examples on how
  252. the :paramref:`~.relationship.cascade_backrefs` option is used.
  253. :param collection_class:
  254. a class or callable that returns a new list-holding object. will
  255. be used in place of a plain list for storing elements.
  256. .. seealso::
  257. :ref:`custom_collections` - Introductory documentation and
  258. examples.
  259. :param comparator_factory:
  260. a class which extends :class:`.RelationshipProperty.Comparator`
  261. which provides custom SQL clause generation for comparison
  262. operations.
  263. .. seealso::
  264. :class:`.PropComparator` - some detail on redefining comparators
  265. at this level.
  266. :ref:`custom_comparators` - Brief intro to this feature.
  267. :param distinct_target_key=None:
  268. Indicate if a "subquery" eager load should apply the DISTINCT
  269. keyword to the innermost SELECT statement. When left as ``None``,
  270. the DISTINCT keyword will be applied in those cases when the target
  271. columns do not comprise the full primary key of the target table.
  272. When set to ``True``, the DISTINCT keyword is applied to the
  273. innermost SELECT unconditionally.
  274. It may be desirable to set this flag to False when the DISTINCT is
  275. reducing performance of the innermost subquery beyond that of what
  276. duplicate innermost rows may be causing.
  277. .. versionadded:: 0.8.3 -
  278. :paramref:`~.relationship.distinct_target_key` allows the
  279. subquery eager loader to apply a DISTINCT modifier to the
  280. innermost SELECT.
  281. .. versionchanged:: 0.9.0 -
  282. :paramref:`~.relationship.distinct_target_key` now defaults to
  283. ``None``, so that the feature enables itself automatically for
  284. those cases where the innermost query targets a non-unique
  285. key.
  286. .. seealso::
  287. :ref:`loading_toplevel` - includes an introduction to subquery
  288. eager loading.
  289. :param doc:
  290. docstring which will be applied to the resulting descriptor.
  291. :param extension:
  292. an :class:`.AttributeExtension` instance, or list of extensions,
  293. which will be prepended to the list of attribute listeners for
  294. the resulting descriptor placed on the class.
  295. .. deprecated:: 0.7 Please see :class:`.AttributeEvents`.
  296. :param foreign_keys:
  297. a list of columns which are to be used as "foreign key"
  298. columns, or columns which refer to the value in a remote
  299. column, within the context of this :func:`.relationship`
  300. object's :paramref:`~.relationship.primaryjoin` condition.
  301. That is, if the :paramref:`~.relationship.primaryjoin`
  302. condition of this :func:`.relationship` is ``a.id ==
  303. b.a_id``, and the values in ``b.a_id`` are required to be
  304. present in ``a.id``, then the "foreign key" column of this
  305. :func:`.relationship` is ``b.a_id``.
  306. In normal cases, the :paramref:`~.relationship.foreign_keys`
  307. parameter is **not required.** :func:`.relationship` will
  308. automatically determine which columns in the
  309. :paramref:`~.relationship.primaryjoin` conditition are to be
  310. considered "foreign key" columns based on those
  311. :class:`.Column` objects that specify :class:`.ForeignKey`,
  312. or are otherwise listed as referencing columns in a
  313. :class:`.ForeignKeyConstraint` construct.
  314. :paramref:`~.relationship.foreign_keys` is only needed when:
  315. 1. There is more than one way to construct a join from the local
  316. table to the remote table, as there are multiple foreign key
  317. references present. Setting ``foreign_keys`` will limit the
  318. :func:`.relationship` to consider just those columns specified
  319. here as "foreign".
  320. .. versionchanged:: 0.8
  321. A multiple-foreign key join ambiguity can be resolved by
  322. setting the :paramref:`~.relationship.foreign_keys`
  323. parameter alone, without the need to explicitly set
  324. :paramref:`~.relationship.primaryjoin` as well.
  325. 2. The :class:`.Table` being mapped does not actually have
  326. :class:`.ForeignKey` or :class:`.ForeignKeyConstraint`
  327. constructs present, often because the table
  328. was reflected from a database that does not support foreign key
  329. reflection (MySQL MyISAM).
  330. 3. The :paramref:`~.relationship.primaryjoin` argument is used to
  331. construct a non-standard join condition, which makes use of
  332. columns or expressions that do not normally refer to their
  333. "parent" column, such as a join condition expressed by a
  334. complex comparison using a SQL function.
  335. The :func:`.relationship` construct will raise informative
  336. error messages that suggest the use of the
  337. :paramref:`~.relationship.foreign_keys` parameter when
  338. presented with an ambiguous condition. In typical cases,
  339. if :func:`.relationship` doesn't raise any exceptions, the
  340. :paramref:`~.relationship.foreign_keys` parameter is usually
  341. not needed.
  342. :paramref:`~.relationship.foreign_keys` may also be passed as a
  343. callable function which is evaluated at mapper initialization time,
  344. and may be passed as a Python-evaluable string when using
  345. Declarative.
  346. .. seealso::
  347. :ref:`relationship_foreign_keys`
  348. :ref:`relationship_custom_foreign`
  349. :func:`.foreign` - allows direct annotation of the "foreign"
  350. columns within a :paramref:`~.relationship.primaryjoin` condition.
  351. .. versionadded:: 0.8
  352. The :func:`.foreign` annotation can also be applied
  353. directly to the :paramref:`~.relationship.primaryjoin`
  354. expression, which is an alternate, more specific system of
  355. describing which columns in a particular
  356. :paramref:`~.relationship.primaryjoin` should be considered
  357. "foreign".
  358. :param info: Optional data dictionary which will be populated into the
  359. :attr:`.MapperProperty.info` attribute of this object.
  360. .. versionadded:: 0.8
  361. :param innerjoin=False:
  362. when ``True``, joined eager loads will use an inner join to join
  363. against related tables instead of an outer join. The purpose
  364. of this option is generally one of performance, as inner joins
  365. generally perform better than outer joins.
  366. This flag can be set to ``True`` when the relationship references an
  367. object via many-to-one using local foreign keys that are not
  368. nullable, or when the reference is one-to-one or a collection that
  369. is guaranteed to have one or at least one entry.
  370. The option supports the same "nested" and "unnested" options as
  371. that of :paramref:`.joinedload.innerjoin`. See that flag
  372. for details on nested / unnested behaviors.
  373. .. seealso::
  374. :paramref:`.joinedload.innerjoin` - the option as specified by
  375. loader option, including detail on nesting behavior.
  376. :ref:`what_kind_of_loading` - Discussion of some details of
  377. various loader options.
  378. :param join_depth:
  379. when non-``None``, an integer value indicating how many levels
  380. deep "eager" loaders should join on a self-referring or cyclical
  381. relationship. The number counts how many times the same Mapper
  382. shall be present in the loading condition along a particular join
  383. branch. When left at its default of ``None``, eager loaders
  384. will stop chaining when they encounter a the same target mapper
  385. which is already higher up in the chain. This option applies
  386. both to joined- and subquery- eager loaders.
  387. .. seealso::
  388. :ref:`self_referential_eager_loading` - Introductory documentation
  389. and examples.
  390. :param lazy='select': specifies
  391. how the related items should be loaded. Default value is
  392. ``select``. Values include:
  393. * ``select`` - items should be loaded lazily when the property is
  394. first accessed, using a separate SELECT statement, or identity map
  395. fetch for simple many-to-one references.
  396. * ``immediate`` - items should be loaded as the parents are loaded,
  397. using a separate SELECT statement, or identity map fetch for
  398. simple many-to-one references.
  399. * ``joined`` - items should be loaded "eagerly" in the same query as
  400. that of the parent, using a JOIN or LEFT OUTER JOIN. Whether
  401. the join is "outer" or not is determined by the
  402. :paramref:`~.relationship.innerjoin` parameter.
  403. * ``subquery`` - items should be loaded "eagerly" as the parents are
  404. loaded, using one additional SQL statement, which issues a JOIN to
  405. a subquery of the original statement, for each collection
  406. requested.
  407. * ``noload`` - no loading should occur at any time. This is to
  408. support "write-only" attributes, or attributes which are
  409. populated in some manner specific to the application.
  410. * ``raise`` - lazy loading is disallowed; accessing
  411. the attribute, if its value were not already loaded via eager
  412. loading, will raise an :exc:`~sqlalchemy.exc.InvalidRequestError`.
  413. This strategy can be used when objects are to be detached from
  414. their attached :class:`.Session` after they are loaded.
  415. .. versionadded:: 1.1
  416. * ``raise_on_sql`` - lazy loading that emits SQL is disallowed;
  417. accessing the attribute, if its value were not already loaded via
  418. eager loading, will raise an
  419. :exc:`~sqlalchemy.exc.InvalidRequestError`, **if the lazy load
  420. needs to emit SQL**. If the lazy load can pull the related value
  421. from the identity map or determine that it should be None, the
  422. value is loaded. This strategy can be used when objects will
  423. remain associated with the attached :class:`.Session`, however
  424. additional SELECT statements should be blocked.
  425. .. versionadded:: 1.1
  426. * ``dynamic`` - the attribute will return a pre-configured
  427. :class:`.Query` object for all read
  428. operations, onto which further filtering operations can be
  429. applied before iterating the results. See
  430. the section :ref:`dynamic_relationship` for more details.
  431. * True - a synonym for 'select'
  432. * False - a synonym for 'joined'
  433. * None - a synonym for 'noload'
  434. .. seealso::
  435. :doc:`/orm/loading_relationships` - Full documentation on relationship loader
  436. configuration.
  437. :ref:`dynamic_relationship` - detail on the ``dynamic`` option.
  438. :ref:`collections_noload_raiseload` - notes on "noload" and "raise"
  439. :param load_on_pending=False:
  440. Indicates loading behavior for transient or pending parent objects.
  441. When set to ``True``, causes the lazy-loader to
  442. issue a query for a parent object that is not persistent, meaning it
  443. has never been flushed. This may take effect for a pending object
  444. when autoflush is disabled, or for a transient object that has been
  445. "attached" to a :class:`.Session` but is not part of its pending
  446. collection.
  447. The :paramref:`~.relationship.load_on_pending` flag does not improve
  448. behavior when the ORM is used normally - object references should be
  449. constructed at the object level, not at the foreign key level, so
  450. that they are present in an ordinary way before a flush proceeds.
  451. This flag is not not intended for general use.
  452. .. seealso::
  453. :meth:`.Session.enable_relationship_loading` - this method
  454. establishes "load on pending" behavior for the whole object, and
  455. also allows loading on objects that remain transient or
  456. detached.
  457. :param order_by:
  458. indicates the ordering that should be applied when loading these
  459. items. :paramref:`~.relationship.order_by` is expected to refer to
  460. one of the :class:`.Column` objects to which the target class is
  461. mapped, or the attribute itself bound to the target class which
  462. refers to the column.
  463. :paramref:`~.relationship.order_by` may also be passed as a callable
  464. function which is evaluated at mapper initialization time, and may
  465. be passed as a Python-evaluable string when using Declarative.
  466. :param passive_deletes=False:
  467. Indicates loading behavior during delete operations.
  468. A value of True indicates that unloaded child items should not
  469. be loaded during a delete operation on the parent. Normally,
  470. when a parent item is deleted, all child items are loaded so
  471. that they can either be marked as deleted, or have their
  472. foreign key to the parent set to NULL. Marking this flag as
  473. True usually implies an ON DELETE <CASCADE|SET NULL> rule is in
  474. place which will handle updating/deleting child rows on the
  475. database side.
  476. Additionally, setting the flag to the string value 'all' will
  477. disable the "nulling out" of the child foreign keys, when there
  478. is no delete or delete-orphan cascade enabled. This is
  479. typically used when a triggering or error raise scenario is in
  480. place on the database side. Note that the foreign key
  481. attributes on in-session child objects will not be changed
  482. after a flush occurs so this is a very special use-case
  483. setting.
  484. .. seealso::
  485. :ref:`passive_deletes` - Introductory documentation
  486. and examples.
  487. :param passive_updates=True:
  488. Indicates the persistence behavior to take when a referenced
  489. primary key value changes in place, indicating that the referencing
  490. foreign key columns will also need their value changed.
  491. When True, it is assumed that ``ON UPDATE CASCADE`` is configured on
  492. the foreign key in the database, and that the database will
  493. handle propagation of an UPDATE from a source column to
  494. dependent rows. When False, the SQLAlchemy :func:`.relationship`
  495. construct will attempt to emit its own UPDATE statements to
  496. modify related targets. However note that SQLAlchemy **cannot**
  497. emit an UPDATE for more than one level of cascade. Also,
  498. setting this flag to False is not compatible in the case where
  499. the database is in fact enforcing referential integrity, unless
  500. those constraints are explicitly "deferred", if the target backend
  501. supports it.
  502. It is highly advised that an application which is employing
  503. mutable primary keys keeps ``passive_updates`` set to True,
  504. and instead uses the referential integrity features of the database
  505. itself in order to handle the change efficiently and fully.
  506. .. seealso::
  507. :ref:`passive_updates` - Introductory documentation and
  508. examples.
  509. :paramref:`.mapper.passive_updates` - a similar flag which
  510. takes effect for joined-table inheritance mappings.
  511. :param post_update:
  512. this indicates that the relationship should be handled by a
  513. second UPDATE statement after an INSERT or before a
  514. DELETE. Currently, it also will issue an UPDATE after the
  515. instance was UPDATEd as well, although this technically should
  516. be improved. This flag is used to handle saving bi-directional
  517. dependencies between two individual rows (i.e. each row
  518. references the other), where it would otherwise be impossible to
  519. INSERT or DELETE both rows fully since one row exists before the
  520. other. Use this flag when a particular mapping arrangement will
  521. incur two rows that are dependent on each other, such as a table
  522. that has a one-to-many relationship to a set of child rows, and
  523. also has a column that references a single child row within that
  524. list (i.e. both tables contain a foreign key to each other). If
  525. a flush operation returns an error that a "cyclical
  526. dependency" was detected, this is a cue that you might want to
  527. use :paramref:`~.relationship.post_update` to "break" the cycle.
  528. .. seealso::
  529. :ref:`post_update` - Introductory documentation and examples.
  530. :param primaryjoin:
  531. a SQL expression that will be used as the primary
  532. join of this child object against the parent object, or in a
  533. many-to-many relationship the join of the primary object to the
  534. association table. By default, this value is computed based on the
  535. foreign key relationships of the parent and child tables (or
  536. association table).
  537. :paramref:`~.relationship.primaryjoin` may also be passed as a
  538. callable function which is evaluated at mapper initialization time,
  539. and may be passed as a Python-evaluable string when using
  540. Declarative.
  541. .. seealso::
  542. :ref:`relationship_primaryjoin`
  543. :param remote_side:
  544. used for self-referential relationships, indicates the column or
  545. list of columns that form the "remote side" of the relationship.
  546. :paramref:`.relationship.remote_side` may also be passed as a
  547. callable function which is evaluated at mapper initialization time,
  548. and may be passed as a Python-evaluable string when using
  549. Declarative.
  550. .. versionchanged:: 0.8
  551. The :func:`.remote` annotation can also be applied
  552. directly to the ``primaryjoin`` expression, which is an
  553. alternate, more specific system of describing which columns in a
  554. particular ``primaryjoin`` should be considered "remote".
  555. .. seealso::
  556. :ref:`self_referential` - in-depth explanation of how
  557. :paramref:`~.relationship.remote_side`
  558. is used to configure self-referential relationships.
  559. :func:`.remote` - an annotation function that accomplishes the
  560. same purpose as :paramref:`~.relationship.remote_side`, typically
  561. when a custom :paramref:`~.relationship.primaryjoin` condition
  562. is used.
  563. :param query_class:
  564. a :class:`.Query` subclass that will be used as the base of the
  565. "appender query" returned by a "dynamic" relationship, that
  566. is, a relationship that specifies ``lazy="dynamic"`` or was
  567. otherwise constructed using the :func:`.orm.dynamic_loader`
  568. function.
  569. .. seealso::
  570. :ref:`dynamic_relationship` - Introduction to "dynamic"
  571. relationship loaders.
  572. :param secondaryjoin:
  573. a SQL expression that will be used as the join of
  574. an association table to the child object. By default, this value is
  575. computed based on the foreign key relationships of the association
  576. and child tables.
  577. :paramref:`~.relationship.secondaryjoin` may also be passed as a
  578. callable function which is evaluated at mapper initialization time,
  579. and may be passed as a Python-evaluable string when using
  580. Declarative.
  581. .. seealso::
  582. :ref:`relationship_primaryjoin`
  583. :param single_parent:
  584. when True, installs a validator which will prevent objects
  585. from being associated with more than one parent at a time.
  586. This is used for many-to-one or many-to-many relationships that
  587. should be treated either as one-to-one or one-to-many. Its usage
  588. is optional, except for :func:`.relationship` constructs which
  589. are many-to-one or many-to-many and also
  590. specify the ``delete-orphan`` cascade option. The
  591. :func:`.relationship` construct itself will raise an error
  592. instructing when this option is required.
  593. .. seealso::
  594. :ref:`unitofwork_cascades` - includes detail on when the
  595. :paramref:`~.relationship.single_parent` flag may be appropriate.
  596. :param uselist:
  597. a boolean that indicates if this property should be loaded as a
  598. list or a scalar. In most cases, this value is determined
  599. automatically by :func:`.relationship` at mapper configuration
  600. time, based on the type and direction
  601. of the relationship - one to many forms a list, many to one
  602. forms a scalar, many to many is a list. If a scalar is desired
  603. where normally a list would be present, such as a bi-directional
  604. one-to-one relationship, set :paramref:`~.relationship.uselist` to
  605. False.
  606. The :paramref:`~.relationship.uselist` flag is also available on an
  607. existing :func:`.relationship` construct as a read-only attribute,
  608. which can be used to determine if this :func:`.relationship` deals
  609. with collections or scalar attributes::
  610. >>> User.addresses.property.uselist
  611. True
  612. .. seealso::
  613. :ref:`relationships_one_to_one` - Introduction to the "one to
  614. one" relationship pattern, which is typically when the
  615. :paramref:`~.relationship.uselist` flag is needed.
  616. :param viewonly=False:
  617. when set to True, the relationship is used only for loading objects,
  618. and not for any persistence operation. A :func:`.relationship`
  619. which specifies :paramref:`~.relationship.viewonly` can work
  620. with a wider range of SQL operations within the
  621. :paramref:`~.relationship.primaryjoin` condition, including
  622. operations that feature the use of a variety of comparison operators
  623. as well as SQL functions such as :func:`~.sql.expression.cast`. The
  624. :paramref:`~.relationship.viewonly` flag is also of general use when
  625. defining any kind of :func:`~.relationship` that doesn't represent
  626. the full set of related objects, to prevent modifications of the
  627. collection from resulting in persistence operations.
  628. """
  629. super(RelationshipProperty, self).__init__()
  630. self.uselist = uselist
  631. self.argument = argument
  632. self.secondary = secondary
  633. self.primaryjoin = primaryjoin
  634. self.secondaryjoin = secondaryjoin
  635. self.post_update = post_update
  636. self.direction = None
  637. self.viewonly = viewonly
  638. self.lazy = lazy
  639. self.single_parent = single_parent
  640. self._user_defined_foreign_keys = foreign_keys
  641. self.collection_class = collection_class
  642. self.passive_deletes = passive_deletes
  643. self.cascade_backrefs = cascade_backrefs
  644. self.passive_updates = passive_updates
  645. self.remote_side = remote_side
  646. self.enable_typechecks = enable_typechecks
  647. self.query_class = query_class
  648. self.innerjoin = innerjoin
  649. self.distinct_target_key = distinct_target_key
  650. self.doc = doc
  651. self.active_history = active_history
  652. self.join_depth = join_depth
  653. self.local_remote_pairs = _local_remote_pairs
  654. self.extension = extension
  655. self.bake_queries = bake_queries
  656. self.load_on_pending = load_on_pending
  657. self.comparator_factory = comparator_factory or \
  658. RelationshipProperty.Comparator
  659. self.comparator = self.comparator_factory(self, None)
  660. util.set_creation_order(self)
  661. if info is not None:
  662. self.info = info
  663. self.strategy_key = (("lazy", self.lazy), )
  664. self._reverse_property = set()
  665. self.cascade = cascade if cascade is not False \
  666. else "save-update, merge"
  667. self.order_by = order_by
  668. self.back_populates = back_populates
  669. if self.back_populates:
  670. if backref:
  671. raise sa_exc.ArgumentError(
  672. "backref and back_populates keyword arguments "
  673. "are mutually exclusive")
  674. self.backref = None
  675. else:
  676. self.backref = backref
  677. def instrument_class(self, mapper):
  678. attributes.register_descriptor(
  679. mapper.class_,
  680. self.key,
  681. comparator=self.comparator_factory(self, mapper),
  682. parententity=mapper,
  683. doc=self.doc,
  684. )
  685. class Comparator(PropComparator):
  686. """Produce boolean, comparison, and other operators for
  687. :class:`.RelationshipProperty` attributes.
  688. See the documentation for :class:`.PropComparator` for a brief
  689. overview of ORM level operator definition.
  690. See also:
  691. :class:`.PropComparator`
  692. :class:`.ColumnProperty.Comparator`
  693. :class:`.ColumnOperators`
  694. :ref:`types_operators`
  695. :attr:`.TypeEngine.comparator_factory`
  696. """
  697. _of_type = None
  698. def __init__(
  699. self, prop, parentmapper, adapt_to_entity=None, of_type=None):
  700. """Construction of :class:`.RelationshipProperty.Comparator`
  701. is internal to the ORM's attribute mechanics.
  702. """
  703. self.prop = prop
  704. self._parententity = parentmapper
  705. self._adapt_to_entity = adapt_to_entity
  706. if of_type:
  707. self._of_type = of_type
  708. def adapt_to_entity(self, adapt_to_entity):
  709. return self.__class__(self.property, self._parententity,
  710. adapt_to_entity=adapt_to_entity,
  711. of_type=self._of_type)
  712. @util.memoized_property
  713. def mapper(self):
  714. """The target :class:`.Mapper` referred to by this
  715. :class:`.RelationshipProperty.Comparator`.
  716. This is the "target" or "remote" side of the
  717. :func:`.relationship`.
  718. """
  719. return self.property.mapper
  720. @util.memoized_property
  721. def _parententity(self):
  722. return self.property.parent
  723. def _source_selectable(self):
  724. if self._adapt_to_entity:
  725. return self._adapt_to_entity.selectable
  726. else:
  727. return self.property.parent._with_polymorphic_selectable
  728. def __clause_element__(self):
  729. adapt_from = self._source_selectable()
  730. if self._of_type:
  731. of_type = inspect(self._of_type).mapper
  732. else:
  733. of_type = None
  734. pj, sj, source, dest, \
  735. secondary, target_adapter = self.property._create_joins(
  736. source_selectable=adapt_from,
  737. source_polymorphic=True,
  738. of_type=of_type)
  739. if sj is not None:
  740. return pj & sj
  741. else:
  742. return pj
  743. def of_type(self, cls):
  744. """Produce a construct that represents a particular 'subtype' of
  745. attribute for the parent class.
  746. Currently this is usable in conjunction with :meth:`.Query.join`
  747. and :meth:`.Query.outerjoin`.
  748. """
  749. return RelationshipProperty.Comparator(
  750. self.property,
  751. self._parententity,
  752. adapt_to_entity=self._adapt_to_entity,
  753. of_type=cls)
  754. def in_(self, other):
  755. """Produce an IN clause - this is not implemented
  756. for :func:`~.orm.relationship`-based attributes at this time.
  757. """
  758. raise NotImplementedError('in_() not yet supported for '
  759. 'relationships. For a simple '
  760. 'many-to-one, use in_() against '
  761. 'the set of foreign key values.')
  762. __hash__ = None
  763. def __eq__(self, other):
  764. """Implement the ``==`` operator.
  765. In a many-to-one context, such as::
  766. MyClass.some_prop == <some object>
  767. this will typically produce a
  768. clause such as::
  769. mytable.related_id == <some id>
  770. Where ``<some id>`` is the primary key of the given
  771. object.
  772. The ``==`` operator provides partial functionality for non-
  773. many-to-one comparisons:
  774. * Comparisons against collections are not supported.
  775. Use :meth:`~.RelationshipProperty.Comparator.contains`.
  776. * Compared to a scalar one-to-many, will produce a
  777. clause that compares the target columns in the parent to
  778. the given target.
  779. * Compared to a scalar many-to-many, an alias
  780. of the association table will be rendered as
  781. well, forming a natural join that is part of the
  782. main body of the query. This will not work for
  783. queries that go beyond simple AND conjunctions of
  784. comparisons, such as those which use OR. Use
  785. explicit joins, outerjoins, or
  786. :meth:`~.RelationshipProperty.Comparator.has` for
  787. more comprehensive non-many-to-one scalar
  788. membership tests.
  789. * Comparisons against ``None`` given in a one-to-many
  790. or many-to-many context produce a NOT EXISTS clause.
  791. """
  792. if isinstance(other, (util.NoneType, expression.Null)):
  793. if self.property.direction in [ONETOMANY, MANYTOMANY]:
  794. return ~self._criterion_exists()
  795. else:
  796. return _orm_annotate(self.property._optimized_compare(
  797. None, adapt_source=self.adapter))
  798. elif self.property.uselist:
  799. raise sa_exc.InvalidRequestError(
  800. "Can't compare a collection to an object or collection; "
  801. "use contains() to test for membership.")
  802. else:
  803. return _orm_annotate(
  804. self.property._optimized_compare(
  805. other, adapt_source=self.adapter))
  806. def _criterion_exists(self, criterion=None, **kwargs):
  807. if getattr(self, '_of_type', None):
  808. info = inspect(self._of_type)
  809. target_mapper, to_selectable, is_aliased_class = \
  810. info.mapper, info.selectable, info.is_aliased_class
  811. if self.property._is_self_referential and not \
  812. is_aliased_class:
  813. to_selectable = to_selectable.alias()
  814. single_crit = target_mapper._single_table_criterion
  815. if single_crit is not None:
  816. if criterion is not None:
  817. criterion = single_crit & criterion
  818. else:
  819. criterion = single_crit
  820. else:
  821. is_aliased_class = False
  822. to_selectable = None
  823. if self.adapter:
  824. source_selectable = self._source_selectable()
  825. else:
  826. source_selectable = None
  827. pj, sj, source, dest, secondary, target_adapter = \
  828. self.property._create_joins(
  829. dest_polymorphic=True,
  830. dest_selectable=to_selectable,
  831. source_selectable=source_selectable)
  832. for k in kwargs:
  833. crit = getattr(self.property.mapper.class_, k) == kwargs[k]
  834. if criterion is None:
  835. criterion = crit
  836. else:
  837. criterion = criterion & crit
  838. # annotate the *local* side of the join condition, in the case
  839. # of pj + sj this is the full primaryjoin, in the case of just
  840. # pj its the local side of the primaryjoin.
  841. if sj is not None:
  842. j = _orm_annotate(pj) & sj
  843. else:
  844. j = _orm_annotate(pj, exclude=self.property.remote_side)
  845. if criterion is not None and target_adapter and not \
  846. is_aliased_class:
  847. # limit this adapter to annotated only?
  848. criterion = target_adapter.traverse(criterion)
  849. # only have the "joined left side" of what we
  850. # return be subject to Query adaption. The right
  851. # side of it is used for an exists() subquery and
  852. # should not correlate or otherwise reach out
  853. # to anything in the enclosing query.
  854. if criterion is not None:
  855. criterion = criterion._annotate(
  856. {'no_replacement_traverse': True})
  857. crit = j & sql.True_._ifnone(criterion)
  858. ex = sql.exists([1], crit, from_obj=dest).correlate_except(dest)
  859. if secondary is not None:
  860. ex = ex.correlate_except(secondary)
  861. return ex
  862. def any(self, criterion=None, **kwargs):
  863. """Produce an expression that tests a collection against
  864. particular criterion, using EXISTS.
  865. An expression like::
  866. session.query(MyClass).filter(
  867. MyClass.somereference.any(SomeRelated.x==2)
  868. )
  869. Will produce a query like::
  870. SELECT * FROM my_table WHERE
  871. EXISTS (SELECT 1 FROM related WHERE related.my_id=my_table.id
  872. AND related.x=2)
  873. Because :meth:`~.RelationshipProperty.Comparator.any` uses
  874. a correlated subquery, its performance is not nearly as
  875. good when compared against large target tables as that of
  876. using a join.
  877. :meth:`~.RelationshipProperty.Comparator.any` is particularly
  878. useful for testing for empty collections::
  879. session.query(MyClass).filter(
  880. ~MyClass.somereference.any()
  881. )
  882. will produce::
  883. SELECT * FROM my_table WHERE
  884. NOT EXISTS (SELECT 1 FROM related WHERE
  885. related.my_id=my_table.id)
  886. :meth:`~.RelationshipProperty.Comparator.any` is only
  887. valid for collections, i.e. a :func:`.relationship`
  888. that has ``uselist=True``. For scalar references,
  889. use :meth:`~.RelationshipProperty.Comparator.has`.
  890. """
  891. if not self.property.uselist:
  892. raise sa_exc.InvalidRequestError(
  893. "'any()' not implemented for scalar "
  894. "attributes. Use has()."
  895. )
  896. return self._criterion_exists(criterion, **kwargs)
  897. def has(self, criterion=None, **kwargs):
  898. """Produce an expression that tests a scalar reference against
  899. particular criterion, using EXISTS.
  900. An expression like::
  901. session.query(MyClass).filter(
  902. MyClass.somereference.has(SomeRelated.x==2)
  903. )
  904. Will produce a query like::
  905. SELECT * FROM my_table WHERE
  906. EXISTS (SELECT 1 FROM related WHERE
  907. related.id==my_table.related_id AND related.x=2)
  908. Because :meth:`~.RelationshipProperty.Comparator.has` uses
  909. a correlated subquery, its performance is not nearly as
  910. good when compared against large target tables as that of
  911. using a join.
  912. :meth:`~.RelationshipProperty.Comparator.has` is only
  913. valid for scalar references, i.e. a :func:`.relationship`
  914. that has ``uselist=False``. For collection references,
  915. use :meth:`~.RelationshipProperty.Comparator.any`.
  916. """
  917. if self.property.uselist:
  918. raise sa_exc.InvalidRequestError(
  919. "'has()' not implemented for collections. "
  920. "Use any().")
  921. return self._criterion_exists(criterion, **kwargs)
  922. def contains(self, other, **kwargs):
  923. """Return a simple expression that tests a collection for
  924. containment of a particular item.
  925. :meth:`~.RelationshipProperty.Comparator.contains` is
  926. only valid for a collection, i.e. a
  927. :func:`~.orm.relationship` that implements
  928. one-to-many or many-to-many with ``uselist=True``.
  929. When used in a simple one-to-many context, an
  930. expression like::
  931. MyClass.contains(other)
  932. Produces a clause like::
  933. mytable.id == <some id>
  934. Where ``<some id>`` is the value of the foreign key
  935. attribute on ``other`` which refers to the primary
  936. key of its parent object. From this it follows that
  937. :meth:`~.RelationshipProperty.Comparator.contains` is
  938. very useful when used with simple one-to-many
  939. operations.
  940. For many-to-many operations, the behavior of
  941. :meth:`~.RelationshipProperty.Comparator.contains`
  942. has more caveats. The association table will be
  943. rendered in the statement, producing an "implicit"
  944. join, that is, includes multiple tables in the FROM
  945. clause which are equated in the WHERE clause::
  946. query(MyClass).filter(MyClass.contains(other))
  947. Produces a query like::
  948. SELECT * FROM my_table, my_association_table AS
  949. my_association_table_1 WHERE
  950. my_table.id = my_association_table_1.parent_id
  951. AND my_association_table_1.child_id = <some id>
  952. Where ``<some id>`` would be the primary key of
  953. ``other``. From the above, it is clear that
  954. :meth:`~.RelationshipProperty.Comparator.contains`
  955. will **not** work with many-to-many collections when
  956. used in queries that move beyond simple AND
  957. conjunctions, such as multiple
  958. :meth:`~.RelationshipProperty.Comparator.contains`
  959. expressions joined by OR. In such cases subqueries or
  960. explicit "outer joins" will need to be used instead.
  961. See :meth:`~.RelationshipProperty.Comparator.any` for
  962. a less-performant alternative using EXISTS, or refer
  963. to :meth:`.Query.outerjoin` as well as :ref:`ormtutorial_joins`
  964. for more details on constructing outer joins.
  965. """
  966. if not self.property.uselist:
  967. raise sa_exc.InvalidRequestError(
  968. "'contains' not implemented for scalar "
  969. "attributes. Use ==")
  970. clause = self.property._optimized_compare(
  971. other, adapt_source=self.adapter)
  972. if self.property.secondaryjoin is not None:
  973. clause.negation_clause = \
  974. self.__negated_contains_or_equals(other)
  975. return clause
  976. def __negated_contains_or_equals(self, other):
  977. if self.property.direction == MANYTOONE:
  978. state = attributes.instance_state(other)
  979. def state_bindparam(x, state, col):
  980. dict_ = state.dict
  981. return sql.bindparam(
  982. x, unique=True,
  983. callable_=self.property._get_attr_w_warn_on_none(
  984. col,
  985. self.property.mapper._get_state_attr_by_column,
  986. state, dict_, col, passive=attributes.PASSIVE_OFF
  987. )
  988. )
  989. def adapt(col):
  990. if self.adapter:
  991. return self.adapter(col)
  992. else:
  993. return col
  994. if self.property._use_get:
  995. return sql.and_(*[
  996. sql.or_(
  997. adapt(x) != state_bindparam(adapt(x), state, y),
  998. adapt(x) == None)
  999. for (x, y) in self.property.local_remote_pairs])
  1000. criterion = sql.and_(*[
  1001. x == y for (x, y) in
  1002. zip(
  1003. self.property.mapper.primary_key,
  1004. self.property.mapper.primary_key_from_instance(other)
  1005. )
  1006. ])
  1007. return ~self._criterion_exists(criterion)
  1008. def __ne__(self, other):
  1009. """Implement the ``!=`` operator.
  1010. In a many-to-one context, such as::
  1011. MyClass.some_prop != <some object>
  1012. This will typically produce a clause such as::
  1013. mytable.related_id != <some id>
  1014. Where ``<some id>`` is the primary key of the
  1015. given object.
  1016. The ``!=`` operator provides partial functionality for non-
  1017. many-to-one comparisons:
  1018. * Comparisons against collections are not supported.
  1019. Use
  1020. :meth:`~.RelationshipProperty.Comparator.contains`
  1021. in conjunction with :func:`~.expression.not_`.
  1022. * Compared to a scalar one-to-many, will produce a
  1023. clause that compares the target columns in the parent to
  1024. the given target.
  1025. * Compared to a scalar many-to-many, an alias
  1026. of the association table will be rendered as
  1027. well, forming a natural join that is part of the
  1028. main body of the query. This will not work for
  1029. queries that go beyond simple AND conjunctions of
  1030. comparisons, such as those which use OR. Use
  1031. explicit joins, outerjoins, or
  1032. :meth:`~.RelationshipProperty.Comparator.has` in
  1033. conjunction with :func:`~.expression.not_` for
  1034. more comprehensive non-many-to-one scalar
  1035. membership tests.
  1036. * Comparisons against ``None`` given in a one-to-many
  1037. or many-to-many context produce an EXISTS clause.
  1038. """
  1039. if isinstance(other, (util.NoneType, expression.Null)):
  1040. if self.property.direction == MANYTOONE:
  1041. return _orm_annotate(~self.property._optimized_compare(
  1042. None, adapt_source=self.adapter))
  1043. else:
  1044. return self._criterion_exists()
  1045. elif self.property.uselist:
  1046. raise sa_exc.InvalidRequestError(
  1047. "Can't compare a collection"
  1048. " to an object or collection; use "
  1049. "contains() to test for membership.")
  1050. else:
  1051. return _orm_annotate(self.__negated_contains_or_equals(other))
  1052. @util.memoized_property
  1053. def property(self):
  1054. if mapperlib.Mapper._new_mappers:
  1055. mapperlib.Mapper._configure_all()
  1056. return self.prop
  1057. def _with_parent(self, instance, alias_secondary=True):
  1058. assert instance is not None
  1059. return self._optimized_compare(
  1060. instance, value_is_parent=True, alias_secondary=alias_secondary)
  1061. def _optimized_compare(self, state, value_is_parent=False,
  1062. adapt_source=None,
  1063. alias_secondary=True):
  1064. if state is not None:
  1065. state = attributes.instance_state(state)
  1066. reverse_direction = not value_is_parent
  1067. if state is None:
  1068. return self._lazy_none_clause(
  1069. reverse_direction,
  1070. adapt_source=adapt_source)
  1071. if not reverse_direction:
  1072. criterion, bind_to_col = \
  1073. self._lazy_strategy._lazywhere, \
  1074. self._lazy_strategy._bind_to_col
  1075. else:
  1076. criterion, bind_to_col = \
  1077. self._lazy_strategy._rev_lazywhere, \
  1078. self._lazy_strategy._rev_bind_to_col
  1079. if reverse_direction:
  1080. mapper = self.mapper
  1081. else:
  1082. mapper = self.parent
  1083. dict_ = attributes.instance_dict(state.obj())
  1084. def visit_bindparam(bindparam):
  1085. if bindparam._identifying_key in bind_to_col:
  1086. bindparam.callable = self._get_attr_w_warn_on_none(
  1087. bind_to_col[bindparam._identifying_key],
  1088. mapper._get_state_attr_by_column,
  1089. state, dict_,
  1090. bind_to_col[bindparam._identifying_key],
  1091. passive=attributes.PASSIVE_OFF)
  1092. if self.secondary is not None and alias_secondary:
  1093. criterion = ClauseAdapter(
  1094. self.secondary.alias()).\
  1095. traverse(criterion)
  1096. criterion = visitors.cloned_traverse(
  1097. criterion, {}, {'bindparam': visit_bindparam})
  1098. if adapt_source:
  1099. criterion = adapt_source(criterion)
  1100. return criterion
  1101. def _get_attr_w_warn_on_none(self, column, fn, *arg, **kw):
  1102. def _go():
  1103. value = fn(*arg, **kw)
  1104. if value is None:
  1105. util.warn(
  1106. "Got None for value of column %s; this is unsupported "
  1107. "for a relationship comparison and will not "
  1108. "currently produce an IS comparison "
  1109. "(but may in a future release)" % column)
  1110. return value
  1111. return _go
  1112. def _lazy_none_clause(self, reverse_direction=False, adapt_source=None):
  1113. if not reverse_direction:
  1114. criterion, bind_to_col = \
  1115. self._lazy_strategy._lazywhere, \
  1116. self._lazy_strategy._bind_to_col
  1117. else:
  1118. criterion, bind_to_col = \
  1119. self._lazy_strategy._rev_lazywhere, \
  1120. self._lazy_strategy._rev_bind_to_col
  1121. criterion = adapt_criterion_to_null(criterion, bind_to_col)
  1122. if adapt_source:
  1123. criterion = adapt_source(criterion)
  1124. return criterion
  1125. def __str__(self):
  1126. return str(self.parent.class_.__name__) + "." + self.key
  1127. def merge(self,
  1128. session,
  1129. source_state,
  1130. source_dict,
  1131. dest_state,
  1132. dest_dict,
  1133. load, _recursive, _resolve_conflict_map):
  1134. if load:
  1135. for r in self._reverse_property:
  1136. if (source_state, r) in _recursive:
  1137. return
  1138. if "merge" not in self._cascade:
  1139. return
  1140. if self.key not in source_dict:
  1141. return
  1142. if self.uselist:
  1143. instances = source_state.get_impl(self.key).\
  1144. get(source_state, source_dict)
  1145. if hasattr(instances, '_sa_adapter'):
  1146. # convert collections to adapters to get a true iterator
  1147. instances = instances._sa_adapter
  1148. if load:
  1149. # for a full merge, pre-load the destination collection,
  1150. # so that individual _merge of each item pulls from identity
  1151. # map for those already present.
  1152. # also assumes CollectionAttrbiuteImpl behavior of loading
  1153. # "old" list in any case
  1154. dest_state.get_impl(self.key).get(dest_state, dest_dict)
  1155. dest_list = []
  1156. for current in instances:
  1157. current_state = attributes.instance_state(current)
  1158. current_dict = attributes.instance_dict(current)
  1159. _recursive[(current_state, self)] = True
  1160. obj = session._merge(
  1161. current_state, current_dict,
  1162. load=load, _recursive=_recursive,
  1163. _resolve_conflict_map=_resolve_conflict_map)
  1164. if obj is not None:
  1165. dest_list.append(obj)
  1166. if not load:
  1167. coll = attributes.init_state_collection(dest_state,
  1168. dest_dict, self.key)
  1169. for c in dest_list:
  1170. coll.append_without_event(c)
  1171. else:
  1172. dest_state.get_impl(self.key).set(
  1173. dest_state, dest_dict, dest_list,
  1174. _adapt=False)
  1175. else:
  1176. current = source_dict[self.key]
  1177. if current is not None:
  1178. current_state = attributes.instance_state(current)
  1179. current_dict = attributes.instance_dict(current)
  1180. _recursive[(current_state, self)] = True
  1181. obj = session._merge(
  1182. current_state, current_dict,
  1183. load=load, _recursive=_recursive,
  1184. _resolve_conflict_map=_resolve_conflict_map)
  1185. else:
  1186. obj = None
  1187. if not load:
  1188. dest_dict[self.key] = obj
  1189. else:
  1190. dest_state.get_impl(self.key).set(dest_state,
  1191. dest_dict, obj, None)
  1192. def _value_as_iterable(self, state, dict_, key,
  1193. passive=attributes.PASSIVE_OFF):
  1194. """Return a list of tuples (state, obj) for the given
  1195. key.
  1196. returns an empty list if the value is None/empty/PASSIVE_NO_RESULT
  1197. """
  1198. impl = state.manager[key].impl
  1199. x = impl.get(state, dict_, passive=passive)
  1200. if x is attributes.PASSIVE_NO_RESULT or x is None:
  1201. return []
  1202. elif hasattr(impl, 'get_collection'):
  1203. return [
  1204. (attributes.instance_state(o), o) for o in
  1205. impl.get_collection(state, dict_, x, passive=passive)
  1206. ]
  1207. else:
  1208. return [(attributes.instance_state(x), x)]
  1209. def cascade_iterator(self, type_, state, dict_,
  1210. visited_states, halt_on=None):
  1211. # assert type_ in self._cascade
  1212. # only actively lazy load on the 'delete' cascade
  1213. if type_ != 'delete' or self.passive_deletes:
  1214. passive = attributes.PASSIVE_NO_INITIALIZE
  1215. else:
  1216. passive = attributes.PASSIVE_OFF
  1217. if type_ == 'save-update':
  1218. tuples = state.manager[self.key].impl.\
  1219. get_all_pending(state, dict_)
  1220. else:
  1221. tuples = self._value_as_iterable(state, dict_, self.key,
  1222. passive=passive)
  1223. skip_pending = type_ == 'refresh-expire' and 'delete-orphan' \
  1224. not in self._cascade
  1225. for instance_state, c in tuples:
  1226. if instance_state in visited_states:
  1227. continue
  1228. if c is None:
  1229. # would like to emit a warning here, but
  1230. # would not be consistent with collection.append(None)
  1231. # current behavior of silently skipping.
  1232. # see [ticket:2229]
  1233. continue
  1234. instance_dict = attributes.instance_dict(c)
  1235. if halt_on and halt_on(instance_state):
  1236. continue
  1237. if skip_pending and not instance_state.key:
  1238. continue
  1239. instance_mapper = instance_state.manager.mapper
  1240. if not instance_mapper.isa(self.mapper.class_manager.mapper):
  1241. raise AssertionError("Attribute '%s' on class '%s' "
  1242. "doesn't handle objects "
  1243. "of type '%s'" % (
  1244. self.key,
  1245. self.parent.class_,
  1246. c.__class__
  1247. ))
  1248. visited_states.add(instance_state)
  1249. yield c, instance_mapper, instance_state, instance_dict
  1250. def _add_reverse_property(self, key):
  1251. other = self.mapper.get_property(key, _configure_mappers=False)
  1252. self._reverse_property.add(other)
  1253. other._reverse_property.add(self)
  1254. if not other.mapper.common_parent(self.parent):
  1255. raise sa_exc.ArgumentError(
  1256. 'reverse_property %r on '
  1257. 'relationship %s references relationship %s, which '
  1258. 'does not reference mapper %s' %
  1259. (key, self, other, self.parent))
  1260. if self.direction in (ONETOMANY, MANYTOONE) and self.direction \
  1261. == other.direction:
  1262. raise sa_exc.ArgumentError(
  1263. '%s and back-reference %s are '
  1264. 'both of the same direction %r. Did you mean to '
  1265. 'set remote_side on the many-to-one side ?' %
  1266. (other, self, self.direction))
  1267. @util.memoized_property
  1268. def mapper(self):
  1269. """Return the targeted :class:`.Mapper` for this
  1270. :class:`.RelationshipProperty`.
  1271. This is a lazy-initializing static attribute.
  1272. """
  1273. if util.callable(self.argument) and \
  1274. not isinstance(self.argument, (type, mapperlib.Mapper)):
  1275. argument = self.argument()
  1276. else:
  1277. argument = self.argument
  1278. if isinstance(argument, type):
  1279. mapper_ = mapperlib.class_mapper(argument,
  1280. configure=False)
  1281. elif isinstance(self.argument, mapperlib.Mapper):
  1282. mapper_ = argument
  1283. else:
  1284. raise sa_exc.ArgumentError(
  1285. "relationship '%s' expects "
  1286. "a class or a mapper argument (received: %s)"
  1287. % (self.key, type(argument)))
  1288. return mapper_
  1289. @util.memoized_property
  1290. @util.deprecated("0.7", "Use .target")
  1291. def table(self):
  1292. """Return the selectable linked to this
  1293. :class:`.RelationshipProperty` object's target
  1294. :class:`.Mapper`.
  1295. """
  1296. return self.target
  1297. def do_init(self):
  1298. self._check_conflicts()
  1299. self._process_dependent_arguments()
  1300. self._setup_join_conditions()
  1301. self._check_cascade_settings(self._cascade)
  1302. self._post_init()
  1303. self._generate_backref()
  1304. self._join_condition._warn_for_conflicting_sync_targets()
  1305. super(RelationshipProperty, self).do_init()
  1306. self._lazy_strategy = self._get_strategy((("lazy", "select"),))
  1307. def _process_dependent_arguments(self):
  1308. """Convert incoming configuration arguments to their
  1309. proper form.
  1310. Callables are resolved, ORM annotations removed.
  1311. """
  1312. # accept callables for other attributes which may require
  1313. # deferred initialization. This technique is used
  1314. # by declarative "string configs" and some recipes.
  1315. for attr in (
  1316. 'order_by', 'primaryjoin', 'secondaryjoin',
  1317. 'secondary', '_user_defined_foreign_keys', 'remote_side',
  1318. ):
  1319. attr_value = getattr(self, attr)
  1320. if util.callable(attr_value):
  1321. setattr(self, attr, attr_value())
  1322. # remove "annotations" which are present if mapped class
  1323. # descriptors are used to create the join expression.
  1324. for attr in 'primaryjoin', 'secondaryjoin':
  1325. val = getattr(self, attr)
  1326. if val is not None:
  1327. setattr(self, attr, _orm_deannotate(
  1328. expression._only_column_elements(val, attr))
  1329. )
  1330. # ensure expressions in self.order_by, foreign_keys,
  1331. # remote_side are all columns, not strings.
  1332. if self.order_by is not False and self.order_by is not None:
  1333. self.order_by = [
  1334. expression._only_column_elements(x, "order_by")
  1335. for x in
  1336. util.to_list(self.order_by)]
  1337. self._user_defined_foreign_keys = \
  1338. util.column_set(
  1339. expression._only_column_elements(x, "foreign_keys")
  1340. for x in util.to_column_set(
  1341. self._user_defined_foreign_keys
  1342. ))
  1343. self.remote_side = \
  1344. util.column_set(
  1345. expression._only_column_elements(x, "remote_side")
  1346. for x in
  1347. util.to_column_set(self.remote_side))
  1348. self.target = self.mapper.mapped_table
  1349. def _setup_join_conditions(self):
  1350. self._join_condition = jc = JoinCondition(
  1351. parent_selectable=self.parent.mapped_table,
  1352. child_selectable=self.mapper.mapped_table,
  1353. parent_local_selectable=self.parent.local_table,
  1354. child_local_selectable=self.mapper.local_table,
  1355. primaryjoin=self.primaryjoin,
  1356. secondary=self.secondary,
  1357. secondaryjoin=self.secondaryjoin,
  1358. parent_equivalents=self.parent._equivalent_columns,
  1359. child_equivalents=self.mapper._equivalent_columns,
  1360. consider_as_foreign_keys=self._user_defined_foreign_keys,
  1361. local_remote_pairs=self.local_remote_pairs,
  1362. remote_side=self.remote_side,
  1363. self_referential=self._is_self_referential,
  1364. prop=self,
  1365. support_sync=not self.viewonly,
  1366. can_be_synced_fn=self._columns_are_mapped
  1367. )
  1368. self.primaryjoin = jc.deannotated_primaryjoin
  1369. self.secondaryjoin = jc.deannotated_secondaryjoin
  1370. self.direction = jc.direction
  1371. self.local_remote_pairs = jc.local_remote_pairs
  1372. self.remote_side = jc.remote_columns
  1373. self.local_columns = jc.local_columns
  1374. self.synchronize_pairs = jc.synchronize_pairs
  1375. self._calculated_foreign_keys = jc.foreign_key_columns
  1376. self.secondary_synchronize_pairs = jc.secondary_synchronize_pairs
  1377. def _check_conflicts(self):
  1378. """Test that this relationship is legal, warn about
  1379. inheritance conflicts."""
  1380. if self.parent.non_primary and not mapperlib.class_mapper(
  1381. self.parent.class_,
  1382. configure=False).has_property(self.key):
  1383. raise sa_exc.ArgumentError(
  1384. "Attempting to assign a new "
  1385. "relationship '%s' to a non-primary mapper on "
  1386. "class '%s'. New relationships can only be added "
  1387. "to the primary mapper, i.e. the very first mapper "
  1388. "created for class '%s' " %
  1389. (self.key, self.parent.class_.__name__,
  1390. self.parent.class_.__name__))
  1391. def _get_cascade(self):
  1392. """Return the current cascade setting for this
  1393. :class:`.RelationshipProperty`.
  1394. """
  1395. return self._cascade
  1396. def _set_cascade(self, cascade):
  1397. cascade = CascadeOptions(cascade)
  1398. if 'mapper' in self.__dict__:
  1399. self._check_cascade_settings(cascade)
  1400. self._cascade = cascade
  1401. if self._dependency_processor:
  1402. self._dependency_processor.cascade = cascade
  1403. cascade = property(_get_cascade, _set_cascade)
  1404. def _check_cascade_settings(self, cascade):
  1405. if cascade.delete_orphan and not self.single_parent \
  1406. and (self.direction is MANYTOMANY or self.direction
  1407. is MANYTOONE):
  1408. raise sa_exc.ArgumentError(
  1409. 'On %s, delete-orphan cascade is not supported '
  1410. 'on a many-to-many or many-to-one relationship '
  1411. 'when single_parent is not set. Set '
  1412. 'single_parent=True on the relationship().'
  1413. % self)
  1414. if self.direction is MANYTOONE and self.passive_deletes:
  1415. util.warn("On %s, 'passive_deletes' is normally configured "
  1416. "on one-to-many, one-to-one, many-to-many "
  1417. "relationships only."
  1418. % self)
  1419. if self.passive_deletes == 'all' and \
  1420. ("delete" in cascade or
  1421. "delete-orphan" in cascade):
  1422. raise sa_exc.ArgumentError(
  1423. "On %s, can't set passive_deletes='all' in conjunction "
  1424. "with 'delete' or 'delete-orphan' cascade" % self)
  1425. if cascade.delete_orphan:
  1426. self.mapper.primary_mapper()._delete_orphans.append(
  1427. (self.key, self.parent.class_)
  1428. )
  1429. def _columns_are_mapped(self, *cols):
  1430. """Return True if all columns in the given collection are
  1431. mapped by the tables referenced by this :class:`.Relationship`.
  1432. """
  1433. for c in cols:
  1434. if self.secondary is not None \
  1435. and self.secondary.c.contains_column(c):
  1436. continue
  1437. if not self.parent.mapped_table.c.contains_column(c) and \
  1438. not self.target.c.contains_column(c):
  1439. return False
  1440. return True
  1441. def _generate_backref(self):
  1442. """Interpret the 'backref' instruction to create a
  1443. :func:`.relationship` complementary to this one."""
  1444. if self.parent.non_primary:
  1445. return
  1446. if self.backref is not None and not self.back_populates:
  1447. if isinstance(self.backref, util.string_types):
  1448. backref_key, kwargs = self.backref, {}
  1449. else:
  1450. backref_key, kwargs = self.backref
  1451. mapper = self.mapper.primary_mapper()
  1452. if not mapper.concrete:
  1453. check = set(mapper.iterate_to_root()).\
  1454. union(mapper.self_and_descendants)
  1455. for m in check:
  1456. if m.has_property(backref_key) and not m.concrete:
  1457. raise sa_exc.ArgumentError(
  1458. "Error creating backref "
  1459. "'%s' on relationship '%s': property of that "
  1460. "name exists on mapper '%s'" %
  1461. (backref_key, self, m))
  1462. # determine primaryjoin/secondaryjoin for the
  1463. # backref. Use the one we had, so that
  1464. # a custom join doesn't have to be specified in
  1465. # both directions.
  1466. if self.secondary is not None:
  1467. # for many to many, just switch primaryjoin/
  1468. # secondaryjoin. use the annotated
  1469. # pj/sj on the _join_condition.
  1470. pj = kwargs.pop(
  1471. 'primaryjoin',
  1472. self._join_condition.secondaryjoin_minus_local)
  1473. sj = kwargs.pop(
  1474. 'secondaryjoin',
  1475. self._join_condition.primaryjoin_minus_local)
  1476. else:
  1477. pj = kwargs.pop(
  1478. 'primaryjoin',
  1479. self._join_condition.primaryjoin_reverse_remote)
  1480. sj = kwargs.pop('secondaryjoin', None)
  1481. if sj:
  1482. raise sa_exc.InvalidRequestError(
  1483. "Can't assign 'secondaryjoin' on a backref "
  1484. "against a non-secondary relationship."
  1485. )
  1486. foreign_keys = kwargs.pop('foreign_keys',
  1487. self._user_defined_foreign_keys)
  1488. parent = self.parent.primary_mapper()
  1489. kwargs.setdefault('viewonly', self.viewonly)
  1490. kwargs.setdefault('post_update', self.post_update)
  1491. kwargs.setdefault('passive_updates', self.passive_updates)
  1492. self.back_populates = backref_key
  1493. relationship = RelationshipProperty(
  1494. parent, self.secondary,
  1495. pj, sj,
  1496. foreign_keys=foreign_keys,
  1497. back_populates=self.key,
  1498. **kwargs)
  1499. mapper._configure_property(backref_key, relationship)
  1500. if self.back_populates:
  1501. self._add_reverse_property(self.back_populates)
  1502. def _post_init(self):
  1503. if self.uselist is None:
  1504. self.uselist = self.direction is not MANYTOONE
  1505. if not self.viewonly:
  1506. self._dependency_processor = \
  1507. dependency.DependencyProcessor.from_relationship(self)
  1508. @util.memoized_property
  1509. def _use_get(self):
  1510. """memoize the 'use_get' attribute of this RelationshipLoader's
  1511. lazyloader."""
  1512. strategy = self._lazy_strategy
  1513. return strategy.use_get
  1514. @util.memoized_property
  1515. def _is_self_referential(self):
  1516. return self.mapper.common_parent(self.parent)
  1517. def _create_joins(self, source_polymorphic=False,
  1518. source_selectable=None, dest_polymorphic=False,
  1519. dest_selectable=None, of_type=None):
  1520. if source_selectable is None:
  1521. if source_polymorphic and self.parent.with_polymorphic:
  1522. source_selectable = self.parent._with_polymorphic_selectable
  1523. aliased = False
  1524. if dest_selectable is None:
  1525. if dest_polymorphic and self.mapper.with_polymorphic:
  1526. dest_selectable = self.mapper._with_polymorphic_selectable
  1527. aliased = True
  1528. else:
  1529. dest_selectable = self.mapper.mapped_table
  1530. if self._is_self_referential and source_selectable is None:
  1531. dest_selectable = dest_selectable.alias()
  1532. aliased = True
  1533. else:
  1534. aliased = True
  1535. dest_mapper = of_type or self.mapper
  1536. single_crit = dest_mapper._single_table_criterion
  1537. aliased = aliased or (source_selectable is not None)
  1538. primaryjoin, secondaryjoin, secondary, target_adapter, dest_selectable = \
  1539. self._join_condition.join_targets(
  1540. source_selectable, dest_selectable, aliased, single_crit
  1541. )
  1542. if source_selectable is None:
  1543. source_selectable = self.parent.local_table
  1544. if dest_selectable is None:
  1545. dest_selectable = self.mapper.local_table
  1546. return (primaryjoin, secondaryjoin, source_selectable,
  1547. dest_selectable, secondary, target_adapter)
  1548. def _annotate_columns(element, annotations):
  1549. def clone(elem):
  1550. if isinstance(elem, expression.ColumnClause):
  1551. elem = elem._annotate(annotations.copy())
  1552. elem._copy_internals(clone=clone)
  1553. return elem
  1554. if element is not None:
  1555. element = clone(element)
  1556. return element
  1557. class JoinCondition(object):
  1558. def __init__(self,
  1559. parent_selectable,
  1560. child_selectable,
  1561. parent_local_selectable,
  1562. child_local_selectable,
  1563. primaryjoin=None,
  1564. secondary=None,
  1565. secondaryjoin=None,
  1566. parent_equivalents=None,
  1567. child_equivalents=None,
  1568. consider_as_foreign_keys=None,
  1569. local_remote_pairs=None,
  1570. remote_side=None,
  1571. self_referential=False,
  1572. prop=None,
  1573. support_sync=True,
  1574. can_be_synced_fn=lambda *c: True
  1575. ):
  1576. self.parent_selectable = parent_selectable
  1577. self.parent_local_selectable = parent_local_selectable
  1578. self.child_selectable = child_selectable
  1579. self.child_local_selectable = child_local_selectable
  1580. self.parent_equivalents = parent_equivalents
  1581. self.child_equivalents = child_equivalents
  1582. self.primaryjoin = primaryjoin
  1583. self.secondaryjoin = secondaryjoin
  1584. self.secondary = secondary
  1585. self.consider_as_foreign_keys = consider_as_foreign_keys
  1586. self._local_remote_pairs = local_remote_pairs
  1587. self._remote_side = remote_side
  1588. self.prop = prop
  1589. self.self_referential = self_referential
  1590. self.support_sync = support_sync
  1591. self.can_be_synced_fn = can_be_synced_fn
  1592. self._determine_joins()
  1593. self._annotate_fks()
  1594. self._annotate_remote()
  1595. self._annotate_local()
  1596. self._setup_pairs()
  1597. self._check_foreign_cols(self.primaryjoin, True)
  1598. if self.secondaryjoin is not None:
  1599. self._check_foreign_cols(self.secondaryjoin, False)
  1600. self._determine_direction()
  1601. self._check_remote_side()
  1602. self._log_joins()
  1603. def _log_joins(self):
  1604. if self.prop is None:
  1605. return
  1606. log = self.prop.logger
  1607. log.info('%s setup primary join %s', self.prop,
  1608. self.primaryjoin)
  1609. log.info('%s setup secondary join %s', self.prop,
  1610. self.secondaryjoin)
  1611. log.info('%s synchronize pairs [%s]', self.prop,
  1612. ','.join('(%s => %s)' % (l, r) for (l, r) in
  1613. self.synchronize_pairs))
  1614. log.info('%s secondary synchronize pairs [%s]', self.prop,
  1615. ','.join('(%s => %s)' % (l, r) for (l, r) in
  1616. self.secondary_synchronize_pairs or []))
  1617. log.info('%s local/remote pairs [%s]', self.prop,
  1618. ','.join('(%s / %s)' % (l, r) for (l, r) in
  1619. self.local_remote_pairs))
  1620. log.info('%s remote columns [%s]', self.prop,
  1621. ','.join('%s' % col for col in self.remote_columns)
  1622. )
  1623. log.info('%s local columns [%s]', self.prop,
  1624. ','.join('%s' % col for col in self.local_columns)
  1625. )
  1626. log.info('%s relationship direction %s', self.prop,
  1627. self.direction)
  1628. def _determine_joins(self):
  1629. """Determine the 'primaryjoin' and 'secondaryjoin' attributes,
  1630. if not passed to the constructor already.
  1631. This is based on analysis of the foreign key relationships
  1632. between the parent and target mapped selectables.
  1633. """
  1634. if self.secondaryjoin is not None and self.secondary is None:
  1635. raise sa_exc.ArgumentError(
  1636. "Property %s specified with secondary "
  1637. "join condition but "
  1638. "no secondary argument" % self.prop)
  1639. # find a join between the given mapper's mapped table and
  1640. # the given table. will try the mapper's local table first
  1641. # for more specificity, then if not found will try the more
  1642. # general mapped table, which in the case of inheritance is
  1643. # a join.
  1644. try:
  1645. consider_as_foreign_keys = self.consider_as_foreign_keys or None
  1646. if self.secondary is not None:
  1647. if self.secondaryjoin is None:
  1648. self.secondaryjoin = \
  1649. join_condition(
  1650. self.child_selectable,
  1651. self.secondary,
  1652. a_subset=self.child_local_selectable,
  1653. consider_as_foreign_keys=consider_as_foreign_keys
  1654. )
  1655. if self.primaryjoin is None:
  1656. self.primaryjoin = \
  1657. join_condition(
  1658. self.parent_selectable,
  1659. self.secondary,
  1660. a_subset=self.parent_local_selectable,
  1661. consider_as_foreign_keys=consider_as_foreign_keys
  1662. )
  1663. else:
  1664. if self.primaryjoin is None:
  1665. self.primaryjoin = \
  1666. join_condition(
  1667. self.parent_selectable,
  1668. self.child_selectable,
  1669. a_subset=self.parent_local_selectable,
  1670. consider_as_foreign_keys=consider_as_foreign_keys
  1671. )
  1672. except sa_exc.NoForeignKeysError:
  1673. if self.secondary is not None:
  1674. raise sa_exc.NoForeignKeysError(
  1675. "Could not determine join "
  1676. "condition between parent/child tables on "
  1677. "relationship %s - there are no foreign keys "
  1678. "linking these tables via secondary table '%s'. "
  1679. "Ensure that referencing columns are associated "
  1680. "with a ForeignKey or ForeignKeyConstraint, or "
  1681. "specify 'primaryjoin' and 'secondaryjoin' "
  1682. "expressions." % (self.prop, self.secondary))
  1683. else:
  1684. raise sa_exc.NoForeignKeysError(
  1685. "Could not determine join "
  1686. "condition between parent/child tables on "
  1687. "relationship %s - there are no foreign keys "
  1688. "linking these tables. "
  1689. "Ensure that referencing columns are associated "
  1690. "with a ForeignKey or ForeignKeyConstraint, or "
  1691. "specify a 'primaryjoin' expression." % self.prop)
  1692. except sa_exc.AmbiguousForeignKeysError:
  1693. if self.secondary is not None:
  1694. raise sa_exc.AmbiguousForeignKeysError(
  1695. "Could not determine join "
  1696. "condition between parent/child tables on "
  1697. "relationship %s - there are multiple foreign key "
  1698. "paths linking the tables via secondary table '%s'. "
  1699. "Specify the 'foreign_keys' "
  1700. "argument, providing a list of those columns which "
  1701. "should be counted as containing a foreign key "
  1702. "reference from the secondary table to each of the "
  1703. "parent and child tables."
  1704. % (self.prop, self.secondary))
  1705. else:
  1706. raise sa_exc.AmbiguousForeignKeysError(
  1707. "Could not determine join "
  1708. "condition between parent/child tables on "
  1709. "relationship %s - there are multiple foreign key "
  1710. "paths linking the tables. Specify the "
  1711. "'foreign_keys' argument, providing a list of those "
  1712. "columns which should be counted as containing a "
  1713. "foreign key reference to the parent table."
  1714. % self.prop)
  1715. @property
  1716. def primaryjoin_minus_local(self):
  1717. return _deep_deannotate(self.primaryjoin, values=("local", "remote"))
  1718. @property
  1719. def secondaryjoin_minus_local(self):
  1720. return _deep_deannotate(self.secondaryjoin,
  1721. values=("local", "remote"))
  1722. @util.memoized_property
  1723. def primaryjoin_reverse_remote(self):
  1724. """Return the primaryjoin condition suitable for the
  1725. "reverse" direction.
  1726. If the primaryjoin was delivered here with pre-existing
  1727. "remote" annotations, the local/remote annotations
  1728. are reversed. Otherwise, the local/remote annotations
  1729. are removed.
  1730. """
  1731. if self._has_remote_annotations:
  1732. def replace(element):
  1733. if "remote" in element._annotations:
  1734. v = element._annotations.copy()
  1735. del v['remote']
  1736. v['local'] = True
  1737. return element._with_annotations(v)
  1738. elif "local" in element._annotations:
  1739. v = element._annotations.copy()
  1740. del v['local']
  1741. v['remote'] = True
  1742. return element._with_annotations(v)
  1743. return visitors.replacement_traverse(
  1744. self.primaryjoin, {}, replace)
  1745. else:
  1746. if self._has_foreign_annotations:
  1747. # TODO: coverage
  1748. return _deep_deannotate(self.primaryjoin,
  1749. values=("local", "remote"))
  1750. else:
  1751. return _deep_deannotate(self.primaryjoin)
  1752. def _has_annotation(self, clause, annotation):
  1753. for col in visitors.iterate(clause, {}):
  1754. if annotation in col._annotations:
  1755. return True
  1756. else:
  1757. return False
  1758. @util.memoized_property
  1759. def _has_foreign_annotations(self):
  1760. return self._has_annotation(self.primaryjoin, "foreign")
  1761. @util.memoized_property
  1762. def _has_remote_annotations(self):
  1763. return self._has_annotation(self.primaryjoin, "remote")
  1764. def _annotate_fks(self):
  1765. """Annotate the primaryjoin and secondaryjoin
  1766. structures with 'foreign' annotations marking columns
  1767. considered as foreign.
  1768. """
  1769. if self._has_foreign_annotations:
  1770. return
  1771. if self.consider_as_foreign_keys:
  1772. self._annotate_from_fk_list()
  1773. else:
  1774. self._annotate_present_fks()
  1775. def _annotate_from_fk_list(self):
  1776. def check_fk(col):
  1777. if col in self.consider_as_foreign_keys:
  1778. return col._annotate({"foreign": True})
  1779. self.primaryjoin = visitors.replacement_traverse(
  1780. self.primaryjoin,
  1781. {},
  1782. check_fk
  1783. )
  1784. if self.secondaryjoin is not None:
  1785. self.secondaryjoin = visitors.replacement_traverse(
  1786. self.secondaryjoin,
  1787. {},
  1788. check_fk
  1789. )
  1790. def _annotate_present_fks(self):
  1791. if self.secondary is not None:
  1792. secondarycols = util.column_set(self.secondary.c)
  1793. else:
  1794. secondarycols = set()
  1795. def is_foreign(a, b):
  1796. if isinstance(a, schema.Column) and \
  1797. isinstance(b, schema.Column):
  1798. if a.references(b):
  1799. return a
  1800. elif b.references(a):
  1801. return b
  1802. if secondarycols:
  1803. if a in secondarycols and b not in secondarycols:
  1804. return a
  1805. elif b in secondarycols and a not in secondarycols:
  1806. return b
  1807. def visit_binary(binary):
  1808. if not isinstance(binary.left, sql.ColumnElement) or \
  1809. not isinstance(binary.right, sql.ColumnElement):
  1810. return
  1811. if "foreign" not in binary.left._annotations and \
  1812. "foreign" not in binary.right._annotations:
  1813. col = is_foreign(binary.left, binary.right)
  1814. if col is not None:
  1815. if col.compare(binary.left):
  1816. binary.left = binary.left._annotate(
  1817. {"foreign": True})
  1818. elif col.compare(binary.right):
  1819. binary.right = binary.right._annotate(
  1820. {"foreign": True})
  1821. self.primaryjoin = visitors.cloned_traverse(
  1822. self.primaryjoin,
  1823. {},
  1824. {"binary": visit_binary}
  1825. )
  1826. if self.secondaryjoin is not None:
  1827. self.secondaryjoin = visitors.cloned_traverse(
  1828. self.secondaryjoin,
  1829. {},
  1830. {"binary": visit_binary}
  1831. )
  1832. def _refers_to_parent_table(self):
  1833. """Return True if the join condition contains column
  1834. comparisons where both columns are in both tables.
  1835. """
  1836. pt = self.parent_selectable
  1837. mt = self.child_selectable
  1838. result = [False]
  1839. def visit_binary(binary):
  1840. c, f = binary.left, binary.right
  1841. if (
  1842. isinstance(c, expression.ColumnClause) and
  1843. isinstance(f, expression.ColumnClause) and
  1844. pt.is_derived_from(c.table) and
  1845. pt.is_derived_from(f.table) and
  1846. mt.is_derived_from(c.table) and
  1847. mt.is_derived_from(f.table)
  1848. ):
  1849. result[0] = True
  1850. visitors.traverse(
  1851. self.primaryjoin,
  1852. {},
  1853. {"binary": visit_binary}
  1854. )
  1855. return result[0]
  1856. def _tables_overlap(self):
  1857. """Return True if parent/child tables have some overlap."""
  1858. return selectables_overlap(
  1859. self.parent_selectable, self.child_selectable)
  1860. def _annotate_remote(self):
  1861. """Annotate the primaryjoin and secondaryjoin
  1862. structures with 'remote' annotations marking columns
  1863. considered as part of the 'remote' side.
  1864. """
  1865. if self._has_remote_annotations:
  1866. return
  1867. if self.secondary is not None:
  1868. self._annotate_remote_secondary()
  1869. elif self._local_remote_pairs or self._remote_side:
  1870. self._annotate_remote_from_args()
  1871. elif self._refers_to_parent_table():
  1872. self._annotate_selfref(lambda col: "foreign" in col._annotations, False)
  1873. elif self._tables_overlap():
  1874. self._annotate_remote_with_overlap()
  1875. else:
  1876. self._annotate_remote_distinct_selectables()
  1877. def _annotate_remote_secondary(self):
  1878. """annotate 'remote' in primaryjoin, secondaryjoin
  1879. when 'secondary' is present.
  1880. """
  1881. def repl(element):
  1882. if self.secondary.c.contains_column(element):
  1883. return element._annotate({"remote": True})
  1884. self.primaryjoin = visitors.replacement_traverse(
  1885. self.primaryjoin, {}, repl)
  1886. self.secondaryjoin = visitors.replacement_traverse(
  1887. self.secondaryjoin, {}, repl)
  1888. def _annotate_selfref(self, fn, remote_side_given):
  1889. """annotate 'remote' in primaryjoin, secondaryjoin
  1890. when the relationship is detected as self-referential.
  1891. """
  1892. def visit_binary(binary):
  1893. equated = binary.left.compare(binary.right)
  1894. if isinstance(binary.left, expression.ColumnClause) and \
  1895. isinstance(binary.right, expression.ColumnClause):
  1896. # assume one to many - FKs are "remote"
  1897. if fn(binary.left):
  1898. binary.left = binary.left._annotate({"remote": True})
  1899. if fn(binary.right) and not equated:
  1900. binary.right = binary.right._annotate(
  1901. {"remote": True})
  1902. elif not remote_side_given:
  1903. self._warn_non_column_elements()
  1904. self.primaryjoin = visitors.cloned_traverse(
  1905. self.primaryjoin, {},
  1906. {"binary": visit_binary})
  1907. def _annotate_remote_from_args(self):
  1908. """annotate 'remote' in primaryjoin, secondaryjoin
  1909. when the 'remote_side' or '_local_remote_pairs'
  1910. arguments are used.
  1911. """
  1912. if self._local_remote_pairs:
  1913. if self._remote_side:
  1914. raise sa_exc.ArgumentError(
  1915. "remote_side argument is redundant "
  1916. "against more detailed _local_remote_side "
  1917. "argument.")
  1918. remote_side = [r for (l, r) in self._local_remote_pairs]
  1919. else:
  1920. remote_side = self._remote_side
  1921. if self._refers_to_parent_table():
  1922. self._annotate_selfref(lambda col: col in remote_side, True)
  1923. else:
  1924. def repl(element):
  1925. if element in remote_side:
  1926. return element._annotate({"remote": True})
  1927. self.primaryjoin = visitors.replacement_traverse(
  1928. self.primaryjoin, {}, repl)
  1929. def _annotate_remote_with_overlap(self):
  1930. """annotate 'remote' in primaryjoin, secondaryjoin
  1931. when the parent/child tables have some set of
  1932. tables in common, though is not a fully self-referential
  1933. relationship.
  1934. """
  1935. def visit_binary(binary):
  1936. binary.left, binary.right = proc_left_right(binary.left,
  1937. binary.right)
  1938. binary.right, binary.left = proc_left_right(binary.right,
  1939. binary.left)
  1940. check_entities = self.prop is not None and \
  1941. self.prop.mapper is not self.prop.parent
  1942. def proc_left_right(left, right):
  1943. if isinstance(left, expression.ColumnClause) and \
  1944. isinstance(right, expression.ColumnClause):
  1945. if self.child_selectable.c.contains_column(right) and \
  1946. self.parent_selectable.c.contains_column(left):
  1947. right = right._annotate({"remote": True})
  1948. elif check_entities and \
  1949. right._annotations.get('parentmapper') is self.prop.mapper:
  1950. right = right._annotate({"remote": True})
  1951. elif check_entities and \
  1952. left._annotations.get('parentmapper') is self.prop.mapper:
  1953. left = left._annotate({"remote": True})
  1954. else:
  1955. self._warn_non_column_elements()
  1956. return left, right
  1957. self.primaryjoin = visitors.cloned_traverse(
  1958. self.primaryjoin, {},
  1959. {"binary": visit_binary})
  1960. def _annotate_remote_distinct_selectables(self):
  1961. """annotate 'remote' in primaryjoin, secondaryjoin
  1962. when the parent/child tables are entirely
  1963. separate.
  1964. """
  1965. def repl(element):
  1966. if self.child_selectable.c.contains_column(element) and \
  1967. (not self.parent_local_selectable.c.
  1968. contains_column(element) or
  1969. self.child_local_selectable.c.
  1970. contains_column(element)):
  1971. return element._annotate({"remote": True})
  1972. self.primaryjoin = visitors.replacement_traverse(
  1973. self.primaryjoin, {}, repl)
  1974. def _warn_non_column_elements(self):
  1975. util.warn(
  1976. "Non-simple column elements in primary "
  1977. "join condition for property %s - consider using "
  1978. "remote() annotations to mark the remote side."
  1979. % self.prop
  1980. )
  1981. def _annotate_local(self):
  1982. """Annotate the primaryjoin and secondaryjoin
  1983. structures with 'local' annotations.
  1984. This annotates all column elements found
  1985. simultaneously in the parent table
  1986. and the join condition that don't have a
  1987. 'remote' annotation set up from
  1988. _annotate_remote() or user-defined.
  1989. """
  1990. if self._has_annotation(self.primaryjoin, "local"):
  1991. return
  1992. if self._local_remote_pairs:
  1993. local_side = util.column_set([l for (l, r)
  1994. in self._local_remote_pairs])
  1995. else:
  1996. local_side = util.column_set(self.parent_selectable.c)
  1997. def locals_(elem):
  1998. if "remote" not in elem._annotations and \
  1999. elem in local_side:
  2000. return elem._annotate({"local": True})
  2001. self.primaryjoin = visitors.replacement_traverse(
  2002. self.primaryjoin, {}, locals_
  2003. )
  2004. def _check_remote_side(self):
  2005. if not self.local_remote_pairs:
  2006. raise sa_exc.ArgumentError(
  2007. 'Relationship %s could '
  2008. 'not determine any unambiguous local/remote column '
  2009. 'pairs based on join condition and remote_side '
  2010. 'arguments. '
  2011. 'Consider using the remote() annotation to '
  2012. 'accurately mark those elements of the join '
  2013. 'condition that are on the remote side of '
  2014. 'the relationship.' % (self.prop, ))
  2015. def _check_foreign_cols(self, join_condition, primary):
  2016. """Check the foreign key columns collected and emit error
  2017. messages."""
  2018. can_sync = False
  2019. foreign_cols = self._gather_columns_with_annotation(
  2020. join_condition, "foreign")
  2021. has_foreign = bool(foreign_cols)
  2022. if primary:
  2023. can_sync = bool(self.synchronize_pairs)
  2024. else:
  2025. can_sync = bool(self.secondary_synchronize_pairs)
  2026. if self.support_sync and can_sync or \
  2027. (not self.support_sync and has_foreign):
  2028. return
  2029. # from here below is just determining the best error message
  2030. # to report. Check for a join condition using any operator
  2031. # (not just ==), perhaps they need to turn on "viewonly=True".
  2032. if self.support_sync and has_foreign and not can_sync:
  2033. err = "Could not locate any simple equality expressions "\
  2034. "involving locally mapped foreign key columns for "\
  2035. "%s join condition "\
  2036. "'%s' on relationship %s." % (
  2037. primary and 'primary' or 'secondary',
  2038. join_condition,
  2039. self.prop
  2040. )
  2041. err += \
  2042. " Ensure that referencing columns are associated "\
  2043. "with a ForeignKey or ForeignKeyConstraint, or are "\
  2044. "annotated in the join condition with the foreign() "\
  2045. "annotation. To allow comparison operators other than "\
  2046. "'==', the relationship can be marked as viewonly=True."
  2047. raise sa_exc.ArgumentError(err)
  2048. else:
  2049. err = "Could not locate any relevant foreign key columns "\
  2050. "for %s join condition '%s' on relationship %s." % (
  2051. primary and 'primary' or 'secondary',
  2052. join_condition,
  2053. self.prop
  2054. )
  2055. err += \
  2056. ' Ensure that referencing columns are associated '\
  2057. 'with a ForeignKey or ForeignKeyConstraint, or are '\
  2058. 'annotated in the join condition with the foreign() '\
  2059. 'annotation.'
  2060. raise sa_exc.ArgumentError(err)
  2061. def _determine_direction(self):
  2062. """Determine if this relationship is one to many, many to one,
  2063. many to many.
  2064. """
  2065. if self.secondaryjoin is not None:
  2066. self.direction = MANYTOMANY
  2067. else:
  2068. parentcols = util.column_set(self.parent_selectable.c)
  2069. targetcols = util.column_set(self.child_selectable.c)
  2070. # fk collection which suggests ONETOMANY.
  2071. onetomany_fk = targetcols.intersection(
  2072. self.foreign_key_columns)
  2073. # fk collection which suggests MANYTOONE.
  2074. manytoone_fk = parentcols.intersection(
  2075. self.foreign_key_columns)
  2076. if onetomany_fk and manytoone_fk:
  2077. # fks on both sides. test for overlap of local/remote
  2078. # with foreign key.
  2079. # we will gather columns directly from their annotations
  2080. # without deannotating, so that we can distinguish on a column
  2081. # that refers to itself.
  2082. # 1. columns that are both remote and FK suggest
  2083. # onetomany.
  2084. onetomany_local = self._gather_columns_with_annotation(
  2085. self.primaryjoin, "remote", "foreign")
  2086. # 2. columns that are FK but are not remote (e.g. local)
  2087. # suggest manytoone.
  2088. manytoone_local = set([c for c in
  2089. self._gather_columns_with_annotation(
  2090. self.primaryjoin,
  2091. "foreign")
  2092. if "remote" not in c._annotations])
  2093. # 3. if both collections are present, remove columns that
  2094. # refer to themselves. This is for the case of
  2095. # and_(Me.id == Me.remote_id, Me.version == Me.version)
  2096. if onetomany_local and manytoone_local:
  2097. self_equated = self.remote_columns.intersection(
  2098. self.local_columns
  2099. )
  2100. onetomany_local = onetomany_local.difference(self_equated)
  2101. manytoone_local = manytoone_local.difference(self_equated)
  2102. # at this point, if only one or the other collection is
  2103. # present, we know the direction, otherwise it's still
  2104. # ambiguous.
  2105. if onetomany_local and not manytoone_local:
  2106. self.direction = ONETOMANY
  2107. elif manytoone_local and not onetomany_local:
  2108. self.direction = MANYTOONE
  2109. else:
  2110. raise sa_exc.ArgumentError(
  2111. "Can't determine relationship"
  2112. " direction for relationship '%s' - foreign "
  2113. "key columns within the join condition are present "
  2114. "in both the parent and the child's mapped tables. "
  2115. "Ensure that only those columns referring "
  2116. "to a parent column are marked as foreign, "
  2117. "either via the foreign() annotation or "
  2118. "via the foreign_keys argument." % self.prop)
  2119. elif onetomany_fk:
  2120. self.direction = ONETOMANY
  2121. elif manytoone_fk:
  2122. self.direction = MANYTOONE
  2123. else:
  2124. raise sa_exc.ArgumentError(
  2125. "Can't determine relationship "
  2126. "direction for relationship '%s' - foreign "
  2127. "key columns are present in neither the parent "
  2128. "nor the child's mapped tables" % self.prop)
  2129. def _deannotate_pairs(self, collection):
  2130. """provide deannotation for the various lists of
  2131. pairs, so that using them in hashes doesn't incur
  2132. high-overhead __eq__() comparisons against
  2133. original columns mapped.
  2134. """
  2135. return [(x._deannotate(), y._deannotate())
  2136. for x, y in collection]
  2137. def _setup_pairs(self):
  2138. sync_pairs = []
  2139. lrp = util.OrderedSet([])
  2140. secondary_sync_pairs = []
  2141. def go(joincond, collection):
  2142. def visit_binary(binary, left, right):
  2143. if "remote" in right._annotations and \
  2144. "remote" not in left._annotations and \
  2145. self.can_be_synced_fn(left):
  2146. lrp.add((left, right))
  2147. elif "remote" in left._annotations and \
  2148. "remote" not in right._annotations and \
  2149. self.can_be_synced_fn(right):
  2150. lrp.add((right, left))
  2151. if binary.operator is operators.eq and \
  2152. self.can_be_synced_fn(left, right):
  2153. if "foreign" in right._annotations:
  2154. collection.append((left, right))
  2155. elif "foreign" in left._annotations:
  2156. collection.append((right, left))
  2157. visit_binary_product(visit_binary, joincond)
  2158. for joincond, collection in [
  2159. (self.primaryjoin, sync_pairs),
  2160. (self.secondaryjoin, secondary_sync_pairs)
  2161. ]:
  2162. if joincond is None:
  2163. continue
  2164. go(joincond, collection)
  2165. self.local_remote_pairs = self._deannotate_pairs(lrp)
  2166. self.synchronize_pairs = self._deannotate_pairs(sync_pairs)
  2167. self.secondary_synchronize_pairs = \
  2168. self._deannotate_pairs(secondary_sync_pairs)
  2169. _track_overlapping_sync_targets = weakref.WeakKeyDictionary()
  2170. def _warn_for_conflicting_sync_targets(self):
  2171. if not self.support_sync:
  2172. return
  2173. # we would like to detect if we are synchronizing any column
  2174. # pairs in conflict with another relationship that wishes to sync
  2175. # an entirely different column to the same target. This is a
  2176. # very rare edge case so we will try to minimize the memory/overhead
  2177. # impact of this check
  2178. for from_, to_ in [
  2179. (from_, to_) for (from_, to_) in self.synchronize_pairs
  2180. ] + [
  2181. (from_, to_) for (from_, to_) in self.secondary_synchronize_pairs
  2182. ]:
  2183. # save ourselves a ton of memory and overhead by only
  2184. # considering columns that are subject to a overlapping
  2185. # FK constraints at the core level. This condition can arise
  2186. # if multiple relationships overlap foreign() directly, but
  2187. # we're going to assume it's typically a ForeignKeyConstraint-
  2188. # level configuration that benefits from this warning.
  2189. if len(to_.foreign_keys) < 2:
  2190. continue
  2191. if to_ not in self._track_overlapping_sync_targets:
  2192. self._track_overlapping_sync_targets[to_] = \
  2193. weakref.WeakKeyDictionary({self.prop: from_})
  2194. else:
  2195. other_props = []
  2196. prop_to_from = self._track_overlapping_sync_targets[to_]
  2197. for pr, fr_ in prop_to_from.items():
  2198. if pr.mapper in mapperlib._mapper_registry and \
  2199. fr_ is not from_ and \
  2200. pr not in self.prop._reverse_property:
  2201. other_props.append((pr, fr_))
  2202. if other_props:
  2203. util.warn(
  2204. "relationship '%s' will copy column %s to column %s, "
  2205. "which conflicts with relationship(s): %s. "
  2206. "Consider applying "
  2207. "viewonly=True to read-only relationships, or provide "
  2208. "a primaryjoin condition marking writable columns "
  2209. "with the foreign() annotation." % (
  2210. self.prop,
  2211. from_, to_,
  2212. ", ".join(
  2213. "'%s' (copies %s to %s)" % (pr, fr_, to_)
  2214. for (pr, fr_) in other_props)
  2215. )
  2216. )
  2217. self._track_overlapping_sync_targets[to_][self.prop] = from_
  2218. @util.memoized_property
  2219. def remote_columns(self):
  2220. return self._gather_join_annotations("remote")
  2221. @util.memoized_property
  2222. def local_columns(self):
  2223. return self._gather_join_annotations("local")
  2224. @util.memoized_property
  2225. def foreign_key_columns(self):
  2226. return self._gather_join_annotations("foreign")
  2227. @util.memoized_property
  2228. def deannotated_primaryjoin(self):
  2229. return _deep_deannotate(self.primaryjoin)
  2230. @util.memoized_property
  2231. def deannotated_secondaryjoin(self):
  2232. if self.secondaryjoin is not None:
  2233. return _deep_deannotate(self.secondaryjoin)
  2234. else:
  2235. return None
  2236. def _gather_join_annotations(self, annotation):
  2237. s = set(
  2238. self._gather_columns_with_annotation(
  2239. self.primaryjoin, annotation)
  2240. )
  2241. if self.secondaryjoin is not None:
  2242. s.update(
  2243. self._gather_columns_with_annotation(
  2244. self.secondaryjoin, annotation)
  2245. )
  2246. return set([x._deannotate() for x in s])
  2247. def _gather_columns_with_annotation(self, clause, *annotation):
  2248. annotation = set(annotation)
  2249. return set([
  2250. col for col in visitors.iterate(clause, {})
  2251. if annotation.issubset(col._annotations)
  2252. ])
  2253. def join_targets(self, source_selectable,
  2254. dest_selectable,
  2255. aliased,
  2256. single_crit=None):
  2257. """Given a source and destination selectable, create a
  2258. join between them.
  2259. This takes into account aliasing the join clause
  2260. to reference the appropriate corresponding columns
  2261. in the target objects, as well as the extra child
  2262. criterion, equivalent column sets, etc.
  2263. """
  2264. # place a barrier on the destination such that
  2265. # replacement traversals won't ever dig into it.
  2266. # its internal structure remains fixed
  2267. # regardless of context.
  2268. dest_selectable = _shallow_annotate(
  2269. dest_selectable,
  2270. {'no_replacement_traverse': True})
  2271. primaryjoin, secondaryjoin, secondary = self.primaryjoin, \
  2272. self.secondaryjoin, self.secondary
  2273. # adjust the join condition for single table inheritance,
  2274. # in the case that the join is to a subclass
  2275. # this is analogous to the
  2276. # "_adjust_for_single_table_inheritance()" method in Query.
  2277. if single_crit is not None:
  2278. if secondaryjoin is not None:
  2279. secondaryjoin = secondaryjoin & single_crit
  2280. else:
  2281. primaryjoin = primaryjoin & single_crit
  2282. if aliased:
  2283. if secondary is not None:
  2284. secondary = secondary.alias(flat=True)
  2285. primary_aliasizer = ClauseAdapter(secondary)
  2286. secondary_aliasizer = \
  2287. ClauseAdapter(dest_selectable,
  2288. equivalents=self.child_equivalents).\
  2289. chain(primary_aliasizer)
  2290. if source_selectable is not None:
  2291. primary_aliasizer = \
  2292. ClauseAdapter(secondary).\
  2293. chain(ClauseAdapter(
  2294. source_selectable,
  2295. equivalents=self.parent_equivalents))
  2296. secondaryjoin = \
  2297. secondary_aliasizer.traverse(secondaryjoin)
  2298. else:
  2299. primary_aliasizer = ClauseAdapter(
  2300. dest_selectable,
  2301. exclude_fn=_ColInAnnotations("local"),
  2302. equivalents=self.child_equivalents)
  2303. if source_selectable is not None:
  2304. primary_aliasizer.chain(
  2305. ClauseAdapter(source_selectable,
  2306. exclude_fn=_ColInAnnotations("remote"),
  2307. equivalents=self.parent_equivalents))
  2308. secondary_aliasizer = None
  2309. primaryjoin = primary_aliasizer.traverse(primaryjoin)
  2310. target_adapter = secondary_aliasizer or primary_aliasizer
  2311. target_adapter.exclude_fn = None
  2312. else:
  2313. target_adapter = None
  2314. return primaryjoin, secondaryjoin, secondary, \
  2315. target_adapter, dest_selectable
  2316. def create_lazy_clause(self, reverse_direction=False):
  2317. binds = util.column_dict()
  2318. equated_columns = util.column_dict()
  2319. has_secondary = self.secondaryjoin is not None
  2320. if has_secondary:
  2321. lookup = collections.defaultdict(list)
  2322. for l, r in self.local_remote_pairs:
  2323. lookup[l].append((l, r))
  2324. equated_columns[r] = l
  2325. elif not reverse_direction:
  2326. for l, r in self.local_remote_pairs:
  2327. equated_columns[r] = l
  2328. else:
  2329. for l, r in self.local_remote_pairs:
  2330. equated_columns[l] = r
  2331. def col_to_bind(col):
  2332. if (
  2333. (not reverse_direction and 'local' in col._annotations) or
  2334. reverse_direction and (
  2335. (has_secondary and col in lookup) or
  2336. (not has_secondary and 'remote' in col._annotations)
  2337. )
  2338. ):
  2339. if col not in binds:
  2340. binds[col] = sql.bindparam(
  2341. None, None, type_=col.type, unique=True)
  2342. return binds[col]
  2343. return None
  2344. lazywhere = self.primaryjoin
  2345. if self.secondaryjoin is None or not reverse_direction:
  2346. lazywhere = visitors.replacement_traverse(
  2347. lazywhere, {}, col_to_bind)
  2348. if self.secondaryjoin is not None:
  2349. secondaryjoin = self.secondaryjoin
  2350. if reverse_direction:
  2351. secondaryjoin = visitors.replacement_traverse(
  2352. secondaryjoin, {}, col_to_bind)
  2353. lazywhere = sql.and_(lazywhere, secondaryjoin)
  2354. bind_to_col = dict((binds[col].key, col) for col in binds)
  2355. # this is probably not necessary
  2356. lazywhere = _deep_deannotate(lazywhere)
  2357. return lazywhere, bind_to_col, equated_columns
  2358. class _ColInAnnotations(object):
  2359. """Seralizable equivalent to:
  2360. lambda c: "name" in c._annotations
  2361. """
  2362. def __init__(self, name):
  2363. self.name = name
  2364. def __call__(self, c):
  2365. return self.name in c._annotations