
    [hYE                         d Z ddlmZ ddlZddlmZ ddlmZ ddl	mZ
 ddlmZ ddlmZ ddlmZ dd	lmZ ddlmZ  ej        e          Z G d
 d          Z G d d          Z G d d          Zej        ZdS )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                   "    e Zd ZdZdZd Zd ZdS )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


    clscachec                 "    || _         || _        d S Nr   )selfcls_r   s      c/var/www/api.easyaligner.net/htdocs/venv_linux/lib/python3.11/site-packages/sqlalchemy/ext/baked.py__init__zBakery.__init__1   s    


    c                 :    |                      | j        ||          S r   r   )r   
initial_fnargss      r   __call__zBakery.__call__5   s    xx
J555r   N)__name__
__module____qualname____doc__	__slots__r   r    r   r   r   r   #   sC        	 	 I  6 6 6 6 6r   r   c                       e Zd ZdZdZddZedd            Zd Zdd	Z	d
 Z
d Zd Zd Zd Zd ZddZd ZddZddZd Zd Zd Zd ZdS )
BakedQueryz3A builder object for :class:`.query.Query` objects.)steps_bakery
_cache_key_spoiledr   c                 l    d| _         |                     ||           |g| _        d| _        || _        d S )Nr   F)r$   _update_cache_keyr"   r%   r#   )r   bakeryr   r   s       r   r   zBakedQuery.__init__>   s:    z4000 \
r      Nc                 J    t          | t          j        ||                    S )zSConstruct a new bakery.

        :return: an instance of :class:`.Bakery`

        )
size_alert)r   r   LRUCache)r   size_size_alerts      r   r(   zBakedQuery.bakeryE   s#     c4=+FFFGGGr   c                     t                               t                     }| j        |_        t          | j                  |_        | j        |_        | j        |_        |S r   )r!   __new__r$   listr"   r#   r%   )r   b1s     r   _clonezBakedQuery._cloneO   sF    
++
##\
m	r   c                 8    | xj         |j        f|z   z  c_         d S r   )r$   __code__r   fnr   s      r   r'   zBakedQuery._update_cache_keyW   s    BK>D00r   c                 p    t          |t                    r | j        |  n|                     |           | S r   )
isinstancetupleadd_criteriar   others     r   __iadd__zBakedQuery.__iadd__Z   s@    eU## 	%Du%%%e$$$r   c                 j    t          |t                    r
 | j        | S |                     |          S r   )r9   r:   with_criteriar<   s     r   __add__zBakedQuery.__add__a   s8    eU## 	-%4%u--%%e,,,r   c                 f    |                      ||           | 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"   appendr6   s      r   r;   zBakedQuery.add_criteriag   s5     	r4(((
"r   c                 B     |                                  j        |g|R  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.

        )r3   r;   r6   s      r   r@   zBakedQuery.with_criteriar   s'     *t{{}})"4t4444r   c                 "    t          | |          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)``.

        )Resultr   sessions     r   for_sessionzBakedQuery.for_session|   s     dG$$$r   c                 ,    |                      |          S r   )rI   rG   s     r   r   zBakedQuery.__call__   s    (((r   Fc                     |s8| j         s1|                                 }|xj        dz  c_        |j        g| _        d| _         | S )a  Cancel 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%   r3   r$   _retrieve_baked_queryr"   )r   full_spoil_points      r   spoilzBakedQuery.spoil   sP    (  	>DM 	>;;==L##'77##&<=DJr   c                 "    | j         |j        fz   S )a  Return 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_clsrG   s     r   _effective_keyzBakedQuery._effective_key   s     '"4!666r   c                 ^    |                                  }|                    |||           |S )z)Cloning version of _add_lazyload_options.)
cache_path)r3   _add_lazyload_options)r   optionseffective_pathrU   qs        r   _with_lazyload_optionsz!BakedQuery._with_lazyload_options   s/    KKMM	JOOOr   c                    d}|s}D ]Z}|j         s|j        rJ|                                }||                     d           =|d         r
J d            ||d         z  }[|                     fd|j        |           dS )	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   NT)rN      zloader options with variable bound parameters not supported with baked queries.  Please use new-style select() statements for cached ORM queries.r   c                 >     |                                j         S r   )_with_current_pathrW   )rY   rX   rW   s    r   <lambda>z2BakedQuery._add_lazyload_options.<locals>.<lambda>   s     Ba**>::BGL r   )_is_legacy_option_is_compile_state_generate_cache_keyrP   r;   path)r   rW   rX   rU   keyoptcks    ``    r   rV   z BakedQuery._add_lazyload_options   s      	('J 	! 	!C$ !(= !,,..:JJDJ))))!!u  '   2a5LCLLLLLO	
 	
 	
 	
 	
r   c                    | j                             |                     |          d           }|E|                     |          }|                    d           | j         |                     |          <   |                    |          S r   )r#   getrS   	_as_querywith_session)r   rH   querys      r   rM   z BakedQuery._retrieve_baked_query   s      !4!4W!=!=tDD=NN7++E9>9K9K: :DL,,W556 !!'***r   c                     |                      |          }d |_        |                                }|j        j        r||f| j        |                     |          <   ||fS r   )ri   rH   _statement_20_compile_options_bake_okr#   rS   )r   rH   rk   	statements       r   _bakezBakedQuery._bake   sl    w'' ''))	 %. 	:DL,,W556
 ir   c                     t          |t                    r|}nRt          |t                    r|j        }|t	          j        d          nt          dt          |          z            |                     |          S )a  Return 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


        Nz1Given Query needs to be associated with a Sessionz)Query or Session object expected, got %r.)	r9   r   r   rH   sa_excArgumentError	TypeErrortyperi   )r   query_or_sessionrH   s      r   to_queryzBakedQuery.to_query   s    D &00 	&GG(%00 
	&.G*G   
 ;'(()   ~~g&&&r   c                 l     | j         d         |          }| j         dd          D ]} ||          }|S Nr   r\   )r"   )r   rH   rk   steps       r   ri   zBakedQuery._as_query-  sD    
1g&&JqrrN 	  	 DDKKEEr   )r   )r)   N)Fr   )r   r   r   r   r   r   classmethodr(   r3   r'   r>   rA   r;   r@   rI   r   rP   rS   rZ   rV   rM   rq   rx   ri   r   r   r   r!   r!   9   s]       ==<I    H H H [H  1 1 1 1  - - -	 	 	5 5 5% % %) ) )   67 7 7   !
 !
 !
 !
F+ + +     2/' /' /'b    r   r!   c                   v    e Zd ZdZdZd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd ZdS )rF   a  Invokes a :class:`.BakedQuery` against a :class:`.Session`.

    The :class:`_baked.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.

    bqrH   _params_post_criteriac                 >    || _         || _        i | _        g | _        d S r   r~   )r   r   rH   s      r   r   zResult.__init__A  s%     r   c                     t          |          dk    r|                    |d                    n't          |          dk    rt          j        d          | j                            |           | S )z@Specify parameters to be replaced into the string SQL statement.r\   r   zFparams() takes zero or one positional argument, which is a dictionary.)lenupdaters   rt   r   )r   r   kws      r   paramszResult.paramsG  sr     t99>>IId1gYY]]&)   	Br   c                 >    |r| j                             |           | S r   )r   extend)r   fnss     r   _using_post_criteriazResult._using_post_criteriaT  s&     	,&&s+++r   c                 .    |                      |g          S )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.    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   )r   r7   s     r   with_post_criteriazResult.with_post_criteriaY  s    . (("...r   c                     | j                             | j                                      | j                  }| j        D ]} ||          }|S r   )r   ri   rH   r   r   r   )r   rY   r7   s      r   ri   zResult._as_queryr  sO    Gdl++224<@@% 	 	B1AAr   c                 D    t          |                                           S r   )strri   r   s    r   __str__zResult.__str__x  s    4>>##$$$r   c                 N    |                                                                  S r   )_iter__iter__r   s    r   r   zResult.__iter__{  s    zz||$$&&&r   c                    | j         }| j        j        r|j        r&|                                                                 S |j                            |                    | j                  d          \  }}||	                    | j                  \  }}| j
        r|                    | j
                  }n|}| j        D ]} ||          }|j
        }t          |j                  }|                    |j        |j        d           | j                            |||          }|j                            dd          r|                                }|j                            dd          r|                                }|S )N)NN)_sa_orm_load_optionscompiled_cache)execution_optionsis_single_entityFfiltered)r   rH   enable_baked_queriesr%   ri   r   r#   rh   rS   rq   r   r   r   dict_execution_optionsr   load_optionsexecute_attributesscalarsunique)	r   r   rk   rp   rY   r7   r   r   results	            r   r   zResult._iter~  s   W|0 	,BK 	,>>##))+++:>>dl++\
 
y =!xx55E9< 	T\**AAA% 	 	B1AA !566  ()"$* 	
 	
 	
 %%v1B & 
 
 !!"4e<< 	&^^%%F!!*e44 	%]]__Fr   c                    t          j        t          d                    | j                            fd          }|                    | 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.

        *c                 .    |                                S r   )_legacy_from_self)rY   cols    r   r_   zResult.count.<locals>.<lambda>  s    Q-@-@-E-E r   )
r   countr	   r   r@   rI   rH   r   r   scalar)r   r   r   s     @r   r   zResult.count  sk     j,,--W""#E#E#E#EFF~~dl++224<@@GGIIIr   c                     	 |                                  }t          |t          j                  s|S |d         S # t          j        $ r Y dS w xY w)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`.

        r   N)oner9   collections_abcSequenceorm_excNoResultFound)r   rets     r   r   zResult.scalar  s\    	((**Cc?#;<< 
q6M$ 	 	 	44	s   /: : AAc                    | j                             d           }|                    | j                                      | j                                      | j                                                  	                                S )zRReturn the first row.

        Equivalent to :meth:`_query.Query.first`.

        c                 .    |                      dd          S rz   )slice)rY   s    r   r_   zResult.first.<locals>.<lambda>  s    QWWQ]] r   )
r   r@   rI   rH   r   r   r   r   r   first)r   r   s     r   r   zResult.first  se     W""#:#:;;NN4<((VDL!!!!$"566UWWUWW	
r   c                 N    |                                                                  S )zkReturn exactly one result or raise an exception.

        Equivalent to :meth:`_query.Query.one`.

        )r   r   r   s    r   r   z
Result.one       zz||!!!r   c                 N    |                                                                  S )zReturn one or zero results, or raise an exception for multiple
        rows.

        Equivalent to :meth:`_query.Query.one_or_none`.

        )r   one_or_noner   s    r   r   zResult.one_or_none  s     zz||'')))r   c                 N    |                                                                  S )zKReturn all rows.

        Equivalent to :meth:`_query.Query.all`.

        )r   allr   s    r   r   z
Result.all  r   r   c                 x     | j         j        d         | j                  }|                    || j                  S )z`Retrieve an object based on identity.

        Equivalent to :meth:`_query.Query.get`.

        r   )r   r"   rH   	_get_impl_load_on_pk_identity)r   identrk   s      r   rh   z
Result.get  s5     !a ..ud&?@@@r   c                 "   
 |j         d         j        d         j        \  

 fd} j        }|                                }|xj        
fz  c_        |                    |t          d D                                 }fdt          j	                  D             }t           |                     j                  j        di |          }t          |          }	|	dk    rt          j                    |	r|d         S dS )	z6Load the given primary key identity from the database.r   parententityc                 B   }|                                  }|                                 d |_        d v r6fdt          j                  D             }t          j        ||          }t          j        |ddi          f|_        	j	        D ]} ||          }|S )Nc                 4    h | ]\  }}||         j         S r   rd   ).0r   value_get_paramss      r   	<setcomp>z=Result._load_on_pk_identity.<locals>.setup.<locals>.<setcomp>  s6       "U }	  $( %}}r   
_orm_adaptT)
r3   _get_condition	_order_byzipprimary_keysql_utiladapt_criterion_to_null_deep_annotate_where_criteriar   )
rk   _lcl_get_clauserY   nonesr7   _get_clauser   mapperprimary_key_identityr   s
        r   setupz*Result._load_on_pk_identity.<locals>.setup  s    )OAAK +++   &)*,@' '   #+"B#U# # ',9MNN!A )  BqEEHr   c              3      K   | ]}|d u V  	d S r   r   )r   elems     r   	<genexpr>z.Result._load_on_pk_identity.<locals>.<genexpr>&  s&      GG$GGGGGGr   c                 2    i | ]\  }}|         j         |S r   r   )r   id_valr   r   s      r   
<dictcomp>z/Result._load_on_pk_identity.<locals>.<dictcomp>)  s7     
 
 
# $(&
 
 
r   r\   Nr   )_raw_columns_annotationsr   r   r3   r$   r@   r:   r   r   r1   rI   rH   r   r   r   MultipleResultsFound)r   rH   rk   r   r   r   r   r   r   lr   r   r   s   `  `      @@@r   r   zResult._load_on_pk_identity  sZ    #A&3NC#)#5 [	 	 	 	 	 	 	 	 	@ W
 YY[[
+'5GG2FGGGGG
 

 
 
 
'*$f&8( (
 
 
 9bnnT\229CCFCCDDKKq55.000 	!94r   N)r   r   r   r   r   r   r   r   r   ri   r   r   r   r   r   r   r   r   r   rh   r   r   r   r   rF   rF   6  s!         =I! ! !    
/ / /2  % % %' ' '% % %NJ J J   
 
 
 " " "* * *" " "A A AA A A A Ar   rF   )r   collections.abcabcr   logging r   rs   r   ormr   	orm.queryr   orm.sessionr   sqlr   r	   r   	getLoggerr   logr   r!   rF   r(   r   r   r   <module>r      sh    * ) ) ) ) )                                ! ! ! ! ! !                   " " " " " " g!!6 6 6 6 6 6 6 6,z z z z z z z zzA A A A A A A AH 
	r   