7p^ӍXdZddlZddlZddlmZddlmZddlmZddlm Z ddl m Z ddl m Z dd lmZdd lmZddlmZejeZGd d eZGd deZGddeZejdddZejdddZe jdZejejdddZejejdddZ ej!Ze j"Z ej#Z#dS)zBaked query extension. Provides a creational pattern for the :class:`.query.Query` object which allows the fully constructed object, Core select statement, and string compiled result to be fully cached. N)exc)util)strategy_options)Query)Session)func)literal_columnc"eZdZdZdZdZdZdS)BakeryzCallable which returns a :class:`.BakedQuery`. This object is returned by the class method :meth:`.BakedQuery.bakery`. It exists as an object so that the "cache" can be easily inspected. .. versionadded:: 1.2 clscachec"||_||_dSNr )selfcls_rs /srv/buildsys-work-dir/castor/build_node/builder-2/WGSG1/unpkd_srcs/cloudlinux-venv-1.0.6/venv/lib/python3.11/site-packages/sqlalchemy/ext/baked.py__init__zBakery.__init__/s c:||j||Srr )r initial_fnargss r__call__zBakery.__call__3sxx J555rN)__name__ __module__ __qualname____doc__ __slots__rrrrr r !sC  I66666rr ceZdZdZdZddZeddZdZdd Z d Z d Z d Z d Z dZdZddZdZddZddZdZdZdZdZdZdZdS) BakedQueryz3A builder object for :class:`.query.Query` objects.)steps_bakery _cache_key_spoiledr cld|_||||g|_d|_||_dS)Nr F)r%_update_cache_keyr#r&r$)rbakeryrrs rrzBakedQuery.__init__<s: z4000 \   rNcJt|tj||S)zSConstruct a new bakery. :return: an instance of :class:`.Bakery` ) size_alert)r rLRUCache)rsize _size_alerts rr)zBakedQuery.bakeryCs#c4=+FFFGGGrctt}|j|_t|j|_|j|_|j|_|Sr)r"__new__r%listr#r$r&)rb1s r_clonezBakedQuery._cloneMsF    + +  ##\ m  rc8|xj|jf|zz c_dSr)r%__code__rfnrs rr(zBakedQuery._update_cache_keyUs BK>D00rcpt|tr |j|n|||Sr) isinstancetuple add_criteriarothers r__iadd__zBakedQuery.__iadd__Xs@ eU # # % D u % % %   e $ $ $ rcjt|tr |j|S||Sr)r:r; with_criteriar=s r__add__zBakedQuery.__add___s8 eU # # -%4%u- -%%e,, ,rcf||||j||S)zAdd a criteria function to this :class:`.BakedQuery`. This is equivalent to using the ``+=`` operator to modify a :class:`.BakedQuery` in-place. )r(r#appendr7s rr<zBakedQuery.add_criteriaes5 r4((( " rcB|j|g|RS)zAdd a criteria function to a :class:`.BakedQuery` cloned from this one. This is equivalent to using the ``+`` operator to produce a new :class:`.BakedQuery` with modifications. )r4r<r7s rrAzBakedQuery.with_criteriaps'*t{{}})"4t4444rc"t||S)zReturn a :class:`.Result` object for this :class:`.BakedQuery`. This is equivalent to calling the :class:`.BakedQuery` as a Python callable, e.g. ``result = my_baked_query(session)``. )Resultrsessions r for_sessionzBakedQuery.for_sessionysdG$$$rc,||Sr)rJrHs rrzBakedQuery.__call__s(((rFc|s8|js1|}|xjdz c_|jg|_d|_|S)aCancel any query caching that will occur on this BakedQuery object. The BakedQuery can continue to be used normally, however additional creational functions will not be cached; they will be called on every invocation. This is to support the case where a particular step in constructing a baked query disqualifies the query from being cacheable, such as a variant that relies upon some uncacheable value. :param full: if False, only functions added to this :class:`.BakedQuery` object subsequent to the spoil step will be non-cached; the state of the :class:`.BakedQuery` up until this point will be pulled from the cache. If True, then the entire :class:`_query.Query` object is built from scratch each time, with all creational functions being called on each invocation. ) _query_onlyT)r&r4r%_retrieve_baked_queryr#)rfull _spoil_points rspoilzBakedQuery.spoilsP( >DM >;;==L  # #'7 7 # #&<=DJ  rc"|j|jfzS)aReturn the key that actually goes into the cache dictionary for this :class:`.BakedQuery`, taking into account the given :class:`.Session`. This basically means we also will include the session's query_class, as the actual :class:`_query.Query` object is part of what's cached and needs to match the type of :class:`_query.Query` that a later session will want to use. )r% _query_clsrHs r_effective_keyzBakedQuery._effective_keys'"4!666rc^|}|||||S)z)Cloning version of _add_lazyload_options.) cache_path)r4_add_lazyload_options)roptionseffective_pathrVqs r_with_lazyload_optionsz!BakedQuery._with_lazyload_optionss/ KKMM JOOOrc d}|s}|jdjr|dn<D]9}||}|dur|d2|||z }:|fd|j|dS)a*Used by per-state lazy loaders to add options to the "lazy load" query from a parent query. Creates a cache key based on given load path and query options; if a repeatable cache key cannot be generated, the query is "spoiled" so that it won't use caching. r rT)rOFNc>|jSr)_with_current_path_conditional_options)rZrYrXs rz2BakedQuery._add_lazyload_options..s)#a**"G-r)pathis_aliased_classrQ_generate_cache_keyr<)rrXrYrVkeyopt cache_keys `` rrWz BakedQuery._add_lazyload_optionss ('J ?1  . % JJDJ ! ! ! ! % %33J?? %%JJDJ))))*9$C  - - - - - O       rc|j||d}|E||}|d|j||<||Sr)r$getrT _as_query with_session)rrIquerys rrNz BakedQuery._retrieve_baked_querys   !4!4W!=!=tDD =NN7++E9>9K9K::DL,,W55 6!!'***rc||}|}|||d|_|jdx|_}|jd|ji|_dD]}|j |d|jj r||j| |<|S)Ncompiled_cache) _correlate _from_obj_mapper_adapter_map _joinpath _joinpoint) ri_compile_context_bake_subquery_loadersrIrkrj_execution_optionsunionr$__dict__pop_bake_okrT)rrIrkcontextattrs r_bakezBakedQuery._bakesw''((** ##GW555 ' : :4 @ @@ #(#;#A#A t| ,$ $    + +D N  tT * * * * = ! A9@DL,,W55 6rct|tr|}nRt|tr|j}|t jdnt dt|z||S)a5Return the :class:`_query.Query` object for use as a subquery. This method should be used within the lambda callable being used to generate a step of an enclosing :class:`.BakedQuery`. The parameter should normally be the :class:`_query.Query` object that is passed to the lambda:: sub_bq = self.bakery(lambda s: s.query(User.name)) sub_bq += lambda q: q.filter( User.id == Address.user_id).correlate(Address) main_bq = self.bakery(lambda s: s.query(Address)) main_bq += lambda q: q.filter( sub_bq.to_query(q).exists()) In the case where the subquery is used in the first callable against a :class:`.Session`, the :class:`.Session` is also accepted:: sub_bq = self.bakery(lambda s: s.query(User.name)) sub_bq += lambda q: q.filter( User.id == Address.user_id).correlate(Address) main_bq = self.bakery( lambda s: s.query(Address.id, sub_bq.to_query(q).as_scalar()) ) :param query_or_session: a :class:`_query.Query` object or a class :class:`.Session` object, that is assumed to be within the context of an enclosing :class:`.BakedQuery` callable. .. versionadded:: 1.3 Nz1Given Query needs to be associated with a Sessionz)Query or Session object expected, got %r.) r:rrrIsa_exc ArgumentError TypeErrortyperi)rquery_or_sessionrIs rto_queryzBakedQuery.to_querysJ & 0 0 &GG (% 0 0 &.G*G ;'(() ~~g&&&rcl|jd|}|jddD] }||}|SNr)r#)rrIrksteps rrizBakedQuery._as_query2sD 1 g&&JqrrN  DDKKEE rclgx|jd<}t|jD]\}ttred|vrYt |jfd}|j|z|_||| ||jf|j|=dS)abconvert subquery eager loaders in the cache into baked queries. For subquery eager loading to work, all we need here is that the Query point to the correct session when it is run. However, since we are "baking" anyway, we may as well also turn the query into a "baked" query so that we save on performance too. baked_queriessubquerycSrr )rvs rr`z3BakedQuery._bake_subquery_loaders..FsrN) attributesr2itemsr:rr"r$r%r|rD)rrIrzrkbkrs @rrtz!BakedQuery._bake_subquery_loaders9s?A@?+m+113344 * *DAq!U## *??#DL////BBB$(Oa$7BMHHW%%%!((!R]A)>???&q) * *rc d|jvrdS|jdD]i\}}}t|j|fd}||_||} |D]} | | } | jdi||j|<jdS)zRetrieve subquery eager loaders stored by _bake_subquery_loaders and turn them back into Result objects that will iterate just like a Query object. rNc,||Sr)rj)sessrZs rr`z5BakedQuery._unbake_subquery_loaders..YsANN44H4Hrr )rr"r$r%rJwith_post_criteriaparams) rrIrzr post_criteriarrfrkrrZr8s r_unbake_subquery_loadersz#BakedQuery._unbake_subquery_loadersLs '"4 4 4 F#*#5o#F 7 7 Ay% UHHHB&BMw''A# - -((,,$,AH$6$6v$6$6G q ! ! 7 7r)r )r*N)Fr)rrrrrr classmethodr)r4r(r?rBr<rArJrrQrTr[rWrNr|rrirtrr rrr"r"7s{==2'2'2'h***&77777rr"cpeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdS)rGa Invokes a :class:`.BakedQuery` against a :class:`.Session`. The :class:`.Result` object is where the actual :class:`.query.Query` object gets created, or retrieved from the cache, against a target :class:`.Session`, and is then invoked for results. bqrI_params_post_criteriac>||_||_i|_g|_dSrr)rrrIs rrzResult.__init__ms%   rct|dkr||dn't|dkrtjd|j||S)z@Specify parameters to be replaced into the string SQL statement.rrzFparams() takes zero or one positional argument, which is a dictionary.)lenupdater~rr)rrkws rrz Result.paramsssr t99>> IId1g     YY]]&)  B rc>|r|j||Sr)rextend)rfnss r_using_post_criteriazResult._using_post_criterias&  ,   & &s + + + rc.||gS)a'Add a criteria function that will be applied post-cache. This adds a function that will be run against the :class:`_query.Query` object after it is retrieved from the cache. Functions here can be used to alter the query in ways that **do not affect the SQL output**, such as execution options and shard identifiers (when using a shard-enabled query object) .. warning:: :meth:`.Result.with_post_criteria` functions are applied to the :class:`_query.Query` object **after** the query's SQL statement object has been retrieved from the cache. Any operations here which intend to modify the SQL should ensure that :meth:`.BakedQuery.spoil` was called first. .. versionadded:: 1.2 )r)rr8s rrzResult.with_post_criterias((("...rc|j|j|j}|jD] }||}|Sr)rrirIrrr)rrZr8s rrizResult._as_querysO G  dl + + 2 24< @ @%  B1AArcDt|Sr)strrirs r__str__zResult.__str__s4>>##$$$rc|j}|jjr|jr!t |S|j||jd}|| |j}tj |}|j|_|j |_ | |j||j |jd|j_|jr |js|j|j|j |j}|jD] }||}||SNT)rrIenable_baked_queriesr&iterrir$rhrTr|copyrrrr statement use_labels autoflushpopulate_existing _autoflushrkrrj_execute_and_instances)rr baked_contextrzrZr8s r__iter__zResult.__iter__s^ W|0 *BK *(()) ) r'8'8'F'FMM  HHT\22M)M**,$/4466 ## L'4<1D   (,$   &W%> & L # # % % % M  . . ; ;DL I I%  B1AA''000rctjtd|jfd}||j|j S)zreturn the 'count'. Equivalent to :meth:`_query.Query.count`. Note this uses a subquery to ensure an accurate count regardless of the structure of the original statement. .. versionadded:: 1.1.6 *c.|Sr) from_self)rZcols rr`zResult.count..sQ[[-=-=r) r countr rrArJrIrrscalar)rrrs @rrz Result.countskj,,-- W " "#=#=#=#= > >~~dl++224<@@GGIIIrc |}t|ts|S|dS#tj$rYdSwxYw)zReturn the first element of the first result or None if no rows present. If multiple rows are returned, raises MultipleResultsFound. Equivalent to :meth:`_query.Query.scalar`. .. versionadded:: 1.1.6 rN)oner:r;orm_exc NoResultFound)rrets rrz Result.scalarsY ((**Cc5))  q6M$   44 s*55AAc |jd}t||j|j|j}t|dkr|dSdS)zRReturn the first row. Equivalent to :meth:`_query.Query.first`. c.|ddSr)slice)rZs rr`zResult.first..sQWWQ]]rrN) rrAr2rJrIrrrrr)rrrs rfirstz Result.firsts| W " "#:#: ; ; NN4< ( ( VDL ! ! ! !$"5 6 6   s88a<<q6M4rc |}|tjd|S#tj$r3}t jtjd|Yd}~dSd}~wwxYw)zkReturn exactly one result or raise an exception. Equivalent to :meth:`_query.Query.one`. NzNo row was found for one()z"Multiple rows were found for one())replace_context) one_or_nonerrMultipleResultsFoundrraise_)rrerrs rrz Result.ones ""$$C{+,HIIIJ+    K,8!$            s.A0(A++A0ct|}t|}|dkr|dS|dkrdStjd)zReturn one or zero results, or raise an exception for multiple rows. Equivalent to :meth:`_query.Query.one_or_none`. .. versionadded:: 1.0.9 rrNz*Multiple rows were found for one_or_none())r2rrr)rrls rrzResult.one_or_nonesR4jj HH 66q6M !VV4.< rc t|S)zKReturn all rows. Equivalent to :meth:`_query.Query.all`. )r2rs rallz Result.alls Dzzrcx|jjd|j}|||jS)z`Retrieve an object based on identity. Equivalent to :meth:`_query.Query.get`. r)rr#rI _get_impl_load_on_pk_identity)ridentrks rrhz Result.get"s5! a ..ud&?@@@rc4 | j\  fd}j}|}|xjfz c_||t dD}t fdt j D}t| j j di|}t|}|dkrtj|r|dSdS)z6Load the given primary key identity from the database.c^}|}|d|_dvrCtfdt jD}t j||}||dd}||_ j D] }||}|S)Nc4g|]\}}||jSrrd).0rvalue _get_paramss r z>Result._load_on_pk_identity..setup..=s6&C!= $C(,)==rTF) r4_get_condition _order_bysetzip primary_keysql_utiladapt_criterion_to_null _adapt_clause _criterionr) rk_lcl_get_clauserZnonesr8 _get_clausermapperprimary_key_identityrs rsetupz*Result._load_on_pk_identity..setup3s)O A     AK+++*-".0D++#+"B#U## oootUKKO*AL)  BqEEHrc3K|]}|duV dSrr )relems r z.Result._load_on_pk_identity..[s&GG$GGGGGGrc4g|]\}}|j|fSr r)rid_valrrs rrz/Result._load_on_pk_identity.._s:   'FK[)-v6   rrrNr ) _mapper_zerorrr4r%rAr;dictrrr2rJrIrrrr) rrkrrrrresultrrrrs ` ` @@@rrzResult._load_on_pk_identity,sd##%%#)#5 [         >W YY[[ +'    5GG2FGGGGG      +.(&*<,,     9bnnT\229CCFCCDD KK q55.00 0  !9 4rN)rrrrrrrrrrirrrrrrrrrhrr rrrGrGbs=I!!!    ///, %%%1114JJJ $"(*AAABBBBBrrGz1.2z5Baked lazy loading is now the default implementation.cdS)zEnable the use of baked queries for all lazyloaders systemwide. The "baked" implementation of lazy loading is now the sole implementation for the base lazy loader; this method has no effect except for a warning. Nr r rrbake_lazy_loadersrqs  Drc td)aHDisable the use of baked queries for all lazyloaders systemwide. This method now raises NotImplementedError() as the "baked" implementation is the only lazy load implementation. The :paramref:`_orm.relationship.bake_queries` flag may be used to disable the caching of queries on a per-relationship basis. z4Baked lazy loading is now the default implementation)NotImplementedErrorr rrunbake_lazy_loadersr~s >  rc2||ddiS)zxIndicate that the given attribute should be loaded using "lazy" loading with a "baked" query used in the load. lazy baked_select)set_relationship_strategy)loadoptr{s rbaked_lazyloadrs  , ,TFN3K L LLrzFBaked lazy loading is now the default implementation for lazy loading.cdtjtjj|diS)NFr _UnboundLoad _from_keysrkeyss rrrs.  ( 3 3%4dE2  rcdtjtjj|diSrrrs rbaked_lazyload_allr s.  ( 3 3%4dD"  r)$rrloggingrr~rormrr orm.queryr orm.sessionrsqlr r r getLoggerrlogobjectr r"rG deprecatedrr loader_optionr_add_unbound_fn_add_unbound_all_fnr  _unbound_fn_unbound_all_fnr)r rrrs  """"""!!!!!! """"""g!!66666V666,h7h7h7h7h7h7h7h7V LLLLLVLLL^ B    B    !!MM"!M '     # '  $#   +'7  r