
    [h3A                       d 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 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 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r`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/m0Z0 dd%lm1Z1 dd&lm2Z2 dd'lm3Z3 dd(l4m5Z5 dd)l6m7Z7 dd*l8m9Z9 dd+l:m;Z; d,d-gZ< ed.e/          Z=e>Z? G d0 d1e"          Z@ G d2 d3e"          ZA G d4 d-ee=                   ZB G d5 d,e           ZC G d6 d7e          ZDd>d<ZEd=S )?a  Horizontal sharding support.

Defines a rudimental 'horizontal sharding' system which allows a Session to
distribute queries and persistence operations across multiple databases.

For a usage example, see the :ref:`examples_sharding` example included in
the source distribution.

.. deepalchemy:: The horizontal sharding extension is an advanced feature,
   involving a complex statement -> database interaction as well as
   use of semi-public APIs for non-trivial cases.   Simpler approaches to
   refering to multiple database "shards", most commonly using a distinct
   :class:`_orm.Session` per "shard", should always be considered first
   before using this more complex and less-production-tested system.



    )annotations)Any)Callable)Dict)Iterable)Optional)Tuple)Type)TYPE_CHECKING)TypeVar)Union   )event)exc)inspect)util)PassiveFlag)OrmExecuteOptionsParameter)	ORMOption)Mapper)Query)_BindArguments)_PKIdentityArgument)Session)Protocol)Self)
Connection)Engine)OptionEngine)IteratorResult)Result)LoaderCallableStatus)_O)BulkUDCompileState)QueryContext)_EntityBindKey)_SessionBind)ORMExecuteState)InstanceState)
Executable)_TP)ClauseElementShardedSessionShardedQuery_T)boundc                      e Zd Zd
dZd	S )ShardChoosermapperOptional[Mapper[_T]]instancer   clauseOptional[ClauseElement]returnc                    d S N )selfr3   r5   r6   s       n/var/www/api.easyaligner.net/htdocs/venv_linux/lib/python3.11/site-packages/sqlalchemy/ext/horizontal_shard.py__call__zShardChooser.__call__Q   s	    
 c    N)r3   r4   r5   r   r6   r7   r8   r   __name__
__module____qualname__r>   r;   r?   r=   r2   r2   P   s(             r?   r2   c                      e Zd ZddZdS )IdentityChooserr3   
Mapper[_T]primary_keyr   lazy_loaded_fromOptional[InstanceState[Any]]execution_optionsr   bind_argumentsr   kwr   r8   c                   d S r:   r;   )r<   r3   rG   rH   rJ   rK   rL   s          r=   r>   zIdentityChooser.__call__Z   s	     cr?   Nr3   rF   rG   r   rH   rI   rJ   r   rK   r   rL   r   r8   r   r@   r;   r?   r=   rE   rE   Y   s(        	 	 	 	 	 	r?   rE   c                  ,     e Zd ZdZd fdZddZ xZS )r.   a  Query class used with :class:`.ShardedSession`.

    .. legacy:: The :class:`.ShardedQuery` is a subclass of the legacy
       :class:`.Query` class.   The :class:`.ShardedSession` now supports
       2.0 style execution via the :meth:`.ShardedSession.execute` method.

    argsr   kwargsr8   Nonec                     t                      j        |i | t          | j        t                    sJ | j        j        | _        | j        j        | _        d | _        d S r:   )super__init__
isinstancesessionr-   identity_chooserexecute_chooser	_shard_id)r<   rP   rQ   	__class__s      r=   rU   zShardedQuery.__init__o   s\    $)&)))$,77777 $ =#|;r?   shard_idShardIdentifierr   c                .    |                      |          S )a  Return a new query, limited to a single shard ID.

        All subsequent operations with the returned query will
        be against the single shard regardless of other state.

        The shard_id can be passed for a 2.0 style execution to the
        bind_arguments dictionary of :meth:`.Session.execute`::

            results = session.execute(stmt, bind_arguments={"shard_id": "my_shard"})

        )_sa_shard_id)rJ   )r<   r\   s     r=   	set_shardzShardedQuery.set_shardw   s     %%8%<<<r?   )rP   r   rQ   r   r8   rR   )r\   r]   r8   r   )rA   rB   rC   __doc__rU   r`   __classcell__r[   s   @r=   r.   r.   f   s[              = = = = = = = =r?   c                       e Zd ZU ded<   ded<   ded<   dddefdddd: fdZdej        dej	        dfd; fd(Z
d<d+Z	 	 	 d=d>d0Z	 d?dddd1d@d5ZdAd9Z xZS )Br-   r2   shard_chooserrE   rX   z*Callable[[ORMExecuteState], Iterable[Any]]rY   N)
id_chooserquery_chooserOptional[IdentityChooser]4Optional[Callable[[ORMExecuteState], Iterable[Any]]]shardsOptional[Dict[str, Any]]	query_clsType[Query[_T]]rf   <Optional[Callable[[Query[_T], Iterable[_T]], Iterable[Any]]]rg   /Optional[Callable[[Executable], Iterable[Any]]]rQ   r   r8   rR   c                    t                      j        dd|i| t          j         dt          d           | _        |r&|t          j        dd           d  fd}	|	 _        n|r| _        nt          j
        d          |r7|t          j        dd           |rt          j
        d          d!fd}
||
}|t          j
        d          | _        i  _        |!|D ] }                     |||                    dS dS )"a  Construct a ShardedSession.

        :param shard_chooser: A callable which, passed a Mapper, a mapped
          instance, and possibly a SQL clause, returns a shard ID.  This id
          may be based off of the attributes present within the object, or on
          some round-robin scheme. If the scheme is based on a selection, it
          should set whatever state on the instance to mark it in the future as
          participating in that shard.

        :param identity_chooser: A callable, passed a Mapper and primary key
         argument, which should return a list of shard ids where this
         primary key might reside.

          .. versionchanged:: 2.0  The ``identity_chooser`` parameter
             supersedes the ``id_chooser`` parameter.

        :param execute_chooser: For a given :class:`.ORMExecuteState`,
          returns the list of shard_ids
          where the query should be issued.  Results from all shards returned
          will be combined together into a single listing.

          .. versionchanged:: 1.4  The ``execute_chooser`` parameter
             supersedes the ``query_chooser`` parameter.

        :param shards: A dictionary of string shard names
          to :class:`~sqlalchemy.engine.Engine` objects.

        rl   do_orm_executeT)retvalzLThe ``id_chooser`` parameter is deprecated; please use ``identity_chooser``.z2.0r3   rF   rG   r   rH   rI   rJ   r   rK   r   rL   r   r8   c               t                         |           }|r|                    |          } ||          S r:   )query_set_lazyload_from)	r3   rG   rH   rJ   rK   rL   q_id_chooserr<   s	          r=   _legacy_identity_chooserz9ShardedSession.__init__.<locals>._legacy_identity_chooser   sD     JJv&&# ?,,-=>>A"{1k222r?   z*identity_chooser or id_chooser is requiredzNThe ``query_chooser`` parameter is deprecated; please use ``execute_chooser``.z1.4z>Can't pass query_chooser and execute_chooser at the same time.orm_contextr(   Iterable[Any]c                $     | j                   S r:   )	statement)ry   _query_choosers    r=   _default_execute_chooserz9ShardedSession.__init__.<locals>._default_execute_chooser   s     &~k&;<<<r?   Nz,execute_chooser or query_chooser is requiredr;   rN   )ry   r(   r8   rz   )rT   rU   r   listenexecute_and_instancesre   r   warn_deprecatedrX   r   ArgumentErrorrY   _ShardedSession__shards
bind_shard)r<   re   rX   rY   rj   rl   rf   rg   rQ   rx   r~   krw   r}   r[   s   `           @@r=   rU   zShardedSession.__init__   s   X 	7797777"$9$	
 	
 	
 	
 + 	$K 3  3 3 3 3 3 3 3 %=D!! 	$4D!!#<    	;*N 2  
  '(  
= = = = = =
 &":"#>    /=? . .6!9---- . .r?   r3   
Mapper[_O]primary_key_identityUnion[Any, Tuple[Any, ...]]identity_tokenOptional[Any]passiver   rH   rI   rJ   r   rK   Optional[_BindArguments]rL   )Union[Optional[_O], LoaderCallableStatus]c           	         | t                      j        ||fd|i|}	|	S |                     |||||rt          |          ni           D ]&}
 t                      j        ||f|
|d|}||c S 'dS )a_  override the default :meth:`.Session._identity_lookup` method so
        that we search for a given non-token primary key identity across all
        possible identity tokens (e.g. shard ids).

        .. versionchanged:: 1.4  Moved :meth:`.Session._identity_lookup` from
           the :class:`_query.Query` object to the :class:`.Session`.

        Nr   )rH   rJ   rK   )r   rH   )rT   _identity_lookuprX   dict)r<   r3   r   r   r   rH   rJ   rK   rL   objr\   obj2r[   s               r=   r   zShardedSession._identity_lookup   s    ( %*%''*$   . 	 C J 11$!1"37EMtN3332 2       0uww/( $,%5	 
   #KKK $ 4r?   Optional[_EntityBindKey[_O]]r5   c                    |7t          |          }|j        r|j        d         }|J |S |j        r|j        S t          |t                    sJ  | j        ||fi |}|||_        |S )Nr   )r   keyr   rV   r   re   )r<   r3   r5   rL   statetokenr\   s          r=   _choose_shard_and_assignz'ShardedSession._choose_shard_and_assign,  s     H%%Ey ,	!(((% ,++&&)))))%4%fh=="==#+E r?   r4   r\   Optional[ShardIdentifier]r   c                ^   ||                      ||          }|                                 r/|                                 }|J |                    ||          S |                     |||          }t          |t                    r |j        di |S t          |t                    sJ |S )zaProvide a :class:`_engine.Connection` to use in the unit of work
        flush process.

        N)r\   )r3   r\   r5   r;   )	r   in_transactionget_transaction
connectionget_bindrV   r   connectr   )r<   r3   r5   r\   rL   transbinds          r=   connection_callablez"ShardedSession.connection_callableA  s     44VXFFH   	((**E$$$##FX#>>>==8 !  D $'' #t|))b)))!$
33333r?   )r\   r5   r6   r6   r7   r'   c               X    ||                      |||          }|J | j        |         S )N)r5   r6   )r   r   )r<   r3   r\   r5   r6   rL   s         r=   r   zShardedSession.get_bind_  sF     44& 5  H '''}X&&r?   r]   r   Union[Engine, OptionEngine]c                    || j         |<   d S r:   )r   )r<   r\   r   s      r=   r   zShardedSession.bind_shardo  s     #'hr?   )re   r2   rX   rh   rY   ri   rj   rk   rl   rm   rf   rn   rg   ro   rQ   r   r8   rR   )r3   r   r   r   r   r   r   r   rH   rI   rJ   r   rK   r   rL   r   r8   r   )r3   r   r5   r   rL   r   r8   r   )NNN)
r3   r4   r5   r   r\   r   rL   r   r8   r   r:   )r3   r   r\   r   r5   r   r6   r7   rL   r   r8   r'   )r\   r]   r   r   r8   rR   )rA   rB   rC   __annotations__r.   rU   r   PASSIVE_OFFr   
EMPTY_DICTr   r   r   r   r   rb   rc   s   @r=   r-   r-      sN        %%%%????
 7; +/%1n. IMn. n. n. n. n. n. n. n.h )-*69=8<37/ / / / / / /b   . (,"&.2	    @ 04' /3"&*.' ' ' ' ' ' ' ' ' ' ' ' ' 'r?   c                  "    e Zd ZdZdZ	 d
ddZd	S )set_shard_ida  a loader option for statements to apply a specific shard id to the
    primary query as well as for additional relationship and column
    loaders.

    The :class:`_horizontal.set_shard_id` option may be applied using
    the :meth:`_sql.Executable.options` method of any executable statement::

        stmt = (
            select(MyObject)
            .where(MyObject.name == "some name")
            .options(set_shard_id("shard1"))
        )

    Above, the statement when invoked will limit to the "shard1" shard
    identifier for the primary query as well as for all relationship and
    column loading strategies, including eager loaders such as
    :func:`_orm.selectinload`, deferred column loaders like :func:`_orm.defer`,
    and the lazy relationship loader :func:`_orm.lazyload`.

    In this way, the :class:`_horizontal.set_shard_id` option has much wider
    scope than using the "shard_id" argument within the
    :paramref:`_orm.Session.execute.bind_arguments` dictionary.


    .. versionadded:: 2.0.0

    r\   propagate_to_loadersTr\   r]   r   boolc                "    || _         || _        dS )aH  Construct a :class:`_horizontal.set_shard_id` option.

        :param shard_id: shard identifier
        :param propagate_to_loaders: if left at its default of ``True``, the
         shard option will take place for lazy loaders such as
         :func:`_orm.lazyload` and :func:`_orm.defer`; if False, the option
         will not be propagated to loaded objects. Note that :func:`_orm.defer`
         always limits to the shard_id of the parent row in any case, so the
         parameter only has a net effect on the behavior of the
         :func:`_orm.lazyload` strategy.

        Nr   )r<   r\   r   s      r=   rU   zset_shard_id.__init__  s     !$8!!!r?   N)T)r\   r]   r   r   )rA   rB   rC   ra   	__slots__rU   r;   r?   r=   r   r   u  sE         8 5I GK9 9 9 9 9 9 9r?   r   ry   r(   r8   &Union[Result[_T], IteratorResult[_TP]]c                *     j         r j        }n j        s j        r j        }nd } j        }t          |t                    sJ d	 fd} j        D ] }t          |t                    r	|j
        } nB!|r|j        |j        }n0d j        v r j        d         }nd j        v r j        d         }nd }| ||          S g }|                               D ]"} ||          }|                    |           # |d         j        |dd           S )
Nr\   r]   r8   r   c                    t          j                  }| |d<                       |                                |          S )Nr\   )r   )rK   )r   rK   update_execution_optionsinvoke_statement)r\   rK   ry   s     r=   iter_for_shardz-execute_and_instances.<locals>.iter_for_shard  sM     k899%-z",,H,EEE++>+JJJr?   r_   r      )r\   r]   r8   r   )	is_selectload_options	is_update	is_deleteupdate_delete_optionsrW   rV   r-   _non_compile_orm_optionsr   r\   _identity_tokenrJ   rK   rY   appendmerge)ry   active_optionsrW   r   orm_optr\   partialresult_s   `       r=   r   r     s     $1		 +"7 $:!Gg~.....K K K K K K 7   g|,, 	'HE	  	n<H%5HH{<<<"4^DHH;555"1*=HHH~h'''//<< 	$ 	$H$nX..GNN7####wqz--r?   N)ry   r(   r8   r   )Fra   
__future__r   typingr   r   r   r   r   r	   r
   r   r   r    r   r   r   r   ormr   orm._typingr   orm.interfacesr   
orm.mapperr   	orm.queryr   orm.sessionr   r   r   util.typingr   r   engine.baser   r   r   engine.resultr    r!   r"   r#   orm.bulk_persistencer$   orm.contextr%   r&   r'   r(   	orm.stater)   sqlr*   sql._typingr+   sql.elementsr,   __all__r/   strr]   r2   rE   r.   r-   r   r   r;   r?   r=   <module>r      s   $ # " " " " "                                                                                                 4 4 4 4 4 4 & & & & & &             ( ( ( ( ( ( - - - - - - ! ! ! ! ! ! " " " " " "       -(((((($$$$$$******......&&&&&&******      999999******,,,,,,******------))))))      !!!!!!,,,,,,^
,WT     8   
 
 
 
 
h 
 
 
= = = = =59 = = =@l' l' l' l' l'W l' l' l'^/9 /9 /9 /9 /99 /9 /9 /9d7. 7. 7. 7. 7. 7.r?   