U
    ÌZjN  ã                   @   s@  d 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 ddlmZ ddlmZ e e¡ZG dd„ deƒZG dd„ deƒZG dd„ deƒZe dd¡dd„ ƒZe dd¡dd„ ƒZe ¡ dd„ ƒZeje dd¡dd„ ƒƒZeje dd¡dd„ ƒƒZ ej!Ze j"Z ej#Z#dS )zÎBaked 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_column)Úcollections_abcc                   @   s$   e Zd ZdZdZdd„ Zdd„ ZdS )ÚBakeryzêCallable 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   úW/var/www/html/TRUCKING_PROJECT/venv/lib/python3.8/site-packages/sqlalchemy/ext/baked.pyÚ__init__/   s    zBakery.__init__c                 G   s   |   | j||¡S r   r   )r   Ú
initial_fnÚargsr   r   r   Ú__call__3   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d0d!d"„Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ ZdS )1Ú
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"   C   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   Ú_cloneM   s    
zBakedQuery._clonec                 C   s   |  j |jf| 7  _ d S r   )r   Ú__code__©r   Úfnr   r   r   r   r!   U   s    zBakedQuery._update_cache_keyc                 C   s$   t |tƒr| j|Ž  n
|  |¡ | S r   )Ú
isinstanceÚtupleÚadd_criteria©r   Úotherr   r   r   Ú__iadd__X   s    

zBakedQuery.__iadd__c                 C   s"   t |tƒr| j|Ž S |  |¡S d S r   )r,   r-   Úwith_criteriar/   r   r   r   Ú__add___   s    

zBakedQuery.__add__c                 G   s   |   ||¡ | j |¡ | S )z«Add 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.   e   s    zBakedQuery.add_criteriac                 G   s   |   ¡ j|f|žŽ S )zÓAdd 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   r2   p   s    zBakedQuery.with_criteriac                 C   s
   t | |ƒS )zàReturn 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_sessionz   s    zBakedQuery.for_sessionc                 C   s
   |   |¡S r   )r8   r6   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_clsr6   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}|j s |jr| ¡ }|dkr>| jdd� q|d rNt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)r:   é   z‘loader 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?   ©rA   ©r@   r?   r   r   Ú<lambda>Ó   ó    z2BakedQuery._add_lazyload_options.<locals>.<lambda>)Z_is_legacy_optionZ_is_compile_stateZ_generate_cache_keyr;   ÚAssertionErrorr.   Úpath)r   r?   r@   r=   ÚkeyÚoptZckr   rE   r   r>   µ   s"    

ÿýz BakedQuery._add_lazyload_optionsc                 C   sF   | j  |  |¡d ¡}|d kr<|  |¡}| d ¡| j |  |¡< | |¡S r   )r   Úgetr<   Ú	_as_queryZwith_session)r   r7   Úqueryr   r   r   r9   Ø   s    
ÿz BakedQuery._retrieve_baked_queryc                 C   s<   |   |¡}d |_| ¡ }|jjr4||f| j|  |¡< ||fS r   )rM   r7   Z_statement_20Z_compile_optionsZ_bake_okr   r<   )r   r7   rN   Ú	statementr   r   r   Ú_bakeá   s    
þzBakedQuery._bakec                 C   sN   t |tƒr|}n4t |tƒr4|j}|dkrDt 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   r7   Úsa_excÚArgumentErrorÚ	TypeErrorÚtyperM   )r   Zquery_or_sessionr7   r   r   r   Úto_queryú   s    &

ÿÿÿzBakedQuery.to_queryc                 C   s.   | j d |ƒ}| j dd … D ]}||ƒ}q|S ©Nr   rC   )r   )r   r7   rN   Ústepr   r   r   rM   /  s    
zBakedQuery._as_query)r   )r#   N)r   )F)N)N)r   r   r   r   r   r   Úclassmethodr"   r(   r!   r1   r3   r.   r2   r8   r   r;   r<   rB   r>   r9   rP   rU   rM   r   r   r   r   r   7   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 )$r5   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.

    ©Úbqr7   Ú_paramsÚ_post_criteriac                 C   s   || _ || _i | _g | _d S r   rY   )r   rZ   r7   r   r   r   r   C  s    zResult.__init__c                 O   sB   t |ƒdkr| |d ¡ nt |ƒdkr2t d¡‚| j |¡ | S )z@Specify parameters to be replaced into the string SQL statement.rC   r   zFparams() takes zero or one positional argument, which is a dictionary.)ÚlenÚupdaterQ   rR   r[   )r   r   Úkwr   r   r   ÚparamsI  s    ÿzResult.paramsc                 C   s   |r| j  |¡ | S r   )r\   Úextend)r   Zfnsr   r   r   Ú_using_post_criteriaV  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


        )rb   )r   r+   r   r   r   Úwith_post_criteria[  s    zResult.with_post_criteriac                 C   s.   | j  | j¡ | j¡}| jD ]}||ƒ}q|S r   )rZ   rM   r7   r`   r[   r\   )r   rA   r+   r   r   r   rM   t  s    

zResult._as_queryc                 C   s   t |  ¡ ƒS r   )ÚstrrM   ©r   r   r   r   Ú__str__z  s    zResult.__str__c                 C   s   |   ¡  ¡ S r   )Ú_iterÚ__iter__re   r   r   r   rh   }  s    zResult.__iter__c           	      C   sä   | j }| jjr|jr |  ¡  ¡ S |j | | j¡d¡\}}|d krR| 	| j¡\}}| j
rf| | j
¡}n|}| jD ]}||ƒ}qp|j
}t|jƒ}| |j|jdœ¡ | jj|||d�}|j dd¡rÊ| ¡ }|j dd¡rà| ¡ }|S )N)NN)Z_sa_orm_load_optionsZcompiled_cache)Úexecution_optionsZis_single_entityFÚfiltered)rZ   r7   Zenable_baked_queriesr    rM   rg   r   rL   r<   rP   r[   r`   r\   ÚdictZ_execution_optionsr^   Zload_optionsÚexecuteÚ_attributesZscalarsÚunique)	r   rZ   rN   rO   rA   r+   r`   ri   Úresultr   r   r   rg   €  s>    
 ÿ


þÿ  ÿzResult._iterc                    s:   t  tdƒ¡‰ | j ‡ fdd„¡}| | j¡ | j¡ 	¡ S )zïreturn 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                    s
   |   ˆ ¡S r   )Z
_from_selfrD   ©Úcolr   r   rF   ´  rG   zResult.count.<locals>.<lambda>)
r   Úcountr	   rZ   r2   r8   r7   r`   r[   Úscalar©r   rZ   r   rq   r   rs   §  s    zResult.countc                 C   sB   z$|   ¡ }t|tjƒs|W S |d W S  tjk
r<   Y dS X dS )zôReturn 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

        r   N)Úoner,   r
   ÚSequenceÚorm_excZNoResultFound)r   Úretr   r   r   rt   ·  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 rV   )ÚslicerD   r   r   r   rF   Ð  rG   zResult.first.<locals>.<lambda>)
rZ   r2   r8   r7   r`   r[   rb   r\   rg   Úfirstru   r   r   r   r{   É  s    ÿþ
ÿzResult.firstc                 C   s   |   ¡  ¡ S )zkReturn exactly one result or raise an exception.

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

        )rg   rv   re   r   r   r   rv   Ù  s    z
Result.onec                 C   s   |   ¡  ¡ S )z°Return one or zero results, or raise an exception for multiple
        rows.

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

        .. versionadded:: 1.0.9

        )rg   Úone_or_nonere   r   r   r   r|   á  s    	zResult.one_or_nonec                 C   s   |   ¡  ¡ S )zKReturn all rows.

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

        )rg   Úallre   r   r   r   r}   ì  s    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   )rZ   r   r7   Z	_get_implÚ_load_on_pk_identity)r   ÚidentrN   r   r   r   rL   ô  s    z
Result.getc           
         sÊ   |j d jd ‰ˆj\‰ ‰‡ ‡‡‡‡fdd„}ˆj}| ¡ }| jˆ f7  _| |tdd„ ˆD ƒƒ¡}t‡fdd„t	ˆˆj
ƒD ƒƒ}t| ˆj¡jf |Žƒ}t|ƒ}	|	d	kr¶t ¡ ‚n|	rÂ|d S d
S d
S )z6Load the given primary key identity from the database.r   Zparententityc                    sx   ˆ }|   ¡ }| ¡  d |_d ˆkrLt‡fdd„tˆjˆƒD ƒƒ}t ||¡}t |ddi¡f|_	ˆj
D ]}||ƒ}qf|S )Nc                    s"   g | ]\}}|d krˆ | j ‘qS r   ©rJ   )Ú.0rr   Úvalue©Ú_get_paramsr   r   Ú
<listcomp>  s   üz>Result._load_on_pk_identity.<locals>.setup.<locals>.<listcomp>Z
_orm_adaptT)r(   Z_get_conditionZ	_order_byÚsetÚzipÚprimary_keyÚsql_utilZadapt_criterion_to_nullZ_deep_annotateZ_where_criteriar\   )rN   Z_lcl_get_clauserA   Znonesr+   ©Ú_get_clauser„   ZmapperÚprimary_key_identityr   r   r   Úsetup  s,    
 ÿþÿ	 ÿÿ

z*Result._load_on_pk_identity.<locals>.setupc                 s   s   | ]}|d kV  qd S r   r   )r�   Úelemr   r   r   Ú	<genexpr>0  s     z.Result._load_on_pk_identity.<locals>.<genexpr>c                    s   g | ]\}}ˆ | j |f‘qS r   r€   )r�   Zid_valrˆ   rƒ   r   r   r…   4  s   ÿz/Result._load_on_pk_identity.<locals>.<listcomp>rC   N)Z_raw_columnsZ_annotationsr‹   rZ   r(   r   r2   r-   rk   r‡   rˆ   r&   r8   r7   r`   r]   rx   ZMultipleResultsFound)
r   r7   rN   rŒ   r_   r�   rZ   r`   ro   Úlr   rŠ   r   r~   þ  s2    
" ÿ
 ÿþÿ	
zResult._load_on_pk_identityN)r   r   r   r   r   r   r`   rb   rc   rM   rf   rh   rg   rs   rt   r{   rv   r|   r}   rL   r~   r   r   r   r   r5   8  s$   '
r5   z1.2z5Baked lazy loading is now the default implementation.c                   C   s   dS )zâEnable 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   r   r   r   Úbake_lazy_loadersF  s    
r‘   c                   C   s   t dƒ‚dS )aH  Disable 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 implementationN)ÚNotImplementedErrorr   r   r   r   Úunbake_lazy_loadersS  s    ÿr“   c                 C   s   |   |ddi¡S )zxIndicate that the given attribute should be loaded using "lazy"
    loading with a "baked" query used in the load.

    ZlazyZbaked_select)Zset_relationship_strategy)ZloadoptÚattrr   r   r   Úbaked_lazyloadd  s    r•   zFBaked lazy loading is now the default implementation for lazy loading.c                  G   s   t j t jj| di ¡S )NF©r   Z_UnboundLoadZ
_from_keysr•   ©Úkeysr   r   r   r•   m  s       ÿc                  G   s   t j t jj| di ¡S )NTr–   r—   r   r   r   Úbaked_lazyload_ally  s       ÿr™   )$r   ÚloggingÚ r   rQ   r   Zormrx   r   Z	orm.queryr   Zorm.sessionr   Úsqlr   r	   r‰   r
   Ú	getLoggerr   ÚlogÚobjectr   r   r5   Ú
deprecatedr‘   r“   Zloader_optionr•   Z_add_unbound_fnZ_add_unbound_all_fnr™   Z_unbound_fnZ_unbound_all_fnr"   r   r   r   r   Ú<module>   s\   	
     ÿ

 ÿ

þþ