a
    [g3A                     @  sv  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rd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d/Z=e>Z?G d0d1 d1e"Z@G d2d3 d3e"ZAG d4d- d-ee= ZBG d5d, d,e ZCG d6d7 d7eZDd8d9d:d;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                   @  s    e Zd ZdddddddZdS )ShardChooserOptional[Mapper[_T]]r   Optional[ClauseElement])mapperinstanceclausereturnc                 C  s   d S N )selfr3   r4   r5   r8   r8   m/var/www/html/cobodadashboardai.evdpl.com/venv/lib/python3.9/site-packages/sqlalchemy/ext/horizontal_shard.py__call__Q   s    zShardChooser.__call__N__name__
__module____qualname__r;   r8   r8   r8   r:   r0   P   s   r0   c                   @  s&   e Zd Zdddddddddd	Zd
S )IdentityChooser
Mapper[_T]r   Optional[InstanceState[Any]]r   r   r   r3   primary_keylazy_loaded_fromexecution_optionsbind_argumentskwr6   c                K  s   d S r7   r8   )r9   r3   rD   rE   rF   rG   rH   r8   r8   r:   r;   Z   s    	zIdentityChooser.__call__Nr<   r8   r8   r8   r:   r@   Y   s   r@   c                      s:   e Zd ZdZdddd fddZddd	d
dZ  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.

    r   None)argskwargsr6   c                   s@   t  j|i | t| jts"J | jj| _| jj| _d | _d S r7   )super__init__
isinstancesessionr,   identity_chooserexecute_chooserZ	_shard_id)r9   rJ   rK   	__class__r8   r:   rM   o   s
    

zShardedQuery.__init__ShardIdentifierr   shard_idr6   c                 C  s   | j |d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)rF   )r9   rV   r8   r8   r:   	set_shardw   s    zShardedQuery.set_shard)r=   r>   r?   __doc__rM   rX   __classcell__r8   r8   rR   r:   r-   f   s   c                      s   e Zd ZU ded< ded< ded< dddefddddd	d
ddddddd	 fddZdejdej	dfdddddddddd	 fddZ
ddddd d!d"Zd4d#dd$dd%d&d'd(Zd5dddd)dd$dd*dd+d,d-d.Zd/d0dd1d2d3Z  ZS )6r,   r0   shard_chooserr@   rP   z*Callable[[ORMExecuteState], Iterable[Any]]rQ   N)
id_chooserquery_chooserzOptional[IdentityChooser]z4Optional[Callable[[ORMExecuteState], Iterable[Any]]]zOptional[Dict[str, Any]]zType[Query[_T]]z<Optional[Callable[[Query[_T], Iterable[_T]], Iterable[Any]]]z/Optional[Callable[[Executable], Iterable[Any]]]r   rI   )	r[   rP   rQ   shards	query_clsr\   r]   rK   r6   c                  s  t  jf d|i| tjdtdd |_|rj| tdd ddd	d
dddd fdd}	|	_n|rv|_n
t	
d|r|tdd |rt	
ddddfdd}
|du r|
}|du rt	
d|_i _|dur|D ]}|||  qd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.

        r_   Zdo_orm_executeT)retvalzLThe ``id_chooser`` parameter is deprecated; please use ``identity_chooser``.z2.0rA   r   rB   r   r   r   rC   c                  s"    | }|r||} ||S r7   )queryZ_set_lazyload_from)r3   rD   rE   rF   rG   rH   q)_id_chooserr9   r8   r:   _legacy_identity_chooser   s    	

z9ShardedSession.__init__.<locals>._legacy_identity_chooserz*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.r'   zIterable[Any]orm_contextr6   c                   s
    | j S r7   )Z	statementrf   )_query_chooserr8   r:   _default_execute_chooser   s    z9ShardedSession.__init__.<locals>._default_execute_chooserNz,execute_chooser or query_chooser is required)rL   rM   r   listenexecute_and_instancesr[   r   Zwarn_deprecatedrP   r   ArgumentErrorrQ   _ShardedSession__shards
bind_shard)r9   r[   rP   rQ   r^   r_   r\   r]   rK   rd   ri   krR   )rc   rh   r9   r:   rM      sP    , 
zShardedSession.__init__z
Mapper[_O]zUnion[Any, Tuple[Any, ...]]zOptional[Any]r   rB   r   zOptional[_BindArguments]z)Union[Optional[_O], LoaderCallableStatus])	r3   primary_key_identityidentity_tokenpassiverE   rF   rG   rH   r6   c                   s   |dur&t  j||fd|i|}	|	S | j|||||r>t|ni dD ]0}
t  j||f|
|d|}|durF|  S qFd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`.

        Nrq   )rE   rF   rG   )rq   rE   )rL   _identity_lookuprP   dict)r9   r3   rp   rq   rr   rE   rF   rG   rH   objrV   obj2rR   r8   r:   rs      s:    

zShardedSession._identity_lookupzOptional[_EntityBindKey[_O]])r3   r4   rH   r6   c                 K  sp   |d ur<t |}|jr0|jd }|d us,J |S |jr<|jS t|tsJJ | j||fi |}|d url||_|S )Nr   )r   keyrq   rN   r   r[   )r9   r3   r4   rH   statetokenrV   r8   r8   r:   _choose_shard_and_assign,  s    
z'ShardedSession._choose_shard_and_assignr1   zOptional[ShardIdentifier]r   )r3   r4   rV   rH   r6   c                 K  s~   |du r|  ||}|  r>|  }|dus0J |j||dS | j|||d}t|trh|jf i |S t|tsvJ |S dS )zaProvide a :class:`_engine.Connection` to use in the unit of work
        flush process.

        N)rV   )r3   rV   r4   )	rz   Zin_transactionZget_transaction
connectionget_bindrN   r   connectr   )r9   r3   r4   rV   rH   Ztransbindr8   r8   r:   connection_callableA  s    
z"ShardedSession.connection_callable)rV   r4   r5   r2   r&   )r3   rV   r4   r5   rH   r6   c                K  s.   |d u r$| j |||d}|d us$J | j| S )N)r4   r5   )rz   rm   )r9   r3   rV   r4   r5   rH   r8   r8   r:   r|   _  s    	zShardedSession.get_bindrT   zUnion[Engine, OptionEngine])rV   r~   r6   c                 C  s   || j |< d S r7   )rm   )r9   rV   r~   r8   r8   r:   rn   o  s    zShardedSession.bind_shard)NNN)N)r=   r>   r?   __annotations__r-   rM   r   ZPASSIVE_OFFr   
EMPTY_DICTrs   rz   r   r|   rn   rZ   r8   r8   rR   r:   r,      s:   
&t$1     c                   @  s&   e Zd ZdZdZd	dd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

    rV   propagate_to_loadersTrT   boolc                 C  s   || _ || _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   )r9   rV   r   r8   r8   r:   rM     s    zset_shard_id.__init__N)T)r=   r>   r?   rY   	__slots__rM   r8   r8   r8   r:   r   u  s    r   r'   &Union[Result[_T], IteratorResult[_TP]]re   c                   s   j r j}n js jr" j}nd } j}t|ts:J ddd fdd} jD ]}t|t	rT|j
} qqT|r|jd ur|j}n0d jv r jd }nd jv r jd }nd }|d ur||S g }| D ]}||}|| q|d j|d	d   S d S )
NrT   r   rU   c                   s*   t  j}| |d<  j| d  j|dS )NrV   )rq   )rG   )rt   rG   Zupdate_execution_optionsZinvoke_statement)rV   rG   rg   r8   r:   iter_for_shard  s    
z-execute_and_instances.<locals>.iter_for_shardrW   rV   r      )Z	is_selectZload_optionsZ	is_updateZ	is_deleteZupdate_delete_optionsrO   rN   r,   Z_non_compile_orm_optionsr   rV   Z_identity_tokenrF   rG   rQ   appendmerge)rf   Zactive_optionsrO   r   Zorm_optrV   partialZresult_r8   rg   r:   rk     s4    	



rk   N)FrY   
__future__r   typingr   r   r   r   r   r   r	   r
   r   r    r   r   r   r   Zormr   Zorm._typingr   Zorm.interfacesr   Z
orm.mapperr   Z	orm.queryr   Zorm.sessionr   r   r   Zutil.typingr   r   Zengine.baser   r   r   Zengine.resultr   r    r!   r"   Zorm.bulk_persistencer#   Zorm.contextr$   r%   r&   r'   Z	orm.stater(   sqlr)   Zsql._typingr*   Zsql.elementsr+   __all__r.   strrT   r0   r@   r-   r,   r   rk   r8   r8   r8   r:   <module>   sh   	  p2