L iYEdZddlmZddlZddlmZddlmZddl mZ ddl m Z ddl mZddlmZdd lmZddlmZej&eZGd d ZGd d ZGddZej2Zy)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)Query)Session)func)literal_columnc eZdZdZdZdZdZy)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 ||_||_yNr )selfcls_rs Z/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sqlalchemy/ext/baked.py__init__zBakery.__init__1s c<|j|j||Srr )r initial_fnargss r__call__zBakery.__call__5sxx J55rN)__name__ __module__ __qualname____doc__ __slots__rrrrr r #s I6rr ceZdZdZdZddZeddZdZddZ dZ d Z d Z d Z d Zd ZddZdZddZddZdZdZdZdZy) BakedQueryz3A builder object for :class:`.query.Query` objects.)steps_bakery _cache_key_spoiledcbd|_|j|||g|_d|_||_y)NrF)r$_update_cache_keyr"r%r#)rbakeryrrs rrzBakedQuery.__init__>s0 z40 \   rNcDt|tj||S)zSConstruct a new bakery. :return: an instance of :class:`.Bakery` ) size_alert)r rLRUCache)r size _size_alerts rr(zBakedQuery.bakeryEsc4==+FGGrctjt}|j|_t|j|_|j |_|j |_|Sr)r!__new__r$listr"r#r%)rb1s r_clonezBakedQuery._cloneOsH    +  #\\ mm  rcJ|xj|jf|zz c_yr)r$__code__rfnrs rr'zBakedQuery._update_cache_keyWs BKK>D00rcjt|tr|j||S|j||Sr) isinstancetuple add_criteriarothers r__iadd__zBakedQuery.__iadd__Zs8 eU # D  u %    e $ rcbt|tr|j|S|j|Sr)r8r9 with_criteriar;s r__add__zBakedQuery.__add__as0 eU #%4%%u- -%%e, ,rc`|j|||jj||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"appendr5s rr:zBakedQuery.add_criteriags+ r4( " rcD|jj|g|S)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. )r2r:r5s rr?zBakedQuery.with_criteriars"*t{{}))"4t44rct||S)zReturn a :class:`_baked.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_session|sdG$$rc$|j|Sr)rHrFs rrzBakedQuery.__call__s((rc|sC|js7|j}|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%r2r$_retrieve_baked_queryr")rfull _spoil_points rspoilzBakedQuery.spoilsF(DMM;;=L  # #'7 7 #&<<=DJ  rc6|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_clsrFs r_effective_keyzBakedQuery._effective_keys'"4"4!666rcN|j}|j||||S)z)Cloning version of _add_lazyload_options.) cache_path)r2_add_lazyload_options)roptionseffective_pathrTqs r_with_lazyload_optionsz!BakedQuery._with_lazyload_optionss' KKM JOrcd}|s}D]T}|js |js|j}||jdA|drJd||dz }V|j fd|j |y) 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. rNT)rMzloader options with variable bound parameters not supported with baked queries. Please use new-style select() statements for cached ORM queries.rc@|jjSr)_with_current_pathrV)rXrWrVs rz2BakedQuery._add_lazyload_options..s Ba**>:BBGLr)_is_legacy_option_is_compile_state_generate_cache_keyrOr:path)rrVrWrTkeyoptcks `` rrUz BakedQuery._add_lazyload_optionss'J !C$$(=(=,,.:JJDJ)!!u'9 2a5LC !  L OO  rc|jj|j|d}|>|j|}|j d|j|j|<|j |Sr)r#getrR _as_query with_session)rrGquerys rrLz BakedQuery._retrieve_baked_querysp   !4!4W!=tD =NN7+E9>9K9K:DLL,,W5 6!!'**rc|j|}d|_|j}|jjr ||f|j |j |<||fSr)rhrG _statement_20_compile_options_bake_okr#rR)rrGrj statements r_bakezBakedQuery._bakesfw' '')   % % . .:DLL,,W5 6 irct|tr|}nJt|tr#|j}|,t j dt dt|z|j|S)aReturn 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).scalar_subquery()) ) :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 z1Given Query needs to be associated with a Sessionz)Query or Session object expected, got %r.) r8rrrGsa_exc ArgumentError TypeErrortyperh)rquery_or_sessionrGs rto_queryzBakedQuery.to_queryswD & 0&G (% 0&..G**G;'() ~~g&&rch|jd|}|jddD] }||} |SNrr[)r")rrGrjsteps rrhzBakedQuery._as_query-s? 1 g&JJqrN DKE  r)r)N)Fr)rrrrrr classmethodr(r2r'r=r@r:r?rHrrOrRrYrUrLrprwrhrrrr!r!9sw= IId1g  Y]&&)  B rc@|r|jj||Sr)rextend)rfnss r_using_post_criteriazResult._using_post_criteriaTs     & &s + rc&|j|gS)aAdd 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. This currently includes **only** the :meth:`_query.Query.params` and :meth:`_query.Query.execution_options` methods. .. warning:: :meth:`_baked.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. Only :meth:`_query.Query.params` and :meth:`_query.Query.execution_options` methods should be used. .. versionadded:: 1.2 )r)rr6s rwith_post_criteriazResult.with_post_criteriaYs.(("..rc|jj|jj|j}|j D] }||} |Sr)rrhrGrrr)rrXr6s rrhzResult._as_queryrsL GG  dll + 2 24<< @%% B1A rc4t|jSr)strrhrs r__str__zResult.__str__xs4>>#$$rc>|jjSr)_iter__iter__rs rrzResult.__iter__{szz|$$&&rcR|j}|jjr |jr|j j S|j j|j|jd\}}||j|j\}}|jr|j|j}n|}|jD] }||} |j}t|j}|j|j |j d|jj#|||}|j$jddr|j'}|j$jddr|j)}|S)N)NN)_sa_orm_load_optionscompiled_cache)execution_optionsis_single_entityFfiltered)rrGenable_baked_queriesr%rhrr#rgrRrprrrdict_execution_optionsr load_optionsexecute _attributesscalarsunique) rrrjrorXr6rrresults rrz Result._iter~sd WW||00BKK>>#))+ +::>>   dll +\ y =!xx 5 E9 << T\\*AA%% B1A  !5!56  ()"$**  %% v1B&     ! !"4e <^^%F    ! !*e 4]]_F rctjtd|jj fd}|j |j j|jjS)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. *c&|jSr)_legacy_from_self)rXcols rr^zResult.count..sQ-@-@-Er) rcountr rr?rHrGrrscalar)rrrs @rrz Result.countsXjj,- WW " "#E F~~dll+224<<@GGIIrc |j}t|tjs|S|dS#tj $rYywxYw)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`. rN)oner8collections_abcSequenceorm_exc NoResultFound)rrets rrz Result.scalarsH ((*Cc?#;#;< q6M$$  s+33A A c |jjd}|j|jj |j j |jjjS)zRReturn the first row. Equivalent to :meth:`_query.Query.first`. c&|jddSry)slice)rXs rr^zResult.first..sQWWQ]r) rr?rHrGrrrrrfirst)rrs rrz Result.firsts[WW " "#: ; NN4<< ( VDLL ! ! !$"5"5 6 UW UW  rc>|jjS)zkReturn exactly one result or raise an exception. Equivalent to :meth:`_query.Query.one`. )rrrs rrz Result.one zz|!!rc>|jjS)zReturn one or zero results, or raise an exception for multiple rows. Equivalent to :meth:`_query.Query.one_or_none`. )r one_or_noners rrzResult.one_or_noneszz|''))rc>|jjS)zKReturn all rows. Equivalent to :meth:`_query.Query.all`. )rallrs rrz Result.allrrc|jjd|j}|j||jS)z`Retrieve an object based on identity. Equivalent to :meth:`_query.Query.get`. r)rr"rG _get_impl_load_on_pk_identity)ridentrjs rrgz Result.gets8! a .ud&?&?@@rc T |jdjdj\ fd}j}|j }|xj fz c_|j |tdD}tjDcic]\}} |j|} }}t|jjjdi| } t| } | dkDrt!j"| r| dSycc}}w)z6Load the given primary key identity from the database.r parententitycv}|j}|jd|_d vrMt j Dchc]\}}||j }}}t j||}t j|ddif|_ jD] }||} |Scc}}w)N _orm_adaptT) r2_get_condition _order_byzip primary_keyrcsql_utiladapt_criterion_to_null_deep_annotate_where_criteriar) rj_lcl_get_clauserXrvaluenonesr6 _get_clause _get_paramsmapperprimary_key_identityrs rsetupz*Result._load_on_pk_identity..setups)O A   AK++'***,@'"U}  $((#+"B"B#U# '',9MN!A )) qE H%sB5c3$K|]}|du ywrr).0elems r z.Result._load_on_pk_identity..&sG$Gsr[Nr) _raw_columns _annotationsrrr2r$r?r9rrrcr0rHrGrrrMultipleResultsFound)rrGrjrrrrid_valrrrlrrrs` ` @@@rrzResult._load_on_pk_identitys%##A&33NC#)#5#5 [  @WW YY[ +'    5G2FGG  (+$f&8&8( #   $ ( (& 0  9bnnT\\299CFCD K q5..0 0 !9  s'D$N)rrrrrrrrrrhrrrrrrrrrrgrrrrrErE6sb=I!  /2 %'%N J  "*"AArrE)rcollections.abcabcrloggingrrrrormr orm.queryr orm.sessionrsqlrr r getLoggerrlogr r!rEr(rrrrso* ! "g!66,zzzAAH   r