
    +hN                     h   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j$                  e      Z G d de      Z G d de      Z G d de      Z ej2                  dd      d        Z ej2                  dd      d        Z ej8                         d        Zej<                   ej2                  dd      d               Zej>                   ej2                  dd      d               Z ejB                  Ze jD                  Z ejF                  Z#y)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_column)collections_abcc                        e Zd ZdZdZd Zd Zy)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                      || _         || _        y Nr   )selfcls_r   s      G/var/www/html/venv/lib/python3.12/site-packages/sqlalchemy/ext/baked.py__init__zBakery.__init__/   s    
    c                 <    | j                  | j                  ||      S r   r   )r   
initial_fnargss      r   __call__zBakery.__call__3   s    xx

J55r   N)__name__
__module____qualname____doc__	__slots__r   r    r   r   r   r   !   s    	 I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y)
BakedQueryz3A builder object for :class:`.query.Query` objects.)steps_bakery
_cache_key_spoiledc                 b    d| _         | j                  ||       |g| _        d| _        || _        y )Nr!   F)r&   _update_cache_keyr$   r'   r%   )r   bakeryr   r   s       r   r   zBakedQuery.__init__<   s0    z40 \
r   Nc                 D    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.bakeryC   s     c4==+FGGr   c                     t         j                  t               }| j                  |_        t        | j                        |_        | j
                  |_        | j                  |_        |S r   )r#   __new__r&   listr$   r%   r'   )r   b1s     r   _clonezBakedQuery._cloneM   sH    
+

#\\
mm	r   c                 J    | xj                   |j                  f|z   z  c_         y r   )r&   __code__r   fnr   s      r   r)   zBakedQuery._update_cache_keyU   s    BKK>D00r   c                 j    t        |t              r | j                  |  | S | j                  |       | S r   )
isinstancetupleadd_criteriar   others     r   __iadd__zBakedQuery.__iadd__X   s8    eU#Du%  e$r   c                 b    t        |t              r | j                  | S | j                  |      S r   )r:   r;   with_criteriar=   s     r   __add__zBakedQuery.__add___   s0    eU#%4%%u--%%e,,r   c                 `    | j                  ||       | j                  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$   appendr7   s      r   r<   zBakedQuery.add_criteriae   s+     	r4(

"r   c                 D     | j                         j                  |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.

        )r4   r<   r7   s      r   rA   zBakedQuery.with_criteriap   s"     *t{{}))"4t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_sessionz   s     dG$$r   c                 $    | j                  |      S r   )rJ   rH   s     r   r   zBakedQuery.__call__   s    ((r   c                     |sC| j                   s7| j                         }|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'   r4   r&   _retrieve_baked_queryr$   )r   full_spoil_points      r   spoilzBakedQuery.spoil   sF    ( DMM;;=L##'77#&<<=DJr   c                 6    | 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_clsrH   s     r   _effective_keyzBakedQuery._effective_key   s     '"4"4!666r   c                 N    | j                         }|j                  |||       |S )z)Cloning version of _add_lazyload_options.)
cache_path)r4   _add_lazyload_options)r   optionseffective_pathrV   qs        r   _with_lazyload_optionsz!BakedQuery._with_lazyload_options   s'    KKM	JOr   c                    d}|s}D ]T  }|j                   s|j                  s|j                         }|| j                  d       A|d   rJ d       ||d   z  }V | j	                  fd|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.

        r!   NT)rO      zloader options with variable bound parameters not supported with baked queries.  Please use new-style select() statements for cached ORM queries.r   c                 @     | j                        j                   S r   )_with_current_pathrX   )rZ   rY   rX   s    r   <lambda>z2BakedQuery._add_lazyload_options.<locals>.<lambda>   s     Ba**>:BBGL r   )_is_legacy_option_is_compile_state_generate_cache_keyrQ   r<   path)r   rX   rY   rV   keyoptcks    ``    r   rW   z BakedQuery._add_lazyload_options   s     'J 	!C$$(=(=,,.:JJDJ)!!u '9 2a5LC	! 	LOO	
r   c                     | j                   j                  | j                  |      d       }|>| j                  |      }|j	                  d       | j                   | j                  |      <   |j	                  |      S r   )r%   getrT   	_as_querywith_session)r   rI   querys      r   rN   z BakedQuery._retrieve_baked_query   sp      !4!4W!=tD=NN7+E9>9K9K:DLL,,W56 !!'**r   c                     | j                  |      }d |_        |j                         }|j                  j                  r ||f| j
                  | j                  |      <   ||fS r   )rj   rI   _statement_20_compile_options_bake_okr%   rT   )r   rI   rl   	statements       r   _bakezBakedQuery._bake   sf    w' '')	 %%..:DLL,,W56
 ir   c                     t        |t              r|}nJt        |t              r#|j                  }|,t	        j
                  d      t        dt        |      z        | j                  |      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


        z1Given Query needs to be associated with a Sessionz)Query or Session object expected, got %r.)	r:   r   r   rI   sa_excArgumentError	TypeErrortyperj   )r   query_or_sessionrI   s      r   to_queryzBakedQuery.to_query   sw    L &0&G(%0&..G**G  ;'()  ~~g&&r   c                 h     | j                   d   |      }| j                   dd  D ]
  } ||      } |S Nr   r]   )r$   )r   rI   rl   steps       r   rj   zBakedQuery._as_query/  s?    

1g&JJqrN 	 DKE	  r   )r!   )   N)Fr   )r   r   r   r   r    r   classmethodr*   r4   r)   r?   rB   r<   rA   rJ   r   rQ   rT   r[   rW   rN   rr   ry   rj   r!   r   r   r#   r#   7   sw    =<I H H1-	5%)67!
F+ 23'jr   r#   c                   t    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y)rG   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.

    bqrI   _params_post_criteriac                 <    || _         || _        i | _        g | _        y r   r   )r   r   rI   s      r   r   zResult.__init__C  s     r   c                     t        |      dk(  r|j                  |d          n#t        |      dkD  rt        j                  d      | j                  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updatert   ru   r   )r   r   kws      r   paramszResult.paramsI  s[     t9>IId1gY]&&)  	Br   c                 @    |r| j                   j                  |       | S r   )r   extend)r   fnss     r   _using_post_criteriazResult._using_post_criteriaV  s    &&s+r   c                 &    | j                  |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   r8   s     r   with_post_criteriazResult.with_post_criteria[  s    . (("..r   c                     | j                   j                  | j                        j                  | j                        }| j
                  D ]
  } ||      } |S r   )r   rj   rI   r   r   r   )r   rZ   r8   s      r   rj   zResult._as_queryt  sL    GGdll+224<<@%% 	B1A	r   c                 4    t        | j                               S r   )strrj   r   s    r   __str__zResult.__str__z  s    4>>#$$r   c                 >    | j                         j                         S r   )_iter__iter__r   s    r   r   zResult.__iter__}  s    zz|$$&&r   c                 R   | j                   }| j                  j                  r|j                  r| j	                         j                         S |j                  j                  |j                  | j                        d      \  }}||j                  | j                        \  }}| j                  r|j                  | j                        }n|}| j                  D ]
  } ||      } |j                  }t        |j                        }|j                  |j                   |j                  d       | j                  j#                  |||      }|j$                  j                  dd      r|j'                         }|j$                  j                  dd      r|j)                         }|S )N)NN)_sa_orm_load_optionscompiled_cache)execution_optionsis_single_entityFfiltered)r   rI   enable_baked_queriesr'   rj   r   r%   ri   rT   rr   r   r   r   dict_execution_optionsr   load_optionsexecute_attributesscalarsunique)	r   r   rl   rq   rZ   r8   r   r   results	            r   r   zResult._iter  sd   WW||00BKK>>#))++::>>dll+\
y =!xx5E9<<T\\*AA%% 	B1A	  !5!56  ()"$**	
 %%v1B & 
 !!"4e<^^%F!!*e4]]_Fr   c                     t        j                  t        d            | j                  j	                  fd      }|j                  | j                        j                  | 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                 &    | j                        S r   )
_from_self)rZ   cols    r   r`   zResult.count.<locals>.<lambda>  s    Q\\#-> r   )
r	   countr
   r   rA   rJ   rI   r   r   scalar)r   r   r   s     @r   r   zResult.count  sX     jj,-WW""#>?~~dll+224<<@GGIIr   c                     	 | j                         }t        |t        j                        s|S |d   S # t        j
                  $ r Y y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`.

        .. versionadded:: 1.1.6

        r   N)oner:   r   Sequenceorm_excNoResultFound)r   rets     r   r   zResult.scalar  sH    	((*Cc?#;#;<
q6M$$ 		s   +3 3 A	A	c                    | j                   j                  d       }|j                  | j                        j	                  | j
                        j                  | j                        j                         j                         S )zRReturn the first row.

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

        c                 &    | j                  dd      S r{   )slice)rZ   s    r   r`   zResult.first.<locals>.<lambda>  s    QWWQ] r   )
r   rA   rJ   rI   r   r   r   r   r   first)r   r   s     r   r   zResult.first  s[     WW""#:;NN4<<(VDLL!!!$"5"56UWUW	
r   c                 >    | j                         j                         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                 >    | j                         j                         S )zReturn one or zero results, or raise an exception for multiple
        rows.

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

        .. versionadded:: 1.0.9

        )r   one_or_noner   s    r   r   zResult.one_or_none  s     zz|''))r   c                 >    | j                         j                         S )zKReturn all rows.

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

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

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

        r   )r   r$   rI   	_get_impl_load_on_pk_identity)r   identrl   s      r   ri   z
Result.get  s8     !a .ud&?&?@@r   c                 j    |j                   d   j                  d   j                  \   fd} j                  }|j	                         }|xj
                  fz  c_        |j                  |t        d D                    }t        t        j                        D cg c]  \  }}|   j                  |f c}}      }	t         |j                   j                        j                  di |	      }
t!        |
      }|dkD  rt#        j$                         |r|
d   S yc c}}w )z6Load the given primary key identity from the database.r   parententityc                    }| j                         }|j                          d |_        d 
v rWt        t	        	j
                  
      D cg c]  \  }}||   j                   c}}      }t        j                  ||      }t        j                  |ddi      f|_
        j                  D ]
  } ||      } |S c c}}w )N
_orm_adaptT)r4   _get_condition	_order_bysetzipprimary_keyre   sql_utiladapt_criterion_to_null_deep_annotate_where_criteriar   )rl   _lcl_get_clauserZ   r   valuenonesr8   _get_clause_get_paramsmapperprimary_key_identityr   s          r   setupz*Result._load_on_pk_identity.<locals>.setup  s    )OAAK ++ +."..0D+&C !=	 $C(,, #+"B"B#U# '',9MN!A )) qEH's   B?
c              3   $   K   | ]  }|d u  
 y wr   r!   ).0elems     r   	<genexpr>z.Result._load_on_pk_identity.<locals>.<genexpr>0  s     G$Gs   r]   Nr!   )_raw_columns_annotationsr   r   r4   r&   rA   r;   r   r   r   re   r2   rJ   rI   r   r   r   MultipleResultsFound)r   rI   rl   r   r   r   r   id_valr   r   r   lr   r   r   s   `  `        @@@r   r   zResult._load_on_pk_identity  s*    ##A&33NC#)#5#5 [	 	D WW
 YY[
+'5G2FGG
  ,/(&*<*<,'FK [)--v6
 9bnnT\\299CFCDKq5..00!9s   ,D/
N)r   r   r   r   r    r   r   r   r   rj   r   r   r   r   r   r   r   r   r   ri   r   r!   r   r   rG   rG   8  sb     =I!
/2%'%NJ $
 "	*"AEr   rG   z1.2z5Baked lazy loading is now the default implementation.c                       y)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!   r   r   bake_lazy_loadersr   F  s     	r   c                      t        d      )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 implementation)NotImplementedErrorr!   r   r   unbake_lazy_loadersr   S  s     > r   c                 *    | j                  |ddi      S )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)loadoptattrs     r   baked_lazyloadr   d  s     ,,TFN3KLLr   zFBaked lazy loading is now the default implementation for lazy loading.c                  v    t         j                  j                  t         j                  j                  | di       S )NFr   _UnboundLoad
_from_keysr   keyss    r   r   r   m  s2     ((33%%44dE2 r   c                  v    t         j                  j                  t         j                  j                  | di       S )NTr   r   s    r   baked_lazyload_allr   y  s2     ((33%%44dD" r   )$r   logging r   rt   r   ormr   r   	orm.queryr   orm.sessionr   sqlr	   r
   r   r   	getLoggerr   logobjectr   r#   rG   
deprecatedr   r   loader_optionr   _add_unbound_fn_add_unbound_all_fnr   _unbound_fn_unbound_all_fnr*   r!   r   r   <module>r     se        "  !    " " g!6V 6,~ ~BKV K\ 	B		 	B  !M "M 	'
   ##	'
 $  ++'77 			r   