o
    E6dG                     @   s   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eZG d
d dZG dd dZG d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                   @   s$   e Zd ZdZdZdd Zd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                 C   s   || _ || _d S Nr
   )selfZcls_r    r   kC:\Users\jesus\OneDrive\Desktop\erpjis_fastapi\backend\jisbackend\Lib\site-packages\sqlalchemy/ext/baked.py__init__1   s   
zBakery.__init__c                 G   s   |  | j||S r   r
   )r   
initial_fnargsr   r   r   __call__5   s   zBakery.__call__N)__name__
__module____qualname____doc__	__slots__r   r   r   r   r   r   r	   #   s
    r	   c                   @   s   e Zd ZdZdZd+ddZed,dd	Zd
d Zd+ddZ	dd Z
dd Zdd Zdd Zdd Zdd Zd-ddZdd Zd.dd Zd.d!d"Zd#d$ Zd%d& Zd'd( Zd)d* ZdS )/
BakedQueryz3A builder object for :class:`.query.Query` objects.)steps_bakery
_cache_key_spoiledr   c                 C   s*   d| _ | || |g| _d| _|| _d S )Nr   F)r   _update_cache_keyr   r   r   )r   bakeryr   r   r   r   r   r   >   s
   
zBakedQuery.__init__   Nc                 C   s   t | tj||dS )zSConstruct a new bakery.

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

        )Z
size_alert)r	   r   ZLRUCache)r   sizeZ_size_alertr   r   r   r    E   s   zBakedQuery.bakeryc                 C   s2   t t }| j|_t| j|_| j|_| j|_|S r   )r   __new__r   listr   r   r   )r   b1r   r   r   _cloneO   s   
zBakedQuery._clonec                 C   s   |  j |jf| 7  _ d S r   )r   __code__r   fnr   r   r   r   r   W   s   zBakedQuery._update_cache_keyc                 C   s&   t |tr| j|  | S | | | S r   )
isinstancetupleadd_criteriar   otherr   r   r   __iadd__Z   s
   


zBakedQuery.__iadd__c                 C   s   t |tr
| j| S | |S r   )r*   r+   with_criteriar-   r   r   r   __add__a   s   


zBakedQuery.__add__c                 G   s   |  || | 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   appendr(   r   r   r   r,   g   s   zBakedQuery.add_criteriac                 G   s   |   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.

        )r&   r,   r(   r   r   r   r0   r   s   zBakedQuery.with_criteriac                 C   s
   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   sessionr   r   r   for_session|   s   
zBakedQuery.for_sessionc                 C   s
   |  |S r   )r6   r4   r   r   r   r      s   
zBakedQuery.__call__Fc                 C   s4   |s| j s|  }| jd7  _|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.

        )Z_query_onlyT)r   r&   r   _retrieve_baked_queryr   )r   fullZ_spoil_pointr   r   r   spoil   s   

zBakedQuery.spoilc                 C   s   | j |jf 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   Z
_query_clsr4   r   r   r   _effective_key   s   zBakedQuery._effective_keyc                 C   s   |   }|j|||d |S )z)Cloning version of _add_lazyload_options.)
cache_path)r&   _add_lazyload_options)r   optionseffective_pathr;   qr   r   r   _with_lazyload_options   s   z!BakedQuery._with_lazyload_optionsc                    sz   d}|s }D ]%}|j s|jr-| }|du r| jdd q|d r'J d||d 7 }q|  fd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)r8      zloader options with variable bound parameters not supported with baked queries.  Please use new-style select() statements for cached ORM queries.r   c                    s   |   j S r   )Z_with_current_pathr=   r?   r>   r=   r   r   <lambda>   s    z2BakedQuery._add_lazyload_options.<locals>.<lambda>)Z_is_legacy_optionZ_is_compile_stateZ_generate_cache_keyr9   r,   path)r   r=   r>   r;   keyoptZckr   rC   r   r<      s$   

z BakedQuery._add_lazyload_optionsc                 C   sF   | j | |d }|d u r| |}|d | j | |< ||S r   )r   getr:   	_as_queryZwith_session)r   r5   queryr   r   r   r7      s   

z BakedQuery._retrieve_baked_queryc                 C   s<   |  |}d |_| }|jjr||f| j| |< ||fS r   )rI   r5   Z_statement_20Z_compile_optionsZ_bake_okr   r:   )r   r5   rJ   	statementr   r   r   _bake   s   
zBakedQuery._bakec                 C   sN   t |tr|}nt |tr|j}|du rtdntdt| | |S )aL  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.)	r*   r   r   r5   sa_excArgumentError	TypeErrortyperI   )r   Zquery_or_sessionr5   r   r   r   to_query   s   
&

zBakedQuery.to_queryc                 C   s.   | j d |}| j dd  D ]}||}q|S Nr   rA   )r   )r   r5   rJ   stepr   r   r   rI   1  s   
zBakedQuery._as_query)r   )r!   N)Fr   )r   r   r   r   r   r   classmethodr    r&   r   r/   r1   r,   r0   r6   r   r9   r:   r@   r<   r7   rL   rQ   rI   r   r   r   r   r   9   s,    
	





#	5r   c                   @   s   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#S )$r3   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.

    bqr5   _params_post_criteriac                 C   s   || _ || _i | _g | _d S r   rU   )r   rV   r5   r   r   r   r   E  s   
zResult.__init__c                 O   sB   t |dkr||d  nt |dkrtd| j| | S )z@Specify parameters to be replaced into the string SQL statement.rA   r   zFparams() takes zero or one positional argument, which is a dictionary.)lenupdaterM   rN   rW   )r   r   kwr   r   r   paramsK  s   zResult.paramsc                 C   s   |r| j | | S r   )rX   extend)r   fnsr   r   r   _using_post_criteriaX  s   zResult._using_post_criteriac                 C   s   |  |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   r)   r   r   r   with_post_criteria]  s   zResult.with_post_criteriac                 C   s.   | j | j| j}| jD ]}||}q|S r   )rV   rI   r5   r\   rW   rX   )r   r?   r)   r   r   r   rI   v  s   

zResult._as_queryc                 C   s   t |  S r   )strrI   r   r   r   r   __str__|     zResult.__str__c                 C      |    S r   )_iter__iter__rb   r   r   r   rg     rd   zResult.__iter__c           	      C   s   | j }| jjr
|jr|   S |j|| jd\}}|d u r)|	| j\}}| j
r3|| j
}n|}| jD ]}||}q8|j
}t|j}||j|jd | jj|||d}|jddre| }|jddrp| }|S )N)NN)Z_sa_orm_load_optionsZcompiled_cache)execution_optionsZis_single_entityFfiltered)rV   r5   Zenable_baked_queriesr   rI   rf   r   rH   r:   rL   rW   r\   rX   dictZ_execution_optionsrZ   Zload_optionsexecute_attributesZscalarsunique)	r   rV   rJ   rK   r?   r)   r\   rh   resultr   r   r   rf     s8   


zResult._iterc                    s:   t td | j fd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
   |   S r   )Z_legacy_from_selfrB   colr   r   rD     s   
 zResult.count.<locals>.<lambda>)
r   countr   rV   r0   r6   r5   r\   rW   scalarr   rV   r   rp   r   rr     s   
zResult.countc                 C   s<   z|   }t|tjs|W S |d W S  tjy   Y dS 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)oner*   collections_abcSequenceorm_excZNoResultFound)r   retr   r   r   rs     s   
zResult.scalarc                 C   s4   | j dd }|| j| j| j 	 S )zRReturn the first row.

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

        c                 S   s   |  ddS rR   )slicerB   r   r   r   rD     s    zResult.first.<locals>.<lambda>)
rV   r0   r6   r5   r\   rW   r_   rX   rf   firstrt   r   r   r   r{     s   
zResult.firstc                 C   re   )zkReturn exactly one result or raise an exception.

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

        )rf   ru   rb   r   r   r   ru        z
Result.onec                 C   re   )zReturn one or zero results, or raise an exception for multiple
        rows.

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

        )rf   one_or_nonerb   r   r   r   r}     s   zResult.one_or_nonec                 C   re   )zKReturn all rows.

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

        )rf   allrb   r   r   r   r~     r|   z
Result.allc                 C   s    | j jd | j}||| jS )z`Retrieve an object based on identity.

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

        r   )rV   r   r5   Z	_get_impl_load_on_pk_identity)r   identrJ   r   r   r   rH     s   z
Result.getc           
         s   |j d jd j\  fdd}j}| }| j f7  _||tdd D }fddtj	D }t
|jjdi |}t|}	|	d	krZt |	r`|d S d
S )z6Load the given primary key identity from the database.r   Zparententityc                    st    }|   }|  d |_d v r$fddtjD }t||}t|ddif|_j	D ]}||}q1|S )Nc                    s"   h | ]\}}|d u r | j qS r   rF   ).0rq   value_get_paramsr   r   	<setcomp>
  s
    z=Result._load_on_pk_identity.<locals>.setup.<locals>.<setcomp>Z
_orm_adaptT)
r&   Z_get_conditionZ	_order_byzipprimary_keysql_utilZadapt_criterion_to_nullZ_deep_annotateZ_where_criteriarX   )rJ   Z_lcl_get_clauser?   Znonesr)   _get_clauser   Zmapperprimary_key_identityr   r   r   setup  s$   


z*Result._load_on_pk_identity.<locals>.setupc                 s   s    | ]}|d u V  qd S r   r   )r   elemr   r   r   	<genexpr>*  s    z.Result._load_on_pk_identity.<locals>.<genexpr>c                    s   i | ]
\}} | j |qS r   r   )r   Zid_valr   r   r   r   
<dictcomp>-  s    
z/Result._load_on_pk_identity.<locals>.<dictcomp>rA   Nr   )Z_raw_columnsZ_annotationsr   rV   r&   r   r0   r+   r   r   r$   r6   r5   r\   rY   rx   ZMultipleResultsFound)
r   r5   rJ   r   r[   r   rV   r\   rn   lr   r   r   r     s*   
 
zResult._load_on_pk_identityN)r   r   r   r   r   r   r\   r_   r`   rI   rc   rg   rf   rr   rs   r{   ru   r}   r~   rH   r   r   r   r   r   r3   :  s&    '	
r3   )r   collections.abcabcrv   logging r   rM   r   Zormrx   Z	orm.queryr   Zorm.sessionr   sqlr   r   r   	getLoggerr   logr	   r   r3   r    r   r   r   r   <module>   s(   		
    
